BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / nfs / nfs_vnops.c
index 11f2c9a..3e55e48 100644 (file)
@@ -5,47 +5,60 @@
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
- * Redistribution is only permitted until one year after the first shipment
- * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
- * binary forms are permitted provided that: (1) source distributions retain
- * this entire copyright notice and comment, and (2) distributions including
- * binaries display the following acknowledgement:  This product includes
- * software developed by the University of California, Berkeley and its
- * contributors'' in the documentation or other materials provided with the
- * distribution and in all advertising materials mentioning features or use
- * of this software.  Neither the name of the University nor the names of
- * its contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)nfs_vnops.c 7.46 (Berkeley) 7/26/90
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)nfs_vnops.c 7.60 (Berkeley) 5/24/91
  */
 
 /*
  * vnode op calls for sun nfs version 2
  */
 
  */
 
 /*
  * vnode op calls for sun nfs version 2
  */
 
-#include "machine/pte.h"
-#include "machine/mtpr.h"
 #include "param.h"
 #include "param.h"
-#include "user.h"
 #include "proc.h"
 #include "kernel.h"
 #include "proc.h"
 #include "kernel.h"
+#include "systm.h"
 #include "mount.h"
 #include "buf.h"
 #include "mount.h"
 #include "buf.h"
-#include "vm.h"
 #include "malloc.h"
 #include "mbuf.h"
 #include "malloc.h"
 #include "mbuf.h"
-#include "errno.h"
-#include "file.h"
 #include "conf.h"
 #include "conf.h"
+#include "namei.h"
 #include "vnode.h"
 #include "vnode.h"
-#include "text.h"
+#include "specdev.h"
+#include "fifo.h"
 #include "map.h"
 #include "map.h"
+
 #include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/quota.h"
 #include "../ufs/inode.h"
+#include "../ufs/dir.h"
+
 #include "nfsv2.h"
 #include "nfs.h"
 #include "nfsnode.h"
 #include "nfsv2.h"
 #include "nfs.h"
 #include "nfsnode.h"
 #include "nfsm_subs.h"
 #include "nfsiom.h"
 
 #include "nfsm_subs.h"
 #include "nfsiom.h"
 
+#include "machine/mtpr.h"
+
 /* Defs */
 #define        TRUE    1
 #define        FALSE   0
 
 /* Defs */
 #define        TRUE    1
 #define        FALSE   0
 
