home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / nfs / nfs_bio.c next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  8.5 KB  |  306 lines

  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. }
  306.