update from Rick Macklem
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 17 Sep 1992 09:29:42 +0000 (01:29 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 17 Sep 1992 09:29:42 +0000 (01:29 -0800)
SCCS-vsn: sys/nfs/nfs.h 7.18
SCCS-vsn: sys/nfs/nfsm_subs.h 7.14
SCCS-vsn: sys/nfs/nfsnode.h 7.29
SCCS-vsn: sys/nfs/nfsproto.h 7.10
SCCS-vsn: sys/nfs/nqnfs.h 7.5
SCCS-vsn: sys/nfs/xdr_subs.h 7.5
SCCS-vsn: sys/nfs/nfs_bio.c 7.32
SCCS-vsn: sys/nfs/nfs_node.c 7.43
SCCS-vsn: sys/nfs/nfs_nqlease.c 7.11
SCCS-vsn: sys/nfs/nfs_serv.c 7.59
SCCS-vsn: sys/nfs/nfs_socket.c 7.37
SCCS-vsn: sys/nfs/nfs_subs.c 7.63
SCCS-vsn: sys/nfs/nfs_vfsops.c 7.45
SCCS-vsn: sys/nfs/nfs_vnops.c 7.91

14 files changed:
usr/src/sys/nfs/nfs.h
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_serv.c
usr/src/sys/nfs/nfs_socket.c
usr/src/sys/nfs/nfs_subs.c
usr/src/sys/nfs/nfs_vfsops.c
usr/src/sys/nfs/nfs_vnops.c
usr/src/sys/nfs/nfsm_subs.h
usr/src/sys/nfs/nfsnode.h
usr/src/sys/nfs/nfsproto.h
usr/src/sys/nfs/nqnfs.h
usr/src/sys/nfs/xdr_subs.h

index 7d1f999..f58b441 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs.h       7.17 (Berkeley) %G%
+ *     @(#)nfs.h       7.18 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -24,7 +24,8 @@
 #define        NFS_MAXWINDOW   1024            /* Max number of outstanding requests */
 #define        NFS_RETRANS     10              /* Num of retrans for soft mounts */
 #define        NFS_MAXGRPS     16              /* Max. size of groups list */
 #define        NFS_MAXWINDOW   1024            /* Max number of outstanding requests */
 #define        NFS_RETRANS     10              /* Num of retrans for soft mounts */
 #define        NFS_MAXGRPS     16              /* Max. size of groups list */
-#define        NFS_ATTRTIMEO   5               /* Attribute cache timeout in sec */
+#define        NFS_MINATTRTIMO 5               /* Attribute cache timeout in sec */
+#define        NFS_MAXATTRTIMO 60
 #define        NFS_WSIZE       8192            /* Def. write data size <= 8192 */
 #define        NFS_RSIZE       8192            /* Def. read data size <= 8192 */
 #define        NFS_DEFRAHEAD   1               /* Def. read ahead # blocks */
 #define        NFS_WSIZE       8192            /* Def. write data size <= 8192 */
 #define        NFS_RSIZE       8192            /* Def. read data size <= 8192 */
 #define        NFS_DEFRAHEAD   1               /* Def. read ahead # blocks */
 #define        NFS_DIRBLKSIZ   1024            /* Size of an NFS directory block */
 #define        NMOD(a)         ((a) % nfs_asyncdaemons)
 
 #define        NFS_DIRBLKSIZ   1024            /* Size of an NFS directory block */
 #define        NMOD(a)         ((a) % nfs_asyncdaemons)
 
+/*
+ * Set the attribute timeout based on how recently the file has been modified.
+ */
+#define        NFS_ATTRTIMEO(np) \
+       ((((np)->n_flag & NMODIFIED) || \
+        5 * (time.tv_sec - (np)->n_mtime) < NFS_MINATTRTIMO) ? NFS_MINATTRTIMO : \
+        (5 * (time.tv_sec - (np)->n_mtime) > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
+         5 * (time.tv_sec - (np)->n_mtime)))
+
 /*
  * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
  * should ever try and use it.
 /*
  * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
  * should ever try and use it.
index f65c53d..6172fa3 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_bio.c   7.31 (Berkeley) %G%
+ *     @(#)nfs_bio.c   7.32 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -302,6 +302,7 @@ nfs_write(ap)
        if (ioflag & (IO_APPEND | IO_SYNC)) {
                if (np->n_flag & NMODIFIED) {
                        np->n_flag &= ~NMODIFIED;
        if (ioflag & (IO_APPEND | IO_SYNC)) {
                if (np->n_flag & NMODIFIED) {
                        np->n_flag &= ~NMODIFIED;
+                       np->n_attrstamp = 0;
                        vinvalbuf(vp, TRUE, cred, p);
                }
                if (ioflag & IO_APPEND) {
                        vinvalbuf(vp, TRUE, cred, p);
                }
                if (ioflag & IO_APPEND) {
@@ -352,7 +353,7 @@ nfs_write(ap)
                        }
                }
                if (np->n_flag & NQNFSNONCACHE)
                        }
                }
                if (np->n_flag & NQNFSNONCACHE)
-                       return (nfs_writerpc(vp, uio, cred));
+                       return (nfs_writerpc(vp, uio, cred, 0));
                nfsstats.biocache_writes++;
                lbn = uio->uio_offset / biosize;
                on = uio->uio_offset & (biosize-1);
                nfsstats.biocache_writes++;
                lbn = uio->uio_offset / biosize;
                on = uio->uio_offset & (biosize-1);
@@ -397,8 +398,10 @@ again:
                        }
                        if (np->n_lrev != np->n_brev ||
                            (np->n_flag & NQNFSNONCACHE)) {
                        }
                        if (np->n_lrev != np->n_brev ||
                            (np->n_flag & NQNFSNONCACHE)) {
+                               brelse(bp);
                                vinvalbuf(vp, TRUE, cred, p);
                                np->n_brev = np->n_lrev;
                                vinvalbuf(vp, TRUE, cred, p);
                                np->n_brev = np->n_lrev;
+                               goto again;
                        }
                }
                if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
                        }
                }
                if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
index 6c412b1..475c82c 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_node.c  7.42 (Berkeley) %G%
+ *     @(#)nfs_node.c  7.43 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -116,13 +116,13 @@ loop:
        np->n_direofoffset = 0;
        np->n_sillyrename = (struct sillyrename *)0;
        np->n_size = 0;
        np->n_direofoffset = 0;
        np->n_sillyrename = (struct sillyrename *)0;
        np->n_size = 0;
+       np->n_mtime = 0;
        if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
                np->n_brev = 0;
                np->n_lrev = 0;
                np->n_expiry = (time_t)0;
                np->n_tnext = (struct nfsnode *)0;
        if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
                np->n_brev = 0;
                np->n_lrev = 0;
                np->n_expiry = (time_t)0;
                np->n_tnext = (struct nfsnode *)0;
-       } else
-               np->n_mtime = 0;
+       }
        *npp = np;
        return (0);
 }
        *npp = np;
        return (0);
 }
index 089e424..cf2645a 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_nqlease.c       7.10 (Berkeley) %G%
+ *     @(#)nfs_nqlease.c       7.11 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -64,6 +64,7 @@ int nqsrv_maxnumlease = NQ_MAXNUMLEASE;
 void nqsrv_instimeq(), nqsrv_send_eviction(), nfs_sndunlock();
 void nqsrv_unlocklease(), nqsrv_waitfor_expiry(), nfsrv_slpderef();
 void nqsrv_addhost(), nqsrv_locklease(), nqnfs_serverd();
 void nqsrv_instimeq(), nqsrv_send_eviction(), nfs_sndunlock();
 void nqsrv_unlocklease(), nqsrv_waitfor_expiry(), nfsrv_slpderef();
 void nqsrv_addhost(), nqsrv_locklease(), nqnfs_serverd();
+void nqnfs_clientlease();
 struct mbuf *nfsm_rpchead();
 
 /*
 struct mbuf *nfsm_rpchead();
 
 /*
@@ -692,12 +693,12 @@ nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
                nam, &cache, &frev, cred);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
                nam, &cache, &frev, cred);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_FATTR + 4*NFSX_UNSIGNED);
+       nfsm_reply(NFSX_NQFATTR + 4*NFSX_UNSIGNED);
        nfsm_build(tl, u_long *, 4*NFSX_UNSIGNED);
        *tl++ = txdr_unsigned(cache);
        *tl++ = txdr_unsigned(nfsd->nd_duration);
        txdr_hyper(&frev, tl);
        nfsm_build(tl, u_long *, 4*NFSX_UNSIGNED);
        *tl++ = txdr_unsigned(cache);
        *tl++ = txdr_unsigned(nfsd->nd_duration);
        txdr_hyper(&frev, tl);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_NQFATTR);
        nfsm_srvfillattr;
        nfsm_srvdone;
 }
        nfsm_srvfillattr;
        nfsm_srvdone;
 }
@@ -804,6 +805,7 @@ nqnfs_getlease(vp, rwflag, cred, p)
        int error = 0;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        int cachable;
        int error = 0;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        int cachable;
+       u_quad_t frev;
        
        nfsstats.rpccnt[NQNFSPROC_GETLEASE]++;
        mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_FH+2*NFSX_UNSIGNED,
        
        nfsstats.rpccnt[NQNFSPROC_GETLEASE]++;
        mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_FH+2*NFSX_UNSIGNED,
@@ -819,42 +821,8 @@ nqnfs_getlease(vp, rwflag, cred, p)
        cachable = fxdr_unsigned(int, *tl++);
        reqtime += fxdr_unsigned(int, *tl++);
        if (reqtime > time.tv_sec) {
        cachable = fxdr_unsigned(int, *tl++);
        reqtime += fxdr_unsigned(int, *tl++);
        if (reqtime > time.tv_sec) {
-               if (np->n_tnext) {
-                       if (np->n_tnext == (struct nfsnode *)nmp)
-                               nmp->nm_tprev = np->n_tprev;
-                       else
-                               np->n_tnext->n_tprev = np->n_tprev;
-                       if (np->n_tprev == (struct nfsnode *)nmp)
-                               nmp->nm_tnext = np->n_tnext;
-                       else
-                               np->n_tprev->n_tnext = np->n_tnext;
-                       if (rwflag == NQL_WRITE)
-                               np->n_flag |= NQNFSWRITE;
-               } else if (rwflag == NQL_READ)
-                       np->n_flag &= ~NQNFSWRITE;
-               else
-                       np->n_flag |= NQNFSWRITE;
-               if (cachable)
-                       np->n_flag &= ~NQNFSNONCACHE;
-               else
-                       np->n_flag |= NQNFSNONCACHE;
-               np->n_expiry = reqtime;
-               fxdr_hyper(tl, &np->n_lrev);
-               tp = nmp->nm_tprev;
-               while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry)
-                       tp = tp->n_tprev;
-               if (tp == (struct nfsnode *)nmp) {
-                       np->n_tnext = nmp->nm_tnext;
-                       nmp->nm_tnext = np;
-               } else {
-                       np->n_tnext = tp->n_tnext;
-                       tp->n_tnext = np;
-               }
-               np->n_tprev = tp;
-               if (np->n_tnext == (struct nfsnode *)nmp)
-                       nmp->nm_tprev = np;
-               else
-                       np->n_tnext->n_tprev = np;
+               fxdr_hyper(tl, &frev);
+               nqnfs_clientlease(nmp, np, rwflag, cachable, reqtime, frev);
                nfsm_loadattr(vp, (struct vattr *)0);
        } else
                error = NQNFS_EXPIRED;
                nfsm_loadattr(vp, (struct vattr *)0);
        } else
                error = NQNFS_EXPIRED;
@@ -1177,3 +1145,54 @@ nqsrv_unlocklease(lp)
        if (lp->lc_flag & LC_WANTED)
                wakeup((caddr_t)lp);
 }
        if (lp->lc_flag & LC_WANTED)
                wakeup((caddr_t)lp);
 }
+
+/*
+ * Update a client lease.
+ */
+void
+nqnfs_clientlease(nmp, np, rwflag, cachable, expiry, frev)
+       register struct nfsmount *nmp;
+       register struct nfsnode *np;
+       int rwflag, cachable;
+       time_t expiry;
+       u_quad_t frev;
+{
+       register struct nfsnode *tp;
+
+       if (np->n_tnext) {
+               if (np->n_tnext == (struct nfsnode *)nmp)
+                       nmp->nm_tprev = np->n_tprev;
+               else
+                       np->n_tnext->n_tprev = np->n_tprev;
+               if (np->n_tprev == (struct nfsnode *)nmp)
+                       nmp->nm_tnext = np->n_tnext;
+               else
+                       np->n_tprev->n_tnext = np->n_tnext;
+               if (rwflag == NQL_WRITE)
+                       np->n_flag |= NQNFSWRITE;
+       } else if (rwflag == NQL_READ)
+               np->n_flag &= ~NQNFSWRITE;
+       else
+               np->n_flag |= NQNFSWRITE;
+       if (cachable)
+               np->n_flag &= ~NQNFSNONCACHE;
+       else
+               np->n_flag |= NQNFSNONCACHE;
+       np->n_expiry = expiry;
+       np->n_lrev = frev;
+       tp = nmp->nm_tprev;
+       while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry)
+               tp = tp->n_tprev;
+       if (tp == (struct nfsnode *)nmp) {
+               np->n_tnext = nmp->nm_tnext;
+               nmp->nm_tnext = np;
+       } else {
+               np->n_tnext = tp->n_tnext;
+               tp->n_tnext = np;
+       }
+       np->n_tprev = tp;
+       if (np->n_tnext == (struct nfsnode *)nmp)
+               nmp->nm_tprev = np;
+       else
+               np->n_tnext->n_tprev = np;
+}
index 55f467a..97a41be 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_serv.c  7.58 (Berkeley) %G%
+ *     @(#)nfs_serv.c  7.59 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -90,8 +90,8 @@ nfsrv_getattr(nfsd, mrep, md, dpos, cred, nam, mrq)
        nqsrv_getl(vp, NQL_READ);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
        nqsrv_getl(vp, NQL_READ);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_FATTR);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfillattr;
        nfsm_srvdone;
 }
        nfsm_srvfillattr;
        nfsm_srvdone;
 }