-/* Global vars */
-int    nfs_lookup(),
-       nfs_create(),
-       nfs_mknod(),
-       nfs_open(),
-       nfs_close(),
-       nfs_access(),
-       nfs_getattr(),
-       nfs_setattr(),
-       nfs_read(),
-       nfs_write(),
-       vfs_noop(),
-       vfs_nullop(),
-       nfs_remove(),
-       nfs_link(),
-       nfs_rename(),
-       nfs_mkdir(),
-       nfs_rmdir(),
-       nfs_symlink(),
-       nfs_readdir(),
-       nfs_readlink(),
-       nfs_abortop(),
-       nfs_lock(),
-       nfs_unlock(),
-       nfs_bmap(),
-       nfs_strategy(),
-       nfs_fsync(),
-       nfs_inactive(),
-       nfs_reclaim(),
-       nfs_print(),
-       nfs_islocked();
-
+/*
+ * Global vfs data structures for nfs
+ */
 struct vnodeops nfsv2_vnodeops = {
        nfs_lookup,             /* lookup */
        nfs_create,             /* create */
 struct vnodeops nfsv2_vnodeops = {
        nfs_lookup,             /* lookup */
        nfs_create,             /* create */
@@ -101,11 +87,11 @@ struct vnodeops nfsv2_vnodeops = {
        nfs_setattr,            /* setattr */
        nfs_read,               /* read */
        nfs_write,              /* write */
        nfs_setattr,            /* setattr */
        nfs_read,               /* read */
        nfs_write,              /* write */
-       vfs_noop,               /* ioctl */
-       vfs_noop,               /* select */
-       vfs_noop,               /* mmap */
+       nfs_ioctl,              /* ioctl */
+       nfs_select,             /* select */
+       nfs_mmap,               /* mmap */
        nfs_fsync,              /* fsync */
        nfs_fsync,              /* fsync */
-       vfs_nullop,             /* seek */
+       nfs_seek,               /* seek */
        nfs_remove,             /* remove */
        nfs_link,               /* link */
        nfs_rename,             /* rename */
        nfs_remove,             /* remove */
        nfs_link,               /* link */
        nfs_rename,             /* rename */
@@ -123,25 +109,16 @@ struct vnodeops nfsv2_vnodeops = {
        nfs_strategy,           /* strategy */
        nfs_print,              /* print */
        nfs_islocked,           /* islocked */
        nfs_strategy,           /* strategy */
        nfs_print,              /* print */
        nfs_islocked,           /* islocked */
+       nfs_advlock,            /* advlock */
 };
 
 };
 
-/* Special device vnode ops */
-int    spec_lookup(),
-       spec_open(),
-       spec_read(),
-       spec_write(),
-       spec_strategy(),
-       spec_bmap(),
-       spec_ioctl(),
-       spec_select(),
-       spec_close(),
-       spec_badop(),
-       spec_nullop();
-
+/*
+ * Special device vnode ops
+ */
 struct vnodeops spec_nfsv2nodeops = {
        spec_lookup,            /* lookup */
 struct vnodeops spec_nfsv2nodeops = {
        spec_lookup,            /* lookup */
-       spec_badop,             /* create */
-       spec_badop,             /* mknod */
+       spec_create,            /* create */
+       spec_mknod,             /* mknod */
        spec_open,              /* open */
        spec_close,             /* close */
        nfs_access,             /* access */
        spec_open,              /* open */
        spec_close,             /* close */
        nfs_access,             /* access */
@@ -151,18 +128,18 @@ struct vnodeops spec_nfsv2nodeops = {
        spec_write,             /* write */
        spec_ioctl,             /* ioctl */
        spec_select,            /* select */
        spec_write,             /* write */
        spec_ioctl,             /* ioctl */
        spec_select,            /* select */
-       spec_badop,             /* mmap */
-       spec_nullop,            /* fsync */
-       spec_badop,             /* seek */
-       spec_badop,             /* remove */
-       spec_badop,             /* link */
-       spec_badop,             /* rename */
-       spec_badop,             /* mkdir */
-       spec_badop,             /* rmdir */
-       spec_badop,             /* symlink */
-       spec_badop,             /* readdir */
-       spec_badop,             /* readlink */
-       spec_badop,             /* abortop */
+       spec_mmap,              /* mmap */
+       spec_fsync,             /* fsync */
+       spec_seek,              /* seek */
+       spec_remove,            /* remove */
+       spec_link,              /* link */
+       spec_rename,            /* rename */
+       spec_mkdir,             /* mkdir */
+       spec_rmdir,             /* rmdir */
+       spec_symlink,           /* symlink */
+       spec_readdir,           /* readdir */
+       spec_readlink,          /* readlink */
+       spec_abortop,           /* abortop */
        nfs_inactive,           /* inactive */
        nfs_reclaim,            /* reclaim */
        nfs_lock,               /* lock */
        nfs_inactive,           /* inactive */
        nfs_reclaim,            /* reclaim */
        nfs_lock,               /* lock */
@@ -171,25 +148,14 @@ struct vnodeops spec_nfsv2nodeops = {
        spec_strategy,          /* strategy */
        nfs_print,              /* print */
        nfs_islocked,           /* islocked */
        spec_strategy,          /* strategy */
        nfs_print,              /* print */
        nfs_islocked,           /* islocked */
+       spec_advlock,           /* advlock */
 };
 
 #ifdef FIFO
 };
 
 #ifdef FIFO
-int    fifo_lookup(),
-       fifo_open(),
-       fifo_read(),
-       fifo_write(),
-       fifo_bmap(),
-       fifo_ioctl(),
-       fifo_select(),
-       fifo_close(),
-       fifo_print(),
-       fifo_badop(),
-       fifo_nullop();
-
 struct vnodeops fifo_nfsv2nodeops = {
        fifo_lookup,            /* lookup */
 struct vnodeops fifo_nfsv2nodeops = {
        fifo_lookup,            /* lookup */
-       fifo_badop,             /* create */
-       fifo_badop,             /* mknod */
+       fifo_create,            /* create */
+       fifo_mknod,             /* mknod */
        fifo_open,              /* open */
        fifo_close,             /* close */
        nfs_access,             /* access */
        fifo_open,              /* open */
        fifo_close,             /* close */
        nfs_access,             /* access */
@@ -199,18 +165,18 @@ struct vnodeops fifo_nfsv2nodeops = {
        fifo_write,             /* write */
        fifo_ioctl,             /* ioctl */
        fifo_select,            /* select */
        fifo_write,             /* write */
        fifo_ioctl,             /* ioctl */
        fifo_select,            /* select */
-       fifo_badop,             /* mmap */
-       fifo_nullop,            /* fsync */
-       fifo_badop,             /* seek */
-       fifo_badop,             /* remove */
-       fifo_badop,             /* link */
-       fifo_badop,             /* rename */
-       fifo_badop,             /* mkdir */
-       fifo_badop,             /* rmdir */
-       fifo_badop,             /* symlink */
-       fifo_badop,             /* readdir */
-       fifo_badop,             /* readlink */
-       fifo_badop,             /* abortop */
+       fifo_mmap,              /* mmap */
+       fifo_fsync,             /* fsync */
+       fifo_seek,              /* seek */
+       fifo_remove,            /* remove */
+       fifo_link,              /* link */
+       fifo_rename,            /* rename */
+       fifo_mkdir,             /* mkdir */
+       fifo_rmdir,             /* rmdir */
+       fifo_symlink,           /* symlink */
+       fifo_readdir,           /* readdir */
+       fifo_readlink,          /* readlink */
+       fifo_abortop,           /* abortop */
        nfs_inactive,           /* inactive */
        nfs_reclaim,            /* reclaim */
        nfs_lock,               /* lock */
        nfs_inactive,           /* inactive */
        nfs_reclaim,            /* reclaim */
        nfs_lock,               /* lock */
@@ -219,24 +185,29 @@ struct vnodeops fifo_nfsv2nodeops = {
        fifo_badop,             /* strategy */
        nfs_print,              /* print */
        nfs_islocked,           /* islocked */
        fifo_badop,             /* strategy */
        nfs_print,              /* print */
        nfs_islocked,           /* islocked */
+       fifo_advlock,           /* advlock */
 };
 #endif /* FIFO */
 
 };
 #endif /* FIFO */
 
+/*
+ * Global vars
+ */
 extern u_long nfs_procids[NFS_NPROCS];
 extern u_long nfs_prog, nfs_vers;
 extern char nfsiobuf[MAXPHYS+NBPG];
 struct map nfsmap[NFS_MSIZ];
 struct buf nfs_bqueue;         /* Queue head for nfsiod's */
 extern u_long nfs_procids[NFS_NPROCS];
 extern u_long nfs_prog, nfs_vers;
 extern char nfsiobuf[MAXPHYS+NBPG];
 struct map nfsmap[NFS_MSIZ];
 struct buf nfs_bqueue;         /* Queue head for nfsiod's */
-int nfs_asyncdaemons = 0;
 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
+int nfs_numasync = 0;
 static int nfsmap_want = 0;
 
 /*
  * nfs null call from vfs.
  */
 static int nfsmap_want = 0;
 
 /*
  * nfs null call from vfs.
  */
-nfs_null(vp, cred)
+nfs_null(vp, cred, p)
        struct vnode *vp;
        struct ucred *cred;
        struct vnode *vp;
        struct ucred *cred;
+       struct proc *p;
 {
        caddr_t bpos, dpos;
        u_long xid;
 {
        caddr_t bpos, dpos;
        u_long xid;
@@ -244,7 +215,7 @@ nfs_null(vp, cred)
        struct mbuf *mreq, *mrep, *md, *mb;
        
        nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
        struct mbuf *mreq, *mrep, *md, *mb;
        
        nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
-       nfsm_request(vp, NFSPROC_NULL, u.u_procp, 0);
+       nfsm_request(vp, NFSPROC_NULL, p, 0);
        nfsm_reqdone;
        return (error);
 }
        nfsm_reqdone;
        return (error);
 }
@@ -253,10 +224,11 @@ nfs_null(vp, cred)
  * nfs access vnode op.
  * Essentially just get vattr and then imitate iaccess()
  */
  * nfs access vnode op.
  * Essentially just get vattr and then imitate iaccess()
  */
-nfs_access(vp, mode, cred)
+nfs_access(vp, mode, cred, p)
        struct vnode *vp;
        int mode;
        register struct ucred *cred;
        struct vnode *vp;
        int mode;
        register struct ucred *cred;
+       struct proc *p;
 {
        register struct vattr *vap;
        register gid_t *gp;
 {
        register struct vattr *vap;
        register gid_t *gp;
@@ -271,7 +243,7 @@ nfs_access(vp, mode, cred)
        if (cred->cr_uid == 0)
                return (0);
        vap = &vattr;
        if (cred->cr_uid == 0)
                return (0);
        vap = &vattr;
-       if (error = nfs_dogetattr(vp, vap, cred, 0))
+       if (error = nfs_dogetattr(vp, vap, cred, 0, p))
                return (error);
        /*
         * Access check is based on only one of owner, group, public.
                return (error);
        /*
         * Access check is based on only one of owner, group, public.
@@ -298,10 +270,11 @@ found:
  * Just check to see if the type is ok
  */
 /* ARGSUSED */
  * Just check to see if the type is ok
  */
 /* ARGSUSED */
-nfs_open(vp, mode, cred)
+nfs_open(vp, mode, cred, p)
        struct vnode *vp;
        int mode;
        struct ucred *cred;
        struct vnode *vp;
        int mode;
        struct ucred *cred;
+       struct proc *p;
 {
        register enum vtype vtyp;
 
 {
        register enum vtype vtyp;
 
@@ -317,10 +290,11 @@ nfs_open(vp, mode, cred)
  * For reg files, invalidate any buffer cache entries.
  */
 /* ARGSUSED */
  * For reg files, invalidate any buffer cache entries.
  */
 /* ARGSUSED */
-nfs_close(vp, fflags, cred)
+nfs_close(vp, fflags, cred, p)
        register struct vnode *vp;
        int fflags;
        struct ucred *cred;
        register struct vnode *vp;
        int fflags;
        struct ucred *cred;
+       struct proc *p;
 {
        register struct nfsnode *np = VTONFS(vp);
        int error = 0;
 {
        register struct nfsnode *np = VTONFS(vp);
        int error = 0;
@@ -342,19 +316,21 @@ nfs_close(vp, fflags, cred)
 /*
  * nfs getattr call from vfs.
  */
 /*
  * nfs getattr call from vfs.
  */
-nfs_getattr(vp, vap, cred)
+nfs_getattr(vp, vap, cred, p)
        register struct vnode *vp;
        struct vattr *vap;
        struct ucred *cred;
        register struct vnode *vp;
        struct vattr *vap;
        struct ucred *cred;
+       struct proc *p;
 {
 {
-       return (nfs_dogetattr(vp, vap, cred, 0));
+       return (nfs_dogetattr(vp, vap, cred, 0, p));
 }
 
 }
 
-nfs_dogetattr(vp, vap, cred, tryhard)
+nfs_dogetattr(vp, vap, cred, tryhard, p)
        register struct vnode *vp;
        struct vattr *vap;
        struct ucred *cred;
        int tryhard;
        register struct vnode *vp;
        struct vattr *vap;
        struct ucred *cred;
        int tryhard;
+       struct proc *p;
 {
        register caddr_t cp;
        register long t1;
 {
        register caddr_t cp;
        register long t1;
@@ -369,7 +345,7 @@ nfs_dogetattr(vp, vap, cred, tryhard)
        nfsstats.rpccnt[NFSPROC_GETATTR]++;
        nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
        nfsm_fhtom(vp);
        nfsstats.rpccnt[NFSPROC_GETATTR]++;
        nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
        nfsm_fhtom(vp);
-       nfsm_request(vp, NFSPROC_GETATTR, u.u_procp, tryhard);
+       nfsm_request(vp, NFSPROC_GETATTR, p, tryhard);
        nfsm_loadattr(vp, vap);
        nfsm_reqdone;
        return (error);
        nfsm_loadattr(vp, vap);
        nfsm_reqdone;
        return (error);
@@ -378,10 +354,11 @@ nfs_dogetattr(vp, vap, cred, tryhard)
 /*
  * nfs setattr call.
  */
 /*
  * nfs setattr call.
  */
-nfs_setattr(vp, vap, cred)
+nfs_setattr(vp, vap, cred, p)
        register struct vnode *vp;
        register struct vattr *vap;
        struct ucred *cred;
        register struct vnode *vp;
        register struct vattr *vap;
        struct ucred *cred;
+       struct proc *p;
 {
        register struct nfsv2_sattr *sp;
        register caddr_t cp;
 {
        register struct nfsv2_sattr *sp;
        register caddr_t cp;
@@ -417,11 +394,14 @@ nfs_setattr(vp, vap, cred)
                np = VTONFS(vp);
                if (np->n_flag & NMODIFIED) {
                        np->n_flag &= ~NMODIFIED;
                np = VTONFS(vp);
                if (np->n_flag & NMODIFIED) {
                        np->n_flag &= ~NMODIFIED;
-                       vinvalbuf(vp, TRUE);
+                       if (vap->va_size == 0)
+                               vinvalbuf(vp, FALSE);
+                       else
+                               vinvalbuf(vp, TRUE);
                        np->n_attrstamp = 0;
                }
        }
                        np->n_attrstamp = 0;
                }
        }
-       nfsm_request(vp, NFSPROC_SETATTR, u.u_procp, 1);
+       nfsm_request(vp, NFSPROC_SETATTR, p, 1);
        nfsm_loadattr(vp, (struct vattr *)0);
        /* should we fill in any vap fields ?? */
        nfsm_reqdone;
        nfsm_loadattr(vp, (struct vattr *)0);
        /* should we fill in any vap fields ?? */
        nfsm_reqdone;
@@ -433,12 +413,13 @@ nfs_setattr(vp, vap, cred)
  * First look in cache
  * If not found, unlock the directory nfsnode and do the rpc
  */
  * First look in cache
  * If not found, unlock the directory nfsnode and do the rpc
  */
-nfs_lookup(vp, ndp)
+nfs_lookup(vp, ndp, p)
        register struct vnode *vp;
        register struct nameidata *ndp;
        register struct vnode *vp;
        register struct nameidata *ndp;
+       struct proc *p;
 {
        register struct vnode *vdp;
 {
        register struct vnode *vdp;
-       register u_long *p;
+       register u_long *tl;
        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;
@@ -455,14 +436,12 @@ nfs_lookup(vp, ndp)
        if (vp->v_type != VDIR)
                return (ENOTDIR);
        lockparent = ndp->ni_nameiop & LOCKPARENT;
        if (vp->v_type != VDIR)
                return (ENOTDIR);
        lockparent = ndp->ni_nameiop & LOCKPARENT;
-       flag = ndp->ni_nameiop & OPFLAG;
+       flag = ndp->ni_nameiop & OPMASK;
        wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
        if ((error = cache_lookup(ndp)) && error != ENOENT) {
                struct vattr vattr;
                int vpid;
 
        wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
        if ((error = cache_lookup(ndp)) && error != ENOENT) {
                struct vattr vattr;
                int vpid;
 
-               if (vp == ndp->ni_rdir && ndp->ni_isdotdot)
-                       panic("nfs_lookup: .. through root");
                vdp = ndp->ni_vp;
                vpid = vdp->v_id;
                /*
                vdp = ndp->ni_vp;
                vpid = vdp->v_id;
                /*
@@ -475,23 +454,27 @@ nfs_lookup(vp, ndp)
                } else if (ndp->ni_isdotdot) {
                        nfs_unlock(vp);
                        error = vget(vdp);
                } else if (ndp->ni_isdotdot) {
                        nfs_unlock(vp);
                        error = vget(vdp);
+                       if (!error && lockparent && *ndp->ni_next == '\0')
+                               nfs_lock(vp);
                } else {
                        error = vget(vdp);
                } else {
                        error = vget(vdp);
-                       nfs_unlock(vp);
+                       if (!lockparent || error || *ndp->ni_next != '\0')
+                               nfs_unlock(vp);
                }
                if (!error) {
                        if (vpid == vdp->v_id) {
                }
                if (!error) {
                        if (vpid == vdp->v_id) {
-                          if (!nfs_dogetattr(vdp, &vattr, ndp->ni_cred, 0&&
+                          if (!nfs_dogetattr(vdp, &vattr, ndp->ni_cred, 0, p)&&
                               vattr.va_ctime.tv_sec == VTONFS(vdp)->n_ctime) {
                                nfsstats.lookupcache_hits++;
                               vattr.va_ctime.tv_sec == VTONFS(vdp)->n_ctime) {
                                nfsstats.lookupcache_hits++;
+                               if (flag != LOOKUP && *ndp->ni_next == 0)
+                                       ndp->ni_nameiop |= SAVENAME;
                                return (0);
                                return (0);
-                          } else {
-                               cache_purge(vdp);
-                               nfs_nput(vdp);
                           }
                           }
-                       } else {
-                               nfs_nput(vdp);
+                          cache_purge(vdp);
                        }
                        }
+                       nfs_nput(vdp);
+                       if (lockparent && vdp != vp && *ndp->ni_next == '\0')
+                               nfs_unlock(vp);
                }
                ndp->ni_vp = NULLVP;
        } else
                }
                ndp->ni_vp = NULLVP;
        } else
@@ -503,12 +486,14 @@ nfs_lookup(vp, ndp)
        nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
        nfsm_fhtom(vp);
        nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
        nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
        nfsm_fhtom(vp);
        nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
-       nfsm_request(vp, NFSPROC_LOOKUP, u.u_procp, 0);
+       nfsm_request(vp, NFSPROC_LOOKUP, p, 0);
 nfsmout:
        if (error) {
                if (lockparent || (flag != CREATE && flag != RENAME) ||
                    *ndp->ni_next != 0)
                        nfs_lock(vp);
 nfsmout:
        if (error) {
                if (lockparent || (flag != CREATE && flag != RENAME) ||
                    *ndp->ni_next != 0)
                        nfs_lock(vp);
+               if (flag != LOOKUP && *ndp->ni_next == 0)
+                       ndp->ni_nameiop |= SAVENAME;
                return (error);
        }
        nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH);
                return (error);
        }
        nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH);
@@ -543,6 +528,7 @@ nfsmout:
                if (lockparent || vp == newvp)
                        nfs_lock(vp);
                m_freem(mrep);
                if (lockparent || vp == newvp)
                        nfs_lock(vp);
                m_freem(mrep);
+               ndp->ni_nameiop |= SAVENAME;
                return (0);
        }
 
                return (0);
        }
 
@@ -568,6 +554,8 @@ nfsmout:
                ndp->ni_vp = newvp;
                if (lockparent)
                        nfs_lock(vp);
                ndp->ni_vp = newvp;
                if (lockparent)
                        nfs_lock(vp);
+               m_freem(mrep);
+               ndp->ni_nameiop |= SAVENAME;
                return (0);
        }
 
                return (0);
        }
 
@@ -604,6 +592,8 @@ nfsmout:
        if (vp == newvp || (lockparent && *ndp->ni_next == '\0'))
                nfs_lock(vp);
        ndp->ni_vp = newvp;
        if (vp == newvp || (lockparent && *ndp->ni_next == '\0'))
                nfs_lock(vp);
        ndp->ni_vp = newvp;
+       if (flag != LOOKUP && *ndp->ni_next == 0)
+               ndp->ni_nameiop |= SAVENAME;
        if (error == 0 && ndp->ni_makeentry) {
                np->n_ctime = np->n_vattr.va_ctime.tv_sec;
                cache_enter(ndp);
        if (error == 0 && ndp->ni_makeentry) {
                np->n_ctime = np->n_vattr.va_ctime.tv_sec;
                cache_enter(ndp);
@@ -643,13 +633,12 @@ nfs_readlink(vp, uiop, cred)
  * Do a readlink rpc.
  * Called by nfs_doio() from below the buffer cache.
  */
  * Do a readlink rpc.
  * Called by nfs_doio() from below the buffer cache.
  */
-nfs_readlinkrpc(vp, uiop, cred, procp)
+nfs_readlinkrpc(vp, uiop, cred)
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
-       struct proc *procp;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos, cp2;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos, cp2;
@@ -659,14 +648,12 @@ nfs_readlinkrpc(vp, uiop, cred, procp)
        long len;
 
        nfsstats.rpccnt[NFSPROC_READLINK]++;
        long len;
 
        nfsstats.rpccnt[NFSPROC_READLINK]++;
-       nfs_unlock(vp);
        nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
        nfsm_fhtom(vp);
        nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
        nfsm_fhtom(vp);
-       nfsm_request(vp, NFSPROC_READLINK, procp, 0);
+       nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, 0);
        nfsm_strsiz(len, NFS_MAXPATHLEN);
        nfsm_mtouio(uiop, len);
        nfsm_reqdone;
        nfsm_strsiz(len, NFS_MAXPATHLEN);
        nfsm_mtouio(uiop, len);
        nfsm_reqdone;
-       nfs_lock(vp);
        return (error);
 }
 
        return (error);
 }
 
@@ -674,13 +661,12 @@ nfs_readlinkrpc(vp, uiop, cred, procp)
  * nfs read rpc call
  * Ditto above
  */
  * nfs read rpc call
  * Ditto above
  */
-nfs_readrpc(vp, uiop, cred, procp)
+nfs_readrpc(vp, uiop, cred)
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
-       struct proc *procp;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos, cp2;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos, cp2;
@@ -697,11 +683,11 @@ nfs_readrpc(vp, uiop, cred, procp)
                len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
                nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3);
                nfsm_fhtom(vp);
                len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
                nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3);
                nfsm_fhtom(vp);
-               nfsm_build(p, u_long *, NFSX_UNSIGNED*3);
-               *p++ = txdr_unsigned(uiop->uio_offset);
-               *p++ = txdr_unsigned(len);
-               *p = 0;
-               nfsm_request(vp, NFSPROC_READ, procp, 1);
+               nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);
+               *tl++ = txdr_unsigned(uiop->uio_offset);
+               *tl++ = txdr_unsigned(len);
+               *tl = 0;
+               nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, 1);
                nfsm_loadattr(vp, (struct vattr *)0);
                nfsm_strsiz(retlen, nmp->nm_rsize);
                nfsm_mtouio(uiop, retlen);
                nfsm_loadattr(vp, (struct vattr *)0);
                nfsm_strsiz(retlen, nmp->nm_rsize);
                nfsm_mtouio(uiop, retlen);
@@ -718,13 +704,12 @@ nfsmout:
 /*
  * nfs write call
  */
 /*
  * nfs write call
  */
-nfs_writerpc(vp, uiop, cred, procp)
+nfs_writerpc(vp, uiop, cred)
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
-       struct proc *procp;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1;
        caddr_t bpos, dpos;
@@ -742,11 +727,11 @@ nfs_writerpc(vp, uiop, cred, procp)
                nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred,
                        NFSX_FH+NFSX_UNSIGNED*4);
                nfsm_fhtom(vp);
                nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred,
                        NFSX_FH+NFSX_UNSIGNED*4);
                nfsm_fhtom(vp);
-               nfsm_build(p, u_long *, NFSX_UNSIGNED*4);
-               *(p+1) = txdr_unsigned(uiop->uio_offset);
-               *(p+3) = txdr_unsigned(len);
+               nfsm_build(tl, u_long *, NFSX_UNSIGNED*4);
+               *(tl+1) = txdr_unsigned(uiop->uio_offset);
+               *(tl+3) = txdr_unsigned(len);
                nfsm_uiotom(uiop, len);
                nfsm_uiotom(uiop, len);
-               nfsm_request(vp, NFSPROC_WRITE, procp, 1);
+               nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, 1);
                nfsm_loadattr(vp, (struct vattr *)0);
                m_freem(mrep);
                tsiz -= len;
                nfsm_loadattr(vp, (struct vattr *)0);
                m_freem(mrep);
                tsiz -= len;
@@ -761,13 +746,14 @@ nfsmout:
  * set to specify the file type and the size field for rdev.
  */
 /* ARGSUSED */
  * set to specify the file type and the size field for rdev.
  */
 /* ARGSUSED */
-nfs_mknod(ndp, vap, cred)
+nfs_mknod(ndp, vap, cred, p)
        struct nameidata *ndp;
        struct ucred *cred;
        register struct vattr *vap;
        struct nameidata *ndp;
        struct ucred *cred;
        register struct vattr *vap;
+       struct proc *p;
 {
        register struct nfsv2_sattr *sp;
 {
        register struct nfsv2_sattr *sp;
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -789,9 +775,9 @@ nfs_mknod(ndp, vap, cred)
        }
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
        }
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
-         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR);
+         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_SATTR);
        nfsm_fhtom(ndp->ni_dvp);
        nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
+       nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
@@ -800,8 +786,9 @@ nfs_mknod(ndp, vap, cred)
        /* or should these be VNOVAL ?? */
        txdr_time(&vap->va_atime, &sp->sa_atime);
        txdr_time(&vap->va_mtime, &sp->sa_mtime);
        /* or should these be VNOVAL ?? */
        txdr_time(&vap->va_atime, &sp->sa_atime);
        txdr_time(&vap->va_mtime, &sp->sa_mtime);
-       nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, u.u_procp, 1);
+       nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, p, 1);
        nfsm_reqdone;
        nfsm_reqdone;
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfs_nput(ndp->ni_dvp);
        return (error);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfs_nput(ndp->ni_dvp);
        return (error);
@@ -810,12 +797,13 @@ nfs_mknod(ndp, vap, cred)
 /*
  * nfs file create call
  */
 /*
  * nfs file create call
  */
-nfs_create(ndp, vap)
+nfs_create(ndp, vap, p)
        register struct nameidata *ndp;
        register struct vattr *vap;
        register struct nameidata *ndp;
        register struct vattr *vap;
+       struct proc *p;
 {
        register struct nfsv2_sattr *sp;
 {
        register struct nfsv2_sattr *sp;
-       register u_long *p;
+       register u_long *tl;
        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;
@@ -825,20 +813,21 @@ nfs_create(ndp, vap)
 
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
 
        nfsstats.rpccnt[NFSPROC_CREATE]++;
        nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
-         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR);
+         NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_SATTR);
        nfsm_fhtom(ndp->ni_dvp);
        nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
+       nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
-       sp->sa_mode = vtonfs_mode(VREG, vap->va_mode);
+       sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
        sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(ndp->ni_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);
        sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
        sp->sa_gid = txdr_unsigned(ndp->ni_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);
-       nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, u.u_procp, 1);
+       nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, p, 1);
        nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
        nfsm_reqdone;
        nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
        nfsm_reqdone;
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfs_nput(ndp->ni_dvp);
        return (error);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfs_nput(ndp->ni_dvp);
        return (error);
@@ -855,12 +844,13 @@ nfs_create(ndp, vap)
  *     else
  *       do the remove rpc
  */
  *     else
  *       do the remove rpc
  */
-nfs_remove(ndp)
+nfs_remove(ndp, p)
        register struct nameidata *ndp;
        register struct nameidata *ndp;
+       struct proc *p;
 {
        register struct vnode *vp = ndp->ni_vp;
        register struct nfsnode *np = VTONFS(ndp->ni_vp);
 {
        register struct vnode *vp = ndp->ni_vp;
        register struct nfsnode *np = VTONFS(ndp->ni_vp);
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -870,15 +860,16 @@ nfs_remove(ndp)
 
        if (vp->v_usecount > 1) {
                if (!np->n_sillyrename)
 
        if (vp->v_usecount > 1) {
                if (!np->n_sillyrename)
-                       error = nfs_sillyrename(ndp, REMOVE);
+                       error = nfs_sillyrename(ndp, p);
        } else {
                nfsstats.rpccnt[NFSPROC_REMOVE]++;
                nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
        } else {
                nfsstats.rpccnt[NFSPROC_REMOVE]++;
                nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
-                       NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
+                       NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
                nfsm_fhtom(ndp->ni_dvp);
                nfsm_fhtom(ndp->ni_dvp);
-               nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
-               nfsm_request(ndp->ni_dvp, NFSPROC_REMOVE, u.u_procp, 1);
+               nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
+               nfsm_request(ndp->ni_dvp, NFSPROC_REMOVE, p, 1);
                nfsm_reqdone;
                nfsm_reqdone;
+               FREE(ndp->ni_pnbuf, M_NAMEI);
                VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
                /*
                 * Kludge City: If the first reply to the remove rpc is lost..
                VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
                /*
                 * Kludge City: If the first reply to the remove rpc is lost..
@@ -901,10 +892,11 @@ nfs_remove(ndp)
 /*
  * nfs file remove rpc called from nfs_inactive
  */
 /*
  * nfs file remove rpc called from nfs_inactive
  */
-nfs_removeit(ndp)
-       register struct nameidata *ndp;
+nfs_removeit(sp, p)
+       register struct sillyrename *sp;
+       struct proc *p;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -913,23 +905,24 @@ nfs_removeit(ndp)
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_REMOVE]++;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_REMOVE]++;
-       nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
-               NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
-       nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
-       nfsm_request(ndp->ni_dvp, NFSPROC_REMOVE, u.u_procp, 1);
+       nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], sp->s_cred,
+               NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen));
+       nfsm_fhtom(sp->s_dvp);
+       nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
+       nfsm_request(sp->s_dvp, NFSPROC_REMOVE, p, 1);
        nfsm_reqdone;
        nfsm_reqdone;
-       VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
+       VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
        return (error);
 }
 
 /*
  * nfs file rename call
  */
        return (error);
 }
 
 /*
  * nfs file rename call
  */
