update for 4.4BSD from Rick Macklem
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 3 Feb 1993 07:18:00 +0000 (23:18 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 3 Feb 1993 07:18:00 +0000 (23:18 -0800)
SCCS-vsn: sys/nfs/nfsrvcache.h 7.6
SCCS-vsn: sys/nfs/nfsdiskless.h 7.5
SCCS-vsn: sys/nfs/nfs_bio.c 7.36
SCCS-vsn: sys/nfs/nfs_node.c 7.46
SCCS-vsn: sys/nfs/nfs_nqlease.c 7.18
SCCS-vsn: sys/nfs/nfs_socket.c 7.42
SCCS-vsn: sys/nfs/nfs_subs.c 7.68

usr/src/sys/nfs/nfs_bio.c
usr/src/sys/nfs/nfs_node.c
usr/src/sys/nfs/nfs_nqlease.c
usr/src/sys/nfs/nfs_socket.c
usr/src/sys/nfs/nfs_subs.c
usr/src/sys/nfs/nfsdiskless.h
usr/src/sys/nfs/nfsrvcache.h

index a970fa1..0a25833 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_bio.c   7.35 (Berkeley) %G%
+ *     @(#)nfs_bio.c   7.36 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <nfs/nfsmount.h>
 #include <nfs/nqnfs.h>
 
 #include <nfs/nfsmount.h>
 #include <nfs/nqnfs.h>
 
-/* True and false, how exciting */
-#define        TRUE    1
-#define        FALSE   0
+struct buf *nfsincore(), *nfs_getcacheblk(), *nfsgetblk();
+extern struct queue_entry nfs_bufq;
+extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
+extern int nfs_numasync;
 
 /*
  * Vnode op for read using bio
 
 /*
  * Vnode op for read using bio
@@ -44,13 +45,14 @@ nfs_bioread(vp, uio, ioflag, cred)
        struct ucred *cred;
 {
        register struct nfsnode *np = VTONFS(vp);
        struct ucred *cred;
 {
        register struct nfsnode *np = VTONFS(vp);
-       register int biosize;
-       struct buf *bp;
+       register int biosize, diff;
+       struct buf *bp, *rabp;
        struct vattr vattr;
        struct vattr vattr;
+       struct proc *p;
        struct nfsmount *nmp;
        struct nfsmount *nmp;
-       daddr_t lbn, bn, rablock[NFS_MAXRAHEAD];
-       int rasize[NFS_MAXRAHEAD], nra, diff, error = 0;
-       int n, on;
+       daddr_t lbn, bn, rabn;
+       caddr_t baddr;
+       int got_buf, len, nra, error = 0, n, on, not_readin;
 
 #ifdef lint
        ioflag = ioflag;
 
 #ifdef lint
        ioflag = ioflag;
@@ -65,6 +67,7 @@ nfs_bioread(vp, uio, ioflag, cred)
                return (EINVAL);
        nmp = VFSTONFS(vp->v_mount);
        biosize = nmp->nm_rsize;
                return (EINVAL);
        nmp = VFSTONFS(vp->v_mount);
        biosize = nmp->nm_rsize;
+       p = uio->uio_procp;
        /*
         * For nfs, cache consistency can only be maintained approximately.
         * Although RFC1094 does not specify the criteria, the following is
        /*
         * For nfs, cache consistency can only be maintained approximately.
         * Although RFC1094 does not specify the criteria, the following is
@@ -87,19 +90,22 @@ nfs_bioread(vp, uio, ioflag, cred)
        if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
                if (np->n_flag & NMODIFIED) {
                        if ((nmp->nm_flag & NFSMNT_MYWRITE) == 0 ||
        if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
                if (np->n_flag & NMODIFIED) {
                        if ((nmp->nm_flag & NFSMNT_MYWRITE) == 0 ||
-                            vp->v_type != VREG)
-                               NFS_VINVBUF(np, vp, TRUE, cred, uio->uio_procp);
+                            vp->v_type != VREG) {
+                               if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                                       return (error);
+                       }
                        np->n_attrstamp = 0;
                        np->n_direofoffset = 0;
                        np->n_attrstamp = 0;
                        np->n_direofoffset = 0;
-                       if (error = VOP_GETATTR(vp, &vattr, cred, uio->uio_procp))
+                       if (error = VOP_GETATTR(vp, &vattr, cred, p))
                                return (error);
                        np->n_mtime = vattr.va_mtime.ts_sec;
                } else {
                                return (error);
                        np->n_mtime = vattr.va_mtime.ts_sec;
                } else {
-                       if (error = VOP_GETATTR(vp, &vattr, cred, uio->uio_procp))
+                       if (error = VOP_GETATTR(vp, &vattr, cred, p))
                                return (error);
                        if (np->n_mtime != vattr.va_mtime.ts_sec) {
                                np->n_direofoffset = 0;
                                return (error);
                        if (np->n_mtime != vattr.va_mtime.ts_sec) {
                                np->n_direofoffset = 0;
-                               NFS_VINVBUF(np, vp, TRUE, cred, uio->uio_procp);
+                               if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                                       return (error);
                                np->n_mtime = vattr.va_mtime.ts_sec;
                        }
                }
                                np->n_mtime = vattr.va_mtime.ts_sec;
                        }
                }
@@ -109,21 +115,28 @@ nfs_bioread(vp, uio, ioflag, cred)
            /*
             * Get a valid lease. If cached data is stale, flush it.
             */
            /*
             * Get a valid lease. If cached data is stale, flush it.
             */
-           if ((nmp->nm_flag & NFSMNT_NQNFS) &&
-               NQNFS_CKINVALID(vp, np, NQL_READ)) {
-               do {
-                       error = nqnfs_getlease(vp, NQL_READ, cred, uio->uio_procp);
-               } while (error == NQNFS_EXPIRED);
-               if (error)
+           if (nmp->nm_flag & NFSMNT_NQNFS) {
+               if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
+                   do {
+                       error = nqnfs_getlease(vp, NQL_READ, cred, p);
+                   } while (error == NQNFS_EXPIRED);
+                   if (error)
                        return (error);
                        return (error);
-               if (np->n_lrev != np->n_brev ||
-                   ((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
+                   if (np->n_lrev != np->n_brev ||
+                       ((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
                        if (vp->v_type == VDIR) {
                        if (vp->v_type == VDIR) {
-                               np->n_direofoffset = 0;
-                               cache_purge(vp);
+                           np->n_direofoffset = 0;
+                           cache_purge(vp);
                        }
                        }
-                       NFS_VINVBUF(np, vp, TRUE, cred, uio->uio_procp);
+                       if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                           return (error);
                        np->n_brev = np->n_lrev;
                        np->n_brev = np->n_lrev;
+                   }
+               } else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
+                   np->n_direofoffset = 0;
+                   cache_purge(vp);
+                   if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                       return (error);
                }
            }
            if (np->n_flag & NQNFSNONCACHE) {
                }
            }
            if (np->n_flag & NQNFSNONCACHE) {
@@ -140,113 +153,155 @@ nfs_bioread(vp, uio, ioflag, cred)
                };
                return (error);
            }
                };
                return (error);
            }
+           baddr = (caddr_t)0;
            switch (vp->v_type) {
            case VREG:
                nfsstats.biocache_reads++;
                lbn = uio->uio_offset / biosize;
                on = uio->uio_offset & (biosize-1);
            switch (vp->v_type) {
            case VREG:
                nfsstats.biocache_reads++;
                lbn = uio->uio_offset / biosize;
                on = uio->uio_offset & (biosize-1);
+               bn = lbn * (biosize / DEV_BSIZE);
+               not_readin = 1;
+
+               /*
+                * Start the read ahead(s), as required.
+                */
+               if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
+                   lbn == vp->v_lastr + 1) {
+                   for (nra = 0; nra < nmp->nm_readahead &&
+                       (lbn + 1 + nra) * biosize < np->n_size; nra++) {
+                       rabn = (lbn + 1 + nra) * (biosize / DEV_BSIZE);
+                       if (!nfsincore(vp, rabn)) {
+                           rabp = nfs_getcacheblk(vp, rabn, biosize, p);
+                           if (!rabp)
+                               return (EINTR);
+                           if ((rabp->b_flags & (B_DELWRI | B_DONE)) == 0) {
+                               rabp->b_flags |= (B_READ | B_ASYNC);
+                               if (nfs_asyncio(rabp, cred)) {
+                                   rabp->b_flags |= B_INVAL;
+                                   brelse(rabp);
+                               }
+                           }
+                       }
+                   }
+               }
+
+               /*
+                * If the block is in the cache and has the required data
+                * in a valid region, just copy it out.
+                * Otherwise, get the block and write back/read in,
+                * as required.
+                */
+               if ((bp = nfsincore(vp, bn)) &&
+                   (bp->b_flags & (B_BUSY | B_WRITEINPROG)) ==
+                   (B_BUSY | B_WRITEINPROG))
+                       got_buf = 0;
+               else {
+again:
+                       bp = nfs_getcacheblk(vp, bn, biosize, p);
+                       if (!bp)
+                               return (EINTR);
+                       got_buf = 1;
+                       if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) {
+                               bp->b_flags |= B_READ;
+                               not_readin = 0;
+                               if (error = nfs_doio(bp, cred, p)) {
+                                   brelse(bp);
+                                   return (error);
+                               }
+                       }
+               }
                n = min((unsigned)(biosize - on), uio->uio_resid);
                diff = np->n_size - uio->uio_offset;
                n = min((unsigned)(biosize - on), uio->uio_resid);
                diff = np->n_size - uio->uio_offset;
-               if (diff <= 0)
-                       return (error);
                if (diff < n)
                        n = diff;
                if (diff < n)
                        n = diff;
-               bn = lbn*(biosize/DEV_BSIZE);
-               for (nra = 0; nra < nmp->nm_readahead &&
-                       (lbn + 1 + nra) * biosize < np->n_size; nra++) {
-                       rablock[nra] = (lbn + 1 + nra) * (biosize / DEV_BSIZE);
-                       rasize[nra] = biosize;
-               }
-again:
-               if (nra > 0 && lbn >= vp->v_lastr)
-                       error = breadn(vp, bn, biosize, rablock, rasize, nra,
-                               cred, &bp);
-               else
-                       error = bread(vp, bn, biosize, cred, &bp);
-               if (bp->b_validend > 0) {
-                       if (on < bp->b_validoff || (on+n) > bp->b_validend) {
+               if (not_readin && n > 0) {
+                       if (on < bp->b_validoff || (on + n) > bp->b_validend) {
+                               if (!got_buf) {
+                                   bp = nfs_getcacheblk(vp, bn, biosize, p);
+                                   if (!bp)
+                                       return (EINTR);
+                                   got_buf = 1;
+                               }
                                bp->b_flags |= B_INVAL;
                                if (bp->b_dirtyend > 0) {
                                bp->b_flags |= B_INVAL;
                                if (bp->b_dirtyend > 0) {
-                                       if ((bp->b_flags & B_DELWRI) == 0)
-                                               panic("nfsbioread");
-                                       (void) bwrite(bp);
+                                   if ((bp->b_flags & B_DELWRI) == 0)
+                                       panic("nfsbioread");
+                                   if (VOP_BWRITE(bp) == EINTR)
+                                       return (EINTR);
                                } else
                                } else
-                                       brelse(bp);
+                                   brelse(bp);
                                goto again;
                        }
                                goto again;
                        }
-               } else {
-                       bp->b_validoff = 0;
-                       bp->b_validend = biosize - bp->b_resid;
                }
                vp->v_lastr = lbn;
                }
                vp->v_lastr = lbn;
-               if (bp->b_resid) {
-                  diff = (on >= (biosize-bp->b_resid)) ? 0 :
-                       (biosize-bp->b_resid-on);
-                  n = min(n, diff);
-               }
+               diff = (on >= bp->b_validend) ? 0 : (bp->b_validend - on);
+               if (diff < n)
+                       n = diff;
                break;
            case VLNK:
                nfsstats.biocache_readlinks++;
                break;
            case VLNK:
                nfsstats.biocache_readlinks++;
-               on = 0;
-               error = bread(vp, (daddr_t)0, NFS_MAXPATHLEN, cred, &bp);
+               bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, p);
+               if (!bp)
+                       return (EINTR);
+               if ((bp->b_flags & B_DONE) == 0) {
+                       bp->b_flags |= B_READ;
+                       if (error = nfs_doio(bp, cred, p)) {
+                               brelse(bp);
+                               return (error);
+                       }
+               }
                n = min(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
                n = min(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
+               got_buf = 1;
+               on = 0;
                break;
            case VDIR:
                nfsstats.biocache_readdirs++;
                break;
            case VDIR:
                nfsstats.biocache_readdirs++;
-               on = 0;
-               error = bread(vp, (daddr_t)uio->uio_offset, NFS_DIRBLKSIZ,
-                   cred, &bp);
-               n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
-               break;
-           };
-           if (error) {
-               brelse(bp);
-               return (error);
-           }
-
-           /*
-            * For nqnfs:
-            * Must check for valid lease, since it may have expired while in
-            * bread(). If expired, get a lease.
-            * If data is stale, flush and try again.
-            * nb: If a read rpc is done by bread() or breada() and there is
-            *     no valid lease, a get_lease request will be piggy backed.
-            */
-           if (nmp->nm_flag & NFSMNT_NQNFS) {
-               if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
-                       do {
-                               error = nqnfs_getlease(vp, NQL_READ, cred, uio->uio_procp);
-                       } while (error == NQNFS_EXPIRED);
-                       if (error) {
+               bn = (daddr_t)uio->uio_offset;
+               bp = nfs_getcacheblk(vp, bn, NFS_DIRBLKSIZ, p);
+               if (!bp)
+                       return (EINTR);
+               if ((bp->b_flags & B_DONE) == 0) {
+                       bp->b_flags |= B_READ;
+                       if (error = nfs_doio(bp, cred, p)) {
                                brelse(bp);
                                return (error);
                        }
                                brelse(bp);
                                return (error);
                        }
-                       if ((np->n_flag & NQNFSNONCACHE) ||
-                           np->n_lrev != np->n_brev ||
-                           ((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
-                               if (vp->v_type == VDIR) {
-                                       np->n_direofoffset = 0;
-                                       cache_purge(vp);
+               }
+
+               /*
+                * If not eof and read aheads are enabled, start one.
+                * (You need the current block first, so that you have the
+                *  directory offset cookie of the next block.
+                */
+               rabn = bp->b_blkno;
+               if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
+                   rabn != 0 && rabn != np->n_direofoffset &&
+                   !nfsincore(vp, rabn)) {
+                       rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
+                       if (rabp) {
+                           if ((rabp->b_flags & (B_DONE | B_DELWRI)) == 0) {
+                               rabp->b_flags |= (B_READ | B_ASYNC);
+                               if (nfs_asyncio(rabp, cred)) {
+                                   rabp->b_flags |= B_INVAL;
+                                   brelse(rabp);
                                }
                                }
-                               brelse(bp);
-                               NFS_VINVBUF(np, vp, TRUE, cred, uio->uio_procp);
-                               np->n_brev = np->n_lrev;
-                               continue;
+                           }
                        }
                        }
-               } else if ((np->n_flag & NQNFSNONCACHE) ||
-                   ((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
-                       np->n_direofoffset = 0;
-                       brelse(bp);
-                       NFS_VINVBUF(np, vp, TRUE, cred, uio->uio_procp);
-                       np->n_brev = np->n_lrev;
-                       continue;
                }
                }
+               on = 0;
+               n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
+               got_buf = 1;
+               break;
+           };
+
+           if (n > 0) {
+               if (!baddr)
+                       baddr = bp->b_un.b_addr;
+               error = uiomove(baddr + on, (int)n, uio);
            }
            }
-           if (n > 0)
-               error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
            switch (vp->v_type) {
            case VREG:
            switch (vp->v_type) {
            case VREG:
-               if (n+on == biosize || uio->uio_offset == np->n_size)
+               if (n + on == biosize || uio->uio_offset == np->n_size)
                        bp->b_flags |= B_AGE;
                break;
            case VLNK:
                        bp->b_flags |= B_AGE;
                break;
            case VLNK:
@@ -256,8 +311,9 @@ again:
                uio->uio_offset = bp->b_blkno;
                break;
            };
                uio->uio_offset = bp->b_blkno;
                break;
            };
-           brelse(bp);
-       } while (error == 0 && uio->uio_resid > 0 && n != 0);
+           if (got_buf)
+               brelse(bp);
+       } while (error == 0 && uio->uio_resid > 0 && n > 0);
        return (error);
 }
 
        return (error);
 }
 
