diff options
author | jeff <jeff@FreeBSD.org> | 2007-03-17 18:18:08 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2007-03-17 18:18:08 +0000 |
commit | d43d58ff4578f356c44c4ad57ff2d4c6b2b99a50 (patch) | |
tree | 3cce5e99818314cbc53c7fe494e3fdbfa9017a1e /sys/nfsserver | |
parent | 82143f95ad1b41e027bececf613c3e94f1556ac6 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/nfsserver/nfs.h | 5 | ||||
-rw-r--r-- | sys/nfsserver/nfs_serv.c | 741 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvcache.c | 2 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsock.c | 10 | ||||
-rw-r--r-- | sys/nfsserver/nfs_srvsubs.c | 113 | ||||
-rw-r--r-- | sys/nfsserver/nfs_syscalls.c | 2 | ||||
-rw-r--r-- | sys/nfsserver/nfsm_subs.h | 7 |
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, ¬runc); 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 |