@@ -123,7 +123,7 @@ nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR);
+       nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
                nfsm_reply(0);
        nqsrv_getl(vp, NQL_WRITE);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
                nfsm_reply(0);
        nqsrv_getl(vp, NQL_WRITE);
@@ -143,21 +143,28 @@ nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq)
                vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
        if (sp->sa_gid != nfs_xdrneg1)
                vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
                vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
        if (sp->sa_gid != nfs_xdrneg1)
                vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
-       if (sp->sa_size != nfs_xdrneg1)
-               vap->va_size = fxdr_unsigned(u_long, sp->sa_size);
-       /*
-        * The usec field of sa_atime is overloaded with the va_flags field
-        * for 4.4BSD clients. Hopefully other clients always set both the
-        * sec and usec fields to -1 when not setting the atime.
-        */
-       if (sp->sa_atime.tv_sec != nfs_xdrneg1) {
-               vap->va_atime.ts_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec);
-               vap->va_atime.ts_nsec = 0;
+       if (nfsd->nd_nqlflag == NQL_NOVAL) {
+               if (sp->sa_nfssize != nfs_xdrneg1)
+                       vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_nfssize);
+               /*
+                * The usec field of sa_atime is overloaded with the va_flags field
+                * for 4.4BSD clients. Hopefully other clients always set both the
+                * sec and usec fields to -1 when not setting the atime.
+                */
+               if (sp->sa_nfsatime.nfs_sec != nfs_xdrneg1) {
+                       vap->va_atime.ts_sec = fxdr_unsigned(long, sp->sa_nfsatime.nfs_sec);
+                       vap->va_atime.ts_nsec = 0;
+               }
+               if (sp->sa_nfsatime.nfs_usec != nfs_xdrneg1)
+                       vap->va_flags = fxdr_unsigned(u_long, sp->sa_nfsatime.nfs_usec);
+               if (sp->sa_nfsmtime.nfs_sec != nfs_xdrneg1)
+                       fxdr_nfstime(&sp->sa_nfsmtime, &vap->va_mtime);
+       } else {
+               fxdr_hyper(&sp->sa_nqsize, &vap->va_size);
+               fxdr_nqtime(&sp->sa_nqatime, &vap->va_atime);
+               fxdr_nqtime(&sp->sa_nqmtime, &vap->va_mtime);
+               vap->va_flags = fxdr_unsigned(u_long, sp->sa_nqflags);
        }
        }
-       if (sp->sa_atime.tv_usec != nfs_xdrneg1)
-               vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec);
-       if (sp->sa_mtime.tv_sec != nfs_xdrneg1)
-               fxdr_time(&sp->sa_mtime, &vap->va_mtime);
        if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
                vput(vp);
                nfsm_reply(0);
        if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
                vput(vp);
                nfsm_reply(0);
@@ -165,8 +172,8 @@ nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq)
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
 out:
        vput(vp);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
 out:
        vput(vp);
-       nfsm_reply(NFSX_FATTR + 2*NFSX_UNSIGNED);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 2*NFSX_UNSIGNED);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfillattr;
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
                nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
        nfsm_srvfillattr;
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
                nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
@@ -194,7 +201,7 @@ nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)
        register u_long *tl;
        register long t1;
        caddr_t bpos;
        register u_long *tl;
        register long t1;
        caddr_t bpos;
-       int error = 0, lflag = 0, rdonly, cache, duration2, cache2, len;
+       int error = 0, rdonly, cache, duration2, cache2, len;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vattr va, *vap = &va;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vattr va, *vap = &va;
@@ -203,11 +210,7 @@ nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)
        fhp = &nfh.fh_generic;
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
                nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
        fhp = &nfh.fh_generic;
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
                nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
-               if (*tl) {
-                       lflag = fxdr_unsigned(int, *tl);
-                       nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
-                       duration2 = fxdr_unsigned(int, *tl);
-               }
+               duration2 = fxdr_unsigned(int, *tl);
        }
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        }
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
@@ -227,16 +230,16 @@ nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
-       if (lflag)
-               (void) nqsrv_getlease(vp, &duration2, lflag, nfsd,
+       if (duration2)
+               (void) nqsrv_getlease(vp, &duration2, NQL_READ, nfsd,
                        nam, &cache2, &frev2, cred);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
                        nam, &cache2, &frev2, cred);
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_FH + NFSX_FATTR + 5*NFSX_UNSIGNED);
+       nfsm_reply(NFSX_FH + NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 5*NFSX_UNSIGNED);
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
-               if (lflag) {
+               if (duration2) {
                        nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
                        nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
-                       *tl++ = txdr_unsigned(lflag);
+                       *tl++ = txdr_unsigned(NQL_READ);
                        *tl++ = txdr_unsigned(cache2);
                        *tl++ = txdr_unsigned(duration2);
                        txdr_hyper(&frev2, tl);
                        *tl++ = txdr_unsigned(cache2);
                        *tl++ = txdr_unsigned(duration2);
                        txdr_hyper(&frev2, tl);
@@ -246,7 +249,7 @@ nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)
                }
        }
        nfsm_srvfhtom(fhp);
                }
        }
        nfsm_srvfhtom(fhp);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfillattr;
        nfsm_srvdone;
 }
        nfsm_srvfillattr;
        nfsm_srvdone;
 }
@@ -364,8 +367,13 @@ nfsrv_read(nfsd, mrep, md, dpos, cred, nam, mrq)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
-       off = fxdr_unsigned(off_t, *tl);
+       if (nfsd->nd_nqlflag == NQL_NOVAL) {
+               nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
+               off = (off_t)fxdr_unsigned(u_long, *tl);
+       } else {
+               nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
+               fxdr_hyper(tl, &off);
+       }
        nfsm_srvstrsiz(cnt, NFS_MAXDATA);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
                nfsm_reply(0);
        nfsm_srvstrsiz(cnt, NFS_MAXDATA);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
                nfsm_reply(0);
@@ -382,8 +390,8 @@ nfsrv_read(nfsd, mrep, md, dpos, cred, nam, mrq)
                cnt = 0;
        else if ((off + cnt) > vap->va_size)
                cnt = nfsm_rndup(vap->va_size - off);
                cnt = 0;
        else if ((off + cnt) > vap->va_size)
                cnt = nfsm_rndup(vap->va_size - off);
-       nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED+nfsm_rndup(cnt));
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)+NFSX_UNSIGNED+nfsm_rndup(cnt));
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_build(tl, u_long *, NFSX_UNSIGNED);
        len = left = cnt;
        if (cnt > 0) {
        nfsm_build(tl, u_long *, NFSX_UNSIGNED);
        len = left = cnt;
        if (cnt > 0) {
@@ -461,6 +469,7 @@ nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq)
        register long t1;
        caddr_t bpos;
        int error = 0, rdonly, cache, siz, len, xfer;
        register long t1;
        caddr_t bpos;
        int error = 0, rdonly, cache, siz, len, xfer;
+       int ioflags = IO_SYNC | IO_NODELOCKED;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp;
@@ -472,9 +481,16 @@ nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
-       off = fxdr_unsigned(off_t, *++tl);
-       tl += 2;
+       nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
+       if (nfsd->nd_nqlflag == NQL_NOVAL) {
+               off = (off_t)fxdr_unsigned(u_long, *++tl);
+               tl += 2;
+       } else {
+               fxdr_hyper(tl, &off);
+               tl += 2;
+               if (fxdr_unsigned(u_long, *tl++))
+                       ioflags |= IO_APPEND;
+       }
        len = fxdr_unsigned(long, *tl);
        if (len > NFS_MAXDATA || len <= 0) {
                error = EBADRPC;
        len = fxdr_unsigned(long, *tl);
        if (len > NFS_MAXDATA || len <= 0) {
                error = EBADRPC;
@@ -538,8 +554,7 @@ nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq)
                        nfsm_reply(0);
                }
                uiop->uio_resid = siz;
                        nfsm_reply(0);
                }
                uiop->uio_resid = siz;
-               if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED,
-                       cred)) {
+               if (error = VOP_WRITE(vp, uiop, ioflags, cred)) {
                        vput(vp);
                        nfsm_reply(0);
                }
                        vput(vp);
                        nfsm_reply(0);
                }
@@ -547,8 +562,8 @@ nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq)
        }
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
        }
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_FATTR);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfillattr;
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
                nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
        nfsm_srvfillattr;
        if (nfsd->nd_nqlflag != NQL_NOVAL) {
                nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
@@ -571,12 +586,13 @@ nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq)
        register struct nfsv2_fattr *fp;
        struct vattr va;
        register struct vattr *vap = &va;
        register struct nfsv2_fattr *fp;
        struct vattr va;
        register struct vattr *vap = &va;
+       register struct nfsv2_sattr *sp;
+       register u_long *tl;
        struct nameidata nd;
        register caddr_t cp;
        struct nameidata nd;
        register caddr_t cp;
-       register u_long *tl;
        register long t1;
        caddr_t bpos;
        register long t1;
        caddr_t bpos;
-       int error = 0, rdev, cache, len;
+       int error = 0, rdev, cache, len, tsize;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp;
@@ -595,18 +611,21 @@ nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq)
            nfsd->nd_procp))
                nfsm_reply(0);
        VATTR_NULL(vap);
            nfsd->nd_procp))
                nfsm_reply(0);
        VATTR_NULL(vap);
-       nfsm_dissect(tl, u_long *, NFSX_SATTR);
+       nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        /*
         * Iff doesn't exist, create it
         * otherwise just truncate to 0 length
         *   should I set the mode too ??
         */
        if (nd.ni_vp == NULL) {
        /*
         * Iff doesn't exist, create it
         * otherwise just truncate to 0 length
         *   should I set the mode too ??
         */
        if (nd.ni_vp == NULL) {
-               vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl));
+               vap->va_type = IFTOVT(fxdr_unsigned(u_long, sp->sa_mode));
                if (vap->va_type == VNON)
                        vap->va_type = VREG;
                if (vap->va_type == VNON)
                        vap->va_type = VREG;
-               vap->va_mode = nfstov_mode(*tl);
-               rdev = fxdr_unsigned(long, *(tl+3));
+               vap->va_mode = nfstov_mode(sp->sa_mode);
+               if (nfsd->nd_nqlflag == NQL_NOVAL)
+                       rdev = fxdr_unsigned(long, sp->sa_nfssize);
+               else
+                       rdev = fxdr_unsigned(long, sp->sa_nqrdev);
                if (vap->va_type == VREG || vap->va_type == VSOCK) {
                        p->p_spare[1]--;
                        vrele(nd.ni_startdir);
                if (vap->va_type == VREG || vap->va_type == VSOCK) {
                        p->p_spare[1]--;
                        vrele(nd.ni_startdir);
@@ -670,11 +689,20 @@ nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq)
                else
                        vput(nd.ni_dvp);
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                else
                        vput(nd.ni_dvp);
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
-               vap->va_size = 0;
-               nqsrv_getl(vp, NQL_WRITE);
-               if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
-                       vput(vp);
-                       nfsm_reply(0);
+               if (nfsd->nd_nqlflag == NQL_NOVAL) {
+                       tsize = fxdr_unsigned(long, sp->sa_nfssize);
+                       if (tsize != -1)
+                               vap->va_size = (u_quad_t)tsize;
+                       else
+                               vap->va_size = -1;
+               } else
+                       fxdr_hyper(&sp->sa_nqsize, &vap->va_size);
+               if (vap->va_size != -1) {
+                       nqsrv_getl(vp, NQL_WRITE);
+                       if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
+                               vput(vp);
+                               nfsm_reply(0);
+                       }
                }
        }
        bzero((caddr_t)fhp, sizeof(nfh));
                }
        }
        bzero((caddr_t)fhp, sizeof(nfh));
@@ -685,9 +713,9 @@ nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq)
        }
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
        }
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_FH+NFSX_FATTR);
+       nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfhtom(fhp);
        nfsm_srvfhtom(fhp);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfillattr;
        return (error);
 nfsmout:
        nfsm_srvfillattr;
        return (error);
 nfsmout:
@@ -1019,7 +1047,7 @@ nfsrv_symlink(nfsd, mrep, md, dpos, cred, nam, mrq)
        io.uio_rw = UIO_READ;
        io.uio_procp = (struct proc *)0;
        nfsm_mtouio(&io, len2);
        io.uio_rw = UIO_READ;
        io.uio_procp = (struct proc *)0;
        nfsm_mtouio(&io, len2);