@@ -300,7 +356,8 @@ nfs_write(ap)
        if (ioflag & (IO_APPEND | IO_SYNC)) {
                if (np->n_flag & NMODIFIED) {
                        np->n_attrstamp = 0;
        if (ioflag & (IO_APPEND | IO_SYNC)) {
                if (np->n_flag & NMODIFIED) {
                        np->n_attrstamp = 0;
-                       NFS_VINVBUF(np, vp, TRUE, cred, p);
+                       if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                               return (error);
                }
                if (ioflag & IO_APPEND) {
                        np->n_attrstamp = 0;
                }
                if (ioflag & IO_APPEND) {
                        np->n_attrstamp = 0;
@@ -329,7 +386,6 @@ nfs_write(ap)
         * still use nm_wsize when sizing the rpc's.
         */
        biosize = nmp->nm_rsize;
         * still use nm_wsize when sizing the rpc's.
         */
        biosize = nmp->nm_rsize;
-       np->n_flag |= NMODIFIED;
        do {
 
                /*
        do {
 
                /*
@@ -345,27 +401,31 @@ nfs_write(ap)
                                return (error);
                        if (np->n_lrev != np->n_brev ||
                            (np->n_flag & NQNFSNONCACHE)) {
                                return (error);
                        if (np->n_lrev != np->n_brev ||
                            (np->n_flag & NQNFSNONCACHE)) {
-                               NFS_VINVBUF(np, vp, TRUE, cred, p);
+                               if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                                       return (error);
                                np->n_brev = np->n_lrev;
                        }
                }
                if (np->n_flag & NQNFSNONCACHE)
                                np->n_brev = np->n_lrev;
                        }
                }
                if (np->n_flag & NQNFSNONCACHE)
-                       return (nfs_writerpc(vp, uio, cred, 0));
+                       return (nfs_writerpc(vp, uio, cred, ioflag));
                nfsstats.biocache_writes++;
                lbn = uio->uio_offset / biosize;
                on = uio->uio_offset & (biosize-1);
                n = min((unsigned)(biosize - on), uio->uio_resid);
                nfsstats.biocache_writes++;
                lbn = uio->uio_offset / biosize;
                on = uio->uio_offset & (biosize-1);
                n = min((unsigned)(biosize - on), uio->uio_resid);
-               if (uio->uio_offset + n > np->n_size) {
-                       np->n_size = uio->uio_offset + n;
-                       vnode_pager_setsize(vp, (u_long)np->n_size);
-               }
                bn = lbn * (biosize / DEV_BSIZE);
 again:
                bn = lbn * (biosize / DEV_BSIZE);
 again:
-               bp = getblk(vp, bn, biosize);
+               bp = nfs_getcacheblk(vp, bn, biosize, p);
+               if (!bp)
+                       return (EINTR);
                if (bp->b_wcred == NOCRED) {
                        crhold(cred);
                        bp->b_wcred = cred;
                }
                if (bp->b_wcred == NOCRED) {
                        crhold(cred);
                        bp->b_wcred = cred;
                }
+               np->n_flag |= NMODIFIED;
+               if (uio->uio_offset + n > np->n_size) {
+                       np->n_size = uio->uio_offset + n;
+                       vnode_pager_setsize(vp, (u_long)np->n_size);
+               }
 
                /*
                 * If the new write will leave a contiguous dirty
 
                /*
                 * If the new write will leave a contiguous dirty
@@ -375,8 +435,8 @@ again:
                if (bp->b_dirtyend > 0 &&
                    (on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) {
                        bp->b_proc = p;
                if (bp->b_dirtyend > 0 &&
                    (on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) {
                        bp->b_proc = p;
-                       if (error = bwrite(bp))
-                               return (error);
+                       if (VOP_BWRITE(bp) == EINTR)
+                               return (EINTR);
                        goto again;
                }
 
                        goto again;
                }
 
@@ -396,22 +456,25 @@ again:
                        if (np->n_lrev != np->n_brev ||
                            (np->n_flag & NQNFSNONCACHE)) {
                                brelse(bp);
                        if (np->n_lrev != np->n_brev ||
                            (np->n_flag & NQNFSNONCACHE)) {
                                brelse(bp);
-                               NFS_VINVBUF(np, vp, TRUE, cred, p);
+                               if (error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1))
+                                       return (error);
                                np->n_brev = np->n_lrev;
                                goto again;
                        }
                }
                if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
                                np->n_brev = np->n_lrev;
                                goto again;
                        }
                }
                if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
+                       bp->b_flags |= B_ERROR;
                        brelse(bp);
                        return (error);
                }
                if (bp->b_dirtyend > 0) {
                        bp->b_dirtyoff = min(on, bp->b_dirtyoff);
                        brelse(bp);
                        return (error);
                }
                if (bp->b_dirtyend > 0) {
                        bp->b_dirtyoff = min(on, bp->b_dirtyoff);
-                       bp->b_dirtyend = max((on+n), bp->b_dirtyend);
+                       bp->b_dirtyend = max((on + n), bp->b_dirtyend);
                } else {
                        bp->b_dirtyoff = on;
                } else {
                        bp->b_dirtyoff = on;
-                       bp->b_dirtyend = on+n;
+                       bp->b_dirtyend = on + n;
                }
                }
+#ifndef notdef
                if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
                    bp->b_validoff > bp->b_dirtyend) {
                        bp->b_validoff = bp->b_dirtyoff;
                if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
                    bp->b_validoff > bp->b_dirtyend) {
                        bp->b_validoff = bp->b_dirtyoff;
@@ -420,22 +483,291 @@ again:
                        bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
                        bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
                }
                        bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
                        bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
                }
+#else
+               bp->b_validoff = bp->b_dirtyoff;
+               bp->b_validend = bp->b_dirtyend;
+#endif
+               if (ioflag & IO_APPEND)
+                       bp->b_flags |= B_APPENDWRITE;
 
                /*
                 * If the lease is non-cachable or IO_SYNC do bwrite().
                 */
                if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) {
                        bp->b_proc = p;
 
                /*
                 * If the lease is non-cachable or IO_SYNC do bwrite().
                 */
                if ((np->n_flag & NQNFSNONCACHE) || (ioflag & IO_SYNC)) {
                        bp->b_proc = p;
-                       bwrite(bp);
-               } else if ((n+on) == biosize &&
-                        (nmp->nm_flag & NFSMNT_NQNFS) == 0) {
-                       bp->b_flags |= B_AGE;
+                       if (error = VOP_BWRITE(bp))
+                               return (error);
+               } else if ((n + on) == biosize &&
+                       (nmp->nm_flag & NFSMNT_NQNFS) == 0) {
                        bp->b_proc = (struct proc *)0;
                        bawrite(bp);
                        bp->b_proc = (struct proc *)0;
                        bawrite(bp);
-               } else {
-                       bp->b_proc = (struct proc *)0;
+               } else
                        bdwrite(bp);
                        bdwrite(bp);
+       } while (uio->uio_resid > 0 && n > 0);
+       return (0);
+}
+
+/*
+ * Get an nfs cache block.
+ * Allocate a new one if the block isn't currently in the cache
+ * and return the block marked busy. If the calling process is
+ * interrupted by a signal for an interruptible mount point, return
+ * NULL.
+ */
+struct buf *
+nfs_getcacheblk(vp, bn, size, p)
+       struct vnode *vp;
+       daddr_t bn;
+       int size;
+       struct proc *p;
+{
+       register struct buf *bp;
+       struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+
+       if (nmp->nm_flag & NFSMNT_INT) {
+               bp = nfsgetblk(vp, bn, size, PCATCH, 0);
+               while (bp == (struct buf *)0) {
+                       if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
+                               return ((struct buf *)0);
+                       bp = nfsgetblk(vp, bn, size, 0, 2 * hz);
                }
                }
-       } while (error == 0 && uio->uio_resid > 0 && n != 0);
+       } else
+               bp = nfsgetblk(vp, bn, size, 0, 0);
+       return (bp);
+}
+
+/*
+ * Flush and invalidate all dirty buffers. If another process is already
+ * doing the flush, just wait for completion.
+ */
+nfs_vinvalbuf(vp, flags, cred, p, intrflg)
+       struct vnode *vp;
+       int flags;
+       struct ucred *cred;
+       struct proc *p;
+       int intrflg;
+{
+       register struct nfsnode *np = VTONFS(vp);
+       struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+       int error = 0, slpflag, slptimeo;
+
+       if ((nmp->nm_flag & NFSMNT_INT) == 0)
+               intrflg = 0;
+       if (intrflg) {
+               slpflag = PCATCH;
+               slptimeo = 2 * hz;
+       } else {
+               slpflag = 0;
+               slptimeo = 0;
+       }
+       /*
+        * First wait for any other process doing a flush to complete.
+        */
+       while (np->n_flag & NFLUSHINPROG) {
+               np->n_flag |= NFLUSHWANT;
+               error = tsleep((caddr_t)&np->n_flag, PRIBIO + 2, "nfsvinval",
+                       slptimeo);
+               if (error && intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, p))
+                       return (EINTR);
+       }
+
+       /*
+        * Now, flush as required.
+        */
+       np->n_flag |= NFLUSHINPROG;
+       error = nfsvinvalbuf(vp, flags, cred, p, slpflag, 0);
+       while (error) {
+               if (intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
+                       np->n_flag &= ~NFLUSHINPROG;
+                       if (np->n_flag & NFLUSHWANT) {
+                               np->n_flag &= ~NFLUSHWANT;
+                               wakeup((caddr_t)&np->n_flag);
+                       }
+                       return (EINTR);
+               }
+               error = nfsvinvalbuf(vp, flags, cred, p, 0, slptimeo);
+       }
+       np->n_flag &= ~(NMODIFIED | NFLUSHINPROG);
+       if (np->n_flag & NFLUSHWANT) {
+               np->n_flag &= ~NFLUSHWANT;
+               wakeup((caddr_t)&np->n_flag);
+       }
+       return (0);
+}
+
+/*
+ * Initiate asynchronous I/O. Return an error if no nfsiods are available.
+ * This is mainly to avoid queueing async I/O requests when the nfsiods
+ * are all hung on a dead server.
+ */
+nfs_asyncio(bp, cred)
+       register struct buf *bp;
+       struct ucred *cred;
+{
+       register int i;
+
+       if (nfs_numasync == 0)
+               return (EIO);
+       for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
+           if (nfs_iodwant[i]) {
+               if (bp->b_flags & B_READ) {
+                       if (bp->b_rcred == NOCRED && cred != NOCRED) {
+                               crhold(cred);
+                               bp->b_rcred = cred;
+                       }
+               } else {
+                       if (bp->b_wcred == NOCRED && cred != NOCRED) {
+                               crhold(cred);
+                               bp->b_wcred = cred;
+                       }
+               }
+       
+               queue_enter_tail(&nfs_bufq, bp, struct buf *, b_freelist);
+               nfs_iodwant[i] = (struct proc *)0;
+               wakeup((caddr_t)&nfs_iodwant[i]);
+               return (0);
+           }
+       return (EIO);
+}
+
+/*
+ * Do an I/O operation to/from a cache block. This may be called
+ * synchronously or from an nfsiod.
+ */
+int
+nfs_doio(bp, cr, p)
+       register struct buf *bp;
+       struct cred *cr;
+       struct proc *p;
+{
+       register struct uio *uiop;
+       register struct vnode *vp;
+       struct nfsnode *np;
+       struct nfsmount *nmp;
+       int error, diff, len;
+       struct uio uio;
+       struct iovec io;
+
+       vp = bp->b_vp;
+       np = VTONFS(vp);
+       nmp = VFSTONFS(vp->v_mount);
+       uiop = &uio;
+       uiop->uio_iov = &io;
+       uiop->uio_iovcnt = 1;
+       uiop->uio_segflg = UIO_SYSSPACE;
+       uiop->uio_procp = p;
+
+       /*
+        * Historically, paging was done with physio, but no more.
+        */
+       if (bp->b_flags & B_PHYS)
+           panic("doio phys");
+       if (bp->b_flags & B_READ) {
+           io.iov_len = uiop->uio_resid = bp->b_bcount;
+           io.iov_base = bp->b_un.b_addr;
+           uiop->uio_rw = UIO_READ;
+           switch (vp->v_type) {
+           case VREG:
+               uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
+               nfsstats.read_bios++;
+               error = nfs_readrpc(vp, uiop, cr);
+               if (!error) {
+                   bp->b_validoff = 0;
+                   if (uiop->uio_resid) {
+                       /*
+                        * If len > 0, there is a hole in the file and
+                        * no writes after the hole have been pushed to
+                        * the server yet.
+                        * Just zero fill the rest of the valid area.
+                        */
+                       diff = bp->b_bcount - uiop->uio_resid;
+                       len = np->n_size - (bp->b_blkno * DEV_BSIZE
+                               + diff);
+                       if (len > 0) {
+                           len = min(len, uiop->uio_resid);
+                           bzero(bp->b_un.b_addr + diff, len);
+                           bp->b_validend = diff + len;
+                       } else
+                           bp->b_validend = diff;
+                   } else
+                       bp->b_validend = bp->b_bcount;
+               }
+               if (p && (vp->v_flag & VTEXT) &&
+                       (((nmp->nm_flag & NFSMNT_NQNFS) &&
+                         np->n_lrev != np->n_brev) ||
+                        (!(nmp->nm_flag & NFSMNT_NQNFS) &&
+                         np->n_mtime != np->n_vattr.va_mtime.ts_sec))) {
+                       uprintf("Process killed due to text file modification\n");
+                       psignal(p, SIGKILL);
+                       p->p_flag |= SKEEP;
+               }
+               break;
+           case VLNK:
+               uiop->uio_offset = 0;
+               nfsstats.readlink_bios++;
+               error = nfs_readlinkrpc(vp, uiop, cr);
+               break;
+           case VDIR:
+               uiop->uio_offset = bp->b_lblkno;
+               nfsstats.readdir_bios++;
+               if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS)
+                   error = nfs_readdirlookrpc(vp, uiop, cr);
+               else
+                   error = nfs_readdirrpc(vp, uiop, cr);
+               /*
+                * Save offset cookie in b_blkno.
+                */
+               bp->b_blkno = uiop->uio_offset;
+               break;
+           };
+           if (error) {
+               bp->b_flags |= B_ERROR;
+               bp->b_error = error;
+           }
+       } else {
+           io.iov_len = uiop->uio_resid = bp->b_dirtyend
+               - bp->b_dirtyoff;
+           uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
+               + bp->b_dirtyoff;
+           io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff;
+           uiop->uio_rw = UIO_WRITE;
+           nfsstats.write_bios++;
+           if (bp->b_flags & B_APPENDWRITE)
+               error = nfs_writerpc(vp, uiop, cr, IO_APPEND);
+           else
+               error = nfs_writerpc(vp, uiop, cr, 0);
+           bp->b_flags &= ~(B_WRITEINPROG | B_APPENDWRITE);
+
+           /*
+            * For an interrupted write, the buffer is still valid and the
+            * write hasn't been pushed to the server yet, so we can't set
+            * B_ERROR and report the interruption by setting B_EINTR. For
+            * the B_ASYNC case, B_EINTR is not relevant, so the rpc attempt
+            * is essentially a noop.
+            */
+           if (error == EINTR) {
+               bp->b_flags &= ~B_INVAL;
+               bp->b_flags |= B_DELWRI;
+
+               /*
+                * Since for the B_ASYNC case, nfs_bwrite() has reassigned the
+                * buffer to the clean list, we have to reassign it back to the
+                * dirty one. Ugh.
+                */
+               if (bp->b_flags & B_ASYNC)
+                   reassignbuf(bp, vp);
+               else
+                   bp->b_flags |= B_EINTR;
+           } else {
+               if (error) {
+                   bp->b_flags |= B_ERROR;
+                   bp->b_error = np->n_error = error;
+                   np->n_flag |= NWRITEERR;
+               }
+               bp->b_dirtyoff = bp->b_dirtyend = 0;
+           }
+       }
+       bp->b_resid = uiop->uio_resid;
+       biodone(bp);
        return (error);
 }
        return (error);
 }
