summaryrefslogtreecommitdiffstats
path: root/sys/nfsserver/nfs_serv.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2007-03-17 18:18:08 +0000
committerjeff <jeff@FreeBSD.org>2007-03-17 18:18:08 +0000
commitd43d58ff4578f356c44c4ad57ff2d4c6b2b99a50 (patch)
tree3cce5e99818314cbc53c7fe494e3fdbfa9017a1e /sys/nfsserver/nfs_serv.c
parent82143f95ad1b41e027bececf613c3e94f1556ac6 (diff)
downloadFreeBSD-src-d43d58ff4578f356c44c4ad57ff2d4c6b2b99a50.zip
FreeBSD-src-d43d58ff4578f356c44c4ad57ff2d4c6b2b99a50.tar.gz
- Turn all explicit giant acquires into conditional VFS_LOCK_GIANTs.
Only ops which used namei still remained. - Implement a scheme for reducing the overhead of tracking which vops require giant by constantly reducing the number of recursive giant acquires to one, leaving us with only one vfslocked variable. - Remove all NFSD lock acquisition and release from the individual nfs ops. Careful examination has shown that they are not required. This greatly simplifies the code. Sponsored by: Isilon Systems, Inc. Discussed with: rwatson Tested by: kkenn Approved by: re
Diffstat (limited to 'sys/nfsserver/nfs_serv.c')
-rw-r--r--sys/nfsserver/nfs_serv.c741
1 files changed, 187 insertions, 554 deletions
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 4b5ba21..85c7b52 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -137,8 +137,8 @@ struct nfsrvstats nfsrvstats;
SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RD,
&nfsrvstats, nfsrvstats, "S,nfsrvstats");
-static int nfsrv_access(struct vnode *vp, int flags, struct ucred *cred,
- int rdonly, struct thread *td, int override);
+static int nfsrv_access(struct vnode *, int, struct ucred *, int,
+ struct thread *, int);
static void nfsrvw_coalesce(struct nfsrv_descript *,
struct nfsrv_descript *);
@@ -158,6 +158,32 @@ ndclear(struct nameidata *nd)
}
/*
+ * Takes two vfslocked integers and returns with at most one
+ * reference to giant. The return value indicates whether giant
+ * is held by either lock. This simplifies nfsrv ops by allowing
+ * them to track only one vfslocked var.
+ */
+static __inline int
+nfsrv_lockedpair(int vfs1, int vfs2)
+{
+
+ if (vfs1 && vfs2)
+ VFS_UNLOCK_GIANT(vfs2);
+
+ return (vfs1 | vfs2);
+}
+
+static __inline int
+nfsrv_lockedpair_nd(int vfs1, struct nameidata *nd)
+{
+ int vfs2;
+
+ vfs2 = NDHASGIANT(nd);
+
+ return nfsrv_lockedpair(vfs1, vfs2);
+}
+
+/*
* nfs v3 access service
*/
int
@@ -180,26 +206,21 @@ nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
int v3 = (nfsd->nd_flag & ND_NFSV3);
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
if (!v3)
panic("nfsrv3_access: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- NFSD_UNLOCK();
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (error) {
- NFSD_LOCK();
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(1, NULL);
error = 0;
goto nfsmout;
}
nfsmode = fxdr_unsigned(u_int32_t, *tl);
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if ((nfsmode & NFSV3ACCESS_READ) &&
nfsrv_access(vp, VREAD, cred, rdonly, td, 0))
nfsmode &= ~NFSV3ACCESS_READ;
@@ -220,22 +241,15 @@ nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsmode &= ~testmode;
getret = VOP_GETATTR(vp, vap, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, vap);
tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(nfsmode);
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -261,25 +275,20 @@ nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mbuf *mb, *mreq;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp, nam,
+ &rdonly, TRUE);
if (error) {
- NFSD_LOCK();
nfsm_reply(0);
error = 0;
goto nfsmout;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = VOP_GETATTR(vp, vap, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
if (error) {
error = 0;
@@ -291,14 +300,9 @@ nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
/* fall through */
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -327,14 +331,13 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mbuf *mb, *mreq;
struct timespec guard;
struct mount *mp = NULL;
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
error = ESTALE;
goto out;
@@ -342,9 +345,7 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
VATTR_NULL(vap);
- NFSD_LOCK();
if (v3) {
nfsm_srvsattr(vap);
tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
@@ -383,14 +384,14 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
}
- NFSD_UNLOCK();
/*
* Now that we have all the fields, lets do it.
*/
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &tvfslocked, cred, slp,
+ nam, &rdonly, TRUE);
+ vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
if (error) {
- NFSD_LOCK();
nfsm_reply(2 * NFSX_UNSIGNED);
if (v3)
nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
@@ -402,7 +403,6 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
* vp now an active resource, pay careful attention to cleanup
*/
if (v3) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = preat_ret = VOP_GETATTR(vp, &preat, cred, td);
if (!error && gcheck &&
(preat.va_ctime.tv_sec != guard.tv_sec ||
@@ -410,16 +410,13 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = NFSERR_NOT_SYNC;
if (error) {
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_WCCDATA(v3));
if (v3)
nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
error = 0;
goto nfsmout;
}
- VFS_UNLOCK_GIANT(vfslocked);
}
/*
@@ -435,32 +432,19 @@ nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
if (vp->v_type == VDIR) {
error = EISDIR;
goto out;
- } else {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
- td, 0)) != 0) {
- VFS_UNLOCK_GIANT(vfslocked);
- goto out;
- }
- VFS_UNLOCK_GIANT(vfslocked);
- }
+ } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
+ td, 0)) != 0)
+ goto out;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = VOP_SETATTR(vp, vap, cred, td);
postat_ret = VOP_GETATTR(vp, vap, cred, td);
- VFS_UNLOCK_GIANT(vfslocked);
if (!error)
error = postat_ret;
out:
- NFSD_UNLOCK_ASSERT();
- if (vp != NULL) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp != NULL)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- }
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_WCCORFATTR(v3));
if (v3) {
nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
@@ -473,14 +457,10 @@ out:
/* fall through */
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(mp);
if (vp)
vput(vp);
vn_finished_write(mp);
VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
return(error);
}
@@ -505,11 +485,12 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
struct mbuf *mb, *mreq;
struct vattr va, dirattr, *vap = &va;
-
- NFSD_LOCK_ASSERT();
+ int tvfslocked;
+ int vfslocked;
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@@ -519,27 +500,21 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART | MPSAFE;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirattr, &dirattr_ret, td, pubflag);
- NFSD_UNLOCK();
+ vfslocked = NDHASGIANT(&nd);
/*
* namei failure, only dirp to cleanup. Clear out garbarge from
* structure in case macros jump to nfsmout.
- *
- * XXXRW: For now, use Giant unconditionally during name lookup,
- * rather than deal with complexity of conditional Giant acqusition
- * as moving across the name space.
*/
- 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);
@@ -575,13 +550,14 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfs_pub.np_index;
ind.ni_startdir = nd.ni_vp;
VREF(ind.ni_startdir);
-
+ ind.ni_cnd.cn_flags &= ~GIANTHELD;
+ tvfslocked = VFS_LOCK_GIANT(ind.ni_startdir->v_mount);
+ if (tvfslocked)
+ nd.ni_cnd.cn_flags |= GIANTHELD;
error = lookup(&ind);
ind.ni_dvp = NULL;
- if (ind.ni_cnd.cn_flags & GIANTHELD) {
- mtx_unlock(&Giant);
- ind.ni_cnd.cn_flags &= ~GIANTHELD;
- }
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &ind);
+ ind.ni_cnd.cn_flags &= ~GIANTHELD;
if (error == 0) {
/*
@@ -618,8 +594,6 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
*/
if (error) {
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
nfsm_reply(NFSX_POSTOPATTR(v3));
if (v3)
nfsm_srvpostop_attr(dirattr_ret, &dirattr);
@@ -644,8 +618,6 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
ndp->ni_vp = NULL;
ndp->ni_startdir = NULL;
dirp = NULL;
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
if (error) {
if (v3)
@@ -663,20 +635,16 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
nfsmout:
- NFSD_LOCK_ASSERT();
if (ndp->ni_vp || dirp || ndp->ni_startdir) {
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
if (ndp->ni_vp)
vput(ndp->ni_vp);
if (dirp)
vrele(dirp);
if (ndp->ni_startdir)
vrele(ndp->ni_startdir);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
}
NDFREE(&nd, NDF_ONLY_PNBUF);
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -706,16 +674,14 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct uio io, *uiop = &io;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
#ifndef nolint
mp = NULL;
#endif
mp3 = NULL;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
len = 0;
i = 0;
while (len < NFS_MAXPATHLEN) {
@@ -745,16 +711,15 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
uiop->uio_rw = UIO_READ;
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_td = NULL;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (error) {
- NFSD_LOCK();
nfsm_reply(2 * NFSX_UNSIGNED);
if (v3)
nfsm_srvpostop_attr(1, NULL);
error = 0;
goto nfsmout;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if (vp->v_type != VLNK) {
if (v3)
error = EINVAL;
@@ -764,9 +729,7 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = VOP_READLINK(vp, uiop, cred);
getret = VOP_GETATTR(vp, &attr, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
if (v3)
nfsm_srvpostop_attr(getret, &attr);
@@ -784,16 +747,11 @@ nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
mb->m_next = mp3;
mp3 = NULL;
nfsmout:
- NFSD_LOCK_ASSERT();
if (mp3)
m_freem(mp3);
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -829,9 +787,9 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
int ioflag = 0;
int vfslocked;
- NFSD_LOCK_ASSERT();
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (v3) {
@@ -842,18 +800,17 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
off = (off_t)fxdr_unsigned(u_int32_t, *tl);
}
nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
- NFSD_UNLOCK();
/*
* Reference vp. If an error occurs, vp will be invalid, but we
* have to NULL it just in case. The macros might goto nfsmout
* as well.
*/
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- TRUE);
+
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (error) {
vp = NULL;
- NFSD_LOCK();
nfsm_reply(2 * NFSX_UNSIGNED);
if (v3)
nfsm_srvpostop_attr(1, NULL);
@@ -867,27 +824,24 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
else
error = (vp->v_type == VDIR) ? EISDIR : EACCES;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if (!error) {
- if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1))
- != 0)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1);
+ if ((error = nfsrv_access(vp, VREAD, cred, rdonly,
+ td, 1)) != 0)
+ error = nfsrv_access(vp, VEXEC, cred,
+ rdonly, td, 1);
}
getret = VOP_GETATTR(vp, vap, cred, td);
if (!error)
error = getret;
if (error) {
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_POSTOPATTR(v3));
if (v3)
nfsm_srvpostop_attr(getret, vap);
error = 0;
goto nfsmout;
}
- VFS_UNLOCK_GIANT(vfslocked);
/*
* Calculate byte count to read
@@ -900,7 +854,6 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
else
cnt = reqlen;
- NFSD_LOCK();
/*
* Calculate seqcount for heuristic
*/
@@ -967,7 +920,6 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
fp = (struct nfs_fattr *)tl;
tl += (NFSX_V2FATTR / sizeof (u_int32_t));
}
- NFSD_UNLOCK();
len = left = nfsm_rndup(cnt);
if (cnt > 0) {
/*
@@ -1014,7 +966,6 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
uiop->uio_resid = len;
uiop->uio_rw = UIO_READ;
uiop->uio_segflg = UIO_SYSSPACE;
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
off = uiop->uio_offset;
nh->nh_nextr = off;
@@ -1024,8 +975,6 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = getret;
m_freem(mreq);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
vp = NULL;
nfsm_reply(NFSX_POSTOPATTR(v3));
if (v3)
@@ -1033,15 +982,10 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = 0;
goto nfsmout;
}
- } else {
+ } else
uiop->uio_resid = 0;
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- }
- VFS_ASSERT_GIANT(vp->v_mount);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_srvfillattr(vap, fp);
tlen = len - uiop->uio_resid;
cnt = cnt < tlen ? cnt : tlen;
@@ -1057,14 +1001,9 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
*tl = txdr_unsigned(cnt);
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -1099,11 +1038,11 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct uio io, *uiop = &io;
off_t off;
struct mount *mntp = NULL;
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
if (mrep == NULL) {
*mrq = NULL;
error = 0;
@@ -1111,27 +1050,20 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
error = ESTALE;
- NFSD_LOCK();
goto ereply;
}
vfslocked = VFS_LOCK_GIANT(mntp);
(void) vn_start_write(NULL, &mntp, V_WAIT);
vfs_rel(mntp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
if (v3) {
- NFSD_LOCK();
tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
- NFSD_UNLOCK();
off = fxdr_hyper(tl);
tl += 3;
stable = fxdr_unsigned(int, *tl++);
} else {
- NFSD_LOCK();
tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
- NFSD_UNLOCK();
off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
tl += 2;
if (nfs_async)
@@ -1172,46 +1104,36 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
if (len > NFS_MAXDATA || len < 0 || i < len) {
error = EIO;
- NFSD_LOCK();
nfsm_reply(2 * NFSX_UNSIGNED);
if (v3)
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
error = 0;
goto nfsmout;
}
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
- TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &tvfslocked, cred, slp,
+ nam, &rdonly, TRUE);
+ vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
if (error) {
vp = NULL;
- NFSD_LOCK();
nfsm_reply(2 * NFSX_UNSIGNED);
if (v3)
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
error = 0;
goto nfsmout;
}
- if (v3) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (v3)
forat_ret = VOP_GETATTR(vp, &forat, cred, td);
- VFS_UNLOCK_GIANT(vfslocked);
- }
if (vp->v_type != VREG) {
if (v3)
error = EINVAL;
else
error = (vp->v_type == VDIR) ? EISDIR : EACCES;
}
- if (!error) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (!error)
error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
- VFS_UNLOCK_GIANT(vfslocked);
- }
if (error) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_WCCDATA(v3));
if (v3)
nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
@@ -1252,23 +1174,17 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_td = NULL;
uiop->uio_offset = off;
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = VOP_WRITE(vp, uiop, ioflags, cred);
/* XXXRW: unlocked write. */
nfsrvstats.srvvop_writes++;
FREE((caddr_t)iv, M_TEMP);
- } else
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- VFS_ASSERT_GIANT(vp->v_mount);
+ }
aftat_ret = VOP_GETATTR(vp, vap, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
if (!error)
error = aftat_ret;
- NFSD_LOCK();
ereply:
- NFSD_LOCK_ASSERT();
nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
if (v3) {
@@ -1302,14 +1218,10 @@ ereply:
}
error = 0;
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(mntp);
if (vp)
vput(vp);
vn_finished_write(mntp);
VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
return(error);
}
@@ -1324,8 +1236,6 @@ nfsrv_samecred(struct ucred *cr1, struct ucred *cr2)
{
int i;
- NFSD_LOCK_DONTCARE();
-
if (cr1->cr_uid != cr2->cr_uid)
return (0);
if (cr1->cr_ngroups != cr2->cr_ngroups)
@@ -1366,10 +1276,9 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
struct uio io, *uiop = &io;
u_quad_t cur_usec;
struct mount *mntp = NULL;
+ int mvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
#ifndef nolint
i = 0;
@@ -1439,7 +1348,6 @@ nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
}
if (len > NFS_MAXDATA || len < 0 || i < len) {
nfsmout:
- NFSD_LOCK_ASSERT();
m_freem(mrep);
error = EIO;
nfsm_writereply(2 * NFSX_UNSIGNED);
@@ -1520,16 +1428,12 @@ loop1:
nfsd->nd_mrep = NULL;
cred = nfsd->nd_cr;
v3 = (nfsd->nd_flag & ND_NFSV3);
- NFSD_UNLOCK();
forat_ret = aftat_ret = 1;
- error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
- nfsd->nd_nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, &vfslocked, cred,
+ slp, nfsd->nd_nam, &rdonly, TRUE);
if (!error) {
- if (v3) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (v3)
forat_ret = VOP_GETATTR(vp, &forat, cred, td);
- VFS_UNLOCK_GIANT(vfslocked);
- }
if (vp->v_type != VREG) {
if (v3)
error = EINVAL;
@@ -1539,9 +1443,9 @@ loop1:
} else {
vp = NULL;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if (!error)
- error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
+ error = nfsrv_access(vp, VWRITE, cred, rdonly,
+ td, 1);
if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
ioflags = IO_NODELOCKED;
else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
@@ -1574,12 +1478,14 @@ loop1:
}
mp = mp->m_next;
}
+ mvfslocked = 0;
if (!error) {
if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
VOP_UNLOCK(vp, 0, td);
error = vn_start_write(NULL, &mntp, V_WAIT);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
}
+ mvfslocked = VFS_LOCK_GIANT(mntp);
}
if (!error) {
error = VOP_WRITE(vp, uiop, ioflags, cred);
@@ -1587,6 +1493,7 @@ loop1:
nfsrvstats.srvvop_writes++;
vn_finished_write(mntp);
}
+ VFS_UNLOCK_GIANT(mvfslocked);
FREE((caddr_t)iov, M_TEMP);
}
m_freem(mrep);
@@ -1596,12 +1503,10 @@ loop1:
vp = NULL;
}
VFS_UNLOCK_GIANT(vfslocked);
-
/*
* Loop around generating replies for all write rpcs that have
* now been completed.
*/
- NFSD_LOCK();
swp = nfsd;
do {
NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
@@ -1664,7 +1569,6 @@ loop1:
* Search for a reply to return.
*/
s = splsoftclock();
- NFSD_LOCK_ASSERT();
LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
if (nfsd->nd_mreq) {
NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
@@ -1692,8 +1596,6 @@ 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);
@@ -1759,11 +1661,11 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
u_quad_t tempsize;
u_char cverf[NFSX_V3CREATEVERF];
struct mount *mp = NULL;
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
#ifndef nolint
rdev = 0;
#endif
@@ -1771,22 +1673,18 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
error = ESTALE;
- NFSD_LOCK();
- goto ereply_locked;
+ goto ereply;
}
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE;
/*
* Call namei and do initial cleanup to get a few things
@@ -1799,12 +1697,9 @@ 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);
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
if (dirp && !v3) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(dirp->v_mount);
vrele(dirp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
dirp = NULL;
}
if (error) {
@@ -1848,12 +1743,10 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
exclusive_flag = 1;
break;
};
- NFSD_UNLOCK();
vap->va_type = VREG;
} else {
sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
- NFSD_UNLOCK();
if (vap->va_type == VNON)
vap->va_type = VREG;
vap->va_mode = nfstov_mode(sp->sa_mode);
@@ -1880,12 +1773,7 @@ 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.
- *
- * XXXRW: For now acquire Giant unconditionally during create to
- * avoid interactions between Giant for ndvp and Giant for vp if it
- * already exists.
*/
- mtx_lock(&Giant); /* VFS */
if (nd.ni_vp == NULL) {
if (vap->va_mode == (mode_t)VNOVAL)
vap->va_mode = 0;
@@ -1932,7 +1820,6 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
*/
vput(nd.ni_dvp);
nd.ni_dvp = NULL;
-
/*
* Setup for lookup.
*
@@ -1943,13 +1830,13 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
nd.ni_cnd.cn_thread = td;
nd.ni_cnd.cn_cred = cred;
-
+ tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
+ if (tvfslocked)
+ nd.ni_cnd.cn_flags |= GIANTHELD;
error = lookup(&nd);
nd.ni_dvp = NULL;
- if (nd.ni_cnd.cn_flags & GIANTHELD) {
- mtx_unlock(&Giant);
- nd.ni_cnd.cn_flags &= ~GIANTHELD;
- }
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
+ nd.ni_cnd.cn_flags &= ~GIANTHELD;
if (error)
goto ereply;
@@ -1962,8 +1849,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
} else {
if (vap->va_size != -1) {
- error = nfsrv_access(nd.ni_vp, VWRITE, cred,
- (nd.ni_cnd.cn_flags & RDONLY), td, 0);
+ error = nfsrv_access(nd.ni_vp, VWRITE,
+ cred, (nd.ni_cnd.cn_flags & RDONLY), td, 0);
if (!error) {
tempsize = vap->va_size;
VATTR_NULL(vap);
@@ -2006,11 +1893,6 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
}
ereply:
- NFSD_UNLOCK_ASSERT();
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
-ereply_locked:
- NFSD_LOCK_ASSERT();
nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
if (v3) {
if (!error) {
@@ -2027,9 +1909,6 @@ ereply_locked:
error = 0;
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
if (nd.ni_dvp) {
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
@@ -2046,8 +1925,7 @@ nfsmout:
vrele(dirp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -2076,33 +1954,29 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
fhandle_t *fhp;
struct mount *mp = NULL;
int v3 = (nfsd->nd_flag & ND_NFSV3);
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
if (!v3)
panic("nfsrv_mknod: v3 proc called on a v2 connection");
ndclear(&nd);
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
error = ESTALE;
- NFSD_LOCK();
goto ereply;
}
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE;
/*
* Handle nfs_namei() call. If an error occurs, the nd structure
@@ -2112,23 +1986,17 @@ nfsrv_mknod(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);
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
if (error) {
nfsm_reply(NFSX_WCCDATA(1));
nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
error = 0;
goto nfsmout;
}
-
- /*
- * XXXRW: For now, acquire Giant unconditionally to avoid complexity
- * of dealing with Giant separately for dvp and vp.
- */
tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
vtyp = nfsv3tov_type(*tl);
if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
- NFSD_UNLOCK();
error = NFSERR_BADTYPE;
- mtx_lock(&Giant); /* VFS */
goto out;
}
VATTR_NULL(vap);
@@ -2144,16 +2012,12 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
* Iff doesn't exist, create it.
*/
if (nd.ni_vp) {
- NFSD_UNLOCK();
error = EEXIST;
- mtx_lock(&Giant); /* VFS */
goto out;
}
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;
@@ -2181,13 +2045,13 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
nd.ni_cnd.cn_thread = td;
nd.ni_cnd.cn_cred = td->td_ucred;
-
+ tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
+ if (tvfslocked)
+ nd.ni_cnd.cn_flags |= GIANTHELD;
error = lookup(&nd);
nd.ni_dvp = NULL;
- if (nd.ni_cnd.cn_flags & GIANTHELD) {
- mtx_unlock(&Giant);
- nd.ni_cnd.cn_flags &= ~GIANTHELD;
- }
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
+ nd.ni_cnd.cn_flags &= ~GIANTHELD;
if (error)
goto out;
@@ -2199,8 +2063,6 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
* send response, cleanup, return.
*/
out:
- GIANT_REQUIRED;
- NFSD_UNLOCK_ASSERT();
vp = nd.ni_vp;
if (!error) {
bzero((caddr_t)fhp, sizeof(nfh));
@@ -2231,10 +2093,7 @@ out:
diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
VOP_UNLOCK(dirp, 0, td);
}
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
ereply:
- NFSD_LOCK_ASSERT();
nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
if (v3) {
if (!error) {
@@ -2243,16 +2102,10 @@ ereply:
}
nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
}
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(mp);
vn_finished_write(mp);
VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
return (0);
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
if (nd.ni_dvp) {
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
@@ -2267,8 +2120,7 @@ nfsmout:
vrele(nd.ni_startdir);
NDFREE(&nd, NDF_ONLY_PNBUF);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -2295,33 +2147,27 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mount *mp = NULL;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- NFSD_UNLOCK();
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
error = ESTALE;
- NFSD_LOCK();
goto ereply;
}
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = DELETE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
+ nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | MPSAFE;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
+ vfslocked = NDHASGIANT(&nd);
if (dirp && !v3) {
vrele(dirp);
dirp = NULL;
@@ -2339,7 +2185,6 @@ nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
goto out;
}
out:
- NFSD_UNLOCK_ASSERT();
if (!error) {
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2368,19 +2213,13 @@ out:
vrele(dirp);
dirp = NULL;
}
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
ereply:
- NFSD_LOCK_ASSERT();
nfsm_reply(NFSX_WCCDATA(v3));
if (v3) {
nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
error = 0;
}
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp) {
if (nd.ni_dvp == nd.ni_vp)
@@ -2391,8 +2230,7 @@ nfsmout:
if (nd.ni_vp)
vput(nd.ni_vp);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -2422,9 +2260,8 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mount *mp = NULL;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
#ifndef nolint
fvp = NULL;
#endif
@@ -2439,17 +2276,13 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
ndclear(&tond);
nfsm_srvmtofh(ffhp);
- NFSD_UNLOCK();
if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
error = ESTALE;
- NFSD_LOCK();
goto out1;
}
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
/*
* Remember our original uid so that we can reset cr_uid before
@@ -2458,15 +2291,12 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
saved_uid = cred->cr_uid;
fromnd.ni_cnd.cn_cred = cred;
fromnd.ni_cnd.cn_nameiop = DELETE;
- fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
+ fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART | MPSAFE;
error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
&dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE);
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &fromnd);
if (fdirp && !v3) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(fdirp->v_mount);
vrele(fdirp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
fdirp = NULL;
}
if (error) {
@@ -2484,20 +2314,16 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
cred->cr_uid = saved_uid;
tond.ni_cnd.cn_cred = cred;
tond.ni_cnd.cn_nameiop = RENAME;
- tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
+ tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | MPSAFE;
error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
&dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE);
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &tond);
if (tdirp && !v3) {
vrele(tdirp);
tdirp = NULL;
}
- if (error) {
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ if (error)
goto out1;
- }
tdvp = tond.ni_dvp;
tvp = tond.ni_vp;
@@ -2554,8 +2380,6 @@ nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
fromnd.ni_cnd.cn_namelen))
error = -1;
out:
- GIANT_REQUIRED;
- NFSD_UNLOCK_ASSERT();
if (!error) {
/*
* The VOP_RENAME function releases all vnode references &
@@ -2577,16 +2401,10 @@ out:
error = 0;
}
/* fall through */
-
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
out1:
- NFSD_LOCK_ASSERT();
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);
@@ -2608,8 +2426,6 @@ 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);
}
@@ -2620,9 +2436,6 @@ nfsmout:
/*
* Clear out tond related fields
*/
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
if (tond.ni_dvp) {
if (tond.ni_dvp == tond.ni_vp)
vrele(tond.ni_dvp);
@@ -2650,8 +2463,7 @@ nfsmout:
vrele(fromnd.ni_vp);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -2676,12 +2488,12 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsfh_t nfh, dnfh;
fhandle_t *fhp, *dfhp;
struct mount *mp = NULL;
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
+ vfslocked = 0;
fhp = &nfh.fh_generic;
dfhp = &dnfh.fh_generic;
@@ -2690,17 +2502,15 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = ESTALE;
goto ereply;
}
- NFSD_UNLOCK();
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvmtofh(dfhp);
nfsm_srvnamesiz(len);
- error = nfsrv_fhtovp_locked(fhp, TRUE, &vp, cred, slp, nam, &rdonly,
- TRUE);
+ error = nfsrv_fhtovp(fhp, TRUE, &vp, &tvfslocked, cred, slp,
+ nam, &rdonly, TRUE);
+ vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
if (error) {
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
if (v3) {
@@ -2711,8 +2521,6 @@ 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) {
@@ -2722,13 +2530,10 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
VOP_UNLOCK(vp, 0, td);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT;
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ nd.ni_cnd.cn_flags = LOCKPARENT | MPSAFE | MPSAFE;
error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
if (dirp && !v3) {
vrele(dirp);
dirp = NULL;
@@ -2782,10 +2587,7 @@ out2:
VOP_UNLOCK(dirp, 0, td);
}
}
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
ereply:
- NFSD_LOCK_ASSERT();
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
if (v3) {
nfsm_srvpostop_attr(getret, &at);
@@ -2795,9 +2597,6 @@ ereply:
/* fall through */
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
NDFREE(&nd, NDF_ONLY_PNBUF);
if (vp)
vput(vp);
@@ -2812,8 +2611,7 @@ nfsmout:
if (nd.ni_vp)
vrele(nd.ni_vp);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -2842,46 +2640,35 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsfh_t nfh;
fhandle_t *fhp;
struct mount *mp = NULL;
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
+ vfslocked = 0;
- /*
- * XXXRW: For now, unconditionally acquire Giant in several places to
- * avoid complexity of unwinding separately when several vnodes are
- * in flight.
- */
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
error = ESTALE;
goto out;
}
- NFSD_UNLOCK();
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
+ nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | MPSAFE;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
if (error == 0) {
VATTR_NULL(vap);
if (v3)
nfsm_srvsattr(vap);
nfsm_srvpathsiz(len2);
}
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
if (dirp && !v3) {
vrele(dirp);
dirp = NULL;
@@ -2941,13 +2728,13 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
nd.ni_cnd.cn_thread = td;
nd.ni_cnd.cn_cred = cred;
-
+ tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
+ if (tvfslocked)
+ nd.ni_cnd.cn_flags |= GIANTHELD;
error = lookup(&nd);
nd.ni_dvp = NULL;
- if (nd.ni_cnd.cn_flags & GIANTHELD) {
- mtx_unlock(&Giant);
- nd.ni_cnd.cn_flags &= ~GIANTHELD;
- }
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
+ nd.ni_cnd.cn_flags &= ~GIANTHELD;
if (error == 0) {
bzero((caddr_t)fhp, sizeof(nfh));
@@ -2962,7 +2749,6 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
}
}
out:
- NFSD_UNLOCK_ASSERT();
/*
* These releases aren't strictly required, does even doing them
* make any sense? XXX can nfsm_reply() block?
@@ -2980,8 +2766,6 @@ 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) {
@@ -2994,9 +2778,6 @@ out:
/* fall through */
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp) {
if (nd.ni_dvp == nd.ni_vp)
@@ -3014,8 +2795,7 @@ nfsmout:
FREE(pathcp, M_TEMP);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -3046,42 +2826,29 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mount *mp = NULL;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
+ vfslocked = 0;
- /*
- * XXXRW: For now, unconditionally acquire Giant so as to avoid the
- * complexity of tracking it for several in-flight vnodes.
- */
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
error = ESTALE;
goto out;
}
- NFSD_UNLOCK();
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT;
+ nd.ni_cnd.cn_flags = LOCKPARENT | MPSAFE;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
if (dirp && !v3) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(dirp->v_mount);
vrele(dirp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
dirp = NULL;
}
if (error) {
@@ -3104,8 +2871,6 @@ 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);
@@ -3135,7 +2900,6 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
}
out:
- NFSD_UNLOCK_ASSERT();
if (dirp) {
if (dirp == nd.ni_dvp) {
diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
@@ -3161,8 +2925,6 @@ 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) {
@@ -3180,9 +2942,6 @@ out:
/* fall through */
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
if (nd.ni_dvp) {
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp == nd.ni_vp && vpexcl)
@@ -3199,8 +2958,7 @@ nfsmout:
if (dirp)
vrele(dirp);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -3227,10 +2985,9 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mount *mp = NULL;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
ndclear(&nd);
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@@ -3238,24 +2995,18 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = ESTALE;
goto out;
}
- NFSD_UNLOCK();
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
nfsm_srvnamesiz(len);
nd.ni_cnd.cn_cred = cred;
nd.ni_cnd.cn_nameiop = DELETE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
+ nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | MPSAFE;
error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
&dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
+ vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
if (dirp && !v3) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(dirp->v_mount);
vrele(dirp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
dirp = NULL;
}
if (error) {
@@ -3286,13 +3037,7 @@ out:
/*
* Issue or abort op. Since SAVESTART is not set, path name
* component is freed by the VOP after either.
- *
- * XXXRW: For now, acquire Giant unconditionally to avoid the
- * complexity of unwinding Giant for several vnodes in flight.
*/
- NFSD_LOCK_ASSERT();
- 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);
@@ -3317,8 +3062,6 @@ out:
VOP_UNLOCK(dirp, 0, td);
}
}
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
nfsm_reply(NFSX_WCCDATA(v3));
error = 0;
if (v3)
@@ -3326,9 +3069,6 @@ out:
/* fall through */
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- mtx_lock(&Giant); /* VFS */
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp) {
if (nd.ni_dvp == nd.ni_vp)
@@ -3342,8 +3082,7 @@ nfsmout:
vrele(dirp);
vn_finished_write(mp);
- mtx_unlock(&Giant); /* VFS */
- NFSD_LOCK();
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -3414,9 +3153,8 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
if (v3) {
@@ -3430,7 +3168,6 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
toff = fxdr_unsigned(u_quad_t, *tl++);
verf = 0; /* shut up gcc */
}
- NFSD_UNLOCK();
off = toff;
cnt = fxdr_unsigned(int, *tl);
siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
@@ -3440,16 +3177,14 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
if (siz > xfer)
siz = xfer;
fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (!error && vp->v_type != VDIR) {
error = ENOTDIR;
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
}
if (error) {
- NFSD_LOCK();
nfsm_reply(NFSX_UNSIGNED);
if (v3)
nfsm_srvpostop_attr(getret, &at);
@@ -3460,7 +3195,6 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
/*
* Obtain lock on vnode for this section of the code
*/
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if (v3) {
error = getret = VOP_GETATTR(vp, &at, cred, td);
#if 0
@@ -3475,8 +3209,6 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
if (error) {
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
vp = NULL;
nfsm_reply(NFSX_POSTOPATTR(v3));
if (v3)
@@ -3491,7 +3223,6 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
*/
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
again:
- NFSD_UNLOCK_ASSERT();
iv.iov_base = rbuf;
iv.iov_len = fullsiz;
io.uio_iov = &iv;
@@ -3519,12 +3250,10 @@ again:
VOP_UNLOCK(vp, 0, td);
if (error) {
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
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);
@@ -3540,9 +3269,7 @@ again:
*/
if (siz == 0) {
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2 * NFSX_UNSIGNED);
if (v3) {
@@ -3590,8 +3317,6 @@ again:
goto again;
}
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
if (v3) {
@@ -3668,11 +3393,7 @@ again:
cookiep++;
ncookies--;
}
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
vp = NULL;
nfsm_clget;
*tl = nfsrv_nfs_false;
@@ -3692,14 +3413,9 @@ again:
FREE((caddr_t)cookies, M_TEMP);
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -3734,9 +3450,8 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
int v3 = (nfsd->nd_flag & ND_NFSV3);
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
if (!v3)
panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
@@ -3751,28 +3466,24 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
off = toff;
siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
xfer = NFS_SRVMAXDATA(nfsd);
- NFSD_UNLOCK();
if (cnt > xfer)
cnt = xfer;
if (siz > xfer)
siz = xfer;
fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (!error && vp->v_type != VDIR) {
error = ENOTDIR;
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
}
if (error) {
- NFSD_LOCK();
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = getret = VOP_GETATTR(vp, &at, cred, td);
#if 0
/*
@@ -3785,8 +3496,6 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0);
if (error) {
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
vp = NULL;
nfsm_reply(NFSX_V3POSTOPATTR);
nfsm_srvpostop_attr(getret, &at);
@@ -3796,7 +3505,6 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
VOP_UNLOCK(vp, 0, td);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
again:
- NFSD_UNLOCK_ASSERT();
iv.iov_base = rbuf;
iv.iov_len = fullsiz;
io.uio_iov = &iv;
@@ -3822,12 +3530,10 @@ again:
error = getret;
if (error) {
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
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;
@@ -3842,8 +3548,6 @@ again:
*/
if (siz == 0) {
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
vp = NULL;
nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
2 * NFSX_UNSIGNED);
@@ -3897,23 +3601,19 @@ again:
EOPNOTSUPP) {
error = NFSERR_NOTSUPP;
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
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);
- VFS_UNLOCK_GIANT(vfslocked);
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);
@@ -3922,8 +3622,6 @@ again:
bp = bpos;
be = bp + M_TRAILINGSPACE(mp);
- NFSD_UNLOCK();
- VFS_LOCK_GIANT(vp->v_mount);
/* Loop through the records and build reply */
while (cpos < cend && ncookies > 0) {
if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
@@ -3986,16 +3684,16 @@ again:
fl.fl_off.nfsuquad[0] = 0;
fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
- nfsm_clget_nolock;
+ nfsm_clget;
*tl = nfsrv_nfs_true;
bp += NFSX_UNSIGNED;
- nfsm_clget_nolock;
+ nfsm_clget;
*tl = 0;
bp += NFSX_UNSIGNED;
- nfsm_clget_nolock;
+ nfsm_clget;
*tl = txdr_unsigned(dp->d_fileno);
bp += NFSX_UNSIGNED;
- nfsm_clget_nolock;
+ nfsm_clget;
*tl = txdr_unsigned(nlen);
bp += NFSX_UNSIGNED;
@@ -4003,7 +3701,7 @@ again:
xfer = nlen;
cp = dp->d_name;
while (xfer > 0) {
- nfsm_clget_nolock;
+ nfsm_clget;
if ((bp + xfer) > be)
tsiz = be - bp;
else
@@ -4024,7 +3722,7 @@ again:
xfer = sizeof (struct flrep);
cp = (caddr_t)&fl;
while (xfer > 0) {
- nfsm_clget_nolock;
+ nfsm_clget;
if ((bp + xfer) > be)
tsiz = be - bp;
else
@@ -4037,19 +3735,16 @@ again:
}
}
invalid:
- NFSD_UNLOCK_ASSERT();
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
cookiep++;
ncookies--;
}
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- nfsm_clget_nolock;
+ nfsm_clget;
*tl = nfsrv_nfs_false;
bp += NFSX_UNSIGNED;
- NFSD_LOCK();
nfsm_clget;
if (eofflag)
*tl = nfsrv_nfs_true;
@@ -4064,14 +3759,9 @@ invalid:
FREE((caddr_t)cookies, M_TEMP);
FREE((caddr_t)rbuf, M_TEMP);
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -4097,11 +3787,11 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
u_quad_t off;
struct mount *mp = NULL;
int v3 = (nfsd->nd_flag & ND_NFSV3);
+ int tvfslocked;
int vfslocked;
- NFSD_LOCK_ASSERT();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
if (!v3)
panic("nfsrv_commit: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
@@ -4110,11 +3800,9 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = ESTALE;
goto ereply;
}
- NFSD_UNLOCK();
vfslocked = VFS_LOCK_GIANT(mp);
(void) vn_start_write(NULL, &mp, V_WAIT);
vfs_rel(mp); /* The write holds a ref. */
- VFS_UNLOCK_GIANT(vfslocked);
tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
/*
@@ -4124,15 +3812,15 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
off = fxdr_hyper(tl);
tl += 2;
cnt = fxdr_unsigned(int, *tl);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &tvfslocked, cred, slp,
+ nam, &rdonly, TRUE);
+ vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
if (error) {
- NFSD_LOCK();
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
error = 0;
goto nfsmout;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
for_ret = VOP_GETATTR(vp, &bfor, cred, td);
if (cnt > MAX_COMMIT_COUNT) {
@@ -4220,11 +3908,8 @@ nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
aft_ret = VOP_GETATTR(vp, &aft, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
ereply:
- NFSD_LOCK_ASSERT();
nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
if (!error) {
@@ -4237,14 +3922,10 @@ ereply:
error = 0;
}
nfsmout:
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(mp);
if (vp)
vput(vp);
vn_finished_write(mp);
VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
return(error);
}
@@ -4273,15 +3954,13 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
u_quad_t tval;
int vfslocked;
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
+ vfslocked = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (error) {
- NFSD_LOCK();
nfsm_reply(NFSX_UNSIGNED);
if (v3)
nfsm_srvpostop_attr(getret, &at);
@@ -4289,13 +3968,10 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
goto nfsmout;
}
sf = &statfs;
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = VFS_STATFS(vp->v_mount, sf, td);
getret = VOP_GETATTR(vp, &at, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
if (v3)
nfsm_srvpostop_attr(getret, &at);
@@ -4341,14 +4017,9 @@ nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
}
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -4376,33 +4047,27 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
int v3 = (nfsd->nd_flag & ND_NFSV3);
int vfslocked;
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
if (!v3)
panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (error) {
- NFSD_LOCK();
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
/* 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);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
nfsm_srvpostop_attr(getret, &at);
sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
@@ -4430,14 +4095,9 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
NFSV3FSINFO_CANSETTIME);
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -4464,23 +4124,19 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
int v3 = (nfsd->nd_flag & ND_NFSV3);
int vfslocked;
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
-
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
if (!v3)
panic("nfsrv_pathconf: v3 proc called on a v2 connection");
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
+ error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, cred, slp,
+ nam, &rdonly, TRUE);
if (error) {
- NFSD_LOCK();
nfsm_reply(NFSX_UNSIGNED);
nfsm_srvpostop_attr(getret, &at);
error = 0;
goto nfsmout;
}
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
if (!error)
error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
@@ -4490,9 +4146,7 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
getret = VOP_GETATTR(vp, &at, cred, td);
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
vp = NULL;
- NFSD_LOCK();
nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
nfsm_srvpostop_attr(getret, &at);
if (error) {
@@ -4514,14 +4168,9 @@ nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
pc->pc_caseinsensitive = nfsrv_nfs_false;
pc->pc_casepreserving = nfsrv_nfs_true;
nfsmout:
- NFSD_LOCK_ASSERT();
- if (vp) {
- NFSD_UNLOCK();
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ if (vp)
vput(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- NFSD_LOCK();
- }
+ VFS_UNLOCK_GIANT(vfslocked);
return(error);
}
@@ -4538,12 +4187,9 @@ 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:
- NFSD_LOCK_ASSERT();
return (error);
}
@@ -4560,8 +4206,6 @@ 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;
@@ -4570,7 +4214,6 @@ nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsm_reply(0);
error = 0;
nfsmout:
- NFSD_LOCK_ASSERT();
return (error);
}
@@ -4588,15 +4231,6 @@ nfsmout:
*
* The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
* will return EPERM instead of EACCESS. EPERM is always an error.
- *
- * There are two versions: one called while holding the NFS server lock,
- * which will be dropped and re-acquired, and one called without it.
- *
- * nfsrv_access() assumes that the NFS server lock is not held, but that if
- * Giant is required for the vnode it will already be acquired.
- *
- * nfsrv_access_locked() assumes that the NFS server lock is held, but that
- * it will need to acquire Giant for the vnode.
*/
static int
nfsrv_access(struct vnode *vp, int flags, struct ucred *cred,
@@ -4605,7 +4239,6 @@ nfsrv_access(struct vnode *vp, int flags, struct ucred *cred,
struct vattr vattr;
int error;
- NFSD_UNLOCK_ASSERT();
VFS_ASSERT_GIANT(vp->v_mount);
nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
OpenPOWER on IntegriCloud