diff options
Diffstat (limited to 'sys/nfsserver')
-rw-r--r-- | sys/nfsserver/nfs.h | 11 | ||||
-rw-r--r-- | sys/nfsserver/nfs_serv.c | 432 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvcache.c | 26 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsock.c | 52 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsubs.c | 133 | ||||
-rw-r--r-- | sys/nfsserver/nfs_syscalls.c | 65 | ||||
-rw-r--r-- | sys/nfsserver/nfsm_subs.h | 7 |
7 files changed, 642 insertions, 84 deletions
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h index 5295b69..3f83115 100644 --- a/sys/nfsserver/nfs.h +++ b/sys/nfsserver/nfs.h @@ -116,6 +116,13 @@ struct nfsd_args { #ifdef _KERNEL +extern struct mtx nfsd_mtx; +#define NFSD_LOCK_ASSERT() mtx_assert(&nfsd_mtx, MA_OWNED) +#define NFSD_UNLOCK_ASSERT() mtx_assert(&nfsd_mtx, MA_NOTOWNED) +#define NFSD_LOCK_DONTCARE() +#define NFSD_LOCK() mtx_lock(&nfsd_mtx) +#define NFSD_UNLOCK() mtx_unlock(&nfsd_mtx) + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_NFSRVDESC); MALLOC_DECLARE(M_NFSD); @@ -145,8 +152,8 @@ extern u_int32_t nfsrv_rpc_auth_unix, nfsrv_rpc_msgaccepted, nfsrv_rpc_call, nfsrv_rpc_autherr; /* Procedure table data */ -extern int nfsrvv2_procid[NFS_NPROCS]; -extern int nfsrv_nfsv3_procid[NFS_NPROCS]; +extern const int nfsrvv2_procid[NFS_NPROCS]; +extern const int nfsrv_nfsv3_procid[NFS_NPROCS]; extern int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd, struct nfssvc_sock *slp, struct thread *td, struct mbuf **mreqp); diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index 258da54..ea06231 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/nfs_serv.c @@ -179,6 +179,8 @@ nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, u_long testmode, nfsmode; int v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) panic("nfsrv3_access: v3 proc called on a v2 connection"); @@ -211,9 +213,13 @@ nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, if ((nfsmode & testmode) && nfsrv_access(vp, VEXEC, cred, rdonly, td, 0)) nfsmode &= ~testmode; + NFSD_UNLOCK(); + mtx_lock(&Giant); getret = VOP_GETATTR(vp, vap, cred, td); vput(vp); + mtx_unlock(&Giant); vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED); nfsm_srvpostop_attr(getret, vap); tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED); @@ -245,6 +251,8 @@ nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, int error = 0, rdonly; struct mbuf *mb, *mreq; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); @@ -254,9 +262,13 @@ nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); error = VOP_GETATTR(vp, vap, cred, td); vput(vp); + mtx_unlock(&Giant); vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); if (error) { error = 0; @@ -299,6 +311,8 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct timespec guard; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); @@ -306,7 +320,11 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto out; } + NFSD_UNLOCK(); + mtx_lock(&Giant); (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); + NFSD_LOCK(); VATTR_NULL(vap); if (v3) { nfsm_srvsattr(vap); @@ -363,20 +381,26 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * vp now an active resource, pay careful attention to cleanup */ if (v3) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = preat_ret = VOP_GETATTR(vp, &preat, cred, td); if (!error && gcheck && (preat.va_ctime.tv_sec != guard.tv_sec || preat.va_ctime.tv_nsec != guard.tv_nsec)) error = NFSERR_NOT_SYNC; if (error) { + mtx_unlock(&Giant); /* VFS */ vput(vp); vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_WCCDATA(v3)); if (v3) nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); error = 0; goto nfsmout; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); } /* @@ -396,13 +420,23 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, td, 0)) != 0) goto out; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = VOP_SETATTR(vp, vap, cred, td); postat_ret = VOP_GETATTR(vp, vap, cred, td); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); if (!error) error = postat_ret; out: - if (vp != NULL) + if (vp != NULL) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } + vp = NULL; nfsm_reply(NFSX_WCCORFATTR(v3)); if (v3) { @@ -416,9 +450,13 @@ out: /* fall through */ nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); if (vp) vput(vp); vn_finished_write(mp); + mtx_unlock(&Giant); + NFSD_LOCK(); return(error); } @@ -444,6 +482,8 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mbuf *mb, *mreq; struct vattr va, dirattr, *vap = &va; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); @@ -464,11 +504,15 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * structure in case macros jump to nfsmout. */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (error) { if (dirp) { vrele(dirp); dirp = NULL; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3)); if (v3) nfsm_srvpostop_attr(dirattr_ret, &dirattr); @@ -549,6 +593,8 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, */ if (error) { + mtx_unlock(&Giant); + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3)); if (v3) nfsm_srvpostop_attr(dirattr_ret, &dirattr); @@ -577,7 +623,9 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = VOP_GETATTR(vp, vap, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ ndp->ni_vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3)); if (error) { if (v3) @@ -595,6 +643,8 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, } nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (dirp) vrele(dirp); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -602,6 +652,8 @@ nfsmout: vrele(ndp->ni_startdir); if (ndp->ni_vp) vput(ndp->ni_vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -630,6 +682,8 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, fhandle_t *fhp; struct uio io, *uiop = &io; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); #ifndef nolint mp = NULL; @@ -639,6 +693,7 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nfsm_srvmtofh(fhp); len = 0; i = 0; + NFSD_UNLOCK(); while (len < NFS_MAXPATHLEN) { MGET(nmp, M_TRYWAIT, MT_DATA); MCLGET(nmp, M_TRYWAIT); @@ -666,6 +721,7 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; uiop->uio_td = NULL; + NFSD_LOCK(); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { nfsm_reply(2 * NFSX_UNSIGNED); @@ -674,18 +730,20 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (vp->v_type != VLNK) { if (v3) error = EINVAL; else error = ENXIO; - goto out; - } - error = VOP_READLINK(vp, uiop, cred); -out: + } else + error = VOP_READLINK(vp, uiop, cred); getret = VOP_GETATTR(vp, &attr, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED); if (v3) nfsm_srvpostop_attr(getret, &attr); @@ -705,8 +763,13 @@ out: nfsmout: if (mp3) m_freem(mp3); - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } return(error); } @@ -741,6 +804,8 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, off_t off; int ioflag = 0; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); @@ -779,18 +844,24 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0) error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1); } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ getret = VOP_GETATTR(vp, vap, cred, td); if (!error) error = getret; if (error) { vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3)); if (v3) nfsm_srvpostop_attr(getret, vap); error = 0; goto nfsmout; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); /* * Calculate byte count to read @@ -870,6 +941,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, tl += (NFSX_V2FATTR / sizeof (u_int32_t)); } len = left = nfsm_rndup(cnt); + NFSD_UNLOCK(); if (cnt > 0) { /* * Generate the mbuf list with the uio_iov ref. to it. @@ -915,6 +987,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, uiop->uio_resid = len; uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; + mtx_lock(&Giant); /* VFS */ error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); off = uiop->uio_offset; nh->nh_nextr = off; @@ -924,6 +997,8 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = getret; m_freem(mreq); vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_POSTOPATTR(v3)); if (v3) @@ -933,9 +1008,13 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, } } else { uiop->uio_resid = 0; + mtx_lock(&Giant); /* VFS */ } + mtx_assert(&Giant, MA_OWNED); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_srvfillattr(vap, fp); tlen = len - uiop->uio_resid; cnt = cnt < tlen ? cnt : tlen; @@ -951,8 +1030,13 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, } *tl = txdr_unsigned(cnt); nfsmout: - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } return(error); } @@ -988,6 +1072,8 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, off_t off; struct mount *mntp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (mrep == NULL) { *mrq = NULL; @@ -1000,7 +1086,11 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto ereply; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mntp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); if (v3) { tl = nfsm_dissect(u_int32_t *, 5 * NFSX_UNSIGNED); off = fxdr_hyper(tl); @@ -1063,8 +1153,13 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } - if (v3) + if (v3) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ forat_ret = VOP_GETATTR(vp, &forat, cred, td); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } if (vp->v_type != VREG) { if (v3) error = EINVAL; @@ -1074,7 +1169,11 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, if (!error) error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1); if (error) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_WCCDATA(v3)); if (v3) @@ -1083,6 +1182,7 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, goto nfsmout; } + NFSD_UNLOCK(); if (len > 0) { MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP, M_WAITOK); @@ -1116,12 +1216,18 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, uiop->uio_segflg = UIO_SYSSPACE; uiop->uio_td = NULL; uiop->uio_offset = off; + mtx_lock(&Giant); /* VFS */ error = VOP_WRITE(vp, uiop, ioflags, cred); + /* XXXRW: unlocked write. */ nfsrvstats.srvvop_writes++; FREE((caddr_t)iv, M_TEMP); - } + } else + mtx_lock(&Giant); /* VFS */ + mtx_assert(&Giant, MA_OWNED); /* VFS */ aftat_ret = VOP_GETATTR(vp, vap, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; if (!error) error = aftat_ret; @@ -1159,9 +1265,13 @@ ereply: } error = 0; nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (vp) vput(vp); vn_finished_write(mntp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return(error); } @@ -1195,6 +1305,8 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp, u_quad_t cur_usec; struct mount *mntp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); #ifndef nolint i = 0; @@ -1348,8 +1460,13 @@ loop1: error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp, nfsd->nd_nam, &rdonly, TRUE); if (!error) { - if (v3) + if (v3) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ forat_ret = VOP_GETATTR(vp, &forat, cred, td); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } if (vp->v_type != VREG) { if (v3) error = EINVAL; @@ -1361,6 +1478,7 @@ loop1: } if (!error) error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1); + NFSD_UNLOCK(); if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE) ioflags = IO_NODELOCKED; else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC) @@ -1372,6 +1490,7 @@ loop1: uiop->uio_td = NULL; uiop->uio_offset = nfsd->nd_off; uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off; + mtx_lock(&Giant); /* VFS */ if (uiop->uio_resid > 0) { mp = mrep; i = 0; @@ -1402,6 +1521,7 @@ loop1: } if (!error) { error = VOP_WRITE(vp, uiop, ioflags, cred); + /* XXXRW: unlocked write. */ nfsrvstats.srvvop_writes++; vn_finished_write(mntp); } @@ -1413,6 +1533,8 @@ loop1: vput(vp); vp = NULL; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); /* * Loop around generating replies for all write rpcs that have @@ -1507,6 +1629,8 @@ nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd) struct mbuf *mp; struct nfsrv_descript *p; + NFSD_LOCK_ASSERT(); + NFS_DPF(WG, ("C%03x-%03x", nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff)); LIST_REMOVE(nfsd, nd_hash); @@ -1573,6 +1697,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, u_char cverf[NFSX_V3CREATEVERF]; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); #ifndef nolint rdev = 0; @@ -1585,7 +1711,11 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto ereply; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; @@ -1604,7 +1734,11 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); if (dirp && !v3) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vrele(dirp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); dirp = NULL; } if (error) { @@ -1679,6 +1813,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * The only possible error we can have at this point is EEXIST. * nd.ni_vp will also be non-NULL in that case. */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (nd.ni_vp == NULL) { if (vap->va_mode == (mode_t)VNOVAL) vap->va_mode = 0; @@ -1797,6 +1933,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, } } ereply: + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { if (!error) { @@ -1813,6 +1951,8 @@ ereply: error = 0; nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (nd.ni_startdir) { vrele(nd.ni_startdir); nd.ni_startdir = NULL; @@ -1829,6 +1969,8 @@ nfsmout: if (nd.ni_vp) vput(nd.ni_vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -1858,6 +2000,8 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mount *mp = NULL; int v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) panic("nfsrv_mknod: v3 proc called on a v2 connection"); @@ -1869,7 +2013,11 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto ereply; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; @@ -1915,6 +2063,8 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, vap->va_type = vtyp; if (vap->va_mode == (mode_t)VNOVAL) vap->va_mode = 0; + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (vtyp == VSOCK) { vrele(nd.ni_startdir); nd.ni_startdir = NULL; @@ -1987,6 +2137,8 @@ out: VOP_UNLOCK(dirp, 0, td); } ereply: + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1)); if (v3) { if (!error) { @@ -1995,9 +2147,15 @@ ereply: } nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (0); nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (dirp) vrele(dirp); if (nd.ni_startdir) @@ -2012,6 +2170,8 @@ nfsmout: if (nd.ni_vp) vput(nd.ni_vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -2037,6 +2197,8 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, fhandle_t *fhp; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); @@ -2046,7 +2208,11 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto ereply; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; @@ -2054,6 +2220,8 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (dirp && !v3) { vrele(dirp); dirp = NULL; @@ -2099,6 +2267,8 @@ out: vrele(dirp); dirp = NULL; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); ereply: nfsm_reply(NFSX_WCCDATA(v3)); if (v3) { @@ -2106,6 +2276,8 @@ ereply: error = 0; } nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_dvp) { if (nd.ni_dvp == nd.ni_vp) @@ -2116,6 +2288,8 @@ nfsmout: if (nd.ni_vp) vput(nd.ni_vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return(error); } @@ -2144,6 +2318,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, uid_t saved_uid; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); #ifndef nolint fvp = NULL; @@ -2176,7 +2352,11 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md, &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE); if (fdirp && !v3) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vrele(fdirp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); fdirp = NULL; } if (error) { @@ -2197,6 +2377,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART; error = nfs_namei(&tond, tfhp, len2, slp, nam, &md, &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (tdirp && !v3) { vrele(tdirp); tdirp = NULL; @@ -2282,9 +2464,13 @@ out: /* fall through */ out1: + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(2 * NFSX_WCCDATA(v3)); if (v3) { /* Release existing locks to prevent deadlock. */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (tond.ni_dvp) { if (tond.ni_dvp == tond.ni_vp) vrele(tond.ni_dvp); @@ -2306,6 +2492,8 @@ out1: tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td); VOP_UNLOCK(tdirp, 0, td); } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); } @@ -2316,6 +2504,8 @@ nfsmout: /* * Clear out tond related fields */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (tdirp) vrele(tdirp); if (tond.ni_startdir) @@ -2344,6 +2534,8 @@ nfsmout: vrele(fromnd.ni_vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -2369,6 +2561,8 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, fhandle_t *fhp, *dfhp; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); @@ -2379,7 +2573,11 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto ereply; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvmtofh(dfhp); nfsm_srvnamesiz(len); @@ -2394,6 +2592,8 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (v3) getret = VOP_GETATTR(vp, &at, cred, td); if (vp->v_type == VDIR) { @@ -2404,8 +2604,12 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (dirp && !v3) { vrele(dirp); dirp = NULL; @@ -2459,6 +2663,8 @@ out2: VOP_UNLOCK(dirp, 0, td); } } + mtx_lock(&Giant); /* VFS */ + NFSD_LOCK(); ereply: nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { @@ -2469,6 +2675,8 @@ ereply: /* fall through */ nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ NDFREE(&nd, NDF_ONLY_PNBUF); if (dirp) vrele(dirp); @@ -2483,6 +2691,8 @@ nfsmout: if (nd.ni_vp) vrele(nd.ni_vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return(error); } @@ -2512,6 +2722,8 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, fhandle_t *fhp; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); @@ -2521,13 +2733,19 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto out; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART; error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (dirp && !v3) { vrele(dirp); dirp = NULL; @@ -2626,6 +2844,8 @@ out: vrele(nd.ni_startdir); nd.ni_startdir = NULL; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { if (!error) { @@ -2638,6 +2858,8 @@ out: /* fall through */ nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_dvp) { if (nd.ni_dvp == nd.ni_vp) @@ -2655,6 +2877,8 @@ nfsmout: FREE(pathcp, M_TEMP); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -2684,6 +2908,8 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, fhandle_t *fhp; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); @@ -2693,7 +2919,11 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto out; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; @@ -2702,7 +2932,11 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); if (dirp && !v3) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vrele(dirp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); dirp = NULL; } if (error) { @@ -2725,6 +2959,8 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * nd.ni_vp, if it exists, is referenced but not locked. */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vap->va_type = VDIR; if (nd.ni_vp != NULL) { NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2779,6 +3015,8 @@ out: VOP_UNLOCK(dirp, 0, td); } } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { if (!error) { @@ -2796,6 +3034,8 @@ out: /* fall through */ nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (dirp) vrele(dirp); if (nd.ni_dvp) { @@ -2812,6 +3052,8 @@ nfsmout: vrele(nd.ni_vp); } vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -2837,6 +3079,8 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct nameidata nd; struct mount *mp = NULL; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); @@ -2846,7 +3090,11 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto out; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = DELETE; @@ -2886,6 +3134,8 @@ out: * Issue or abort op. Since SAVESTART is not set, path name * component is freed by the VOP after either. */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (!error) error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2910,6 +3160,8 @@ out: VOP_UNLOCK(dirp, 0, td); } } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); nfsm_reply(NFSX_WCCDATA(v3)); error = 0; if (v3) @@ -2917,6 +3169,8 @@ out: /* fall through */ nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ NDFREE(&nd, NDF_ONLY_PNBUF); if (dirp) vrele(dirp); @@ -2930,6 +3184,8 @@ nfsmout: vput(nd.ni_vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return(error); } @@ -2999,6 +3255,8 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, u_quad_t off, toff, verf; u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); @@ -3025,7 +3283,11 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (!error && vp->v_type != VDIR) { error = ENOTDIR; + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; } if (error) { @@ -3039,6 +3301,8 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, /* * Obtain lock on vnode for this section of the code */ + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (v3) { error = getret = VOP_GETATTR(vp, &at, cred, td); #if 0 @@ -3049,10 +3313,17 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = NFSERR_BAD_COOKIE; #endif } - if (!error) + if (!error) { + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ + } if (error) { vput(vp); + mtx_unlock(&Giant); + NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_POSTOPATTR(v3)); if (v3) @@ -3094,10 +3365,12 @@ again: VOP_UNLOCK(vp, 0, td); if (error) { vrele(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; free((caddr_t)rbuf, M_TEMP); if (cookies) free((caddr_t)cookies, M_TEMP); + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3)); if (v3) nfsm_srvpostop_attr(getret, &at); @@ -3113,7 +3386,9 @@ again: */ if (siz == 0) { vrele(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 2 * NFSX_UNSIGNED); if (v3) { @@ -3161,6 +3436,8 @@ again: goto again; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); if (v3) { @@ -3237,7 +3514,11 @@ again: cookiep++; ncookies--; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vrele(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; nfsm_clget; *tl = nfsrv_nfs_false; @@ -3257,8 +3538,13 @@ again: FREE((caddr_t)cookies, M_TEMP); nfsmout: - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vrele(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } return(error); } @@ -3292,6 +3578,8 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ int v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) panic("nfsrv_readdirplus: v3 proc called on a v2 connection"); @@ -3315,8 +3603,12 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (!error && vp->v_type != VDIR) { error = ENOTDIR; + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); } if (error) { nfsm_reply(NFSX_UNSIGNED); @@ -3324,6 +3616,8 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = getret = VOP_GETATTR(vp, &at, cred, td); #if 0 /* @@ -3332,10 +3626,17 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, if (!error && toff && verf && verf != at.va_filerev) error = NFSERR_BAD_COOKIE; #endif - if (!error) + if (!error) { + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ + } if (error) { vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_V3POSTOPATTR); nfsm_srvpostop_attr(getret, &at); @@ -3370,10 +3671,12 @@ again: error = getret; if (error) { vrele(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; if (cookies) free((caddr_t)cookies, M_TEMP); free((caddr_t)rbuf, M_TEMP); + NFSD_LOCK(); nfsm_reply(NFSX_V3POSTOPATTR); nfsm_srvpostop_attr(getret, &at); error = 0; @@ -3388,6 +3691,8 @@ again: */ if (siz == 0) { vrele(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED); @@ -3441,19 +3746,23 @@ again: EOPNOTSUPP) { error = NFSERR_NOTSUPP; vrele(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; free((caddr_t)cookies, M_TEMP); free((caddr_t)rbuf, M_TEMP); + NFSD_LOCK(); nfsm_reply(NFSX_V3POSTOPATTR); nfsm_srvpostop_attr(getret, &at); error = 0; goto nfsmout; } vput(nvp); + mtx_unlock(&Giant); /* VFS */ nvp = NULL; dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; + NFSD_LOCK(); nfsm_reply(cnt); nfsm_srvpostop_attr(getret, &at); tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED); @@ -3462,6 +3771,8 @@ again: bp = bpos; be = bp + M_TRAILINGSPACE(mp); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ /* Loop through the records and build reply */ while (cpos < cend && ncookies > 0) { if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { @@ -3517,16 +3828,16 @@ again: fl.fl_off.nfsuquad[0] = 0; fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep); - nfsm_clget; + nfsm_clget_nolock; *tl = nfsrv_nfs_true; bp += NFSX_UNSIGNED; - nfsm_clget; + nfsm_clget_nolock; *tl = 0; bp += NFSX_UNSIGNED; - nfsm_clget; + nfsm_clget_nolock; *tl = txdr_unsigned(dp->d_fileno); bp += NFSX_UNSIGNED; - nfsm_clget; + nfsm_clget_nolock; *tl = txdr_unsigned(nlen); bp += NFSX_UNSIGNED; @@ -3555,7 +3866,7 @@ again: xfer = sizeof (struct flrep); cp = (caddr_t)&fl; while (xfer > 0) { - nfsm_clget; + nfsm_clget_nolock; if ((bp + xfer) > be) tsiz = be - bp; else @@ -3574,10 +3885,12 @@ invalid: ncookies--; } vrele(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; - nfsm_clget; + nfsm_clget_nolock; *tl = nfsrv_nfs_false; bp += NFSX_UNSIGNED; + NFSD_LOCK(); nfsm_clget; if (eofflag) *tl = nfsrv_nfs_true; @@ -3592,8 +3905,13 @@ invalid: FREE((caddr_t)cookies, M_TEMP); FREE((caddr_t)rbuf, M_TEMP); nfsmout: - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vrele(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } return(error); } @@ -3620,6 +3938,8 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mount *mp = NULL; int v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) panic("nfsrv_commit: v3 proc called on a v2 connection"); @@ -3629,7 +3949,11 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = ESTALE; goto ereply; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ (void) vn_start_write(NULL, &mp, V_WAIT); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED); /* @@ -3646,6 +3970,8 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ for_ret = VOP_GETATTR(vp, &bfor, cred, td); if (cnt > MAX_COMMIT_COUNT) { @@ -3733,7 +4059,9 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, aft_ret = VOP_GETATTR(vp, &aft, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); ereply: nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); @@ -3747,9 +4075,13 @@ ereply: error = 0; } nfsmout: + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (vp) vput(vp); vn_finished_write(mp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return(error); } @@ -3777,6 +4109,8 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct statfs statfs; u_quad_t tval; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); @@ -3789,10 +4123,14 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, goto nfsmout; } sf = &statfs; + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = VFS_STATFS(vp->v_mount, sf, td); getret = VOP_GETATTR(vp, &at, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); if (v3) nfsm_srvpostop_attr(getret, &at); @@ -3838,8 +4176,13 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, sfp->sf_bavail = txdr_unsigned(sf->f_bavail); } nfsmout: - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); vput(vp); + mtx_unlock(&Giant); + NFSD_LOCK(); + } return(error); } @@ -3866,6 +4209,8 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct statfs sb; int v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) panic("nfsrv_fsinfo: v3 proc called on a v2 connection"); @@ -3879,13 +4224,17 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ /* XXX Try to make a guess on the max file size. */ VFS_STATFS(vp->v_mount, &sb, td); maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; getret = VOP_GETATTR(vp, &at, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); nfsm_srvpostop_attr(getret, &at); sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO); @@ -3913,8 +4262,13 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | NFSV3FSINFO_CANSETTIME); nfsmout: - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } return(error); } @@ -3940,6 +4294,8 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, fhandle_t *fhp; int v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) panic("nfsrv_pathconf: v3 proc called on a v2 connection"); @@ -3952,6 +4308,8 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = 0; goto nfsmout; } + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); if (!error) error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); @@ -3961,7 +4319,9 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); getret = VOP_GETATTR(vp, &at, cred, td); vput(vp); + mtx_unlock(&Giant); /* VFS */ vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); nfsm_srvpostop_attr(getret, &at); if (error) { @@ -3983,8 +4343,13 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, pc->pc_caseinsensitive = nfsrv_nfs_false; pc->pc_casepreserving = nfsrv_nfs_true; nfsmout: - if (vp) + if (vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ vput(vp); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } return(error); } @@ -4001,6 +4366,8 @@ nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, int error = NFSERR_RETVOID; struct mbuf *mb, *mreq; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); nfsm_reply(0); nfsmout: @@ -4020,6 +4387,8 @@ nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, int error; struct mbuf *mb, *mreq; + NFSD_LOCK_ASSERT(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (nfsd->nd_repstat) error = nfsd->nd_repstat; @@ -4052,6 +4421,9 @@ nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly, struct vattr vattr; int error; + NFSD_LOCK_ASSERT(); + NFSD_UNLOCK(); + nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (flags & VWRITE) { /* Just vn_writechk() changed to check rdonly */ @@ -4065,7 +4437,8 @@ nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly, case VREG: case VDIR: case VLNK: - return (EROFS); + error = EROFS; + goto out; default: break; } @@ -4074,12 +4447,15 @@ nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly, * If there's shared text associated with * the inode, we can't allow writing. */ - if (vp->v_vflag & VV_TEXT) + if (vp->v_vflag & VV_TEXT) { + NFSD_LOCK(); return (ETXTBSY); + } } + mtx_lock(&Giant); /* VFS */ error = VOP_GETATTR(vp, &vattr, cred, td); if (error) - return (error); + goto out2; error = VOP_ACCESS(vp, flags, cred, td); /* * Allow certain operations for the owner (reads and writes @@ -4087,5 +4463,9 @@ nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly, */ if (override && error == EACCES && cred->cr_uid == vattr.va_uid) error = 0; +out2: + mtx_unlock(&Giant); /* VFS */ +out: + NFSD_LOCK(); return error; } diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c index f0e940d..e82625e 100644 --- a/sys/nfsserver/nfs_srvcache.c +++ b/sys/nfsserver/nfs_srvcache.c @@ -44,7 +44,9 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mount.h> #include <sys/systm.h> +#include <sys/lock.h> #include <sys/mbuf.h> +#include <sys/mutex.h> #include <sys/socket.h> #include <sys/socketvar.h> /* for sodupsockaddr */ @@ -72,7 +74,7 @@ static u_long nfsrvhash; /* * Static array that defines which nfs rpc's are nonidempotent */ -static int nonidempotent[NFS_NPROCS] = { +static const int nonidempotent[NFS_NPROCS] = { FALSE, FALSE, TRUE, @@ -99,7 +101,7 @@ static int nonidempotent[NFS_NPROCS] = { }; /* True iff the rpc reply is an nfs status ONLY! */ -static int nfsv2_repstat[NFS_NPROCS] = { +static const int nfsv2_repstat[NFS_NPROCS] = { FALSE, FALSE, FALSE, @@ -154,6 +156,8 @@ nfsrv_getcache(struct nfsrv_descript *nd, struct mbuf **repp) caddr_t bpos; int ret; + NFSD_LOCK_ASSERT(); + /* * Don't cache recent requests for reliable transport protocols. * (Maybe we should for the case of a reconnect, but..) @@ -167,7 +171,8 @@ loop: NFS_DPF(RC, ("H%03x", rp->rc_xid & 0xfff)); if ((rp->rc_flag & RC_LOCKED) != 0) { rp->rc_flag |= RC_WANTED; - (void) tsleep(rp, PZERO-1, "nfsrc", 0); + (void) msleep(rp, &nfsd_mtx, PZERO-1, + "nfsrc", 0); goto loop; } rp->rc_flag |= RC_LOCKED; @@ -188,8 +193,10 @@ loop: ret = RC_REPLY; } else if (rp->rc_flag & RC_REPMBUF) { nfsrvstats.srvcache_nonidemdonehits++; + NFSD_UNLOCK(); *repp = m_copym(rp->rc_reply, 0, M_COPYALL, M_TRYWAIT); + NFSD_LOCK(); ret = RC_REPLY; } else { nfsrvstats.srvcache_idemdonehits++; @@ -207,15 +214,17 @@ loop: nfsrvstats.srvcache_misses++; NFS_DPF(RC, ("M%03x", nd->nd_retxid & 0xfff)); if (numnfsrvcache < desirednfsrvcache) { + NFSD_UNLOCK(); rp = (struct nfsrvcache *)malloc((u_long)sizeof *rp, M_NFSD, M_WAITOK | M_ZERO); + NFSD_LOCK(); numnfsrvcache++; rp->rc_flag = RC_LOCKED; } else { rp = TAILQ_FIRST(&nfsrvlruhead); while ((rp->rc_flag & RC_LOCKED) != 0) { rp->rc_flag |= RC_WANTED; - (void) tsleep(rp, PZERO-1, "nfsrc", 0); + (void) msleep(rp, &nfsd_mtx, PZERO-1, "nfsrc", 0); rp = TAILQ_FIRST(&nfsrvlruhead); } rp->rc_flag |= RC_LOCKED; @@ -261,6 +270,8 @@ nfsrv_updatecache(struct nfsrv_descript *nd, int repvalid, struct mbuf *repmbuf) { struct nfsrvcache *rp; + NFSD_LOCK_ASSERT(); + if (!nd->nd_nam2) return; loop: @@ -270,7 +281,8 @@ loop: NFS_DPF(RC, ("U%03x", rp->rc_xid & 0xfff)); if ((rp->rc_flag & RC_LOCKED) != 0) { rp->rc_flag |= RC_WANTED; - (void) tsleep(rp, PZERO-1, "nfsrc", 0); + (void) msleep(rp, &nfsd_mtx, PZERO-1, + "nfsrc", 0); goto loop; } rp->rc_flag |= RC_LOCKED; @@ -298,8 +310,10 @@ loop: rp->rc_status = nd->nd_repstat; rp->rc_flag |= RC_REPSTATUS; } else { + NFSD_UNLOCK(); rp->rc_reply = m_copym(repmbuf, 0, M_COPYALL, M_TRYWAIT); + NFSD_LOCK(); rp->rc_flag |= RC_REPMBUF; } } @@ -322,6 +336,8 @@ nfsrv_cleancache(void) { struct nfsrvcache *rp, *nextrp; + NFSD_LOCK_ASSERT(); + for (rp = TAILQ_FIRST(&nfsrvlruhead); rp != 0; rp = nextrp) { nextrp = TAILQ_NEXT(rp, rc_lru); LIST_REMOVE(rp, rc_hash); diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c index 32a42b2..d43b97a 100644 --- a/sys/nfsserver/nfs_srvsock.c +++ b/sys/nfsserver/nfs_srvsock.c @@ -97,7 +97,7 @@ struct callout nfsrv_callout; static void nfs_realign(struct mbuf **pm, int hsiz); /* XXX SHARED */ static int nfsrv_getstream(struct nfssvc_sock *, int); -int (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd, +int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd, struct nfssvc_sock *slp, struct thread *td, struct mbuf **mreqp) = { @@ -140,9 +140,13 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, int err, caddr_t bpos; struct mbuf *mb; + /* XXXRW: not 100% clear the lock is needed here. */ + NFSD_LOCK_ASSERT(); + nd->nd_repstat = err; if (err && (nd->nd_flag & ND_NFSV3) == 0) /* XXX recheck */ siz = 0; + NFSD_UNLOCK(); MGETHDR(mreq, M_TRYWAIT, MT_DATA); mb = mreq; /* @@ -155,6 +159,7 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, int err, MCLGET(mreq, M_TRYWAIT); } else mreq->m_data += min(max_hdr, M_TRAILINGSPACE(mreq)); + NFSD_LOCK(); tl = mtod(mreq, u_int32_t *); bpos = ((caddr_t)tl) + mreq->m_len; *tl++ = txdr_unsigned(nd->nd_retxid); @@ -236,13 +241,18 @@ nfs_realign(struct mbuf **pm, int hsiz) /* XXX COMMON */ struct mbuf *n = NULL; int off = 0; + /* XXXRW: may not need lock? */ + NFSD_LOCK_ASSERT(); + ++nfs_realign_test; while ((m = *pm) != NULL) { if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) { + NFSD_UNLOCK(); MGET(n, M_TRYWAIT, MT_DATA); if (m->m_len >= MINCLSIZE) { MCLGET(n, M_TRYWAIT); } + NFSD_LOCK(); n->m_len = 0; break; } @@ -281,6 +291,8 @@ nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header) int error = 0; struct mbuf *mrep, *md; + NFSD_LOCK_ASSERT(); + mrep = nd->nd_mrep; md = nd->nd_md; dpos = nd->nd_dpos; @@ -410,6 +422,15 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) struct uio auio; int flags, error; + /* + * XXXRW: For now, assert Giant here since the NFS server upcall + * will perform socket operations requiring Giant in a non-mpsafe + * kernel. + */ + NET_ASSERT_GIANT(); + NFSD_UNLOCK_ASSERT(); + + /* XXXRW: Unlocked read. */ if ((slp->ns_flag & SLP_VALID) == 0) return; #ifdef notdef @@ -417,12 +438,13 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) * Define this to test for nfsds handling this under heavy load. */ if (waitflag == M_DONTWAIT) { + NFSD_LOCK(); slp->ns_flag |= SLP_NEEDQ; goto dorecs; } #endif - GIANT_REQUIRED; /* XXX until socket locking is done */ + NFSD_LOCK(); auio.uio_td = NULL; if (so->so_type == SOCK_STREAM) { /* @@ -441,8 +463,10 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) */ auio.uio_resid = 1000000000; flags = MSG_DONTWAIT; + NFSD_UNLOCK(); error = so->so_proto->pr_usrreqs->pru_soreceive (so, &nam, &auio, &mp, NULL, &flags); + NFSD_LOCK(); if (error || mp == NULL) { if (error == EWOULDBLOCK) slp->ns_flag |= SLP_NEEDQ; @@ -476,6 +500,7 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) do { auio.uio_resid = 1000000000; flags = MSG_DONTWAIT; + NFSD_UNLOCK(); error = so->so_proto->pr_usrreqs->pru_soreceive (so, &nam, &auio, &mp, NULL, &flags); if (mp) { @@ -487,13 +512,16 @@ nfsrv_rcv(struct socket *so, void *arg, int waitflag) if (nam) FREE(nam, M_SONAME); m_freem(mp); + NFSD_LOCK(); continue; } + NFSD_LOCK(); nfs_realign(&mp, 10 * NFSX_UNSIGNED); rec->nr_address = nam; rec->nr_packet = mp; STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link); - } + } else + NFSD_LOCK(); if (error) { if ((so->so_proto->pr_flags & PR_CONNREQUIRED) && error != EWOULDBLOCK) { @@ -512,6 +540,7 @@ dorecs: (STAILQ_FIRST(&slp->ns_rec) != NULL || (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN)))) nfsrv_wakenfsd(slp); + NFSD_UNLOCK(); } /* @@ -528,6 +557,8 @@ nfsrv_getstream(struct nfssvc_sock *slp, int waitflag) struct mbuf *om, *m2, *recm; u_int32_t recmark; + NFSD_LOCK_ASSERT(); + if (slp->ns_flag & SLP_GETSTREAM) panic("nfs getstream"); slp->ns_flag |= SLP_GETSTREAM; @@ -586,8 +617,10 @@ nfsrv_getstream(struct nfssvc_sock *slp, int waitflag) while (len < slp->ns_reclen) { if ((len + m->m_len) > slp->ns_reclen) { + NFSD_UNLOCK(); m2 = m_copym(m, 0, slp->ns_reclen - len, waitflag); + NFSD_LOCK(); if (m2) { if (om) { om->m_next = m2; @@ -630,8 +663,10 @@ nfsrv_getstream(struct nfssvc_sock *slp, int waitflag) *mpp = recm; if (slp->ns_flag & SLP_LASTFRAG) { struct nfsrv_rec *rec; + NFSD_UNLOCK(); rec = malloc(sizeof(struct nfsrv_rec), M_NFSRVDESC, waitflag == M_DONTWAIT ? M_NOWAIT : M_WAITOK); + NFSD_LOCK(); if (!rec) { m_freem(slp->ns_frag); } else { @@ -658,6 +693,8 @@ nfsrv_dorec(struct nfssvc_sock *slp, struct nfsd *nfsd, struct nfsrv_descript *nd; int error; + NFSD_LOCK_ASSERT(); + *ndp = NULL; if ((slp->ns_flag & SLP_VALID) == 0 || STAILQ_FIRST(&slp->ns_rec) == NULL) @@ -667,8 +704,10 @@ nfsrv_dorec(struct nfssvc_sock *slp, struct nfsd *nfsd, nam = rec->nr_address; m = rec->nr_packet; free(rec, M_NFSRVDESC); + NFSD_UNLOCK(); MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript), M_NFSRVDESC, M_WAITOK); + NFSD_LOCK(); nd->nd_md = nd->nd_mrep = m; nd->nd_nam2 = nam; nd->nd_dpos = mtod(m, caddr_t); @@ -695,6 +734,8 @@ nfsrv_wakenfsd(struct nfssvc_sock *slp) { struct nfsd *nd; + NFSD_LOCK_ASSERT(); + if ((slp->ns_flag & SLP_VALID) == 0) return; TAILQ_FOREACH(nd, &nfsd_head, nfsd_chain) { @@ -725,7 +766,8 @@ nfsrv_send(struct socket *so, struct sockaddr *nam, struct mbuf *top) struct sockaddr *sendnam; int error, soflags, flags; - GIANT_REQUIRED; /* XXX until socket locking is done */ + NET_ASSERT_GIANT(); + NFSD_UNLOCK_ASSERT(); soflags = so->so_proto->pr_flags; if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED)) @@ -766,6 +808,7 @@ nfsrv_timer(void *arg) u_quad_t cur_usec; s = splnet(); + NFSD_LOCK(); /* * Scan the write gathering queues for writes that need to be * completed now. @@ -776,6 +819,7 @@ nfsrv_timer(void *arg) LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec) nfsrv_wakenfsd(slp); } + NFSD_UNLOCK(); splx(s); callout_reset(&nfsrv_callout, nfsrv_ticks, nfsrv_timer, NULL); } diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c index 9da4b1a..7217150 100644 --- a/sys/nfsserver/nfs_srvsubs.c +++ b/sys/nfsserver/nfs_srvsubs.c @@ -85,8 +85,8 @@ u_int32_t nfsrv_rpc_call, nfsrv_rpc_vers, nfsrv_rpc_reply, u_int32_t nfsrv_nfs_prog, nfsrv_nfs_true, nfsrv_nfs_false; /* And other global data */ -static nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, - NFNON, NFCHR, NFNON }; +static const nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, + NFLNK, NFNON, NFCHR, NFNON }; #define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))]) #define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS) @@ -100,10 +100,12 @@ int nfsd_head_flag; static int nfs_prev_nfssvc_sy_narg; static sy_call_t *nfs_prev_nfssvc_sy_call; +struct mtx nfsd_mtx; + /* * Mapping of old NFS Version 2 RPC numbers to generic numbers. */ -int nfsrv_nfsv3_procid[NFS_NPROCS] = { +const int nfsrv_nfsv3_procid[NFS_NPROCS] = { NFSPROC_NULL, NFSPROC_GETATTR, NFSPROC_SETATTR, @@ -132,7 +134,7 @@ int nfsrv_nfsv3_procid[NFS_NPROCS] = { /* * and the reverse mapping from generic to Version 2 procedure numbers */ -int nfsrvv2_procid[NFS_NPROCS] = { +const int nfsrvv2_procid[NFS_NPROCS] = { NFSV2PROC_NULL, NFSV2PROC_GETATTR, NFSV2PROC_SETATTR, @@ -163,7 +165,7 @@ int nfsrvv2_procid[NFS_NPROCS] = { * Use 0 (which gets converted to NFSERR_IO) as the catch all for ones not * specifically defined in RFC 1094. */ -static u_char nfsrv_v2errmap[ELAST] = { +static const u_char nfsrv_v2errmap[ELAST] = { NFSERR_PERM, NFSERR_NOENT, 0, 0, 0, NFSERR_NXIO, 0, 0, 0, 0, 0, 0, NFSERR_ACCES, 0, 0, @@ -192,12 +194,12 @@ static u_char nfsrv_v2errmap[ELAST] = { * The first entry is the default error return and the rest are the valid * errors for that RPC in increasing numeric order. */ -static short nfsv3err_null[] = { +static const short nfsv3err_null[] = { 0, 0, }; -static short nfsv3err_getattr[] = { +static const short nfsv3err_getattr[] = { NFSERR_IO, NFSERR_IO, NFSERR_STALE, @@ -206,7 +208,7 @@ static short nfsv3err_getattr[] = { 0, }; -static short nfsv3err_setattr[] = { +static const short nfsv3err_setattr[] = { NFSERR_IO, NFSERR_PERM, NFSERR_IO, @@ -222,7 +224,7 @@ static short nfsv3err_setattr[] = { 0, }; -static short nfsv3err_lookup[] = { +static const short nfsv3err_lookup[] = { NFSERR_IO, NFSERR_NOENT, NFSERR_IO, @@ -235,7 +237,7 @@ static short nfsv3err_lookup[] = { 0, }; -static short nfsv3err_access[] = { +static const short nfsv3err_access[] = { NFSERR_IO, NFSERR_IO, NFSERR_STALE, @@ -244,7 +246,7 @@ static short nfsv3err_access[] = { 0, }; -static short nfsv3err_readlink[] = { +static const short nfsv3err_readlink[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -256,7 +258,7 @@ static short nfsv3err_readlink[] = { 0, }; -static short nfsv3err_read[] = { +static const short nfsv3err_read[] = { NFSERR_IO, NFSERR_IO, NFSERR_NXIO, @@ -268,7 +270,7 @@ static short nfsv3err_read[] = { 0, }; -static short nfsv3err_write[] = { +static const short nfsv3err_write[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -283,7 +285,7 @@ static short nfsv3err_write[] = { 0, }; -static short nfsv3err_create[] = { +static const short nfsv3err_create[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -300,7 +302,7 @@ static short nfsv3err_create[] = { 0, }; -static short nfsv3err_mkdir[] = { +static const short nfsv3err_mkdir[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -317,7 +319,7 @@ static short nfsv3err_mkdir[] = { 0, }; -static short nfsv3err_symlink[] = { +static const short nfsv3err_symlink[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -334,7 +336,7 @@ static short nfsv3err_symlink[] = { 0, }; -static short nfsv3err_mknod[] = { +static const short nfsv3err_mknod[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -352,7 +354,7 @@ static short nfsv3err_mknod[] = { 0, }; -static short nfsv3err_remove[] = { +static const short nfsv3err_remove[] = { NFSERR_IO, NFSERR_NOENT, NFSERR_IO, @@ -366,7 +368,7 @@ static short nfsv3err_remove[] = { 0, }; -static short nfsv3err_rmdir[] = { +static const short nfsv3err_rmdir[] = { NFSERR_IO, NFSERR_NOENT, NFSERR_IO, @@ -384,7 +386,7 @@ static short nfsv3err_rmdir[] = { 0, }; -static short nfsv3err_rename[] = { +static const short nfsv3err_rename[] = { NFSERR_IO, NFSERR_NOENT, NFSERR_IO, @@ -407,7 +409,7 @@ static short nfsv3err_rename[] = { 0, }; -static short nfsv3err_link[] = { +static const short nfsv3err_link[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -427,7 +429,7 @@ static short nfsv3err_link[] = { 0, }; -static short nfsv3err_readdir[] = { +static const short nfsv3err_readdir[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -440,7 +442,7 @@ static short nfsv3err_readdir[] = { 0, }; -static short nfsv3err_readdirplus[] = { +static const short nfsv3err_readdirplus[] = { NFSERR_IO, NFSERR_IO, NFSERR_ACCES, @@ -454,7 +456,7 @@ static short nfsv3err_readdirplus[] = { 0, }; -static short nfsv3err_fsstat[] = { +static const short nfsv3err_fsstat[] = { NFSERR_IO, NFSERR_IO, NFSERR_STALE, @@ -463,7 +465,7 @@ static short nfsv3err_fsstat[] = { 0, }; -static short nfsv3err_fsinfo[] = { +static const short nfsv3err_fsinfo[] = { NFSERR_STALE, NFSERR_STALE, NFSERR_BADHANDLE, @@ -471,7 +473,7 @@ static short nfsv3err_fsinfo[] = { 0, }; -static short nfsv3err_pathconf[] = { +static const short nfsv3err_pathconf[] = { NFSERR_STALE, NFSERR_STALE, NFSERR_BADHANDLE, @@ -479,7 +481,7 @@ static short nfsv3err_pathconf[] = { 0, }; -static short nfsv3err_commit[] = { +static const short nfsv3err_commit[] = { NFSERR_IO, NFSERR_IO, NFSERR_STALE, @@ -488,7 +490,7 @@ static short nfsv3err_commit[] = { 0, }; -static short *nfsrv_v3errmap[] = { +static const short *nfsrv_v3errmap[] = { nfsv3err_null, nfsv3err_getattr, nfsv3err_setattr, @@ -520,8 +522,11 @@ static int nfsrv_modevent(module_t mod, int type, void *data) { + NET_LOCK_GIANT(); + switch (type) { case MOD_LOAD: + mtx_init(&nfsd_mtx, "nfsd_mtx", NULL, MTX_DEF); nfsrv_rpc_vers = txdr_unsigned(RPC_VER2); nfsrv_rpc_call = txdr_unsigned(RPC_CALL); nfsrv_rpc_reply = txdr_unsigned(RPC_REPLY); @@ -538,10 +543,11 @@ nfsrv_modevent(module_t mod, int type, void *data) if (nfsrv_ticks < 1) nfsrv_ticks = 1; - nfsrv_init(0); /* Init server data structures */ nfsrv_initcache(); /* Init the server request cache */ - + NFSD_LOCK(); + nfsrv_init(0); /* Init server data structures */ callout_init(&nfsrv_callout, 0); + NFSD_UNLOCK(); nfsrv_timer(0); nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg; @@ -557,8 +563,10 @@ nfsrv_modevent(module_t mod, int type, void *data) callout_stop(&nfsrv_callout); sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg; sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call; + mtx_destroy(&nfsd_mtx); break; } + NET_UNLOCK_GIANT(); return 0; } static moduledata_t nfsserver_mod = { @@ -603,6 +611,10 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, struct componentname *cnp = &ndp->ni_cnd; int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0; + NFSD_LOCK_ASSERT(); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ + *retdirp = NULL; cnp->cn_flags |= NOMACCHECK; cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); @@ -646,8 +658,12 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len, /* * Extract and set starting directory. */ + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp, nam, &rdonly, pubflag); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ if (error) goto out; if (dp->v_type != VDIR) { @@ -868,6 +884,8 @@ out: } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) { ndp->ni_dvp = NULL; } + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); return (error); } @@ -882,6 +900,8 @@ nfsm_adj(struct mbuf *mp, int len, int nul) int count, i; char *cp; + NFSD_LOCK_DONTCARE(); + /* * Trim from tail. Scan the mbuf chain, * calculating its length and finding the last mbuf. @@ -1043,6 +1063,8 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, struct sockaddr_int *saddr; #endif + NFSD_LOCK_ASSERT(); + *vpp = NULL; if (nfs_ispublicfh(fhp)) { @@ -1054,12 +1076,14 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, mp = vfs_getvfs(&fhp->fh_fsid); if (!mp) return (ESTALE); + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); if (error) - return (error); + goto out; error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); if (error) - return (error); + goto out; #ifdef MNT_EXNORESPORT if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) { saddr = (struct sockaddr_in *)nam; @@ -1069,7 +1093,7 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, ntohs(saddr->sin_port) >= IPPORT_RESERVED) { vput(*vpp); *vpp = NULL; - return (NFSERR_AUTHERR | AUTH_TOOWEAK); + error = NFSERR_AUTHERR | AUTH_TOOWEAK; } } #endif @@ -1091,7 +1115,10 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, if (!lockflag) VOP_UNLOCK(*vpp, 0, td); - return (0); +out: + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + return (error); } @@ -1106,6 +1133,8 @@ nfs_ispublicfh(fhandle_t *fhp) char *cp = (char *)fhp; int i; + NFSD_LOCK_DONTCARE(); + for (i = 0; i < NFSX_V3FH; i++) if (*cp++ != 0) return (FALSE); @@ -1124,6 +1153,8 @@ netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam) { struct sockaddr_in *inetaddr; + NFSD_LOCK_DONTCARE(); + switch (family) { case AF_INET: inetaddr = (struct sockaddr_in *)nam; @@ -1159,9 +1190,11 @@ netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam) int nfsrv_errmap(struct nfsrv_descript *nd, int err) { - short *defaulterrp, *errp; + const short *defaulterrp, *errp; int e; + NFSD_LOCK_DONTCARE(); + if (nd->nd_flag & ND_NFSV3) { if (nd->nd_procnum <= NFSPROC_COMMIT) { errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; @@ -1187,6 +1220,9 @@ int nfsrv_object_create(struct vnode *vp) { + GIANT_REQUIRED; + NFSD_UNLOCK_ASSERT(); + if (vp == NULL || vp->v_type != VREG) return (1); return (vfs_object_create(vp, curthread, curthread->td_ucred)); @@ -1203,6 +1239,8 @@ nfsrvw_sort(gid_t *list, int num) int i, j; gid_t v; + NFSD_LOCK_DONTCARE(); + /* Insertion sort. */ for (i = 1; i < num; i++) { v = list[i]; @@ -1221,6 +1259,8 @@ nfsrv_setcred(struct ucred *incred, struct ucred *outcred) { int i; + NFSD_LOCK_DONTCARE(); + bzero((caddr_t)outcred, sizeof (struct ucred)); outcred->cr_ref = 1; outcred->cr_uid = incred->cr_uid; @@ -1239,6 +1279,8 @@ nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos) { u_int32_t *tl; + NFSD_LOCK_DONTCARE(); + if (v3) { tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos); *tl++ = txdr_unsigned(NFSX_V3FH); @@ -1265,6 +1307,8 @@ nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos) { u_int32_t *tl; + NFSD_LOCK_DONTCARE(); + tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); if (tl == NULL) return EBADRPC; @@ -1279,6 +1323,8 @@ nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos) { u_int32_t *tl; + NFSD_LOCK_DONTCARE(); + tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); if (tl == NULL) return EBADRPC; @@ -1292,15 +1338,26 @@ nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos) void nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp, - char **bp, char **be, caddr_t bpos) + char **bp, char **be, caddr_t bpos, int droplock) { struct mbuf *nmp; + NFSD_LOCK_DONTCARE(); + + if (droplock) + NFSD_LOCK_ASSERT(); + else + NFSD_UNLOCK_ASSERT(); + if (*bp >= *be) { if (*mp == mb) (*mp)->m_len += *bp - bpos; + if (droplock) + NFSD_UNLOCK(); MGET(nmp, M_TRYWAIT, MT_DATA); MCLGET(nmp, M_TRYWAIT); + if (droplock) + NFSD_LOCK(); nmp->m_len = NFSMSIZ(nmp); (*mp)->m_next = nmp; *mp = nmp; @@ -1317,6 +1374,8 @@ nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd, struct mbuf **md, u_int32_t *tl; int fhlen; + NFSD_LOCK_DONTCARE(); + if (nfsd->nd_flag & ND_NFSV3) { tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); if (tl == NULL) @@ -1343,6 +1402,8 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos) { u_int32_t *tl; + NFSD_LOCK_DONTCARE(); + tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos); if (tl == NULL) return EBADRPC; diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c index c3b097e..19ef606 100644 --- a/sys/nfsserver/nfs_syscalls.c +++ b/sys/nfsserver/nfs_syscalls.c @@ -142,11 +142,14 @@ nfssvc(struct thread *td, struct nfssvc_args *uap) error = suser(td); if (error) return (error); - mtx_lock(&Giant); + NET_LOCK_GIANT(); + NFSD_LOCK(); while (nfssvc_sockhead_flag & SLP_INIT) { nfssvc_sockhead_flag |= SLP_WANTINIT; - (void) tsleep(&nfssvc_sockhead, PSOCK, "nfsd init", 0); + (void) msleep(&nfssvc_sockhead, &nfsd_mtx, PSOCK, + "nfsd init", 0); } + NFSD_UNLOCK(); if (uap->flag & NFSSVC_ADDSOCK) { error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg)); if (error) @@ -180,7 +183,7 @@ nfssvc(struct thread *td, struct nfssvc_args *uap) if (error == EINTR || error == ERESTART) error = 0; done2: - mtx_unlock(&Giant); + NET_UNLOCK_GIANT(); return (error); } @@ -195,10 +198,14 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) struct socket *so; int error, s; - GIANT_REQUIRED; /* XXX until socket locking done */ + NET_ASSERT_GIANT(); so = fp->f_data; #if 0 + /* + * XXXRW: If this code is ever enabled, there's a race when running + * MPSAFE. + */ tslp = NULL; /* * Add it to the list, as required. @@ -263,12 +270,16 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO); STAILQ_INIT(&slp->ns_rec); + NFSD_LOCK(); TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); slp->ns_so = so; slp->ns_nam = mynam; fhold(fp); slp->ns_fp = fp; + /* + * XXXRW: Socket locking here? + */ s = splnet(); so->so_upcallarg = (caddr_t)slp; so->so_upcall = nfsrv_rcv; @@ -276,6 +287,7 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) slp->ns_flag = (SLP_VALID | SLP_NEEDQ); nfsrv_wakenfsd(slp); splx(s); + NFSD_UNLOCK(); return (0); } @@ -295,6 +307,8 @@ nfssvc_nfsd(struct thread *td) int procrastinate; u_quad_t cur_usec; + NET_ASSERT_GIANT(); + #ifndef nolint cacherep = RC_DOIT; writes_todo = 0; @@ -302,6 +316,8 @@ nfssvc_nfsd(struct thread *td) nfsd = (struct nfsd *) malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK | M_ZERO); s = splnet(); + NFSD_LOCK(); + nfsd->nfsd_td = td; TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain); nfsrv_numnfsd++; @@ -315,8 +331,8 @@ nfssvc_nfsd(struct thread *td) (nfsd_head_flag & NFSD_CHECKSLP) == 0) { nfsd->nfsd_flag |= NFSD_WAITING; nfsd_waiting++; - error = tsleep(nfsd, PSOCK | PCATCH, - "-", 0); + error = msleep(nfsd, &nfsd_mtx, + PSOCK | PCATCH, "-", 0); nfsd_waiting--; if (error) goto done; @@ -343,8 +359,10 @@ nfssvc_nfsd(struct thread *td) else if (slp->ns_flag & SLP_NEEDQ) { slp->ns_flag &= ~SLP_NEEDQ; (void) nfs_slplock(slp, 1); + NFSD_UNLOCK(); nfsrv_rcv(slp->ns_so, (caddr_t)slp, M_TRYWAIT); + NFSD_LOCK(); nfs_slpunlock(slp); } error = nfsrv_dorec(slp, nfsd, &nd); @@ -458,6 +476,7 @@ nfssvc_nfsd(struct thread *td) nd->nd_mrep = NULL; /* FALLTHROUGH */ case RC_REPLY: + NFSD_UNLOCK(); siz = m_length(mreq, NULL); if (siz <= 0 || siz > NFS_MAXPACKET) { printf("mbuf siz=%d\n",siz); @@ -474,11 +493,16 @@ nfssvc_nfsd(struct thread *td) M_PREPEND(m, NFSX_UNSIGNED, M_TRYWAIT); *mtod(m, u_int32_t *) = htonl(0x80000000 | siz); } + NFSD_LOCK(); if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED) (void) nfs_slplock(slp, 1); - if (slp->ns_flag & SLP_VALID) + if (slp->ns_flag & SLP_VALID) { + NFSD_UNLOCK(); + NET_LOCK_GIANT(); error = nfsrv_send(slp->ns_so, nd->nd_nam2, m); - else { + NET_UNLOCK_GIANT(); + NFSD_LOCK(); + } else { error = EPIPE; m_freem(m); } @@ -535,6 +559,7 @@ done: free((caddr_t)nfsd, M_NFSD); if (--nfsrv_numnfsd == 0) nfsrv_init(TRUE); /* Reinitialize everything */ + NFSD_UNLOCK(); return (error); } @@ -554,9 +579,18 @@ nfsrv_zapsock(struct nfssvc_sock *slp) struct nfsrv_rec *rec; int s; + NET_ASSERT_GIANT(); + NFSD_LOCK_ASSERT(); + + /* + * XXXRW: By clearing all flags, other threads/etc should ignore + * this slp and we can safely release nfsd_mtx so we can clean + * up the slp safely. + */ slp->ns_flag &= ~SLP_ALLFLAGS; fp = slp->ns_fp; if (fp) { + NFSD_UNLOCK(); slp->ns_fp = NULL; so = slp->ns_so; so->so_rcv.sb_flags &= ~SB_UPCALL; @@ -564,6 +598,7 @@ nfsrv_zapsock(struct nfssvc_sock *slp) so->so_upcallarg = NULL; soshutdown(so, SHUT_RDWR); closef(fp, NULL); + NFSD_LOCK(); if (slp->ns_nam) FREE(slp->ns_nam, M_SONAME); m_freem(slp->ns_raw); @@ -593,6 +628,8 @@ void nfsrv_slpderef(struct nfssvc_sock *slp) { + NFSD_LOCK_ASSERT(); + if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); free((caddr_t)slp, M_NFSSVC); @@ -601,17 +638,22 @@ nfsrv_slpderef(struct nfssvc_sock *slp) /* * Lock a socket against others. + * + * XXXRW: Wait argument is always 1 in the caller. Replace with a real + * sleep lock? */ int nfs_slplock(struct nfssvc_sock *slp, int wait) { int *statep = &slp->ns_solock; + NFSD_LOCK_ASSERT(); + if (!wait && (*statep & NFSRV_SNDLOCK)) return(0); /* already locked, fail */ while (*statep & NFSRV_SNDLOCK) { *statep |= NFSRV_WANTSND; - (void) tsleep(statep, PZERO - 1, "nfsslplck", 0); + (void) msleep(statep, &nfsd_mtx, PZERO - 1, "nfsslplck", 0); } *statep |= NFSRV_SNDLOCK; return (1); @@ -625,6 +667,8 @@ nfs_slpunlock(struct nfssvc_sock *slp) { int *statep = &slp->ns_solock; + NFSD_LOCK_ASSERT(); + if ((*statep & NFSRV_SNDLOCK) == 0) panic("nfs slpunlock"); *statep &= ~NFSRV_SNDLOCK; @@ -644,6 +688,9 @@ nfsrv_init(int terminating) { struct nfssvc_sock *slp, *nslp; + NET_ASSERT_GIANT(); + NFSD_LOCK_ASSERT(); + if (nfssvc_sockhead_flag & SLP_INIT) panic("nfsd init"); nfssvc_sockhead_flag |= SLP_INIT; diff --git a/sys/nfsserver/nfsm_subs.h b/sys/nfsserver/nfsm_subs.h index 07b958c..8e404d8 100644 --- a/sys/nfsserver/nfsm_subs.h +++ b/sys/nfsserver/nfsm_subs.h @@ -160,7 +160,7 @@ void nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos); void nfsm_srvpostop_fh_xx(fhandle_t *f, struct mbuf **mb, caddr_t *bpos); void nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp, - char **bp, char **be, caddr_t bpos); + char **bp, char **be, caddr_t bpos, int droplock); #define nfsm_srvfhtom(f, v3) \ nfsm_srvfhtom_xx((f), (v3), &mb, &bpos) @@ -178,6 +178,9 @@ void nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp, nfsm_srvfattr(nfsd, (a), (f)) #define nfsm_clget \ - nfsm_clget_xx(&tl, mb, &mp, &bp, &be, bpos) + nfsm_clget_xx(&tl, mb, &mp, &bp, &be, bpos, 1) + +#define nfsm_clget_nolock \ + nfsm_clget_xx(&tl, mb, &mp, &bp, &be, bpos, 0) #endif |