index 90624f7..11b4986 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_node.c  7.45 (Berkeley) %G%
+ *     @(#)nfs_node.c  7.46 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -134,6 +134,7 @@ nfs_inactive(ap)
 {
        register struct nfsnode *np;
        register struct sillyrename *sp;
 {
        register struct nfsnode *np;
        register struct sillyrename *sp;
+       struct proc *p = curproc;       /* XXX */
        extern int prtactive;
 
        np = VTONFS(ap->a_vp);
        extern int prtactive;
 
        np = VTONFS(ap->a_vp);
@@ -145,6 +146,7 @@ nfs_inactive(ap)
                /*
                 * Remove the silly file that was rename'd earlier
                 */
                /*
                 * Remove the silly file that was rename'd earlier
                 */
+               (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, p, 1);
                nfs_removeit(sp);
                crfree(sp->s_cred);
                vrele(sp->s_dvp);
                nfs_removeit(sp);
                crfree(sp->s_cred);
                vrele(sp->s_dvp);
@@ -152,7 +154,7 @@ nfs_inactive(ap)
                free((caddr_t)sp, M_NFSREQ);
 #endif
        }
                free((caddr_t)sp, M_NFSREQ);
 #endif
        }
-       np->n_flag &= NMODIFIED;
+       np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT);
        return (0);
 }
 
        return (0);
 }
 
