BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / nfs / nfs_serv.c
index a9d58ce..a83dfe9 100644 (file)
@@ -5,22 +5,35 @@
  * 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_serv.c  7.27 (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_serv.c  7.40 (Berkeley) 5/15/91
  */
 
 /*
  */
 
 /*
  */
 
 #include "param.h"
  */
 
 #include "param.h"
-#include "user.h"
+#include "proc.h"
 #include "file.h"
 #include "file.h"
+#include "namei.h"
 #include "vnode.h"
 #include "mount.h"
 #include "mbuf.h"
 #include "vnode.h"
 #include "mount.h"
 #include "mbuf.h"
-#include "errno.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 "xdr_subs.h"
 #include "nfsv2.h"
 #include "nfs.h"
 #include "xdr_subs.h"
@@ -69,13 +85,14 @@ nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
 /*
  * nfs getattr service
  */
 /*
  * nfs getattr service
  */
-nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        register struct nfsv2_fattr *fp;
        struct vattr va;
 {
        register struct nfsv2_fattr *fp;
        struct vattr va;
@@ -83,7 +100,7 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat)
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -94,7 +111,7 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat)
        nfsm_srvmtofh(fhp);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        nfsm_srvmtofh(fhp);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       error = VOP_GETATTR(vp, vap, cred);
+       error = VOP_GETATTR(vp, vap, cred, p);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
@@ -105,13 +122,14 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat)
 /*
  * nfs setattr service
  */
 /*
  * nfs setattr service
  */
-nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        struct vattr va;
        register struct vattr *vap = &va;
 {
        struct vattr va;
        register struct vattr *vap = &va;
@@ -120,7 +138,7 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat)
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -132,7 +150,7 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat)
        nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if (error = nfsrv_access(vp, VWRITE, cred))
+       if (error = nfsrv_access(vp, VWRITE, cred, p))
                goto out;
        VATTR_NULL(vap);
        /*
                goto out;
        VATTR_NULL(vap);
        /*
@@ -163,11 +181,11 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat)
                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);
                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)) {
+       if (error = VOP_SETATTR(vp, vap, cred, p)) {
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
-       error = VOP_GETATTR(vp, vap, cred);
+       error = VOP_GETATTR(vp, vap, cred, p);
 out:
        vput(vp);
        nfsm_reply(NFSX_FATTR);
 out:
        vput(vp);
        nfsm_reply(NFSX_FATTR);
@@ -179,22 +197,22 @@ out:
 /*
  * nfs lookup rpc
  */
 /*
  * nfs lookup rpc
  */
-nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        register struct nfsv2_fattr *fp;
 {
        register struct nfsv2_fattr *fp;
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
+       struct nameidata nd;
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        register caddr_t cp;
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        register caddr_t cp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -203,22 +221,21 @@ nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat)
        long len;
        struct vattr va, *vap = &va;
 
        long len;
        struct vattr va, *vap = &va;
 
-       ndinit(ndp);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = LOOKUP | LOCKLEAF;
-       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = LOOKUP | LOCKLEAF;
+       if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
                nfsm_reply(0);
                nfsm_reply(0);
-       vp = ndp->ni_vp;
+       vp = nd.ni_vp;
        bzero((caddr_t)fhp, sizeof(nfh));
        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
                vput(vp);
                nfsm_reply(0);
        }
        bzero((caddr_t)fhp, sizeof(nfh));
        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
                vput(vp);
                nfsm_reply(0);
        }
-       error = VOP_GETATTR(vp, vap, cred);
+       error = VOP_GETATTR(vp, vap, cred, p);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
@@ -230,18 +247,19 @@ nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat)
 /*
  * nfs readlink service
  */
 /*
  * nfs readlink service
  */
-nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
        register struct iovec *ivp = iv;
        register struct mbuf *mp;
 {
        struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
        register struct iovec *ivp = iv;
        register struct mbuf *mp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -283,6 +301,7 @@ nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat)
        uiop->uio_resid = len;
        uiop->uio_rw = UIO_READ;
        uiop->uio_segflg = UIO_SYSSPACE;
        uiop->uio_resid = len;
        uiop->uio_rw = UIO_READ;
        uiop->uio_segflg = UIO_SYSSPACE;
+       uiop->uio_procp = (struct proc *)0;
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) {
                m_freem(mp3);
                nfsm_reply(0);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) {
                m_freem(mp3);
                nfsm_reply(0);
@@ -302,8 +321,8 @@ out:
                tlen = nfsm_rndup(len);
                nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
        }
                tlen = nfsm_rndup(len);
                nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
        }
-       nfsm_build(p, u_long *, NFSX_UNSIGNED);
-       *p = txdr_unsigned(len);
+       nfsm_build(tl, u_long *, NFSX_UNSIGNED);
+       *tl = txdr_unsigned(len);
        mb->m_next = mp3;
        nfsm_srvdone;
 }
        mb->m_next = mp3;
        nfsm_srvdone;
 }
@@ -311,19 +330,20 @@ out:
 /*
  * nfs read service
  */
 /*
  * nfs read service
  */
-nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        register struct iovec *iv;
        struct iovec *iv2;
        register struct mbuf *m;
        register struct nfsv2_fattr *fp;
 {
        register struct iovec *iv;
        struct iovec *iv2;
        register struct mbuf *m;
        register struct nfsv2_fattr *fp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -340,12 +360,12 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_disect(p, u_long *, NFSX_UNSIGNED);
-       off = fxdr_unsigned(off_t, *p);
+       nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
+       off = fxdr_unsigned(off_t, *tl);
        nfsm_srvstrsiz(cnt, NFS_MAXDATA);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        nfsm_srvstrsiz(cnt, NFS_MAXDATA);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if (error = nfsrv_access(vp, VREAD | VEXEC, cred)) {
+       if (error = nfsrv_access(vp, VREAD | VEXEC, cred, p)) {
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
@@ -386,6 +406,7 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat)
        uiop->uio_resid = cnt;
        uiop->uio_rw = UIO_READ;
        uiop->uio_segflg = UIO_SYSSPACE;
        uiop->uio_resid = cnt;
        uiop->uio_rw = UIO_READ;
        uiop->uio_segflg = UIO_SYSSPACE;
+       uiop->uio_procp = (struct proc *)0;
        error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
        off = uiop->uio_offset;
        FREE((caddr_t)iv2, M_TEMP);
        error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
        off = uiop->uio_offset;
        FREE((caddr_t)iv2, M_TEMP);
@@ -394,24 +415,23 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat)
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
-       if (error = VOP_GETATTR(vp, vap, cred))
+       if (error = VOP_GETATTR(vp, vap, cred, p))
                m_freem(m3);
        vput(vp);
        nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        nfsm_srvfillattr;
                m_freem(m3);
        vput(vp);
        nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        nfsm_srvfillattr;
-       if (uiop->uio_resid > 0) {
-               len -= uiop->uio_resid;
-               if (len > 0) {
-                       tlen = nfsm_rndup(len);
+       len -= uiop->uio_resid;
+       if (len > 0) {
+               tlen = nfsm_rndup(len);
+               if (cnt != tlen || tlen != len)
                        nfsm_adj(m3, cnt-tlen, tlen-len);
                        nfsm_adj(m3, cnt-tlen, tlen-len);
-               } else {
-                       m_freem(m3);
-                       m3 = (struct mbuf *)0;
-               }
+       } else {
+               m_freem(m3);
+               m3 = (struct mbuf *)0;
        }
        }
-       nfsm_build(p, u_long *, NFSX_UNSIGNED);
-       *p = txdr_unsigned(len);
+       nfsm_build(tl, u_long *, NFSX_UNSIGNED);
+       *tl = txdr_unsigned(len);
        mb->m_next = m3;
        nfsm_srvdone;
 }
        mb->m_next = m3;
        nfsm_srvdone;
 }
@@ -419,12 +439,13 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat)
 /*
  * nfs write service
  */
 /*
  * nfs write service
  */
-nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        register struct iovec *ivp;
        register struct mbuf *mp;
 {
        register struct iovec *ivp;
        register struct mbuf *mp;
@@ -432,7 +453,7 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat)
        struct iovec iv[NFS_MAXIOVEC];
        struct vattr va;
        register struct vattr *vap = &va;
        struct iovec iv[NFS_MAXIOVEC];
        struct vattr va;
        register struct vattr *vap = &va;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -447,10 +468,10 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_disect(p, u_long *, 4*NFSX_UNSIGNED);
-       off = fxdr_unsigned(off_t, *++p);
-       p += 2;
-       len = fxdr_unsigned(long, *p);
+       nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED);
+       off = fxdr_unsigned(off_t, *++tl);
+       tl += 2;
+       len = fxdr_unsigned(long, *tl);
        if (len > NFS_MAXDATA || len <= 0) {
                error = EBADRPC;
                nfsm_reply(0);
        if (len > NFS_MAXDATA || len <= 0) {
                error = EBADRPC;
                nfsm_reply(0);
@@ -469,13 +490,14 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat)
        }
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        }
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if (error = nfsrv_access(vp, VWRITE, cred)) {
+       if (error = nfsrv_access(vp, VWRITE, cred, p)) {
                vput(vp);
                nfsm_reply(0);
        }
        uiop->uio_resid = 0;
        uiop->uio_rw = UIO_WRITE;
        uiop->uio_segflg = UIO_SYSSPACE;
                vput(vp);
                nfsm_reply(0);
        }
        uiop->uio_resid = 0;
        uiop->uio_rw = UIO_WRITE;
        uiop->uio_segflg = UIO_SYSSPACE;
+       uiop->uio_procp = (struct proc *)0;
        /*
         * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
         * loop until done.
        /*
         * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
         * loop until done.
@@ -518,7 +540,7 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat)
                }
                off = uiop->uio_offset;
        }
                }
                off = uiop->uio_offset;
        }
-       error = VOP_GETATTR(vp, vap, cred);
+       error = VOP_GETATTR(vp, vap, cred, p);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
@@ -530,20 +552,20 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat)
  * nfs create service
  * now does a truncate to 0 length via. setattr if it already exists
  */
  * nfs create service
  * now does a truncate to 0 length via. setattr if it already exists
  */
-nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        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;
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
+       struct nameidata nd;
        register caddr_t cp;
        register caddr_t cp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        long rdev;
        register long t1;
        caddr_t bpos;
        long rdev;
@@ -555,69 +577,85 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat)
        fhandle_t *fhp;
        long len;
 
        fhandle_t *fhp;
        long len;
 
-       ndinit(ndp);
+       nd.ni_nameiop = 0;
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF;
-       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART;
+       if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
                nfsm_reply(0);
        VATTR_NULL(vap);
                nfsm_reply(0);
        VATTR_NULL(vap);
-       nfsm_disect(p, u_long *, NFSX_SATTR);
+       nfsm_disect(tl, u_long *, NFSX_SATTR);
        /*
         * Iff doesn't exist, create it
         * otherwise just truncate to 0 length
         *   should I set the mode too ??
         */
        /*
         * Iff doesn't exist, create it
         * otherwise just truncate to 0 length
         *   should I set the mode too ??
         */