-nfs_rename(sndp, tndp)
+nfs_rename(sndp, tndp, p)
        register struct nameidata *sndp, *tndp;
        register struct nameidata *sndp, *tndp;
+       struct proc *p;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -939,13 +932,13 @@ nfs_rename(sndp, tndp)
 
        nfsstats.rpccnt[NFSPROC_RENAME]++;
        nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
 
        nfsstats.rpccnt[NFSPROC_RENAME]++;
        nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
-               (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+
-               nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/
+               (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_namelen) +
+               nfsm_rndup(tndp->ni_namelen)); /* or sndp->ni_cred?*/
        nfsm_fhtom(sndp->ni_dvp);
        nfsm_fhtom(sndp->ni_dvp);
-       nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
+       nfsm_strtom(sndp->ni_ptr, sndp->ni_namelen, NFS_MAXNAMLEN);
        nfsm_fhtom(tndp->ni_dvp);
        nfsm_fhtom(tndp->ni_dvp);
-       nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
-       nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, u.u_procp, 1);
+       nfsm_strtom(tndp->ni_ptr, tndp->ni_namelen, NFS_MAXNAMLEN);
+       nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, p, 1);
        nfsm_reqdone;
        VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
        VTONFS(tndp->ni_dvp)->n_flag |= NMODIFIED;
        nfsm_reqdone;
        VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
        VTONFS(tndp->ni_dvp)->n_flag |= NMODIFIED;