@@ -208,6 +210,11 @@ nfs_lock(ap)
 {
        register struct vnode *vp = ap->a_vp;
 
 {
        register struct vnode *vp = ap->a_vp;
 
+       /*
+        * Ugh, another place where interruptible mounts will get hung.
+        * If you make this sleep interruptible, then you have to fix all
+        * the VOP_LOCK() calls to expect interruptibility.
+        */
        while (vp->v_flag & VXLOCK) {
                vp->v_flag |= VXWANT;
                sleep((caddr_t)vp, PINOD);
        while (vp->v_flag & VXLOCK) {
                vp->v_flag |= VXWANT;
                sleep((caddr_t)vp, PINOD);
index c61b560..0ce92ae 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_nqlease.c       7.17 (Berkeley) %G%
+ *     @(#)nfs_nqlease.c       7.18 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -996,14 +996,14 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash3");
                                if ((np->n_flag & (NMODIFIED | NQNFSEVICTED))
                                    && vp->v_type == VREG) {
                                        if (np->n_flag & NQNFSEVICTED) {
                                if ((np->n_flag & (NMODIFIED | NQNFSEVICTED))
                                    && vp->v_type == VREG) {
                                        if (np->n_flag & NQNFSEVICTED) {
-                                               NFS_VINVBUF(np, vp,
-                                                           TRUE, cred, p);
+                                               (void) nfs_vinvalbuf(vp,
+                                                      V_SAVE, cred, p, 0);
                                                np->n_flag &= ~NQNFSEVICTED;
                                                (void) nqnfs_vacated(vp, cred);
                                        } else {
                                                np->n_flag &= ~NQNFSEVICTED;
                                                (void) nqnfs_vacated(vp, cred);
                                        } else {
-                                               np->n_flag &= ~NMODIFIED;
                                                (void) VOP_FSYNC(vp, cred,
                                                    MNT_WAIT, p);
                                                (void) VOP_FSYNC(vp, cred,
                                                    MNT_WAIT, p);
+                                               np->n_flag &= ~NMODIFIED;
                                        }
                                }
                              }
                                        }
                                }
                              }
@@ -1040,7 +1040,7 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
             */
            if ((nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT | NFSMNT_HASAUTH)) == 0) {
                ncd->ncd_authuid = nmp->nm_authuid;
             */
            if ((nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT | NFSMNT_HASAUTH)) == 0) {
                ncd->ncd_authuid = nmp->nm_authuid;
-               if (copyout((caddr_t)ncd, argp, sizeof (*ncd)))
+               if (copyout((caddr_t)ncd, argp, sizeof (struct nfsd_cargs)))
                        nmp->nm_flag |= NFSMNT_WAITAUTH;
                else
                        return (ENEEDAUTH);
                        nmp->nm_flag |= NFSMNT_WAITAUTH;
                else
                        return (ENEEDAUTH);
index 0872305..08234c0 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_socket.c        7.41 (Berkeley) %G%
+ *     @(#)nfs_socket.c        7.42 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -688,7 +688,6 @@ nfs_reply(myrep)
                 */
                error = nfs_receive(myrep, &nam, &mrep);
                nfs_rcvunlock(&nmp->nm_flag);
                 */
                error = nfs_receive(myrep, &nam, &mrep);
                nfs_rcvunlock(&nmp->nm_flag);
-if (error) printf("rcv err=%d\n",error);
                if (error) {
 
                        /*
                if (error) {
 
                        /*
@@ -1337,16 +1336,24 @@ nfs_sndlock(flagp, rep)
        struct nfsreq *rep;
 {
        struct proc *p;
        struct nfsreq *rep;
 {
        struct proc *p;
+       int slpflag = 0, slptimeo = 0;
 
 
-       if (rep)
+       if (rep) {
                p = rep->r_procp;
                p = rep->r_procp;
-       else
+               if (rep->r_nmp->nm_flag & NFSMNT_INT)
+                       slpflag = PCATCH;
+       } else
                p = (struct proc *)0;
        while (*flagp & NFSMNT_SNDLOCK) {
                if (nfs_sigintr(rep->r_nmp, rep, p))
                        return (EINTR);
                *flagp |= NFSMNT_WANTSND;
                p = (struct proc *)0;
        while (*flagp & NFSMNT_SNDLOCK) {
                if (nfs_sigintr(rep->r_nmp, rep, p))
                        return (EINTR);
                *flagp |= NFSMNT_WANTSND;
-               (void) tsleep((caddr_t)flagp, PZERO-1, "nfsndlck", 0);
+               (void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "nfsndlck",
+                       slptimeo);
+               if (slpflag == PCATCH) {
+                       slpflag = 0;
+                       slptimeo = 2 * hz;
+               }
        }
        *flagp |= NFSMNT_SNDLOCK;
        return (0);
        }
        *flagp |= NFSMNT_SNDLOCK;
        return (0);
@@ -1373,12 +1380,22 @@ nfs_rcvlock(rep)
        register struct nfsreq *rep;
 {
        register int *flagp = &rep->r_nmp->nm_flag;
        register struct nfsreq *rep;
 {
        register int *flagp = &rep->r_nmp->nm_flag;
+       int slpflag, slptimeo = 0;
 
 
+       if (*flagp & NFSMNT_INT)
+               slpflag = PCATCH;
+       else
+               slpflag = 0;
        while (*flagp & NFSMNT_RCVLOCK) {
                if (nfs_sigintr(rep->r_nmp, rep, rep->r_procp))
                        return (EINTR);
                *flagp |= NFSMNT_WANTRCV;
        while (*flagp & NFSMNT_RCVLOCK) {
                if (nfs_sigintr(rep->r_nmp, rep, rep->r_procp))
                        return (EINTR);
                *flagp |= NFSMNT_WANTRCV;
-               (void) tsleep((caddr_t)flagp, PZERO-1, "nfsrcvlck", 0);
+               (void) tsleep((caddr_t)flagp, slpflag | (PZERO - 1), "nfsrcvlk",
+                       slptimeo);
+               if (slpflag == PCATCH) {
+                       slpflag = 0;
+                       slptimeo = 2 * hz;
+               }
        }
        *flagp |= NFSMNT_RCVLOCK;
        return (0);
        }
        *flagp |= NFSMNT_RCVLOCK;
        return (0);
@@ -1841,8 +1858,8 @@ nfs_getreq(nd, has_header)
        } else if (auth_type == rpc_auth_kerb) {
                nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
                nd->nd_authlen = fxdr_unsigned(int, *tl);
        } else if (auth_type == rpc_auth_kerb) {
                nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
                nd->nd_authlen = fxdr_unsigned(int, *tl);
-               iov.iov_len = uio.uio_resid = nfsm_rndup(nd->nd_authlen);
-               if (uio.uio_resid > (len - 2*NFSX_UNSIGNED)) {
+               uio.uio_resid = nfsm_rndup(nd->nd_authlen);
+               if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
                        m_freem(mrep);
                        return (EBADRPC);
                }
                        m_freem(mrep);
                        return (EBADRPC);
                }
@@ -1851,8 +1868,9 @@ nfs_getreq(nd, has_header)
                uio.uio_iovcnt = 1;
                uio.uio_segflg = UIO_SYSSPACE;
                iov.iov_base = (caddr_t)nd->nd_authstr;
                uio.uio_iovcnt = 1;
                uio.uio_segflg = UIO_SYSSPACE;
                iov.iov_base = (caddr_t)nd->nd_authstr;
+               iov.iov_len = RPCAUTH_MAXSIZ;
                nfsm_mtouio(&uio, uio.uio_resid);
                nfsm_mtouio(&uio, uio.uio_resid);
-               nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
+               nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
                nd->nd_flag |= NFSD_NEEDAUTH;
        }
 
                nd->nd_flag |= NFSD_NEEDAUTH;
        }
 
index 3c8284c..e230713 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_subs.c  7.67 (Berkeley) %G%
+ *     @(#)nfs_subs.c  7.68 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -217,7 +217,7 @@ nfsm_rpchead(cr, nqnfs, procid, auth_type, auth_len, auth_str, mrest,
                        bpos += i;
                        siz -= i;
                }
                        bpos += i;
                        siz -= i;
                }
-               if ((siz = nfsm_rndup(auth_len) - auth_len) > 0) {
+               if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
                        for (i = 0; i < siz; i++)
                                *bpos++ = '\0';
                        mb->m_len += siz;
                        for (i = 0; i < siz; i++)
                                *bpos++ = '\0';
                        mb->m_len += siz;
@@ -748,17 +748,29 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
                vap->va_gen = fxdr_unsigned(u_long, fp->fa_nfsctime.nfs_usec);
                vap->va_filerev = 0;
        }
                vap->va_gen = fxdr_unsigned(u_long, fp->fa_nfsctime.nfs_usec);
                vap->va_filerev = 0;
        }
-       if (vap->va_size > np->n_size) {
-               np->n_size = vap->va_size;
-               vnode_pager_setsize(vp, (u_long)np->n_size);
+       if (vap->va_size != np->n_size) {
+               if (vap->va_type == VREG) {
+                       if (np->n_flag & NMODIFIED) {
+                               if (vap->va_size < np->n_size)
+                                       vap->va_size = np->n_size;
+                               else
+                                       np->n_size = vap->va_size;
+                       } else
+                               np->n_size = vap->va_size;
+                       vnode_pager_setsize(vp, (u_long)np->n_size);
+               } else
+                       np->n_size = vap->va_size;
        }
        np->n_attrstamp = time.tv_sec;
        *dposp = dpos;
        *mdp = md;
        if (vaper != NULL) {
                bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
        }
        np->n_attrstamp = time.tv_sec;
        *dposp = dpos;
        *mdp = md;
        if (vaper != NULL) {
                bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
+#ifdef notdef
                if ((np->n_flag & NMODIFIED) && np->n_size > vap->va_size)
                if ((np->n_flag & NMODIFIED) && np->n_size > vap->va_size)
+               if (np->n_size > vap->va_size)
                        vaper->va_size = np->n_size;
                        vaper->va_size = np->n_size;
+#endif
                if (np->n_flag & NCHG) {
                        if (np->n_flag & NACC) {
                                vaper->va_atime.ts_sec = np->n_atim.tv_sec;
                if (np->n_flag & NCHG) {
                        if (np->n_flag & NACC) {
                                vaper->va_atime.ts_sec = np->n_atim.tv_sec;
@@ -780,13 +792,13 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
  * If the cache is valid, copy contents to *vap and return 0
  * otherwise return an error
  */
  * If the cache is valid, copy contents to *vap and return 0
  * otherwise return an error
  */
-nfs_getattrcache(vp, vap)
+nfs_getattrcache(vp, vaper)
        register struct vnode *vp;
        register struct vnode *vp;
-       struct vattr *vap;
+       struct vattr *vaper;
 {
 {
-       register struct nfsnode *np;
+       register struct nfsnode *np = VTONFS(vp);
+       register struct vattr *vap;
 
 
-       np = VTONFS(vp);
        if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQLOOKLEASE) {
                if (!NQNFS_CKCACHABLE(vp, NQL_READ) || np->n_attrstamp == 0) {
                        nfsstats.attrcache_misses++;
        if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQLOOKLEASE) {
                if (!NQNFS_CKCACHABLE(vp, NQL_READ) || np->n_attrstamp == 0) {
                        nfsstats.attrcache_misses++;
@@ -797,20 +809,37 @@ nfs_getattrcache(vp, vap)
                return (ENOENT);
        }
        nfsstats.attrcache_hits++;
                return (ENOENT);
        }
        nfsstats.attrcache_hits++;
-       bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
+       vap = &np->n_vattr;
+       if (vap->va_size != np->n_size) {
+               if (vap->va_type == VREG) {
+                       if (np->n_flag & NMODIFIED) {
+                               if (vap->va_size < np->n_size)
+                                       vap->va_size = np->n_size;
+                               else
+                                       np->n_size = vap->va_size;
+                       } else
+                               np->n_size = vap->va_size;
+                       vnode_pager_setsize(vp, (u_long)np->n_size);
+               } else
+                       np->n_size = vap->va_size;
+       }
+       bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
+#ifdef notdef
        if ((np->n_flag & NMODIFIED) == 0) {
        if ((np->n_flag & NMODIFIED) == 0) {
-               np->n_size = vap->va_size;
+               np->n_size = vaper->va_size;
                vnode_pager_setsize(vp, (u_long)np->n_size);
                vnode_pager_setsize(vp, (u_long)np->n_size);
-       } else if (np->n_size > vap->va_size)
-               vap->va_size = np->n_size;
+       } else if (np->n_size > vaper->va_size)
+       if (np->n_size > vaper->va_size)
+               vaper->va_size = np->n_size;
+#endif
        if (np->n_flag & NCHG) {
                if (np->n_flag & NACC) {
        if (np->n_flag & NCHG) {
                if (np->n_flag & NACC) {
-                       vap->va_atime.ts_sec = np->n_atim.tv_sec;
-                       vap->va_atime.ts_nsec = np->n_atim.tv_usec * 1000;
+                       vaper->va_atime.ts_sec = np->n_atim.tv_sec;
+                       vaper->va_atime.ts_nsec = np->n_atim.tv_usec * 1000;
                }
                if (np->n_flag & NUPD) {
                }
                if (np->n_flag & NUPD) {
-                       vap->va_mtime.ts_sec = np->n_mtim.tv_sec;
-                       vap->va_mtime.ts_nsec = np->n_mtim.tv_usec * 1000;
+                       vaper->va_mtime.ts_sec = np->n_mtim.tv_sec;
+                       vaper->va_mtime.ts_nsec = np->n_mtim.tv_usec * 1000;
                }
        }
        return (0);
                }
        }
        return (0);
@@ -1008,6 +1037,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
 {
        register struct mount *mp;
        register struct nfsuid *uidp;
 {
        register struct mount *mp;
        register struct nfsuid *uidp;
+       register int i;
        struct ucred *credanon;
        int error, exflags;
 
        struct ucred *credanon;
        int error, exflags;
 
@@ -1027,13 +1057,18 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)
                        uidp = uidp->nu_hnext;
                }
                if (uidp) {
                        uidp = uidp->nu_hnext;
                }
                if (uidp) {
-                       if (cred->cr_ref != 1)
-                               panic("nsrv fhtovp");
-                       *cred = uidp->nu_cr;
-               } else
+                       cred->cr_uid = uidp->nu_cr.cr_uid;
+                       for (i = 0; i < uidp->nu_cr.cr_ngroups; i++)
+                               cred->cr_groups[i] = uidp->nu_cr.cr_groups[i];
+               } else {
+                       vput(*vpp);
                        return (NQNFS_AUTHERR);
                        return (NQNFS_AUTHERR);
-       } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON))
-               *cred = *credanon;
+               }
+       } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
+               cred->cr_uid = credanon->cr_uid;
+               for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
+                       cred->cr_groups[i] = credanon->cr_groups[i];
+       }
        if (exflags & MNT_EXRDONLY)
                *rdonlyp = 1;
        else
        if (exflags & MNT_EXRDONLY)
                *rdonlyp = 1;
        else
index d2e5721..033c140 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfsdiskless.h       7.4 (Berkeley) %G%
+ *     @(#)nfsdiskless.h       7.5 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -35,6 +35,6 @@ struct nfs_diskless {
        u_char          root_fh[NFS_FHSIZE];    /* File handle of root dir */
        struct sockaddr_in root_saddr;          /* Address of root server */
        char            root_hostnam[MNAMELEN]; /* Host name for mount pt */
        u_char          root_fh[NFS_FHSIZE];    /* File handle of root dir */
        struct sockaddr_in root_saddr;          /* Address of root server */
        char            root_hostnam[MNAMELEN]; /* Host name for mount pt */
-       time_t          root_time;              /* Timestamp of root fs */
+       long            root_time;              /* Timestamp of root fs */
        char            my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
 };
        char            my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
 };
index 598c75f..810ccee 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfsrvcache.h        7.5 (Berkeley) %G%
+ *     @(#)nfsrvcache.h        7.6 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -47,6 +47,7 @@ struct nfsrvcache {
 #define        RC_DROPIT       0
 #define        RC_REPLY        1
 #define        RC_DOIT         2
 #define        RC_DROPIT       0
 #define        RC_REPLY        1
 #define        RC_DOIT         2
+#define        RC_CHECKIT      3
 
 /* Flag bits */
 #define        RC_LOCKED       0x01
 
 /* Flag bits */
 #define        RC_LOCKED       0x01