-       if (ndp->ni_vp == NULL) {
-               vap->va_type = IFTOVT(fxdr_unsigned(u_long, *p));
+       if (nd.ni_vp == NULL) {
+               vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl));
                if (vap->va_type == VNON)
                        vap->va_type = VREG;
                if (vap->va_type == VNON)
                        vap->va_type = VREG;
-               vap->va_mode = nfstov_mode(*p);
-               rdev = fxdr_unsigned(long, *(p+3));
-               if (vap->va_type == VREG) {
-                       if (error = VOP_CREATE(ndp, vap))
+               vap->va_mode = nfstov_mode(*tl);
+               rdev = fxdr_unsigned(long, *(tl+3));
+               if (vap->va_type == VREG || vap->va_type == VSOCK) {
+                       vrele(nd.ni_startdir);
+                       if (error = VOP_CREATE(&nd, vap, p))
                                nfsm_reply(0);
                                nfsm_reply(0);
+                       FREE(nd.ni_pnbuf, M_NAMEI);
                } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
                        vap->va_type == VFIFO) {
                        if (vap->va_type == VCHR && rdev == 0xffffffff)
                                vap->va_type = VFIFO;
                        if (vap->va_type == VFIFO) {
 #ifndef FIFO
                } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
                        vap->va_type == VFIFO) {
                        if (vap->va_type == VCHR && rdev == 0xffffffff)
                                vap->va_type = VFIFO;
                        if (vap->va_type == VFIFO) {
 #ifndef FIFO
-                               VOP_ABORTOP(ndp);
-                               vput(ndp->ni_dvp);
+                               VOP_ABORTOP(&nd);
+                               vput(nd.ni_dvp);
                                error = ENXIO;
                                error = ENXIO;
-                               nfsm_reply(0);
+                               goto out;
 #endif /* FIFO */
                        } else if (error = suser(cred, (short *)0)) {
 #endif /* FIFO */
                        } else if (error = suser(cred, (short *)0)) {
-                               VOP_ABORTOP(ndp);
-                               vput(ndp->ni_dvp);
-                               nfsm_reply(0);
+                               VOP_ABORTOP(&nd);
+                               vput(nd.ni_dvp);
+                               goto out;
                        } else
                                vap->va_rdev = (dev_t)rdev;
                        } else
                                vap->va_rdev = (dev_t)rdev;
-                       if (error = VOP_MKNOD(ndp, vap, cred))
+                       if (error = VOP_MKNOD(&nd, vap, cred, p)) {
+                               vrele(nd.ni_startdir);
+                               nfsm_reply(0);
+                       }
+                       nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART);
+                       nd.ni_nameiop |= LOOKUP;
+                       if (error = lookup(&nd, p)) {
+                               free(nd.ni_pnbuf, M_NAMEI);
                                nfsm_reply(0);
                                nfsm_reply(0);
-                       ndp->ni_nameiop = LOOKUP | LOCKLEAF | HASBUF;
-                       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+                       }
+                       FREE(nd.ni_pnbuf, M_NAMEI);
+                       if (nd.ni_more) {
+                               vrele(nd.ni_dvp);
+                               vput(nd.ni_vp);
+                               VOP_ABORTOP(&nd);
+                               error = EINVAL;
                                nfsm_reply(0);
                                nfsm_reply(0);
+                       }
                } else {
                } else {
-                       VOP_ABORTOP(ndp);
-                       vput(ndp->ni_dvp);
+                       VOP_ABORTOP(&nd);
+                       vput(nd.ni_dvp);
                        error = ENXIO;
                        error = ENXIO;
-                       nfsm_reply(0);
+                       goto out;
                }
                }
-               vp = ndp->ni_vp;
+               vp = nd.ni_vp;
        } else {
        } else {
-               vp = ndp->ni_vp;
-               ndp->ni_vp = NULLVP;
-               VOP_ABORTOP(ndp);
-               if (ndp->ni_dvp == vp)
-                       vrele(ndp->ni_dvp);
+               vrele(nd.ni_startdir);
+               free(nd.ni_pnbuf, M_NAMEI);
+               vp = nd.ni_vp;
+               if (nd.ni_dvp == vp)
+                       vrele(nd.ni_dvp);
                else
                else
-                       vput(ndp->ni_dvp);
+                       vput(nd.ni_dvp);
+               VOP_ABORTOP(&nd);
                vap->va_size = 0;
                vap->va_size = 0;
-               if (error = VOP_SETATTR(vp, vap, cred)) {
+               if (error = VOP_SETATTR(vp, vap, cred, p)) {
                        vput(vp);
                        nfsm_reply(0);
                }
                        vput(vp);
                        nfsm_reply(0);
                }
@@ -628,7 +666,7 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat)
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
-       error = VOP_GETATTR(vp, vap, cred);
+       error = VOP_GETATTR(vp, vap, cred, p);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
@@ -636,29 +674,36 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat)
        nfsm_srvfillattr;
        return (error);
 nfsmout:
        nfsm_srvfillattr;
        return (error);
 nfsmout:
-       VOP_ABORTOP(ndp);
-       if (ndp->ni_dvp == ndp->ni_vp)
-               vrele(ndp->ni_dvp);
+       if (nd.ni_nameiop)
+               vrele(nd.ni_startdir);
+       VOP_ABORTOP(&nd);
+       if (nd.ni_dvp == nd.ni_vp)
+               vrele(nd.ni_dvp);
        else
        else
-               vput(ndp->ni_dvp);
-       if (ndp->ni_vp)
-               vput(ndp->ni_vp);
+               vput(nd.ni_dvp);
+       if (nd.ni_vp)
+               vput(nd.ni_vp);
        return (error);
        return (error);
