NFS - create nfsm_subs.c, clean up externs
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 16 Jul 2009 15:19:14 +0000 (08:19 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 16 Jul 2009 15:19:14 +0000 (08:19 -0700)
* Move nfsm_*() procedures from nfs_subs.c to nfsm_subs.c

* Clean up externs improperly embedded in .c files.

15 files changed:
sys/conf/files
sys/vfs/nfs/Makefile
sys/vfs/nfs/bootp_subr.c
sys/vfs/nfs/nfs.h
sys/vfs/nfs/nfs_bio.c
sys/vfs/nfs/nfs_mountrpc.c
sys/vfs/nfs/nfs_node.c
sys/vfs/nfs/nfs_serv.c
sys/vfs/nfs/nfs_socket.c
sys/vfs/nfs/nfs_srvcache.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 [new file with mode: 0644]

index 022fa58..afaaf3f 100644 (file)
@@ -1265,6 +1265,7 @@ vfs/nfs/nfs_vfsops.c              optional nfs
 vfs/nfs/nfs_vnops.c            optional nfs
 vfs/nfs/nfs_kerb.c             optional nfs
 vfs/nfs/nfs_iod.c              optional nfs
+vfs/nfs/nfsm_subs.c            optional nfs
 vfs/nfs/bootp_subr.c           optional bootp
 vfs/nfs/nfs_mountrpc.c         optional nfs
 vfs/nfs/krpc_subr.c            optional nfs
index 67df628..f3e8e49 100644 (file)
@@ -4,9 +4,12 @@
 KMOD=  nfs
 SRCS=  nfs_bio.c nfs_node.c nfs_kerb.c nfs_serv.c nfs_socket.c \
        nfs_srvcache.c nfs_subs.c nfs_syscalls.c nfs_vfsops.c nfs_iod.c \
-       nfs_vnops.c opt_inet.h opt_nfs.h opt_vmpage.h opt_bootp.h \
-       opt_nfsroot.h
-NFS_INET?=     1       # 0/1 - requires INET to be configured in kernel
+       nfsm_subs.c nfs_vnops.c \
+       opt_inet.h opt_nfs.h opt_vmpage.h opt_bootp.h opt_nfsroot.h
+
+# 0/1 - requires INET to be configured in kernel
+#
+NFS_INET?=     1
 
 opt_inet.h:
        touch ${.TARGET}
index 8e50a48..2e1b9c7 100644 (file)
@@ -212,7 +212,6 @@ struct bootpc_globalcontext {
 #define DHCP_REQUEST  3
 #define DHCP_ACK      5
 
-extern struct nfsv3_diskless nfsv3_diskless;
 static char bootp_cookie[128];
 SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD,
        bootp_cookie, 0, "Cookie (T134) supplied by bootp server");
index 4c38f42..bf80f83 100644 (file)
@@ -45,6 +45,7 @@
 #include "opt_nfs.h"
 #endif
 
+#include <sys/vnode.h>
 #include <sys/mutex.h>
 
 /*
@@ -401,8 +402,6 @@ struct nfsreq {
 #endif
 #define        NMUIDHASH(nmp, uid) \
        (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
-#define        NFSNOHASH(fhsum) \
-       (&nfsnodehashtbl[(fhsum) & nfsnodehash])
 
 /*
  * Network address hash list element
@@ -597,6 +596,29 @@ extern int nfs_debug;
 
 #endif
 
+extern u_int32_t nfs_xdrneg1;
+extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers;
+extern u_int32_t rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr;
+extern u_int32_t rpc_auth_kerb;
+extern u_int32_t nfs_prog, nfs_true, nfs_false;
+extern struct nfsstats nfsstats;
+extern nfstype nfsv2_type[9];
+extern nfstype nfsv3_type[9];
+extern int nfsv2_procid[NFS_NPROCS];
+extern enum vtype nv3tov_type[8];
+extern int nfsv3_procid[NFS_NPROCS];
+extern int nfs_ticks;
+extern struct nfsrtt nfsrtt;
+extern int nfsrtton;
+extern int nfsrvw_procrastinate;
+extern int nfsrvw_procrastinate_v3;
+extern int32_t (*nfsrv3_procs[NFS_NPROCS]) (struct nfsrv_descript *nd,
+                                           struct nfssvc_sock *slp,
+                                           struct thread *td,
+                                           struct mbuf **mreqp);
+
+extern struct nfsv3_diskless nfsv3_diskless;
+
 u_quad_t nfs_curusec (void);
 int    nfs_init (struct vfsconf *vfsp);
 int    nfs_uninit (struct vfsconf *vfsp);
index 1b572d1..a10aa70 100644 (file)
@@ -71,9 +71,6 @@ static struct buf *nfs_getcacheblk(struct vnode *vp, off_t loffset,
 static int nfs_check_dirent(struct nfs_dirent *dp, int maxlen);
 static void nfsiodone_sync(struct bio *bio);
 
-extern int nfs_pbuf_freecnt;
-extern struct nfsstats nfsstats;
-
 /*
  * Vnode op for VM getpages.
  *
index 668baca..233cbc9 100644 (file)
@@ -86,8 +86,6 @@
  * first complaint will happen after (1+2+3+4+5)=15 seconds.
  */
 
-extern struct nfsv3_diskless nfsv3_diskless;
-
 static int getdec(char **ptr);
 static char *substr(char *a,char *b);
 static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
index 63f676d..78952a3 100644 (file)
@@ -63,6 +63,8 @@ static u_long nfsnodehash;
 #define TRUE   1
 #define        FALSE   0
 
+#define NFSNOHASH(fhsum)       (&nfsnodehashtbl[(fhsum) & nfsnodehash])
+
 /*
  * Initialize hash links for nfsnodes
  * and build nfsnode free list.
index 2aba4d5..220db22 100644 (file)
@@ -122,11 +122,6 @@ nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
 #ifndef NFS_NOSERVER 
 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
                      NFCHR, NFNON };
-/* Global vars */
-extern u_int32_t nfs_xdrneg1;
-extern u_int32_t nfs_false, nfs_true;
-extern enum vtype nv3tov_type[8];
-extern struct nfsstats nfsstats;
 
 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
 int nfsrvw_procrastinate_v3 = 0;
index 03a2889..1bbfefa 100644 (file)
          ((((n)->nm_srtt[t-1] + 7) >> 3) + (n)->nm_sdrtt[t-1] + 1)))
 #define        NFS_SRTT(r)     (r)->r_nmp->nm_srtt[proct[(r)->r_procnum] - 1]
 #define        NFS_SDRTT(r)    (r)->r_nmp->nm_sdrtt[proct[(r)->r_procnum] - 1]
