summaryrefslogtreecommitdiffstats
path: root/sys
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
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')
-rw-r--r--sys/nfsserver/nfs.h5
-rw-r--r--sys/nfsserver/nfs_serv.c741
-rw-r--r--sys/nfsserver/nfs_srvcache.c2
-rw-r--r--sys/nfsserver/nfs_srvsock.c10
-rw-r--r--sys/nfsserver/nfs_srvsubs.c113
-rw-r--r--sys/nfsserver/nfs_syscalls.c2
-rw-r--r--sys/nfsserver/nfsm_subs.h7
7 files changed, 236 insertions, 644 deletions
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index 292584e..72e1204 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -358,11 +358,8 @@ int nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct thread *td, struct mbuf **mrq);
int nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct thread *td, struct mbuf **mrq);
-int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, struct ucred *,
+int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, int *, struct ucred *,
struct nfssvc_sock *, struct sockaddr *, int *, int);
-int nfsrv_fhtovp_locked(fhandle_t *, int, struct vnode **,
- struct ucred *, struct nfssvc_sock *, struct sockaddr *, int *,
- int);
int nfsrv_setpublicfs(struct mount *, struct netexport *,
struct export_args *);
int nfs_ispublicfh(fhandle_t *);
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__));
diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c
index 7d0c126..ca6b8c2 100644
--- a/sys/nfsserver/nfs_srvcache.c
+++ b/sys/nfsserver/nfs_srvcache.c
@@ -218,9 +218,11 @@ loop:
ret = RC_DROPIT;
} else if (rp->rc_flag & RC_REPSTATUS) {
nfsrvstats.srvcache_nonidemdonehits++;
+ NFSD_UNLOCK();
*repp = nfs_rephead(0, nd, rp->rc_status,
&mb, &bpos);
ret = RC_REPLY;
+ NFSD_LOCK();
} else if (rp->rc_flag & RC_REPMBUF) {
nfsrvstats.srvcache_nonidemdonehits++;
NFSD_UNLOCK();
diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c
index eba9cfb..971368f 100644
--- a/sys/nfsserver/nfs_srvsock.c
+++ b/sys/nfsserver/nfs_srvsock.c
@@ -145,13 +145,9 @@ 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;
/*
@@ -164,7 +160,6 @@ 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);
@@ -246,18 +241,13 @@ 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;
}
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 3551b91..b064fb3 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -621,10 +621,11 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
int error, rdonly, linklen;
struct componentname *cnp = &ndp->ni_cnd;
int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0;
+ int dvfslocked;
+ int vfslocked;
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
-
+ vfslocked = 0;
+ dvfslocked = 0;
*retdirp = NULL;
cnp->cn_flags |= NOMACCHECK;
cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
@@ -642,14 +643,14 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
md = md->m_next;
if (md == NULL) {
error = EBADRPC;
- goto out_nogiant;
+ goto out;
}
fromcp = mtod(md, caddr_t);
rem = md->m_len;
}
if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
error = EACCES;
- goto out_nogiant;
+ goto out;
}
*tocp++ = *fromcp++;
rem--;
@@ -662,20 +663,17 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
if (rem >= len)
*dposp += len;
else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
- goto out_nogiant;
+ goto out;
}
/*
* Extract and set starting directory.
- *
- * XXXRW: For now, acquire Giant unconditionally to avoid tracking it
- * on multiple vnodes.
*/
- error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
- nam, &rdonly, pubflag);
- mtx_lock(&Giant); /* VFS */
+ error = nfsrv_fhtovp(fhp, FALSE, &dp, &dvfslocked,
+ ndp->ni_cnd.cn_cred, slp, nam, &rdonly, pubflag);
if (error)
goto out;
+ vfslocked = VFS_LOCK_GIANT(dp->v_mount);
if (dp->v_type != VDIR) {
vrele(dp);
error = ENOTDIR;
@@ -753,8 +751,14 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
if (pubflag) {
ndp->ni_rootdir = rootvnode;
ndp->ni_loopcnt = 0;
- if (cnp->cn_pnbuf[0] == '/')
+ if (cnp->cn_pnbuf[0] == '/') {
+ int tvfslocked;
+
+ tvfslocked = VFS_LOCK_GIANT(rootvnode->v_mount);
+ VFS_UNLOCK_GIANT(vfslocked);
dp = rootvnode;
+ vfslocked = tvfslocked;
+ }
} else {
cnp->cn_flags |= NOCROSSMOUNT;
}
@@ -779,7 +783,11 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
* In either case ni_startdir will be dereferenced and NULLed
* out.
*/
+ if (vfslocked)
+ ndp->ni_cnd.cn_flags |= GIANTHELD;
error = lookup(ndp);
+ vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
+ ndp->ni_cnd.cn_flags &= ~GIANTHELD;
if (error)
break;
@@ -888,18 +896,27 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
* cleanup state trivially.
*/
out:
- mtx_unlock(&Giant); /* VFS */
-out_nogiant:
if (error) {
uma_zfree(namei_zone, cnp->cn_pnbuf);
ndp->ni_vp = NULL;
ndp->ni_dvp = NULL;
ndp->ni_startdir = NULL;
cnp->cn_flags &= ~HASBUF;
+ VFS_UNLOCK_GIANT(vfslocked);
+ vfslocked = 0;
} else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
ndp->ni_dvp = NULL;
}
- NFSD_LOCK();
+ /*
+ * This differs from normal namei() in that even on failure we may
+ * return with Giant held due to the dirp return. Make sure we only
+ * have not recursed however. The calling code only expects to drop
+ * one acquire.
+ */
+ if (vfslocked || dvfslocked)
+ ndp->ni_cnd.cn_flags |= GIANTHELD;
+ if (vfslocked && dvfslocked)
+ VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
@@ -914,8 +931,6 @@ 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.
@@ -1064,13 +1079,9 @@ nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
* - get vp and export rights by calling VFS_FHTOVP()
* - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
* - if not lockflag unlock it with VOP_UNLOCK()
- *
- * As this routine may acquire Giant and may sleep, it can't be called with
- * nfsd_mtx. Caller should invoke nfsrv_fhtovp_locked() if the lock is held
- * so that it can be automatically dropped and re-acquired.
*/
int
-nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
+nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp,
struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam,
int *rdonlyp, int pubflag)
{
@@ -1079,13 +1090,12 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
int i;
struct ucred *credanon;
int error, exflags;
- int vfslocked;
#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
struct sockaddr_int *saddr;
#endif
+ int vfslocked;
- NFSD_UNLOCK_ASSERT();
-
+ *vfslockedp = 0;
*vpp = NULL;
if (nfs_ispublicfh(fhp)) {
@@ -1135,28 +1145,13 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
VOP_UNLOCK(*vpp, 0, td);
out:
vfs_rel(mp);
- VFS_UNLOCK_GIANT(vfslocked);
+ if (error) {
+ VFS_UNLOCK_GIANT(vfslocked);
+ } else
+ *vfslockedp = vfslocked;
return (error);
}
-/*
- * Version of nfsrv_fhtovp() that can be called holding nfsd_mtx: it will
- * drop and re-acquire the lock for the caller.
- */
-int
-nfsrv_fhtovp_locked(fhandle_t *fhp, int lockflag, struct vnode **vpp,
- struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam,
- int *rdonlyp, int pubflag)
-{
- int error;
-
- NFSD_LOCK_ASSERT();
- NFSD_UNLOCK();
- error = nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp,
- pubflag);
- NFSD_LOCK();
- return (error);
-}
/*
* WebNFS: check if a filehandle is a public filehandle. For v3, this
@@ -1229,7 +1224,6 @@ nfsrv_errmap(struct nfsrv_descript *nd, int err)
const short *defaulterrp, *errp;
int e;
- NFSD_LOCK_DONTCARE();
if (nd->nd_flag & ND_NFSV3) {
if (nd->nd_procnum <= NFSPROC_COMMIT) {
@@ -1263,8 +1257,6 @@ 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];
@@ -1283,8 +1275,6 @@ nfsrv_setcred(struct ucred *incred, struct ucred *outcred)
{
int i;
- NFSD_LOCK_DONTCARE();
-
bzero((caddr_t)outcred, sizeof (struct ucred));
refcount_init(&outcred->cr_ref, 1);
outcred->cr_uid = incred->cr_uid;
@@ -1303,8 +1293,6 @@ 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);
@@ -1331,8 +1319,6 @@ nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
{
u_int32_t *tl;
- NFSD_LOCK_DONTCARE();
-
tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
return EBADRPC;
@@ -1365,8 +1351,6 @@ nfsm_srvnamesiz0_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
{
u_int32_t *tl;
- NFSD_LOCK_DONTCARE();
-
tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
return EBADRPC;
@@ -1380,26 +1364,17 @@ nfsm_srvnamesiz0_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, int droplock)
+ char **bp, char **be, caddr_t bpos)
{
struct mbuf *nmp;
- NFSD_LOCK_DONTCARE();
-
- if (droplock)
- NFSD_LOCK_ASSERT();
- else
- NFSD_UNLOCK_ASSERT();
+ 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;
@@ -1416,8 +1391,6 @@ 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_nonblock(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
@@ -1445,8 +1418,6 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
u_int32_t *tl;
int toclient = 0;
- NFSD_LOCK_DONTCARE();
-
tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
return EBADRPC;
diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c
index 4c6b7f0..f81900b 100644
--- a/sys/nfsserver/nfs_syscalls.c
+++ b/sys/nfsserver/nfs_syscalls.c
@@ -467,6 +467,7 @@ nfssvc_nfsd(struct thread *td)
procrastinate = nfsrvw_procrastinate_v3;
else
procrastinate = nfsrvw_procrastinate;
+ NFSD_UNLOCK();
if (writes_todo || (!(nd->nd_flag & ND_NFSV3) &&
nd->nd_procnum == NFSPROC_WRITE &&
procrastinate > 0 && !notstarted))
@@ -475,6 +476,7 @@ nfssvc_nfsd(struct thread *td)
else
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
slp, nfsd->nfsd_td, &mreq);
+ NFSD_LOCK();
if (mreq == NULL)
break;
if (error != 0 && error != NFSERR_RETVOID) {
diff --git a/sys/nfsserver/nfsm_subs.h b/sys/nfsserver/nfsm_subs.h
index b605c5d..f2dafc4 100644
--- a/sys/nfsserver/nfsm_subs.h
+++ b/sys/nfsserver/nfsm_subs.h
@@ -161,7 +161,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, int droplock);
+ char **bp, char **be, caddr_t bpos);
#define nfsm_srvfhtom(f, v3) \
nfsm_srvfhtom_xx((f), (v3), &mb, &bpos)
@@ -179,9 +179,6 @@ 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, 1)
-
-#define nfsm_clget_nolock \
- nfsm_clget_xx(&tl, mb, &mp, &bp, &be, bpos, 0)
+ nfsm_clget_xx(&tl, mb, &mp, &bp, &be, bpos)
#endif
OpenPOWER on IntegriCloud