diff options
author | jeff <jeff@FreeBSD.org> | 2005-04-13 10:57:13 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2005-04-13 10:57:13 +0000 |
commit | ee55350db0df9355dc355166596611b59aa29ed1 (patch) | |
tree | 5d432596cb8266f5d2e84dafae23a57391276c5b | |
parent | 82691535ee5ae34bb001a324b8a9fd4ddda369e9 (diff) | |
download | FreeBSD-src-ee55350db0df9355dc355166596611b59aa29ed1.zip FreeBSD-src-ee55350db0df9355dc355166596611b59aa29ed1.tar.gz |
- Further simplify lookup; Force all filesystems to relock in the DOTDOT
case. There are bugs in some which didn't unlock in the ISDOTDOT case
to begin with that need to be addressed seperately. This simplifies
things anyway.
- Fix relookup() to prevent it from vrele()'ing the dvp while the vp
is locked. Catch up to other lookup changes.
Sponsored by: Isilon Systems, Inc.
Reported by: Peter Wemm
-rw-r--r-- | sys/kern/vfs_lookup.c | 53 |
1 files changed, 23 insertions, 30 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index ff8ba2d..eaf2fcc 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -592,12 +592,6 @@ unionlookup: printf("found\n"); #endif /* - * In the DOTDOT case dp is unlocked, we relock it here even if we - * may not need it to simplify the code below. - */ - if (cnp->cn_flags & ISDOTDOT) - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); - /* * Take into account any additional components consumed by * the underlying filesystem. */ @@ -746,6 +740,7 @@ relookup(dvp, vpp, cnp) * Setup: break out flag bits into variables. */ wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); + KASSERT(wantparent, ("relookup: parent not wanted.")); rdonly = cnp->cn_flags & RDONLY; cnp->cn_flags &= ~ISSYMLINK; dp = dvp; @@ -826,46 +821,44 @@ relookup(dvp, vpp, cnp) */ return (0); } - /* - * In the DOTDOT case dp is unlocked, we may have to relock it if - * LOCKPARENT is set. Otherwise, unlock the parent. - */ - if ((cnp->cn_flags & (ISDOTDOT | LOCKPARENT)) == - (ISDOTDOT | LOCKPARENT)) - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); - else if ((cnp->cn_flags & (ISDOTDOT | LOCKPARENT)) == 0 && dp != *vpp) - VOP_UNLOCK(dp, 0, td); dp = *vpp; /* - * Check for symbolic link - */ - KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW), - ("relookup: symlink found.\n")); - - /* * Disallow directory write attempts on read-only filesystems. */ if (rdonly && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { + printf("this is it?\n"); + if (dvp == dp) + vrele(dvp); + else + vput(dvp); error = EROFS; - goto bad2; + goto bad; } + /* + * Set the parent lock/ref state to the requested state. + */ + if ((cnp->cn_flags & LOCKPARENT) == 0 && dvp != dp) { + if (wantparent) + VOP_UNLOCK(dvp, 0, td); + else + vput(dvp); + } else if (!wantparent) + vrele(dvp); + /* + * Check for symbolic link + */ + KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW), + ("relookup: symlink found.\n")); + /* ASSERT(dvp == ndp->ni_startdir) */ if (cnp->cn_flags & SAVESTART) VREF(dvp); - if (!wantparent) - vrele(dvp); - if ((cnp->cn_flags & LOCKLEAF) == 0) VOP_UNLOCK(dp, 0, td); return (0); - -bad2: - if (cnp->cn_flags & LOCKPARENT) - VOP_UNLOCK(dvp, 0, td); - vrele(dvp); bad: vput(dp); *vpp = NULL; |