-/*
- * External data, mostly RPC constants in XDR form
- */
-extern u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers,
-       rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr,
-       rpc_auth_kerb;
-extern u_int32_t nfs_prog;
-extern struct nfsstats nfsstats;
-extern int nfsv3_procid[NFS_NPROCS];
-extern int nfs_ticks;
 
 /*
  * Defines which timer to use for the procnum.
index a0c5558..00cd75b 100644 (file)
@@ -58,8 +58,6 @@
 #include "nfsrvcache.h"
 
 #ifndef NFS_NOSERVER 
-extern struct nfsstats nfsstats;
-extern int nfsv2_procid[NFS_NPROCS];
 static long numnfsrvcache;
 static long desirednfsrvcache = NFSRVCACHESIZ;
 
index 0931c9f..4051d75 100644 (file)
  * This is kinda hokey, but may save a little time doing byte swaps
  */
 u_int32_t nfs_xdrneg1;
-u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
-       rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
-       rpc_auth_kerb;
+u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers;
+u_int32_t rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr;
+u_int32_t rpc_auth_kerb;
 u_int32_t nfs_prog, nfs_true, nfs_false;
 
 /* And other global data */
-static u_int32_t nfs_xid = 0;
 static enum vtype nv2tov_type[8]= {
        VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON,  VNON 
 };
@@ -99,7 +98,8 @@ enum vtype nv3tov_type[8]= {
 };
 
 int nfs_ticks;
-int nfs_pbuf_freecnt = -1;     /* start out unlimited */
+
+static int nfs_pbuf_freecnt = -1;      /* start out unlimited */
 
 struct nfsmount_head nfs_mountq = TAILQ_HEAD_INITIALIZER(nfs_mountq);
 struct nfssvc_sockhead nfssvc_sockhead;
