NFS - Marathon - completely refactor the nfsm_* macros.
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 16 Jul 2009 23:21:36 +0000 (16:21 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 16 Jul 2009 23:21:36 +0000 (16:21 -0700)
Completely refactor the nfsm_*() macros in nfsm_subs.h, converting
all of them to procedures in nfsm_subs.c.

Add a nfsm_info structure to track the persistent state that the code
depends on, and remove all related local variables from the other bits
of the NFS code.

sys/vfs/nfs/nfs.h
sys/vfs/nfs/nfs_serv.c
sys/vfs/nfs/nfs_socket.c
sys/vfs/nfs/nfs_subs.c
sys/vfs/nfs/nfs_syscalls.c
sys/vfs/nfs/nfs_vfsops.c
sys/vfs/nfs/nfs_vnops.c
sys/vfs/nfs/nfsm_subs.c
sys/vfs/nfs/nfsm_subs.h

index bf80f83..6621ab6 100644 (file)
@@ -644,13 +644,6 @@ int        nfs_doio (struct vnode *vp, struct bio *, struct thread *);
 int    nfs_readlinkrpc (struct vnode *, struct uio *);
 int    nfs_sigintr (struct nfsmount *, struct nfsreq *, struct thread *);
 int    nfs_readdirplusrpc (struct vnode *, struct uio *);
-int    nfsm_disct (struct mbuf **, caddr_t *, int, int, caddr_t *);
-void   nfsm_srvfattr (struct nfsrv_descript *, struct vattr *, 
-                          struct nfs_fattr *);
-void   nfsm_srvwcc (struct nfsrv_descript *, int, struct vattr *, int,
-                        struct vattr *, struct mbuf **, char **);
-void   nfsm_srvpostopattr (struct nfsrv_descript *, int, struct vattr *,
-                               struct mbuf **, char **);
 int    netaddr_match (int, union nethostaddr *, struct sockaddr *);
 int    nfs_request (struct vnode *, struct mbuf *, int, struct thread *,
                         struct ucred *, struct mbuf **, struct mbuf **,
@@ -665,14 +658,12 @@ int       nfs_request_processreply(struct nfsreq *rep, int error);
 
 
 
-int    nfs_loadattrcache (struct vnode **, struct mbuf **, caddr_t *,
-                              struct vattr *, int);
+int    nfs_loadattrcache (struct vnode *, struct mbuf **, caddr_t *,
+                       struct vattr *, int);
 int    nfs_namei (struct nlookupdata *, struct ucred *, int, 
                    struct vnode **, struct vnode **, fhandle_t *, int,
                    struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
                    caddr_t *, struct vnode **, struct thread *, int, int);
-void   nfsm_adj (struct mbuf *, int, int);
-int    nfsm_mbuftouio (struct mbuf **, struct uio *, int, caddr_t *);
 void   nfsrv_initcache (void);
 int    nfs_getauth (struct nfsmount *, struct nfsreq *, struct ucred *, 
                         char **, int *, char *, int *, NFSKERBKEY_T);
@@ -695,9 +686,7 @@ int nfs_connect (struct nfsmount *, struct nfsreq *);
 void   nfs_disconnect (struct nfsmount *);
 void   nfs_safedisconnect (struct nfsmount *);
 int    nfs_getattrcache (struct vnode *, struct vattr *);
-int    nfsm_strtmbuf (struct mbuf **, char **, const char *, long);
 int    nfs_bioread (struct vnode *, struct uio *, int);
-int    nfsm_uiotombuf (struct uio *, struct mbuf **, int, caddr_t *);
 void   nfsrv_init (int);
 void   nfs_clearcommit (struct mount *);
 int    nfsrv_errmap (struct nfsrv_descript *, int);
index 220db22..6f37d66 100644 (file)
@@ -149,32 +149,32 @@ int
 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
              struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        nfsfh_t nfh;
        fhandle_t *fhp;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, getret;
-       char *cp2;
-       struct mbuf *mb, *mreq, *mb2;
        struct vattr vattr, *vap = &vattr;
        u_long testmode, nfsmode;
+       struct nfsm_info info;
+       u_int32_t *tl;
+
+       info.dpos = nfsd->nd_dpos;
+       info.md = nfsd->nd_md;
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, &rdonly,
            (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(1, NULL);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, 1, NULL);
                error = 0;
                goto nfsmout;
        }
@@ -200,11 +200,13 @@ nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        getret = VOP_GETATTR(vp, vap);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
-       nfsm_srvpostop_attr(getret, vap);
-       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_POSTOPATTR(1) + NFSX_UNSIGNED, &error));
+       nfsm_srvpostop_attr(&info, nfsd, getret, vap);
+       tl = nfsm_build(&info, NFSX_UNSIGNED);
        *tl = txdr_unsigned(nfsmode);
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -217,9 +219,7 @@ int
 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
              struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct nfs_fattr *fp;
        struct vattr va;
@@ -228,36 +228,39 @@ nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct mount *mp = NULL;
        nfsfh_t nfh;
        fhandle_t *fhp;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.mreq = NULL;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(0);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
                error = 0;
                goto nfsmout;
        }
        error = VOP_GETATTR(vp, vap);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_FATTR(nfsd->nd_flag & ND_NFSV3), &error));
        if (error) {
                error = 0;
                goto nfsmout;
        }
-       nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
-       nfsm_srvfillattr(vap, fp);
+       fp = nfsm_build(&info, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
+       nfsm_srvfattr(nfsd, vap, fp);
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -270,9 +273,7 @@ int
 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
              struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct vattr va, preat;
        struct vattr *vap = &va;
@@ -283,28 +284,31 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        nfsfh_t nfh;
        fhandle_t *fhp;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
+       int gcheck = 0;
        struct timespec guard;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
        VATTR_NULL(vap);
-       if (v3) {
-               nfsm_srvsattr(vap);
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+       if (info.v3) {
+               ERROROUT(nfsm_srvsattr(&info, vap));
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                gcheck = fxdr_unsigned(int, *tl);
                if (gcheck) {
-                       nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                        fxdr_nfsv3time(tl, &guard);
                }
        } else {
-               nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+               NULLOUT(sp = nfsm_dissect(&info, NFSX_V2SATTR));
                /*
                 * Nah nah nah nah na nah
                 * There is a bug in the Sun client that puts 0xffff in the mode
@@ -340,8 +344,10 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, &rdonly,
                (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(2 * NFSX_UNSIGNED);
-               nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_UNSIGNED, &error));
+               nfsm_srvwcc_data(&info, nfsd, preat_ret, &preat,
+                                postat_ret, vap);
                error = 0;
                goto nfsmout;
        }
@@ -350,7 +356,7 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         * vp now an active resource, pay careful attention to cleanup
         */
 
-       if (v3) {
+       if (info.v3) {
                error = preat_ret = VOP_GETATTR(vp, &preat);
                if (!error && gcheck &&
                        (preat.va_ctime.tv_sec != guard.tv_sec ||
@@ -359,8 +365,10 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                if (error) {
                        vput(vp);
                        vp = NULL;
-                       nfsm_reply(NFSX_WCCDATA(v3));
-                       nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
+                       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                             NFSX_WCCDATA(info.v3), &error));
+                       nfsm_srvwcc_data(&info, nfsd, preat_ret, &preat,
+                                        postat_ret, vap);
                        error = 0;
                        goto nfsmout;
                }
@@ -391,18 +399,21 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 out:
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_WCCORFATTR(v3));
-       if (v3) {
-               nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                  NFSX_WCCORFATTR(info.v3), &error));
+       if (info.v3) {
+               nfsm_srvwcc_data(&info, nfsd, preat_ret, &preat,
+                                postat_ret, vap);
                error = 0;
                goto nfsmout;
        } else {
-               nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
-               nfsm_srvfillattr(vap, fp);
+               fp = nfsm_build(&info, NFSX_V2FATTR);
+               nfsm_srvfattr(nfsd, vap, fp);
        }
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -415,9 +426,7 @@ int
 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct nfs_fattr *fp;
        struct nlookupdata nd;
@@ -426,15 +435,16 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct nchandle nch;
        nfsfh_t nfh;
        fhandle_t *fhp;
-       caddr_t cp;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, dirattr_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
+       int pubflag;
        struct vattr va, dirattr, *vap = &va;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -442,13 +452,13 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        vp = NULL;
 
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        pubflag = nfs_ispublicfh(fhp);
 
        error = nfs_namei(&nd, cred, 0, NULL, &vp,
-               fhp, len, slp, nam, &md, &dpos,
+               fhp, len, slp, nam, &info.md, &info.dpos,
                &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
 
        /*
@@ -458,13 +468,14 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 
        if (error) {
                if (dirp) {
-                       if (v3)
+                       if (info.v3)
                                dirattr_ret = VOP_GETATTR(dirp, &dirattr);
                        vrele(dirp);
                        dirp = NULL;
                }
-               nfsm_reply(NFSX_POSTOPATTR(v3));
-               nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_POSTOPATTR(info.v3), &error));
+               nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
                error = 0;
                goto nfsmout;
        }
@@ -532,7 +543,7 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        }
 
        if (dirp) {
-               if (v3)
+               if (info.v3)
                        dirattr_ret = VOP_GETATTR(dirp, &dirattr);
                vrele(dirp);
                dirp = NULL;
@@ -545,8 +556,9 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         */
 
        if (error) {
-               nfsm_reply(NFSX_POSTOPATTR(v3));
-               nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_POSTOPATTR(info.v3), &error));
+               nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
                error = 0;
                goto nfsmout;
        }
@@ -569,22 +581,27 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_SRVFH(info.v3) +
+                             NFSX_POSTOPORFATTR(info.v3) +
+                             NFSX_POSTOPATTR(info.v3),
+                             &error));
        if (error) {
-               nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+               nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
                error = 0;
                goto nfsmout;
        }
-       nfsm_srvfhtom(fhp, v3);
-       if (v3) {
-               nfsm_srvpostop_attr(0, vap);
-               nfsm_srvpostop_attr(dirattr_ret, &dirattr);
+       nfsm_srvfhtom(&info, fhp);
+       if (info.v3) {
+               nfsm_srvpostop_attr(&info, nfsd, 0, vap);
+               nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
        } else {
-               nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
-               nfsm_srvfillattr(vap, fp);
+               fp = nfsm_build(&info, NFSX_V2FATTR);
+               nfsm_srvfattr(nfsd, vap, fp);
        }
 
 nfsmout:
+       *mrq = info.mreq;
        if (dirp)
                vrele(dirp);
        nlookup_done(&nd);              /* may be called twice */
@@ -600,25 +617,26 @@ int
 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
               struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
        struct iovec *ivp = iv;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, i, tlen, len, getret;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mb2, *mp1, *mp2, *mp3, *mreq;
+       struct mbuf *mp1, *mp2, *mp3;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        struct vattr attr;
        nfsfh_t nfh;
        fhandle_t *fhp;
        struct uio io, *uiop = &io;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 #ifndef nolint
@@ -626,7 +644,7 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 #endif
        mp3 = NULL;
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
        len = 0;
        i = 0;
        while (len < NFS_MAXPATHLEN) {
@@ -658,13 +676,14 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(2 * NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(1, NULL);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, 1, NULL);
                error = 0;
                goto nfsmout;
        }
        if (vp->v_type != VLNK) {
-               if (v3)
+               if (info.v3)
                        error = EINVAL;
                else
                        error = ENXIO;
@@ -675,9 +694,11 @@ out:
        getret = VOP_GETATTR(vp, &attr);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
-       if (v3) {
-               nfsm_srvpostop_attr(getret, &attr);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                            NFSX_POSTOPATTR(info.v3) + NFSX_UNSIGNED,
+                            &error));
+       if (info.v3) {
+               nfsm_srvpostop_attr(&info, nfsd, getret, &attr);
                if (error) {
                        error = 0;
                        goto nfsmout;
@@ -688,11 +709,12 @@ out:
                tlen = nfsm_rndup(len);
                nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
        }
-       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+       tl = nfsm_build(&info, NFSX_UNSIGNED);
        *tl = txdr_unsigned(len);
-       mb->m_next = mp3;
+       info.mb->m_next = mp3;
        mp3 = NULL;
 nfsmout:
+       *mrq = info.mreq;
        if (mp3)
                m_freem(mp3);
        if (vp)
@@ -707,22 +729,17 @@ int
 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
           struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
+       struct nfsm_info info;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct iovec *iv;
        struct iovec *iv2;
        struct mbuf *m;
        struct nfs_fattr *fp;
        u_int32_t *tl;
-       int32_t t1;
        int i;
-       caddr_t bpos;
+       int reqlen;
        int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
-       int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct mbuf *m2;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
@@ -734,17 +751,24 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        off_t off;
        int ioflag = 0;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       if (v3) {
-               nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       if (info.v3) {
+               NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                off = fxdr_hyper(tl);
        } else {
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                off = (off_t)fxdr_unsigned(u_int32_t, *tl);
        }
-       nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
+       NEGREPLYOUT(reqlen = nfsm_srvstrsiz(&info,
+                                           NFS_SRVMAXDATA(nfsd), &error));
 
        /*
         * Reference vp.  If an error occurs, vp will be invalid, but we
@@ -756,14 +780,15 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
                vp = NULL;
-               nfsm_reply(2 * NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(1, NULL);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, 1, NULL);
                error = 0;
                goto nfsmout;
        }
 
        if (vp->v_type != VREG) {
-               if (v3)
+               if (info.v3)
                        error = EINVAL;
                else
                        error = (vp->v_type == VDIR) ? EISDIR : EACCES;
@@ -778,8 +803,9 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        if (error) {
                vput(vp);
                vp = NULL;
-               nfsm_reply(NFSX_POSTOPATTR(v3));
-               nfsm_srvpostop_attr(getret, vap);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_POSTOPATTR(info.v3), &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, vap);
                error = 0;
                goto nfsmout;
        }
@@ -850,14 +876,17 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
         }
 
-       nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
-       if (v3) {
-               nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_POSTOPORFATTR(info.v3) +
+                             3 * NFSX_UNSIGNED + nfsm_rndup(cnt),
+                             &error));
+       if (info.v3) {
+               tl = nfsm_build(&info, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
                *tl++ = nfs_true;
                fp = (struct nfs_fattr *)tl;
                tl += (NFSX_V3FATTR / sizeof (u_int32_t));
        } else {
-               nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
+               tl = nfsm_build(&info, NFSX_V2FATTR + NFSX_UNSIGNED);
                fp = (struct nfs_fattr *)tl;
                tl += (NFSX_V2FATTR / sizeof (u_int32_t));
        }
@@ -867,7 +896,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                 * Generate the mbuf list with the uio_iov ref. to it.
                 */
                i = 0;
-               m = m2 = mb;
+               m = m2 = info.mb;
                while (left > 0) {
                        siz = min(M_TRAILINGSPACE(m), left);
                        if (siz > 0) {
@@ -884,7 +913,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
                       M_TEMP, M_WAITOK);
                uiop->uio_iov = iv2 = iv;
-               m = mb;
+               m = info.mb;
                left = len;
                i = 0;
                while (left > 0) {
@@ -913,11 +942,14 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                if (error || (getret = VOP_GETATTR(vp, vap))) {
                        if (!error)
                                error = getret;
-                       m_freem(mreq);
+                       m_freem(info.mreq);
+                       info.mreq = NULL;
                        vput(vp);
                        vp = NULL;
-                       nfsm_reply(NFSX_POSTOPATTR(v3));
-                       nfsm_srvpostop_attr(getret, vap);
+                       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                             NFSX_POSTOPATTR(info.v3),
+                                             &error));
+                       nfsm_srvpostop_attr(&info, nfsd, getret, vap);
                        error = 0;
                        goto nfsmout;
                }
@@ -926,13 +958,13 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        }
        vput(vp);
        vp = NULL;
-       nfsm_srvfillattr(vap, fp);
+       nfsm_srvfattr(nfsd, vap, fp);
        tlen = len - uiop->uio_resid;
        cnt = cnt < tlen ? cnt : tlen;
        tlen = nfsm_rndup(cnt);
        if (len != tlen || tlen != cnt)
-               nfsm_adj(mb, len - tlen, tlen - cnt);
-       if (v3) {
+               nfsm_adj(info.mb, len - tlen, tlen - cnt);
+       if (info.v3) {
                *tl++ = txdr_unsigned(cnt);
                if (len < reqlen)
                        *tl++ = nfs_true;
@@ -941,6 +973,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        }
        *tl = txdr_unsigned(cnt);
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -953,9 +986,7 @@ int
 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
            struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct iovec *ivp;
        int i, cnt;
@@ -965,36 +996,37 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct vattr va, forat;
        struct vattr *vap = &va;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, len, forat_ret = 1;
        int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
        int stable = NFSV3WRITE_FILESYNC;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        nfsfh_t nfh;
        fhandle_t *fhp;
        struct uio io, *uiop = &io;
+       struct nfsm_info info;
        off_t off;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-       if (mrep == NULL) {
-               *mrq = NULL;
+       if (info.mrep == NULL) {
                error = 0;
                goto nfsmout;
        }
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       if (v3) {
-               nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       if (info.v3) {
+               NULLOUT(tl = nfsm_dissect(&info, 5 * NFSX_UNSIGNED));
                off = fxdr_hyper(tl);
                tl += 3;
                stable = fxdr_unsigned(int, *tl++);
        } else {
-               nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, 4 * NFSX_UNSIGNED));
                off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
                tl += 2;
                if (nfs_async)
@@ -1010,14 +1042,14 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         */
        if (len > 0) {
            zeroing = 1;
-           mp1 = mrep;
+           mp1 = info.mrep;
            while (mp1) {
-               if (mp1 == md) {
+               if (mp1 == info.md) {
                        zeroing = 0;
-                       adjust = dpos - mtod(mp1, caddr_t);
+                       adjust = info.dpos - mtod(mp1, caddr_t);
                        mp1->m_len -= adjust;
                        if (mp1->m_len > 0 && adjust > 0)
-                               NFSMADV(mp1, adjust);
+                               mp1->m_data += adjust;
                }
                if (zeroing)
                        mp1->m_len = 0;
@@ -1035,8 +1067,10 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        }
        if (len > NFS_MAXDATA || len < 0 || i < len) {
                error = EIO;
-               nfsm_reply(2 * NFSX_UNSIGNED);
-               nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_UNSIGNED, &error));
+               nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                aftat_ret, vap);
                error = 0;
                goto nfsmout;
        }
@@ -1044,15 +1078,17 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
                vp = NULL;
-               nfsm_reply(2 * NFSX_UNSIGNED);
-               nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_UNSIGNED, &error));
+               nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                aftat_ret, vap);
                error = 0;
                goto nfsmout;
        }
-       if (v3)
+       if (info.v3)
                forat_ret = VOP_GETATTR(vp, &forat);
        if (vp->v_type != VREG) {
-               if (v3)
+               if (info.v3)
                        error = EINVAL;
                else
                        error = (vp->v_type == VDIR) ? EISDIR : EACCES;
@@ -1063,8 +1099,10 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        if (error) {
                vput(vp);
                vp = NULL;
-               nfsm_reply(NFSX_WCCDATA(v3));
-               nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_WCCDATA(info.v3), &error));
+               nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                aftat_ret, vap);
                error = 0;
                goto nfsmout;
        }
@@ -1074,7 +1112,7 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                M_WAITOK);
            uiop->uio_iov = iv = ivp;
            uiop->uio_iovcnt = cnt;
-           mp1 = mrep;
+           mp1 = info.mrep;
            while (mp1) {
                if (mp1->m_len > 0) {
                        ivp->iov_base = mtod(mp1, caddr_t);
@@ -1111,15 +1149,19 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        vp = NULL;
        if (!error)
                error = aftat_ret;
-       nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
-               2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
-       if (v3) {
-               nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_PREOPATTR(info.v3) +
+                             NFSX_POSTOPORFATTR(info.v3) +
+                             2 * NFSX_UNSIGNED + NFSX_WRITEVERF(info.v3),
+                             &error));
+       if (info.v3) {
+               nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                aftat_ret, vap);
                if (error) {
                        error = 0;
                        goto nfsmout;
                }
-               nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+               tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
                *tl++ = txdr_unsigned(retlen);
                /*
                 * If nfs_async is set, then pretend the write was FILESYNC.
@@ -1138,10 +1180,11 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                *tl++ = txdr_unsigned(nfsver.tv_sec);
                *tl = txdr_unsigned(nfsver.tv_nsec / 1000);
        } else {
-               nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
-               nfsm_srvfillattr(vap, fp);
+               fp = nfsm_build(&info, NFSX_V2FATTR);
+               nfsm_srvfattr(nfsd, vap, fp);
        }
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -1167,16 +1210,14 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
        struct ucred *cred;
        struct vattr va, forat;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos, dpos;
        int error = 0, rdonly, len, forat_ret = 1;
-       int ioflags, aftat_ret = 1, adjust, v3, zeroing;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq, *mrep, *md, *mp1;
+       int ioflags, aftat_ret = 1, adjust, zeroing;
+       struct mbuf *mp1;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        struct uio io, *uiop = &io;
        u_quad_t cur_usec;
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 #ifndef nolint
@@ -1187,29 +1228,30 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
        if (*ndp) {
            nfsd = *ndp;
            *ndp = NULL;
-           mrep = nfsd->nd_mrep;
-           md = nfsd->nd_md;
-           dpos = nfsd->nd_dpos;
+           info.mrep = nfsd->nd_mrep;
+           info.mreq = NULL;
+           info.md = nfsd->nd_md;
+           info.dpos = nfsd->nd_dpos;
+           info.v3 = (nfsd->nd_flag & ND_NFSV3);
            cred = &nfsd->nd_cr;
-           v3 = (nfsd->nd_flag & ND_NFSV3);
            LIST_INIT(&nfsd->nd_coalesce);
            nfsd->nd_mreq = NULL;
            nfsd->nd_stable = NFSV3WRITE_FILESYNC;
            cur_usec = nfs_curusec();
            nfsd->nd_time = cur_usec +
-               (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
+               (info.v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
     
            /*
             * Now, get the write header..
             */
-           nfsm_srvmtofh(&nfsd->nd_fh);
-           if (v3) {
-               nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
+           NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, &nfsd->nd_fh, &error));
+           if (info.v3) {
+               NULLOUT(tl = nfsm_dissect(&info, 5 * NFSX_UNSIGNED));
                nfsd->nd_off = fxdr_hyper(tl);
                tl += 3;
                nfsd->nd_stable = fxdr_unsigned(int, *tl++);
            } else {
-               nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, 4 * NFSX_UNSIGNED));
                nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
                tl += 2;
                if (nfs_async)
@@ -1225,14 +1267,14 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
             */
            zeroing = 1;
            i = 0;
-           mp1 = mrep;
+           mp1 = info.mrep;
            while (mp1) {
-               if (mp1 == md) {
+               if (mp1 == info.md) {
                    zeroing = 0;
-                   adjust = dpos - mtod(mp1, caddr_t);
+                   adjust = info.dpos - mtod(mp1, caddr_t);
                    mp1->m_len -= adjust;
                    if (mp1->m_len > 0 && adjust > 0)
-                       NFSMADV(mp1, adjust);
+                       mp1->m_data += adjust;
                }
                if (zeroing)
                    mp1->m_len = 0;
@@ -1247,12 +1289,15 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
            }
            if (len > NFS_MAXDATA || len < 0  || i < len) {
 nfsmout:
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
                error = EIO;
-               nfsm_writereply(2 * NFSX_UNSIGNED, v3);
-               if (v3)
-                   nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
-               nfsd->nd_mreq = mreq;
+               nfsm_writereply(&info, nfsd, slp, error, 2 * NFSX_UNSIGNED);
+               if (info.v3) {
+                   nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                    aftat_ret, &va);
+               }
+               nfsd->nd_mreq = info.mreq;
                nfsd->nd_mrep = NULL;
                nfsd->nd_time = 0;
            }