@@ -954,14 +947,12 @@ nfs_rename(sndp, tndp)
                        cache_purge(tndp->ni_dvp);
                cache_purge(sndp->ni_dvp);
        }
                        cache_purge(tndp->ni_dvp);
                cache_purge(sndp->ni_dvp);
        }
-       VOP_ABORTOP(tndp);
        if (tndp->ni_dvp == tndp->ni_vp)
                vrele(tndp->ni_dvp);
        else
                vput(tndp->ni_dvp);
        if (tndp->ni_vp)
                vput(tndp->ni_vp);
        if (tndp->ni_dvp == tndp->ni_vp)
                vrele(tndp->ni_dvp);
        else
                vput(tndp->ni_dvp);
        if (tndp->ni_vp)
                vput(tndp->ni_vp);
-       VOP_ABORTOP(sndp);
        vrele(sndp->ni_dvp);
        vrele(sndp->ni_vp);
        /*
        vrele(sndp->ni_dvp);
        vrele(sndp->ni_vp);
        /*
@@ -975,10 +966,12 @@ nfs_rename(sndp, tndp)
 /*
  * nfs file rename rpc called from nfs_remove() above
  */
 /*
  * nfs file rename rpc called from nfs_remove() above
  */
-nfs_renameit(sndp, tndp)
-       register struct nameidata *sndp, *tndp;
+nfs_renameit(sndp, sp, p)
+       register struct nameidata *sndp;
+       register struct sillyrename *sp;
+       struct proc *p;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -987,28 +980,30 @@ nfs_renameit(sndp, tndp)
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_RENAME]++;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        nfsstats.rpccnt[NFSPROC_RENAME]++;
-       nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
-               (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+
-               nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/
+       nfsm_reqhead(nfs_procids[NFSPROC_RENAME], sp->s_cred,
+               (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_namelen) +
+               nfsm_rndup(sp->s_namlen)); /* or sndp->ni_cred?*/
        nfsm_fhtom(sndp->ni_dvp);
        nfsm_fhtom(sndp->ni_dvp);
-       nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
-       nfsm_fhtom(tndp->ni_dvp);
-       nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
-       nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, u.u_procp, 1);
+       nfsm_strtom(sndp->ni_ptr, sndp->ni_namelen, NFS_MAXNAMLEN);
+       nfsm_fhtom(sp->s_dvp);
+       nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
+       nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, p, 1);
        nfsm_reqdone;
        nfsm_reqdone;