@@ -541,18 +541,9 @@ static short *nfsrv_v3errmap[] = {
 
 #endif /* NFS_NOSERVER */
 
-extern struct nfsrtt nfsrtt;
-extern struct nfsstats nfsstats;
-extern nfstype nfsv2_type[9];
-extern nfstype nfsv3_type[9];
-extern struct nfsnodehashhead *nfsnodehashtbl;
-extern u_long nfsnodehash;
-
 struct nfssvc_args;
 extern int sys_nfssvc(struct proc *, struct nfssvc_args *, int *);
 
-LIST_HEAD(nfsnodehashhead, nfsnode);
-
 /*
  * This needs to return a monotonically increasing or close to monotonically
  * increasing result, otherwise the write gathering queues won't work 
@@ -568,465 +559,6 @@ nfs_curusec(void)
 }
 
 /*
- * Create the header for an rpc request packet
- * 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)
-{
-       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);
-}
-
-/*
- * Build the RPC header and fill in the authorization info.
- * The authorization string argument is only used when the credentials
- * come from outside of the kernel.
- * Returns the head of the mbuf list.
- */
-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)
-{
-       struct mbuf *mb;
-       u_int32_t *tl;
-       caddr_t bpos;
-       int i;
-       struct mbuf *mreq, *mb2;
-       int siz, grpsiz, authsiz, dsiz;
-
-       authsiz = nfsm_rndup(auth_len);
-       dsiz = authsiz + 10 * NFSX_UNSIGNED;
-       mb = m_getl(dsiz, MB_WAIT, MT_DATA, M_PKTHDR, NULL);
-       if (dsiz < MINCLSIZE) {
-               if (dsiz < MHLEN)
-                       MH_ALIGN(mb, dsiz);
-               else
-                       MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
-       }
-       mb->m_len = mb->m_pkthdr.len = 0;
-       mreq = mb;
-       bpos = mtod(mb, caddr_t);
-
-       /*
-        * First the RPC header.
-        */
-       nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
-
-       /* Get a pretty random xid to start with */
-       if (!nfs_xid) 
-               nfs_xid = krandom();
-       /*
-        * Skip zero xid if it should ever happen.
-        */
-       if (++nfs_xid == 0)
-               nfs_xid++;
-
-       *tl++ = *xidp = txdr_unsigned(nfs_xid);
-       *tl++ = rpc_call;
-       *tl++ = rpc_vers;
-       *tl++ = txdr_unsigned(NFS_PROG);
-       if (nmflag & NFSMNT_NFSV3)
-               *tl++ = txdr_unsigned(NFS_VER3);
-       else
-               *tl++ = txdr_unsigned(NFS_VER2);
-       if (nmflag & NFSMNT_NFSV3)
-               *tl++ = txdr_unsigned(procid);
-       else
-               *tl++ = txdr_unsigned(nfsv2_procid[procid]);
-
-       /*
-        * And then the authorization cred.
-        */
-       *tl++ = txdr_unsigned(auth_type);
-       *tl = txdr_unsigned(authsiz);
-       switch (auth_type) {
-       case RPCAUTH_UNIX:
-               nfsm_build(tl, u_int32_t *, auth_len);
-               *tl++ = 0;              /* stamp ?? */
-               *tl++ = 0;              /* NULL hostname */
-               *tl++ = txdr_unsigned(cr->cr_uid);
-               *tl++ = txdr_unsigned(cr->cr_groups[0]);
-               grpsiz = (auth_len >> 2) - 5;
-               *tl++ = txdr_unsigned(grpsiz);
-               for (i = 1; i <= grpsiz; i++)
-                       *tl++ = txdr_unsigned(cr->cr_groups[i]);
-               break;
-       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);
-                       }
-                       i = min(siz, M_TRAILINGSPACE(mb));
-                       bcopy(auth_str, bpos, i);
-                       mb->m_len += i;
-                       auth_str += i;
-                       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;
-               }
-               break;
-       };
-
-       /*
-        * And the verifier...
-        */
-       nfsm_build(tl, u_int32_t *, 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);
-                       }
-                       i = min(siz, M_TRAILINGSPACE(mb));
-                       bcopy(verf_str, bpos, i);
-                       mb->m_len += i;
-                       verf_str += i;
-                       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;
-               }
-       } 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);
-}
-
-/*
- * copies mbuf chain to the uio scatter/gather list
- */
-int
-nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
-{
-       char *mbufcp, *uiocp;
-       int xfer, left, len;
-       struct mbuf *mp;
-       long uiosiz, rem;
-       int error = 0;
-
-       mp = *mrep;
-       mbufcp = *dpos;
-       len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
-       rem = nfsm_rndup(siz)-siz;
-       while (siz > 0) {
-               if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
-                       return (EFBIG);
-               left = uiop->uio_iov->iov_len;
-               uiocp = uiop->uio_iov->iov_base;
-               if (left > siz)
-                       left = siz;
-               uiosiz = left;
-               while (left > 0) {
-                       while (len == 0) {
-                               mp = mp->m_next;
-                               if (mp == NULL)
-                                       return (EBADRPC);
-                               mbufcp = mtod(mp, caddr_t);
-                               len = mp->m_len;
-                       }
-                       xfer = (left > len) ? len : left;
-#ifdef notdef
-                       /* Not Yet.. */
-                       if (uiop->uio_iov->iov_op != NULL)
-                               (*(uiop->uio_iov->iov_op))
-                               (mbufcp, uiocp, xfer);
-                       else
-#endif
-                       if (uiop->uio_segflg == UIO_SYSSPACE)
-                               bcopy(mbufcp, uiocp, xfer);
-                       else
-                               copyout(mbufcp, uiocp, xfer);
-                       left -= xfer;
-                       len -= xfer;
-                       mbufcp += xfer;
-                       uiocp += xfer;
-                       uiop->uio_offset += xfer;
-                       uiop->uio_resid -= xfer;
-               }
-               if (uiop->uio_iov->iov_len <= siz) {
-                       uiop->uio_iovcnt--;
-                       uiop->uio_iov++;
-               } else {
-                       uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + uiosiz;
-                       uiop->uio_iov->iov_len -= uiosiz;
-               }
-               siz -= uiosiz;
-       }
-       *dpos = mbufcp;
-       *mrep = mp;
-       if (rem > 0) {
-               if (len < rem)
-                       error = nfs_adv(mrep, dpos, rem, len);
-               else
-                       *dpos += rem;
-       }
-       return (error);
-}
-
-/*
- * copies a uio scatter/gather list to an mbuf chain.
- * NOTE: can ony handle iovcnt == 1
- */
-int
-nfsm_uiotombuf(struct uio *uiop, struct mbuf **mq, int siz, caddr_t *bpos)
-{
-       char *uiocp;
-       struct mbuf *mp, *mp2;
-       int xfer, left, mlen;
-       int uiosiz, rem;
-       boolean_t getcluster;
-       char *cp;
-
-#ifdef DIAGNOSTIC
-       if (uiop->uio_iovcnt != 1)
-               panic("nfsm_uiotombuf: iovcnt != 1");
-#endif
-
-       if (siz >= MINCLSIZE)
-               getcluster = TRUE;
-       else
-               getcluster = FALSE;
-       rem = nfsm_rndup(siz) - siz;
-       mp = mp2 = *mq;
-       while (siz > 0) {
-               left = uiop->uio_iov->iov_len;
-               uiocp = uiop->uio_iov->iov_base;
-               if (left > siz)
-                       left = siz;
-               uiosiz = left;
-               while (left > 0) {
-                       mlen = M_TRAILINGSPACE(mp);
-                       if (mlen == 0) {
-                               if (getcluster)
-                                       mp = m_getcl(MB_WAIT, MT_DATA, 0);
-                               else
-                                       mp = m_get(MB_WAIT, MT_DATA);
-                               mp->m_len = 0;
-                               mp2->m_next = mp;
-                               mp2 = mp;
-                               mlen = M_TRAILINGSPACE(mp);
-                       }
-                       xfer = (left > mlen) ? mlen : left;
-#ifdef notdef
-                       /* Not Yet.. */
-                       if (uiop->uio_iov->iov_op != NULL)
-                               (*(uiop->uio_iov->iov_op))
-                               (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
-                       else
-#endif
-                       if (uiop->uio_segflg == UIO_SYSSPACE)
-                               bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
-                       else
-                               copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
-                       mp->m_len += xfer;
-                       left -= xfer;
-                       uiocp += xfer;
-                       uiop->uio_offset += xfer;
-                       uiop->uio_resid -= xfer;
-               }
-               uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + uiosiz;
-               uiop->uio_iov->iov_len -= uiosiz;
-               siz -= uiosiz;
-       }
-       if (rem > 0) {
-               if (rem > M_TRAILINGSPACE(mp)) {
-                       MGET(mp, MB_WAIT, MT_DATA);
-                       mp->m_len = 0;
-                       mp2->m_next = mp;
-               }
-               cp = mtod(mp, caddr_t)+mp->m_len;
-               for (left = 0; left < rem; left++)
-                       *cp++ = '\0';
-               mp->m_len += rem;
-               *bpos = cp;
-       } else
-               *bpos = mtod(mp, caddr_t)+mp->m_len;
-       *mq = mp;
-       return (0);
-}
-
-/*
- * Help break down an mbuf chain by setting the first siz bytes contiguous
- * pointed to by returned val.
- * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
- * cases. (The macros use the vars. dpos and dpos2)
- */
-int
-nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
-{
-       struct mbuf *mp, *mp2;
-       int siz2, xfer;
-       caddr_t p;
-
-       mp = *mdp;
-       while (left == 0) {
-               *mdp = mp = mp->m_next;
-               if (mp == NULL)
-                       return (EBADRPC);
-               left = mp->m_len;
-               *dposp = mtod(mp, caddr_t);
-       }
-       if (left >= siz) {
-               *cp2 = *dposp;
-               *dposp += siz;
-       } else if (mp->m_next == NULL) {
-               return (EBADRPC);
-       } else if (siz > MHLEN) {
-               panic("nfs S too big");
-       } else {
-               MGET(mp2, MB_WAIT, MT_DATA);
-               mp2->m_next = mp->m_next;
-               mp->m_next = mp2;
-               mp->m_len -= left;
-               mp = mp2;
-               *cp2 = p = mtod(mp, caddr_t);
-               bcopy(*dposp, p, left);         /* Copy what was left */
-               siz2 = siz-left;
-               p += left;
-               mp2 = mp->m_next;
-               /* Loop around copying up the siz2 bytes */
-               while (siz2 > 0) {
-                       if (mp2 == NULL)
-                               return (EBADRPC);
-                       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;
-                               p += xfer;
-                               siz2 -= xfer;
-                       }
-                       if (siz2 > 0)
-                               mp2 = mp2->m_next;
-               }
-               mp->m_len = siz;
-               *mdp = mp2;
-               *dposp = mtod(mp2, caddr_t);
-       }
-       return (0);
-}
-
-/*
- * Advance the position in the mbuf chain.
- */
-int
-nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
-{
-       struct mbuf *m;
-       int s;
-
-       m = *mdp;
-       s = left;
-       while (s < offs) {
-               offs -= s;
-               m = m->m_next;
-               if (m == NULL)
-                       return (EBADRPC);
-               s = m->m_len;
-       }
-       *mdp = m;
-       *dposp = mtod(m, caddr_t)+offs;
-       return (0);
-}
-
-/*
- * Copy a string into mbufs for the hard cases...
- */
-int
-nfsm_strtmbuf(struct mbuf **mb, char **bpos, const char *cp, long siz)
-{
-       struct mbuf *m1 = NULL, *m2;
-       long left, xfer, len, tlen;
-       u_int32_t *tl;
-       int putsize;
-
-       putsize = 1;
-       m2 = *mb;
-       left = M_TRAILINGSPACE(m2);
-       if (left > 0) {
-               tl = ((u_int32_t *)(*bpos));
-               *tl++ = txdr_unsigned(siz);
-               putsize = 0;
-               left -= NFSX_UNSIGNED;
-               m2->m_len += NFSX_UNSIGNED;
-               if (left > 0) {
-                       bcopy(cp, (caddr_t) tl, left);
-                       siz -= left;
-                       cp += left;
-                       m2->m_len += left;
-                       left = 0;
-               }
-       }
-       /* Loop around adding mbufs */
-       while (siz > 0) {
-               int msize;
-
-               m1 = m_getl(siz, MB_WAIT, MT_DATA, 0, &msize);
-               m1->m_len = msize;
-               m2->m_next = m1;
-               m2 = m1;
-               tl = mtod(m1, u_int32_t *);
-               tlen = 0;
-               if (putsize) {
-                       *tl++ = txdr_unsigned(siz);
-                       m1->m_len -= NFSX_UNSIGNED;
-                       tlen = NFSX_UNSIGNED;
-                       putsize = 0;
-               }
-               if (siz < m1->m_len) {
-                       len = nfsm_rndup(siz);
-                       xfer = siz;
-                       if (xfer < len)
-                               *(tl+(xfer>>2)) = 0;
-               } else {
-                       xfer = len = m1->m_len;
-               }
-               bcopy(cp, (caddr_t) tl, xfer);
-               m1->m_len = len+tlen;
-               siz -= xfer;
-               cp += xfer;
-       }
-       *mb = m1;
-       *bpos = mtod(m1, caddr_t)+m1->m_len;
-       return (0);
-}
-
-/*
  * Called once to initialize data structures...
  */
 int
