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

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:  *
                     36:  *     @(#)nfs_bio.c   7.19 (Berkeley) 4/16/91
                     37:  */
                     38: 
                     39: #include "param.h"
                     40: #include "proc.h"
                     41: #include "buf.h"
                     42: #include "uio.h"
                     43: #include "namei.h"
                     44: #include "vnode.h"
                     45: #include "trace.h"
                     46: #include "mount.h"
                     47: #include "resourcevar.h"
                     48: 
                     49: #include "nfsnode.h"
                     50: #include "nfsv2.h"
                     51: #include "nfs.h"
                     52: #include "nfsiom.h"
                     53: #include "nfsmount.h"
                     54: 
                     55: /* True and false, how exciting */
                     56: #define        TRUE    1
                     57: #define        FALSE   0
                     58: 
                     59: /*
                     60:  * Vnode op for read using bio
                     61:  * Any similarity to readip() is purely coincidental
                     62:  */
                     63: nfs_bioread(vp, uio, ioflag, cred)
                     64:        register struct vnode *vp;
                     65:        register struct uio *uio;
                     66:        int ioflag;
                     67:        struct ucred *cred;
                     68: {
                     69:        register struct nfsnode *np = VTONFS(vp);
                     70:        register int biosize;
                     71:        struct buf *bp;
                     72:        struct vattr vattr;
                     73:        daddr_t lbn, bn, rablock;
                     74:        int diff, error = 0;
                     75:        long n, on;
                     76: 
                     77: #ifdef lint
                     78:        ioflag = ioflag;
                     79: #endif /* lint */
                     80: #ifdef DIAGNOSTIC
                     81:        if (uio->uio_rw != UIO_READ)
                     82:                panic("nfs_read mode");
                     83: #endif
                     84:        if (uio->uio_resid == 0)
                     85:                return (0);
                     86:        if (uio->uio_offset < 0 && vp->v_type != VDIR)
                     87:                return (EINVAL);
                     88:        biosize = VFSTONFS(vp->v_mount)->nm_rsize;
                     89:        /*
                     90:         * If the file's modify time on the server has changed since the
                     91:         * last read rpc or you have written to the file,
                     92:         * you may have lost data cache consistency with the
                     93:         * server, so flush all of the file's data out of the cache.
                     94:         * Then force a getattr rpc to ensure that you have up to date
                     95:         * attributes.
                     96:         * NB: This implies that cache data can be read when up to
                     97:         * NFS_ATTRTIMEO seconds out of date. If you find that you need current
                     98:         * attributes this could be forced by setting n_attrstamp to 0 before
                     99:         * the nfs_dogetattr() call.
                    100:         */
                    101:        if (vp->v_type != VLNK) {
                    102:                if (np->n_flag & NMODIFIED) {
                    103:                        np->n_flag &= ~NMODIFIED;
                    104:                        vinvalbuf(vp, TRUE);
                    105:                        np->n_attrstamp = 0;
                    106:                        np->n_direofoffset = 0;
                    107:                        if (error = nfs_dogetattr(vp, &vattr, cred, 1,
                    108:                            uio->uio_procp))
                    109:                                return (error);
                    110:                        np->n_mtime = vattr.va_mtime.tv_sec;
                    111:                } else {
                    112:                        if (error = nfs_dogetattr(vp, &vattr, cred, 1,
                    113:                            uio->uio_procp))
                    114:                                return (error);
                    115:                        if (np->n_mtime != vattr.va_mtime.tv_sec) {
                    116:                                np->n_direofoffset = 0;
                    117:                                vinvalbuf(vp, TRUE);
                    118:                                np->n_mtime = vattr.va_mtime.tv_sec;
                    119:                        }
                    120:                }
                    121:        }
                    122:        do {
                    123:            switch (vp->v_type) {
                    124:            case VREG:
                    125:                nfsstats.biocache_reads++;
                    126:                lbn = uio->uio_offset / biosize;
                    127:                on = uio->uio_offset & (biosize-1);
                    128:                n = MIN((unsigned)(biosize - on), uio->uio_resid);
                    129:                diff = np->n_size - uio->uio_offset;
                    130:                if (diff <= 0)
                    131:                        return (error);
                    132:                if (diff < n)
                    133:                        n = diff;
                    134:                bn = lbn*(biosize/DEV_BSIZE);
                    135:                rablock = (lbn+1)*(biosize/DEV_BSIZE);
                    136:                if (vp->v_lastr + 1 == lbn &&
                    137:                    np->n_size > (rablock * DEV_BSIZE))
                    138:                        error = breada(vp, bn, biosize, rablock, biosize,
                    139:                                cred, &bp);
                    140:                else
                    141:                        error = bread(vp, bn, biosize, cred, &bp);
                    142:                vp->v_lastr = lbn;
                    143:                if (bp->b_resid) {
                    144:                   diff = (on >= (biosize-bp->b_resid)) ? 0 :
                    145:                        (biosize-bp->b_resid-on);
                    146:                   n = MIN(n, diff);
                    147:                }
                    148:                break;
                    149:            case VLNK:
                    150:                nfsstats.biocache_readlinks++;
                    151:                on = 0;
                    152:                error = bread(vp, (daddr_t)0, NFS_MAXPATHLEN, cred, &bp);
                    153:                n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
                    154:                break;
                    155:            case VDIR:
                    156:                nfsstats.biocache_readdirs++;
                    157:                on = 0;
                    158:                error = bread(vp, uio->uio_offset, NFS_DIRBLKSIZ, cred, &bp);
                    159:                n = MIN(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
                    160:                break;
                    161:            };
                    162:            if (error) {
                    163:                brelse(bp);
                    164:                return (error);
                    165:            }
                    166:            if (n > 0)
                    167:                error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
                    168:            switch (vp->v_type) {
                    169:            case VREG:
                    170:                if (n+on == biosize || uio->uio_offset == np->n_size)
                    171:                        bp->b_flags |= B_AGE;
                    172:                break;
                    173:            case VLNK:
                    174:                n = 0;
                    175:                break;
                    176:            case VDIR:
                    177:                uio->uio_offset = bp->b_blkno;
                    178:                break;
                    179:            };
                    180:            brelse(bp);
                    181:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    182:        return (error);
                    183: }
                    184: 
                    185: /*
                    186:  * Vnode op for write using bio
                    187:  */
                    188: nfs_write(vp, uio, ioflag, cred)
                    189:        register struct vnode *vp;
                    190:        register struct uio *uio;
                    191:        int ioflag;
                    192:        struct ucred *cred;
                    193: {
                    194:        struct proc *p = uio->uio_procp;
                    195:        register int biosize;
                    196:        struct buf *bp;
                    197:        struct nfsnode *np = VTONFS(vp);
                    198:        struct vattr vattr;
                    199:        daddr_t lbn, bn;
                    200:        int n, on, error = 0;
                    201: 
                    202: #ifdef DIAGNOSTIC
                    203:        if (uio->uio_rw != UIO_WRITE)
                    204:                panic("nfs_write mode");
                    205:        if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
                    206:                panic("nfs_write proc");
                    207: #endif
                    208:        if (vp->v_type != VREG)
                    209:                return (EIO);
                    210:        /* Should we try and do this ?? */
                    211:        if (ioflag & (IO_APPEND | IO_SYNC)) {
                    212:                if (np->n_flag & NMODIFIED) {
                    213:                        np->n_flag &= ~NMODIFIED;
                    214:                        vinvalbuf(vp, TRUE);
                    215:                }
                    216:                if (ioflag & IO_APPEND) {
                    217:                        np->n_attrstamp = 0;
                    218:                        if (error = nfs_dogetattr(vp, &vattr, cred, 1, p))
                    219:                                return (error);
                    220:                        uio->uio_offset = np->n_size;
                    221:                }
                    222:                return (nfs_writerpc(vp, uio, cred));
                    223:        }
                    224: #ifdef notdef
                    225:        cnt = uio->uio_resid;
                    226:        osize = np->n_size;
                    227: #endif
                    228:        if (uio->uio_offset < 0)
                    229:                return (EINVAL);
                    230:        if (uio->uio_resid == 0)
                    231:                return (0);
                    232:        /*
                    233:         * Maybe this should be above the vnode op call, but so long as
                    234:         * file servers have no limits, i don't think it matters
                    235:         */
                    236:        if (uio->uio_offset + uio->uio_resid >
                    237:              p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
                    238:                psignal(p, SIGXFSZ);
                    239:                return (EFBIG);
                    240:        }
                    241:        /*
                    242:         * I use nm_rsize, not nm_wsize so that all buffer cache blocks
                    243:         * will be the same size within a filesystem. nfs_writerpc will
                    244:         * still use nm_wsize when sizing the rpc's.
                    245:         */
                    246:        biosize = VFSTONFS(vp->v_mount)->nm_rsize;
                    247:        np->n_flag |= NMODIFIED;
                    248:        do {
                    249:                nfsstats.biocache_writes++;
                    250:                lbn = uio->uio_offset / biosize;
                    251:                on = uio->uio_offset & (biosize-1);
                    252:                n = MIN((unsigned)(biosize - on), uio->uio_resid);
                    253:                if (uio->uio_offset+n > np->n_size) {
                    254:                        np->n_size = uio->uio_offset+n;
                    255:                        vnode_pager_setsize(vp, np->n_size);
                    256:                }
                    257:                bn = lbn*(biosize/DEV_BSIZE);
                    258: again:
                    259:                bp = getblk(vp, bn, biosize);
                    260:                if (bp->b_wcred == NOCRED) {
                    261:                        crhold(cred);
                    262:                        bp->b_wcred = cred;
                    263:                }
                    264:                if (bp->b_dirtyend > 0) {
                    265:                        /*
                    266:                         * If the new write will leave a contiguous dirty
                    267:                         * area, just update the b_dirtyoff and b_dirtyend,
                    268:                         * otherwise force a write rpc of the old dirty area.
                    269:                         */
                    270:                        if (on <= bp->b_dirtyend && (on+n) >= bp->b_dirtyoff) {
                    271:                                bp->b_dirtyoff = MIN(on, bp->b_dirtyoff);
                    272:                                bp->b_dirtyend = MAX((on+n), bp->b_dirtyend);
                    273:                        } else {
                    274:                                bp->b_proc = p;
                    275:                                if (error = bwrite(bp))
                    276:                                        return (error);
                    277:                                goto again;
                    278:                        }
                    279:                } else {
                    280:                        bp->b_dirtyoff = on;
                    281:                        bp->b_dirtyend = on+n;
                    282:                }
                    283:                if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
                    284:                        brelse(bp);
                    285:                        return (error);
                    286:                }
                    287:                if ((n+on) == biosize) {
                    288:                        bp->b_flags |= B_AGE;
                    289:                        bp->b_proc = (struct proc *)0;
                    290:                        bawrite(bp);
                    291:                } else {
                    292:                        bp->b_proc = (struct proc *)0;
                    293:                        bdwrite(bp);
                    294:                }
                    295:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                    296: #ifdef notdef
                    297:        /* Should we try and do this for nfs ?? */
                    298:        if (error && (ioflag & IO_UNIT)) {
                    299:                np->n_size = osize;
                    300:                uio->uio_offset -= cnt - uio->uio_resid;
                    301:                uio->uio_resid = cnt;
                    302:        }
                    303: #endif
                    304:        return (error);
                    305: }

unix.superglobalmegacorp.com

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