fast track m_adj from tail didn't adjust pkthdr.len
[unix-history] / usr / src / sys / nfs / nfs_serv.c
index 28a26fd..b1f41cc 100644 (file)
@@ -17,7 +17,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)nfs_serv.c  7.3 (Berkeley) %G%
+ *     @(#)nfs_serv.c  7.7 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -78,6 +78,7 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq)
        struct ucred *cred;
        u_long xid;
 {
        struct ucred *cred;
        u_long xid;
 {
+       register struct nfsv2_fattr *fp;
        struct vattr va;
        register struct vattr *vap = &va;
        struct vnode *vp;
        struct vattr va;
        register struct vattr *vap = &va;
        struct vnode *vp;
@@ -92,23 +93,21 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq)
        error = VOP_GETATTR(vp, vap, cred);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
        error = VOP_GETATTR(vp, vap, cred);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
-       nfsm_build(p, u_long *, NFSX_FATTR);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
@@ -124,6 +123,8 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq)
 {
        struct vattr va;
        register struct vattr *vap = &va;
 {
        struct vattr va;
        register struct vattr *vap = &va;
+       register struct nfsv2_sattr *sp;
+       register struct nfsv2_fattr *fp;
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
        struct vnode *vp;
        nfsv2fh_t nfh;
        fhandle_t *fhp;
@@ -131,13 +132,11 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq)
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
 
        fhp = &nfh.fh_generic;
        nfsm_srvmtofh(fhp);
-       nfsm_disect(p, u_long *, NFSX_SATTR);
+       nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if (vp->v_mount->m_flag & (M_RDONLY | M_EXRDONLY)) {
-               error = EROFS;
+       if (error = nfsrv_access(vp, VWRITE, cred))
                goto out;
                goto out;
-       }
        vattr_null(vap);
        /*
         * Nah nah nah nah na nah
        vattr_null(vap);
        /*
         * Nah nah nah nah na nah
@@ -146,20 +145,19 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq)
         * doesn't sign extend.
         * --> check the low order 2 bytes for 0xffff
         */
         * doesn't sign extend.
         * --> check the low order 2 bytes for 0xffff
         */
-       if ((fxdr_unsigned(int, *p) & 0xffff) != 0xffff)
-               vap->va_mode = nfstov_mode(*p);
-       if (*++p != nfs_xdrneg1)
-               vap->va_uid = fxdr_unsigned(uid_t, *p);
-       if (*++p != nfs_xdrneg1)
-               vap->va_gid = fxdr_unsigned(gid_t, *p);
-       if (*++p != nfs_xdrneg1) {
-               vap->va_size = fxdr_unsigned(u_long, *p);
+       if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
+               vap->va_mode = nfstov_mode(sp->sa_mode);
+       if (sp->sa_uid != nfs_xdrneg1)
+               vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
+       if (sp->sa_gid != nfs_xdrneg1)
+               vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
+       if (sp->sa_size != nfs_xdrneg1) {
+               vap->va_size = fxdr_unsigned(u_long, sp->sa_size);
        }
        }
-       if (*++p != nfs_xdrneg1)
-               fxdr_time(p, &(vap->va_atime));
-       p += 2;
-       if (*p != nfs_xdrneg1)
-               fxdr_time(p, &(vap->va_mtime));
+       if (sp->sa_atime.tv_sec != nfs_xdrneg1)
+               fxdr_time(&sp->sa_atime, &vap->va_atime);
+       if (sp->sa_mtime.tv_sec != nfs_xdrneg1)
+               fxdr_time(&sp->sa_mtime, &vap->va_mtime);
        if (error = VOP_SETATTR(vp, vap, cred)) {
                vput(vp);
                nfsm_reply(0);
        if (error = VOP_SETATTR(vp, vap, cred)) {
                vput(vp);
                nfsm_reply(0);
@@ -168,23 +166,21 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq)
 out:
        vput(vp);
        nfsm_reply(NFSX_FATTR);
 out:
        vput(vp);
        nfsm_reply(NFSX_FATTR);
-       nfsm_build(p, u_long *, NFSX_FATTR);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
@@ -198,6 +194,7 @@ nfsrv_lookup(mrep, md, dpos, cred, xid, mrq)
        struct ucred *cred;
        u_long xid;
 {
        struct ucred *cred;
        u_long xid;
 {
+       register struct nfsv2_fattr *fp;
        register struct nameidata *ndp = &u.u_nd;
        struct vnode *vp;
        nfsv2fh_t nfh;
        register struct nameidata *ndp = &u.u_nd;
        struct vnode *vp;
        nfsv2fh_t nfh;
@@ -224,23 +221,21 @@ nfsrv_lookup(mrep, md, dpos, cred, xid, mrq)
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
-       nfsm_build(p, u_long *, NFSX_FATTR);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
@@ -331,6 +326,7 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq)
        struct iovec iv[NFS_MAXDATA/MCLBYTES+1];
        register struct iovec *ivp = iv;
        register struct mbuf *mp;
        struct iovec iv[NFS_MAXDATA/MCLBYTES+1];
        register struct iovec *ivp = iv;
        register struct mbuf *mp;
+       register struct nfsv2_fattr *fp;
        nfsm_srvars;
        struct mbuf *mp2, *mp3;
        struct vnode *vp;
        nfsm_srvars;
        struct mbuf *mp2, *mp3;
        struct vnode *vp;
@@ -348,7 +344,7 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq)
        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 = VOP_ACCESS(vp, VREAD | VEXEC, cred)) {
+       if (error = nfsrv_access(vp, VREAD | VEXEC, cred)) {
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
@@ -396,24 +392,21 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq)
                m_freem(mp3);
        vput(vp);
        nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
                m_freem(mp3);
        vput(vp);
        nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
-       nfsm_build(p, u_long *, NFSX_FATTR+NFSX_UNSIGNED);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
-       p += 2;
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        if (uiop->uio_resid > 0) {
                len -= uiop->uio_resid;
                if (len > 0) {
        if (uiop->uio_resid > 0) {
                len -= uiop->uio_resid;
                if (len > 0) {
@@ -424,6 +417,7 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq)
                        mp3 = (struct mbuf *)0;
                }
        }
                        mp3 = (struct mbuf *)0;
                }
        }
+       nfsm_build(p, u_long *, NFSX_UNSIGNED);
        *p = txdr_unsigned(len);
        mb->m_next = mp3;
        nfsm_srvdone;
        *p = txdr_unsigned(len);
        mb->m_next = mp3;
        nfsm_srvdone;
@@ -440,6 +434,7 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq)
 {
        register struct iovec *ivp;
        register struct mbuf *mp;
 {
        register struct iovec *ivp;
        register struct mbuf *mp;
+       register struct nfsv2_fattr *fp;
        struct iovec iv[MAX_IOVEC];
        struct vattr va;
        register struct vattr *vap = &va;
        struct iovec iv[MAX_IOVEC];
        struct vattr va;
        register struct vattr *vap = &va;
@@ -475,8 +470,7 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq)
        }
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        }
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if ((error = vn_writechk(vp)) ||
-           (error = VOP_ACCESS(vp, VWRITE, cred))) {
+       if (error = nfsrv_access(vp, VWRITE, cred)) {
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
@@ -527,23 +521,21 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq)
        error = VOP_GETATTR(vp, vap, cred);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
        error = VOP_GETATTR(vp, vap, cred);
        vput(vp);
        nfsm_reply(NFSX_FATTR);
-       nfsm_build(p, u_long *, NFSX_FATTR);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
@@ -557,6 +549,7 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq)
        struct ucred *cred;
        long xid;
 {
        struct ucred *cred;
        long xid;
 {
+       register struct nfsv2_fattr *fp;
        struct vattr va;
        register struct vattr *vap = &va;
        register struct nameidata *ndp = &u.u_nd;
        struct vattr va;
        register struct vattr *vap = &va;
        register struct nameidata *ndp = &u.u_nd;
@@ -605,23 +598,21 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq)
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
-       nfsm_build(p, u_long *, NFSX_FATTR);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        return (error);
 nfsmout:
        VOP_ABORTOP(ndp);
        return (error);
 nfsmout:
        VOP_ABORTOP(ndp);
@@ -741,10 +732,12 @@ out:
                VOP_ABORTOP(&tond);
                VOP_ABORTOP(ndp);
        } else {
                VOP_ABORTOP(&tond);
                VOP_ABORTOP(ndp);
        } else {
+               VREF(tond.ni_cdir);
                error = VOP_RENAME(ndp, &tond);
                error = VOP_RENAME(ndp, &tond);
+               vrele(tond.ni_cdir);
        }
 out1:
        }
 out1:
-       ndrele(&tond);
+       ndrele(ndp);
        nfsm_reply(0);
        return (error);
 nfsmout:
        nfsm_reply(0);
        return (error);
 nfsmout:
@@ -866,6 +859,7 @@ nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq)
 {
        struct vattr va;
        register struct vattr *vap = &va;
 {
        struct vattr va;
        register struct vattr *vap = &va;
+       register struct nfsv2_fattr *fp;
        register struct nameidata *ndp = &u.u_nd;
        nfsm_srvars;
        struct vnode *vp;
        register struct nameidata *ndp = &u.u_nd;
        nfsm_srvars;
        struct vnode *vp;
@@ -904,23 +898,21 @@ nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq)
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
        vput(vp);
        nfsm_reply(NFSX_FH+NFSX_FATTR);
        nfsm_srvfhtom(fhp);
-       nfsm_build(p, u_long *, NFSX_FATTR);
-       *p++ = vtonfs_type(vap->va_type);
-       *p++ = vtonfs_mode(vap->va_type, vap->va_mode);
-       *p++ = txdr_unsigned(vap->va_nlink);
-       *p++ = txdr_unsigned(vap->va_uid);
-       *p++ = txdr_unsigned(vap->va_gid);
-       *p++ = txdr_unsigned(vap->va_size);
-       *p++ = txdr_unsigned(vap->va_blocksize);
-       *p++ = txdr_unsigned(vap->va_rdev);
-       *p++ = txdr_unsigned(vap->va_bytes);
-       *p++ = txdr_unsigned(vap->va_fsid);
-       *p++ = txdr_unsigned(vap->va_fileid);
-       txdr_time(&(vap->va_atime), p);
-       p += 2;
-       txdr_time(&(vap->va_mtime), p);
-       p += 2;
-       txdr_time(&(vap->va_ctime), p);
+       nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
+       fp->fa_type = vtonfs_type(vap->va_type);
+       fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
+       fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       fp->fa_size = txdr_unsigned(vap->va_size);
+       fp->fa_blocksize = txdr_unsigned(vap->va_blocksize);
+       fp->fa_rdev = txdr_unsigned(vap->va_rdev);
+       fp->fa_blocks = txdr_unsigned(vap->va_bytes / vap->va_blocksize);
+       fp->fa_fsid = txdr_unsigned(vap->va_fsid);
+       fp->fa_fileid = txdr_unsigned(vap->va_fileid);
+       txdr_time(&vap->va_atime, &fp->fa_atime);
+       txdr_time(&vap->va_mtime, &fp->fa_mtime);
+       txdr_time(&vap->va_ctime, &fp->fa_ctime);
        return (error);
 nfsmout:
        VOP_ABORTOP(ndp);
        return (error);
 nfsmout:
        VOP_ABORTOP(ndp);
@@ -1041,7 +1033,7 @@ nfsrv_readdir(mrep, md, dpos, cred, xid, mrq)
        fullsiz = siz;
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
        fullsiz = siz;
        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
                nfsm_reply(0);
-       if (error = VOP_ACCESS(vp, VEXEC, cred)) {
+       if (error = nfsrv_access(vp, VEXEC, cred)) {
                vput(vp);
                nfsm_reply(0);
        }
                vput(vp);
                nfsm_reply(0);
        }
@@ -1177,6 +1169,7 @@ nfsrv_statfs(mrep, md, dpos, cred, xid, mrq)
        u_long xid;
 {
        register struct statfs *sf;
        u_long xid;
 {
        register struct statfs *sf;
+       register struct nfsv2_statfs *sfp;
        nfsm_srvars;
        struct vnode *vp;
        nfsv2fh_t nfh;
        nfsm_srvars;
        struct vnode *vp;
        nfsv2fh_t nfh;
@@ -1191,12 +1184,12 @@ nfsrv_statfs(mrep, md, dpos, cred, xid, mrq)
        error = VFS_STATFS(vp->v_mount, sf);
        vput(vp);
        nfsm_reply(NFSX_STATFS);
        error = VFS_STATFS(vp->v_mount, sf);
        vput(vp);
        nfsm_reply(NFSX_STATFS);
-       nfsm_build(p, u_long *, NFSX_STATFS);
-       *p++ = txdr_unsigned(NFS_MAXDATA);
-       *p++ = txdr_unsigned(sf->f_fsize);
-       *p++ = txdr_unsigned(sf->f_blocks);
-       *p++ = txdr_unsigned(sf->f_bfree);
-       *p = txdr_unsigned(sf->f_bavail);
+       nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
+       sfp->sf_tsize = txdr_unsigned(NFS_MAXDATA);
+       sfp->sf_bsize = txdr_unsigned(sf->f_fsize);
+       sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
+       sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
+       sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
@@ -1234,3 +1227,53 @@ nfsrv_noop(mrep, md, dpos, cred, xid, mrq)
        nfsm_srvdone;
 }
 
        nfsm_srvdone;
 }
 
+/*
+ * Perform access checking for vnodes obtained from file handles that would
+ * refer to files already opened by a Unix client. You cannot just use
+ * vn_writechk() and VOP_ACCESS() for two reasons.
+ * 1 - You must check for M_EXRDONLY as well as M_RDONLY for the write case
+ * 2 - The owner is to be given access irrespective of mode bits so that
+ *     processes that chmod after opening a file don't break. I don't like
+ *     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)
+       register struct vnode *vp;
+       int flags;
+       register struct ucred *cred;
+{
+       struct vattr vattr;
+       int error;
+       if (flags & VWRITE) {
+               /* Just vn_writechk() changed to check M_EXRDONLY */
+               /*
+                * Disallow write attempts on read-only file systems;
+                * unless the file is a socket or a block or character
+                * device resident on the file system.
+                */
+               if ((vp->v_mount->m_flag & (M_RDONLY | M_EXRDONLY)) &&
+                       vp->v_type != VCHR &&
+                       vp->v_type != VBLK &&
+                       vp->v_type != VSOCK)
+                               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 (vp->v_flag & VTEXT)
+                       xrele(vp);
+               if (vp->v_flag & VTEXT)
+                       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));
+}