@@ -1628,164 +1160,6 @@ out:
 }
 
 /*
- * A fiddled version of m_adj() that ensures null fill to a long
- * boundary and only trims off the back end
- */
-void
-nfsm_adj(struct mbuf *mp, int len, int nul)
-{
-       struct mbuf *m;
-       int count, i;
-       char *cp;
-
-       /*
-        * Trim from tail.  Scan the mbuf chain,
-        * calculating its length and finding the last mbuf.
-        * If the adjustment only affects this mbuf, then just
-        * adjust and return.  Otherwise, rescan and truncate
-        * after the remaining size.
-        */
-       count = 0;
-       m = mp;
-       for (;;) {
-               count += m->m_len;
-               if (m->m_next == NULL)
-                       break;
-               m = m->m_next;
-       }
-       if (m->m_len > len) {
-               m->m_len -= len;
-               if (nul > 0) {
-                       cp = mtod(m, caddr_t)+m->m_len-nul;
-                       for (i = 0; i < nul; i++)
-                               *cp++ = '\0';
-               }
-               return;
-       }
-       count -= len;
-       if (count < 0)
-               count = 0;
-       /*
-        * Correct length for chain is "count".
-        * Find the mbuf with last data, adjust its length,
-        * and toss data from remaining mbufs on chain.
-        */
-       for (m = mp; m; m = m->m_next) {
-               if (m->m_len >= count) {
-                       m->m_len = count;
-                       if (nul > 0) {
-                               cp = mtod(m, caddr_t)+m->m_len-nul;
-                               for (i = 0; i < nul; i++)
-                                       *cp++ = '\0';
-                       }
-                       break;
-               }
-               count -= m->m_len;
-       }
-       for (m = m->m_next;m;m = m->m_next)
-               m->m_len = 0;
-}
-
-/*
- * Make these functions instead of macros, so that the kernel text size
- * 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)
-{
-       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 = nfs_false;
-       } else {
-               nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
-               *tl++ = nfs_true;
-               txdr_hyper(before_vap->va_size, tl);
-               tl += 2;
-               txdr_nfsv3time(&(before_vap->va_mtime), tl);
-               tl += 2;
-               txdr_nfsv3time(&(before_vap->va_ctime), tl);
-       }
-       *bposp = bpos;
-       *mbp = mb;
-       nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
-}
-
-void
-nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
-                  struct vattr *after_vap, struct mbuf **mbp, char **bposp)
-{
-       struct mbuf *mb = *mbp, *mb2;
-       char *bpos = *bposp;
-       u_int32_t *tl;
-       struct nfs_fattr *fp;
-
-       if (after_ret) {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
-               *tl = nfs_false;
-       } else {
-               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
-               *tl++ = nfs_true;
-               fp = (struct nfs_fattr *)tl;
-               nfsm_srvfattr(nfsd, after_vap, fp);
-       }
-       *mbp = mb;
-       *bposp = bpos;
-}
-
-void
-nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
-             struct nfs_fattr *fp)
-{
-       /*
-        * NFS seems to truncate nlink to 16 bits, don't let it overflow.
-        */
-       if (vap->va_nlink > 65535)
-               fp->fa_nlink = 65535;
-       else
-               fp->fa_nlink = txdr_unsigned(vap->va_nlink);
-       fp->fa_uid = txdr_unsigned(vap->va_uid);
-       fp->fa_gid = txdr_unsigned(vap->va_gid);
-       if (nfsd->nd_flag & ND_NFSV3) {
-               fp->fa_type = vtonfsv3_type(vap->va_type);
-               fp->fa_mode = vtonfsv3_mode(vap->va_mode);
-               txdr_hyper(vap->va_size, &fp->fa3_size);
-               txdr_hyper(vap->va_bytes, &fp->fa3_used);
-               fp->fa3_rdev.specdata1 = txdr_unsigned(vap->va_rmajor);
-               fp->fa3_rdev.specdata2 = txdr_unsigned(vap->va_rminor);
-               fp->fa3_fsid.nfsuquad[0] = 0;
-               fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
-               txdr_hyper(vap->va_fileid, &fp->fa3_fileid);
-               txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
-               txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
-               txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
-       } else {
-               fp->fa_type = vtonfsv2_type(vap->va_type);
-               fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
-               fp->fa2_size = txdr_unsigned(vap->va_size);
-               fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
-               if (vap->va_type == VFIFO)
-                       fp->fa2_rdev = 0xffffffff;
-               else
-                       fp->fa2_rdev = txdr_unsigned(makeudev(vap->va_rmajor, vap->va_rminor));
-               fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
-               fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
-               fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
-               txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
-               txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
-               txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
-       }
-}
-
-/*
  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
  *     - look up fsid in mount list (if not found ret error)
  *     - get vp and export rights by calling VFS_FHTOVP()
@@ -1864,7 +1238,6 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag,
        return (0);
 }
 
-
 /*
  * WebNFS: check if a filehandle is a public filehandle. For v3, this
  * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
index 9a43465..82a54e6 100644 (file)
 
 static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure");
 
-/* Global defs. */
-extern int32_t (*nfsrv3_procs[NFS_NPROCS]) (struct nfsrv_descript *nd,
-                                           struct nfssvc_sock *slp,
-                                           struct thread *td,
-                                           struct mbuf **mreqp);
-extern int nfs_numasync;
-extern int nfsrtton;
-extern struct nfsstats nfsstats;
-extern int nfsrvw_procrastinate;
-extern int nfsrvw_procrastinate_v3;
 static int nuidhash_max = NFS_MAXUIDHASH;
 
 #ifndef NFS_NOSERVER