+       FREE(sndp->ni_pnbuf, M_NAMEI);
        VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
        VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
-       VTONFS(tndp->ni_dvp)->n_flag |= NMODIFIED;
+       VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
        return (error);
 }
 
 /*
  * nfs hard link create call
  */
        return (error);
 }
 
 /*
  * nfs hard link create call
  */
-nfs_link(vp, ndp)
+nfs_link(vp, ndp, p)
        register struct vnode *vp;
        register struct nameidata *ndp;
        register struct vnode *vp;
        register struct nameidata *ndp;
+       struct proc *p;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -1020,12 +1015,13 @@ nfs_link(vp, ndp)
                nfs_lock(vp);
        nfsstats.rpccnt[NFSPROC_LINK]++;
        nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred,
                nfs_lock(vp);
        nfsstats.rpccnt[NFSPROC_LINK]++;
        nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred,
-               NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
+               NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
        nfsm_fhtom(vp);
        nfsm_fhtom(ndp->ni_dvp);
        nfsm_fhtom(vp);
        nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
-       nfsm_request(vp, NFSPROC_LINK, u.u_procp, 1);
+       nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
+       nfsm_request(vp, NFSPROC_LINK, p, 1);
        nfsm_reqdone;
        nfsm_reqdone;
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        VTONFS(vp)->n_attrstamp = 0;
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        if (ndp->ni_dvp != vp)
        VTONFS(vp)->n_attrstamp = 0;
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        if (ndp->ni_dvp != vp)
@@ -1042,13 +1038,14 @@ nfs_link(vp, ndp)
 /*
  * nfs symbolic link create call
  */
 /*
  * nfs symbolic link create call
  */
-nfs_symlink(ndp, vap, nm)
+nfs_symlink(ndp, vap, nm, p)
        struct nameidata *ndp;
        struct vattr *vap;
        char *nm;               /* is this the path ?? */
        struct nameidata *ndp;
        struct vattr *vap;
        char *nm;               /* is this the path ?? */
+       struct proc *p;
 {
        register struct nfsv2_sattr *sp;
 {
        register struct nfsv2_sattr *sp;
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -1058,9 +1055,9 @@ nfs_symlink(ndp, vap, nm)
 
        nfsstats.rpccnt[NFSPROC_SYMLINK]++;
        nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred,
 
        nfsstats.rpccnt[NFSPROC_SYMLINK]++;
        nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred,
-       NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_UNSIGNED);
+       NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_UNSIGNED);
        nfsm_fhtom(ndp->ni_dvp);
        nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
+       nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
        nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
        nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
@@ -1069,8 +1066,9 @@ nfs_symlink(ndp, vap, nm)
        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 ?? */
        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 ?? */
-       nfsm_request(ndp->ni_dvp, NFSPROC_SYMLINK, u.u_procp, 1);
+       nfsm_request(ndp->ni_dvp, NFSPROC_SYMLINK, p, 1);
        nfsm_reqdone;
        nfsm_reqdone;
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfs_nput(ndp->ni_dvp);
        /*
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfs_nput(ndp->ni_dvp);
        /*
@@ -1084,12 +1082,13 @@ nfs_symlink(ndp, vap, nm)
 /*
  * nfs make dir call
  */
 /*
  * nfs make dir call
  */
-nfs_mkdir(ndp, vap)
+nfs_mkdir(ndp, vap, p)
        register struct nameidata *ndp;
        struct vattr *vap;
        register struct nameidata *ndp;
        struct vattr *vap;
+       struct proc *p;
 {
        register struct nfsv2_sattr *sp;
 {
        register struct nfsv2_sattr *sp;
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        register int len;
        register caddr_t cp;
        register long t1, t2;
        register int len;
@@ -1098,12 +1097,12 @@ nfs_mkdir(ndp, vap)
        int error = 0, firsttry = 1;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
        int error = 0, firsttry = 1;
        struct mbuf *mreq, *mrep, *md, *mb, *mb2;
 
-       len = ndp->ni_dent.d_namlen;
+       len = ndp->ni_namelen;
        nfsstats.rpccnt[NFSPROC_MKDIR]++;
        nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred,
          NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR);
        nfsm_fhtom(ndp->ni_dvp);
        nfsstats.rpccnt[NFSPROC_MKDIR]++;
        nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred,
          NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR);
        nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
+       nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
        sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
        nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
        sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
        sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
@@ -1111,7 +1110,7 @@ nfs_mkdir(ndp, vap)
        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 ?? */
        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 ?? */