-       nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR);
+       nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        *(pathcp + len2) = '\0';
        if (nd.ni_vp) {
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        *(pathcp + len2) = '\0';
        if (nd.ni_vp) {
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -1115,9 +1143,9 @@ nfsrv_mkdir(nfsd, mrep, md, dpos, cred, nam, mrq)
        }
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
        }
        error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_FH+NFSX_FATTR);
+       nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfhtom(fhp);
        nfsm_srvfhtom(fhp);
-       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
        nfsm_srvfillattr;
        return (error);
 nfsmout:
        nfsm_srvfillattr;
        return (error);
 nfsmout:
@@ -1230,7 +1258,7 @@ struct flrep {
        u_long fl_duration;
        u_long fl_frev[2];
        nfsv2fh_t fl_nfh;
        u_long fl_duration;
        u_long fl_frev[2];
        nfsv2fh_t fl_nfh;
-       struct nfsv2_fattr fl_fattr;
+       u_long fl_fattr[NFSX_NQFATTR / sizeof (u_long)];
 };
 
 nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
 };
 
 nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
@@ -1258,13 +1286,12 @@ nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
        int len, nlen, rem, xfer, tsiz, i, error = 0;
        int siz, cnt, fullsiz, eofflag, rdonly, cache;
        u_quad_t frev;
        int len, nlen, rem, xfer, tsiz, i, error = 0;
        int siz, cnt, fullsiz, eofflag, rdonly, cache;
        u_quad_t frev;
-       u_long on;
-       off_t off, toff;
+       u_long on, off, toff;
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
-       toff = fxdr_unsigned(off_t, *tl++);
+       toff = fxdr_unsigned(u_long, *tl++);
        off = (toff & ~(NFS_DIRBLKSIZ-1));
        on = (toff & (NFS_DIRBLKSIZ-1));
        cnt = fxdr_unsigned(int, *tl);
        off = (toff & ~(NFS_DIRBLKSIZ-1));
        on = (toff & (NFS_DIRBLKSIZ-1));
        cnt = fxdr_unsigned(int, *tl);
@@ -1286,13 +1313,13 @@ again:
        iv.iov_len = fullsiz;
        io.uio_iov = &iv;
        io.uio_iovcnt = 1;
        iv.iov_len = fullsiz;
        io.uio_iov = &iv;
        io.uio_iovcnt = 1;
-       io.uio_offset = off;
+       io.uio_offset = (off_t)off;
        io.uio_resid = fullsiz;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        io.uio_procp = (struct proc *)0;
        error = VOP_READDIR(vp, &io, cred);
        io.uio_resid = fullsiz;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        io.uio_procp = (struct proc *)0;
        error = VOP_READDIR(vp, &io, cred);
-       off = io.uio_offset;
+       off = (off_t)io.uio_offset;
        if (error) {
                vrele(vp);
                free((caddr_t)rbuf, M_TEMP);
        if (error) {
                vrele(vp);
                free((caddr_t)rbuf, M_TEMP);
@@ -1446,13 +1473,12 @@ nqnfsrv_readdirlook(nfsd, mrep, md, dpos, cred, nam, mrq)
        int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;
        int siz, cnt, fullsiz, eofflag, rdonly, cache;
        u_quad_t frev, frev2;
        int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;
        int siz, cnt, fullsiz, eofflag, rdonly, cache;
        u_quad_t frev, frev2;
-       u_long on;
-       off_t off, toff;
+       u_long on, off, toff;
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
-       toff = fxdr_unsigned(off_t, *tl++);
+       toff = fxdr_unsigned(u_long, *tl++);
        off = (toff & ~(NFS_DIRBLKSIZ-1));
        on = (toff & (NFS_DIRBLKSIZ-1));
        cnt = fxdr_unsigned(int, *tl++);
        off = (toff & ~(NFS_DIRBLKSIZ-1));
        on = (toff & (NFS_DIRBLKSIZ-1));
        cnt = fxdr_unsigned(int, *tl++);
@@ -1475,13 +1501,13 @@ again:
        iv.iov_len = fullsiz;
        io.uio_iov = &iv;
        io.uio_iovcnt = 1;
        iv.iov_len = fullsiz;
        io.uio_iov = &iv;
        io.uio_iovcnt = 1;
-       io.uio_offset = off;
+       io.uio_offset = (off_t)off;
        io.uio_resid = fullsiz;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        io.uio_procp = (struct proc *)0;
        error = VOP_READDIR(vp, &io, cred);
        io.uio_resid = fullsiz;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        io.uio_procp = (struct proc *)0;
        error = VOP_READDIR(vp, &io, cred);
-       off = io.uio_offset;
+       off = (u_long)io.uio_offset;
        if (error) {
                vrele(vp);
                free((caddr_t)rbuf, M_TEMP);
        if (error) {
                vrele(vp);
                free((caddr_t)rbuf, M_TEMP);
@@ -1500,8 +1526,8 @@ again:
                 */
                if (siz == 0) {
                        vrele(vp);
                 */
                if (siz == 0) {
                        vrele(vp);
-                       nfsm_reply(2*NFSX_UNSIGNED);
-                       nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+                       nfsm_reply(2 * NFSX_UNSIGNED);
+                       nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
                        *tl++ = nfs_false;
                        *tl = nfs_true;
                        FREE((caddr_t)rbuf, M_TEMP);
                        *tl++ = nfs_false;
                        *tl = nfs_true;
                        FREE((caddr_t)rbuf, M_TEMP);
@@ -1530,7 +1556,7 @@ again:
        cpos = rbuf + on;
        cend = rbuf + siz;
        dp = (struct dirent *)cpos;
        cpos = rbuf + on;
        cend = rbuf + siz;
        dp = (struct dirent *)cpos;
-       len = 3*NFSX_UNSIGNED;  /* paranoia, probably can be 0 */
+       len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
        nfsm_reply(siz);
        mp = mp2 = mb;
        bp = bpos;
        nfsm_reply(siz);
        mp = mp2 = mb;
        bp = bpos;
@@ -1555,20 +1581,23 @@ again:
                                vput(nvp);
                                goto invalid;
                        }
                                vput(nvp);
                                goto invalid;
                        }
-                       (void) nqsrv_getlease(nvp, &duration2, NQL_READ, nfsd,
-                               nam, &cache2, &frev2, cred);
-                       fl.fl_duration = txdr_unsigned(duration2);
-                       fl.fl_cachable = txdr_unsigned(cache2);
-                       txdr_hyper(&frev2, fl.fl_frev);
+                       if (duration2) {
+                               (void) nqsrv_getlease(nvp, &duration2, NQL_READ,
+                                       nfsd, nam, &cache2, &frev2, cred);
+                               fl.fl_duration = txdr_unsigned(duration2);
+                               fl.fl_cachable = txdr_unsigned(cache2);
+                               txdr_hyper(&frev2, fl.fl_frev);
+                       } else
+                               fl.fl_duration = 0;
                        if (VOP_GETATTR(nvp, vap, cred, nfsd->nd_procp)) {
                                vput(nvp);
                                goto invalid;
                        }
                        vput(nvp);
                        if (VOP_GETATTR(nvp, vap, cred, nfsd->nd_procp)) {
                                vput(nvp);
                                goto invalid;
                        }
                        vput(nvp);
-                       fp = &fl.fl_fattr;
+                       fp = (struct nfsv2_fattr *)&fl.fl_fattr;
                        nfsm_srvfillattr;
                        len += (4*NFSX_UNSIGNED + nlen + rem + NFSX_FH
                        nfsm_srvfillattr;
                        len += (4*NFSX_UNSIGNED + nlen + rem + NFSX_FH
-                               + NFSX_FATTR);
+                               + NFSX_NQFATTR);
                        if (len > cnt) {
                                eofflag = 0;
                                break;
                        if (len > cnt) {
                                eofflag = 0;
                                break;
@@ -1669,7 +1698,7 @@ nfsrv_statfs(nfsd, mrep, md, dpos, cred, nam, mrq)
        register u_long *tl;
        register long t1;
        caddr_t bpos;
        register u_long *tl;
        register long t1;
        caddr_t bpos;
-       int error = 0, rdonly, cache;
+       int error = 0, rdonly, cache, isnq;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp;
        char *cp2;
        struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp;
@@ -1679,19 +1708,24 @@ nfsrv_statfs(nfsd, mrep, md, dpos, cred, nam, mrq)
        u_quad_t frev;
 
        fhp = &nfh.fh_generic;
        u_quad_t frev;
 
        fhp = &nfh.fh_generic;
+       isnq = (nfsd->nd_nqlflag != NQL_NOVAL);
        nfsm_srvmtofh(fhp);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
                nfsm_reply(0);
        sf = &statfs;
        error = VFS_STATFS(vp->v_mount, sf, nfsd->nd_procp);
        vput(vp);
        nfsm_srvmtofh(fhp);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
                nfsm_reply(0);
        sf = &statfs;
        error = VFS_STATFS(vp->v_mount, sf, nfsd->nd_procp);
        vput(vp);
-       nfsm_reply(NFSX_STATFS);
-       nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
+       nfsm_reply(NFSX_STATFS(isnq));
+       nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
        sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
        sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
        sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
        sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
        sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
        sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
        sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
        sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
        sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
        sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
+       if (isnq) {
+               sfp->sf_files = txdr_unsigned(sf->f_files);
+               sfp->sf_ffree = txdr_unsigned(sf->f_ffree);
+       }
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
index fd7ccc4..7d29ae7 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_socket.c        7.36 (Berkeley) %G%
+ *     @(#)nfs_socket.c        7.37 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -126,7 +126,7 @@ static int proct[NFS_NPROCS] = {
 static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
 int    nfs_sbwait();
 void   nfs_disconnect(), nfs_realign(), nfsrv_wakenfsd(), nfs_sndunlock();
 static int nfs_backoff[8] = { 2, 4, 8, 16, 32, 64, 128, 256, };
 int    nfs_sbwait();
 void   nfs_disconnect(), nfs_realign(), nfsrv_wakenfsd(), nfs_sndunlock();
-void   nfs_rcvunlock(), nqnfs_serverd();
+void   nfs_rcvunlock(), nqnfs_serverd(), nqnfs_clientlease();
 struct mbuf *nfsm_rpchead();
 int nfsrtton = 0;
 struct nfsrtt nfsrtt;
 struct mbuf *nfsm_rpchead();
 int nfsrtton = 0;
 struct nfsrtt nfsrtt;
@@ -834,6 +834,7 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
        int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
        int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
        u_long xid;
        int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
        int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
        u_long xid;
+       u_quad_t frev;
        char *auth_str;
 
        nmp = VFSTONFS(vp->v_mount);
        char *auth_str;
 
        nmp = VFSTONFS(vp->v_mount);
@@ -1028,6 +1029,13 @@ tryagain:
                                        trylater_cnt++;
                                goto tryagain;
                        }
                                        trylater_cnt++;
                                goto tryagain;
                        }
+
+                       /*
+                        * If the File Handle was stale, invalidate the
+                        * lookup cache, just in case.
+                        */
+                       if (error == ESTALE)
+                               cache_purge(vp);
                        m_freem(rep->r_mreq);
                        free((caddr_t)rep, M_NFSREQ);
                        return (error);
                        m_freem(rep->r_mreq);
                        free((caddr_t)rep, M_NFSREQ);
                        return (error);
@@ -1045,43 +1053,9 @@ tryagain:
                                cachable = fxdr_unsigned(int, *tl++);
                                reqtime += fxdr_unsigned(int, *tl++);
                                if (reqtime > time.tv_sec) {
                                cachable = fxdr_unsigned(int, *tl++);
                                reqtime += fxdr_unsigned(int, *tl++);
                                if (reqtime > time.tv_sec) {
-                                   if (np->n_tnext) {
-                                       if (np->n_tnext == (struct nfsnode *)nmp)
-                                           nmp->nm_tprev = np->n_tprev;
-                                       else
-                                           np->n_tnext->n_tprev = np->n_tprev;
-                                       if (np->n_tprev == (struct nfsnode *)nmp)
-                                           nmp->nm_tnext = np->n_tnext;
-                                       else
-                                           np->n_tprev->n_tnext = np->n_tnext;
-                                       if (nqlflag == NQL_WRITE)
-                                           np->n_flag |= NQNFSWRITE;
-                                   } else if (nqlflag == NQL_READ)
-                                       np->n_flag &= ~NQNFSWRITE;
-                                   else
-                                       np->n_flag |= NQNFSWRITE;
-                                   if (cachable)
-                                       np->n_flag &= ~NQNFSNONCACHE;
-                                   else
-                                       np->n_flag |= NQNFSNONCACHE;
-                                   np->n_expiry = reqtime;
-                                   fxdr_hyper(tl, &np->n_lrev);
-                                   tp = nmp->nm_tprev;
-                                   while (tp != (struct nfsnode *)nmp &&
-                                          tp->n_expiry > np->n_expiry)
-                                               tp = tp->n_tprev;
-                                   if (tp == (struct nfsnode *)nmp) {
-                                       np->n_tnext = nmp->nm_tnext;
-                                       nmp->nm_tnext = np;
-                                   } else {
-                                       np->n_tnext = tp->n_tnext;
-                                       tp->n_tnext = np;
-                                   }
-                                   np->n_tprev = tp;
-                                   if (np->n_tnext == (struct nfsnode *)nmp)
-                                       nmp->nm_tprev = np;
-                                   else
-                                       np->n_tnext->n_tprev = np;
+                                   fxdr_hyper(tl, &frev);
+                                   nqnfs_clientlease(nmp, np, nqlflag,
+                                       cachable, reqtime, frev);
                                }
                        }
                }
                                }
                        }
                }
index 03cdc78..d319e3b 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_subs.c  7.62 (Berkeley) %G%
+ *     @(#)nfs_subs.c  7.63 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -638,26 +638,32 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
        register struct nfsnode *np, *nq, **nhpp;
        register long t1;
        caddr_t dpos, cp2;
        register struct nfsnode *np, *nq, **nhpp;
        register long t1;
        caddr_t dpos, cp2;
-       int error = 0;
+       int error = 0, isnq;
        struct mbuf *md;
        enum vtype vtyp;
        u_short vmode;
        long rdev;
        struct mbuf *md;
        enum vtype vtyp;
        u_short vmode;
        long rdev;
-       struct timeval mtime;
+       struct timespec mtime;
        struct vnode *nvp;
 
        md = *mdp;
        dpos = *dposp;
        t1 = (mtod(md, caddr_t) + md->m_len) - dpos;
        struct vnode *nvp;
 
        md = *mdp;
        dpos = *dposp;
        t1 = (mtod(md, caddr_t) + md->m_len) - dpos;
-       if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2))
+       isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS);
+       if (error = nfsm_disct(&md, &dpos, NFSX_FATTR(isnq), t1, TRUE, &cp2))
                return (error);
        fp = (struct nfsv2_fattr *)cp2;
        vtyp = nfstov_type(fp->fa_type);
        vmode = fxdr_unsigned(u_short, fp->fa_mode);
        if (vtyp == VNON || vtyp == VREG)
                vtyp = IFTOVT(vmode);
                return (error);
        fp = (struct nfsv2_fattr *)cp2;
        vtyp = nfstov_type(fp->fa_type);
        vmode = fxdr_unsigned(u_short, fp->fa_mode);
        if (vtyp == VNON || vtyp == VREG)
                vtyp = IFTOVT(vmode);
