|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.