- Solve a problem where a vput could be called on an outgoing directory
without Giant held. Do this by tracking the vfslocked state for the directory seperate from the child. This is only important in the case where we cross a mountpoint. Sponsored by: Isilon Systems, Inc. MFC After: 3 days
This commit is contained in:
parent
0ac72424f0
commit
9157b485f0
@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <vm/uma.h>
|
||||
|
||||
#define NAMEI_DIAGNOSTIC 1
|
||||
#define NAMEI_DIAGNOSTIC 1
|
||||
#undef NAMEI_DIAGNOSTIC
|
||||
|
||||
/*
|
||||
@ -352,11 +352,13 @@ lookup(ndp)
|
||||
struct thread *td = cnp->cn_thread;
|
||||
int vfslocked;
|
||||
int tvfslocked;
|
||||
int dvfslocked;
|
||||
|
||||
/*
|
||||
* Setup: break out flag bits into variables.
|
||||
*/
|
||||
vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
|
||||
dvfslocked = 0;
|
||||
ndp->ni_cnd.cn_flags &= ~GIANTHELD;
|
||||
wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
|
||||
KASSERT(cnp->cn_nameiop == LOOKUP || wantparent,
|
||||
@ -623,9 +625,8 @@ unionlookup:
|
||||
if (vfs_busy(mp, 0, 0, td))
|
||||
continue;
|
||||
vput(dp);
|
||||
tvfslocked = VFS_LOCK_GIANT(mp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
vfslocked = tvfslocked;
|
||||
dvfslocked = vfslocked;
|
||||
vfslocked = VFS_LOCK_GIANT(mp);
|
||||
VOP_UNLOCK(ndp->ni_dvp, 0, td);
|
||||
error = VFS_ROOT(mp, cnp->cn_lkflags, &tdp, td);
|
||||
VOP_LOCK(ndp->ni_dvp, cnp->cn_lkflags | LK_RETRY, td);
|
||||
@ -687,6 +688,8 @@ nextname:
|
||||
vput(ndp->ni_dvp);
|
||||
else
|
||||
vrele(ndp->ni_dvp);
|
||||
VFS_UNLOCK_GIANT(dvfslocked);
|
||||
dvfslocked = 0;
|
||||
goto dirloop;
|
||||
}
|
||||
/*
|
||||
@ -706,13 +709,17 @@ nextname:
|
||||
vput(ndp->ni_dvp);
|
||||
else
|
||||
vrele(ndp->ni_dvp);
|
||||
VFS_UNLOCK_GIANT(dvfslocked);
|
||||
dvfslocked = 0;
|
||||
} else if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != dp)
|
||||
VOP_UNLOCK(ndp->ni_dvp, 0, td);
|
||||
|
||||
if ((cnp->cn_flags & LOCKLEAF) == 0)
|
||||
VOP_UNLOCK(dp, 0, td);
|
||||
success:
|
||||
if (vfslocked)
|
||||
if (vfslocked && dvfslocked)
|
||||
VFS_UNLOCK_GIANT(dvfslocked); /* Only need one */
|
||||
if (vfslocked || dvfslocked)
|
||||
ndp->ni_cnd.cn_flags |= GIANTHELD;
|
||||
return (0);
|
||||
|
||||
@ -725,6 +732,7 @@ bad:
|
||||
if (!dpunlocked)
|
||||
vput(dp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
VFS_UNLOCK_GIANT(dvfslocked);
|
||||
ndp->ni_cnd.cn_flags &= ~GIANTHELD;
|
||||
ndp->ni_vp = NULL;
|
||||
return (error);
|
||||
|
Loading…
x
Reference in New Issue
Block a user