-       nfsm_request(ndp->ni_dvp, NFSPROC_MKDIR, u.u_procp, 1);
+       nfsm_request(ndp->ni_dvp, NFSPROC_MKDIR, p, 1);
        nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
        nfsm_reqdone;
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
        nfsm_reqdone;
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
@@ -1129,8 +1128,8 @@ nfs_mkdir(ndp, vap)
                nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred,
                    NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
                nfsm_fhtom(ndp->ni_dvp);
                nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred,
                    NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
                nfsm_fhtom(ndp->ni_dvp);
-               nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
-               nfsm_request(ndp->ni_dvp, NFSPROC_LOOKUP, u.u_procp, 1);
+               nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
+               nfsm_request(ndp->ni_dvp, NFSPROC_LOOKUP, p, 1);
                nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
                if (ndp->ni_vp->v_type != VDIR) {
                        vput(ndp->ni_vp);
                nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
                if (ndp->ni_vp->v_type != VDIR) {
                        vput(ndp->ni_vp);
@@ -1138,6 +1137,7 @@ nfs_mkdir(ndp, vap)
                }
                m_freem(mrep);
        }
                }
                m_freem(mrep);
        }
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        nfs_nput(ndp->ni_dvp);
        return (error);
 }
        nfs_nput(ndp->ni_dvp);
        return (error);
 }
@@ -1145,10 +1145,11 @@ nfs_mkdir(ndp, vap)
 /*
  * nfs remove directory call
  */
 /*
  * nfs remove directory call
  */
-nfs_rmdir(ndp)
+nfs_rmdir(ndp, p)
        register struct nameidata *ndp;
        register struct nameidata *ndp;
+       struct proc *p;
 {
 {
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
        register caddr_t cp;
        register long t1, t2;
        caddr_t bpos, dpos;
@@ -1163,11 +1164,12 @@ nfs_rmdir(ndp)
        }
        nfsstats.rpccnt[NFSPROC_RMDIR]++;
        nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred,
        }
        nfsstats.rpccnt[NFSPROC_RMDIR]++;
        nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred,
-               NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
+               NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
        nfsm_fhtom(ndp->ni_dvp);
        nfsm_fhtom(ndp->ni_dvp);
-       nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
-       nfsm_request(ndp->ni_dvp, NFSPROC_RMDIR, u.u_procp, 1);
+       nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
+       nfsm_request(ndp->ni_dvp, NFSPROC_RMDIR, p, 1);
        nfsm_reqdone;
        nfsm_reqdone;
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        cache_purge(ndp->ni_dvp);
        cache_purge(ndp->ni_vp);
        VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
        cache_purge(ndp->ni_dvp);
        cache_purge(ndp->ni_vp);
@@ -1204,7 +1206,7 @@ nfs_readdir(vp, uiop, cred, eofflagp)
         */
        if (uiop->uio_offset != 0 && uiop->uio_offset == np->n_direofoffset &&
            (np->n_flag & NMODIFIED) == 0 &&
         */
        if (uiop->uio_offset != 0 && uiop->uio_offset == np->n_direofoffset &&
            (np->n_flag & NMODIFIED) == 0 &&
-           nfs_dogetattr(vp, &vattr, cred, 0) == 0 &&
+           nfs_dogetattr(vp, &vattr, cred, 0, uiop->uio_procp) == 0 &&
            np->n_mtime == vattr.va_mtime.tv_sec) {
                *eofflagp = 1;
                nfsstats.direofcache_hits++;
            np->n_mtime == vattr.va_mtime.tv_sec) {
                *eofflagp = 1;
                nfsstats.direofcache_hits++;
@@ -1229,15 +1231,14 @@ nfs_readdir(vp, uiop, cred, eofflagp)
  * Readdir rpc call.
  * Called from below the buffer cache by nfs_doio().
  */
  * Readdir rpc call.
  * Called from below the buffer cache by nfs_doio().
  */
-nfs_readdirrpc(vp, uiop, cred, procp)
+nfs_readdirrpc(vp, uiop, cred)
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
        register struct vnode *vp;
        struct uio *uiop;
        struct ucred *cred;
-       struct proc *procp;
 {
        register long len;
        register struct direct *dp;
 {
        register long len;
        register struct direct *dp;
-       register u_long *p;
+       register u_long *tl;
        register caddr_t cp;
        register long t1;
        long tlen, lastlen;
        register caddr_t cp;
        register long t1;
        long tlen, lastlen;
@@ -1259,21 +1260,21 @@ nfs_readdirrpc(vp, uiop, cred, procp)
        tresid = uiop->uio_resid;
        /*
         * Loop around doing readdir rpc's of size uio_resid or nm_rsize,
        tresid = uiop->uio_resid;
        /*
         * Loop around doing readdir rpc's of size uio_resid or nm_rsize,
-        * whichever is smaller, truncated to a multiple of DIRBLKSIZ.
+        * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ.
         * The stopping criteria is EOF or buffer full.
         */
         * The stopping criteria is EOF or buffer full.
         */
-       while (more_dirs && uiop->uio_resid >= DIRBLKSIZ) {
+       while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
                nfsstats.rpccnt[NFSPROC_READDIR]++;
                nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid);
                nfsm_fhtom(vp);
                nfsstats.rpccnt[NFSPROC_READDIR]++;
                nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid);
                nfsm_fhtom(vp);
-               nfsm_build(p, u_long *, 2*NFSX_UNSIGNED);
-               *p++ = txdr_unsigned(uiop->uio_offset);
-               *p = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
-                       nmp->nm_rsize : uiop->uio_resid) & ~(DIRBLKSIZ-1));
-               nfsm_request(vp, NFSPROC_READDIR, procp, 0);
+               nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+               *tl++ = txdr_unsigned(uiop->uio_offset);
+               *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, 0);
                siz = 0;
                siz = 0;
-               nfsm_disect(p, u_long *, NFSX_UNSIGNED);
-               more_dirs = fxdr_unsigned(int, *p);
+               nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
+               more_dirs = fxdr_unsigned(int, *tl);
        
                /* Save the position so that we can do nfsm_mtouio() later */
                dpos2 = dpos;
        
                /* Save the position so that we can do nfsm_mtouio() later */
                dpos2 = dpos;
@@ -1287,10 +1288,10 @@ nfs_readdirrpc(vp, uiop, cred, procp)
                while (more_dirs && siz < uiop->uio_resid) {
                        savoff = off;           /* Hold onto offset and dp */
                        savdp = dp;
                while (more_dirs && siz < uiop->uio_resid) {
                        savoff = off;           /* Hold onto offset and dp */
                        savdp = dp;
-                       nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED);
-                       dp = (struct direct *)p;
-                       dp->d_ino = fxdr_unsigned(u_long, *p++);
-                       len = fxdr_unsigned(int, *p);
+                       nfsm_disecton(tl, u_long *, 2*NFSX_UNSIGNED);
+                       dp = (struct direct *)tl;
+                       dp->d_ino = fxdr_unsigned(u_long, *tl++);
+                       len = fxdr_unsigned(int, *tl);
                        if (len <= 0 || len > NFS_MAXNAMLEN) {
                                error = EBADRPC;
                                m_freem(mrep);
                        if (len <= 0 || len > NFS_MAXNAMLEN) {
                                error = EBADRPC;
                                m_freem(mrep);
@@ -1308,10 +1309,10 @@ nfs_readdirrpc(vp, uiop, cred, procp)
                                nfsm_adv(tlen - len);
                                len = tlen;
                        }
                                nfsm_adv(tlen - len);
                                len = tlen;
                        }
-                       nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED);
-                       off = fxdr_unsigned(off_t, *p);
-                       *p++ = 0;       /* Ensures null termination of name */
-                       more_dirs = fxdr_unsigned(int, *p);
+                       nfsm_disecton(tl, u_long *, 2*NFSX_UNSIGNED);
+                       off = fxdr_unsigned(off_t, *tl);
+                       *tl++ = 0;      /* Ensures null termination of name */
+                       more_dirs = fxdr_unsigned(int, *tl);
                        dp->d_reclen = len+4*NFSX_UNSIGNED;
                        siz += dp->d_reclen;
                }
                        dp->d_reclen = len+4*NFSX_UNSIGNED;
                        siz += dp->d_reclen;
                }