+
+out:
+       vrele(nd.ni_startdir);
+       free(nd.ni_pnbuf, M_NAMEI);
+       nfsm_reply(0);
 }
 
 /*
  * nfs remove service
  */
 }
 
 /*
  * nfs remove service
  */
-nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
 {
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
-       register u_long *p;
+       struct nameidata nd;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -669,36 +714,35 @@ nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat)
        fhandle_t *fhp;
        long len;
 
        fhandle_t *fhp;
        long len;
 
-       ndinit(ndp);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
-       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
+       if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
                nfsm_reply(0);
                nfsm_reply(0);
-       vp = ndp->ni_vp;
+       vp = nd.ni_vp;
        if (vp->v_type == VDIR &&
                (error = suser(cred, (short *)0)))
                goto out;
        /*
        if (vp->v_type == VDIR &&
                (error = suser(cred, (short *)0)))
                goto out;
        /*
-        * Don't unlink a mounted file.
+        * The root of a mounted filesystem cannot be deleted.
         */
        if (vp->v_flag & VROOT) {
                error = EBUSY;
                goto out;
        }
        if (vp->v_flag & VTEXT)
         */
        if (vp->v_flag & VROOT) {
                error = EBUSY;
                goto out;
        }
        if (vp->v_flag & VTEXT)
-               xrele(vp);      /* try once to free text */
+               (void) vnode_pager_uncache(vp);
 out:
        if (!error) {
 out:
        if (!error) {
-               error = VOP_REMOVE(ndp);
+               error = VOP_REMOVE(&nd, p);
        } else {
        } else {
-               VOP_ABORTOP(ndp);
-               if (ndp->ni_dvp == vp)
-                       vrele(ndp->ni_dvp);
+               VOP_ABORTOP(&nd);
+               if (nd.ni_dvp == vp)
+                       vrele(nd.ni_dvp);
                else
                else
-                       vput(ndp->ni_dvp);
+                       vput(nd.ni_dvp);
                vput(vp);
        }
        nfsm_reply(0);
                vput(vp);
        }
        nfsm_reply(0);
@@ -708,31 +752,31 @@ out:
 /*
  * nfs rename service
  */
 /*
  * nfs rename service
  */
-nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
 {
-       register struct nameidata *ndp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        char *cp2;
        struct mbuf *mb, *mreq;
        register long t1;
        caddr_t bpos;
        int error = 0;
        char *cp2;
        struct mbuf *mb, *mreq;
-       struct nameidata nami, tond;
+       struct nameidata fromnd, tond;
        struct vnode *fvp, *tvp, *tdvp;
        nfsv2fh_t fnfh, tnfh;
        fhandle_t *ffhp, *tfhp;
        long len, len2;
        int rootflg = 0;
 
        struct vnode *fvp, *tvp, *tdvp;
        nfsv2fh_t fnfh, tnfh;
        fhandle_t *ffhp, *tfhp;
        long len, len2;
        int rootflg = 0;
 
-       ndp = &nami;
-       ndinit(ndp);
        ffhp = &fnfh.fh_generic;
        tfhp = &tnfh.fh_generic;
        ffhp = &fnfh.fh_generic;
        tfhp = &tnfh.fh_generic;
+       fromnd.ni_nameiop = 0;
+       tond.ni_nameiop = 0;
        nfsm_srvmtofh(ffhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        /*
        nfsm_srvmtofh(ffhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        /*
@@ -741,22 +785,21 @@ nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat)
         */
        if (cred->cr_uid == 0)
                rootflg++;
         */
        if (cred->cr_uid == 0)
                rootflg++;
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = DELETE | WANTPARENT;
-       if (error = nfs_namei(ndp, ffhp, len, &md, &dpos))
+       fromnd.ni_cred = cred;
+       fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
+       if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p))
                nfsm_reply(0);
                nfsm_reply(0);
-       fvp = ndp->ni_vp;
+       fvp = fromnd.ni_vp;
        nfsm_srvmtofh(tfhp);
        nfsm_strsiz(len2, NFS_MAXNAMLEN);
        if (rootflg)
                cred->cr_uid = 0;
        nfsm_srvmtofh(tfhp);
        nfsm_strsiz(len2, NFS_MAXNAMLEN);
        if (rootflg)
                cred->cr_uid = 0;
-       ndinit(&tond);
-       crhold(cred);
        tond.ni_cred = cred;
        tond.ni_cred = cred;
-       tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
-       if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos)) {
-               VOP_ABORTOP(ndp);
-               vrele(ndp->ni_dvp);
+       tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE
+               | SAVESTART;
+       if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) {
+               VOP_ABORTOP(&fromnd);
+               vrele(fromnd.ni_dvp);
                vrele(fvp);
                goto out1;
        }
                vrele(fvp);
                goto out1;
        }
@@ -775,15 +818,20 @@ nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat)
                error = EXDEV;
                goto out;
        }
                error = EXDEV;
                goto out;
        }
-       if (fvp == tdvp || fvp == tvp)
+       if (fvp == tdvp)
                error = EINVAL;
                error = EINVAL;