-       rdev = fxdr_unsigned(long, fp->fa_rdev);
-       fxdr_time(&fp->fa_mtime, &mtime);
+       if (isnq) {
+               rdev = fxdr_unsigned(long, fp->fa_nqrdev);
+               fxdr_nqtime(&fp->fa_nqmtime, &mtime);
+       } else {
+               rdev = fxdr_unsigned(long, fp->fa_nfsrdev);
+               fxdr_nfstime(&fp->fa_nfsmtime, &mtime);
+       }
        /*
         * If v_type == VNON it is a new node, so fill in the v_type,
         * n_mtime fields. Check to see if it represents a special 
        /*
         * If v_type == VNON it is a new node, so fill in the v_type,
         * n_mtime fields. Check to see if it represents a special 
@@ -706,8 +712,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
                                *vpp = vp = nvp;
                        }
                }
                                *vpp = vp = nvp;
                        }
                }
-               if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0)
-                       np->n_mtime = mtime.tv_sec;
+               np->n_mtime = mtime.ts_sec;
        }
        vap = &np->n_vattr;
        vap->va_type = vtyp;
        }
        vap = &np->n_vattr;
        vap->va_type = vtyp;
@@ -715,30 +720,42 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
        vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
        vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
        vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
        vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
        vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
        vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
-       vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
-       if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) {
+       vap->va_rdev = (dev_t)rdev;
+       vap->va_mtime = mtime;
+       vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
+       if (isnq) {
+               fxdr_hyper(&fp->fa_nqsize, &vap->va_size);
+               vap->va_blocksize = fxdr_unsigned(long, fp->fa_nqblocksize);
+               fxdr_hyper(&fp->fa_nqbytes, &vap->va_bytes);
+               vap->va_fileid = fxdr_unsigned(long, fp->fa_nqfileid);
+               fxdr_nqtime(&fp->fa_nqatime, &vap->va_atime);
+               vap->va_flags = fxdr_unsigned(u_long, fp->fa_nqflags);
+               fxdr_nqtime(&fp->fa_nqctime, &vap->va_ctime);
+               vap->va_gen = fxdr_unsigned(u_long, fp->fa_nqgen);
+               fxdr_hyper(&fp->fa_nqfilerev, &vap->va_filerev);
+       } else {
+               vap->va_size = fxdr_unsigned(u_long, fp->fa_nfssize);
+               vap->va_blocksize = fxdr_unsigned(long, fp->fa_nfsblocksize);
+               vap->va_bytes = fxdr_unsigned(long, fp->fa_nfsblocks) * NFS_FABLKSIZE;
+               vap->va_fileid = fxdr_unsigned(long, fp->fa_nfsfileid);
+               vap->va_atime.ts_sec = fxdr_unsigned(long, fp->fa_nfsatime.nfs_sec);
+               vap->va_atime.ts_nsec = 0;
+               vap->va_flags = fxdr_unsigned(u_long, fp->fa_nfsatime.nfs_usec);
+               vap->va_ctime.ts_sec = fxdr_unsigned(long, fp->fa_nfsctime.nfs_sec);
+               vap->va_ctime.ts_nsec = 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);
        }
                np->n_size = vap->va_size;
                vnode_pager_setsize(vp, (u_long)np->n_size);
        }
-       vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
-       vap->va_rdev = (dev_t)rdev;
-       vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE;
-       vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
-       vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid);
-       vap->va_atime.ts_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec);
-       vap->va_atime.ts_nsec = 0;
-       vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec);
-       vap->va_mtime.ts_sec = mtime.tv_sec;
-       vap->va_mtime.ts_nsec = mtime.tv_usec * 1000;
-       vap->va_ctime.ts_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec);
-       vap->va_ctime.ts_nsec = 0;
-       vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec);
        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));
-               if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size))
+               if (np->n_size > vap->va_size)
                        vaper->va_size = np->n_size;
                if (np->n_flag & NCHG) {
                        if (np->n_flag & NACC) {
                        vaper->va_size = np->n_size;
                if (np->n_flag & NCHG) {
                        if (np->n_flag & NACC) {
@@ -768,18 +785,18 @@ nfs_getattrcache(vp, vap)
        register struct nfsnode *np;
 
        np = VTONFS(vp);
        register struct nfsnode *np;
 
        np = VTONFS(vp);
-       if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
+       if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQLOOKLEASE) {
                if (!NQNFS_CKCACHABLE(vp, NQL_READ) || np->n_attrstamp == 0) {
                        nfsstats.attrcache_misses++;
                        return (ENOENT);
                }
                if (!NQNFS_CKCACHABLE(vp, NQL_READ) || np->n_attrstamp == 0) {
                        nfsstats.attrcache_misses++;
                        return (ENOENT);
                }
-       } else if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO) {
+       } else if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
                nfsstats.attrcache_misses++;
                return (ENOENT);
        }
        nfsstats.attrcache_hits++;
        bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
                nfsstats.attrcache_misses++;
                return (ENOENT);
        }
        nfsstats.attrcache_hits++;
        bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
-       if ((np->n_flag & NMODIFIED) == 0) {
+       if (vap->va_size > np->n_size) {
                np->n_size = vap->va_size;
                vnode_pager_setsize(vp, (u_long)np->n_size);
        } else if (np->n_size > vap->va_size)
                np->n_size = vap->va_size;
                vnode_pager_setsize(vp, (u_long)np->n_size);
        } else if (np->n_size > vap->va_size)
index 07aafb0..1b6cc84 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_vfsops.c        7.44 (Berkeley) %G%
+ *     @(#)nfs_vfsops.c        7.45 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -87,13 +87,14 @@ nfs_statfs(mp, sbp, p)
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos, cp2;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos, cp2;
-       int error = 0;
+       int error = 0, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct nfsmount *nmp;
        struct ucred *cred;
        struct nfsnode *np;
 
        nmp = VFSTONFS(mp);
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct nfsmount *nmp;
        struct ucred *cred;
        struct nfsnode *np;
 
        nmp = VFSTONFS(mp);
+       isnq = (nmp->nm_flag & NFSMNT_NQNFS);
        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
                return (error);
        vp = NFSTOV(np);
        if (error = nfs_nget(mp, &nmp->nm_fh, &np))
                return (error);
        vp = NFSTOV(np);
@@ -103,7 +104,7 @@ nfs_statfs(mp, sbp, p)
        nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
        nfsm_fhtom(vp);
        nfsm_request(vp, NFSPROC_STATFS, p, cred);
        nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
        nfsm_fhtom(vp);
        nfsm_request(vp, NFSPROC_STATFS, p, cred);
-       nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
+       nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
        sbp->f_type = MOUNT_NFS;
        sbp->f_flags = nmp->nm_flag;
        sbp->f_iosize = NFS_MAXDGRAMDATA;
        sbp->f_type = MOUNT_NFS;
        sbp->f_flags = nmp->nm_flag;
        sbp->f_iosize = NFS_MAXDGRAMDATA;
@@ -111,8 +112,13 @@ nfs_statfs(mp, sbp, p)
        sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
        sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
        sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
        sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
        sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
        sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
-       sbp->f_files = 0;
-       sbp->f_ffree = 0;
+       if (isnq) {
+               sbp->f_files = fxdr_unsigned(long, sfp->sf_files);
+               sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree);
+       } else {
+               sbp->f_files = 0;
+               sbp->f_ffree = 0;
+       }
        if (sbp != &mp->mnt_stat) {
                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
        if (sbp != &mp->mnt_stat) {
                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
index 16c94a4..9e6fab3 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfs_vnops.c 7.90 (Berkeley) %G%
+ *     @(#)nfs_vnops.c 7.91 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -195,6 +195,8 @@ struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
        { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
 #endif /* FIFO */
 
        { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
 #endif /* FIFO */
 
+void nqnfs_clientlease();
+
 /*
  * Global variables
  */
 /*
  * Global variables
  */
@@ -277,8 +279,10 @@ found:
 
 /*
  * nfs open vnode op
 
 /*
  * nfs open vnode op
- * Just check to see if the type is ok
+ * Check to see if the type is ok
  * and that deletion is not in progress.
  * and that deletion is not in progress.
+ * For paged in text files, you will need to flush the page cache
+ * if consistency is lost.
  */
 /* ARGSUSED */
 int
  */
 /* ARGSUSED */
 int
@@ -291,11 +295,54 @@ nfs_open(ap)
        } */ *ap;
 {
        register struct vnode *vp = ap->a_vp;
        } */ *ap;
 {
        register struct vnode *vp = ap->a_vp;
+       struct nfsnode *np = VTONFS(vp);
+       struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+       struct vattr vattr;
+       int error;
 
        if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
                return (EACCES);
 
        if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
                return (EACCES);
-       if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0)
-               VTONFS(vp)->n_attrstamp = 0; /* For Open/Close consistency */
+       if (vp->v_flag & VTEXT) {
+           /*
+            * Get a valid lease. If cached data is stale, flush it.
+            */
+           if (nmp->nm_flag & NFSMNT_NQNFS) {
+               if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
+                   do {
+                       error = nqnfs_getlease(vp, NQL_READ, ap->a_cred, ap->a_p);
+                   } while (error == NQNFS_EXPIRED);
+                   if (error)
+                       return (error);
+                   if (np->n_lrev != np->n_brev) {
+                       np->n_flag &= ~NMODIFIED;
+                       vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
+                       (void) vnode_pager_uncache(vp);
+                       np->n_brev = np->n_lrev;
+                   }
+               }
+           } else {
+               if (np->n_flag & NMODIFIED) {
+                       np->n_flag &= ~NMODIFIED;
+                       vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
+                       (void) vnode_pager_uncache(vp);
+                       np->n_attrstamp = 0;
+                       np->n_direofoffset = 0;
+                       if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p))
+                               return (error);
+                       np->n_mtime = vattr.va_mtime.ts_sec;
+               } else {
+                       if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p))
+                               return (error);
+                       if (np->n_mtime != vattr.va_mtime.ts_sec) {
+                               np->n_direofoffset = 0;
+                               vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
+                               (void) vnode_pager_uncache(vp);
+                               np->n_mtime = vattr.va_mtime.ts_sec;
+                       }
+               }
+           }
+       } else if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
+               np->n_attrstamp = 0; /* For Open/Close consistency */
        return (0);
 }
 
        return (0);
 }
 
@@ -394,7 +441,7 @@ nfs_setattr(ap)
        register long t1;
        caddr_t bpos, dpos, cp2;
        u_long *tl;
        register long t1;
        caddr_t bpos, dpos, cp2;
        u_long *tl;
-       int error = 0;
+       int error = 0, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        register struct vnode *vp = ap->a_vp;
        register struct nfsnode *np = VTONFS(vp);
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        register struct vnode *vp = ap->a_vp;
        register struct nfsnode *np = VTONFS(vp);
@@ -402,25 +449,34 @@ nfs_setattr(ap)
        u_quad_t frev;
 
        nfsstats.rpccnt[NFSPROC_SETATTR]++;
        u_quad_t frev;
 
        nfsstats.rpccnt[NFSPROC_SETATTR]++;