@@ -1319,8 +1320,8 @@ nfs_readdirrpc(vp, uiop, cred, procp)
                 * If at end of rpc data, get the eof boolean
                 */
                if (!more_dirs) {
                 * If at end of rpc data, get the eof boolean
                 */
                if (!more_dirs) {
-                       nfsm_disecton(p, u_long *, NFSX_UNSIGNED);
-                       more_dirs = (fxdr_unsigned(int, *p) == 0);
+                       nfsm_disecton(tl, u_long *, NFSX_UNSIGNED);
+                       more_dirs = (fxdr_unsigned(int, *tl) == 0);
 
                        /*
                         * If at EOF, cache directory offset
 
                        /*
                         * If at EOF, cache directory offset
@@ -1350,11 +1351,11 @@ nfs_readdirrpc(vp, uiop, cred, procp)
                m_freem(mrep);
        }
        /*
                m_freem(mrep);
        }
        /*
-        * Fill last record, iff any, out to a multiple of DIRBLKSIZ
+        * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
         * by increasing d_reclen for the last record.
         */
        if (uiop->uio_resid < tresid) {
         * by increasing d_reclen for the last record.
         */
        if (uiop->uio_resid < tresid) {
-               len = uiop->uio_resid & (DIRBLKSIZ - 1);
+               len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);
                if (len > 0) {
                        dp = (struct direct *)
                                (uiop->uio_iov->iov_base - lastlen);
                if (len > 0) {
                        dp = (struct direct *)
                                (uiop->uio_iov->iov_base - lastlen);
@@ -1378,51 +1379,51 @@ static char hextoasc[] = "0123456789abcdef";
  * to create the same funny name between the nfs_lookitup() fails and the
  * nfs_rename() completes, but...
  */
  * to create the same funny name between the nfs_lookitup() fails and the
  * nfs_rename() completes, but...
  */
-nfs_sillyrename(ndp, flag)
+nfs_sillyrename(ndp, p)
        register struct nameidata *ndp;
        register struct nameidata *ndp;
-       int flag;
+       struct proc *p;
 {
        register struct nfsnode *np;
        register struct sillyrename *sp;
 {
        register struct nfsnode *np;
        register struct sillyrename *sp;
-       register struct nameidata *tndp;
        int error;
        short pid;
 
        np = VTONFS(ndp->ni_dvp);
        cache_purge(ndp->ni_dvp);
        MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
        int error;
        short pid;
 
        np = VTONFS(ndp->ni_dvp);
        cache_purge(ndp->ni_dvp);
        MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
-               M_TEMP, M_WAITOK);
-       sp->s_flag = flag;
+               M_NFSREQ, M_WAITOK);
        bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH);
        np = VTONFS(ndp->ni_vp);
        bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH);
        np = VTONFS(ndp->ni_vp);
-       tndp = &sp->s_namei;
-       tndp->ni_cred = crdup(ndp->ni_cred);
+       sp->s_cred = crdup(ndp->ni_cred);
+       sp->s_dvp = ndp->ni_dvp;
+       VREF(sp->s_dvp);
 
        /* Fudge together a funny name */
 
        /* Fudge together a funny name */
-       pid = u.u_procp->p_pid;
-       bcopy(".nfsAxxxx4.4", tndp->ni_dent.d_name, 13);
-       tndp->ni_dent.d_namlen = 12;
-       tndp->ni_dent.d_name[8] = hextoasc[pid & 0xf];
-       tndp->ni_dent.d_name[7] = hextoasc[(pid >> 4) & 0xf];
-       tndp->ni_dent.d_name[6] = hextoasc[(pid >> 8) & 0xf];
-       tndp->ni_dent.d_name[5] = hextoasc[(pid >> 12) & 0xf];
+       pid = p->p_pid;
+       bcopy(".nfsAxxxx4.4", sp->s_name, 13);
+       sp->s_namlen = 12;
+       sp->s_name[8] = hextoasc[pid & 0xf];
+       sp->s_name[7] = hextoasc[(pid >> 4) & 0xf];
+       sp->s_name[6] = hextoasc[(pid >> 8) & 0xf];
+       sp->s_name[5] = hextoasc[(pid >> 12) & 0xf];
 
        /* Try lookitups until we get one that isn't there */
 
        /* Try lookitups until we get one that isn't there */
-       while (nfs_lookitup(ndp->ni_dvp, tndp, (nfsv2fh_t *)0) == 0) {
-               tndp->ni_dent.d_name[4]++;
-               if (tndp->ni_dent.d_name[4] > 'z') {
+       while (nfs_lookitup(sp, (nfsv2fh_t *)0, p) == 0) {
+               sp->s_name[4]++;
+               if (sp->s_name[4] > 'z') {
                        error = EINVAL;
                        goto bad;
                }
        }
                        error = EINVAL;
                        goto bad;
                }
        }
-       if (error = nfs_renameit(ndp, tndp))
+       if (error = nfs_renameit(ndp, sp, p))
                goto bad;
                goto bad;
-       nfs_lookitup(ndp->ni_dvp, tndp, &np->n_fh);
+       nfs_lookitup(sp, &np->n_fh, p);
        np->n_sillyrename = sp;
        return (0);
 bad:
        np->n_sillyrename = sp;
        return (0);
 bad:
-       crfree(tndp->ni_cred);
-       free((caddr_t)sp, M_TEMP);
+       vrele(sp->s_dvp);
+       crfree(sp->s_cred);
+       free((caddr_t)sp, M_NFSREQ);
        return (error);
 }
 
        return (error);
 }
 
@@ -1432,12 +1433,13 @@ bad:
  * into the nfsnode table.
  * If fhp != NULL it copies the returned file handle out
  */
  * into the nfsnode table.
  * If fhp != NULL it copies the returned file handle out
  */
-nfs_lookitup(vp, ndp, fhp)
-       register struct vnode *vp;
-       register struct nameidata *ndp;
+nfs_lookitup(sp, fhp, p)
+       register struct sillyrename *sp;
        nfsv2fh_t *fhp;
        nfsv2fh_t *fhp;
+       struct proc *p;
 {
 {
-       register u_long *p;
+       register struct vnode *vp = sp->s_dvp;
+       register u_long *tl;
        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;
@@ -1447,13 +1449,11 @@ nfs_lookitup(vp, ndp, fhp)
        long len;
 
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
        long len;
 
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
-       ndp->ni_dvp = vp;
-       ndp->ni_vp = NULL;
-       len = ndp->ni_dent.d_namlen;
-       nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
+       len = sp->s_namlen;
+       nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], sp->s_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
        nfsm_fhtom(vp);
        nfsm_fhtom(vp);
-       nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
-       nfsm_request(vp, NFSPROC_LOOKUP, u.u_procp, 1);
+       nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN);
+       nfsm_request(vp, NFSPROC_LOOKUP, p, 1);
        if (fhp != NULL) {
                nfsm_disect(cp, caddr_t, NFSX_FH);
                bcopy(cp, (caddr_t)fhp, NFSX_FH);
        if (fhp != NULL) {
                nfsm_disect(cp, caddr_t, NFSX_FH);
                bcopy(cp, (caddr_t)fhp, NFSX_FH);
@@ -1496,36 +1496,30 @@ nfs_strategy(bp)
 {
        register struct buf *dp;
        register int i;
 {
        register struct buf *dp;
        register int i;
-       struct proc *rp;
        int error = 0;
        int fnd = 0;
 
        /*
         * Set b_proc. It seems a bit silly to do it here, but since bread()
         * doesn't set it, I will.
        int error = 0;
        int fnd = 0;
 
        /*
         * Set b_proc. It seems a bit silly to do it here, but since bread()
         * doesn't set it, I will.
-        * Set b_proc == NULL for asynchronous reads, since these may still
+        * Set b_proc == NULL for asynchronous ops, since these may still
         * be hanging about after the process terminates.
         */
         * be hanging about after the process terminates.
         */
-       if ((bp->b_flags & (B_READ | B_ASYNC)) == (B_READ | B_ASYNC))
-               bp->b_proc = (struct proc *)0;
-       else
-               bp->b_proc = u.u_procp;
-
+       if ((bp->b_flags & B_PHYS) == 0) {
+               if (bp->b_flags & B_ASYNC)
+                       bp->b_proc = (struct proc *)0;
+               else
+                       bp->b_proc = curproc;
+       }
        /*
        /*
-        * If an i/o daemon is waiting
+        * If the op is asynchronous and an i/o daemon is waiting
         * queue the request, wake it up and wait for completion
         * queue the request, wake it up and wait for completion
-        * otherwise just do it ourselves
+        * otherwise just do it ourselves.
         */
         */
-       for (i = 0; i < nfs_asyncdaemons; i++) {
-               if (rp = nfs_iodwant[i]) {
-                       /*
-                        * Ensure that the async_daemon is still waiting here
-                        */
-                       if (rp->p_stat != SSLEEP ||
-                           rp->p_wchan != ((caddr_t)&nfs_iodwant[i])) {
-                               nfs_iodwant[i] = (struct proc *)0;
-                               continue;
-                       }
+       if ((bp->b_flags & B_ASYNC) == 0 || nfs_numasync == 0)
+               return (nfs_doio(bp));
+       for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
+               if (nfs_iodwant[i]) {
                        dp = &nfs_bqueue;
                        if (dp->b_actf == NULL) {
                                dp->b_actl = bp;
                        dp = &nfs_bqueue;
                        if (dp->b_actf == NULL) {
                                dp->b_actl = bp;
@@ -1537,7 +1531,6 @@ nfs_strategy(bp)
                        dp->b_actf = bp;
                        bp->b_actl = dp;
                        fnd++;
                        dp->b_actf = bp;
                        bp->b_actl = dp;
                        fnd++;
-                       nfs_iodwant[i] = (struct proc *)0;
                        wakeup((caddr_t)&nfs_iodwant[i]);
                        break;
                }
                        wakeup((caddr_t)&nfs_iodwant[i]);
                        break;
                }
@@ -1563,7 +1556,6 @@ nfs_doio(bp)
        register struct vnode *vp;
        struct nfsnode *np;
        struct ucred *cr;
        register struct vnode *vp;
        struct nfsnode *np;
        struct ucred *cr;
-       struct proc *rp;
        int error;
        struct uio uio;
        struct iovec io;
        int error;
        struct uio uio;
        struct iovec io;
@@ -1582,6 +1574,7 @@ nfs_doio(bp)
        uiop->uio_iov = &io;
        uiop->uio_iovcnt = 1;
        uiop->uio_segflg = UIO_SYSSPACE;
        uiop->uio_iov = &io;
        uiop->uio_iovcnt = 1;
        uiop->uio_segflg = UIO_SYSSPACE;
+       uiop->uio_procp = (struct proc *)0;
 
        /*
         * For phys i/o, map the b_addr into kernel virtual space using
 
        /*
         * For phys i/o, map the b_addr into kernel virtual space using
@@ -1590,11 +1583,9 @@ nfs_doio(bp)
         * and a guess at a group
         */
        if (bp->b_flags & B_PHYS) {
         * and a guess at a group
         */
        if (bp->b_flags & B_PHYS) {
-               bp->b_rcred = cr = crget();
-               rp = (bp->b_flags & B_DIRTY) ? &proc[2] : bp->b_proc;
-               cr->cr_uid = rp->p_uid;
-               cr->cr_gid = 0;         /* Anything ?? */
-               cr->cr_ngroups = 1;
+               if (bp->b_flags & B_DIRTY)
+                       uiop->uio_procp = pageproc;
+               cr = crcopy(uiop->uio_procp->p_ucred);
 #if defined(hp300) || defined(i386)
                /* mapping was already done by vmapbuf */
                io.iov_base = bp->b_un.b_addr;
 #if defined(hp300) || defined(i386)
                /* mapping was already done by vmapbuf */
                io.iov_base = bp->b_un.b_addr;
@@ -1616,9 +1607,9 @@ nfs_doio(bp)
                else {
                        v = btop(bp->b_un.b_addr);
                        if (bp->b_flags & B_UAREA)
                else {
                        v = btop(bp->b_un.b_addr);
                        if (bp->b_flags & B_UAREA)
-                               pte = &rp->p_addr[v];
+                               pte = &uiop->uio_procp->p_addr[v];
                        else
                        else
-                               pte = vtopte(rp, v);
+                               pte = vtopte(uiop->uio_procp, v);
                }
 
                /*
                }
 
                /*
@@ -1647,22 +1638,12 @@ nfs_doio(bp)
                if (bp->b_flags & B_READ) {
                        uiop->uio_rw = UIO_READ;
                        nfsstats.read_physios++;
                if (bp->b_flags & B_READ) {
                        uiop->uio_rw = UIO_READ;
                        nfsstats.read_physios++;
-                       bp->b_error = error = nfs_readrpc(vp, uiop,
-                               bp->b_rcred, bp->b_proc);
-                       /*
-                        * If a text file has been modified since it was exec'd
-                        * blow the process' out of the water. This is the
-                        * closest we can come to "Text File Busy" in good old
-                        * stateless nfs.
-                        */
-                       if ((vp->v_flag & VTEXT) &&
-                           (vp->v_text->x_mtime != np->n_vattr.va_mtime.tv_sec))
-                               xinval(vp);
+                       bp->b_error = error = nfs_readrpc(vp, uiop, cr);
+                       (void) vnode_pager_uncache(vp);
                } 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,
-                               bp->b_wcred, bp->b_proc);
+                       bp->b_error = error = nfs_writerpc(vp, uiop, cr);
                }
 
                /*
                }
 
                /*
@@ -1685,20 +1666,17 @@ nfs_doio(bp)
                        case VREG:
                                uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
                                nfsstats.read_bios++;
                        case VREG:
                                uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
                                nfsstats.read_bios++;
-                               error = nfs_readrpc(vp, uiop, bp->b_rcred,
-                                       bp->b_proc);
+                               error = nfs_readrpc(vp, uiop, bp->b_rcred);
                                break;
                        case VLNK:
                                uiop->uio_offset = 0;
                                nfsstats.readlink_bios++;
                                break;
                        case VLNK:
                                uiop->uio_offset = 0;
                                nfsstats.readlink_bios++;
-                               error = nfs_readlinkrpc(vp, uiop, bp->b_rcred,
-                                               bp->b_proc);
+                               error = nfs_readlinkrpc(vp, uiop, bp->b_rcred);
                                break;
                        case VDIR:
                                uiop->uio_offset = bp->b_lblkno;
                                nfsstats.readdir_bios++;
                                break;
                        case VDIR:
                                uiop->uio_offset = bp->b_lblkno;
                                nfsstats.readdir_bios++;
-                               error = nfs_readdirrpc(vp, uiop, bp->b_rcred,
-                                           bp->b_proc);
+                               error = nfs_readdirrpc(vp, uiop, bp->b_rcred);
                                /*
                                 * Save offset cookie in b_blkno.
                                 */
                                /*
                                 * Save offset cookie in b_blkno.
                                 */
@@ -1715,7 +1693,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_proc);
+                               bp->b_wcred);
                        if (error) {
                                np->n_error = error;
                                np->n_flag |= NWRITEERR;
                        if (error) {
                                np->n_error = error;
                                np->n_flag |= NWRITEERR;
@@ -1730,17 +1708,34 @@ nfs_doio(bp)
        return (error);
 }
 
        return (error);
 }
 
+/*
+ * Mmap a file
+ *
+ * NB Currently unsupported.
+ */
+/* ARGSUSED */
+nfs_mmap(vp, fflags, cred, p)
+       struct vnode *vp;
+       int fflags;
+       struct ucred *cred;
+       struct proc *p;
+{
+
+       return (EINVAL);
+}
+
 /*
  * Flush all the blocks associated with a vnode.
  *     Walk through the buffer pool and push any dirty pages
  *     associated with the vnode.
  */
 /* ARGSUSED */
 /*
  * Flush all the blocks associated with a vnode.
  *     Walk through the buffer pool and push any dirty pages
  *     associated with the vnode.
  */
 /* ARGSUSED */
-nfs_fsync(vp, fflags, cred, waitfor)
+nfs_fsync(vp, fflags, cred, waitfor, p)
        register struct vnode *vp;
        int fflags;
        struct ucred *cred;
        int waitfor;
        register struct vnode *vp;
        int fflags;
        struct ucred *cred;
        int waitfor;
+       struct proc *p;
 {
        register struct nfsnode *np = VTONFS(vp);
        int error = 0;
 {
        register struct nfsnode *np = VTONFS(vp);
        int error = 0;
@@ -1754,6 +1749,21 @@ nfs_fsync(vp, fflags, cred, waitfor)
        return (error);
 }
 
        return (error);
 }
 
+/*
+ * NFS advisory byte-level locks.
+ * Currently unsupported.
+ */
+nfs_advlock(vp, id, op, fl, flags)
+       struct vnode *vp;
+       caddr_t id;
+       int op;
+       struct flock *fl;
+       int flags;
+{
+
+       return (EOPNOTSUPP);
+}
+
 /*
  * Print out the contents of an nfsnode.
  */
 /*
  * Print out the contents of an nfsnode.
  */