Annotation of Net2/nfs/nfs_bio.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Rick Macklem at The University of Guelph.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
1.1.1.2 ! root       36:  *     from: @(#)nfs_bio.c     7.19 (Berkeley) 4/16/91
        !            37:  *     nfs_bio.c,v 1.6 1993/07/13 10:50:04 cgd Exp
1.1       root       38:  */
                     39: 
                     40: #include "param.h"
                     41: #include "proc.h"
                     42: #include "buf.h"
                     43: #include "uio.h"
                     44: #include "namei.h"
                     45: #include "vnode.h"
                     46: #include "trace.h"
                     47: #include "mount.h"
                     48: #include "resourcevar.h"
                     49: 
                     50: #include "nfsnode.h"
                     51: #include "nfsv2.h"
                     52: #include "nfs.h"
                     53: #include "nfsiom.h"
                     54: #include "nfsmount.h"
                     55: 
                     56: /* True and false, how exciting */
                     57: #define        TRUE    1
                     58: #define        FALSE   0
                     59: 
                     60: /*
                     61:  * Vnode op for read using bio
                     62:  * Any similarity to readip() is purely coincidental
                     63:  */
                     64: nfs_bioread(vp, uio, ioflag, cred)
                     65:        register struct vnode *vp;
                     66:        register struct uio *uio;
                     67:        int ioflag;
                     68:        struct ucred *cred;
                     69: {
                     70:        register struct nfsnode *np = VTONFS(vp);
                     71:        register int biosize;
                     72:        struct buf *bp;
                     73:        struct vattr vattr;
                     74:        daddr_t lbn, bn, rablock;
                     75:        int diff, error = 0;
                     76:        long n, on;
                     77: 
                     78: #ifdef lint
                     79:        ioflag = ioflag;
                     80: #endif /* lint */
                     81: #ifdef DIAGNOSTIC
                     82:        if (uio->uio_rw != UIO_READ)
                     83:                panic("nfs_read mode");
                     84: #endif
                     85:        if (uio->uio_resid == 0)
                     86:                return (0);
                     87:        if (uio->uio_offset < 0 && vp->v_type != VDIR)
                     88:                return (EINVAL);
                     89:        biosize = VFSTONFS(vp->v_mount)->nm_rsize;
                     90:        /*
                     91:         * If the file's modify time on the server has changed since the
                     92:         * last read rpc or you have written to the file,
                     93:         * you may have lost data cache consistency with the
                     94:         * server, so flush all of the file's data out of the cache.
                     95:         * Then force a getattr rpc to ensure that you have up to date
                     96:         * attributes.
                     97:         * NB: This implies that cache data can be read when up to
                     98:         * NFS_ATTRTIMEO seconds out of date. If you find that you need current
                     99:         * attributes this could be forced by setting n_attrstamp to 0 before
                    100:         * the nfs_dogetattr() call.
                    101:         */
                    102:        if (vp->v_type != VLNK) {
                    103:                if (np->n_flag & NMODIFIED) {
                    104:                        np->n_flag &= ~NMODIFIED;
                    105:                        vinvalbuf(vp, TRUE);
                    106:                        np->n_attrstamp = 0;
                    107:                        np->n_direofoffset = 0;
                    108:                        if (error = nfs_dogetattr(vp, &vattr, cred, 1,
                    109:                            uio->uio_procp))
                    110:                                return (error);
                    111:                        np->n_mtime = vattr.va_mtime.tv_sec;
                    112:                } else {
                    113:                        if (error = nfs_dogetattr(vp, &vattr, cred, 1,
                    114:                            uio->uio_procp))
                    115:                                return (error);
                    116:                        if (np->n_mtime != vattr.va_mtime.tv_sec) {
                    117:                                np->n_direofoffset = 0;
                    118:                                vinvalbuf(vp, TRUE);
                    119:                                np->n_mtime = vattr.va_mtime.tv_sec;
                    120:                        }
                    121:                }
                    122:        }
                    123:        do {
                    124:            switch (vp->v_type) {
                    125:            case VREG:
                    126:                nfsstats.biocache_reads++;
                    127:                lbn = uio->uio_offset / biosize;
                    128:                on = uio->uio_offset & (biosize-1);
                    129:                n = MIN((unsigned)(biosize - on), uio->uio_resid);
                    130:                diff = np->n_size - uio->uio_offset;
                    131:                if (diff <= 0)
                    132:                        return (error);
                    133:                if (diff < n)
                    134:                        n = diff;
                    135:                bn = lbn*(biosize/DEV_BSIZE);
                    136:                rablock = (lbn+1)*(biosize/DEV_BSIZE);
                    137:                if (vp->v_lastr + 1 == lbn &&
                    138:                    np->n_size > (rablock * DEV_BSIZE))
                    139:                        error = breada(vp, bn, biosize, rablock, biosize,
                    140:                                cred, &bp);
                    141:                else
                    142:                        error = bread(vp, bn, biosize, cred, &bp);
                    143:                vp->v_lastr = lbn;
                    144:                if (bp->b_resid) {
                    145:                   diff = (on >= (biosize-bp->b_resid)) ? 0 :
                    146:                        (biosize-bp->b_resid-on);
                    147:                   n = MIN(n, diff);
                    148:                }
                    149:                break;
                    150:            case VLNK:
                    151:                nfsstats.biocache_readlinks++;
                    152:                on = 0;
                    153:                error = bread(vp, (daddr_t)0, NFS_MAXPATHLEN, cred, &bp);
                    154:                n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
                    155:                break;
                    156:            case VDIR:
                    157:                nfsstats.biocache_readdirs++;
                    158:                on = 0;
                    159:                error = bread(vp, uio->uio_offset, NFS_DIRBLKSIZ, cred, &bp);
                    160:                n = MIN(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
                    161:                break;
                    162:            };
                    163:            if (error) {
                    164:                brelse(bp);
                    165:                return (error);
                    166:            }
                    167:            if (n > 0)
                    168:                error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
                    169:            switch (vp->v_type) {
                    170:            case VREG:
                    171:                if (n+on == biosize || uio->uio_offset == np->n_size)
                    172:                        bp->b_flags |= B_AGE;
                    173:                break;
                    174:            case VLNK:
                    175:                n = 0;
                    176:                break;
                    177:            case VDIR:
                    178:                uio->uio_offset = bp->b_blkno;
                    179:                break;
                    180:            };
                    181:            brelse(bp);
                    182:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    183:        return (error);
                    184: }
                    185: 
                    186: /*
                    187:  * Vnode op for write using bio
                    188:  */
                    189: nfs_write(vp, uio, ioflag, cred)
                    190:        register struct vnode *vp;
                    191:        register struct uio *uio;
                    192:        int ioflag;
                    193:        struct ucred *cred;
                    194: {
                    195:        struct proc *p = uio->uio_procp;
                    196:        register int biosize;
                    197:        struct buf *bp;
                    198:        struct nfsnode *np = VTONFS(vp);
                    199:        struct vattr vattr;
                    200:        daddr_t lbn, bn;
                    201:        int n, on, error = 0;
                    202: 
                    203: #ifdef DIAGNOSTIC
                    204:        if (uio->uio_rw != UIO_WRITE)
                    205:                panic("nfs_write mode");
                    206:        if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
                    207:                panic("nfs_write proc");
                    208: #endif
                    209:        if (vp->v_type != VREG)
                    210:                return (EIO);
                    211:        /* Should we try and do this ?? */
                    212:        if (ioflag & (IO_APPEND | IO_SYNC)) {
                    213:                if (np->n_flag & NMODIFIED) {
                    214:                        np->n_flag &= ~NMODIFIED;
                    215:                        vinvalbuf(vp, TRUE);
                    216:                }
                    217:                if (ioflag & IO_APPEND) {
                    218:                        np->n_attrstamp = 0;
                    219:                        if (error = nfs_dogetattr(vp, &vattr, cred, 1, p))
                    220:                                return (error);
                    221:                        uio->uio_offset = np->n_size;
                    222:                }
                    223:                return (nfs_writerpc(vp, uio, cred));
                    224:        }
                    225: #ifdef notdef
                    226:        cnt = uio->uio_resid;
                    227:        osize = np->n_size;
                    228: #endif
                    229:        if (uio->uio_offset < 0)
                    230:                return (EINVAL);
                    231:        if (uio->uio_resid == 0)
                    232:                return (0);
                    233:        /*
                    234:         * Maybe this should be above the vnode op call, but so long as
                    235:         * file servers have no limits, i don't think it matters
                    236:         */
1.1.1.2 ! root      237:        if (p &&
        !           238:            uio->uio_offset + uio->uio_resid >
1.1       root      239:              p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
                    240:                psignal(p, SIGXFSZ);
                    241:                return (EFBIG);
                    242:        }
                    243:        /*
                    244:         * I use nm_rsize, not nm_wsize so that all buffer cache blocks
                    245:         * will be the same size within a filesystem. nfs_writerpc will
                    246:         * still use nm_wsize when sizing the rpc's.
                    247:         */
                    248:        biosize = VFSTONFS(vp->v_mount)->nm_rsize;
                    249:        np->n_flag |= NMODIFIED;
1.1.1.2 ! root      250:        vnode_pager_uncache(vp);
1.1       root      251:        do {
                    252:                nfsstats.biocache_writes++;
                    253:                lbn = uio->uio_offset / biosize;
                    254:                on = uio->uio_offset & (biosize-1);
                    255:                n = MIN((unsigned)(biosize - on), uio->uio_resid);
                    256:                if (uio->uio_offset+n > np->n_size) {
                    257:                        np->n_size = uio->uio_offset+n;
                    258:                        vnode_pager_setsize(vp, np->n_size);
                    259:                }
                    260:                bn = lbn*(biosize/DEV_BSIZE);
                    261: again:
                    262:                bp = getblk(vp, bn, biosize);
1.1.1.2 ! root      263:                if (bp->b_wcred == NOCRED && cred != NOCRED) {
1.1       root      264:                        crhold(cred);
                    265:                        bp->b_wcred = cred;
                    266:                }
                    267:                if (bp->b_dirtyend > 0) {
                    268:                        /*
                    269:                         * If the new write will leave a contiguous dirty
                    270:                         * area, just update the b_dirtyoff and b_dirtyend,
                    271:                         * otherwise force a write rpc of the old dirty area.
                    272:                         */
                    273:                        if (on <= bp->b_dirtyend && (on+n) >= bp->b_dirtyoff) {
                    274:                                bp->b_dirtyoff = MIN(on, bp->b_dirtyoff);
                    275:                                bp->b_dirtyend = MAX((on+n), bp->b_dirtyend);
                    276:                        } else {
                    277:                                bp->b_proc = p;
                    278:                                if (error = bwrite(bp))
                    279:                                        return (error);
                    280:                                goto again;
                    281:                        }
                    282:                } else {
                    283:                        bp->b_dirtyoff = on;
                    284:                        bp->b_dirtyend = on+n;
                    285:                }
                    286:                if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
                    287:                        brelse(bp);
                    288:                        return (error);
                    289:                }
                    290:                if ((n+on) == biosize) {
                    291:                        bp->b_flags |= B_AGE;
                    292:                        bp->b_proc = (struct proc *)0;
                    293:                        bawrite(bp);
                    294:                } else {
                    295:                        bp->b_proc = (struct proc *)0;
                    296:                        bdwrite(bp);
                    297:                }
                    298:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    299: #ifdef notdef
                    300:        /* Should we try and do this for nfs ?? */
                    301:        if (error && (ioflag & IO_UNIT)) {
                    302:                np->n_size = osize;
                    303:                uio->uio_offset -= cnt - uio->uio_resid;
                    304:                uio->uio_resid = cnt;
                    305:        }
                    306: #endif
                    307:        return (error);
                    308: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.