+       /*
+        * If source is the same as the destination (that is the
+        * same vnode with the same name in the same directory),
+        * then there is nothing to do.
+        */
+       if (fvp == tvp && fromnd.ni_dvp == tdvp &&
+           fromnd.ni_namelen == tond.ni_namelen &&
+           !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
+               error = -1;
 out:
        if (!error) {
 out:
        if (!error) {
-               VREF(ndp->ni_cdir);
-               VREF(tond.ni_cdir);
-               error = VOP_RENAME(ndp, &tond);
-               vrele(ndp->ni_cdir);
-               vrele(tond.ni_cdir);
+               error = VOP_RENAME(&fromnd, &tond, p);
        } else {
                VOP_ABORTOP(&tond);
                if (tdvp == tvp)
        } else {
                VOP_ABORTOP(&tond);
                if (tdvp == tvp)
@@ -792,34 +840,46 @@ out:
                        vput(tdvp);
                if (tvp)
                        vput(tvp);
                        vput(tdvp);
                if (tvp)
                        vput(tvp);
-               VOP_ABORTOP(ndp);
-               vrele(ndp->ni_dvp);
+               VOP_ABORTOP(&fromnd);
+               vrele(fromnd.ni_dvp);
                vrele(fvp);
        }
                vrele(fvp);
        }
+       vrele(tond.ni_startdir);
+       FREE(tond.ni_pnbuf, M_NAMEI);
 out1:
 out1:
-       crfree(cred);
+       vrele(fromnd.ni_startdir);
+       FREE(fromnd.ni_pnbuf, M_NAMEI);
        nfsm_reply(0);
        return (error);
        nfsm_reply(0);
        return (error);
+
 nfsmout:
 nfsmout:
-       VOP_ABORTOP(ndp);
-       vrele(ndp->ni_dvp);
-       vrele(fvp);
+       if (tond.ni_nameiop) {
+               vrele(tond.ni_startdir);
+               FREE(tond.ni_pnbuf, M_NAMEI);
+       }
+       if (fromnd.ni_nameiop) {
+               vrele(fromnd.ni_startdir);
+               FREE(fromnd.ni_pnbuf, M_NAMEI);
+               VOP_ABORTOP(&fromnd);
+               vrele(fromnd.ni_dvp);
+               vrele(fvp);
+       }
        return (error);
 }
 
 /*
  * nfs link service
  */
        return (error);
 }
 
 /*
  * nfs link service
  */
-nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
 {
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
-       register u_long *p;
+       struct nameidata nd;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -830,7 +890,6 @@ nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat)
        fhandle_t *fhp, *dfhp;
        long len;
 
        fhandle_t *fhp, *dfhp;
        long len;
 
-       ndinit(ndp);
        fhp = &nfh.fh_generic;
        dfhp = &dnfh.fh_generic;
        nfsm_srvmtofh(fhp);
        fhp = &nfh.fh_generic;
        dfhp = &dnfh.fh_generic;
        nfsm_srvmtofh(fhp);
@@ -840,29 +899,29 @@ nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat)
                nfsm_reply(0);
        if (vp->v_type == VDIR && (error = suser(cred, NULL)))
                goto out1;
                nfsm_reply(0);
        if (vp->v_type == VDIR && (error = suser(cred, NULL)))
                goto out1;
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = CREATE | LOCKPARENT;
-       if (error = nfs_namei(ndp, dfhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = CREATE | LOCKPARENT;
+       if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p))
                goto out1;
                goto out1;
-       xp = ndp->ni_vp;
+       xp = nd.ni_vp;
        if (xp != NULL) {
                error = EEXIST;
                goto out;
        }
        if (xp != NULL) {
                error = EEXIST;
                goto out;
        }
-       xp = ndp->ni_dvp;
+       xp = nd.ni_dvp;
        if (vp->v_mount != xp->v_mount)
                error = EXDEV;
 out:
        if (!error) {
        if (vp->v_mount != xp->v_mount)
                error = EXDEV;
 out:
        if (!error) {
-               error = VOP_LINK(vp, ndp);
+               error = VOP_LINK(vp, &nd, p);
        } else {
        } else {
-               VOP_ABORTOP(ndp);
-               if (ndp->ni_dvp == ndp->ni_vp)
-                       vrele(ndp->ni_dvp);
+               VOP_ABORTOP(&nd);
+               if (nd.ni_dvp == nd.ni_vp)
+                       vrele(nd.ni_dvp);
                else
                else
-                       vput(ndp->ni_dvp);
-               if (ndp->ni_vp)
-                       vrele(ndp->ni_vp);
+                       vput(nd.ni_dvp);
+               if (nd.ni_vp)
+                       vrele(nd.ni_vp);
        }
 out1:
        vrele(vp);
        }
 out1:
        vrele(vp);
@@ -873,19 +932,20 @@ out1:
 /*
  * nfs symbolic link service
  */
 /*
  * nfs symbolic link service
  */
-nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        struct vattr va;
 {
        struct vattr va;
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
+       struct nameidata nd;
        register struct vattr *vap = &va;
        register struct vattr *vap = &va;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        register long t1;
+       struct nfsv2_sattr *sp;
        caddr_t bpos;
        struct uio io;
        struct iovec iv;
        caddr_t bpos;
        struct uio io;
        struct iovec iv;
@@ -897,13 +957,12 @@ nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat)
        long len, len2;
 
        pathcp = (char *)0;
        long len, len2;
 
        pathcp = (char *)0;
-       ndinit(ndp);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = CREATE | LOCKPARENT;
-       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = CREATE | LOCKPARENT;
+       if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
                goto out;
        nfsm_strsiz(len2, NFS_MAXPATHLEN);
        MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
                goto out;
        nfsm_strsiz(len2, NFS_MAXPATHLEN);
        MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
@@ -915,34 +974,36 @@ nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat)
        io.uio_iovcnt = 1;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        io.uio_iovcnt = 1;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
+       io.uio_procp = (struct proc *)0;
        nfsm_mtouio(&io, len2);
        nfsm_mtouio(&io, len2);
+       nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
        *(pathcp + len2) = '\0';
        *(pathcp + len2) = '\0';