@@ -1323,18 +1368,18 @@ loop1:
                LIST_REMOVE(nfsd, nd_tq);
                LIST_REMOVE(nfsd, nd_hash);
                crit_exit();
-               mrep = nfsd->nd_mrep;
+               info.mrep = nfsd->nd_mrep;
+               info.v3 = (nfsd->nd_flag & ND_NFSV3);
                nfsd->nd_mrep = NULL;
                cred = &nfsd->nd_cr;
-               v3 = (nfsd->nd_flag & ND_NFSV3);
                forat_ret = aftat_ret = 1;
                error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &mp, &vp, cred, slp, 
                    nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
                if (!error) {
-                   if (v3)
+                   if (info.v3)
                        forat_ret = VOP_GETATTR(vp, &forat);
                    if (vp->v_type != VREG) {
-                       if (v3)
+                       if (info.v3)
                            error = EINVAL;
                        else
                            error = (vp->v_type == VDIR) ? EISDIR : EACCES;
@@ -1358,7 +1403,7 @@ loop1:
                uiop->uio_offset = nfsd->nd_off;
                uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
                if (uiop->uio_resid > 0) {
-                   mp1 = mrep;
+                   mp1 = info.mrep;
                    i = 0;
                    while (mp1) {
                        if (mp1->m_len > 0)
@@ -1369,7 +1414,7 @@ loop1:
                    MALLOC(iov, struct iovec *, i * sizeof (struct iovec), 
                        M_TEMP, M_WAITOK);
                    uiop->uio_iov = ivp = iov;
-                   mp1 = mrep;
+                   mp1 = info.mrep;
                    while (mp1) {
                        if (mp1->m_len > 0) {
                            ivp->iov_base = mtod(mp1, caddr_t);
@@ -1384,7 +1429,8 @@ loop1:
                    }
                    FREE((caddr_t)iov, M_TEMP);
                }
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
                if (vp) {
                    aftat_ret = VOP_GETATTR(vp, &va);
                    vput(vp);
@@ -1399,17 +1445,22 @@ loop1:
                do {
                    NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
                    if (error) {
-                       nfsm_writereply(NFSX_WCCDATA(v3), v3);
-                       if (v3) {
-                           nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
+                       nfsm_writereply(&info, nfsd, slp, error,
+                                       NFSX_WCCDATA(info.v3));
+                       if (info.v3) {
+                           nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                            aftat_ret, &va);
                        }
                    } else {
-                       nfsm_writereply(NFSX_PREOPATTR(v3) +
-                           NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
-                           NFSX_WRITEVERF(v3), v3);
-                       if (v3) {
-                           nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
-                           nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+                       nfsm_writereply(&info, nfsd, slp, error,
+                                       NFSX_PREOPATTR(info.v3) +
+                                       NFSX_POSTOPORFATTR(info.v3) +
+                                       2 * NFSX_UNSIGNED +
+                                       NFSX_WRITEVERF(info.v3));
+                       if (info.v3) {
+                           nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
+                                            aftat_ret, &va);
+                           tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
                            *tl++ = txdr_unsigned(nfsd->nd_len);
                            *tl++ = txdr_unsigned(swp->nd_stable);
                            /*
@@ -1422,11 +1473,11 @@ loop1:
                            *tl++ = txdr_unsigned(nfsver.tv_sec);
                            *tl = txdr_unsigned(nfsver.tv_nsec / 1000);
                        } else {
-                           nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
-                           nfsm_srvfillattr(&va, fp);
+                           fp = nfsm_build(&info, NFSX_V2FATTR);
+                           nfsm_srvfattr(nfsd, &va, fp);
                        }
                    }
-                   nfsd->nd_mreq = mreq;
+                   nfsd->nd_mreq = info.mreq;
                    if (nfsd->nd_mrep)
                        panic("nfsrv_write: nd_mrep not free");
 
@@ -1528,9 +1579,7 @@ int
 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct nfs_fattr *fp;
        struct vattr va, dirfor, diraft;
@@ -1538,14 +1587,10 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct nfsv2_sattr *sp;
        u_int32_t *tl;
        struct nlookupdata nd;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1;
        udev_t rdev = NOUDEV;
-       int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
        caddr_t cp;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
+       int how, exclusive_flag = 0;
        struct vnode *dirp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -1554,6 +1599,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        fhandle_t *fhp;
        u_quad_t tempsize;
        u_char cverf[NFSX_V3CREATEVERF];
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -1561,9 +1607,15 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        dvp = NULL;
        vp = NULL;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        /*
         * Call namei and do initial cleanup to get a few things
@@ -1575,12 +1627,12 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         * prior to calling nfsm_reply ( which might goto nfsmout ).
         */
        error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
-                         fhp, len, slp, nam, &md, &dpos, &dirp,
+                         fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        mp = vfs_getvfs(&fhp->fh_fsid);
 
        if (dirp) {
-               if (v3) {
+               if (info.v3) {
                        dirfor_ret = VOP_GETATTR(dirp, &dirfor);
                } else {
                        vrele(dirp);
@@ -1588,8 +1640,10 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                }
        }
        if (error) {
-               nfsm_reply(NFSX_WCCDATA(v3));
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_WCCDATA(info.v3), &error));
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
                goto nfsmout;
        }
@@ -1608,8 +1662,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         */
 
        VATTR_NULL(vap);
-       if (v3) {
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+       if (info.v3) {
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                how = fxdr_unsigned(int, *tl);
                switch (how) {
                case NFSV3CREATE_GUARDED:
@@ -1619,17 +1673,17 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                        }
                        /* fall through */
                case NFSV3CREATE_UNCHECKED:
-                       nfsm_srvsattr(vap);
+                       ERROROUT(nfsm_srvsattr(&info, vap));
                        break;
                case NFSV3CREATE_EXCLUSIVE:
-                       nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
+                       NULLOUT(cp = nfsm_dissect(&info, NFSX_V3CREATEVERF));
                        bcopy(cp, cverf, NFSX_V3CREATEVERF);
                        exclusive_flag = 1;
                        break;
                };
                vap->va_type = VREG;
        } else {
-               nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+               NULLOUT(sp = nfsm_dissect(&info, NFSX_V2SATTR));
                vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
                if (vap->va_type == VNON)
                        vap->va_type = VREG;
@@ -1729,7 +1783,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                        nd.ni_dvp = NULL;
 
                        if (error != 0) {
-                               nfsm_reply(0);
+                               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                                     0, &error));
                                /* fall through on certain errors */
                        }
                        nfsrv_object_create(nd.ni_vp);
@@ -1760,7 +1815,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                if (!error)
                        error = VOP_GETATTR(vp, vap);
        }
-       if (v3) {
+       if (info.v3) {
                if (exclusive_flag && !error &&
                        bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
                        error = EEXIST;
@@ -1768,27 +1823,32 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                vrele(dirp);
                dirp = NULL;
        }
-       nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
-       if (v3) {
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_SRVFH(info.v3) + NFSX_FATTR(info.v3) +
+                             NFSX_WCCDATA(info.v3),
+                             &error));
+       if (info.v3) {
                if (!error) {
-                       nfsm_srvpostop_fh(fhp);
-                       nfsm_srvpostop_attr(0, vap);
+                       nfsm_srvpostop_fh(&info, fhp);
+                       nfsm_srvpostop_attr(&info, nfsd, 0, vap);
                }
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
        } else {
-               nfsm_srvfhtom(fhp, v3);
-               nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
-               nfsm_srvfillattr(vap, fp);
+               nfsm_srvfhtom(&info, fhp);
+               fp = nfsm_build(&info, NFSX_V2FATTR);
+               nfsm_srvfattr(nfsd, vap, fp);
        }
        goto nfsmout;
 
 nfsmreply0:
-       nfsm_reply(0);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
        error = 0;
        /* fall through */
 
 nfsmout:
+       info.mreq = NULL;
        if (dirp)
                vrele(dirp);
        nlookup_done(&nd);
@@ -1810,25 +1870,20 @@ int
 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
            struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct vattr va, dirfor, diraft;
        struct vattr *vap = &va;
        u_int32_t *tl;
        struct nlookupdata nd;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
        enum vtype vtyp;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct vnode *dirp;
        struct vnode *dvp;
        struct vnode *vp;
        nfsfh_t nfh;
        fhandle_t *fhp;
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -1836,9 +1891,14 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        dvp = NULL;
        vp = NULL;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        /*
         * Handle nfs_namei() call.  If an error occurs, the nd structure
@@ -1847,26 +1907,28 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         */
 
        error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
-                         fhp, len, slp, nam, &md, &dpos, &dirp,
+                         fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (dirp)
                dirfor_ret = VOP_GETATTR(dirp, &dirfor);
        if (error) {
-               nfsm_reply(NFSX_WCCDATA(1));
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                          NFSX_WCCDATA(1), &error));
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
                goto nfsmout;
        }
-       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+       NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
        vtyp = nfsv3tov_type(*tl);
        if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
                error = NFSERR_BADTYPE;
                goto out;
        }
        VATTR_NULL(vap);
-       nfsm_srvsattr(vap);
+       ERROROUT(nfsm_srvsattr(&info, vap));
        if (vtyp == VCHR || vtyp == VBLK) {
-               nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                vap->va_rmajor = fxdr_unsigned(u_int32_t, *tl++);
                vap->va_rminor = fxdr_unsigned(u_int32_t, *tl);
        }
@@ -1925,14 +1987,18 @@ out:
                vrele(dirp);
                dirp = NULL;
        }
-       nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) +
+                             NFSX_WCCDATA(1), &error));
        if (!error) {
-               nfsm_srvpostop_fh(fhp);
-               nfsm_srvpostop_attr(0, vap);
+               nfsm_srvpostop_fh(&info, fhp);
+               nfsm_srvpostop_attr(&info, nfsd, 0, vap);
        }
-       nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+       nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                        diraft_ret, &diraft);
        return (0);
 nfsmout:
+       *mrq = info.mreq;
        if (dirp)
                vrele(dirp);
        nlookup_done(&nd);
@@ -1954,24 +2020,17 @@ int
 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct nlookupdata nd;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mreq;
        struct vnode *dirp;
        struct vnode *dvp;
        struct vnode *vp;
        struct vattr dirfor, diraft;
        nfsfh_t nfh;
        fhandle_t *fhp;
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -1979,15 +2038,21 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        dvp = NULL;
        vp = NULL;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        error = nfs_namei(&nd, cred, NLC_DELETE, &dvp, &vp,
-                         fhp, len, slp, nam, &md, &dpos, &dirp,
+                         fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (dirp) {
-               if (v3)
+               if (info.v3)
                        dirfor_ret = VOP_GETATTR(dirp, &dirfor);
        }
        if (error == 0) {
@@ -2015,14 +2080,16 @@ out:
                        dvp = NULL;
                }
        }
-       if (dirp && v3)
+       if (dirp && info.v3)
                diraft_ret = VOP_GETATTR(dirp, &diraft);
-       nfsm_reply(NFSX_WCCDATA(v3));
-       if (v3) {
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_WCCDATA(info.v3), &error));
+       if (info.v3) {
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
        }
 nfsmout:
+       *mrq = info.mreq;
        nlookup_done(&nd);
        if (dirp)
                vrele(dirp);
@@ -2044,18 +2111,10 @@ int
 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
        int tdirfor_ret = 1, tdiraft_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mreq;
        struct nlookupdata fromnd, tond;
        struct vnode *fvp, *fdirp, *fdvp;
        struct vnode *tvp, *tdirp, *tdvp;
@@ -2064,6 +2123,13 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        nfsfh_t fnfh, tnfh;
        fhandle_t *ffhp, *tfhp;
        uid_t saved_uid;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
 #ifndef nolint
@@ -2081,8 +2147,9 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        fdirp = NULL;
        tdirp = NULL;
 
-       nfsm_srvmtofh(ffhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, ffhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
+
        /*
         * Remember our original uid so that we can reset cr_uid before
         * the second nfs_namei() call, in case it is remapped.
@@ -2090,16 +2157,19 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        saved_uid = cred->cr_uid;
        error = nfs_namei(&fromnd, cred, NLC_RENAME_SRC,
                          NULL, NULL,
-                         ffhp, len, slp, nam, &md, &dpos, &fdirp,
+                         ffhp, len, slp, nam, &info.md, &info.dpos, &fdirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (fdirp) {
-               if (v3)
+               if (info.v3)
                        fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor);
        }
        if (error) {
-               nfsm_reply(2 * NFSX_WCCDATA(v3));
-               nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
-               nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_WCCDATA(info.v3), &error));
+               nfsm_srvwcc_data(&info, nfsd, fdirfor_ret, &fdirfor,
+                                fdiraft_ret, &fdiraft);
+               nfsm_srvwcc_data(&info, nfsd, tdirfor_ret, &tdirfor,
+                                tdiraft_ret, &tdiraft);
                error = 0;
                goto nfsmout;
        }
@@ -2111,15 +2181,15 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED);
        cache_unlock(&fromnd.nl_nch);
        fromnd.nl_flags &= ~NLC_NCPISLOCKED;
-       nfsm_srvmtofh(tfhp);
-       nfsm_strsiz(len2, NFS_MAXNAMLEN);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, tfhp, &error));
+       NEGATIVEOUT(len2 = nfsm_strsiz(&info, NFS_MAXNAMLEN));
        cred->cr_uid = saved_uid;
 
        error = nfs_namei(&tond, cred, NLC_RENAME_DST, NULL, NULL,
-                         tfhp, len2, slp, nam, &md, &dpos, &tdirp,
+                         tfhp, len2, slp, nam, &info.md, &info.dpos, &tdirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (tdirp) {
-               if (v3)
+               if (info.v3)
                        tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor);
        }
        if (error)
@@ -2165,20 +2235,20 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 
        if (tvp != NULL) {
                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
-                       if (v3)
+                       if (info.v3)
                                error = EEXIST;
                        else
                                error = EISDIR;
                        goto out;
                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
-                       if (v3)
+                       if (info.v3)
                                error = EEXIST;
                        else
                                error = ENOTDIR;
                        goto out;
                }
                if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
-                       if (v3)
+                       if (info.v3)
                                error = EXDEV;
                        else
                                error = ENOTEMPTY;
@@ -2186,21 +2256,21 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                }
        }
        if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
-               if (v3)
+               if (info.v3)
                        error = EXDEV;
                else
                        error = ENOTEMPTY;
                goto out;
        }
        if (fromnd.nl_nch.mount != tond.nl_nch.mount) {
-               if (v3)
+               if (info.v3)
                        error = EXDEV;
                else
                        error = ENOTEMPTY;
                goto out;
        }
        if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) {
-               if (v3)
+               if (info.v3)
                        error = EINVAL;
                else
                        error = ENOTEMPTY;
@@ -2247,15 +2317,19 @@ out1:
                fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft);
        if (tdirp)
                tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft);
-       nfsm_reply(2 * NFSX_WCCDATA(v3));
-       if (v3) {
-               nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
-               nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             2 * NFSX_WCCDATA(info.v3), &error));
+       if (info.v3) {
+               nfsm_srvwcc_data(&info, nfsd, fdirfor_ret, &fdirfor,
+                                fdiraft_ret, &fdiraft);
+               nfsm_srvwcc_data(&info, nfsd, tdirfor_ret, &tdirfor,
+                                tdiraft_ret, &tdiraft);
        }
        error = 0;
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        if (tdirp)
                vrele(tdirp);
        nlookup_done(&tond);
@@ -2272,18 +2346,11 @@ int
 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
           struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct nlookupdata nd;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
-       int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mreq;
+       int getret = 1;
        struct vnode *dirp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -2293,6 +2360,13 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct vattr dirfor, diraft, at;
        nfsfh_t nfh, dnfh;
        fhandle_t *fhp, *dfhp;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -2301,16 +2375,20 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 
        fhp = &nfh.fh_generic;
        dfhp = &dnfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvmtofh(dfhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, dfhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        error = nfsrv_fhtovp(fhp, FALSE, &xmp, &xp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
-               nfsm_srvpostop_attr(getret, &at);
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_POSTOPATTR(info.v3) +
+                                     NFSX_WCCDATA(info.v3),
+                                     &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                xp = NULL;
                error = 0;
                goto nfsmout;
@@ -2321,10 +2399,10 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        }
 
        error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
-                         dfhp, len, slp, nam, &md, &dpos, &dirp,
+                         dfhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (dirp) {
-               if (v3)
+               if (info.v3)
                        dirfor_ret = VOP_GETATTR(dirp, &dirfor);
        }
        if (error)
@@ -2346,19 +2424,23 @@ out:
        /* fall through */
 
 out1:
-       if (v3)
+       if (info.v3)
                getret = VOP_GETATTR(xp, &at);
        if (dirp)
                diraft_ret = VOP_GETATTR(dirp, &diraft);
-       nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
-       if (v3) {
-               nfsm_srvpostop_attr(getret, &at);
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_POSTOPATTR(info.v3) + NFSX_WCCDATA(info.v3),
+                             &error));
+       if (info.v3) {
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
        }
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        nlookup_done(&nd);
        if (dirp)
                vrele(dirp);
@@ -2382,27 +2464,22 @@ int
 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
              struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct vattr va, dirfor, diraft;
        struct nlookupdata nd;
        struct vattr *vap = &va;
-       u_int32_t *tl;
-       int32_t t1;
        struct nfsv2_sattr *sp;
-       char *bpos, *pathcp = NULL, *cp2;
+       char *pathcp = NULL;
        struct uio io;
        struct iovec iv;
        int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       struct mbuf *mb, *mreq, *mb2;
        struct vnode *dirp;
        struct vnode *vp;
        struct vnode *dvp;
        nfsfh_t nfh;
        fhandle_t *fhp;
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -2410,24 +2487,31 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        dvp = NULL;
        vp = NULL;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq =  NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
-                       fhp, len, slp, nam, &md, &dpos, &dirp,
+                       fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                        td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (dirp) {
-               if (v3)
+               if (info.v3)
                        dirfor_ret = VOP_GETATTR(dirp, &dirfor);
        }
        if (error)
                goto out;
 
        VATTR_NULL(vap);
-       if (v3)
-               nfsm_srvsattr(vap);
-       nfsm_strsiz(len2, NFS_MAXPATHLEN);
+       if (info.v3) {
+               ERROROUT(nfsm_srvsattr(&info, vap));
+       }
+       NEGATIVEOUT(len2 = nfsm_strsiz(&info, NFS_MAXPATHLEN));
        MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
        iv.iov_base = pathcp;
        iv.iov_len = len2;
@@ -2438,9 +2522,9 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        io.uio_segflg = UIO_SYSSPACE;
        io.uio_rw = UIO_READ;
        io.uio_td = NULL;
-       nfsm_mtouio(&io, len2);
-       if (!v3) {
-               nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+       ERROROUT(nfsm_mtouio(&info, &io, len2));
+       if (info.v3 == 0) {
+               NULLOUT(sp = nfsm_dissect(&info, NFSX_V2SATTR));
                vap->va_mode = nfstov_mode(sp->sa_mode);
        }
        *(pathcp + len2) = '\0';
@@ -2483,18 +2567,23 @@ out:
                vrele(dirp);
                dirp = NULL;
        }
-       nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
-       if (v3) {
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_SRVFH(info.v3) + NFSX_POSTOPATTR(info.v3) +
+                             NFSX_WCCDATA(info.v3),
+                             &error));
+       if (info.v3) {
                if (!error) {
-                       nfsm_srvpostop_fh(fhp);
-                       nfsm_srvpostop_attr(0, vap);
+                       nfsm_srvpostop_fh(&info, fhp);
+                       nfsm_srvpostop_attr(&info, nfsd, 0, vap);
                }
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
        }
        error = 0;
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        nlookup_done(&nd);
        if (vp)
                vput(vp);
@@ -2512,27 +2601,20 @@ int
 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
            struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct vattr va, dirfor, diraft;
        struct vattr *vap = &va;
        struct nfs_fattr *fp;
        struct nlookupdata nd;
-       caddr_t cp;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct vnode *dirp;
        struct vnode *dvp;
        struct vnode *vp;
        nfsfh_t nfh;
        fhandle_t *fhp;
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -2540,28 +2622,36 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        dvp = NULL;
        vp = NULL;
 
+       info.dpos = nfsd->nd_dpos;
+       info.mrep = nfsd->nd_mrep;
+       info.mreq =  NULL;
+       info.md = nfsd->nd_md;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
-                         fhp, len, slp, nam, &md, &dpos, &dirp,
+                         fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (dirp) {
-               if (v3)
+               if (info.v3)
                        dirfor_ret = VOP_GETATTR(dirp, &dirfor);
        }
        if (error) {
-               nfsm_reply(NFSX_WCCDATA(v3));
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_WCCDATA(info.v3), &error));
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
                goto nfsmout;
        }
        VATTR_NULL(vap);
-       if (v3) {
-               nfsm_srvsattr(vap);
+       if (info.v3) {
+               ERROROUT(nfsm_srvsattr(&info, vap));
        } else {
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                vap->va_mode = nfstov_mode(*tl++);
        }
 
@@ -2597,22 +2687,27 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 out:
        if (dirp)
                diraft_ret = VOP_GETATTR(dirp, &diraft);
-       nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
-       if (v3) {
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_SRVFH(info.v3) + NFSX_POSTOPATTR(info.v3) +
+                             NFSX_WCCDATA(info.v3),
+                             &error));
+       if (info.v3) {
                if (!error) {
-                       nfsm_srvpostop_fh(fhp);
-                       nfsm_srvpostop_attr(0, vap);
+                       nfsm_srvpostop_fh(&info, fhp);
+                       nfsm_srvpostop_attr(&info, nfsd, 0, vap);
                }
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
        } else {
-               nfsm_srvfhtom(fhp, v3);
-               nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
-               nfsm_srvfillattr(vap, fp);
+               nfsm_srvfhtom(&info, fhp);
+               fp = nfsm_build(&info, NFSX_V2FATTR);
+               nfsm_srvfattr(nfsd, vap, fp);
        }
        error = 0;
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        nlookup_done(&nd);
        if (dirp)
                vrele(dirp);
@@ -2634,17 +2729,9 @@ int
 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
            struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mreq;
        struct vnode *dirp;
        struct vnode *dvp;
        struct vnode *vp;
@@ -2652,6 +2739,7 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        nfsfh_t nfh;
        fhandle_t *fhp;
        struct nlookupdata nd;
+       struct nfsm_info info;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        nlookup_zero(&nd);
@@ -2659,20 +2747,28 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        dvp = NULL;
        vp = NULL;
 
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
+
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_srvnamesiz(len);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
 
        error = nfs_namei(&nd, cred, NLC_DELETE, &dvp, &vp,
-                         fhp, len, slp, nam, &md, &dpos, &dirp,
+                         fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
                          td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
        if (dirp) {
-               if (v3)
+               if (info.v3)
                        dirfor_ret = VOP_GETATTR(dirp, &dirfor);
        }
        if (error) {
-               nfsm_reply(NFSX_WCCDATA(v3));
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_WCCDATA(info.v3), &error));
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
                goto nfsmout;
        }
@@ -2704,14 +2800,16 @@ out:
 
        if (dirp)
                diraft_ret = VOP_GETATTR(dirp, &diraft);
-       nfsm_reply(NFSX_WCCDATA(v3));
-       if (v3) {
-               nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_WCCDATA(info.v3), &error));
+       if (info.v3) {
+               nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
+                                diraft_ret, &diraft);
                error = 0;
        }
        /* fall through */
 
 nfsmout:
+       *mrq = info.mreq;
        if (dvp) {
                if (dvp == vp)
                        vrele(dvp);
@@ -2768,18 +2866,14 @@ int
 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
              struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        char *bp, *be;
        struct dirent *dp;
        caddr_t cp;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
-       struct mbuf *mb, *mb2, *mreq, *mp1, *mp2;
-       char *cpos, *cend, *cp2, *rbuf;
+       struct mbuf *mp1, *mp2;
+       char *cpos, *cend, *rbuf;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        struct vattr at;
@@ -2789,21 +2883,27 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        struct iovec iv;
        int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
        int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
        u_quad_t off, toff, verf;
        off_t *cookies = NULL, *cookiep;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       if (v3) {
-               nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       if (info.v3) {
+               NULLOUT(tl = nfsm_dissect(&info, 5 * NFSX_UNSIGNED));
                toff = fxdr_hyper(tl);
                tl += 2;
                verf = fxdr_hyper(tl);
                tl += 2;
        } else {
-               nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                toff = fxdr_unsigned(u_quad_t, *tl++);
                verf = 0;       /* shut up gcc */
        }
@@ -2824,8 +2924,8 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                vp = NULL;
        }
        if (error) {
-               nfsm_reply(NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -2834,7 +2934,7 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
         * Obtain lock on vnode for this section of the code
         */
 
-       if (v3) {
+       if (info.v3) {
                error = getret = VOP_GETATTR(vp, &at);
 #if 0
                /*
@@ -2849,8 +2949,9 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        if (error) {
                vput(vp);
                vp = NULL;
-               nfsm_reply(NFSX_POSTOPATTR(v3));
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_POSTOPATTR(info.v3), &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -2879,7 +2980,7 @@ again:
        off = (off_t)io.uio_offset;
        if (!cookies && !error)
                error = NFSERR_PERM;
-       if (v3) {
+       if (info.v3) {
                getret = VOP_GETATTR(vp, &at);
                if (!error)
                        error = getret;
@@ -2890,8 +2991,9 @@ again:
                kfree((caddr_t)rbuf, M_TEMP);
                if (cookies)
                        kfree((caddr_t)cookies, M_TEMP);
-               nfsm_reply(NFSX_POSTOPATTR(v3));
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_POSTOPATTR(info.v3), &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -2905,15 +3007,18 @@ again:
                if (siz == 0) {
                        vrele(vp);
                        vp = NULL;
-                       nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
-                               2 * NFSX_UNSIGNED);
-                       if (v3) {
-                               nfsm_srvpostop_attr(getret, &at);
-                               nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+                       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                             NFSX_POSTOPATTR(info.v3) +
+                                             NFSX_COOKIEVERF(info.v3) +
+                                             2 * NFSX_UNSIGNED,
+                                             &error));
+                       if (info.v3) {
+                               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+                               tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
                                txdr_hyper(at.va_filerev, tl);
                                tl += 2;
                        } else
-                               nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                               tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
                        *tl++ = nfs_false;
                        *tl = nfs_true;
                        FREE((caddr_t)rbuf, M_TEMP);
@@ -2953,14 +3058,17 @@ again:
        }
 
        len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
-       nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
-       if (v3) {
-               nfsm_srvpostop_attr(getret, &at);
-               nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_POSTOPATTR(info.v3) +
+                             NFSX_COOKIEVERF(info.v3) + siz,
+                             &error));
+       if (info.v3) {
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+               tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
                txdr_hyper(at.va_filerev, tl);
        }
-       mp1 = mp2 = mb;
-       bp = bpos;
+       mp1 = mp2 = info.mb;
+       bp = info.bpos;
        be = bp + M_TRAILINGSPACE(mp1);
 
        /* Loop through the records and build reply */
@@ -2969,7 +3077,7 @@ again:
                        nlen = dp->d_namlen;
                        rem = nfsm_rndup(nlen) - nlen;
                        len += (4 * NFSX_UNSIGNED + nlen + rem);
-                       if (v3)
+                       if (info.v3)
                                len += 2 * NFSX_UNSIGNED;
                        if (len > cnt) {
                                eofflag = 0;
@@ -2979,18 +3087,18 @@ again:
                         * Build the directory record xdr from
                         * the dirent entry.
                         */
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = nfs_true;
                        bp += NFSX_UNSIGNED;
-                       if (v3) {
-                               nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       if (info.v3) {
+                               tl = nfsm_clget(&info, mp1, mp2, bp, be);
                                *tl = 0;
                                bp += NFSX_UNSIGNED;
                        }
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = txdr_unsigned(dp->d_ino);
                        bp += NFSX_UNSIGNED;
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = txdr_unsigned(nlen);
                        bp += NFSX_UNSIGNED;
 
@@ -2998,7 +3106,7 @@ again:
                        xfer = nlen;
                        cp = dp->d_name;
                        while (xfer > 0) {
-                               nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                               tl = nfsm_clget(&info, mp1, mp2, bp, be);
                                if ((bp+xfer) > be)
                                        tsiz = be-bp;
                                else
@@ -3012,13 +3120,13 @@ again:
                        /* And null pad to a int32_t boundary */
                        for (i = 0; i < rem; i++)
                                *bp++ = '\0';
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
 
                        /* Finish off the record */
-                       if (v3) {
+                       if (info.v3) {
                                *tl = txdr_unsigned(*cookiep >> 32);
                                bp += NFSX_UNSIGNED;
-                               nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                               tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        }
                        *tl = txdr_unsigned(*cookiep);
                        bp += NFSX_UNSIGNED;
@@ -3030,24 +3138,25 @@ again:
        }
        vrele(vp);
        vp = NULL;
-       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+       tl = nfsm_clget(&info, mp1, mp2, bp, be);
        *tl = nfs_false;
        bp += NFSX_UNSIGNED;
-       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+       tl = nfsm_clget(&info, mp1, mp2, bp, be);
        if (eofflag)
                *tl = nfs_true;
        else
                *tl = nfs_false;
        bp += NFSX_UNSIGNED;
-       if (mp1 != mb) {
+       if (mp1 != info.mb) {
                if (bp < be)
                        mp1->m_len = bp - mtod(mp1, caddr_t);
        } else
-               mp1->m_len += bp - bpos;
+               mp1->m_len += bp - info.bpos;
        FREE((caddr_t)rbuf, M_TEMP);
        FREE((caddr_t)cookies, M_TEMP);
 
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vrele(vp);
        return(error);
@@ -3057,18 +3166,14 @@ int
 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                  struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        char *bp, *be;
        struct dirent *dp;
        caddr_t cp;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
-       struct mbuf *mb, *mb2, *mreq, *mp1, *mp2;
-       char *cpos, *cend, *cp2, *rbuf;
+       struct mbuf *mp1, *mp2;
+       char *cpos, *cend, *rbuf;
        struct vnode *vp = NULL, *nvp;
        struct mount *mp = NULL;
        struct flrep fl;
@@ -3082,11 +3187,17 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
        u_quad_t off, toff, verf;
        off_t *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NULLOUT(tl = nfsm_dissect(&info, 6 * NFSX_UNSIGNED));
        toff = fxdr_hyper(tl);
        tl += 2;
        verf = fxdr_hyper(tl);
@@ -3109,8 +3220,8 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                vp = NULL;
        }
        if (error) {
-               nfsm_reply(NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3128,8 +3239,9 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        if (error) {
                vput(vp);
                vp = NULL;
-               nfsm_reply(NFSX_V3POSTOPATTR);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_V3POSTOPATTR, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3163,8 +3275,9 @@ again:
                if (cookies)
                        kfree((caddr_t)cookies, M_TEMP);
                kfree((caddr_t)rbuf, M_TEMP);
-               nfsm_reply(NFSX_V3POSTOPATTR);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_V3POSTOPATTR, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3178,10 +3291,13 @@ again:
                if (siz == 0) {
                        vrele(vp);
                        vp = NULL;
-                       nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
-                               2 * NFSX_UNSIGNED);
-                       nfsm_srvpostop_attr(getret, &at);
-                       nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+                       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                             NFSX_V3POSTOPATTR +
+                                             NFSX_V3COOKIEVERF +
+                                             2 * NFSX_UNSIGNED,
+                                             &error));
+                       nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+                       tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
                        txdr_hyper(at.va_filerev, tl);
                        tl += 2;
                        *tl++ = nfs_false;
@@ -3232,8 +3348,9 @@ again:
                vp = NULL;
                kfree((caddr_t)cookies, M_TEMP);
                kfree((caddr_t)rbuf, M_TEMP);
-               nfsm_reply(NFSX_V3POSTOPATTR);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     NFSX_V3POSTOPATTR, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3242,13 +3359,14 @@ again:
                nvp = NULL;
        }
            
-       dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
-       nfsm_reply(cnt);
-       nfsm_srvpostop_attr(getret, &at);
-       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+       dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
+                       2 * NFSX_UNSIGNED;
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, cnt, &error));
+       nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+       tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
        txdr_hyper(at.va_filerev, tl);
-       mp1 = mp2 = mb;
-       bp = bpos;
+       mp1 = mp2 = info.mb;
+       bp = info.bpos;
        be = bp + M_TRAILINGSPACE(mp1);
 
        /* Loop through the records and build reply */
@@ -3297,23 +3415,23 @@ again:
                         * the dirent entry.
                         */
                        fp = (struct nfs_fattr *)&fl.fl_fattr;
-                       nfsm_srvfillattr(vap, fp);
+                       nfsm_srvfattr(nfsd, vap, fp);
                        fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
                        fl.fl_fhok = nfs_true;
                        fl.fl_postopok = nfs_true;
                        fl.fl_off.nfsuquad[0] = txdr_unsigned(*cookiep >> 32);
                        fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
 
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = nfs_true;
                        bp += NFSX_UNSIGNED;
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = 0;
                        bp += NFSX_UNSIGNED;
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = txdr_unsigned(dp->d_ino);
                        bp += NFSX_UNSIGNED;
-                       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                       tl = nfsm_clget(&info, mp1, mp2, bp, be);
                        *tl = txdr_unsigned(nlen);
                        bp += NFSX_UNSIGNED;
 
@@ -3321,7 +3439,7 @@ again:
                        xfer = nlen;
                        cp = dp->d_name;
                        while (xfer > 0) {
-                               nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                               tl = nfsm_clget(&info, mp1, mp2, bp, be);
                                if ((bp + xfer) > be)
                                        tsiz = be - bp;
                                else
@@ -3342,7 +3460,7 @@ again:
                        xfer = sizeof (struct flrep);
                        cp = (caddr_t)&fl;
                        while (xfer > 0) {
-                               nfsm_clget(mp1, mp2, mb, bp, be, tl);
+                               tl = nfsm_clget(&info, mp1, mp2, bp, be);
                                if ((bp + xfer) > be)
                                        tsiz = be - bp;
                                else
@@ -3362,23 +3480,24 @@ invalid:
        }
        vrele(vp);
        vp = NULL;
-       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+       tl = nfsm_clget(&info, mp1, mp2, bp, be);
        *tl = nfs_false;
        bp += NFSX_UNSIGNED;
-       nfsm_clget(mp1, mp2, mb, bp, be, tl);
+       tl = nfsm_clget(&info, mp1, mp2, bp, be);
        if (eofflag)
                *tl = nfs_true;
        else
                *tl = nfs_false;
        bp += NFSX_UNSIGNED;
-       if (mp1 != mb) {
+       if (mp1 != info.mb) {
                if (bp < be)
                        mp1->m_len = bp - mtod(mp1, caddr_t);
        } else
-               mp1->m_len += bp - bpos;
+               mp1->m_len += bp - info.bpos;
        FREE((caddr_t)cookies, M_TEMP);
        FREE((caddr_t)rbuf, M_TEMP);
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vrele(vp);
        return(error);
@@ -3391,9 +3510,7 @@ int
 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct vattr bfor, aft;
        struct vnode *vp = NULL;
@@ -3401,17 +3518,19 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        nfsfh_t nfh;
        fhandle_t *fhp;
        u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        u_quad_t off;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
-       nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
+       NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
 
        /*
         * XXX At this time VOP_FSYNC() does not accept offset and byte
@@ -3423,8 +3542,10 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(2 * NFSX_UNSIGNED);
-               nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                                     2 * NFSX_UNSIGNED, &error));
+               nfsm_srvwcc_data(&info, nfsd, for_ret, &bfor,
+                                aft_ret, &aft);
                error = 0;
                goto nfsmout;
        }
@@ -3503,10 +3624,13 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        aft_ret = VOP_GETATTR(vp, &aft);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
-       nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_V3WCCDATA + NFSX_V3WRITEVERF,
+                             &error));
+       nfsm_srvwcc_data(&info, nfsd, for_ret, &bfor,
+                        aft_ret, &aft);
        if (!error) {
-               nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
+               tl = nfsm_build(&info, NFSX_V3WRITEVERF);
                if (nfsver.tv_sec == 0)
                        nfsver = boottime;
                *tl++ = txdr_unsigned(nfsver.tv_sec);
@@ -3515,6 +3639,7 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                error = 0;
        }
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -3527,19 +3652,11 @@ int
 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
        struct statfs *sf;
        struct nfs_statfs *sfp;
-       u_int32_t *tl;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, getret = 1;
-       int v3 = (nfsd->nd_flag & ND_NFSV3);
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        struct vattr at;
@@ -3547,15 +3664,22 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        fhandle_t *fhp;
        struct statfs statfs;
        u_quad_t tval;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
+       info.v3 = (nfsd->nd_flag & ND_NFSV3);
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3564,15 +3688,17 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        getret = VOP_GETATTR(vp, &at);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
-       if (v3)
-               nfsm_srvpostop_attr(getret, &at);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_POSTOPATTR(info.v3) + NFSX_STATFS(info.v3),
+                             &error));
+       if (info.v3)
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
        if (error) {
                error = 0;
                goto nfsmout;
        }
-       nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
-       if (v3) {
+       sfp = nfsm_build(&info, NFSX_STATFS(info.v3));
+       if (info.v3) {
                tval = (u_quad_t)sf->f_blocks;
                tval *= (u_quad_t)sf->f_bsize;
                txdr_hyper(tval, &sfp->sf_tbytes);
@@ -3597,6 +3723,7 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
        }
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -3609,17 +3736,10 @@ int
 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
             struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
-       u_int32_t *tl;
        struct nfsv3_fsinfo *sip;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, getret = 1, pref;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        struct vattr at;
@@ -3627,15 +3747,21 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        fhandle_t *fhp;
        u_quad_t maxfsize;
        struct statfs sb;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3647,9 +3773,10 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        getret = VOP_GETATTR(vp, &at);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
-       nfsm_srvpostop_attr(getret, &at);
-       nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_V3POSTOPATTR + NFSX_V3FSINFO, &error));
+       nfsm_srvpostop_attr(&info, nfsd, getret, &at);
+       sip = nfsm_build(&info, NFSX_V3FSINFO);
 
        /*
         * XXX
@@ -3674,6 +3801,7 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
                NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
                NFSV3FSINFO_CANSETTIME);
 nfsmout:
+       *mrq = info.mreq;
        if (vp)
                vput(vp);
        return(error);
@@ -3686,32 +3814,31 @@ int
 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
               struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
        struct sockaddr *nam = nfsd->nd_nam;
-       caddr_t dpos = nfsd->nd_dpos;
        struct ucred *cred = &nfsd->nd_cr;
-       u_int32_t *tl;
        struct nfsv3_pathconf *pc;
-       int32_t t1;
-       caddr_t bpos;
        int error = 0, rdonly, getret = 1;
        register_t linkmax, namemax, chownres, notrunc;
-       char *cp2;
-       struct mbuf *mb, *mb2, *mreq;
        struct vnode *vp = NULL;
        struct mount *mp = NULL;
        struct vattr at;
        nfsfh_t nfh;
        fhandle_t *fhp;
+       struct nfsm_info info;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
+       info.md = nfsd->nd_md;
+       info.dpos = nfsd->nd_dpos;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        fhp = &nfh.fh_generic;
-       nfsm_srvmtofh(fhp);
+       NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
        error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
                 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
        if (error) {
-               nfsm_reply(NFSX_UNSIGNED);
-               nfsm_srvpostop_attr(getret, &at);
+               NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
+               nfsm_srvpostop_attr(&info, nfsd, getret, &at);
                error = 0;
                goto nfsmout;
        }
@@ -3725,13 +3852,15 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        getret = VOP_GETATTR(vp, &at);
        vput(vp);
        vp = NULL;
-       nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
-       nfsm_srvpostop_attr(getret, &at);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
+                             NFSX_V3POSTOPATTR + NFSX_V3PATHCONF,
+                             &error));
+       nfsm_srvpostop_attr(&info, nfsd, getret, &at);
        if (error) {
                error = 0;
                goto nfsmout;
        }
-       nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
+       pc = nfsm_build(&info, NFSX_V3PATHCONF);
 
        pc->pc_linkmax = txdr_unsigned(linkmax);
        pc->pc_namemax = txdr_unsigned(namemax);
@@ -3746,6 +3875,7 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
        pc->pc_caseinsensitive = nfs_false;
        pc->pc_casepreserving = nfs_true;
 nfsmout:
+       *mrq = info.mreq;
        if (vp) 
                vput(vp);
        return(error);
@@ -3759,14 +3889,17 @@ int
 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
           struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep;
-       caddr_t bpos;
+       struct nfsm_info info;
        int error = NFSERR_RETVOID;
-       struct mbuf *mb, *mreq;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-       nfsm_reply(0);
-       nfsm_srvdone;
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
+nfsmout:
+       *mrq = info.mreq;
+       return (error);
 }
 
 /*
@@ -3777,19 +3910,22 @@ int
 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
           struct thread *td, struct mbuf **mrq)
 {
-       struct mbuf *mrep = nfsd->nd_mrep;
-       caddr_t bpos;
+       struct nfsm_info info;
        int error;
-       struct mbuf *mb, *mreq;
+
+       info.mrep = nfsd->nd_mrep;
+       info.mreq = NULL;
 
        nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
        if (nfsd->nd_repstat)
                error = nfsd->nd_repstat;
        else
                error = EPROCUNAVAIL;
-       nfsm_reply(0);
+       NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
        error = 0;
-       nfsm_srvdone;
+nfsmout:
+       *mrq = info.mreq;
+       return (error);
 }
 
 /*
index 1bbfefa..644ee1e 100644 (file)
@@ -759,12 +759,12 @@ nfs_reply(struct nfsreq *myrep)
 {
        struct nfsreq *rep;
        struct nfsmount *nmp = myrep->r_nmp;
-       int32_t t1;
-       struct mbuf *mrep, *md;
        struct sockaddr *nam;
-       u_int32_t rxid, *tl;
-       caddr_t dpos, cp2;
+       u_int32_t rxid;
+       u_int32_t *tl;
        int error;
+       struct nfsm_info info;
+       int t1;
 
        /*
         * Loop around until we get our own reply
@@ -782,6 +782,8 @@ nfs_reply(struct nfsreq *myrep)
                 * case, the lock is not taken to avoid races with
                 * other processes.
                 */
+               info.mrep = NULL;
+
                error = nfs_rcvlock(myrep);
                if (error == EALREADY)
                        return (0);
@@ -790,7 +792,7 @@ nfs_reply(struct nfsreq *myrep)
                /*
                 * Get the next Rpc reply off the socket
                 */
-               error = nfs_receive(myrep, &nam, &mrep);
+               error = nfs_receive(myrep, &nam, &info.mrep);
                nfs_rcvunlock(myrep);
                if (error) {
                        /*
@@ -810,13 +812,14 @@ nfs_reply(struct nfsreq *myrep)
                /*
                 * Get the xid and check that it is an rpc reply
                 */
-               md = mrep;
-               dpos = mtod(md, caddr_t);
-               nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED);
+               info.md = info.mrep;
+               info.dpos = mtod(info.md, caddr_t);
+               NULLOUT(tl = nfsm_dissect(&info, 2*NFSX_UNSIGNED));
                rxid = *tl++;
                if (*tl != rpc_reply) {
                        nfsstats.rpcinvalid++;
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
 nfsmout:
                        if (myrep->r_flags & R_GETONEREP)
                                return (0);
@@ -841,8 +844,8 @@ nfsmout:
                 * Fill in the rest of the reply if we found a match.
                 */
                if (rep) {
-                       rep->r_md = md;
-                       rep->r_dpos = dpos;
+                       rep->r_md = info.md;
+                       rep->r_dpos = info.dpos;
                        if (nfsrtton) {
                                struct rttl *rt;
 
@@ -901,7 +904,7 @@ nfsmout:
                                NFS_SDRTT(rep) += t1;
                        }
                        nmp->nm_timeouts = 0;
-                       rep->r_mrep = mrep;
+                       rep->r_mrep = info.mrep;
                        mtx_abort_ex_link(&rep->r_nmp->nm_rxlock, &rep->r_link);
                }
                /*
@@ -910,7 +913,8 @@ nfsmout:
                 */
                if (rep == NULL) {
                        nfsstats.rpcunexpected++;
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
                } else if (rep == myrep) {
                        if (rep->r_mrep == NULL)
                                panic("nfsreply nil");
@@ -1187,14 +1191,11 @@ nfs_request_processreply(struct nfsreq *rep, int error)
 {
        struct nfsmount *nmp = rep->r_nmp;
        time_t waituntil;
-       caddr_t dpos, cp2;
-       struct mbuf *mrep;
-       struct mbuf *md;
        u_int32_t *tl;
        int trylater_delay = 15, trylater_cnt = 0;
        int verf_type;
-       int t1;
        int i;
+       struct nfsm_info info;
 
        /*
         * If there was a successful reply and a tprintf msg.
@@ -1203,9 +1204,9 @@ nfs_request_processreply(struct nfsreq *rep, int error)
        if (!error && (rep->r_flags & R_TPRINTFMSG))
                nfs_msg(rep->r_td, nmp->nm_mountp->mnt_stat.f_mntfromname,
                    "is alive again");
-       mrep = rep->r_mrep;
-       md = rep->r_md;
-       dpos = rep->r_dpos;
+       info.mrep = rep->r_mrep;
+       info.md = rep->r_md;
+       info.dpos = rep->r_dpos;
        if (error) {
                m_freem(rep->r_mreq);
                kfree((caddr_t)rep, M_NFSREQ);
@@ -1215,7 +1216,7 @@ nfs_request_processreply(struct nfsreq *rep, int error)
        /*
         * break down the rpc header and check if ok
         */
-       nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+       NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
        if (*tl++ == rpc_msgdenied) {
                if (*tl == rpc_mismatch) {
                        error = EOPNOTSUPP;
@@ -1224,7 +1225,8 @@ nfs_request_processreply(struct nfsreq *rep, int error)
                        if (!rep->r_failed_auth) {
                                rep->r_failed_auth++;
                                rep->r_mheadend->m_next = NULL;
-                               m_freem(mrep);
+                               m_freem(info.mrep);
+                               info.mrep = NULL;
                                m_freem(rep->r_mreq);
                                return (ENEEDAUTH);
                        } else {
@@ -1233,7 +1235,8 @@ nfs_request_processreply(struct nfsreq *rep, int error)
                } else {
                        error = EACCES;
                }
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
                m_freem(rep->r_mreq);
                kfree((caddr_t)rep, M_NFSREQ);
                return (error);
@@ -1245,21 +1248,23 @@ nfs_request_processreply(struct nfsreq *rep, int error)
        verf_type = fxdr_unsigned(int, *tl++);
        i = fxdr_unsigned(int32_t, *tl);
        if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
-               error = nfs_savenickauth(nmp, rep->r_cred, i,
-                                        rep->r_key, &md, &dpos, mrep);
+               error = nfs_savenickauth(nmp, rep->r_cred, i, rep->r_key,
+                                        &info.md, &info.dpos, info.mrep);
                if (error)
                        goto nfsmout;
-       } else if (i > 0)
-               nfsm_adv(nfsm_rndup(i));
-       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+       } else if (i > 0) {
+               ERROROUT(nfsm_adv(&info, nfsm_rndup(i)));
+       }
+       NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
        /* 0 == ok */
        if (*tl == 0) {
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                if (*tl != 0) {
                        error = fxdr_unsigned(int, *tl);
                        if ((nmp->nm_flag & NFSMNT_NFSV3) &&
                                error == NFSERR_TRYLATER) {
-                               m_freem(mrep);
+                               m_freem(info.mrep);
+                               info.mrep = NULL;
                                error = 0;
                                waituntil = time_second + trylater_delay;
                                while (time_second < waituntil)
@@ -1291,25 +1296,28 @@ nfs_request_processreply(struct nfsreq *rep, int error)
                                        lockmgr(&vp->v_lock, ltype);
                        }
                        if (nmp->nm_flag & NFSMNT_NFSV3) {
-                               *rep->r_mrp = mrep;
-                               *rep->r_mdp = md;
-                               *rep->r_dposp = dpos;
+                               *rep->r_mrp = info.mrep;
+                               *rep->r_mdp = info.md;
+                               *rep->r_dposp = info.dpos;
                                error |= NFSERR_RETERR;
-                       } else
-                               m_freem(mrep);
+                       } else {
+                               m_freem(info.mrep);
+                               info.mrep = NULL;
+                       }
                        m_freem(rep->r_mreq);
                        kfree((caddr_t)rep, M_NFSREQ);
                        return (error);
                }
 
-               *rep->r_mrp = mrep;
-               *rep->r_mdp = md;
-               *rep->r_dposp = dpos;
+               *rep->r_mrp = info.mrep;
+               *rep->r_mdp = info.md;
+               *rep->r_dposp = info.dpos;
                m_freem(rep->r_mreq);
                FREE((caddr_t)rep, M_NFSREQ);
                return (0);
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
        error = EPROTONOSUPPORT;
 nfsmout:
        m_freem(rep->r_mreq);
@@ -1327,22 +1335,21 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
            int err, struct mbuf **mrq, struct mbuf **mbp, caddr_t *bposp)
 {
        u_int32_t *tl;
-       struct mbuf *mreq;
-       caddr_t bpos;
-       struct mbuf *mb, *mb2;
+       struct nfsm_info info;
 
        siz += RPC_REPLYSIZ;
-       mb = mreq = m_getl(max_hdr + siz, MB_WAIT, MT_DATA, M_PKTHDR, NULL);
-       mreq->m_pkthdr.len = 0;
+       info.mb = m_getl(max_hdr + siz, MB_WAIT, MT_DATA, M_PKTHDR, NULL);
+       info.mreq = info.mb;
+       info.mreq->m_pkthdr.len = 0;
        /*
         * If this is not a cluster, try and leave leading space
         * for the lower level headers.
         */
        if ((max_hdr + siz) < MINCLSIZE)
-               mreq->m_data += max_hdr;
-       tl = mtod(mreq, u_int32_t *);
-       mreq->m_len = 6 * NFSX_UNSIGNED;
-       bpos = ((caddr_t)tl) + mreq->m_len;
+               info.mreq->m_data += max_hdr;
+       tl = mtod(info.mreq, u_int32_t *);
+       info.mreq->m_len = 6 * NFSX_UNSIGNED;
+       info.bpos = ((caddr_t)tl) + info.mreq->m_len;
        *tl++ = txdr_unsigned(nd->nd_retxid);
        *tl++ = rpc_reply;
        if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
@@ -1350,8 +1357,8 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
                if (err & NFSERR_AUTHERR) {
                        *tl++ = rpc_autherr;
                        *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
-                       mreq->m_len -= NFSX_UNSIGNED;
-                       bpos -= NFSX_UNSIGNED;
+                       info.mreq->m_len -= NFSX_UNSIGNED;
+                       info.bpos -= NFSX_UNSIGNED;
                } else {
                        *tl++ = rpc_mismatch;
                        *tl++ = txdr_unsigned(RPC_VER2);
@@ -1392,7 +1399,7 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
                        *tl++ = rpc_auth_kerb;
                        *tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
                        *tl = ktvout.tv_sec;
-                       nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+                       tl = nfsm_build(&info, 3 * NFSX_UNSIGNED);
                        *tl++ = ktvout.tv_usec;
                        *tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
                    } else {
@@ -1409,7 +1416,7 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
                        break;
                case EPROGMISMATCH:
                        *tl = txdr_unsigned(RPC_PROGMISMATCH);
-                       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                       tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
                        *tl++ = txdr_unsigned(2);
                        *tl = txdr_unsigned(3);
                        break;
@@ -1422,7 +1429,7 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
                default:
                        *tl = 0;
                        if (err != NFSERR_RETVOID) {
-                               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+                               tl = nfsm_build(&info, NFSX_UNSIGNED);
                                if (err)
                                    *tl = txdr_unsigned(nfsrv_errmap(nd, err));
                                else
@@ -1433,9 +1440,9 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, struct nfssvc_sock *slp,
        }
 
        if (mrq != NULL)
-           *mrq = mreq;
-       *mbp = mb;
-       *bposp = bpos;
+           *mrq = info.mreq;
+       *mbp = info.mb;
+       *bposp = info.bpos;
        if (err != 0 && err != NFSERR_RETVOID)
                nfsstats.srvrpc_errs++;
        return (0);
@@ -1879,32 +1886,33 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
 {
        int len, i;
        u_int32_t *tl;
-       int32_t t1;
        struct uio uio;
        struct iovec iov;
-       caddr_t dpos, cp2, cp;
+       caddr_t cp;
        u_int32_t nfsvers, auth_type;
        uid_t nickuid;
        int error = 0, ticklen;
-       struct mbuf *mrep, *md;
        struct nfsuid *nuidp;
        struct timeval tvin, tvout;
+       struct nfsm_info info;
 #if 0                          /* until encrypted keys are implemented */
        NFSKERBKEYSCHED_T keys; /* stores key schedule */
 #endif
 
-       mrep = nd->nd_mrep;
-       md = nd->nd_md;
-       dpos = nd->nd_dpos;
+       info.mrep = nd->nd_mrep;
+       info.md = nd->nd_md;
+       info.dpos = nd->nd_dpos;
+
        if (has_header) {
-               nfsm_dissect(tl, u_int32_t *, 10 * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, 10 * NFSX_UNSIGNED));
                nd->nd_retxid = fxdr_unsigned(u_int32_t, *tl++);
                if (*tl++ != rpc_call) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
                        return (EBADRPC);
                }
-       } else
-               nfsm_dissect(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
+       } else {
+               NULLOUT(tl = nfsm_dissect(&info, 8 * NFSX_UNSIGNED));
+       }
        nd->nd_repstat = 0;
        nd->nd_flag = 0;
        if (*tl++ != rpc_vers) {
@@ -1941,7 +1949,7 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
        auth_type = *tl++;
        len = fxdr_unsigned(int, *tl++);
        if (len < 0 || len > RPCAUTH_MAXSIZ) {
-               m_freem(mrep);
+               m_freem(info.mrep);
                return (EBADRPC);
        }
 
@@ -1952,21 +1960,21 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
        if (auth_type == rpc_auth_unix) {
                len = fxdr_unsigned(int, *++tl);
                if (len < 0 || len > NFS_MAXNAMLEN) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
                        return (EBADRPC);
                }
-               nfsm_adv(nfsm_rndup(len));
-               nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+               ERROROUT(nfsm_adv(&info, nfsm_rndup(len)));
+               NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
                nd->nd_cr.cr_ref = 1;
                nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
                nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
                len = fxdr_unsigned(int, *tl);
                if (len < 0 || len > RPCAUTH_UNIXGIDS) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
                        return (EBADRPC);
                }
-               nfsm_dissect(tl, u_int32_t *, (len + 2) * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, (len + 2) * NFSX_UNSIGNED));
                for (i = 1; i <= len; i++)
                    if (i < NGROUPS)
                        nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
@@ -1977,11 +1985,12 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                    nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
                len = fxdr_unsigned(int, *++tl);
                if (len < 0 || len > RPCAUTH_MAXSIZ) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
                        return (EBADRPC);
                }
-               if (len > 0)
-                       nfsm_adv(nfsm_rndup(len));
+               if (len > 0) {
+                       ERROROUT(nfsm_adv(&info, nfsm_rndup(len)));
+               }
        } else if (auth_type == rpc_auth_kerb) {
                switch (fxdr_unsigned(int, *tl++)) {
                case RPCAKN_FULLNAME:
@@ -1990,7 +1999,7 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                        uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
                        nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
                        if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
-                               m_freem(mrep);
+                               m_freem(info.mrep);
                                return (EBADRPC);
                        }
                        uio.uio_offset = 0;
@@ -1999,8 +2008,8 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                        uio.uio_segflg = UIO_SYSSPACE;
                        iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
                        iov.iov_len = RPCAUTH_MAXSIZ - 4;
-                       nfsm_mtouio(&uio, uio.uio_resid);
-                       nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                       ERROROUT(nfsm_mtouio(&info, &uio, uio.uio_resid));
+                       NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                        if (*tl++ != rpc_auth_kerb ||
                                fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
                                kprintf("Bad kerb verifier\n");
@@ -2008,7 +2017,7 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                                nd->nd_procnum = NFSPROC_NOOP;
                                return (0);
                        }
-                       nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
+                       NULLOUT(cp = nfsm_dissect(&info, 4 * NFSX_UNSIGNED));
                        tl = (u_int32_t *)cp;
                        if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
                                kprintf("Not fullname kerb verifier\n");
@@ -2030,7 +2039,7 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                                return (0);
                        }
                        nickuid = fxdr_unsigned(uid_t, *tl);
-                       nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                        if (*tl++ != rpc_auth_kerb ||
                                fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
                                kprintf("Kerb nick verifier bad\n");
@@ -2038,7 +2047,7 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                                nd->nd_procnum = NFSPROC_NOOP;
                                return (0);
                        }
-                       nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                        tvin.tv_sec = *tl++;
                        tvin.tv_usec = *tl;
 
@@ -2086,8 +2095,8 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
                return (0);
        }
 
-       nd->nd_md = md;
-       nd->nd_dpos = dpos;
+       nd->nd_md = info.md;
+       nd->nd_dpos = info.dpos;
        return (0);
 nfsmout:
        return (error);
index 4051d75..60795d6 100644 (file)
@@ -637,10 +637,9 @@ nfs_uninit(struct vfsconf *vfsp)
  * n_mtime or n_attr.mtime due to NACC and NUPD.
  */
 int
-nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
+nfs_loadattrcache(struct vnode *vp, struct mbuf **mdp, caddr_t *dposp,
                  struct vattr *vaper, int lattr_flags)
 {
-       struct vnode *vp = *vpp;
        struct vattr *vap;
        struct nfs_fattr *fp;
        struct nfsnode *np;
index 82a54e6..88f2a1b 100644 (file)
@@ -1002,15 +1002,17 @@ nfs_savenickauth(struct nfsmount *nmp, struct ucred *cred, int len,
 {
        struct nfsuid *nuidp;
        u_int32_t *tl;
-       int32_t t1;
-       struct mbuf *md = *mdp;
        struct timeval ktvin, ktvout;
        u_int32_t nick;
-       char *dpos = *dposp, *cp2;
        int deltasec, error = 0;
+       struct nfsm_info info;
+
+       info.md = *mdp;
+       info.dpos = *dposp;
+       info.mrep = mrep;
 
        if (len == (3 * NFSX_UNSIGNED)) {
-               nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                ktvin.tv_sec = *tl++;
                ktvin.tv_usec = *tl++;
                nick = fxdr_unsigned(u_int32_t, *tl);
@@ -1052,10 +1054,11 @@ nfs_savenickauth(struct nfsmount *nmp, struct ucred *cred, int len,
                        LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
                                nuidp, nu_hash);
                }
-       } else
-               nfsm_adv(nfsm_rndup(len));
+       } else {
+               ERROROUT(nfsm_adv(&info, nfsm_rndup(len)));
+       }
 nfsmout:
-       *mdp = md;
-       *dposp = dpos;
+       *mdp = info.md;
+       *dposp = info.dpos;
        return (error);
 }
index dbb4e68..0a8adbb 100644 (file)
@@ -294,16 +294,15 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
 {
        struct vnode *vp;
        struct nfs_statfs *sfp;
-       caddr_t cp;
-       u_int32_t *tl;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        struct nfsmount *nmp = VFSTONFS(mp);
        thread_t td = curthread;
-       int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+       int error = 0, retattr;
        struct nfsnode *np;
        u_quad_t tquad;
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = (nmp->nm_flag & NFSMNT_NFSV3);
 
 #ifndef nolint
        sfp = NULL;
@@ -315,24 +314,26 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
        /* ignore the passed cred */
        cred = crget();
        cred->cr_ngroups = 1;
-       if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
+       if (info.v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
                (void)nfs_fsinfo(nmp, vp, td);
        nfsstats.rpccnt[NFSPROC_FSSTAT]++;
-       nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
-       nfsm_fhtom(vp, v3);
-       nfsm_request(vp, NFSPROC_FSSTAT, td, cred);
-       if (v3)
-               nfsm_postop_attr(vp, retattr, NFS_LATTR_NOSHRINK);
+       nfsm_reqhead(&info, vp, NFSPROC_FSSTAT, NFSX_FH(info.v3));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSSTAT, td, cred, &error));
+       if (info.v3) {
+               ERROROUT(nfsm_postop_attr(&info, vp, &retattr,
+                                        NFS_LATTR_NOSHRINK));
+       }
        if (error) {
-               if (mrep != NULL)
-                       m_freem(mrep);
+               if (info.mrep != NULL)
+                       m_freem(info.mrep);
                goto nfsmout;
        }
-       nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
+       NULLOUT(sfp = nfsm_dissect(&info, NFSX_STATFS(info.v3)));
        sbp->f_flags = nmp->nm_flag;
-       sbp->f_iosize = nfs_iosize(v3, nmp->nm_sotype);
+       sbp->f_iosize = nfs_iosize(info.v3, nmp->nm_sotype);
 
-       if (v3) {
+       if (info.v3) {
                sbp->f_bsize = NFS_FABLKSIZE;
                tquad = fxdr_hyper(&sfp->sf_tbytes);
                sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
@@ -356,7 +357,8 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
                sbp->f_type = mp->mnt_vfc->vfc_typenum;
                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        vput(vp);
        crfree(cred);
@@ -370,21 +372,20 @@ int
 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct thread *td)
 {
        struct nfsv3_fsinfo *fsp;
-       caddr_t cp;
-       int32_t t1, t2;
-       u_int32_t *tl, pref, max;
-       caddr_t bpos, dpos, cp2;
+       u_int32_t pref, max;
        int error = 0, retattr;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        u_int64_t maxfsize;
+       struct nfsm_info info;
 
+       info.v3 = 1;
        nfsstats.rpccnt[NFSPROC_FSINFO]++;
-       nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
-       nfsm_fhtom(vp, 1);
-       nfsm_request(vp, NFSPROC_FSINFO, td, nfs_vpcred(vp, ND_READ));
-       nfsm_postop_attr(vp, retattr, NFS_LATTR_NOSHRINK);
-       if (!error) {
-               nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
+       nfsm_reqhead(&info, vp, NFSPROC_FSINFO, NFSX_FH(1));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSINFO, td,
+                               nfs_vpcred(vp, ND_READ), &error));
+       ERROROUT(nfsm_postop_attr(&info, vp, &retattr, NFS_LATTR_NOSHRINK));
+       if (error == 0) {
+               NULLOUT(fsp = nfsm_dissect(&info, NFSX_V3FSINFO));
                pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
                if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
                        nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
@@ -419,7 +420,8 @@ nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct thread *td)
                        nmp->nm_maxfilesize = maxfsize;
                nmp->nm_state |= NFSSTA_GOTFSINFO;
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        return (error);
 }
index b12425b..f7a62ae 100644 (file)
@@ -252,32 +252,33 @@ static int
 nfs3_access_otw(struct vnode *vp, int wmode,
                struct thread *td, struct ucred *cred)
 {
-       const int v3 = 1;
+       struct nfsnode *np = VTONFS(vp);
+       int attrflag;
+       int error = 0;
        u_int32_t *tl;
-       int error = 0, attrflag;
-       
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       caddr_t bpos, dpos, cp2;
-       int32_t t1, t2;
-       caddr_t cp;
        u_int32_t rmode;
-       struct nfsnode *np = VTONFS(vp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = 1;
 
        nfsstats.rpccnt[NFSPROC_ACCESS]++;
-       nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
-       nfsm_fhtom(vp, v3);
-       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+       nfsm_reqhead(&info, vp, NFSPROC_ACCESS,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED);
+       ERROROUT(nfsm_fhtom(&info, vp));
+       tl = nfsm_build(&info, NFSX_UNSIGNED);
        *tl = txdr_unsigned(wmode); 
-       nfsm_request(vp, NFSPROC_ACCESS, td, cred);
-       nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
-       if (!error) {
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_ACCESS, td, cred, &error));
+       ERROROUT(nfsm_postop_attr(&info, vp, &attrflag, NFS_LATTR_NOSHRINK));
+       if (error == 0) {
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                rmode = fxdr_unsigned(u_int32_t, *tl);
                np->n_mode = rmode;
                np->n_modeuid = cred->cr_uid;
                np->n_modestamp = mycpu->gd_time_seconds;
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        return error;
 }
@@ -297,8 +298,8 @@ nfs_access(struct vop_access_args *ap)
        thread_t td = curthread;
        int error = 0;
        u_int32_t mode, wmode;
-       int v3 = NFS_ISV3(vp);
        struct nfsnode *np = VTONFS(vp);
+       int v3 = NFS_ISV3(vp);
 
        /*
         * Disallow write attempts on filesystems mounted read-only;
@@ -610,14 +611,12 @@ nfs_getattr(struct vop_getattr_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
-       caddr_t cp;
-       u_int32_t *tl;
-       int32_t t1, t2;
-       caddr_t bpos, dpos;
        int error = 0;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3 = NFS_ISV3(vp);
        thread_t td = curthread;
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
        
        /*
         * Update local times for special files.
@@ -630,7 +629,7 @@ nfs_getattr(struct vop_getattr_args *ap)
        if (nfs_getattrcache(vp, ap->a_vap) == 0)
                return (0);
 
-       if (v3 && nfsaccess_cache_timeout > 0) {
+       if (info.v3 && nfsaccess_cache_timeout > 0) {
                nfsstats.accesscache_misses++;
                nfs3_access_otw(vp, NFSV3ACCESS_ALL, td, nfs_vpcred(vp, ND_CHECK));
                if (nfs_getattrcache(vp, ap->a_vap) == 0)
@@ -638,13 +637,15 @@ nfs_getattr(struct vop_getattr_args *ap)
        }
 
        nfsstats.rpccnt[NFSPROC_GETATTR]++;
-       nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
-       nfsm_fhtom(vp, v3);
-       nfsm_request(vp, NFSPROC_GETATTR, td, nfs_vpcred(vp, ND_CHECK));
-       if (!error) {
-               nfsm_loadattr(vp, ap->a_vap);
+       nfsm_reqhead(&info, vp, NFSPROC_GETATTR, NFSX_FH(info.v3));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_GETATTR, td,
+                               nfs_vpcred(vp, ND_CHECK), &error));
+       if (error == 0) {
+               ERROROUT(nfsm_loadattr(&info, vp, ap->a_vap));
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        return (error);
 }
@@ -797,23 +798,23 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap,
 {
        struct nfsv2_sattr *sp;
        struct nfsnode *np = VTONFS(vp);
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        u_int32_t *tl;
        int error = 0, wccflag = NFSV3_WCCRATTR;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3 = NFS_ISV3(vp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
 
        nfsstats.rpccnt[NFSPROC_SETATTR]++;
-       nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
-       nfsm_fhtom(vp, v3);
-       if (v3) {
-               nfsm_v3attrbuild(vap, TRUE);
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+       nfsm_reqhead(&info, vp, NFSPROC_SETATTR,
+                    NFSX_FH(info.v3) + NFSX_SATTR(info.v3));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       if (info.v3) {
+               nfsm_v3attrbuild(&info, vap, TRUE);
+               tl = nfsm_build(&info, NFSX_UNSIGNED);
                *tl = nfs_false;
        } else {
-               nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+               sp = nfsm_build(&info, NFSX_V2SATTR);
                if (vap->va_mode == (mode_t)VNOVAL)
                        sp->sa_mode = nfs_xdrneg1;
                else
@@ -830,13 +831,15 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap,
                txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
                txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
        }
-       nfsm_request(vp, NFSPROC_SETATTR, td, cred);
-       if (v3) {
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_SETATTR, td, cred, &error));
+       if (info.v3) {
                np->n_modestamp = 0;
-               nfsm_wcc_data(vp, wccflag);
-       } else
-               nfsm_loadattr(vp, NULL);
-       m_freem(mrep);
+               ERROROUT(nfsm_wcc_data(&info, vp, &wccflag));
+       } else {
+               ERROROUT(nfsm_loadattr(&info, vp, NULL));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        return (error);
 }
@@ -874,12 +877,7 @@ nfs_nresolve(struct vop_nresolve_args *ap)
        int fhsize;
        int error;
        int len;
-       int v3;
-       /******NFSM MACROS********/
-       struct mbuf *mb, *mrep, *mreq, *mb2, *md;
-       caddr_t bpos, dpos, cp, cp2;
-       u_int32_t *tl;
-       int32_t t1, t2;
+       struct nfsm_info info;
 
        cred = ap->a_cred;
        dvp = ap->a_dvp;
@@ -887,17 +885,20 @@ nfs_nresolve(struct vop_nresolve_args *ap)
        if ((error = vget(dvp, LK_SHARED)) != 0)
                return (error);
 
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
+
        nvp = NULL;
-       v3 = NFS_ISV3(dvp);
        nfsstats.lookupcache_misses++;
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
        ncp = ap->a_nch->ncp;
        len = ncp->nc_nlen;
-       nfsm_reqhead(dvp, NFSPROC_LOOKUP,
-               NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(ncp->nc_name, len, NFS_MAXNAMLEN);
-       nfsm_request(dvp, NFSPROC_LOOKUP, td, ap->a_cred);
+       nfsm_reqhead(&info, dvp, NFSPROC_LOOKUP,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED + nfsm_rndup(len));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, ncp->nc_name, len, NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_LOOKUP, td,
+                               ap->a_cred, &error));
        if (error) {
                /*
                 * Cache negatve lookups to reduce NFS traffic, but use
@@ -909,8 +910,10 @@ nfs_nresolve(struct vop_nresolve_args *ap)
                 */
                if (error == ENOENT)
                        nfs_cache_setvp(ap->a_nch, NULL, nfsneg_cache_timeout);
-               nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
-               m_freem(mrep);
+               ERROROUT(nfsm_postop_attr(&info, dvp, &attrflag,
+                                        NFS_LATTR_NOSHRINK));
+               m_freem(info.mrep);
+               info.mrep = NULL;
                goto nfsmout;
        }
 
@@ -928,7 +931,7 @@ nfs_nresolve(struct vop_nresolve_args *ap)
         * of a bad hack here the rest of the NFS client code needs to do
         * the right thing.
         */
-       nfsm_getfh(fhp, fhsize, v3);
+       NEGATIVEOUT(fhsize = nfsm_getfh(&info, &fhp));
 
        np = VTONFS(dvp);
        if (NFS_CMPFH(np, fhp, fhsize)) {
@@ -937,20 +940,24 @@ nfs_nresolve(struct vop_nresolve_args *ap)
        } else {
                error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
                if (error) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
                        vput(dvp);
                        return (error);
                }
                nvp = NFSTOV(np);
        }
-       if (v3) {
-               nfsm_postop_attr(nvp, attrflag, NFS_LATTR_NOSHRINK);
-               nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
+       if (info.v3) {
+               ERROROUT(nfsm_postop_attr(&info, nvp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
+               ERROROUT(nfsm_postop_attr(&info, dvp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
        } else {
-               nfsm_loadattr(nvp, NULL);
+               ERROROUT(nfsm_loadattr(&info, nvp, NULL));
        }
        nfs_cache_setvp(ap->a_nch, nvp, nfspos_cache_timeout);
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        vput(dvp);
        if (nvp) {
@@ -978,17 +985,15 @@ nfs_lookup(struct vop_old_lookup_args *ap)
        struct vnode **vpp = ap->a_vpp;
        int flags = cnp->cn_flags;
        struct vnode *newvp;
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
        struct nfsmount *nmp;
-       caddr_t bpos, dpos, cp2;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        long len;
        nfsfh_t *fhp;
        struct nfsnode *np;
        int lockparent, wantparent, error = 0, attrflag, fhsize;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        /*
         * Read-only mount check and directory check.
@@ -1020,39 +1025,48 @@ nfs_lookup(struct vop_old_lookup_args *ap)
        nfsstats.lookupcache_misses++;
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
        len = cnp->cn_namelen;
-       nfsm_reqhead(dvp, NFSPROC_LOOKUP,
-               NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
-       nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_td, cnp->cn_cred);
+       nfsm_reqhead(&info, dvp, NFSPROC_LOOKUP,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED + nfsm_rndup(len));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, len, NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_LOOKUP, cnp->cn_td,
+                               cnp->cn_cred, &error));
        if (error) {
-               nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
-               m_freem(mrep);
+               ERROROUT(nfsm_postop_attr(&info, dvp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
+               m_freem(info.mrep);
+               info.mrep = NULL;
                goto nfsmout;
        }
-       nfsm_getfh(fhp, fhsize, v3);
+       NEGATIVEOUT(fhsize = nfsm_getfh(&info, &fhp));
 
        /*
         * Handle RENAME case...
         */
        if (cnp->cn_nameiop == NAMEI_RENAME && wantparent) {
                if (NFS_CMPFH(np, fhp, fhsize)) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
                        return (EISDIR);
                }
                error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
                if (error) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
                        return (error);
                }
                newvp = NFSTOV(np);
-               if (v3) {
-                       nfsm_postop_attr(newvp, attrflag, NFS_LATTR_NOSHRINK);
-                       nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
-               } else
-                       nfsm_loadattr(newvp, NULL);
+               if (info.v3) {
+                       ERROROUT(nfsm_postop_attr(&info, newvp, &attrflag,
+                                                 NFS_LATTR_NOSHRINK));
+                       ERROROUT(nfsm_postop_attr(&info, dvp, &attrflag,
+                                                 NFS_LATTR_NOSHRINK));
+               } else {
+                       ERROROUT(nfsm_loadattr(&info, newvp, NULL));
+               }
                *vpp = newvp;
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
                if (!lockparent) {
                        vn_unlock(dvp);
                        cnp->cn_flags |= CNP_PDIRUNLOCK;
@@ -1084,7 +1098,8 @@ nfs_lookup(struct vop_old_lookup_args *ap)
        } else {
                error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
                if (error) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
                        return (error);
                }
                if (!lockparent) {
@@ -1093,11 +1108,14 @@ nfs_lookup(struct vop_old_lookup_args *ap)
                }
                newvp = NFSTOV(np);
        }
-       if (v3) {
-               nfsm_postop_attr(newvp, attrflag, NFS_LATTR_NOSHRINK);
-               nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
-       } else
-               nfsm_loadattr(newvp, NULL);
+       if (info.v3) {
+               ERROROUT(nfsm_postop_attr(&info, newvp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
+               ERROROUT(nfsm_postop_attr(&info, dvp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
+       } else {
+               ERROROUT(nfsm_loadattr(&info, newvp, NULL));
+       }
 #if 0
        /* XXX MOVE TO nfs_nremove() */
        if ((cnp->cn_flags & CNP_MAKEENTRY) &&
@@ -1106,7 +1124,8 @@ nfs_lookup(struct vop_old_lookup_args *ap)
        }
 #endif
        *vpp = newvp;
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        if (error) {
                if (newvp != NULLVP) {
@@ -1166,30 +1185,32 @@ nfs_readlink(struct vop_readlink_args *ap)
 int
 nfs_readlinkrpc(struct vnode *vp, struct uio *uiop)
 {
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        int error = 0, len, attrflag;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3 = NFS_ISV3(vp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
 
        nfsstats.rpccnt[NFSPROC_READLINK]++;
-       nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
-       nfsm_fhtom(vp, v3);
-       nfsm_request(vp, NFSPROC_READLINK, uiop->uio_td, nfs_vpcred(vp, ND_CHECK));
-       if (v3)
-               nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
+       nfsm_reqhead(&info, vp, NFSPROC_READLINK, NFSX_FH(info.v3));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_READLINK, uiop->uio_td,
+                               nfs_vpcred(vp, ND_CHECK), &error));
+       if (info.v3) {
+               ERROROUT(nfsm_postop_attr(&info, vp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
+       }
        if (!error) {
-               nfsm_strsiz(len, NFS_MAXPATHLEN);
+               NEGATIVEOUT(len = nfsm_strsiz(&info, NFS_MAXPATHLEN));
                if (len == NFS_MAXPATHLEN) {
                        struct nfsnode *np = VTONFS(vp);
                        if (np->n_size && np->n_size < NFS_MAXPATHLEN)
                                len = np->n_size;
                }
-               nfsm_mtouio(uiop, len);
+               ERROROUT(nfsm_mtouio(&info, uiop, len));
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        return (error);
 }
@@ -1202,13 +1223,12 @@ int
 nfs_readrpc(struct vnode *vp, struct uio *uiop)
 {
        u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct nfsmount *nmp;
        int error = 0, len, retlen, tsiz, eof, attrflag;
-       int v3 = NFS_ISV3(vp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
 
 #ifndef nolint
        eof = 0;
@@ -1220,10 +1240,11 @@ nfs_readrpc(struct vnode *vp, struct uio *uiop)
        while (tsiz > 0) {
                nfsstats.rpccnt[NFSPROC_READ]++;
                len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
-               nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
-               nfsm_fhtom(vp, v3);
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
-               if (v3) {
+               nfsm_reqhead(&info, vp, NFSPROC_READ,
+                            NFSX_FH(info.v3) + NFSX_UNSIGNED * 3);
+               ERROROUT(nfsm_fhtom(&info, vp));
+               tl = nfsm_build(&info, NFSX_UNSIGNED * 3);
+               if (info.v3) {
                        txdr_hyper(uiop->uio_offset, tl);
                        *(tl + 2) = txdr_unsigned(len);
                } else {
@@ -1231,22 +1252,22 @@ nfs_readrpc(struct vnode *vp, struct uio *uiop)
                        *tl++ = txdr_unsigned(len);
                        *tl = 0;
                }
-               nfsm_request(vp, NFSPROC_READ, uiop->uio_td, nfs_vpcred(vp, ND_READ));
-               if (v3) {
-                       nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
-                       if (error) {
-                               m_freem(mrep);
-                               goto nfsmout;
-                       }
-                       nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+               NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_READ, uiop->uio_td,
+                                       nfs_vpcred(vp, ND_READ), &error));
+               if (info.v3) {
+                       ERROROUT(nfsm_postop_attr(&info, vp, &attrflag,
+                                                NFS_LATTR_NOSHRINK));
+                       NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                        eof = fxdr_unsigned(int, *(tl + 1));
-               } else
-                       nfsm_loadattr(vp, NULL);
-               nfsm_strsiz(retlen, nmp->nm_rsize);
-               nfsm_mtouio(uiop, retlen);
-               m_freem(mrep);
+               } else {
+                       ERROROUT(nfsm_loadattr(&info, vp, NULL));
+               }
+               NEGATIVEOUT(retlen = nfsm_strsiz(&info, nmp->nm_rsize));
+               ERROROUT(nfsm_mtouio(&info, uiop, retlen));
+               m_freem(info.mrep);
+               info.mrep = NULL;
                tsiz -= retlen;
-               if (v3) {
+               if (info.v3) {
                        if (eof || retlen == 0) {
                                tsiz = 0;
                        }
@@ -1265,13 +1286,14 @@ int
 nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
 {
        u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2, backup;
-       caddr_t bpos, dpos, cp2;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+       int32_t backup;
        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
        int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
-       int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
+       int  committed = NFSV3WRITE_FILESYNC;
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
 
 #ifndef DIAGNOSTIC
        if (uiop->uio_iovcnt != 1)
@@ -1284,11 +1306,11 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
        while (tsiz > 0) {
                nfsstats.rpccnt[NFSPROC_WRITE]++;
                len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
-               nfsm_reqhead(vp, NFSPROC_WRITE,
-                       NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
-               nfsm_fhtom(vp, v3);
-               if (v3) {
-                       nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
+               nfsm_reqhead(&info, vp, NFSPROC_WRITE,
+                            NFSX_FH(info.v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
+               ERROROUT(nfsm_fhtom(&info, vp));
+               if (info.v3) {
+                       tl = nfsm_build(&info, 5 * NFSX_UNSIGNED);
                        txdr_hyper(uiop->uio_offset, tl);
                        tl += 2;
                        *tl++ = txdr_unsigned(len);
@@ -1297,7 +1319,7 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
                } else {
                        u_int32_t x;
 
-                       nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
+                       tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
                        /* Set both "begin" and "current" to non-garbage. */
                        x = txdr_unsigned((u_int32_t)uiop->uio_offset);
                        *tl++ = x;      /* "begin offset" */
@@ -1306,9 +1328,10 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
                        *tl++ = x;      /* total to this offset */
                        *tl = x;        /* size of this write */
                }
-               nfsm_uiotom(uiop, len);
-               nfsm_request(vp, NFSPROC_WRITE, uiop->uio_td, nfs_vpcred(vp, ND_WRITE));
-               if (v3) {
+               ERROROUT(nfsm_uiotom(&info, uiop, len));
+               NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_WRITE, uiop->uio_td,
+                                       nfs_vpcred(vp, ND_WRITE), &error));
+               if (info.v3) {
                        /*
                         * The write RPC returns a before and after mtime.  The
                         * nfsm_wcc_data() macro checks the before n_mtime
@@ -1318,14 +1341,14 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
                         * time did not match the original mtime.
                         */
                        wccflag = NFSV3_WCCCHK;
-                       nfsm_wcc_data(vp, wccflag);
-                       if (!error) {
-                               nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
-                                       + NFSX_V3WRITEVERF);
+                       ERROROUT(nfsm_wcc_data(&info, vp, &wccflag));
+                       if (error == 0) {
+                               NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED + NFSX_V3WRITEVERF));
                                rlen = fxdr_unsigned(int, *tl++);
                                if (rlen == 0) {
                                        error = NFSERR_IO;
-                                       m_freem(mrep);
+                                       m_freem(info.mrep);
+                                       info.mrep = NULL;
                                        break;
                                } else if (rlen < len) {
                                        backup = len - rlen;
@@ -1358,9 +1381,10 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
                                }
                        }
                } else {
-                       nfsm_loadattr(vp, NULL);
+                       ERROROUT(nfsm_loadattr(&info, vp, NULL));
                }
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
                if (error)
                        break;
                tsiz -= len;
@@ -1385,17 +1409,15 @@ nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
 {
        struct nfsv2_sattr *sp;
        u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
        struct vnode *newvp = NULL;
        struct nfsnode *np = NULL;
        struct vattr vattr;
-       char *cp2;
-       caddr_t bpos, dpos;
        int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        int rmajor, rminor;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        if (vap->va_type == VCHR || vap->va_type == VBLK) {
                rmajor = txdr_unsigned(vap->va_rmajor);
@@ -1410,21 +1432,23 @@ nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
                return (error);
        }
        nfsstats.rpccnt[NFSPROC_MKNOD]++;
-       nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
-               + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       if (v3) {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+       nfsm_reqhead(&info, dvp, NFSPROC_MKNOD,
+                    NFSX_FH(info.v3) + 4 * NFSX_UNSIGNED +
+                    nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(info.v3));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, cnp->cn_namelen,
+                            NFS_MAXNAMLEN));
+       if (info.v3) {
+               tl = nfsm_build(&info, NFSX_UNSIGNED);
                *tl++ = vtonfsv3_type(vap->va_type);
-               nfsm_v3attrbuild(vap, FALSE);
+               nfsm_v3attrbuild(&info, vap, FALSE);
                if (vap->va_type == VCHR || vap->va_type == VBLK) {
-                       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                       tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
                        *tl++ = txdr_unsigned(vap->va_rmajor);
                        *tl = txdr_unsigned(vap->va_rminor);
                }
        } else {
-               nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+               sp = nfsm_build(&info, NFSX_V2SATTR);
                sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
                sp->sa_uid = nfs_xdrneg1;
                sp->sa_gid = nfs_xdrneg1;
@@ -1432,9 +1456,10 @@ nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
                txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
                txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
        }
-       nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_td, cnp->cn_cred);
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_MKNOD, cnp->cn_td,
+                               cnp->cn_cred, &error));
        if (!error) {
-               nfsm_mtofh(dvp, newvp, v3, gotvp);
+               ERROROUT(nfsm_mtofh(&info, dvp, &newvp, &gotvp));
                if (!gotvp) {
                        if (newvp) {
                                vput(newvp);
@@ -1446,9 +1471,11 @@ nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
                                newvp = NFSTOV(np);
                }
        }
-       if (v3)
-               nfsm_wcc_data(dvp, wccflag);
-       m_freem(mrep);
+       if (info.v3) {
+               ERROROUT(nfsm_wcc_data(&info, dvp, &wccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        if (error) {
                if (newvp)
@@ -1491,15 +1518,14 @@ nfs_create(struct vop_old_create_args *ap)
        struct componentname *cnp = ap->a_cnp;
        struct nfsv2_sattr *sp;
        u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
        struct nfsnode *np = NULL;
        struct vnode *newvp = NULL;
-       caddr_t bpos, dpos, cp2;
        int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct vattr vattr;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        /*
         * Oops, not for me..
@@ -1514,15 +1540,17 @@ nfs_create(struct vop_old_create_args *ap)
                fmode |= O_EXCL;
 again:
        nfsstats.rpccnt[NFSPROC_CREATE]++;
-       nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
-               nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       if (v3) {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+       nfsm_reqhead(&info, dvp, NFSPROC_CREATE,
+                    NFSX_FH(info.v3) + 2 * NFSX_UNSIGNED +
+                    nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(info.v3));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, cnp->cn_namelen,
+                            NFS_MAXNAMLEN));
+       if (info.v3) {
+               tl = nfsm_build(&info, NFSX_UNSIGNED);
                if (fmode & O_EXCL) {
                        *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
-                       nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
+                       tl = nfsm_build(&info, NFSX_V3CREATEVERF);
 #ifdef INET
                        if (!TAILQ_EMPTY(&in_ifaddrheads[mycpuid]))
                                *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrheads[mycpuid])->ia)->sin_addr.s_addr;
@@ -1532,10 +1560,10 @@ again:
                        *tl = ++create_verf;
                } else {
                        *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
-                       nfsm_v3attrbuild(vap, FALSE);
+                       nfsm_v3attrbuild(&info, vap, FALSE);
                }
        } else {
-               nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+               sp = nfsm_build(&info, NFSX_V2SATTR);
                sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
                sp->sa_uid = nfs_xdrneg1;
                sp->sa_gid = nfs_xdrneg1;
@@ -1543,9 +1571,10 @@ again:
                txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
                txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
        }
-       nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_td, cnp->cn_cred);
-       if (!error) {
-               nfsm_mtofh(dvp, newvp, v3, gotvp);
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_CREATE, cnp->cn_td,
+                               cnp->cn_cred, &error));
+       if (error == 0) {
+               ERROROUT(nfsm_mtofh(&info, dvp, &newvp, &gotvp));
                if (!gotvp) {
                        if (newvp) {
                                vput(newvp);
@@ -1557,17 +1586,19 @@ again:
                                newvp = NFSTOV(np);
                }
        }
-       if (v3)
-               nfsm_wcc_data(dvp, wccflag);
-       m_freem(mrep);
+       if (info.v3) {
+               ERROROUT(nfsm_wcc_data(&info, dvp, &wccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        if (error) {
-               if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
+               if (info.v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
                        KKASSERT(newvp == NULL);
                        fmode &= ~O_EXCL;
                        goto again;
                }
-       } else if (v3 && (fmode & O_EXCL)) {
+       } else if (info.v3 && (fmode & O_EXCL)) {
                /*
                 * We are normally called with only a partially initialized
                 * VAP.  Since the NFSv3 spec says that server may use the
@@ -1677,23 +1708,23 @@ static int
 nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
              struct ucred *cred, struct thread *td)
 {
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        int error = 0, wccflag = NFSV3_WCCRATTR;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        nfsstats.rpccnt[NFSPROC_REMOVE]++;
-       nfsm_reqhead(dvp, NFSPROC_REMOVE,
-               NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
-       nfsm_request(dvp, NFSPROC_REMOVE, td, cred);
-       if (v3)
-               nfsm_wcc_data(dvp, wccflag);
-       m_freem(mrep);
+       nfsm_reqhead(&info, dvp, NFSPROC_REMOVE,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, name, namelen, NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_REMOVE, td, cred, &error));
+       if (info.v3) {
+               ERROROUT(nfsm_wcc_data(&info, dvp, &wccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        VTONFS(dvp)->n_flag |= NLMODIFIED;
        if (!wccflag)
@@ -1800,28 +1831,27 @@ nfs_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
              struct vnode *tdvp, const char *tnameptr, int tnamelen,
              struct ucred *cred, struct thread *td)
 {
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3 = NFS_ISV3(fdvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(fdvp);
 
        nfsstats.rpccnt[NFSPROC_RENAME]++;
-       nfsm_reqhead(fdvp, NFSPROC_RENAME,
-               (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
-               nfsm_rndup(tnamelen));
-       nfsm_fhtom(fdvp, v3);
-       nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
-       nfsm_fhtom(tdvp, v3);
-       nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
-       nfsm_request(fdvp, NFSPROC_RENAME, td, cred);
-       if (v3) {
-               nfsm_wcc_data(fdvp, fwccflag);
-               nfsm_wcc_data(tdvp, twccflag);
-       }
-       m_freem(mrep);
+       nfsm_reqhead(&info, fdvp, NFSPROC_RENAME,
+                   (NFSX_FH(info.v3) + NFSX_UNSIGNED)*2 +
+                   nfsm_rndup(fnamelen) + nfsm_rndup(tnamelen));
+       ERROROUT(nfsm_fhtom(&info, fdvp));
+       ERROROUT(nfsm_strtom(&info, fnameptr, fnamelen, NFS_MAXNAMLEN));
+       ERROROUT(nfsm_fhtom(&info, tdvp));
+       ERROROUT(nfsm_strtom(&info, tnameptr, tnamelen, NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, fdvp, NFSPROC_RENAME, td, cred, &error));
+       if (info.v3) {
+               ERROROUT(nfsm_wcc_data(&info, fdvp, &fwccflag));
+               ERROROUT(nfsm_wcc_data(&info, tdvp, &twccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        VTONFS(fdvp)->n_flag |= NLMODIFIED;
        VTONFS(tdvp)->n_flag |= NLMODIFIED;
@@ -1844,13 +1874,8 @@ nfs_link(struct vop_old_link_args *ap)
        struct vnode *vp = ap->a_vp;
        struct vnode *tdvp = ap->a_tdvp;
        struct componentname *cnp = ap->a_cnp;
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3;
+       struct nfsm_info info;
 
        if (vp->v_mount != tdvp->v_mount) {
                return (EXDEV);
@@ -1865,19 +1890,26 @@ nfs_link(struct vop_old_link_args *ap)
        if (nfs_flush_on_hlink)
                VOP_FSYNC(vp, MNT_WAIT);
 
-       v3 = NFS_ISV3(vp);
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
+
        nfsstats.rpccnt[NFSPROC_LINK]++;
-       nfsm_reqhead(vp, NFSPROC_LINK,
-               NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
-       nfsm_fhtom(vp, v3);
-       nfsm_fhtom(tdvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       nfsm_request(vp, NFSPROC_LINK, cnp->cn_td, cnp->cn_cred);
-       if (v3) {
-               nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
-               nfsm_wcc_data(tdvp, wccflag);
-       }
-       m_freem(mrep);
+       nfsm_reqhead(&info, vp, NFSPROC_LINK,
+                    NFSX_FH(info.v3) * 2 + NFSX_UNSIGNED +
+                    nfsm_rndup(cnp->cn_namelen));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       ERROROUT(nfsm_fhtom(&info, tdvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, cnp->cn_namelen,
+                            NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_LINK, cnp->cn_td,
+                               cnp->cn_cred, &error));
+       if (info.v3) {
+               ERROROUT(nfsm_postop_attr(&info, vp, &attrflag,
+                                        NFS_LATTR_NOSHRINK));
+               ERROROUT(nfsm_wcc_data(&info, tdvp, &wccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        VTONFS(tdvp)->n_flag |= NLMODIFIED;
        if (!attrflag)
@@ -1906,27 +1938,28 @@ nfs_symlink(struct vop_old_symlink_args *ap)
        struct vattr *vap = ap->a_vap;
        struct componentname *cnp = ap->a_cnp;
        struct nfsv2_sattr *sp;
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        struct vnode *newvp = NULL;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        nfsstats.rpccnt[NFSPROC_SYMLINK]++;
        slen = strlen(ap->a_target);
-       nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
-           nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       if (v3) {
-               nfsm_v3attrbuild(vap, FALSE);
-       }
-       nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
-       if (!v3) {
-               nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+       nfsm_reqhead(&info, dvp, NFSPROC_SYMLINK,
+                    NFSX_FH(info.v3) + 2*NFSX_UNSIGNED +
+                    nfsm_rndup(cnp->cn_namelen) +
+                    nfsm_rndup(slen) + NFSX_SATTR(info.v3));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, cnp->cn_namelen,
+                            NFS_MAXNAMLEN));
+       if (info.v3) {
+               nfsm_v3attrbuild(&info, vap, FALSE);
+       }
+       ERROROUT(nfsm_strtom(&info, ap->a_target, slen, NFS_MAXPATHLEN));
+       if (info.v3 == 0) {
+               sp = nfsm_build(&info, NFSX_V2SATTR);
                sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
                sp->sa_uid = nfs_xdrneg1;
                sp->sa_gid = nfs_xdrneg1;
@@ -1942,18 +1975,21 @@ nfs_symlink(struct vop_old_symlink_args *ap)
         * a file handle that can be converted into newvp without having
         * to do an extra lookup rpc.
         */
-       nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_td, cnp->cn_cred);
-       if (v3) {
-               if (error == 0)
-                       nfsm_mtofh(dvp, newvp, v3, gotvp);
-               nfsm_wcc_data(dvp, wccflag);
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_SYMLINK, cnp->cn_td,
+                               cnp->cn_cred, &error));
+       if (info.v3) {
+               if (error == 0) {
+                      ERROROUT(nfsm_mtofh(&info, dvp, &newvp, &gotvp));
+               }
+               ERROROUT(nfsm_wcc_data(&info, dvp, &wccflag));
        }
 
        /*
         * out code jumps -> here, mrep is also freed.
         */
 
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
 
        /*
@@ -2002,32 +2038,31 @@ nfs_mkdir(struct vop_old_mkdir_args *ap)
        struct vattr *vap = ap->a_vap;
        struct componentname *cnp = ap->a_cnp;
        struct nfsv2_sattr *sp;
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       int len;
        struct nfsnode *np = NULL;
        struct vnode *newvp = NULL;
-       caddr_t bpos, dpos, cp2;
+       struct vattr vattr;
        int error = 0, wccflag = NFSV3_WCCRATTR;
        int gotvp = 0;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       struct vattr vattr;
-       int v3 = NFS_ISV3(dvp);
+       int len;
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        if ((error = VOP_GETATTR(dvp, &vattr)) != 0) {
                return (error);
        }
        len = cnp->cn_namelen;
        nfsstats.rpccnt[NFSPROC_MKDIR]++;
-       nfsm_reqhead(dvp, NFSPROC_MKDIR,
-         NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
-       if (v3) {
-               nfsm_v3attrbuild(vap, FALSE);
+       nfsm_reqhead(&info, dvp, NFSPROC_MKDIR,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED +
+                    nfsm_rndup(len) + NFSX_SATTR(info.v3));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, len, NFS_MAXNAMLEN));
+       if (info.v3) {
+               nfsm_v3attrbuild(&info, vap, FALSE);
        } else {
-               nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
+               sp = nfsm_build(&info, NFSX_V2SATTR);
                sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
                sp->sa_uid = nfs_xdrneg1;
                sp->sa_gid = nfs_xdrneg1;
@@ -2035,12 +2070,16 @@ nfs_mkdir(struct vop_old_mkdir_args *ap)
                txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
                txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
        }
-       nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_td, cnp->cn_cred);
-       if (!error)
-               nfsm_mtofh(dvp, newvp, v3, gotvp);
-       if (v3)
-               nfsm_wcc_data(dvp, wccflag);
-       m_freem(mrep);
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_MKDIR, cnp->cn_td,
+                   cnp->cn_cred, &error));
+       if (error == 0) {
+               ERROROUT(nfsm_mtofh(&info, dvp, &newvp, &gotvp));
+       }
+       if (info.v3) {
+               ERROROUT(nfsm_wcc_data(&info, dvp, &wccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        VTONFS(dvp)->n_flag |= NLMODIFIED;
        if (!wccflag)
@@ -2082,25 +2121,28 @@ nfs_rmdir(struct vop_old_rmdir_args *ap)
        struct vnode *vp = ap->a_vp;
        struct vnode *dvp = ap->a_dvp;
        struct componentname *cnp = ap->a_cnp;
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
-       caddr_t bpos, dpos, cp2;
        int error = 0, wccflag = NFSV3_WCCRATTR;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        if (dvp == vp)
                return (EINVAL);
        nfsstats.rpccnt[NFSPROC_RMDIR]++;
-       nfsm_reqhead(dvp, NFSPROC_RMDIR,
-               NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
-       nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_td, cnp->cn_cred);
-       if (v3)
-               nfsm_wcc_data(dvp, wccflag);
-       m_freem(mrep);
+       nfsm_reqhead(&info, dvp, NFSPROC_RMDIR,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED +
+                    nfsm_rndup(cnp->cn_namelen));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, cnp->cn_nameptr, cnp->cn_namelen,
+                NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_RMDIR, cnp->cn_td,
+                               cnp->cn_cred, &error));
+       if (info.v3) {
+               ERROROUT(nfsm_wcc_data(&info, dvp, &wccflag));
+       }
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        VTONFS(dvp)->n_flag |= NLMODIFIED;
        if (!wccflag)
@@ -2178,18 +2220,18 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
        int len, left;
        struct nfs_dirent *dp = NULL;
        u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
        nfsuint64 *cookiep;
-       caddr_t bpos, dpos, cp2;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+       caddr_t cp;
        nfsuint64 cookie;
        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
        struct nfsnode *dnp = VTONFS(vp);
        u_quad_t fileno;
        int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
        int attrflag;
-       int v3 = NFS_ISV3(vp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(vp);
 
 #ifndef DIAGNOSTIC
        if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
@@ -2212,52 +2254,48 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
         */
        while (more_dirs && bigenough) {
                nfsstats.rpccnt[NFSPROC_READDIR]++;
-               nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
-                       NFSX_READDIR(v3));
-               nfsm_fhtom(vp, v3);
-               if (v3) {
-                       nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
+               nfsm_reqhead(&info, vp, NFSPROC_READDIR,
+                            NFSX_FH(info.v3) + NFSX_READDIR(info.v3));
+               ERROROUT(nfsm_fhtom(&info, vp));
+               if (info.v3) {
+                       tl = nfsm_build(&info, 5 * NFSX_UNSIGNED);
                        *tl++ = cookie.nfsuquad[0];
                        *tl++ = cookie.nfsuquad[1];
                        *tl++ = dnp->n_cookieverf.nfsuquad[0];
                        *tl++ = dnp->n_cookieverf.nfsuquad[1];
                } else {
-                       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+                       tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
                        *tl++ = cookie.nfsuquad[0];
                }
                *tl = txdr_unsigned(nmp->nm_readdirsize);
-               nfsm_request(vp, NFSPROC_READDIR, uiop->uio_td, nfs_vpcred(vp, ND_READ));
-               if (v3) {
-                       nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
-                       if (!error) {
-                               nfsm_dissect(tl, u_int32_t *,
-                                   2 * NFSX_UNSIGNED);
-                               dnp->n_cookieverf.nfsuquad[0] = *tl++;
-                               dnp->n_cookieverf.nfsuquad[1] = *tl;
-                       } else {
-                               m_freem(mrep);
-                               goto nfsmout;
-                       }
+               NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_READDIR,
+                                       uiop->uio_td,
+                                       nfs_vpcred(vp, ND_READ), &error));
+               if (info.v3) {
+                       ERROROUT(nfsm_postop_attr(&info, vp, &attrflag,
+                                                 NFS_LATTR_NOSHRINK));
+                       NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
+                       dnp->n_cookieverf.nfsuquad[0] = *tl++;
+                       dnp->n_cookieverf.nfsuquad[1] = *tl;
                }
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                more_dirs = fxdr_unsigned(int, *tl);
        
                /* loop thru the dir entries, converting them to std form */
                while (more_dirs && bigenough) {
-                       if (v3) {
-                               nfsm_dissect(tl, u_int32_t *,
-                                   3 * NFSX_UNSIGNED);
+                       if (info.v3) {
+                               NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                                fileno = fxdr_hyper(tl);
                                len = fxdr_unsigned(int, *(tl + 2));
                        } else {
-                               nfsm_dissect(tl, u_int32_t *,
-                                   2 * NFSX_UNSIGNED);
+                               NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                                fileno = fxdr_unsigned(u_quad_t, *tl++);
                                len = fxdr_unsigned(int, *tl);
                        }
                        if (len <= 0 || len > NFS_MAXNAMLEN) {
                                error = EBADRPC;
-                               m_freem(mrep);
+                               m_freem(info.mrep);
+                               info.mrep = NULL;
                                goto nfsmout;
                        }
 
@@ -2301,7 +2339,7 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
                                uiop->uio_resid -= sizeof(struct nfs_dirent);
                                uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + sizeof(struct nfs_dirent);
                                uiop->uio_iov->iov_len -= sizeof(struct nfs_dirent);
-                               nfsm_mtouio(uiop, len);
+                               ERROROUT(nfsm_mtouio(&info, uiop, len));
 
                                /*
                                 * The uiop has advanced by nfs_dirent + len
@@ -2320,14 +2358,12 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
                                 * NFS strings must be rounded up (nfsm_myouio
                                 * handled that in the bigenough case).
                                 */
-                               nfsm_adv(nfsm_rndup(len));
+                               ERROROUT(nfsm_adv(&info, nfsm_rndup(len)));
                        }
-                       if (v3) {
-                               nfsm_dissect(tl, u_int32_t *,
-                                   3 * NFSX_UNSIGNED);
+                       if (info.v3) {
+                               NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                        } else {
-                               nfsm_dissect(tl, u_int32_t *,
-                                   2 * NFSX_UNSIGNED);
+                               NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
                        }
 
                        /*
@@ -2338,9 +2374,9 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
                         */
                        if (bigenough) {
                                cookie.nfsuquad[0] = *tl++;
-                               if (v3)
+                               if (info.v3)
                                        cookie.nfsuquad[1] = *tl++;
-                       } else if (v3) {
+                       } else if (info.v3) {
                                tl += 2;
                        } else {
                                tl++;
@@ -2351,10 +2387,11 @@ nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
                 * If at end of rpc data, get the eof boolean
                 */
                if (!more_dirs) {
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                        more_dirs = (fxdr_unsigned(int, *tl) == 0);
                }
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
        }
        /*
         * Fill last record, iff any, out to a multiple of DIRBLKSIZ
@@ -2397,12 +2434,11 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
        int len, left;
        struct nfs_dirent *dp;
        u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
        struct vnode *newvp;
        nfsuint64 *cookiep;
-       caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
+       caddr_t dpossav1, dpossav2;
+       caddr_t cp;
+       struct mbuf *mdsav1, *mdsav2;
        nfsuint64 cookie;
        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
        struct nfsnode *dnp = VTONFS(vp), *np;
@@ -2413,6 +2449,10 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
        struct nchandle nch;
        struct nchandle dnch;
        struct nlcomponent nlc;
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = 1;
 
 #ifndef nolint
        dp = NULL;
@@ -2449,35 +2489,35 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
         */
        while (more_dirs && bigenough) {
                nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
-               nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
-                       NFSX_FH(1) + 6 * NFSX_UNSIGNED);
-               nfsm_fhtom(vp, 1);
-               nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
+               nfsm_reqhead(&info, vp, NFSPROC_READDIRPLUS,
+                            NFSX_FH(1) + 6 * NFSX_UNSIGNED);
+               ERROROUT(nfsm_fhtom(&info, vp));
+               tl = nfsm_build(&info, 6 * NFSX_UNSIGNED);
                *tl++ = cookie.nfsuquad[0];
                *tl++ = cookie.nfsuquad[1];
                *tl++ = dnp->n_cookieverf.nfsuquad[0];
                *tl++ = dnp->n_cookieverf.nfsuquad[1];
                *tl++ = txdr_unsigned(nmp->nm_readdirsize);
                *tl = txdr_unsigned(nmp->nm_rsize);
-               nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, nfs_vpcred(vp, ND_READ));
-               nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
-               if (error) {
-                       m_freem(mrep);
-                       goto nfsmout;
-               }
-               nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+               NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_READDIRPLUS,
+                                       uiop->uio_td,
+                                       nfs_vpcred(vp, ND_READ), &error));
+               ERROROUT(nfsm_postop_attr(&info, vp, &attrflag,
+                                         NFS_LATTR_NOSHRINK));
+               NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                dnp->n_cookieverf.nfsuquad[0] = *tl++;
                dnp->n_cookieverf.nfsuquad[1] = *tl++;
                more_dirs = fxdr_unsigned(int, *tl);
 
                /* loop thru the dir entries, doctoring them to 4bsd form */
                while (more_dirs && bigenough) {
-                       nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                        fileno = fxdr_hyper(tl);
                        len = fxdr_unsigned(int, *(tl + 2));
                        if (len <= 0 || len > NFS_MAXNAMLEN) {
                                error = EBADRPC;
-                               m_freem(mrep);
+                               m_freem(info.mrep);
+                               info.mrep = NULL;
                                goto nfsmout;
                        }
                        tlen = nfsm_rndup(len);
@@ -2509,7 +2549,7 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                                uiop->uio_iov->iov_len -= sizeof(struct nfs_dirent);
                                nlc.nlc_nameptr = uiop->uio_iov->iov_base;
                                nlc.nlc_namelen = len;
-                               nfsm_mtouio(uiop, len);
+                               ERROROUT(nfsm_mtouio(&info, uiop, len));
                                cp = uiop->uio_iov->iov_base;
                                tlen -= len;
                                *cp = '\0';
@@ -2517,9 +2557,10 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                                uiop->uio_iov->iov_len -= tlen;
                                uiop->uio_offset += tlen;
                                uiop->uio_resid -= tlen;
-                       } else
-                               nfsm_adv(nfsm_rndup(len));
-                       nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+                       } else {
+                               ERROROUT(nfsm_adv(&info, nfsm_rndup(len)));
+                       }
+                       NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
                        if (bigenough) {
                                cookie.nfsuquad[0] = *tl++;
                                cookie.nfsuquad[1] = *tl++;
@@ -2533,13 +2574,13 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                         */
                        attrflag = fxdr_unsigned(int, *tl);
                        if (attrflag) {
-                           dpossav1 = dpos;
-                           mdsav1 = md;
-                           nfsm_adv(NFSX_V3FATTR);
-                           nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+                           dpossav1 = info.dpos;
+                           mdsav1 = info.md;
+                           ERROROUT(nfsm_adv(&info, NFSX_V3FATTR));
+                           NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                            doit = fxdr_unsigned(int, *tl);
                            if (doit) {
-                               nfsm_getfh(fhp, fhsize, 1);
+                               NEGATIVEOUT(fhsize = nfsm_getfh(&info, &fhp));
                                if (NFS_CMPFH(dnp, fhp, fhsize)) {
                                    vref(vp);
                                    newvp = vp;
@@ -2554,13 +2595,13 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                                }
                            }
                            if (doit && bigenough) {
-                               dpossav2 = dpos;
-                               dpos = dpossav1;
-                               mdsav2 = md;
-                               md = mdsav1;
-                               nfsm_loadattr(newvp, NULL);
-                               dpos = dpossav2;
-                               md = mdsav2;
+                               dpossav2 = info.dpos;
+                               info.dpos = dpossav1;
+                               mdsav2 = info.md;
+                               info.md = mdsav1;
+                               ERROROUT(nfsm_loadattr(&info, newvp, NULL));
+                               info.dpos = dpossav2;
+                               info.md = mdsav2;
                                dp->nfs_type =
                                    IFTODT(VTTOIF(np->n_vattr.va_type));
                                if (dnch.ncp) {
@@ -2581,9 +2622,9 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                            }
                        } else {
                            /* Just skip over the file handle */
-                           nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+                           NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                            i = fxdr_unsigned(int, *tl);
-                           nfsm_adv(nfsm_rndup(i));
+                           ERROROUT(nfsm_adv(&info, nfsm_rndup(i)));
                        }
                        if (newvp != NULLVP) {
                            if (newvp == vp)
@@ -2592,17 +2633,18 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                                vput(newvp);
                            newvp = NULLVP;
                        }
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                        more_dirs = fxdr_unsigned(int, *tl);
                }
                /*
                 * If at end of rpc data, get the eof boolean
                 */
                if (!more_dirs) {
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
+                       NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
                        more_dirs = (fxdr_unsigned(int, *tl) == 0);
                }
-               m_freem(mrep);
+               m_freem(info.mrep);
+               info.mrep = NULL;
        }
        /*
         * Fill last record, iff any, out to a multiple of DIRBLKSIZ
@@ -2713,25 +2755,23 @@ static int
 nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
             struct thread *td, struct nfsnode **npp)
 {
-       u_int32_t *tl;
-       caddr_t cp;
-       int32_t t1, t2;
        struct vnode *newvp = NULL;
        struct nfsnode *np, *dnp = VTONFS(dvp);
-       caddr_t bpos, dpos, cp2;
        int error = 0, fhlen, attrflag;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
        nfsfh_t *nfhp;
-       int v3 = NFS_ISV3(dvp);
+       struct nfsm_info info;
+
+       info.mrep = NULL;
+       info.v3 = NFS_ISV3(dvp);
 
        nfsstats.rpccnt[NFSPROC_LOOKUP]++;
-       nfsm_reqhead(dvp, NFSPROC_LOOKUP,
-               NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
-       nfsm_fhtom(dvp, v3);
-       nfsm_strtom(name, len, NFS_MAXNAMLEN);
-       nfsm_request(dvp, NFSPROC_LOOKUP, td, cred);
+       nfsm_reqhead(&info, dvp, NFSPROC_LOOKUP,
+                    NFSX_FH(info.v3) + NFSX_UNSIGNED + nfsm_rndup(len));
+       ERROROUT(nfsm_fhtom(&info, dvp));
+       ERROROUT(nfsm_strtom(&info, name, len, NFS_MAXNAMLEN));
+       NEGKEEPOUT(nfsm_request(&info, dvp, NFSPROC_LOOKUP, td, cred, &error));
        if (npp && !error) {
-               nfsm_getfh(nfhp, fhlen, v3);
+               NEGATIVEOUT(fhlen = nfsm_getfh(&info, &nfhp));
                if (*npp) {
                    np = *npp;
                    if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
@@ -2748,25 +2788,30 @@ nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
                } else {
                    error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
                    if (error) {
-                       m_freem(mrep);
+                       m_freem(info.mrep);
+                       info.mrep = NULL;
                        return (error);
                    }
                    newvp = NFSTOV(np);
                }
-               if (v3) {
-                       nfsm_postop_attr(newvp, attrflag, NFS_LATTR_NOSHRINK);
+               if (info.v3) {
+                       ERROROUT(nfsm_postop_attr(&info, newvp, &attrflag,
+                                                 NFS_LATTR_NOSHRINK));
                        if (!attrflag && *npp == NULL) {
-                               m_freem(mrep);
+                               m_freem(info.mrep);
+                               info.mrep = NULL;
                                if (newvp == dvp)
                                        vrele(newvp);
                                else
                                        vput(newvp);
                                return (ENOENT);
                        }
-               } else
-                       nfsm_loadattr(newvp, NULL);
+               } else {
+                       ERROROUT(error = nfsm_loadattr(&info, newvp, NULL));
+               }
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        if (npp && *npp == NULL) {
                if (error) {
@@ -2788,27 +2833,28 @@ nfsmout:
 int
 nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct thread *td)
 {
-       caddr_t cp;
-       u_int32_t *tl;
-       int32_t t1, t2;
        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
-       caddr_t bpos, dpos, cp2;
        int error = 0, wccflag = NFSV3_WCCRATTR;
-       struct mbuf *mreq, *mrep, *md, *mb, *mb2;
+       struct nfsm_info info;
+       u_int32_t *tl;
+
+       info.mrep = NULL;
+       info.v3 = 1;
        
        if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
                return (0);
        nfsstats.rpccnt[NFSPROC_COMMIT]++;
-       nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
-       nfsm_fhtom(vp, 1);
-       nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
+       nfsm_reqhead(&info, vp, NFSPROC_COMMIT, NFSX_FH(1));
+       ERROROUT(nfsm_fhtom(&info, vp));
+       tl = nfsm_build(&info, 3 * NFSX_UNSIGNED);
        txdr_hyper(offset, tl);
        tl += 2;
        *tl = txdr_unsigned(cnt);
-       nfsm_request(vp, NFSPROC_COMMIT, td, nfs_vpcred(vp, ND_WRITE));
-       nfsm_wcc_data(vp, wccflag);
+       NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_COMMIT, td,
+                               nfs_vpcred(vp, ND_WRITE), &error));
+       ERROROUT(nfsm_wcc_data(&info, vp, &wccflag));
        if (!error) {
-               nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
+               NULLOUT(tl = nfsm_dissect(&info, NFSX_V3WRITEVERF));
                if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
                        NFSX_V3WRITEVERF)) {
                        bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
@@ -2816,7 +2862,8 @@ nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct thread *td)
                        error = NFSERR_STALEWRITEVERF;
                }
        }
-       m_freem(mrep);
+       m_freem(info.mrep);
+       info.mrep = NULL;
 nfsmout:
        return (error);
 }
index 7e803c3..31e9b33 100644 (file)
@@ -115,19 +115,13 @@ static u_int32_t nfs_xid = 0;
  * The hsiz is the size of the rest of the nfs request header.
  * (just used to decide if a cluster is a good idea)
  */
-struct mbuf *
-nfsm_reqh(struct vnode *vp, u_long procid, int hsiz, caddr_t *bposp)
+void
+nfsm_reqhead(nfsm_info_t info, struct vnode *vp, u_long procid, int hsiz)
 {
-       struct mbuf *mb;
-       caddr_t bpos;
-
-       mb = m_getl(hsiz, MB_WAIT, MT_DATA, 0, NULL);
-       mb->m_len = 0;
-       bpos = mtod(mb, caddr_t);
-
-       /* Finally, return values */
-       *bposp = bpos;
-       return (mb);
+       info->mb = m_getl(hsiz, MB_WAIT, MT_DATA, 0, NULL);
+       info->mb->m_len = 0;
+       info->mreq = info->mb;
+       info->bpos = mtod(info->mb, caddr_t);
 }
 
 /*
@@ -142,30 +136,28 @@ nfsm_rpchead(struct ucred *cr, int nmflag, int procid, int auth_type,
             struct mbuf *mrest, int mrest_len, struct mbuf **mbp,
             u_int32_t *xidp)
 {
-       struct mbuf *mb;
+       struct nfsm_info info;
        u_int32_t *tl;
-       caddr_t bpos;
-       int i;
-       struct mbuf *mreq, *mb2;
        int siz, grpsiz, authsiz, dsiz;
+       int i;
 
        authsiz = nfsm_rndup(auth_len);
        dsiz = authsiz + 10 * NFSX_UNSIGNED;
-       mb = m_getl(dsiz, MB_WAIT, MT_DATA, M_PKTHDR, NULL);
+       info.mb = m_getl(dsiz, MB_WAIT, MT_DATA, M_PKTHDR, NULL);
        if (dsiz < MINCLSIZE) {
                if (dsiz < MHLEN)
-                       MH_ALIGN(mb, dsiz);
+                       MH_ALIGN(info.mb, dsiz);
                else
-                       MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
+                       MH_ALIGN(info.mb, 8 * NFSX_UNSIGNED);
        }
-       mb->m_len = mb->m_pkthdr.len = 0;
-       mreq = mb;
-       bpos = mtod(mb, caddr_t);
+       info.mb->m_len = info.mb->m_pkthdr.len = 0;
+       info.mreq = info.mb;
+       info.bpos = mtod(info.mb, caddr_t);
 
        /*
         * First the RPC header.
         */
-       nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
+       tl = nfsm_build(&info, 8 * NFSX_UNSIGNED);
 
        /* Get a pretty random xid to start with */
        if (!nfs_xid)
@@ -196,7 +188,7 @@ nfsm_rpchead(struct ucred *cr, int nmflag, int procid, int auth_type,
        *tl = txdr_unsigned(authsiz);
        switch (auth_type) {
        case RPCAUTH_UNIX:
-               nfsm_build(tl, u_int32_t *, auth_len);
+               tl = nfsm_build(&info, auth_len);
                *tl++ = 0;              /* stamp ?? */
                *tl++ = 0;              /* NULL hostname */
                *tl++ = txdr_unsigned(cr->cr_uid);
@@ -209,24 +201,24 @@ nfsm_rpchead(struct ucred *cr, int nmflag, int procid, int auth_type,
        case RPCAUTH_KERB4:
                siz = auth_len;
                while (siz > 0) {
-                       if (M_TRAILINGSPACE(mb) == 0) {
-                               mb2 = m_getl(siz, MB_WAIT, MT_DATA, 0, NULL);
-                               mb2->m_len = 0;
-                               mb->m_next = mb2;
-                               mb = mb2;
-                               bpos = mtod(mb, caddr_t);
+                       if (M_TRAILINGSPACE(info.mb) == 0) {
+                               info.mb2 = m_getl(siz, MB_WAIT, MT_DATA, 0, NULL);
+                               info.mb2->m_len = 0;
+                               info.mb->m_next = info.mb2;
+                               info.mb = info.mb2;
+                               info.bpos = mtod(info.mb, caddr_t);
                        }
-                       i = min(siz, M_TRAILINGSPACE(mb));
-                       bcopy(auth_str, bpos, i);
-                       mb->m_len += i;
+                       i = min(siz, M_TRAILINGSPACE(info.mb));
+                       bcopy(auth_str, info.bpos, i);
+                       info.mb->m_len += i;
                        auth_str += i;
-                       bpos += i;
+                       info.bpos += i;
                        siz -= i;
                }
                if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
                        for (i = 0; i < siz; i++)
-                               *bpos++ = '\0';
-                       mb->m_len += siz;
+                               *info.bpos++ = '\0';
+                       info.mb->m_len += siz;
                }
                break;
        };
@@ -234,40 +226,721 @@ nfsm_rpchead(struct ucred *cr, int nmflag, int procid, int auth_type,
        /*
         * And the verifier...
         */
-       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
+       tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
        if (verf_str) {
                *tl++ = txdr_unsigned(RPCAUTH_KERB4);
                *tl = txdr_unsigned(verf_len);
                siz = verf_len;
                while (siz > 0) {
-                       if (M_TRAILINGSPACE(mb) == 0) {
-                               mb2 = m_getl(siz, MB_WAIT, MT_DATA, 0, NULL);
-                               mb2->m_len = 0;
-                               mb->m_next = mb2;
-                               mb = mb2;
-                               bpos = mtod(mb, caddr_t);
+                       if (M_TRAILINGSPACE(info.mb) == 0) {
+                               info.mb2 = m_getl(siz, MB_WAIT, MT_DATA,
+                                                 0, NULL);
+                               info.mb2->m_len = 0;
+                               info.mb->m_next = info.mb2;
+                               info.mb = info.mb2;
+                               info.bpos = mtod(info.mb, caddr_t);
                        }
-                       i = min(siz, M_TRAILINGSPACE(mb));
-                       bcopy(verf_str, bpos, i);
-                       mb->m_len += i;
+                       i = min(siz, M_TRAILINGSPACE(info.mb));
+                       bcopy(verf_str, info.bpos, i);
+                       info.mb->m_len += i;
                        verf_str += i;
-                       bpos += i;
+                       info.bpos += i;
                        siz -= i;
                }
                if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
                        for (i = 0; i < siz; i++)
-                               *bpos++ = '\0';
-                       mb->m_len += siz;
+                               *info.bpos++ = '\0';
+                       info.mb->m_len += siz;
                }
        } else {
                *tl++ = txdr_unsigned(RPCAUTH_NULL);
                *tl = 0;
        }
-       mb->m_next = mrest;
-       mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
-       mreq->m_pkthdr.rcvif = NULL;
-       *mbp = mb;
-       return (mreq);
+       info.mb->m_next = mrest;
+       info.mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
+       info.mreq->m_pkthdr.rcvif = NULL;
+       *mbp = info.mb;
+       return (info.mreq);
+}
+
+void *
+nfsm_build(nfsm_info_t info, int bytes)
+{
+       void *ptr;
+
+       if (bytes > M_TRAILINGSPACE(info->mb)) {
+               MGET(info->mb2, MB_WAIT, MT_DATA);
+               if (bytes > MLEN)
+                       panic("build > MLEN");
+               info->mb->m_next = info->mb2;
+               info->mb = info->mb2;
+               info->mb->m_len = 0;
+               info->bpos = mtod(info->mb, caddr_t);
+       }
+       ptr = info->bpos;
+       info->mb->m_len += bytes;
+       info->bpos += bytes;
+       return (ptr);
+}
+
+/*
+ *
+ * If NULL returned caller is expected to abort with an EBADRPC error.
+ * Caller will usually use the NULLOUT macro.
+ */
+void *
+nfsm_dissect(nfsm_info_t info, int bytes)
+{
+       caddr_t cp2;
+       void *ptr;
+       int error;
+       int n;
+
+       n = mtod(info->md, caddr_t) + info->md->m_len - info->dpos;
+       if (bytes <= n) {
+               ptr = info->dpos;
+               info->dpos += bytes;
+       } else {
+               error = nfsm_disct(&info->md, &info->dpos, bytes, n, &cp2);
+               if (error) {
+                       m_freem(info->mrep);
+                       info->mrep = NULL;
+                       ptr = NULL;
+               } else {
+                       ptr = cp2;
+               }
+       }
+       return (ptr);
+}
+
+/*
+ *
+ * Caller is expected to abort if non-zero error is returned.
+ */
+int
+nfsm_fhtom(nfsm_info_t info, struct vnode *vp)
+{
+       u_int32_t *tl;
+       caddr_t cp;
+       int error;
+       int n;
+
+       if (info->v3) {
+               n = nfsm_rndup(VTONFS(vp)->n_fhsize) + NFSX_UNSIGNED;
+               if (n <= M_TRAILINGSPACE(info->mb)) {
+                       tl = nfsm_build(info, n);
+                       *tl++ = txdr_unsigned(VTONFS(vp)->n_fhsize);
+                       *(tl + ((n >> 2) - 2)) = 0;
+                       bcopy((caddr_t)VTONFS(vp)->n_fhp,(caddr_t)tl,
+                               VTONFS(vp)->n_fhsize);
+                       error = 0;
+               } else if ((error = nfsm_strtmbuf(&info->mb, &info->bpos,
+                                               (caddr_t)VTONFS(vp)->n_fhp,
+                                               VTONFS(vp)->n_fhsize)) != 0) {
+                       m_freem(info->mreq);
+                       info->mreq = NULL;
+               }
+       } else {
+               cp = nfsm_build(info, NFSX_V2FH);
+               bcopy(VTONFS(vp)->n_fhp, cp, NFSX_V2FH);
+               error = 0;
+       }
+       return (error);
+}
+
+void
+nfsm_srvfhtom(nfsm_info_t info, fhandle_t *fhp)
+{
+       u_int32_t *tl;
+
+       if (info->v3) {
+               tl = nfsm_build(info, NFSX_UNSIGNED + NFSX_V3FH);
+               *tl++ = txdr_unsigned(NFSX_V3FH);
+               bcopy(fhp, tl, NFSX_V3FH);
+       } else {
+               tl = nfsm_build(info, NFSX_V2FH);
+               bcopy(fhp, tl, NFSX_V2FH);
+       }
+}
+
+void
+nfsm_srvpostop_fh(nfsm_info_t info, fhandle_t *fhp)
+{
+       u_int32_t *tl;
+
+       tl = nfsm_build(info, 2 * NFSX_UNSIGNED + NFSX_V3FH);
+       *tl++ = nfs_true;
+       *tl++ = txdr_unsigned(NFSX_V3FH);
+       bcopy(fhp, tl, NFSX_V3FH);
+}
+
+/*
+ * Caller is expected to abort if non-zero error is returned.
+ *
+ * NOTE: (*vpp) may be loaded with a valid vnode even if (*gotvpp)
+ *      winds up 0.  The caller is responsible for dealing with (*vpp).
+ */
+int
+nfsm_mtofh(nfsm_info_t info, struct vnode *dvp, struct vnode **vpp, int *gotvpp)
+{
+       struct nfsnode *ttnp;
+       nfsfh_t *ttfhp;
+       u_int32_t *tl;
+       int ttfhsize;
+       int error = 0;
+
+       if (info->v3) {
+               tl = nfsm_dissect(info, NFSX_UNSIGNED);
+               if (tl == NULL)
+                       return(EBADRPC);
+               *gotvpp = fxdr_unsigned(int, *tl);
+       } else {
+               *gotvpp = 1;
+       }
+       if (*gotvpp) {
+               NEGATIVEOUT(ttfhsize = nfsm_getfh(info, &ttfhp));
+               error = nfs_nget(dvp->v_mount, ttfhp, ttfhsize, &ttnp);
+               if (error) {
+                       m_freem(info->mrep);
+                       info->mrep = NULL;
+                       return (error);
+               }
+               *vpp = NFSTOV(ttnp);
+       }
+       if (info->v3) {
+               tl = nfsm_dissect(info, NFSX_UNSIGNED);
+               if (tl == NULL)
+                       return (EBADRPC);
+               if (*gotvpp) {
+                       *gotvpp = fxdr_unsigned(int, *tl);
+               } else if (fxdr_unsigned(int, *tl)) {
+                       error = nfsm_adv(info, NFSX_V3FATTR);
+                       if (error)
+                               return (error);
+               }
+       }
+       if (*gotvpp)
+               error = nfsm_loadattr(info, *vpp, NULL);
+nfsmout:
+       return (error);
+}
+
+/*
+ *
+ * Caller is expected to abort with EBADRPC if a negative length is returned.
+ */
+int
+nfsm_getfh(nfsm_info_t info, nfsfh_t **fhpp)
+{
+       u_int32_t *tl;
+       int n;
+
+       *fhpp = NULL;
+       if (info->v3) {
+               tl = nfsm_dissect(info, NFSX_UNSIGNED);
+               if (tl == NULL)
+                       return(-1);
+               if ((n = fxdr_unsigned(int, *tl)) <= 0 || n > NFSX_V3FHMAX) {
+                       m_freem(info->mrep);
+                       info->mrep = NULL;
+                       return(-1);
+               }
+       } else {
+               n = NFSX_V2FH;
+       }
+       *fhpp = nfsm_dissect(info, nfsm_rndup(n));
+       if (*fhpp == NULL)
+               return(-1);
+       return(n);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_loadattr(nfsm_info_t info, struct vnode *vp, struct vattr *vap)
+{
+       int error;
+
+       error = nfs_loadattrcache(vp, &info->md, &info->dpos, vap, 0);
+       if (error) {
+               m_freem(info->mrep);
+               info->mrep = NULL;
+               return (error);
+       }
+       return (0);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_postop_attr(nfsm_info_t info, struct vnode *vp, int *attrp, int lflags)
+{
+       u_int32_t *tl;
+       int error;
+
+       tl = nfsm_dissect(info, NFSX_UNSIGNED);
+       if (tl == NULL)
+               return(EBADRPC);
+       *attrp = fxdr_unsigned(int, *tl);
+       if (*attrp) {
+               error = nfs_loadattrcache(vp, &info->md, &info->dpos,
+                                         NULL, lflags);
+               if (error) {
+                       *attrp = 0;
+                       m_freem(info->mrep);
+                       info->mrep = NULL;
+                       return (error);
+               }
+       }
+       return (0);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_wcc_data(nfsm_info_t info, struct vnode *vp, int *attrp)
+{
+       u_int32_t *tl;
+       int error;
+       int ttattrf;
+       int ttretf = 0;
+
+       tl = nfsm_dissect(info, NFSX_UNSIGNED);
+       if (tl == NULL)
+               return (EBADRPC);
+       if (*tl == nfs_true) {
+               tl = nfsm_dissect(info, 6 * NFSX_UNSIGNED);
+               if (tl == NULL)
+                       return (EBADRPC);
+               if (*attrp) {
+                       ttretf = (VTONFS(vp)->n_mtime ==
+                               fxdr_unsigned(u_int32_t, *(tl + 2)));
+                       if (ttretf == 0)
+                               VTONFS(vp)->n_flag |= NRMODIFIED;
+               }
+               error = nfsm_postop_attr(info, vp, &ttattrf,
+                                NFS_LATTR_NOSHRINK|NFS_LATTR_NOMTIMECHECK);
+               if (error)
+                       return(error);
+       } else {
+               error = nfsm_postop_attr(info, vp, &ttattrf,
+                                        NFS_LATTR_NOSHRINK);
+               if (error)
+                       return(error);
+       }
+       if (*attrp)
+               *attrp = ttretf;
+       else
+               *attrp = ttattrf;
+       return(0);
+}
+
+/*
+ * This function updates the attribute cache based on data returned in the
+ * NFS reply for NFS RPCs that modify the target file.  If the RPC succeeds
+ * a 'before' and 'after' mtime is returned that allows us to determine if
+ * the new mtime attribute represents our modification or someone else's
+ * modification.
+ *
+ * The flag argument returns non-0 if the original times matched, zero if
+ * they did not match.  NRMODIFIED is automatically set if the before time
+ * does not match the original n_mtime, and n_mtime is automatically updated
+ * to the new after time (by nfsm_postop_attr()).
+ *
+ * If full is true, set all fields, otherwise just set mode and time fields
+ */
+void
+nfsm_v3attrbuild(nfsm_info_t info, struct vattr *vap, int full)
+{
+       u_int32_t *tl;
+
+       if (vap->va_mode != (mode_t)VNOVAL) {
+               tl = nfsm_build(info, 2 * NFSX_UNSIGNED);
+               *tl++ = nfs_true;
+               *tl = txdr_unsigned(vap->va_mode);
+       } else {
+               tl = nfsm_build(info, NFSX_UNSIGNED);
+               *tl = nfs_false;
+       }
+       if (full && vap->va_uid != (uid_t)VNOVAL) {
+               tl = nfsm_build(info, 2 * NFSX_UNSIGNED);
+               *tl++ = nfs_true;
+               *tl = txdr_unsigned(vap->va_uid);
+       } else {
+               tl = nfsm_build(info, NFSX_UNSIGNED);
+               *tl = nfs_false;
+       }
+       if (full && vap->va_gid != (gid_t)VNOVAL) {
+               tl = nfsm_build(info, 2 * NFSX_UNSIGNED);
+               *tl++ = nfs_true;
+               *tl = txdr_unsigned(vap->va_gid);
+       } else {
+               tl = nfsm_build(info, NFSX_UNSIGNED);
+               *tl = nfs_false;
+       }
+       if (full && vap->va_size != VNOVAL) {
+               tl = nfsm_build(info, 3 * NFSX_UNSIGNED);
+               *tl++ = nfs_true;
+               txdr_hyper(vap->va_size, tl);
+       } else {
+               tl = nfsm_build(info, NFSX_UNSIGNED);
+               *tl = nfs_false;
+       }
+       if (vap->va_atime.tv_sec != VNOVAL) {
+               if (vap->va_atime.tv_sec != time_second) {
+                       tl = nfsm_build(info, 3 * NFSX_UNSIGNED);
+                       *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
+                       txdr_nfsv3time(&vap->va_atime, tl);
+               } else {
+                       tl = nfsm_build(info, NFSX_UNSIGNED);
+                       *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
+               }
+       } else {
+               tl = nfsm_build(info, NFSX_UNSIGNED);
+               *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
+       }
+       if (vap->va_mtime.tv_sec != VNOVAL) {
+               if (vap->va_mtime.tv_sec != time_second) {
+                       tl = nfsm_build(info, 3 * NFSX_UNSIGNED);
+                       *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
+                       txdr_nfsv3time(&vap->va_mtime, tl);
+               } else {
+                       tl = nfsm_build(info, NFSX_UNSIGNED);
+                       *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
+               }
+       } else {
+               tl = nfsm_build(info, NFSX_UNSIGNED);
+               *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
+       }
+}
+
+/*
+ * Caller is expected to abort with EBADRPC if a negative length is returned.
+ */
+int
+nfsm_strsiz(nfsm_info_t info, int maxlen)
+{
+       u_int32_t *tl;
+       int len;
+
+       tl = nfsm_dissect(info, NFSX_UNSIGNED);
+       if (tl == NULL)
+               return(-1);
+       len = fxdr_unsigned(int32_t, *tl);
+       if (len < 0 || len > maxlen)
+               return(-1);
+       return (len);
+}
+
+/*
+ * Caller is expected to abort if a negative length is returned, but also
+ * call nfsm_reply(0) if -2 is returned.
+ *
+ * This function sets *errorp.  Caller should not modify the error code.
+ */
+int
+nfsm_srvstrsiz(nfsm_info_t info, int maxlen, int *errorp)
+{
+       u_int32_t *tl;
+       int len;
+
+       tl = nfsm_dissect(info, NFSX_UNSIGNED);
+       if (tl == NULL) {
+               *errorp = EBADRPC;
+               return(-1);
+       }
+       len = fxdr_unsigned(int32_t,*tl);
+       if (len > maxlen || len <= 0) {
+               *errorp = EBADRPC;
+               return(-2);
+       }
+       return(len);
+}
+
+/*
+ * Caller is expected to abort if a negative length is returned, but also
+ * call nfsm_reply(0) if -2 is returned.
+ *
+ * This function sets *errorp.  Caller should not modify the error code.
+ */
+int
+nfsm_srvnamesiz(nfsm_info_t info, int *errorp)
+{
+       u_int32_t *tl;
+       int len;
+
+       tl = nfsm_dissect(info, NFSX_UNSIGNED);
+       if (tl == NULL) {
+               *errorp = EBADRPC;
+               return(-1);
+       }
+
+       /*
+        * In this case if *errorp is not EBADRPC and we are NFSv3,
+        * nfsm_reply() will not return a negative number.  But all
+        * call cases assume len is valid so we really do want
+        * to return -1.
+        */
+       len = fxdr_unsigned(int32_t,*tl);
+       if (len > NFS_MAXNAMLEN)
+               *errorp = NFSERR_NAMETOL;
+       if (len <= 0)
+               *errorp = EBADRPC;
+       if (*errorp)
+               return(-2);
+       return (len);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_mtouio(nfsm_info_t info, struct uio *uiop, int len)
+{
+       int error;
+
+       if (len > 0 &&
+          (error = nfsm_mbuftouio(&info->md, uiop, len, &info->dpos)) != 0) {
+               m_freem(info->mrep);
+               info->mrep = NULL;
+               return(error);
+       }
+       return(0);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_uiotom(nfsm_info_t info, struct uio *uiop, int len)
+{
+       int error;
+
+       if ((error = nfsm_uiotombuf(uiop, &info->mb, len, &info->bpos)) != 0) {
+               m_freem(info->mreq);
+               info->mreq = NULL;
+               return (error);
+       }
+       return(0);
+}
+
+/*
+ * Caller is expected to abort if a negative value is returned.  This
+ * function sets *errorp.  Caller should not modify the error code.
+ */
+int
+nfsm_request(nfsm_info_t info, struct vnode *vp, int procnum,
+            thread_t td, struct ucred *cred, int *errorp)
+{
+       *errorp = nfs_request(vp, info->mreq, procnum, td, cred,
+                             &info->mrep, &info->md, &info->dpos);
+       if (*errorp) {
+               if ((*errorp & NFSERR_RETERR) == 0)
+                       return(-1);
+               *errorp &= ~NFSERR_RETERR;
+       }
+       return(0);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_strtom(nfsm_info_t info, const void *data, int len, int maxlen)
+{
+       u_int32_t *tl;
+       int error;
+       int n;
+
+       if (len > maxlen) {
+               m_freem(info->mreq);
+               info->mreq = NULL;
+               return(ENAMETOOLONG);
+       }
+       n = nfsm_rndup(len) + NFSX_UNSIGNED;
+       if (n <= M_TRAILINGSPACE(info->mb)) {
+               tl = nfsm_build(info, n);
+               *tl++ = txdr_unsigned(len);
+               *(tl + ((n >> 2) - 2)) = 0;
+               bcopy(data, tl, len);
+               error = 0;
+       } else {
+               error = nfsm_strtmbuf(&info->mb, &info->bpos, data, len);
+               if (error) {
+                       m_freem(info->mreq);
+                       info->mreq = NULL;
+               }
+       }
+       return (error);
+}
+
+/*
+ * Caller is expected to abort if a negative value is returned.  This
+ * function sets *errorp.  Caller should not modify the error code.
+ */
+int
+nfsm_reply(nfsm_info_t info,
+          struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+          int siz, int *errorp)
+{
+       nfsd->nd_repstat = *errorp;
+       if (*errorp && !(nfsd->nd_flag & ND_NFSV3))
+               siz = 0;
+       nfs_rephead(siz, nfsd, slp, *errorp, &info->mreq,
+                   &info->mb, &info->bpos);
+       if (info->mrep != NULL) {
+               m_freem(info->mrep);
+               info->mrep = NULL;
+       }
+       if (*errorp && (!(nfsd->nd_flag & ND_NFSV3) || *errorp == EBADRPC)) {
+               *errorp = 0;
+               return(-1);
+       }
+       return(0);
+}
+
+void
+nfsm_writereply(nfsm_info_t info,
+               struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+               int error, int siz)
+{
+       nfsd->nd_repstat = error;
+       if (error && !(info->v3))
+               siz = 0;
+       nfs_rephead(siz, nfsd, slp, error, &info->mreq, &info->mb, &info->bpos);
+}
+
+/*
+ * Caller is expected to abort if a non-zero error is returned.
+ */
+int
+nfsm_adv(nfsm_info_t info, int len)
+{
+       int error;
+       int n;
+
+       n = mtod(info->md, caddr_t) + info->md->m_len - info->dpos;
+       if (n >= len) {
+               info->dpos += len;
+               error = 0;
+       } else if ((error = nfs_adv(&info->md, &info->dpos, len, n)) != 0) {
+               m_freem(info->mrep);
+               info->mrep = NULL;
+       }
+       return (error);
+}
+
+/*
+ * Caller is expected to abort if a negative length is returned, but also
+ * call nfsm_reply(0) if -2 is returned.
+ *
+ * This function sets *errorp.  Caller should not modify the error code.
+ */
+int
+nfsm_srvmtofh(nfsm_info_t info, struct nfsrv_descript *nfsd,
+             fhandle_t *fhp, int *errorp)
+{
+       u_int32_t *tl;
+       int fhlen;
+
+       if (nfsd->nd_flag & ND_NFSV3) {
+               tl = nfsm_dissect(info, NFSX_UNSIGNED);
+               if (tl == NULL) {
+                       *errorp = EBADRPC;
+                       return(-1);
+               }
+               fhlen = fxdr_unsigned(int, *tl);
+               if (fhlen != 0 && fhlen != NFSX_V3FH) {
+                       *errorp = EBADRPC;
+                       return(-2);
+               }
+       } else {
+               fhlen = NFSX_V2FH;
+       }
+       if (fhlen != 0) {
+               tl = nfsm_dissect(info, fhlen);
+               if (tl == NULL) {
+                       *errorp = EBADRPC;
+                       return(-1);
+               }
+               bcopy(tl, fhp, fhlen);
+       } else {
+               bzero(fhp, NFSX_V3FH);
+       }
+       return(0);
+}
+
+void *
+_nfsm_clget(nfsm_info_t info, struct mbuf *mp1, struct mbuf *mp2,
+          char *bp, char *be)
+{
+       u_int32_t *tl;
+
+       if (bp >= be) {
+               if (mp1 == info->mb)
+                       mp1->m_len += bp - info->bpos;
+               mp1 = m_getcl(MB_WAIT, MT_DATA, 0);
+               mp1->m_len = MCLBYTES;
+               mp2->m_next = mp1;
+               mp2 = mp1;
+               bp = mtod(mp1, caddr_t);
+               be = bp + mp1->m_len;
+       }
+       tl = (u_int32_t *)bp;
+       return (tl);
+}
+
+int
+nfsm_srvsattr(nfsm_info_t info, struct vattr *vap)
+{
+       u_int32_t *tl;
+       int error = 0;
+
+       NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+       if (*tl == nfs_true) {
+               NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+               vap->va_mode = nfstov_mode(*tl);
+       }
+       NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+       if (*tl == nfs_true) {
+               NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+               vap->va_uid = fxdr_unsigned(uid_t, *tl);
+       }
+       NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+       if (*tl == nfs_true) {
+               NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+               vap->va_gid = fxdr_unsigned(gid_t, *tl);
+       }
+       NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+       if (*tl == nfs_true) {
+               NULLOUT(tl = nfsm_dissect(info, 2 * NFSX_UNSIGNED));
+               vap->va_size = fxdr_hyper(tl);
+       }
+       NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+       switch (fxdr_unsigned(int, *tl)) {
+       case NFSV3SATTRTIME_TOCLIENT:
+               NULLOUT(tl = nfsm_dissect(info, 2 * NFSX_UNSIGNED));
+               fxdr_nfsv3time(tl, &vap->va_atime);
+               break;
+       case NFSV3SATTRTIME_TOSERVER:
+               getnanotime(&vap->va_atime);
+               break;
+       };
+       NULLOUT(tl = nfsm_dissect(info, NFSX_UNSIGNED));
+       switch (fxdr_unsigned(int, *tl)) {
+       case NFSV3SATTRTIME_TOCLIENT:
+               NULLOUT(tl = nfsm_dissect(info, 2 * NFSX_UNSIGNED));
+               fxdr_nfsv3time(tl, &vap->va_mtime);
+               break;
+       case NFSV3SATTRTIME_TOSERVER:
+               getnanotime(&vap->va_mtime);
+               break;
+       }
+nfsmout:
+       return (error);
 }
 
 /*
@@ -469,8 +1142,8 @@ nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
                        xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
                        if (xfer > 0) {
                                bcopy(mtod(mp2, caddr_t), p, xfer);
-                               NFSMADV(mp2, xfer);
                                mp2->m_len -= xfer;
+                               mp2->m_data += xfer;
                                p += xfer;
                                siz2 -= xfer;
                        }
@@ -633,22 +1306,20 @@ nfsm_adj(struct mbuf *mp, int len, int nul)
  * doesn't get too big...
  */
 void
-nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
-           struct vattr *before_vap, int after_ret, struct vattr *after_vap,
-           struct mbuf **mbp, char **bposp)
+nfsm_srvwcc_data(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                int before_ret, struct vattr *before_vap,
+                int after_ret, struct vattr *after_vap)
 {
-       struct mbuf *mb = *mbp, *mb2;
-       char *bpos = *bposp;
        u_int32_t *tl;
 
        /*
         * before_ret is 0 if before_vap is valid, non-zero if it isn't.
         */
        if (before_ret) {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+               tl = nfsm_build(info, NFSX_UNSIGNED);
                *tl = nfs_false;
        } else {
-               nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
+               tl = nfsm_build(info, 7 * NFSX_UNSIGNED);
                *tl++ = nfs_true;
                txdr_hyper(before_vap->va_size, tl);
                tl += 2;
@@ -656,31 +1327,25 @@ nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
                tl += 2;
                txdr_nfsv3time(&(before_vap->va_ctime), tl);
        }
-       *bposp = bpos;
-       *mbp = mb;
-       nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
+       nfsm_srvpostop_attr(info, nfsd, after_ret, after_vap);
 }
 
 void
-nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
-                  struct vattr *after_vap, struct mbuf **mbp, char **bposp)
+nfsm_srvpostop_attr(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                  int after_ret, struct vattr *after_vap)
 {
-       struct mbuf *mb = *mbp, *mb2;
-       char *bpos = *bposp;
-       u_int32_t *tl;
        struct nfs_fattr *fp;
+       u_int32_t *tl;
 
        if (after_ret) {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+               tl = nfsm_build(info, NFSX_UNSIGNED);
                *tl = nfs_false;
        } else {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
+               tl = nfsm_build(info, NFSX_UNSIGNED + NFSX_V3FATTR);
                *tl++ = nfs_true;
                fp = (struct nfs_fattr *)tl;
                nfsm_srvfattr(nfsd, after_vap, fp);
        }
-       *mbp = mb;
-       *bposp = bpos;
 }
 
 void
index bc78b4f..c01e4f9 100644 (file)
 struct ucred;
 struct vnode;
 
+struct nfsm_info {
+       struct nfsrv_descript *nfsd;
+       struct nfssvc_sock *slp;
+       struct mbuf     *mb;
+       struct mbuf     *mb2;
+       struct mbuf     *md;
+       struct mbuf     *mrep;
+       struct mbuf     *mreq;
+       caddr_t         bpos;
+       caddr_t         dpos;
+       int32_t         t2;
+       int             v3;
+       int             error;  /* if non-zero goto nfsmout */
+};
+
+typedef struct nfsm_info *nfsm_info_t;
+
+#define NULLOUT(nfsmexp)                               \
+       do { if ((nfsmexp) == NULL) {                   \
+               error = EBADRPC; goto nfsmout; }        \
+       } while(0)
+
+#define NEGATIVEOUT(nfsmexp)                           \
+       do { if ((nfsmexp) < 0) {                       \
+               error = EBADRPC; goto nfsmout; }        \
+       } while(0)
+
+#define NEGKEEPOUT(nfsmexp)                            \
+       do { if ((nfsmexp) < 0) {                       \
+               goto nfsmout; }                         \
+       } while(0)
+
+#define NEGREPLYOUT(nfsmexp)                           \
+       do {                                            \
+               int rv = (nfsmexp);                     \
+               if (rv < 0) {                           \
+                       if (rv == -2)                   \
+                               nfsm_reply(&info, nfsd, slp, 0, &error); \
+                       goto nfsmout;                   \
+               }                                       \
+       } while(0)
+
+#define ERROROUT(nfsmexp)      if ((error = (nfsmexp)) != 0) goto nfsmout
+
 /*
  * These macros do strange and peculiar things to mbuf chains for
  * the assistance of the nfs code. To attempt to use them for any
@@ -54,518 +98,66 @@ struct vnode;
 /*
  * First define what the actual subs. return
  */
-struct mbuf *nfsm_reqh (struct vnode *vp, u_long procid, int hsiz,
-                           caddr_t *bposp);
+void   nfsm_reqhead(nfsm_info_t info, struct vnode *vp,
+                               u_long procid, int hsiz);
 struct mbuf *nfsm_rpchead (struct ucred *cr, int nmflag, int procid,
-                              int auth_type, int auth_len, char *auth_str,
-                              int verf_len, char *verf_str,
-                              struct mbuf *mrest, int mrest_len,
-                              struct mbuf **mbp, u_int32_t *xidp);
-
-#define        M_HASCL(m)      ((m)->m_flags & M_EXT)
-#define        NFSMINOFF(m) \
-       do { \
-               if (M_HASCL(m)) \
-                       (m)->m_data = (m)->m_ext.ext_buf; \
-               else if ((m)->m_flags & M_PKTHDR) \
-                       (m)->m_data = (m)->m_pktdat; \
-               else \
-                       (m)->m_data = (m)->m_dat; \
-       } while (0)
-#define        NFSMADV(m, s) \
-       do { \
-               (m)->m_data += (s); \
-       } while (0)
-#define        NFSMSIZ(m)      ((M_HASCL(m))?MCLBYTES: \
-                               (((m)->m_flags & M_PKTHDR)?MHLEN:MLEN))
-
-/*
- * Now for the macros that do the simple stuff and call the functions
- * for the hard stuff.
- * These macros use several vars. declared in nfsm_reqhead and these
- * vars. must not be used elsewhere unless you are careful not to corrupt
- * them. The vars. starting with pN and tN (N=1,2,3,..) are temporaries
- * that may be used so long as the value is not expected to retained
- * after a macro.
- * I know, this is kind of dorkey, but it makes the actual op functions
- * fairly clean and deals with the mess caused by the xdr discriminating
- * unions.
- */
-
-#define        nfsm_build(a,c,s) \
-       do { \
-               if ((s) > M_TRAILINGSPACE(mb)) { \
-                       MGET(mb2, MB_WAIT, MT_DATA); \
-                       if ((s) > MLEN) \
-                               panic("build > MLEN"); \
-                       mb->m_next = mb2; \
-                       mb = mb2; \
-                       mb->m_len = 0; \
-                       bpos = mtod(mb, caddr_t); \
-               } \
-               (a) = (c)(bpos); \
-               mb->m_len += (s); \
-               bpos += (s); \
-       } while (0)
-
-#define        nfsm_dissect(a, c, s) \
-       do { \
-               t1 = mtod(md, caddr_t)+md->m_len-dpos; \
-               if (t1 >= (s)) { \
-                       (a) = (c)(dpos); \
-                       dpos += (s); \
-               } else if ((t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) != 0){ \
-                       error = t1; \
-                       m_freem(mrep); \
-                       goto nfsmout; \
-               } else { \
-                       (a) = (c)cp2; \
-               } \
-       } while (0)
-
-#define nfsm_fhtom(v, v3) \
-       do { \
-               if (v3) { \
-                       t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
-                       if (t2 <= M_TRAILINGSPACE(mb)) { \
-                               nfsm_build(tl, u_int32_t *, t2); \
-                               *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
-                               *(tl + ((t2>>2) - 2)) = 0; \
-                               bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
-                                       VTONFS(v)->n_fhsize); \
-                       } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, \
-                               (caddr_t)VTONFS(v)->n_fhp, \
-                               VTONFS(v)->n_fhsize)) != 0) { \
-                               error = t2; \
-                               m_freem(mreq); \
-                               goto nfsmout; \
-                       } \
-               } else { \
-                       nfsm_build(cp, caddr_t, NFSX_V2FH); \
-                       bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
-               } \
-       } while (0)
-
-#define nfsm_srvfhtom(f, v3) \
-       do { \
-               if (v3) { \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FH);\
-                       *tl++ = txdr_unsigned(NFSX_V3FH); \
-                       bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
-               } else { \
-                       nfsm_build(cp, caddr_t, NFSX_V2FH); \
-                       bcopy((caddr_t)(f), cp, NFSX_V2FH); \
-               } \
-       } while (0)
-
-#define nfsm_srvpostop_fh(f) \
-       do { \
-               nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
-               *tl++ = nfs_true; \
-               *tl++ = txdr_unsigned(NFSX_V3FH); \
-               bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
-       } while (0)
+                               int auth_type, int auth_len, char *auth_str,
+                               int verf_len, char *verf_str,
+                               struct mbuf *mrest, int mrest_len,
+                               struct mbuf **mbp, u_int32_t *xidp);
+void   *nfsm_build(nfsm_info_t info, int bytes);
+void   *nfsm_dissect(nfsm_info_t info, int bytes);
+int    nfsm_fhtom(nfsm_info_t info, struct vnode *vp);
+void   nfsm_srvfhtom(nfsm_info_t info, fhandle_t *fhp);
+void   nfsm_srvpostop_fh(nfsm_info_t info, fhandle_t *fhp);
+int nfsm_mtofh(nfsm_info_t info, struct vnode *dvp,
+                               struct vnode **vpp, int *gotvpp);
+int    nfsm_getfh(nfsm_info_t info, nfsfh_t **fhpp);
+int    nfsm_loadattr(nfsm_info_t info, struct vnode *vp, struct vattr *vap);
+int    nfsm_postop_attr(nfsm_info_t info, struct vnode *vp,
+                               int *attrp, int lflags);
+int    nfsm_wcc_data(nfsm_info_t info, struct vnode *vp, int *attrp);
+void   nfsm_v3attrbuild(nfsm_info_t info, struct vattr *vap, int full);
+int    nfsm_strsiz(nfsm_info_t info, int maxlen);
+int    nfsm_srvstrsiz(nfsm_info_t info, int maxlen, int *errorp);
+int    nfsm_srvnamesiz(nfsm_info_t info, int *errorp);
+int    nfsm_mtouio(nfsm_info_t info, struct uio *uiop, int len);
+int    nfsm_uiotom(nfsm_info_t info, struct uio *uiop, int len);
+int    nfsm_request(nfsm_info_t info, struct vnode *vp, int procnum,
+                               thread_t td, struct ucred *cred, int *errorp);
+int    nfsm_strtom(nfsm_info_t info, const void *data, int len, int maxlen);
+int    nfsm_reply(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                               struct nfssvc_sock *slp, int siz, int *errorp);
+void   nfsm_writereply(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                               struct nfssvc_sock *slp, int error, int siz);
+int    nfsm_adv(nfsm_info_t info, int len);
+int    nfsm_srvmtofh(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                               fhandle_t *fhp, int *errorp);
+void   *_nfsm_clget(nfsm_info_t info, struct mbuf *mp1, struct mbuf *mp2,
+                               char *bp, char *be);
+int    nfsm_srvsattr(nfsm_info_t info, struct vattr *vap);
+int    nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop,
+                               int siz, caddr_t *dpos);
+int    nfsm_uiotombuf (struct uio *uiop, struct mbuf **mq,
+                               int siz, caddr_t *bpos);
+int    nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz,
+                               int left, caddr_t *cp2);
+int    nfsm_strtmbuf (struct mbuf **, char **, const char *, long);
+void   nfsm_adj(struct mbuf *mp, int len, int nul);
+void   nfsm_srvwcc_data(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                               int before_ret, struct vattr *before_vap,
+                               int after_ret, struct vattr *after_vap);
+void   nfsm_srvpostop_attr(nfsm_info_t info, struct nfsrv_descript *nfsd,
+                               int after_ret, struct vattr *after_vap);
+void   nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
+                               struct nfs_fattr *fp);
+
+#define nfsm_clget(info, mp1, mp2, bp, be)     \
+       ((bp >= be) ? _nfsm_clget(info, mp1, mp2, bp, be) : (void *)bp)
+
+#define nfsm_rndup(a)   (((a) + 3) & (~0x3))
 
-#define nfsm_mtofh(d, v, v3, f) \
-       do { \
-               struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
-               if (v3) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       (f) = fxdr_unsigned(int, *tl); \
-               } else \
-                       (f) = 1; \
-               if (f) { \
-                       nfsm_getfh(ttfhp, ttfhsize, (v3)); \
-                       if ((t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
-                               &ttnp)) != 0) { \
-                               error = t1; \
-                               m_freem(mrep); \
-                               goto nfsmout; \
-                       } \
-                       (v) = NFSTOV(ttnp); \
-               } \
-               if (v3) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       if (f) \
-                               (f) = fxdr_unsigned(int, *tl); \
-                       else if (fxdr_unsigned(int, *tl)) \
-                               nfsm_adv(NFSX_V3FATTR); \
-               } \
-               if (f) \
-                       nfsm_loadattr((v), NULL); \
-       } while (0)
-
-#define nfsm_getfh(f, s, v3) \
-       do { \
-               if (v3) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
-                               (s) > NFSX_V3FHMAX) { \
-                               m_freem(mrep); \
-                               error = EBADRPC; \
-                               goto nfsmout; \
-                       } \
-               } else \
-                       (s) = NFSX_V2FH; \
-               nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); \
-       } while (0)
-
-#define        nfsm_loadattr(v, a) \
-       do { \
-               struct vnode *ttvp = (v); \
-               if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \
-                       error = t1; \
-                       m_freem(mrep); \
-                       goto nfsmout; \
-               } \
-               (v) = ttvp; \
-       } while (0)
-
-#define        nfsm_postop_attr(v, f, lflags) \
-       do { \
-               struct vnode *ttvp = (v); \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               if (((f) = fxdr_unsigned(int, *tl)) != 0) { \
-                       if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
-                               NULL, lflags)) != 0) { \
-                               error = t1; \
-                               (f) = 0; \
-                               m_freem(mrep); \
-                               goto nfsmout; \
-                       } \
-                       (v) = ttvp; \
-               } \
-       } while (0)
-
-/*
- * This function updates the attribute cache based on data returned in the
- * NFS reply for NFS RPCs that modify the target file.  If the RPC succeeds
- * a 'before' and 'after' mtime is returned that allows us to determine if
- * the new mtime attribute represents our modification or someone else's
- * modification.  
- *
- * The flag argument returns non-0 if the original times matched, zero if
- * they did not match.  NRMODIFIED is automatically set if the before time
- * does not match the original n_mtime, and n_mtime is automatically updated
- * to the new after time (by nfsm_postop_attr()).
- */
-/* Used as (f) for nfsm_wcc_data() */
 #define NFSV3_WCCRATTR 0
 #define NFSV3_WCCCHK   1
 
-#define        nfsm_wcc_data(v, f) \
-       do { \
-               int ttattrf, ttretf = 0; \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               if (*tl == nfs_true) { \
-                       nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \
-                       if (f) { \
-                               ttretf = (VTONFS(v)->n_mtime == \
-                                       fxdr_unsigned(u_int32_t, *(tl + 2))); \
-                               if (!ttretf) \
-                                       VTONFS(v)->n_flag |= NRMODIFIED; \
-                       } \
-                       nfsm_postop_attr((v), ttattrf, NFS_LATTR_NOSHRINK|NFS_LATTR_NOMTIMECHECK); \
-               } else { \
-                       nfsm_postop_attr((v), ttattrf, NFS_LATTR_NOSHRINK); \
-               } \
-               if (f) { \
-                       (f) = ttretf; \
-               } else { \
-                       (f) = ttattrf; \
-               } \
-       } while (0)
-
-/* If full is true, set all fields, otherwise just set mode and time fields */
-#define nfsm_v3attrbuild(a, full) \
-       do { \
-               if ((a)->va_mode != (mode_t)VNOVAL) {                   \
-                       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
-                       *tl++ = nfs_true;                               \
-                       *tl = txdr_unsigned((a)->va_mode);              \
-               } else {                                                \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
-                       *tl = nfs_false;                                \
-               }                                                       \
-               if ((full) && (a)->va_uid != (uid_t)VNOVAL) {           \
-                       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
-                       *tl++ = nfs_true;                               \
-                       *tl = txdr_unsigned((a)->va_uid);               \
-               } else {                                                \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
-                       *tl = nfs_false;                                \
-               }                                                       \
-               if ((full) && (a)->va_gid != (gid_t)VNOVAL) {           \
-                       nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
-                       *tl++ = nfs_true;                               \
-                       *tl = txdr_unsigned((a)->va_gid);               \
-               } else {                                                \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
-                       *tl = nfs_false;                                \
-               }                                                       \
-               if ((full) && (a)->va_size != VNOVAL) {                 \
-                       nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); \
-                       *tl++ = nfs_true;                               \
-                       txdr_hyper((a)->va_size, tl);                   \
-               } else {                                                \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
-                       *tl = nfs_false;                                \
-               }                                                       \
-               if ((a)->va_atime.tv_sec != VNOVAL) {                   \
-                       if ((a)->va_atime.tv_sec != time_second) {      \
-                               nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
-                               *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
-                               txdr_nfsv3time(&(a)->va_atime, tl);     \
-                       } else {                                        \
-                               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
-                               *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
-                       }                                               \
-               } else {                                                \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
-                       *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
-               }                                                       \
-               if ((a)->va_mtime.tv_sec != VNOVAL) {                   \
-                       if ((a)->va_mtime.tv_sec != time_second) {      \
-                               nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);\
-                               *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);\
-                               txdr_nfsv3time(&(a)->va_mtime, tl);     \
-                       } else {                                        \
-                               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); \
-                               *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); \
-                       }                                               \
-               } else {                                                \
-                       nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);     \
-                       *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); \
-               }                                                       \
-       } while (0)
-                               
-
-#define        nfsm_strsiz(s,m) \
-       do { \
-               nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
-               if (((s) = fxdr_unsigned(int32_t,*tl)) > (m)) { \
-                       m_freem(mrep); \
-                       error = EBADRPC; \
-                       goto nfsmout; \
-               } \
-       } while (0)
-
-#define        nfsm_srvstrsiz(s,m) \
-       do { \
-               nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
-               if (((s) = fxdr_unsigned(int32_t,*tl)) > (m) || (s) <= 0) { \
-                       error = EBADRPC; \
-                       nfsm_reply(0); \
-               } \
-       } while (0)
-
-#define        nfsm_srvnamesiz(s) \
-       do { \
-               nfsm_dissect(tl,u_int32_t *,NFSX_UNSIGNED); \
-               if (((s) = fxdr_unsigned(int32_t,*tl)) > NFS_MAXNAMLEN) \
-                       error = NFSERR_NAMETOL; \
-               if ((s) <= 0) \
-                       error = EBADRPC; \
-               if (error) \
-                       nfsm_reply(0); \
-       } while (0)
-
-#define nfsm_mtouio(p,s) \
-       do {\
-               if ((s) > 0 && \
-                  (t1 = nfsm_mbuftouio(&md,(p),(s),&dpos)) != 0) { \
-                       error = t1; \
-                       m_freem(mrep); \
-                       goto nfsmout; \
-               } \
-       } while (0)
-
-#define nfsm_uiotom(p,s) \
-       do { \
-               if ((t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) != 0) { \
-                       error = t1; \
-                       m_freem(mreq); \
-                       goto nfsmout; \
-               } \
-       } while (0)
-
-#define        nfsm_reqhead(v,a,s) \
-       do { \
-               mb = mreq = nfsm_reqh((v),(a),(s),&bpos); \
-       } while (0)
-
-#define nfsm_rndup(a)  (((a)+3)&(~0x3))
-
-#define        nfsm_request(v, t, td, c) \
-       do { \
-               if ((error = nfs_request((v), mreq, (t), (td), \
-                  (c), &mrep, &md, &dpos)) != 0) { \
-                       if (error & NFSERR_RETERR) \
-                               error &= ~NFSERR_RETERR; \
-                       else \
-                               goto nfsmout; \
-               } \
-       } while (0)
-
-#define        nfsm_strtom(a,s,m) \
-       do {\
-               if ((s) > (m)) { \
-                       m_freem(mreq); \
-                       error = ENAMETOOLONG; \
-                       goto nfsmout; \
-               } \
-               t2 = nfsm_rndup(s)+NFSX_UNSIGNED; \
-               if (t2 <= M_TRAILINGSPACE(mb)) { \
-                       nfsm_build(tl,u_int32_t *,t2); \
-                       *tl++ = txdr_unsigned(s); \
-                       *(tl+((t2>>2)-2)) = 0; \
-                       bcopy((const char *)(a), (caddr_t)tl, (s)); \
-               } else if ((t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) != 0) { \
-                       error = t2; \
-                       m_freem(mreq); \
-                       goto nfsmout; \
-               } \
-       } while (0)
-
-#define        nfsm_srvdone \
-       do { \
-               nfsmout: \
-               return (error); \
-       } while (0)
-
-#define        nfsm_reply(s) \
-       do { \
-               nfsd->nd_repstat = error; \
-               if (error && !(nfsd->nd_flag & ND_NFSV3)) \
-                   nfs_rephead(0, nfsd, slp, error, mrq, &mb, &bpos); \
-               else \
-                   nfs_rephead((s), nfsd, slp, error, mrq, &mb, &bpos); \
-               if (mrep != NULL) { \
-                       m_freem(mrep); \
-                       mrep = NULL; \
-               } \
-               mreq = *mrq; \
-               if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
-                       error == EBADRPC)) { \
-                       error = 0; \
-                       goto nfsmout; \
-               } \
-       } while (0)
-
-#define        nfsm_writereply(s, v3) \
-       do { \
-               nfsd->nd_repstat = error; \
-               if (error && !(v3)) \
-                   nfs_rephead(0, nfsd, slp, error, &mreq, &mb, &bpos); \
-               else \
-                   nfs_rephead((s), nfsd, slp, error, &mreq, &mb, &bpos); \
-       } while (0)
-
-#define        nfsm_adv(s) \
-       do { \
-               t1 = mtod(md, caddr_t)+md->m_len-dpos; \
-               if (t1 >= (s)) { \
-                       dpos += (s); \
-               } else if ((t1 = nfs_adv(&md, &dpos, (s), t1)) != 0) { \
-                       error = t1; \
-                       m_freem(mrep); \
-                       goto nfsmout; \
-               } \
-       } while (0)
-
-#define nfsm_srvmtofh(f) \
-       do { \
-               int fhlen; \
-               if (nfsd->nd_flag & ND_NFSV3) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       fhlen = fxdr_unsigned(int, *tl); \
-                       if (fhlen != 0 && fhlen != NFSX_V3FH) { \
-                               error = EBADRPC; \
-                               nfsm_reply(0); \
-                       } \
-               } else { \
-                       fhlen = NFSX_V2FH; \
-               } \
-               if (fhlen != 0) { \
-                       nfsm_dissect(tl, u_int32_t *, fhlen); \
-                       bcopy((caddr_t)tl, (caddr_t)(f), fhlen); \
-               } else {\
-                       bzero((caddr_t)(f), NFSX_V3FH); \
-               } \
-       } while (0)
-
-#define        nfsm_clget(mp1, mp2, mb, bp, be, tl) \
-       do { \
-               if (bp >= be) { \
-                       if (mp1 == mb) \
-                               mp1->m_len += bp-bpos; \
-                       mp1 = m_getcl(MB_WAIT, MT_DATA, 0); \
-                       mp1->m_len = MCLBYTES; \
-                       mp2->m_next = mp1; \
-                       mp2 = mp1; \
-                       bp = mtod(mp1, caddr_t); \
-                       be = bp+mp1->m_len; \
-               } \
-               tl = (u_int32_t *)bp; \
-       } while (0)
-
-#define        nfsm_srvfillattr(a, f) \
-       do { \
-               nfsm_srvfattr(nfsd, (a), (f)); \
-       } while (0)
-
-#define nfsm_srvwcc_data(br, b, ar, a) \
-       do { \
-               nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos); \
-       } while (0)
-
-#define nfsm_srvpostop_attr(r, a) \
-       do { \
-               nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos); \
-       } while (0)
-
-#define nfsm_srvsattr(a) \
-       do { \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               if (*tl == nfs_true) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       (a)->va_mode = nfstov_mode(*tl); \
-               } \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               if (*tl == nfs_true) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       (a)->va_uid = fxdr_unsigned(uid_t, *tl); \
-               } \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               if (*tl == nfs_true) { \
-                       nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-                       (a)->va_gid = fxdr_unsigned(gid_t, *tl); \
-               } \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               if (*tl == nfs_true) { \
-                       nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \
-                       (a)->va_size = fxdr_hyper(tl); \
-               } \
-               nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
-               switch (fxdr_unsigned(int, *tl)) { \
-               case NFSV3SATTRTIME_TOCLIENT: \
-                       nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); \