- 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
This commit is contained in:
parent
4499aff6ec
commit
37374fc852
@ -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 *);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user