From e97453f3e38fa7883847b71c7a911843b2ea1113 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 16 Jul 2009 08:19:14 -0700 Subject: [PATCH] NFS - create nfsm_subs.c, clean up externs * Move nfsm_*() procedures from nfs_subs.c to nfsm_subs.c * Clean up externs improperly embedded in .c files. --- sys/conf/files | 1 + sys/vfs/nfs/Makefile | 9 +- sys/vfs/nfs/bootp_subr.c | 1 - sys/vfs/nfs/nfs.h | 26 +- sys/vfs/nfs/nfs_bio.c | 3 - sys/vfs/nfs/nfs_mountrpc.c | 2 - sys/vfs/nfs/nfs_node.c | 2 + sys/vfs/nfs/nfs_serv.c | 5 - sys/vfs/nfs/nfs_socket.c | 10 - sys/vfs/nfs/nfs_srvcache.c | 2 - sys/vfs/nfs/nfs_subs.c | 637 +------------------------------- sys/vfs/nfs/nfs_syscalls.c | 10 - sys/vfs/nfs/nfs_vfsops.c | 3 - sys/vfs/nfs/nfs_vnops.c | 8 - sys/vfs/nfs/nfsm_subs.c | 728 +++++++++++++++++++++++++++++++++++++ 15 files changed, 766 insertions(+), 681 deletions(-) create mode 100644 sys/vfs/nfs/nfsm_subs.c diff --git a/sys/conf/files b/sys/conf/files index 022fa58426..afaaf3fcd4 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 diff --git a/sys/vfs/nfs/Makefile b/sys/vfs/nfs/Makefile index 67df6283cc..f3e8e4921c 100644 --- a/sys/vfs/nfs/Makefile +++ b/sys/vfs/nfs/Makefile @@ -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} diff --git a/sys/vfs/nfs/bootp_subr.c b/sys/vfs/nfs/bootp_subr.c index 8e50a48dbb..2e1b9c7c04 100644 --- a/sys/vfs/nfs/bootp_subr.c +++ b/sys/vfs/nfs/bootp_subr.c @@ -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"); diff --git a/sys/vfs/nfs/nfs.h b/sys/vfs/nfs/nfs.h index 4c38f4232c..bf80f832d6 100644 --- a/sys/vfs/nfs/nfs.h +++ b/sys/vfs/nfs/nfs.h @@ -45,6 +45,7 @@ #include "opt_nfs.h" #endif +#include #include /* @@ -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); diff --git a/sys/vfs/nfs/nfs_bio.c b/sys/vfs/nfs/nfs_bio.c index 1b572d131c..a10aa70536 100644 --- a/sys/vfs/nfs/nfs_bio.c +++ b/sys/vfs/nfs/nfs_bio.c @@ -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. * diff --git a/sys/vfs/nfs/nfs_mountrpc.c b/sys/vfs/nfs/nfs_mountrpc.c index 668bacadd2..233cbc93e9 100644 --- a/sys/vfs/nfs/nfs_mountrpc.c +++ b/sys/vfs/nfs/nfs_mountrpc.c @@ -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); diff --git a/sys/vfs/nfs/nfs_node.c b/sys/vfs/nfs/nfs_node.c index 63f676ded7..78952a31d6 100644 --- a/sys/vfs/nfs/nfs_node.c +++ b/sys/vfs/nfs/nfs_node.c @@ -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. diff --git a/sys/vfs/nfs/nfs_serv.c b/sys/vfs/nfs/nfs_serv.c index 2aba4d5d16..220db22c64 100644 --- a/sys/vfs/nfs/nfs_serv.c +++ b/sys/vfs/nfs/nfs_serv.c @@ -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; diff --git a/sys/vfs/nfs/nfs_socket.c b/sys/vfs/nfs/nfs_socket.c index 03a28890f2..1bbfefad7d 100644 --- a/sys/vfs/nfs/nfs_socket.c +++ b/sys/vfs/nfs/nfs_socket.c @@ -101,16 +101,6 @@ ((((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. diff --git a/sys/vfs/nfs/nfs_srvcache.c b/sys/vfs/nfs/nfs_srvcache.c index a0c55588af..00cd75bc3d 100644 --- a/sys/vfs/nfs/nfs_srvcache.c +++ b/sys/vfs/nfs/nfs_srvcache.c @@ -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; diff --git a/sys/vfs/nfs/nfs_subs.c b/sys/vfs/nfs/nfs_subs.c index 0931c9fdf5..4051d75de3 100644 --- a/sys/vfs/nfs/nfs_subs.c +++ b/sys/vfs/nfs/nfs_subs.c @@ -84,13 +84,12 @@ * 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 @@ -567,465 +558,6 @@ nfs_curusec(void) return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec); } -/* - * 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... */ @@ -1627,164 +1159,6 @@ out: return (error); } -/* - * 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) @@ -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 diff --git a/sys/vfs/nfs/nfs_syscalls.c b/sys/vfs/nfs/nfs_syscalls.c index 9a43465d9a..82a54e6385 100644 --- a/sys/vfs/nfs/nfs_syscalls.c +++ b/sys/vfs/nfs/nfs_syscalls.c @@ -79,16 +79,6 @@ 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 diff --git a/sys/vfs/nfs/nfs_vfsops.c b/sys/vfs/nfs/nfs_vfsops.c index ff622556c1..dbb4e68cda 100644 --- a/sys/vfs/nfs/nfs_vfsops.c +++ b/sys/vfs/nfs/nfs_vfsops.c @@ -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; diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index 79eae8b292..b12425b8f1 100644 --- a/sys/vfs/nfs/nfs_vnops.c +++ b/sys/vfs/nfs/nfs_vnops.c @@ -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 index 0000000000..7e803c3f2b --- /dev/null +++ b/sys/vfs/nfs/nfsm_subs.c @@ -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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 + +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); + } +} -- 2.41.0