-       nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR);
+       isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS);
+       nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR(isnq));
        nfsm_fhtom(vp);
        nfsm_fhtom(vp);
-       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
-       if (vap->va_mode == 0xffff)
+       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));
+       if (vap->va_mode == (u_short)-1)
                sp->sa_mode = VNOVAL;
        else
                sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
                sp->sa_mode = VNOVAL;
        else
                sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
-       if (vap->va_uid == 0xffff)
+       if (vap->va_uid == (uid_t)-1)
                sp->sa_uid = VNOVAL;
        else
                sp->sa_uid = txdr_unsigned(vap->va_uid);
                sp->sa_uid = VNOVAL;
        else
                sp->sa_uid = txdr_unsigned(vap->va_uid);
-       if (vap->va_gid == 0xffff)
+       if (vap->va_gid == (gid_t)-1)
                sp->sa_gid = VNOVAL;
        else
                sp->sa_gid = txdr_unsigned(vap->va_gid);
                sp->sa_gid = VNOVAL;
        else
                sp->sa_gid = txdr_unsigned(vap->va_gid);
-       sp->sa_size = txdr_unsigned(vap->va_size);
-       sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.ts_sec);
-       sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
-       txdr_time(&vap->va_mtime, &sp->sa_mtime);
+       if (isnq) {
+               txdr_hyper(&vap->va_size, &sp->sa_nqsize);
+               txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);
+               txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);
+               sp->sa_nqflags = txdr_unsigned(vap->va_flags);
+               sp->sa_nqrdev = VNOVAL;
+       } else {
+               sp->sa_nfssize = txdr_unsigned(vap->va_size);
+               sp->sa_nfsatime.nfs_sec = txdr_unsigned(vap->va_atime.ts_sec);
+               sp->sa_nfsatime.nfs_usec = txdr_unsigned(vap->va_flags);
+               txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);
+       }
        if (vap->va_size != VNOVAL || vap->va_mtime.ts_sec != VNOVAL ||
            vap->va_atime.ts_sec != VNOVAL) {
                if (np->n_flag & NMODIFIED) {
        if (vap->va_size != VNOVAL || vap->va_mtime.ts_sec != VNOVAL ||
            vap->va_atime.ts_sec != VNOVAL) {
                if (np->n_flag & NMODIFIED) {
@@ -432,6 +488,8 @@ nfs_setattr(ap)
                                    vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
                        np->n_flag &= ~NMODIFIED;
                }
                                    vinvalbuf(vp, TRUE, ap->a_cred, ap->a_p);
                        np->n_flag &= ~NMODIFIED;
                }
+               if (vap->va_size != VNOVAL)
+                       np->n_size = np->n_vattr.va_size = vap->va_size;
        }
        nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred);
        nfsm_loadattr(vp, (struct vattr *)0);
        }
        nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred);
        nfsm_loadattr(vp, (struct vattr *)0);
@@ -506,7 +564,13 @@ nfs_lookup(ap)
                if (!error) {
                        if (vpid == vdp->v_id) {
                           if (nmp->nm_flag & NFSMNT_NQNFS) {
                if (!error) {
                        if (vpid == vdp->v_id) {
                           if (nmp->nm_flag & NFSMNT_NQNFS) {
-                               if (NQNFS_CKCACHABLE(dvp, NQL_READ)) {
+                               if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) == 0) {
+                                       nfsstats.lookupcache_hits++;
+                                       if (cnp->cn_nameiop != LOOKUP &&
+                                           (flags & ISLASTCN))
+                                           cnp->cn_flags |= SAVENAME;
+                                       return (0);
+                               } else if (NQNFS_CKCACHABLE(dvp, NQL_READ)) {
                                        if (np->n_lrev != np->n_brev ||
                                            (np->n_flag & NMODIFIED)) {
                                                np->n_direofoffset = 0;
                                        if (np->n_lrev != np->n_brev ||
                                            (np->n_flag & NMODIFIED)) {
                                                np->n_direofoffset = 0;
@@ -548,16 +612,13 @@ nfs_lookup(ap)
         * being looked up.
         */
        if (nmp->nm_flag & NFSMNT_NQNFS) {
         * being looked up.
         */
        if (nmp->nm_flag & NFSMNT_NQNFS) {
+               nfsm_build(tl, u_long *, NFSX_UNSIGNED);
                if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) &&
                    ((cnp->cn_flags & MAKEENTRY) &&
                if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) &&
                    ((cnp->cn_flags & MAKEENTRY) &&
-                   (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)))) {
-                       nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
-                       *tl++ = txdr_unsigned(NQL_READ);
+                   (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))))
                        *tl = txdr_unsigned(nmp->nm_leaseterm);
                        *tl = txdr_unsigned(nmp->nm_leaseterm);
-               } else {
-                       nfsm_build(tl, u_long *, NFSX_UNSIGNED);
+               else
                        *tl = 0;
                        *tl = 0;
-               }
        }
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
        }
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
@@ -633,44 +694,9 @@ nfsmout:
            (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
                if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
                        np->n_ctime = np->n_vattr.va_ctime.ts_sec;
            (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
                if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
                        np->n_ctime = np->n_vattr.va_ctime.ts_sec;
-               else if (nqlflag && reqtime > time.tv_sec) {
-                       if (np->n_tnext) {
-                               if (np->n_tnext == (struct nfsnode *)nmp)
-                                       nmp->nm_tprev = np->n_tprev;
-                               else
-                                       np->n_tnext->n_tprev = np->n_tprev;
-                               if (np->n_tprev == (struct nfsnode *)nmp)
-                                       nmp->nm_tnext = np->n_tnext;
-                               else
-                                       np->n_tprev->n_tnext = np->n_tnext;
-                               if (nqlflag == NQL_WRITE)
-                                       np->n_flag |= NQNFSWRITE;
-                       } else if (nqlflag == NQL_READ)
-                               np->n_flag &= ~NQNFSWRITE;
-                       else
-                               np->n_flag |= NQNFSWRITE;
-                       if (cachable)
-                               np->n_flag &= ~NQNFSNONCACHE;
-                       else
-                               np->n_flag |= NQNFSNONCACHE;
-                       np->n_expiry = reqtime;
-                       np->n_lrev = frev;
-                       tp = nmp->nm_tprev;
-                       while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry)
-                               tp = tp->n_tprev;
-                       if (tp == (struct nfsnode *)nmp) {
-                               np->n_tnext = nmp->nm_tnext;
-                               nmp->nm_tnext = np;
-                       } else {
-                               np->n_tnext = tp->n_tnext;
-                               tp->n_tnext = np;
-                       }
-                       np->n_tprev = tp;
-                       if (np->n_tnext == (struct nfsnode *)nmp)
-                               nmp->nm_tprev = np;
-                       else
-                               np->n_tnext->n_tprev = np;
-               }
+               else if (nqlflag && reqtime > time.tv_sec)
+                       nqnfs_clientlease(nmp, np, nqlflag, cachable, reqtime,
+                               frev);
                cache_enter(dvp, *vpp, cnp);
        }
        return (0);
                cache_enter(dvp, *vpp, cnp);
        }
        return (0);
@@ -763,15 +789,23 @@ nfs_readrpc(vp, uiop, cred)
 
        nmp = VFSTONFS(vp->v_mount);
        tsiz = uiop->uio_resid;
 
        nmp = VFSTONFS(vp->v_mount);
        tsiz = uiop->uio_resid;
+       if (uiop->uio_offset + tsiz > 0xffffffff &&
+           (nmp->nm_flag & NFSMNT_NQNFS) == 0)
+               return (EFBIG);
        while (tsiz > 0) {
                nfsstats.rpccnt[NFSPROC_READ]++;
                len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
                nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3);
                nfsm_fhtom(vp);
                nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);
        while (tsiz > 0) {
                nfsstats.rpccnt[NFSPROC_READ]++;
                len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
                nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3);
                nfsm_fhtom(vp);
                nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);
-               *tl++ = txdr_unsigned(uiop->uio_offset);
-               *tl++ = txdr_unsigned(len);
-               *tl = 0;
+               if (nmp->nm_flag & NFSMNT_NQNFS) {
+                       txdr_hyper(&uiop->uio_offset, tl);
+                       *(tl + 2) = txdr_unsigned(len);
+               } else {
+                       *tl++ = txdr_unsigned(uiop->uio_offset);
+                       *tl++ = txdr_unsigned(len);
+                       *tl = 0;
+               }
                nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred);
                nfsm_loadattr(vp, (struct vattr *)0);
                nfsm_strsiz(retlen, nmp->nm_rsize);
                nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred);
                nfsm_loadattr(vp, (struct vattr *)0);
                nfsm_strsiz(retlen, nmp->nm_rsize);
@@ -790,10 +824,11 @@ nfsmout:
  * nfs write call
  */
 int
  * nfs write call
  */
 int
-nfs_writerpc(vp, uiop, cred)
+nfs_writerpc(vp, uiop, cred, ioflags)
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
+       int ioflags;
 {
        register u_long *tl;
        register caddr_t cp;
 {
        register u_long *tl;
        register caddr_t cp;
@@ -808,15 +843,28 @@ nfs_writerpc(vp, uiop, cred)
 
        nmp = VFSTONFS(vp->v_mount);
        tsiz = uiop->uio_resid;
 
        nmp = VFSTONFS(vp->v_mount);
        tsiz = uiop->uio_resid;
+       if (uiop->uio_offset + tsiz > 0xffffffff &&
+           (nmp->nm_flag & NFSMNT_NQNFS) == 0)
+               return (EFBIG);
        while (tsiz > 0) {
                nfsstats.rpccnt[NFSPROC_WRITE]++;
                len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
                nfsm_reqhead(vp, NFSPROC_WRITE,
                        NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len));
                nfsm_fhtom(vp);
        while (tsiz > 0) {
                nfsstats.rpccnt[NFSPROC_WRITE]++;
                len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
                nfsm_reqhead(vp, NFSPROC_WRITE,
                        NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len));
                nfsm_fhtom(vp);
-               nfsm_build(tl, u_long *, NFSX_UNSIGNED*4);
-               *(tl+1) = txdr_unsigned(uiop->uio_offset);
-               *(tl+3) = txdr_unsigned(len);
+               nfsm_build(tl, u_long *, NFSX_UNSIGNED * 4);
+               if (nmp->nm_flag & NFSMNT_NQNFS) {
+                       txdr_hyper(&uiop->uio_offset, tl);
+                       tl += 2;
+                       if (ioflags & IO_APPEND)
+                               *tl++ = txdr_unsigned(1);
+                       else
+                               *tl++ = 0;
+               } else {
+                       *++tl = txdr_unsigned(uiop->uio_offset);
+                       tl += 2;
+               }
+               *tl = txdr_unsigned(len);
                nfsm_uiotom(uiop, len);
                nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred);
                nfsm_loadattr(vp, (struct vattr *)0);
                nfsm_uiotom(uiop, len);
                nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred);
                nfsm_loadattr(vp, (struct vattr *)0);
@@ -859,12 +907,15 @@ nfs_mknod(ap)
        register struct nfsv2_sattr *sp;
        register u_long *tl;
        register caddr_t cp;
        register struct nfsv2_sattr *sp;
        register u_long *tl;
        register caddr_t cp;
-       register long t2;
+       register long t1, t2;
+       struct vnode *newvp;
+       char *cp2;
        caddr_t bpos, dpos;
        caddr_t bpos, dpos;
-       int error = 0;
+       int error = 0, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        u_long rdev;
 
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        u_long rdev;
 
+       isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS);
        if (vap->va_type == VCHR || vap->va_type == VBLK)
                rdev = txdr_unsigned(vap->va_rdev);
 #ifdef FIFO
        if (vap->va_type == VCHR || vap->va_type == VBLK)
                rdev = txdr_unsigned(vap->va_rdev);
 #ifdef FIFO
@@ -878,19 +929,28 @@ nfs_mknod(ap)
        }
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        nfsm_reqhead(dvp, NFSPROC_CREATE,
        }
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        nfsm_reqhead(dvp, NFSPROC_CREATE,
-         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR);
+         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq));
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
+       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));
        sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
        sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
-       sp->sa_size = rdev;
-       /* or should these be VNOVAL ?? */
-       txdr_time(&vap->va_atime, &sp->sa_atime);
-       txdr_time(&vap->va_mtime, &sp->sa_mtime);
+       if (isnq) {
+               sp->sa_nqrdev = rdev;
+               sp->sa_nqflags = 0;
+               txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);
+               txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);
+       } else {
+               sp->sa_nfssize = rdev;
+               txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime);
+               txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);
+       }
        nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
        nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
+       nfsm_mtofh(dvp, newvp);
        nfsm_reqdone;
        nfsm_reqdone;
+       if (!error)
+               cache_enter(dvp, newvp, cnp);
        FREE(cnp->cn_pnbuf, M_NAMEI);
        VTONFS(dvp)->n_flag |= NMODIFIED;
        vrele(dvp);
        FREE(cnp->cn_pnbuf, M_NAMEI);
        VTONFS(dvp)->n_flag |= NMODIFIED;
        vrele(dvp);