-       if (ndp->ni_vp) {
-               VOP_ABORTOP(ndp);
-               if (ndp->ni_dvp == ndp->ni_vp)
-                       vrele(ndp->ni_dvp);
+       if (nd.ni_vp) {
+               VOP_ABORTOP(&nd);
+               if (nd.ni_dvp == nd.ni_vp)
+                       vrele(nd.ni_dvp);
                else
                else
-                       vput(ndp->ni_dvp);
-               vrele(ndp->ni_vp);
+                       vput(nd.ni_dvp);
+               vrele(nd.ni_vp);
                error = EEXIST;
                goto out;
        }
        VATTR_NULL(vap);
                error = EEXIST;
                goto out;
        }
        VATTR_NULL(vap);
-       vap->va_mode = 0777;
-       error = VOP_SYMLINK(ndp, vap, pathcp);
+       vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
+       error = VOP_SYMLINK(&nd, vap, pathcp, p);
 out:
        if (pathcp)
                FREE(pathcp, M_TEMP);
        nfsm_reply(0);
        return (error);
 nfsmout:
 out:
        if (pathcp)
                FREE(pathcp, M_TEMP);
        nfsm_reply(0);
        return (error);
 nfsmout:
-       VOP_ABORTOP(ndp);
-       if (ndp->ni_dvp == ndp->ni_vp)
-               vrele(ndp->ni_dvp);
+       VOP_ABORTOP(&nd);
+       if (nd.ni_dvp == nd.ni_vp)
+               vrele(nd.ni_dvp);
        else
        else
-               vput(ndp->ni_dvp);
-       if (ndp->ni_vp);
-               vrele(ndp->ni_vp);
+               vput(nd.ni_dvp);
+       if (nd.ni_vp)
+               vrele(nd.ni_vp);
        if (pathcp)
                FREE(pathcp, M_TEMP);
        return (error);
        if (pathcp)
                FREE(pathcp, M_TEMP);
        return (error);
@@ -951,20 +1012,20 @@ nfsmout:
 /*
  * nfs mkdir service
  */
 /*
  * nfs mkdir service
  */
-nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        struct vattr va;
        register struct vattr *vap = &va;
        register struct nfsv2_fattr *fp;
 {
        struct vattr va;
        register struct vattr *vap = &va;
        register struct nfsv2_fattr *fp;
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
+       struct nameidata nd;
        register caddr_t cp;
        register caddr_t cp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -975,39 +1036,38 @@ nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat)
        fhandle_t *fhp;
        long len;
 
        fhandle_t *fhp;
        long len;
 
-       ndinit(ndp);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = CREATE | LOCKPARENT;
-       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = CREATE | LOCKPARENT;
+       if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
                nfsm_reply(0);
                nfsm_reply(0);
-       nfsm_disect(p, u_long *, NFSX_UNSIGNED);
+       nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
        VATTR_NULL(vap);
        vap->va_type = VDIR;
        VATTR_NULL(vap);
        vap->va_type = VDIR;
-       vap->va_mode = nfstov_mode(*p++);
-       vp = ndp->ni_vp;
+       vap->va_mode = nfstov_mode(*tl++);
+       vp = nd.ni_vp;
        if (vp != NULL) {
        if (vp != NULL) {
-               VOP_ABORTOP(ndp);
-               if (ndp->ni_dvp == vp)
-                       vrele(ndp->ni_dvp);
+               VOP_ABORTOP(&nd);
+               if (nd.ni_dvp == vp)
+                       vrele(nd.ni_dvp);
                else
                else
-                       vput(ndp->ni_dvp);
+                       vput(nd.ni_dvp);
                vrele(vp);
                error = EEXIST;
                nfsm_reply(0);
        }
                vrele(vp);
                error = EEXIST;
                nfsm_reply(0);
        }
-       if (error = VOP_MKDIR(ndp, vap))
+       if (error = VOP_MKDIR(&nd, vap, p))
                nfsm_reply(0);
                nfsm_reply(0);
-       vp = ndp->ni_vp;
+       vp = nd.ni_vp;
        bzero((caddr_t)fhp, sizeof(nfh));
        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
                vput(vp);
                nfsm_reply(0);
        }
        bzero((caddr_t)fhp, sizeof(nfh));
        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
                vput(vp);
                nfsm_reply(0);
        }
-       error = VOP_GETATTR(vp, vap, cred);
+       error = VOP_GETATTR(vp, vap, cred, p);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
@@ -1015,29 +1075,28 @@ nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat)
        nfsm_srvfillattr;
        return (error);
 nfsmout:
        nfsm_srvfillattr;
        return (error);
 nfsmout:
-       VOP_ABORTOP(ndp);
-       if (ndp->ni_dvp == ndp->ni_vp)
-               vrele(ndp->ni_dvp);
+       VOP_ABORTOP(&nd);
+       if (nd.ni_dvp == nd.ni_vp)
+               vrele(nd.ni_dvp);
        else
        else
-               vput(ndp->ni_dvp);
-       if (ndp->ni_vp)
-               vrele(ndp->ni_vp);
+               vput(nd.ni_dvp);
+       if (nd.ni_vp)
+               vrele(nd.ni_vp);
        return (error);
 }
 
 /*
  * nfs rmdir service
  */
        return (error);
 }
 
 /*
  * nfs rmdir service
  */
-nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf *mrep, *md, **mrq;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
 {
-       struct nameidata nami;
-       register struct nameidata *ndp = &nami;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -1047,16 +1106,16 @@ nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat)
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        long len;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        long len;
+       struct nameidata nd;
 
 
-       ndinit(ndp);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
-       ndp->ni_cred = cred;
-       ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
-       if (error = nfs_namei(ndp, fhp, len, &md, &dpos))
+       nd.ni_cred = cred;
+       nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
+       if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
                nfsm_reply(0);
                nfsm_reply(0);
