diff options
author | jeff <jeff@FreeBSD.org> | 2005-03-29 10:07:15 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2005-03-29 10:07:15 +0000 |
commit | 4a949bda2b74c7182c22451d4943553ca5005957 (patch) | |
tree | 8f1fccca262dbdec310aa51f13d913fb6d9567e6 /sys/kern/vfs_lookup.c | |
parent | 969761f8daae59964da04616d7b72c868759df58 (diff) | |
download | FreeBSD-src-4a949bda2b74c7182c22451d4943553ca5005957.zip FreeBSD-src-4a949bda2b74c7182c22451d4943553ca5005957.tar.gz |
- Set cn_lkflags to LK_SHARED in the LOOKUP_SHARED case so that we only
acquire shared locks on intermediate directories.
- For the LASTCN, we may have to LK_UPGRADE the parent directory before
we lookup the last component.
- Acquire VFS_ROOT and dp locks based on the cn_lkflag.
Sponsored by: Isilon Systems, Inc.
Diffstat (limited to 'sys/kern/vfs_lookup.c')
-rw-r--r-- | sys/kern/vfs_lookup.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 6b8b806..9177cee 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -360,11 +360,20 @@ lookup(ndp) cnp->cn_nameiop != LOOKUP)) docache = 0; rdonly = cnp->cn_flags & RDONLY; - ndp->ni_dvp = NULL; cnp->cn_flags &= ~ISSYMLINK; + ndp->ni_dvp = NULL; +#ifdef LOOKUP_SHARED + /* + * We use shared locks until we hit the parent of the last cn then + * we adjust based on the requesting flags. + */ + cnp->cn_lkflags = LK_SHARED; +#else + cnp->cn_lkflags = LK_EXCLUSIVE; +#endif dp = ndp->ni_startdir; ndp->ni_startdir = NULLVP; - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td); dirloop: /* @@ -487,7 +496,7 @@ dirloop: vfslocked = VFS_LOCK_GIANT(dp->v_mount); VFS_UNLOCK_GIANT(tvfslocked); VREF(dp); - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td); } } @@ -505,6 +514,20 @@ unionlookup: ndp->ni_dvp = dp; ndp->ni_vp = NULL; ASSERT_VOP_LOCKED(dp, "lookup"); + /* + * If we have a shared lock we may need to upgrade the lock for the + * last operation. + */ + if (VOP_ISLOCKED(dp, td) == LK_SHARED && + (cnp->cn_flags & ISLASTCN) && (cnp->cn_flags & LOCKPARENT)) + vn_lock(dp, LK_UPGRADE|LK_RETRY, td); + /* + * If we're looking up the last component and we need an exclusive + * lock, adjust our lkflags. + */ + if ((cnp->cn_flags & (ISLASTCN|LOCKSHARED|LOCKLEAF)) == + (ISLASTCN|LOCKLEAF)) + cnp->cn_lkflags = LK_EXCLUSIVE; #ifdef NAMEI_DIAGNOSTIC vprint("lookup in", dp); #endif @@ -523,7 +546,7 @@ unionlookup: vfslocked = VFS_LOCK_GIANT(dp->v_mount); VFS_UNLOCK_GIANT(tvfslocked); VREF(dp); - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); + vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td); goto unionlookup; } @@ -604,7 +627,7 @@ unionlookup: continue; VOP_UNLOCK(dp, 0, td); tvfslocked = VFS_LOCK_GIANT(mp); - error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td); + error = VFS_ROOT(mp, cnp->cn_lkflags, &tdp, td); vfs_unbusy(mp, td); if (error) { VFS_UNLOCK_GIANT(tvfslocked); @@ -725,6 +748,7 @@ relookup(dvp, vpp, cnp) rdonly = cnp->cn_flags & RDONLY; cnp->cn_flags &= ~ISSYMLINK; dp = dvp; + cnp->cn_lkflags = LK_EXCLUSIVE; vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); /* |