@@ -917,25 +977,37 @@ nfs_create(ap)
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos, cp2;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos, cp2;
-       int error = 0;
+       int error = 0, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_CREATE]++;
+       isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS);
        nfsm_reqhead(dvp, NFSPROC_CREATE,
        nfsm_reqhead(dvp, NFSPROC_CREATE,
-         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR);
+         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq));
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
+       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));
        sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
        sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
-       sp->sa_size = txdr_unsigned(0);
-       /* or should these be VNOVAL ?? */
-       txdr_time(&vap->va_atime, &sp->sa_atime);
-       txdr_time(&vap->va_mtime, &sp->sa_mtime);
+       if (isnq) {
+               u_quad_t qval = 0;
+
+               txdr_hyper(&qval, &sp->sa_nqsize);
+               sp->sa_nqflags = 0;
+               sp->sa_nqrdev = -1;
+               txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);
+               txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);
+       } else {
+               sp->sa_nfssize = 0;
+               txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime);
+               txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);
+       }
        nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
        nfsm_mtofh(dvp, *ap->a_vpp);
        nfsm_reqdone;
        nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
        nfsm_mtofh(dvp, *ap->a_vpp);
        nfsm_reqdone;
+       if (!error)
+               cache_enter(dvp, *ap->a_vpp, cnp);
        FREE(cnp->cn_pnbuf, M_NAMEI);
        VTONFS(dvp)->n_flag |= NMODIFIED;
        vrele(dvp);
        FREE(cnp->cn_pnbuf, M_NAMEI);
        VTONFS(dvp)->n_flag |= NMODIFIED;
        vrele(dvp);
@@ -1212,23 +1284,33 @@ nfs_symlink(ap)
        register caddr_t cp;
        register long t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t2;
        caddr_t bpos, dpos;
-       int slen, error = 0;
+       int slen, error = 0, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_SYMLINK]++;
        slen = strlen(ap->a_target);
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_SYMLINK]++;
        slen = strlen(ap->a_target);
+       isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS);
        nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+
        nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+
-           nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR);
+           nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR(isnq));
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
        nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
        nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
-       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
+       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));
        sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
        sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
-       sp->sa_size = txdr_unsigned(VNOVAL);
-       txdr_time(&vap->va_atime, &sp->sa_atime);       /* or VNOVAL ?? */
-       txdr_time(&vap->va_mtime, &sp->sa_mtime);       /* or VNOVAL ?? */
+       if (isnq) {
+               quad_t qval = -1;
+
+               txdr_hyper(&qval, &sp->sa_nqsize);
+               sp->sa_nqflags = 0;
+               txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);
+               txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);
+       } else {
+               sp->sa_nfssize = -1;
+               txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime);
+               txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);
+       }
        nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
        nfsm_reqdone;
        FREE(cnp->cn_pnbuf, M_NAMEI);
        nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
        nfsm_reqdone;
        FREE(cnp->cn_pnbuf, M_NAMEI);
@@ -1264,22 +1346,32 @@ nfs_mkdir(ap)
        register long t1, t2;
        register int len;
        caddr_t bpos, dpos, cp2;
        register long t1, t2;
        register int len;
        caddr_t bpos, dpos, cp2;
-       int error = 0, firsttry = 1;
+       int error = 0, firsttry = 1, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        len = cnp->cn_namelen;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        len = cnp->cn_namelen;
+       isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS);
        nfsstats.rpccnt[NFSPROC_MKDIR]++;
        nfsm_reqhead(dvp, NFSPROC_MKDIR,
        nfsstats.rpccnt[NFSPROC_MKDIR]++;
        nfsm_reqhead(dvp, NFSPROC_MKDIR,
-         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR);
+         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR(isnq));
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
        nfsm_fhtom(dvp);
        nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
-       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
+       nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));
        sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
        sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
        sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
-       sp->sa_size = txdr_unsigned(VNOVAL);
-       txdr_time(&vap->va_atime, &sp->sa_atime);       /* or VNOVAL ?? */
-       txdr_time(&vap->va_mtime, &sp->sa_mtime);       /* or VNOVAL ?? */
+       if (isnq) {
+               quad_t qval = -1;
+
+               txdr_hyper(&qval, &sp->sa_nqsize);
+               sp->sa_nqflags = 0;
+               txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);
+               txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);
+       } else {
+               sp->sa_nfssize = -1;
+               txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime);
+               txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);
+       }
        nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
        nfsm_mtofh(dvp, *vpp);
        nfsm_reqdone;
        nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
        nfsm_mtofh(dvp, *vpp);
        nfsm_reqdone;
@@ -1433,7 +1525,7 @@ nfs_readdirrpc(vp, uiop, cred)
        caddr_t dpos2;
        int siz;
        int more_dirs = 1;
        caddr_t dpos2;
        int siz;
        int more_dirs = 1;
-       off_t off, savoff;
+       u_long off, savoff;
        struct dirent *savdp;
        struct nfsmount *nmp;
        struct nfsnode *np = VTONFS(vp);
        struct dirent *savdp;
        struct nfsmount *nmp;
        struct nfsnode *np = VTONFS(vp);
@@ -1449,10 +1541,11 @@ nfs_readdirrpc(vp, uiop, cred)
        while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
                nfsstats.rpccnt[NFSPROC_READDIR]++;
                nfsm_reqhead(vp, NFSPROC_READDIR,
        while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
                nfsstats.rpccnt[NFSPROC_READDIR]++;
                nfsm_reqhead(vp, NFSPROC_READDIR,
-                       NFSX_FH+2*NFSX_UNSIGNED);
+                       NFSX_FH + 2 * NFSX_UNSIGNED);
                nfsm_fhtom(vp);
                nfsm_fhtom(vp);
-               nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
-               *tl++ = txdr_unsigned(uiop->uio_offset);
+               nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
+               off = (u_long)uiop->uio_offset;
+               *tl++ = txdr_unsigned(off);
                *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
                        nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
                nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
                *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
                        nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
                nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
@@ -1465,14 +1558,13 @@ nfs_readdirrpc(vp, uiop, cred)
                md2 = md;
        
                /* loop thru the dir entries, doctoring them to 4bsd form */
                md2 = md;
        
                /* loop thru the dir entries, doctoring them to 4bsd form */
-               off = uiop->uio_offset;
 #ifdef lint
                dp = (struct dirent *)0;
 #endif /* lint */
                while (more_dirs && siz < uiop->uio_resid) {
                        savoff = off;           /* Hold onto offset and dp */
                        savdp = dp;
 #ifdef lint
                dp = (struct dirent *)0;
 #endif /* lint */
                while (more_dirs && siz < uiop->uio_resid) {
                        savoff = off;           /* Hold onto offset and dp */
                        savdp = dp;
-                       nfsm_dissecton(tl, u_long *, 2*NFSX_UNSIGNED);
+                       nfsm_dissecton(tl, u_long *, 2 * NFSX_UNSIGNED);
                        dp = (struct dirent *)tl;
                        dp->d_fileno = fxdr_unsigned(u_long, *tl++);
                        len = fxdr_unsigned(int, *tl);
                        dp = (struct dirent *)tl;
                        dp->d_fileno = fxdr_unsigned(u_long, *tl++);
                        len = fxdr_unsigned(int, *tl);
@@ -1494,11 +1586,11 @@ nfs_readdirrpc(vp, uiop, cred)
                                nfsm_adv(tlen - len);
                                len = tlen;
                        }
                                nfsm_adv(tlen - len);
                                len = tlen;
                        }
-                       nfsm_dissecton(tl, u_long *, 2*NFSX_UNSIGNED);
+                       nfsm_dissecton(tl, u_long *, 2 * NFSX_UNSIGNED);
                        off = fxdr_unsigned(u_long, *tl);
                        *tl++ = 0;      /* Ensures null termination of name */
                        more_dirs = fxdr_unsigned(int, *tl);
                        off = fxdr_unsigned(u_long, *tl);
                        *tl++ = 0;      /* Ensures null termination of name */
                        more_dirs = fxdr_unsigned(int, *tl);
-                       dp->d_reclen = len+4*NFSX_UNSIGNED;
+                       dp->d_reclen = len + 4 * NFSX_UNSIGNED;
                        siz += dp->d_reclen;
                }
                /*
                        siz += dp->d_reclen;
                }
                /*
@@ -1530,7 +1622,7 @@ nfs_readdirrpc(vp, uiop, cred)
                        md = md2;
                        dpos = dpos2;
                        nfsm_mtouio(uiop, siz);
                        md = md2;
                        dpos = dpos2;
                        nfsm_mtouio(uiop, siz);
-                       uiop->uio_offset = off;
+                       uiop->uio_offset = (off_t)off;
                } else
                        more_dirs = 0;  /* Ugh, never happens, but in case.. */
                m_freem(mrep);
                } else
                        more_dirs = 0;  /* Ugh, never happens, but in case.. */
                m_freem(mrep);
@@ -1555,8 +1647,7 @@ nfsmout:
 }
 
 /*
 }
 
 /*
- * Nqnfs readdir_and_lookup RPC. Used in place of nfs_readdirrpc() when
- * the "rdirlook" mount option is specified.
+ * Nqnfs readdir_and_lookup RPC. Used in place of nfs_readdirrpc().
  */
 int
 nfs_readdirlookrpc(vp, uiop, cred)
  */
 int
 nfs_readdirlookrpc(vp, uiop, cred)
@@ -1573,13 +1664,12 @@ nfs_readdirlookrpc(vp, uiop, cred)
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct nameidata nami, *ndp = &nami;
        struct componentname *cnp = &ndp->ni_cnd;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct nameidata nami, *ndp = &nami;
        struct componentname *cnp = &ndp->ni_cnd;
-       off_t off, endoff;
+       u_long off, endoff, fileno;
        time_t reqtime, ltime;
        struct nfsmount *nmp;
        struct nfsnode *np, *tp;
        struct vnode *newvp;
        nfsv2fh_t *fhp;
        time_t reqtime, ltime;
        struct nfsmount *nmp;
        struct nfsnode *np, *tp;
        struct vnode *newvp;
        nfsv2fh_t *fhp;
-       u_long fileno;
        u_quad_t frev;
        int error = 0, tlen, more_dirs = 1, tresid, doit, bigenough, i;
        int cachable;
        u_quad_t frev;
        int error = 0, tlen, more_dirs = 1, tresid, doit, bigenough, i;
        int cachable;
@@ -1598,27 +1688,32 @@ nfs_readdirlookrpc(vp, uiop, cred)
        while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
                nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]++;
                nfsm_reqhead(vp, NQNFSPROC_READDIRLOOK,
        while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
                nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]++;
                nfsm_reqhead(vp, NQNFSPROC_READDIRLOOK,
-                       NFSX_FH+3*NFSX_UNSIGNED);
+                       NFSX_FH + 3 * NFSX_UNSIGNED);
                nfsm_fhtom(vp);
                nfsm_fhtom(vp);
-               nfsm_build(tl, u_long *, 3*NFSX_UNSIGNED);
-               *tl++ = txdr_unsigned(uiop->uio_offset);
+               nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
+               off = (u_long)uiop->uio_offset;
+               *tl++ = txdr_unsigned(off);
                *tl++ = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
                        nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
                *tl++ = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
                        nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
-               *tl = txdr_unsigned(nmp->nm_leaseterm);
+               if (nmp->nm_flag & NFSMNT_NQLOOKLEASE)
+                       *tl = txdr_unsigned(nmp->nm_leaseterm);
+               else
+                       *tl = 0;
                reqtime = time.tv_sec;
                nfsm_request(vp, NQNFSPROC_READDIRLOOK, uiop->uio_procp, cred);
                nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
                more_dirs = fxdr_unsigned(int, *tl);
        
                /* loop thru the dir entries, doctoring them to 4bsd form */
                reqtime = time.tv_sec;
                nfsm_request(vp, NQNFSPROC_READDIRLOOK, uiop->uio_procp, cred);
                nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
                more_dirs = fxdr_unsigned(int, *tl);
        
                /* loop thru the dir entries, doctoring them to 4bsd form */
-               off = uiop->uio_offset;
                bigenough = 1;
                while (more_dirs && bigenough) {
                        doit = 1;
                bigenough = 1;
                while (more_dirs && bigenough) {
                        doit = 1;
-                       nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
-                       cachable = fxdr_unsigned(int, *tl++);
-                       ltime = reqtime + fxdr_unsigned(int, *tl++);
-                       fxdr_hyper(tl, &frev);
+                       nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
+                       if (nmp->nm_flag & NFSMNT_NQLOOKLEASE) {
+                               cachable = fxdr_unsigned(int, *tl++);
+                               ltime = reqtime + fxdr_unsigned(int, *tl++);
+                               fxdr_hyper(tl, &frev);
+                       }
                        nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH);
                        if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
                                VREF(vp);
                        nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH);
                        if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
                                VREF(vp);
@@ -1632,7 +1727,7 @@ nfs_readdirlookrpc(vp, uiop, cred)
                        if (error = nfs_loadattrcache(&newvp, &md, &dpos,
                                (struct vattr *)0))
                                doit = 0;
                        if (error = nfs_loadattrcache(&newvp, &md, &dpos,
                                (struct vattr *)0))
                                doit = 0;
