From 3a8bef861f0b1a62ad9f5e2e87a644b9cb5677ab Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 16 Sep 2008 16:18:36 +0000 Subject: - Only set i_offset in the parent directory's i-node during a lookup for non-LOOKUP operations. - Relax a VOP assertion for a DELETE lookup. rename() uses WANTPARENT instead of LOCKPARENT when looking up the source pathname. ufs_rename() uses a relookup() to lock the parent directory when it decides to finally remove the source path. Thus, it is ok for a DELETE with WANTPARENT set instead of LOCKPARENT to use a shared vnode lock rather than an exclusive vnode lock. Reported by: kris (2) Reviewed by: jeff --- sys/ufs/ufs/ufs_lookup.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 8c68742..d296857 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -390,7 +390,6 @@ notfound: endsearch = i_diroff; goto searchloop; } - dp->i_offset = i_offset; if (bp != NULL) brelse(bp); /* @@ -482,13 +481,13 @@ found: if ((flags & ISLASTCN) && nameiop == LOOKUP) dp->i_diroff = i_offset &~ (DIRBLKSIZ - 1); - dp->i_offset = i_offset; /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. */ if (nameiop == DELETE && (flags & ISLASTCN)) { - ASSERT_VOP_ELOCKED(vdp, __FUNCTION__); + if (flags & LOCKPARENT) + ASSERT_VOP_ELOCKED(vdp, __FUNCTION__); /* * Write access to directory required to delete files. */ @@ -500,7 +499,13 @@ found: * and distance past previous entry (if there * is a previous entry in this block) in dp->i_count. * Save directory inode pointer in ndp->ni_dvp for dirremove(). + * + * Technically we shouldn't be setting these in the + * WANTPARENT case (first lookup in rename()), but any + * lookups that will result in directory changes will + * overwrite these. */ + dp->i_offset = i_offset; if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) dp->i_count = 0; else @@ -542,6 +547,7 @@ found: * Careful about locking second inode. * This can only occur if the target is ".". */ + dp->i_offset = i_offset; if (dp->i_number == ino) return (EISDIR); if ((error = VFS_VGET(vdp->v_mount, ino, -- cgit v1.1