index ff62255..dbb4e68 100644 (file)
@@ -79,7 +79,6 @@
 extern int     nfs_mountroot(struct mount *mp);
 extern void    bootpc_init(void);
 
-extern int     nfs_ticks;
 extern struct vop_ops nfsv2_vnode_vops;
 extern struct vop_ops nfsv2_fifo_vops;
 extern struct vop_ops nfsv2_spec_vops;
@@ -1128,8 +1127,6 @@ nfs_root(struct mount *mp, struct vnode **vpp)
        return (error);
 }
 
-extern int syncprt;
-
 struct scaninfo {
        int rescan;
        int waitfor;
index 79eae8b..b12425b 100644 (file)
@@ -213,14 +213,6 @@ static int nfs_renameit (struct vnode *sdvp,
                                  struct componentname *scnp,
                                  struct sillyrename *sp);
 
-/*
- * Global variables
- */
-extern u_int32_t nfs_true, nfs_false;
-extern u_int32_t nfs_xdrneg1;
-extern struct nfsstats nfsstats;
-extern nfstype nfsv3_type[9];
-
 SYSCTL_DECL(_vfs_nfs);
 
 static int nfs_flush_on_rename = 1;
diff --git a/sys/vfs/nfs/nfsm_subs.c b/sys/vfs/nfs/nfsm_subs.c
new file mode 100644 (file)
index 0000000..7e803c3
--- /dev/null
@@ -0,0 +1,728 @@
+/*
+ * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * These functions support the macros and help fiddle mbuf chains for
+ * the nfs op functions. They do things like create the rpc header and
+ * copy data between mbuf chains and uio lists.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/nlookup.h>
+#include <sys/namei.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/malloc.h>
+#include <sys/sysent.h>
+#include <sys/syscall.h>
+#include <sys/conf.h>
+#include <sys/objcache.h>
+
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_zone.h>
+
+#include <sys/buf2.h>
+
+#include "rpcv2.h"
+#include "nfsproto.h"
+#include "nfs.h"
+#include "nfsmount.h"
+#include "nfsnode.h"
+#include "xdr_subs.h"
+#include "nfsm_subs.h"
+#include "nfsrtt.h"
+
+#include <netinet/in.h>
+
+static u_int32_t nfs_xid = 0;
+
+/*
+ * Create the header for an rpc request packet
+ * 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)
+{
+       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);
+}
+
+/*
+ * Build the RPC header and fill in the authorization info.
+ * The authorization string argument is only used when the credentials
+ * come from outside of the kernel.
+ * Returns the head of the mbuf list.
+ */
+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)
+{
+       struct mbuf *mb;
+       u_int32_t *tl;
+       caddr_t bpos;
+       int i;
+       struct mbuf *mreq, *mb2;
+       int siz, grpsiz, authsiz, dsiz;
+
+       authsiz = nfsm_rndup(auth_len);
+       dsiz = authsiz + 10 * NFSX_UNSIGNED;
+       mb = m_getl(dsiz, MB_WAIT, MT_DATA, M_PKTHDR, NULL);
+       if (dsiz < MINCLSIZE) {
+               if (dsiz < MHLEN)
+                       MH_ALIGN(mb, dsiz);
+               else
+                       MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
+       }
+       mb->m_len = mb->m_pkthdr.len = 0;
+       mreq = mb;
+       bpos = mtod(mb, caddr_t);
+
+       /*
+        * First the RPC header.
+        */
+       nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
+
+       /* Get a pretty random xid to start with */
+       if (!nfs_xid)
+               nfs_xid = krandom();
+       /*
+        * Skip zero xid if it should ever happen.
+        */
+       if (++nfs_xid == 0)
+               nfs_xid++;
+
+       *tl++ = *xidp = txdr_unsigned(nfs_xid);
+       *tl++ = rpc_call;
+       *tl++ = rpc_vers;
+       *tl++ = txdr_unsigned(NFS_PROG);
+       if (nmflag & NFSMNT_NFSV3)
+               *tl++ = txdr_unsigned(NFS_VER3);
+       else
+               *tl++ = txdr_unsigned(NFS_VER2);
+       if (nmflag & NFSMNT_NFSV3)
+               *tl++ = txdr_unsigned(procid);
+       else
+               *tl++ = txdr_unsigned(nfsv2_procid[procid]);
+
+       /*
+        * And then the authorization cred.
+        */
+       *tl++ = txdr_unsigned(auth_type);
+       *tl = txdr_unsigned(authsiz);
+       switch (auth_type) {
+       case RPCAUTH_UNIX:
+               nfsm_build(tl, u_int32_t *, auth_len);
+               *tl++ = 0;              /* stamp ?? */
+               *tl++ = 0;              /* NULL hostname */
+               *tl++ = txdr_unsigned(cr->cr_uid);
+               *tl++ = txdr_unsigned(cr->cr_groups[0]);
+               grpsiz = (auth_len >> 2) - 5;
+               *tl++ = txdr_unsigned(grpsiz);
+               for (i = 1; i <= grpsiz; i++)
+                       *tl++ = txdr_unsigned(cr->cr_groups[i]);
+               break;
+       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);
+                       }
+                       i = min(siz, M_TRAILINGSPACE(mb));
+                       bcopy(auth_str, bpos, i);
+                       mb->m_len += i;
+                       auth_str += i;
+                       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;
+               }
+               break;
+       };
+
+       /*
+        * And the verifier...
+        */
+       nfsm_build(tl, u_int32_t *, 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);
+                       }
+                       i = min(siz, M_TRAILINGSPACE(mb));
+                       bcopy(verf_str, bpos, i);
+                       mb->m_len += i;
+                       verf_str += i;
+                       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;
+               }
+       } 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);
+}
+
+/*
+ * copies mbuf chain to the uio scatter/gather list
+ */
+int
+nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
+{
+       char *mbufcp, *uiocp;
+       int xfer, left, len;
+       struct mbuf *mp;
+       long uiosiz, rem;
+       int error = 0;
+
+       mp = *mrep;
+       mbufcp = *dpos;
+       len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
+       rem = nfsm_rndup(siz)-siz;
+       while (siz > 0) {
+               if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
+                       return (EFBIG);
+               left = uiop->uio_iov->iov_len;
+               uiocp = uiop->uio_iov->iov_base;
+               if (left > siz)
+                       left = siz;
+               uiosiz = left;
+               while (left > 0) {
+                       while (len == 0) {
+                               mp = mp->m_next;
+                               if (mp == NULL)
+                                       return (EBADRPC);
+                               mbufcp = mtod(mp, caddr_t);
+                               len = mp->m_len;
+                       }
+                       xfer = (left > len) ? len : left;
+#ifdef notdef
+                       /* Not Yet.. */
+                       if (uiop->uio_iov->iov_op != NULL)
+                               (*(uiop->uio_iov->iov_op))
+                               (mbufcp, uiocp, xfer);
+                       else
+#endif
+                       if (uiop->uio_segflg == UIO_SYSSPACE)
+                               bcopy(mbufcp, uiocp, xfer);
+                       else
+                               copyout(mbufcp, uiocp, xfer);
+                       left -= xfer;
+                       len -= xfer;
+                       mbufcp += xfer;
+                       uiocp += xfer;
+                       uiop->uio_offset += xfer;
+                       uiop->uio_resid -= xfer;
+               }
+               if (uiop->uio_iov->iov_len <= siz) {
+                       uiop->uio_iovcnt--;
+                       uiop->uio_iov++;
+               } else {
+                       uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + uiosiz;
+                       uiop->uio_iov->iov_len -= uiosiz;
+               }
+               siz -= uiosiz;
+       }
+       *dpos = mbufcp;
+       *mrep = mp;
+       if (rem > 0) {
+               if (len < rem)
+                       error = nfs_adv(mrep, dpos, rem, len);
+               else
+                       *dpos += rem;
+       }
+       return (error);
+}
+
+/*
+ * copies a uio scatter/gather list to an mbuf chain.
+ * NOTE: can ony handle iovcnt == 1
+ */
+int
+nfsm_uiotombuf(struct uio *uiop, struct mbuf **mq, int siz, caddr_t *bpos)
+{
+       char *uiocp;
+       struct mbuf *mp, *mp2;
+       int xfer, left, mlen;
+       int uiosiz, rem;
+       boolean_t getcluster;
+       char *cp;
+
+#ifdef DIAGNOSTIC
+       if (uiop->uio_iovcnt != 1)
+               panic("nfsm_uiotombuf: iovcnt != 1");
+#endif
+
+       if (siz >= MINCLSIZE)
+               getcluster = TRUE;
+       else
+               getcluster = FALSE;
+       rem = nfsm_rndup(siz) - siz;
+       mp = mp2 = *mq;
+       while (siz > 0) {
+               left = uiop->uio_iov->iov_len;
+               uiocp = uiop->uio_iov->iov_base;
+               if (left > siz)
+                       left = siz;
+               uiosiz = left;
+               while (left > 0) {
+                       mlen = M_TRAILINGSPACE(mp);
+                       if (mlen == 0) {
+                               if (getcluster)
+                                       mp = m_getcl(MB_WAIT, MT_DATA, 0);
+                               else
+                                       mp = m_get(MB_WAIT, MT_DATA);
+                               mp->m_len = 0;
+                               mp2->m_next = mp;
+                               mp2 = mp;
+                               mlen = M_TRAILINGSPACE(mp);
+                       }
+                       xfer = (left > mlen) ? mlen : left;
+#ifdef notdef
+                       /* Not Yet.. */
+                       if (uiop->uio_iov->iov_op != NULL)
+                               (*(uiop->uio_iov->iov_op))
+                               (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
+                       else
+#endif
+                       if (uiop->uio_segflg == UIO_SYSSPACE)
+                               bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
+                       else
+                               copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
+                       mp->m_len += xfer;
+                       left -= xfer;
+                       uiocp += xfer;
+                       uiop->uio_offset += xfer;
+                       uiop->uio_resid -= xfer;
+               }
+               uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + uiosiz;
+               uiop->uio_iov->iov_len -= uiosiz;
+               siz -= uiosiz;
+       }
+       if (rem > 0) {
+               if (rem > M_TRAILINGSPACE(mp)) {
+                       MGET(mp, MB_WAIT, MT_DATA);
+                       mp->m_len = 0;
+                       mp2->m_next = mp;
+               }
+               cp = mtod(mp, caddr_t)+mp->m_len;
+               for (left = 0; left < rem; left++)
+                       *cp++ = '\0';
+               mp->m_len += rem;
+               *bpos = cp;
+       } else
+               *bpos = mtod(mp, caddr_t)+mp->m_len;
+       *mq = mp;
+       return (0);
+}
+
+/*
+ * Help break down an mbuf chain by setting the first siz bytes contiguous
+ * pointed to by returned val.
+ * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
+ * cases. (The macros use the vars. dpos and dpos2)
+ */
+int
+nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
+{
+       struct mbuf *mp, *mp2;
+       int siz2, xfer;
+       caddr_t p;
+
+       mp = *mdp;
+       while (left == 0) {
+               *mdp = mp = mp->m_next;
+               if (mp == NULL)
+                       return (EBADRPC);
+               left = mp->m_len;
+               *dposp = mtod(mp, caddr_t);
+       }
+       if (left >= siz) {
+               *cp2 = *dposp;
+               *dposp += siz;
+       } else if (mp->m_next == NULL) {
+               return (EBADRPC);
+       } else if (siz > MHLEN) {
+               panic("nfs S too big");
+       } else {
+               MGET(mp2, MB_WAIT, MT_DATA);
+               mp2->m_next = mp->m_next;
+               mp->m_next = mp2;
+               mp->m_len -= left;
+               mp = mp2;
+               *cp2 = p = mtod(mp, caddr_t);
+               bcopy(*dposp, p, left);         /* Copy what was left */
+               siz2 = siz-left;
+               p += left;
+               mp2 = mp->m_next;
+               /* Loop around copying up the siz2 bytes */
+               while (siz2 > 0) {
+                       if (mp2 == NULL)
+                               return (EBADRPC);
+                       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;
+                               p += xfer;
+                               siz2 -= xfer;
+                       }
+                       if (siz2 > 0)
+                               mp2 = mp2->m_next;
+               }
+               mp->m_len = siz;
+               *mdp = mp2;
+               *dposp = mtod(mp2, caddr_t);
+       }
+       return (0);
+}
+
+/*
+ * Advance the position in the mbuf chain.
+ */
+int
+nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
+{
+       struct mbuf *m;
+       int s;
+
+       m = *mdp;
+       s = left;
+       while (s < offs) {
+               offs -= s;
+               m = m->m_next;
+               if (m == NULL)
+                       return (EBADRPC);
+               s = m->m_len;
+       }
+       *mdp = m;
+       *dposp = mtod(m, caddr_t)+offs;
+       return (0);
+}
+
+/*
+ * Copy a string into mbufs for the hard cases...
+ */
+int
+nfsm_strtmbuf(struct mbuf **mb, char **bpos, const char *cp, long siz)
+{
+       struct mbuf *m1 = NULL, *m2;
+       long left, xfer, len, tlen;
+       u_int32_t *tl;
+       int putsize;
+
+       putsize = 1;
+       m2 = *mb;
+       left = M_TRAILINGSPACE(m2);
+       if (left > 0) {
+               tl = ((u_int32_t *)(*bpos));
+               *tl++ = txdr_unsigned(siz);
+               putsize = 0;
+               left -= NFSX_UNSIGNED;
+               m2->m_len += NFSX_UNSIGNED;
+               if (left > 0) {
+                       bcopy(cp, (caddr_t) tl, left);
+                       siz -= left;
+                       cp += left;
+                       m2->m_len += left;
+                       left = 0;
+               }
+       }
+       /* Loop around adding mbufs */
+       while (siz > 0) {
+               int msize;
+
+               m1 = m_getl(siz, MB_WAIT, MT_DATA, 0, &msize);
+               m1->m_len = msize;
+               m2->m_next = m1;
+               m2 = m1;
+               tl = mtod(m1, u_int32_t *);
+               tlen = 0;
+               if (putsize) {
+                       *tl++ = txdr_unsigned(siz);
+                       m1->m_len -= NFSX_UNSIGNED;
+                       tlen = NFSX_UNSIGNED;
+                       putsize = 0;
+               }
+               if (siz < m1->m_len) {
+                       len = nfsm_rndup(siz);
+                       xfer = siz;
+                       if (xfer < len)
+                               *(tl+(xfer>>2)) = 0;
+               } else {
+                       xfer = len = m1->m_len;
+               }
+               bcopy(cp, (caddr_t) tl, xfer);
+               m1->m_len = len+tlen;
+               siz -= xfer;
+               cp += xfer;
+       }
+       *mb = m1;
+       *bpos = mtod(m1, caddr_t)+m1->m_len;
+       return (0);
+}
+
+/*
+ * A fiddled version of m_adj() that ensures null fill to a long
+ * boundary and only trims off the back end
+ */
+void
+nfsm_adj(struct mbuf *mp, int len, int nul)
+{
+       struct mbuf *m;
+       int count, i;
+       char *cp;
+
+       /*
+        * Trim from tail.  Scan the mbuf chain,
+        * calculating its length and finding the last mbuf.
+        * If the adjustment only affects this mbuf, then just
+        * adjust and return.  Otherwise, rescan and truncate
+        * after the remaining size.
+        */
+       count = 0;
+       m = mp;
+       for (;;) {
+               count += m->m_len;
+               if (m->m_next == NULL)
+                       break;
+               m = m->m_next;
+       }
+       if (m->m_len > len) {
+               m->m_len -= len;
+               if (nul > 0) {
+                       cp = mtod(m, caddr_t)+m->m_len-nul;
+                       for (i = 0; i < nul; i++)
+                               *cp++ = '\0';
+               }
+               return;
+       }
+       count -= len;
+       if (count < 0)
+               count = 0;
+       /*
+        * Correct length for chain is "count".
+        * Find the mbuf with last data, adjust its length,
+        * and toss data from remaining mbufs on chain.
+        */
+       for (m = mp; m; m = m->m_next) {
+               if (m->m_len >= count) {
+                       m->m_len = count;
+                       if (nul > 0) {
+                               cp = mtod(m, caddr_t)+m->m_len-nul;
+                               for (i = 0; i < nul; i++)
+                                       *cp++ = '\0';
+                       }
+                       break;
+               }
+               count -= m->m_len;
+       }
+       for (m = m->m_next;m;m = m->m_next)
+               m->m_len = 0;
+}
+
+/*
+ * Make these functions instead of macros, so that the kernel text size
+ * 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)
+{
+       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 = nfs_false;
+       } else {
+               nfsm_build(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
+               *tl++ = nfs_true;
+               txdr_hyper(before_vap->va_size, tl);
+               tl += 2;
+               txdr_nfsv3time(&(before_vap->va_mtime), tl);
+               tl += 2;
+               txdr_nfsv3time(&(before_vap->va_ctime), tl);
+       }
+       *bposp = bpos;
+       *mbp = mb;
+       nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
+}
+
+void
+nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
+                  struct vattr *after_vap, struct mbuf **mbp, char **bposp)
+{
+       struct mbuf *mb = *mbp, *mb2;
+       char *bpos = *bposp;
+       u_int32_t *tl;
+       struct nfs_fattr *fp;
+
+       if (after_ret) {
+               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
+               *tl = nfs_false;
+       } else {
+               nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
+               *tl++ = nfs_true;
+               fp = (struct nfs_fattr *)tl;
+               nfsm_srvfattr(nfsd, after_vap, fp);
+       }
+       *mbp = mb;
+       *bposp = bpos;
+}
+
+void
+nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
+             struct nfs_fattr *fp)
+{
+       /*
+        * NFS seems to truncate nlink to 16 bits, don't let it overflow.
+        */
+       if (vap->va_nlink > 65535)
+               fp->fa_nlink = 65535;
+       else
+               fp->fa_nlink = txdr_unsigned(vap->va_nlink);
+       fp->fa_uid = txdr_unsigned(vap->va_uid);
+       fp->fa_gid = txdr_unsigned(vap->va_gid);
+       if (nfsd->nd_flag & ND_NFSV3) {
+               fp->fa_type = vtonfsv3_type(vap->va_type);
+               fp->fa_mode = vtonfsv3_mode(vap->va_mode);
+               txdr_hyper(vap->va_size, &fp->fa3_size);
+               txdr_hyper(vap->va_bytes, &fp->fa3_used);
+               fp->fa3_rdev.specdata1 = txdr_unsigned(vap->va_rmajor);
+               fp->fa3_rdev.specdata2 = txdr_unsigned(vap->va_rminor);
+               fp->fa3_fsid.nfsuquad[0] = 0;
+               fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
+               txdr_hyper(vap->va_fileid, &fp->fa3_fileid);
+               txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
+               txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
+               txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
+       } else {
+               fp->fa_type = vtonfsv2_type(vap->va_type);
+               fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
+               fp->fa2_size = txdr_unsigned(vap->va_size);
+               fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
+               if (vap->va_type == VFIFO)
+                       fp->fa2_rdev = 0xffffffff;
+               else
+                       fp->fa2_rdev = txdr_unsigned(makeudev(vap->va_rmajor, vap->va_rminor));
+               fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
+               fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
+               fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
+               txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
+               txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
+               txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
+       }
+}