-                       nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
+                       nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
                        fileno = fxdr_unsigned(u_long, *tl++);
                        len = fxdr_unsigned(int, *tl);
                        if (len <= 0 || len > NFS_MAXNAMLEN) {
                        fileno = fxdr_unsigned(u_long, *tl++);
                        len = fxdr_unsigned(int, *tl);
                        if (len <= 0 || len > NFS_MAXNAMLEN) {
@@ -1667,41 +1762,11 @@ nfs_readdirlookrpc(vp, uiop, cred)
                                cnp->cn_hash = 0;
                                for (cp = cnp->cn_nameptr, i = 1; i <= len; i++, cp++)
                                        cnp->cn_hash += (unsigned char)*cp * i;
                                cnp->cn_hash = 0;
                                for (cp = cnp->cn_nameptr, i = 1; i <= len; i++, cp++)
                                        cnp->cn_hash += (unsigned char)*cp * i;
-                               if (ltime > time.tv_sec) {
-                                       if (np->n_tnext) {
-                                               if (np->n_tnext == (struct nfsnode *)nmp)
-                                                       nmp->nm_tprev = np->n_tprev;
-                                               else
-                                                       np->n_tnext->n_tprev = np->n_tprev;
-                                               if (np->n_tprev == (struct nfsnode *)nmp)
-                                                       nmp->nm_tnext = np->n_tnext;
-                                               else
-                                                       np->n_tprev->n_tnext = np->n_tnext;
-                                       } else
-                                               np->n_flag &= ~NQNFSWRITE;
-                                       if (cachable)
-                                               np->n_flag &= ~NQNFSNONCACHE;
-                                       else
-                                               np->n_flag |= NQNFSNONCACHE;
-                                       np->n_expiry = ltime;
-                                       np->n_lrev = frev;
-                                       tp = nmp->nm_tprev;
-                                       while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry)
-                                               tp = tp->n_tprev;
-                                       if (tp == (struct nfsnode *)nmp) {
-                                               np->n_tnext = nmp->nm_tnext;
-                                               nmp->nm_tnext = np;
-                                       } else {
-                                               np->n_tnext = tp->n_tnext;
-                                               tp->n_tnext = np;
-                                       }
-                                       np->n_tprev = tp;
-                                       if (np->n_tnext == (struct nfsnode *)nmp)
-                                               nmp->nm_tprev = np;
-                                       else
-                                               np->n_tnext->n_tprev = np;
-                                       cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
-                               }
+                               if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) &&
+                                       ltime > time.tv_sec)
+                                       nqnfs_clientlease(nmp, np, NQL_READ,
+                                               cachable, ltime, frev);
+                               cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
                        } else {
                                nfsm_adv(nfsm_rndup(len));
                        }
                        } else {
                                nfsm_adv(nfsm_rndup(len));
                        }
@@ -1709,11 +1774,11 @@ nfs_readdirlookrpc(vp, uiop, cred)
                                vrele(newvp);
                                newvp = NULLVP;
                        }
                                vrele(newvp);
                                newvp = NULLVP;
                        }
-                       nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
+                       nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
                        if (bigenough)
                        if (bigenough)
-                               endoff = off = fxdr_unsigned(off_t, *tl++);
+                               endoff = off = fxdr_unsigned(u_long, *tl++);
                        else
                        else
-                               endoff = fxdr_unsigned(off_t, *tl++);
+                               endoff = fxdr_unsigned(u_long, *tl++);
                        more_dirs = fxdr_unsigned(int, *tl);
                }
                /*
                        more_dirs = fxdr_unsigned(int, *tl);
                }
                /*
@@ -1730,7 +1795,7 @@ nfs_readdirlookrpc(vp, uiop, cred)
                                VTONFS(vp)->n_direofoffset = endoff;
                }
                if (uiop->uio_resid < tresid)
                                VTONFS(vp)->n_direofoffset = endoff;
                }
                if (uiop->uio_resid < tresid)
-                       uiop->uio_offset = off;
+                       uiop->uio_offset = (off_t)off;
                else
                        more_dirs = 0;
                m_freem(mrep);
                else
                        more_dirs = 0;
                m_freem(mrep);
@@ -1834,17 +1899,24 @@ nfs_lookitup(sp, fhp, procp)
        register long t1, t2;
        caddr_t bpos, dpos, cp2;
        u_long xid;
        register long t1, t2;
        caddr_t bpos, dpos, cp2;
        u_long xid;
-       int error = 0;
+       int error = 0, isnq;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        long len;
 
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        long len;
 
+       isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS);
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
        len = sp->s_namlen;
        nfsm_reqhead(vp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
        len = sp->s_namlen;
        nfsm_reqhead(vp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
+       if (isnq) {
+               nfsm_build(tl, u_long *, NFSX_UNSIGNED);
+               *tl = 0;
+       }
        nfsm_fhtom(vp);
        nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN);
        nfsm_request(vp, NFSPROC_LOOKUP, procp, sp->s_cred);
        if (fhp != NULL) {
        nfsm_fhtom(vp);
        nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN);
        nfsm_request(vp, NFSPROC_LOOKUP, procp, sp->s_cred);
        if (fhp != NULL) {
+               if (isnq)
+                       nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
                nfsm_dissect(cp, caddr_t, NFSX_FH);
                bcopy(cp, (caddr_t)fhp, NFSX_FH);
        }
                nfsm_dissect(cp, caddr_t, NFSX_FH);
                bcopy(cp, (caddr_t)fhp, NFSX_FH);
        }
@@ -1994,7 +2066,7 @@ nfs_doio(bp)
                } else {
                        uiop->uio_rw = UIO_WRITE;
                        nfsstats.write_physios++;
                } else {
                        uiop->uio_rw = UIO_WRITE;
                        nfsstats.write_physios++;
-                       bp->b_error = error = nfs_writerpc(vp, uiop, cr);
+                       bp->b_error = error = nfs_writerpc(vp, uiop, cr, 0);
                }
 
                /*
                }
 
                /*
@@ -2020,7 +2092,7 @@ nfs_doio(bp)
                        case VDIR:
                                uiop->uio_offset = bp->b_lblkno;
                                nfsstats.readdir_bios++;
                        case VDIR:
                                uiop->uio_offset = bp->b_lblkno;
                                nfsstats.readdir_bios++;
-                               if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_RDIRALOOK)
+                               if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS)
                                    error = nfs_readdirlookrpc(vp, uiop, bp->b_rcred);
                                else
                                    error = nfs_readdirrpc(vp, uiop, bp->b_rcred);
                                    error = nfs_readdirlookrpc(vp, uiop, bp->b_rcred);
                                else
                                    error = nfs_readdirrpc(vp, uiop, bp->b_rcred);
@@ -2040,7 +2112,7 @@ nfs_doio(bp)
                        uiop->uio_rw = UIO_WRITE;
                        nfsstats.write_bios++;
                        bp->b_error = error = nfs_writerpc(vp, uiop,
                        uiop->uio_rw = UIO_WRITE;
                        nfsstats.write_bios++;
                        bp->b_error = error = nfs_writerpc(vp, uiop,
-                               bp->b_wcred);
+                               bp->b_wcred, 0);
                        if (error) {
                                np->n_error = error;
                                np->n_flag |= NWRITEERR;
                        if (error) {
                                np->n_error = error;
                                np->n_flag |= NWRITEERR;
index 1937521..13e0e98 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfsm_subs.h 7.13 (Berkeley) %G%
+ *     @(#)nfsm_subs.h 7.14 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -221,18 +221,36 @@ extern struct mbuf *nfsm_reqh();
        fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
        fp->fa_uid = txdr_unsigned(vap->va_uid); \
        fp->fa_gid = txdr_unsigned(vap->va_gid); \
        fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
        fp->fa_uid = txdr_unsigned(vap->va_uid); \
        fp->fa_gid = txdr_unsigned(vap->va_gid); \
-       fp->fa_size = txdr_unsigned(vap->va_size); \
-       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize); \
-       if (vap->va_type == VFIFO) \
-               fp->fa_rdev = 0xffffffff; \
-       else \
-               fp->fa_rdev = txdr_unsigned(vap->va_rdev); \
-       fp->fa_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
-       fp->fa_fsid = txdr_unsigned(vap->va_fsid); \
-       fp->fa_fileid = txdr_unsigned(vap->va_fileid); \
-       fp->fa_atime.tv_sec = txdr_unsigned(vap->va_atime.ts_sec); \
-       fp->fa_atime.tv_usec = txdr_unsigned(vap->va_flags); \
-       txdr_time(&vap->va_mtime, &fp->fa_mtime); \
-       fp->fa_ctime.tv_sec = txdr_unsigned(vap->va_ctime.ts_sec); \
-       fp->fa_ctime.tv_usec = txdr_unsigned(vap->va_gen)
+       if (nfsd->nd_nqlflag == NQL_NOVAL) { \
+               fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
+               if (vap->va_type == VFIFO) \
+                       fp->fa_nfsrdev = 0xffffffff; \
+               else \
+                       fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
+               fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
+               fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
+               fp->fa_nfssize = txdr_unsigned(vap->va_size); \
+               fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
+               fp->fa_nfsatime.nfs_sec = txdr_unsigned(vap->va_atime.ts_sec); \
+               fp->fa_nfsatime.nfs_usec = txdr_unsigned(vap->va_flags); \
+               txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
+               fp->fa_nfsctime.nfs_sec = txdr_unsigned(vap->va_ctime.ts_sec); \
+               fp->fa_nfsctime.nfs_usec = txdr_unsigned(vap->va_gen); \
+       } else { \
+               fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
+               if (vap->va_type == VFIFO) \
+                       fp->fa_nqrdev = 0xffffffff; \
+               else \
+                       fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
+               fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
+               fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
+               txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
+               txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
+               txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
+               txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
+               txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
+               fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
+               fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
+               txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
+       }
 
 
index 31229b7..1e86470 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nfsnode.h   7.28 (Berkeley) %G%
+ *     @(#)nfsnode.h   7.29 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -41,34 +41,20 @@ struct nfsnode {
        off_t   n_size;                 /* Current size of file */
        int     n_error;                /* Save write error value */
        u_long  n_direofoffset;         /* Dir. EOF offset cache */
        off_t   n_size;                 /* Current size of file */
        int     n_error;                /* Save write error value */
        u_long  n_direofoffset;         /* Dir. EOF offset cache */
-       union {
-               struct {
-                       time_t  un_mtime; /* Prev modify time. */
-                       time_t  un_ctime; /* Prev create time. */
-               } un_nfs;
-               struct {
-                       u_quad_t un_brev; /* Modify rev when cached */
-                       u_quad_t un_lrev; /* Modify rev for lease */
-                       time_t  un_expiry; /* Lease expiry time */
-                       struct  nfsnode *un_tnext; /* Nqnfs timer chain */
-                       struct  nfsnode *un_tprev;
-                       long    un_spare; /* pad to 8-byte boundary */
-               } un_nqnfs;
-       } n_un;
+       time_t  n_mtime;                 /* Prev modify time. */
+       time_t  n_ctime;                 /* Prev create time. */
+       u_quad_t n_brev;                 /* Modify rev when cached */
+       u_quad_t n_lrev;                 /* Modify rev for lease */
+       time_t  n_expiry;                /* Lease expiry time */
+       struct  nfsnode *n_tnext;        /* Nqnfs timer chain */
+       struct  nfsnode *n_tprev;               
+       long    spare1;                 /* To 8 byte boundary */
        struct  sillyrename n_silly;    /* Silly rename struct */
        struct  timeval n_atim;         /* Special file times */
        struct  timeval n_mtim;
        struct  sillyrename n_silly;    /* Silly rename struct */
        struct  timeval n_atim;         /* Special file times */
        struct  timeval n_mtim;
-       long    n_spare[4];             /* Up to a power of 2 */
+       long    n_spare[2];             /* Up to a power of 2 */
 };
 
 };
 
-#define        n_mtime         n_un.un_nfs.un_mtime
-#define        n_ctime         n_un.un_nfs.un_ctime
-#define        n_brev          n_un.un_nqnfs.un_brev
-#define        n_lrev          n_un.un_nqnfs.un_lrev
-#define        n_expiry        n_un.un_nqnfs.un_expiry
-#define        n_tnext         n_un.un_nqnfs.un_tnext
-#define        n_tprev         n_un.un_nqnfs.un_tprev
-
 /*
  * Flags for n_flag
  */
 /*
  * Flags for n_flag
  */
index 965efa8..e17bcad 100644 (file)
 /* Sizes in bytes of various nfs rpc components */
 #define        NFSX_FH         32
 #define        NFSX_UNSIGNED   4
 /* Sizes in bytes of various nfs rpc components */
 #define        NFSX_FH         32
 #define        NFSX_UNSIGNED   4
-#define        NFSX_FATTR      68
-#define        NFSX_SATTR      32
+#define        NFSX_NFSFATTR   68
+#define        NFSX_NQFATTR    92
+#define        NFSX_NFSSATTR   32
+#define        NFSX_NQSATTR    44
 #define        NFSX_COOKIE     4
 #define        NFSX_COOKIE     4