-       vp = ndp->ni_vp;
+       vp = nd.ni_vp;
        if (vp->v_type != VDIR) {
                error = ENOTDIR;
                goto out;
        if (vp->v_type != VDIR) {
                error = ENOTDIR;
                goto out;
@@ -1064,24 +1123,24 @@ nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat)
        /*
         * No rmdir "." please.
         */
        /*
         * No rmdir "." please.
         */
-       if (ndp->ni_dvp == vp) {
+       if (nd.ni_dvp == vp) {
                error = EINVAL;
                goto out;
        }
        /*
                error = EINVAL;
                goto out;
        }
        /*
-        * Don't unlink a mounted file.
+        * The root of a mounted filesystem cannot be deleted.
         */
        if (vp->v_flag & VROOT)
                error = EBUSY;
 out:
        if (!error) {
         */
        if (vp->v_flag & VROOT)
                error = EBUSY;
 out:
        if (!error) {
-               error = VOP_RMDIR(ndp);
+               error = VOP_RMDIR(&nd, p);
        } else {
        } else {
-               VOP_ABORTOP(ndp);
-               if (ndp->ni_dvp == ndp->ni_vp)
-                       vrele(ndp->ni_dvp);
+               VOP_ABORTOP(&nd);
+               if (nd.ni_dvp == nd.ni_vp)
+                       vrele(nd.ni_dvp);
                else
                else
-                       vput(ndp->ni_dvp);
+                       vput(nd.ni_dvp);
                vput(vp);
        }
        nfsm_reply(0);
                vput(vp);
        }
        nfsm_reply(0);
@@ -1091,7 +1150,7 @@ out:
 /*
  * nfs readdir service
  * - mallocs what it thinks is enough to read
 /*
  * nfs readdir service
  * - mallocs what it thinks is enough to read
- *     count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR
+ *     count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
  * - calls VOP_READDIR()
  * - loops around building the reply
  *     if the output generated exceeds count break out of loop
  * - calls VOP_READDIR()
  * - loops around building the reply
  *     if the output generated exceeds count break out of loop
@@ -1116,19 +1175,20 @@ out:
  *     to including the status longwords that are not a part of the dir.
  *     "entry" structures, but are in the rpc.
  */
  *     to including the status longwords that are not a part of the dir.
  *     "entry" structures, but are in the rpc.
  */
-nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        register char *bp, *be;
        register struct mbuf *mp;
        register struct direct *dp;
        register caddr_t cp;
 {
        register char *bp, *be;
        register struct mbuf *mp;
        register struct direct *dp;
        register caddr_t cp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -1149,18 +1209,18 @@ nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_disect(p, u_long *, 2*NFSX_UNSIGNED);
-       toff = fxdr_unsigned(off_t, *p++);
-       off = (toff & ~(DIRBLKSIZ-1));
-       on = (toff & (DIRBLKSIZ-1));
-       cnt = fxdr_unsigned(int, *p);
-       siz = ((cnt+DIRBLKSIZ-1) & ~(DIRBLKSIZ-1));
+       nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED);
+       toff = fxdr_unsigned(off_t, *tl++);
+       off = (toff & ~(NFS_DIRBLKSIZ-1));
+       on = (toff & (NFS_DIRBLKSIZ-1));
+       cnt = fxdr_unsigned(int, *tl);
+       siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
        if (cnt > NFS_MAXREADDIR)
                siz = NFS_MAXREADDIR;
        fullsiz = siz;
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        if (cnt > NFS_MAXREADDIR)
                siz = NFS_MAXREADDIR;
        fullsiz = siz;
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if (error = nfsrv_access(vp, VEXEC, cred)) {
+       if (error = nfsrv_access(vp, VEXEC, cred, p)) {
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
@@ -1175,6 +1235,7 @@ again:
        io.uio_resid = fullsiz;
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        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, &eofflag);
        off = io.uio_offset;
        if (error) {
        error = VOP_READDIR(vp, &io, cred, &eofflag);
        off = io.uio_offset;
        if (error) {
@@ -1192,9 +1253,9 @@ again:
                if (siz == 0) {
                        vrele(vp);
                        nfsm_reply(2*NFSX_UNSIGNED);
                if (siz == 0) {
                        vrele(vp);
                        nfsm_reply(2*NFSX_UNSIGNED);
-                       nfsm_build(p, u_long *, 2*NFSX_UNSIGNED);
-                       *p++ = nfs_false;
-                       *p = nfs_true;
+                       nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
+                       *tl++ = nfs_false;
+                       *tl = nfs_true;
                        FREE((caddr_t)rbuf, M_TEMP);
                        return (0);
                }
                        FREE((caddr_t)rbuf, M_TEMP);
                        return (0);
                }
@@ -1246,13 +1307,13 @@ again:
        
                        /* Build the directory record xdr from the direct entry */
                        nfsm_clget;
        
                        /* Build the directory record xdr from the direct entry */
                        nfsm_clget;
-                       *p = nfs_true;
+                       *tl = nfs_true;
                        bp += NFSX_UNSIGNED;
                        nfsm_clget;
                        bp += NFSX_UNSIGNED;
                        nfsm_clget;
-                       *p = txdr_unsigned(dp->d_ino);
+                       *tl = txdr_unsigned(dp->d_ino);
                        bp += NFSX_UNSIGNED;
                        nfsm_clget;
                        bp += NFSX_UNSIGNED;
                        nfsm_clget;
-                       *p = txdr_unsigned(nlen);
+                       *tl = txdr_unsigned(nlen);
                        bp += NFSX_UNSIGNED;
        
                        /* And loop arround copying the name */
                        bp += NFSX_UNSIGNED;
        
                        /* And loop arround copying the name */
@@ -1277,7 +1338,7 @@ again:
        
                        /* Finish off the record */
                        toff += dp->d_reclen;
        
                        /* Finish off the record */
                        toff += dp->d_reclen;
-                       *p = txdr_unsigned(toff);
+                       *tl = txdr_unsigned(toff);
                        bp += NFSX_UNSIGNED;
                } else
                        toff += dp->d_reclen;
                        bp += NFSX_UNSIGNED;
                } else
                        toff += dp->d_reclen;
@@ -1285,13 +1346,13 @@ again:
                dp = (struct direct *)cpos;
        }
        nfsm_clget;
                dp = (struct direct *)cpos;
        }
        nfsm_clget;
-       *p = nfs_false;
+       *tl = nfs_false;
        bp += NFSX_UNSIGNED;
        nfsm_clget;
        if (eofflag)
        bp += NFSX_UNSIGNED;
        nfsm_clget;
        if (eofflag)
-               *p = nfs_true;
+               *tl = nfs_true;
        else
        else
-               *p = nfs_false;
+               *tl = nfs_false;
        bp += NFSX_UNSIGNED;
        if (bp < be)
                mp->m_len = bp-mtod(mp, caddr_t);
        bp += NFSX_UNSIGNED;
        if (bp < be)
                mp->m_len = bp-mtod(mp, caddr_t);
@@ -1303,17 +1364,18 @@ again:
 /*
  * nfs statfs service
  */
 /*
  * nfs statfs service
  */
-nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        register struct statfs *sf;
        register struct nfsv2_statfs *sfp;
 {
        register struct statfs *sf;
        register struct nfsv2_statfs *sfp;
-       register u_long *p;
+       register u_long *tl;
        register long t1;
        caddr_t bpos;
        int error = 0;
        register long t1;
        caddr_t bpos;
        int error = 0;
@@ -1329,7 +1391,7 @@ nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat)
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        sf = &statfs;
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        sf = &statfs;
-       error = VFS_STATFS(vp->v_mount, sf);
+       error = VFS_STATFS(vp->v_mount, sf, p);
        vput(vp);
        nfsm_reply(NFSX_STATFS);
        nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
        vput(vp);
        nfsm_reply(NFSX_STATFS);
        nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
@@ -1345,13 +1407,14 @@ nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat)
  * Null operation, used by clients to ping server
  */
 /* ARGSUSED */
  * Null operation, used by clients to ping server
  */
 /* ARGSUSED */
-nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        caddr_t bpos;
        int error = 0;
 {
        caddr_t bpos;
        int error = 0;
@@ -1366,13 +1429,14 @@ nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat)
  * No operation, used for obsolete procedures
  */
 /* ARGSUSED */
  * No operation, used for obsolete procedures
  */
 /* ARGSUSED */
-nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat)
+nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p)
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
        struct mbuf **mrq;
        struct mbuf *mrep, *md;
        caddr_t dpos;
        struct ucred *cred;
        u_long xid;
        int *repstat;
+       struct proc *p;
 {
        caddr_t bpos;
        int error = 0;
 {
        caddr_t bpos;
        int error = 0;
@@ -1393,10 +1457,11 @@ nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat)
  *     this because it opens a security hole, but since the nfs server opens
  *     a security hole the size of a barn door anyhow, what the heck.
  */
  *     this because it opens a security hole, but since the nfs server opens
  *     a security hole the size of a barn door anyhow, what the heck.
  */
-nfsrv_access(vp, flags, cred)
+nfsrv_access(vp, flags, cred, p)
        register struct vnode *vp;
        int flags;
        register struct ucred *cred;
        register struct vnode *vp;
        int flags;
        register struct ucred *cred;
+       struct proc *p;
 {
        struct vattr vattr;
        int error;
 {
        struct vattr vattr;
        int error;
@@ -1407,29 +1472,24 @@ nfsrv_access(vp, flags, cred)
                 * unless the file is a socket or a block or character
                 * device resident on the file system.
                 */
                 * unless the file is a socket or a block or character
                 * device resident on the file system.
                 */
-               if ((vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) &&
-                       vp->v_type != VCHR &&
-                       vp->v_type != VBLK &&
-                       vp->v_type != VSOCK)
+               if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) {
+                       switch (vp->v_type) {
+                       case VREG: case VDIR: case VLNK:
                                return (EROFS);
                                return (EROFS);
+                       }
+               }
                /*
                 * If there's shared text associated with
                 * the inode, try to free it up once.  If
                 * we fail, we can't allow writing.
                 */
                /*
                 * If there's shared text associated with
                 * the inode, try to free it up once.  If
                 * we fail, we can't allow writing.
                 */
-               if (vp->v_flag & VTEXT)
-                       xrele(vp);
-               if (vp->v_flag & VTEXT)
+               if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
                        return (ETXTBSY);
                        return (ETXTBSY);
-               if (error = VOP_GETATTR(vp, &vattr, cred))
-                       return (error);
-               if (cred->cr_uid == vattr.va_uid)
-                       return (0);
-       } else {
-               if (error = VOP_GETATTR(vp, &vattr, cred))
-                       return (error);
-               if (cred->cr_uid == vattr.va_uid)
-                       return (0);
        }
        }
-       return (VOP_ACCESS(vp, flags, cred));
+       if (error = VOP_GETATTR(vp, &vattr, cred, p))
+               return (error);
+       if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
+           cred->cr_uid != vattr.va_uid)
+               return (error);
+       return (0);
 }
 }