-#define NFSX_STATFS    20
+#define NFSX_NFSSTATFS 20
+#define        NFSX_NQSTATFS   28
+#define        NFSX_FATTR(isnq)        ((isnq) ? NFSX_NQFATTR : NFSX_NFSFATTR)
+#define        NFSX_SATTR(isnq)        ((isnq) ? NFSX_NQSATTR : NFSX_NFSSATTR)
+#define        NFSX_STATFS(isnq)       ((isnq) ? NFSX_NQSTATFS : NFSX_NFSSTATFS)
 
 /* nfs rpc procedure numbers */
 #define        NFSPROC_NULL            0
 
 /* nfs rpc procedure numbers */
 #define        NFSPROC_NULL            0
@@ -102,40 +108,126 @@ typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 } nfstype;
 
 /* Structs for common parts of the rpc's */
 struct nfsv2_time {
 
 /* Structs for common parts of the rpc's */
 struct nfsv2_time {
-       u_long  tv_sec;
-       u_long  tv_usec;
+       u_long  nfs_sec;
+       u_long  nfs_usec;
 };
 
 };
 
+struct nqnfs_time {
+       u_long  nq_sec;
+       u_long  nq_nsec;
+};
+
+/*
+ * File attributes and setable attributes. These structures cover both
+ * NFS version 2 and the NQNFS protocol. Note that the union is only
+ * used to that one pointer can refer to both variants. These structures
+ * go out on the wire and must be densely packed, so no quad data types
+ * are used. (all fields are longs or u_longs or structures of same)
+ * NB: You can't do sizeof(struct nfsv2_fattr), you must use the
+ *     NFSX_FATTR(isnq) macro.
+ */
 struct nfsv2_fattr {
        u_long  fa_type;
        u_long  fa_mode;
        u_long  fa_nlink;
        u_long  fa_uid;
        u_long  fa_gid;
 struct nfsv2_fattr {
        u_long  fa_type;
        u_long  fa_mode;
        u_long  fa_nlink;
        u_long  fa_uid;
        u_long  fa_gid;
-       u_long  fa_size;
-       u_long  fa_blocksize;
-       u_long  fa_rdev;
-       u_long  fa_blocks;
-       u_long  fa_fsid;
-       u_long  fa_fileid;
-       struct nfsv2_time fa_atime;
-       struct nfsv2_time fa_mtime;
-       struct nfsv2_time fa_ctime;
+       union {
+               struct {
+                       u_long  nfsfa_size;
+                       u_long  nfsfa_blocksize;
+                       u_long  nfsfa_rdev;
+                       u_long  nfsfa_blocks;
+                       u_long  nfsfa_fsid;
+                       u_long  nfsfa_fileid;
+                       struct nfsv2_time nfsfa_atime;
+                       struct nfsv2_time nfsfa_mtime;
+                       struct nfsv2_time nfsfa_ctime;
+               } fa_nfsv2;
+               struct {
+                       struct {
+                               u_long  nqfa_qsize[2];
+                       } nqfa_size;
+                       u_long  nqfa_blocksize;
+                       u_long  nqfa_rdev;
+                       struct {
+                               u_long  nqfa_qbytes[2];
+                       } nqfa_bytes;
+                       u_long  nqfa_fsid;
+                       u_long  nqfa_fileid;
+                       struct nqnfs_time nqfa_atime;
+                       struct nqnfs_time nqfa_mtime;
+                       struct nqnfs_time nqfa_ctime;
+                       u_long  nqfa_flags;
+                       u_long  nqfa_gen;
+                       struct {
+                               u_long  nqfa_qfilerev[2];
+                       } nqfa_filerev;
+               } fa_nqnfs;
+       } fa_un;
 };
 
 };
 
+/* and some ugly defines for accessing union components */
+#define        fa_nfssize              fa_un.fa_nfsv2.nfsfa_size
+#define        fa_nfsblocksize         fa_un.fa_nfsv2.nfsfa_blocksize
+#define        fa_nfsrdev              fa_un.fa_nfsv2.nfsfa_rdev
+#define        fa_nfsblocks            fa_un.fa_nfsv2.nfsfa_blocks
+#define        fa_nfsfsid              fa_un.fa_nfsv2.nfsfa_fsid
+#define        fa_nfsfileid            fa_un.fa_nfsv2.nfsfa_fileid
+#define        fa_nfsatime             fa_un.fa_nfsv2.nfsfa_atime
+#define        fa_nfsmtime             fa_un.fa_nfsv2.nfsfa_mtime
+#define        fa_nfsctime             fa_un.fa_nfsv2.nfsfa_ctime
+#define        fa_nqsize               fa_un.fa_nqnfs.nqfa_size
+#define        fa_nqblocksize          fa_un.fa_nqnfs.nqfa_blocksize
+#define        fa_nqrdev               fa_un.fa_nqnfs.nqfa_rdev
+#define        fa_nqbytes              fa_un.fa_nqnfs.nqfa_bytes
+#define        fa_nqfsid               fa_un.fa_nqnfs.nqfa_fsid
+#define        fa_nqfileid             fa_un.fa_nqnfs.nqfa_fileid
+#define        fa_nqatime              fa_un.fa_nqnfs.nqfa_atime
+#define        fa_nqmtime              fa_un.fa_nqnfs.nqfa_mtime
+#define        fa_nqctime              fa_un.fa_nqnfs.nqfa_ctime
+#define        fa_nqflags              fa_un.fa_nqnfs.nqfa_flags
+#define        fa_nqgen                fa_un.fa_nqnfs.nqfa_gen
+#define        fa_nqfilerev            fa_un.fa_nqnfs.nqfa_filerev
+
 struct nfsv2_sattr {
        u_long  sa_mode;
        u_long  sa_uid;
        u_long  sa_gid;
 struct nfsv2_sattr {
        u_long  sa_mode;
        u_long  sa_uid;
        u_long  sa_gid;
-       u_long  sa_size;
-       struct nfsv2_time sa_atime;
-       struct nfsv2_time sa_mtime;
+       union {
+               struct {
+                       u_long  nfssa_size;
+                       struct nfsv2_time nfssa_atime;
+                       struct nfsv2_time nfssa_mtime;
+               } sa_nfsv2;
+               struct {
+                       struct {
+                               u_long  nqsa_qsize[2];
+                       } nqsa_size;
+                       struct nqnfs_time nqsa_atime;
+                       struct nqnfs_time nqsa_mtime;
+                       u_long  nqsa_flags;
+                       u_long  nqsa_rdev;
+               } sa_nqnfs;
+       } sa_un;
 };
 
 };
 
+/* and some ugly defines for accessing the unions */
+#define        sa_nfssize              sa_un.sa_nfsv2.nfssa_size
+#define        sa_nfsatime             sa_un.sa_nfsv2.nfssa_atime
+#define        sa_nfsmtime             sa_un.sa_nfsv2.nfssa_mtime
+#define        sa_nqsize               sa_un.sa_nqnfs.nqsa_size
+#define        sa_nqatime              sa_un.sa_nqnfs.nqsa_atime
+#define        sa_nqmtime              sa_un.sa_nqnfs.nqsa_mtime
+#define        sa_nqflags              sa_un.sa_nqnfs.nqsa_flags
+#define        sa_nqrdev               sa_un.sa_nqnfs.nqsa_rdev
+
 struct nfsv2_statfs {
        u_long  sf_tsize;
        u_long  sf_bsize;
        u_long  sf_blocks;
        u_long  sf_bfree;
        u_long  sf_bavail;
 struct nfsv2_statfs {
        u_long  sf_tsize;
        u_long  sf_bsize;
        u_long  sf_blocks;
        u_long  sf_bfree;
        u_long  sf_bavail;
+       u_long  sf_files;       /* Nqnfs only */
+       u_long  sf_ffree;       /* ditto      */
 };
 };
index ba65f50..a580f12 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)nqnfs.h     7.4 (Berkeley) %G%
+ *     @(#)nqnfs.h     7.5 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -17,9 +17,9 @@
 /* Tunable constants */
 #define        NQ_CLOCKSKEW    3       /* Clock skew factor (sec) */
 #define        NQ_WRITESLACK   5       /* Delay for write cache flushing */
 /* Tunable constants */
 #define        NQ_CLOCKSKEW    3       /* Clock skew factor (sec) */
 #define        NQ_WRITESLACK   5       /* Delay for write cache flushing */
-#define        NQ_MAXLEASE     30      /* Max lease duration (sec) */
-#define        NQ_MINLEASE     2       /* Min lease duration (sec) */
-#define        NQ_DEFLEASE     10      /* Default lease duration (sec) */
+#define        NQ_MAXLEASE     60      /* Max lease duration (sec) */
+#define        NQ_MINLEASE     5       /* Min lease duration (sec) */
+#define        NQ_DEFLEASE     30      /* Default lease duration (sec) */
 #define        NQ_RENEWAL      3       /* Time before expiry (sec) to renew */
 #define        NQ_TRYLATERDEL  15      /* Initial try later delay (sec) */
 #define        NQ_MAXNUMLEASE  2048    /* Upper bound on number of server leases */
 #define        NQ_RENEWAL      3       /* Time before expiry (sec) to renew */
 #define        NQ_TRYLATERDEL  15      /* Initial try later delay (sec) */
 #define        NQ_MAXNUMLEASE  2048    /* Upper bound on number of server leases */
index bcf0516..375a570 100644 (file)
@@ -7,7 +7,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)xdr_subs.h  7.4 (Berkeley) %G%
+ *     @(#)xdr_subs.h  7.5 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
  */
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define fxdr_unsigned(t, v)    ((t)ntohl((long)(v)))
  */
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define fxdr_unsigned(t, v)    ((t)ntohl((long)(v)))
-#define        fxdr_time(f, t) { \
-       ((struct timeval *)(t))->tv_sec = \
-               ntohl(((struct timeval *)(f))->tv_sec); \
-       ((struct timeval *)(t))->tv_usec = \
-               ntohl(((struct timeval *)(f))->tv_usec); \
+#define        fxdr_nfstime(f, t) { \
+       (t)->ts_sec = \
+               ntohl(((struct nfsv2_time *)(f))->nfs_sec); \
+       (t)->ts_nsec = 1000 * \
+               ntohl(((struct nfsv2_time *)(f))->nfs_usec); \
+}
+
+#define        fxdr_nqtime(f, t) { \
+       (t)->ts_sec = \
+               ntohl(((struct nqnfs_time *)(f))->nq_sec); \
+       (t)->ts_nsec = \
+               ntohl(((struct nqnfs_time *)(f))->nq_nsec); \
 }
 
 /*
 }
 
 /*
@@ -44,22 +51,36 @@ union _hq {
 }
 
 #define        txdr_unsigned(v)        (htonl((long)(v)))
 }
 
 #define        txdr_unsigned(v)        (htonl((long)(v)))
-#define        txdr_time(f, t) { \
-       ((struct timeval *)(t))->tv_sec = \
-               htonl(((struct timeval *)(f))->tv_sec); \
-       ((struct timeval *)(t))->tv_usec = \
-               htonl(((struct timeval *)(f))->tv_usec); \
+#define        txdr_nqtime(f, t) { \
+       ((struct nqnfs_time *)(t))->nq_sec = \
+               htonl((f)->ts_sec); \
+       ((struct nqnfs_time *)(t))->nq_nsec = \
+               htonl((f)->ts_nsec); \
+}
+#define        txdr_nfstime(f, t) { \
+       ((struct nfsv2_time *)(t))->nfs_sec = \
+               htonl((f)->ts_sec); \
+       ((struct nfsv2_time *)(t))->nfs_usec = \
+               htonl((f)->ts_nsec) / 1000; \
 }
 #else  /* BIG_ENDIAN */
 #define fxdr_unsigned(t, v)    ((t)(v))
 }
 #else  /* BIG_ENDIAN */
 #define fxdr_unsigned(t, v)    ((t)(v))
-#define        fxdr_time(f, t) \
-       *((struct timeval *)(t)) = *((struct timeval *)(f))
+#define        fxdr_nqtime(f, t) \
+       *(t) = *((struct timespec *)(f))
+#define        fxdr_nfstime(f, t) { \
+       (t)->ts_sec = ((struct nfsv2_time *)(f))->nfs_sec; \
+       (t)->ts_nsec = ((struct nfsv2_time *)(f))->nfs_usec * 1000; \
+}
 #define        fxdr_hyper(f, t) \
        *((quad_t *)(t)) = *((quad_t *)(f))
 
 #define        txdr_unsigned(v)        ((long)(v))
 #define        fxdr_hyper(f, t) \
        *((quad_t *)(t)) = *((quad_t *)(f))
 
 #define        txdr_unsigned(v)        ((long)(v))
-#define        txdr_time(f, t) \
-       *((struct timeval *)(t)) = *((struct timeval *)(f))
+#define        txdr_nqtime(f, t) \
+       *(t) = *((struct timespec *)(f))
+#define        txdr_nfstime(f, t) { \
+       ((struct nfsv2_time *)(t))->nfs_sec = (f)->ts_sec; \
+       ((struct nfsv2_time *)(t))->nfs_usec = (f)->ts_nsec / 1000; \
+}
 #define        txdr_hyper(f, t) \
        *((quad_t *)(t)) = *((quad_t *)(f))
 #endif /* ENDIAN */
 #define        txdr_hyper(f, t) \
        *((quad_t *)(t)) = *((quad_t *)(f))
 #endif /* ENDIAN */