diff options
author | dillon <dillon@FreeBSD.org> | 2001-10-02 02:58:48 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2001-10-02 02:58:48 +0000 |
commit | 5eaf310a1439cccfda44f9c31ede278744fa6ad1 (patch) | |
tree | 5ff2dedec8cbd27b9a91947d59195c4cf2f1bb54 /sys/ufs | |
parent | 808dd020941e08b291f0009b33a409b03bd2a39b (diff) | |
download | FreeBSD-src-5eaf310a1439cccfda44f9c31ede278744fa6ad1.zip FreeBSD-src-5eaf310a1439cccfda44f9c31ede278744fa6ad1.tar.gz |
IN_RENAME should only be cleared by the routine that set it. This fixes
a rename/rmdir race that has been shown to cause a panic.
Bug reported by: Yevgeniy Aleynikov <eugenea@infospace.com>
MFC after: 3 days
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index b7d0c28..c0981c3 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -936,6 +936,7 @@ ufs_rename(ap) struct direct newdir; int doingdirectory = 0, oldparent = 0, newparent = 0; int error = 0, ioflag; + int in_rename_flag = 0; #ifdef DIAGNOSTIC if ((tcnp->cn_flags & HASBUF) == 0 || @@ -1049,6 +1050,8 @@ abortit: goto abortit; } ip->i_flag |= IN_RENAME; + /* note: only the routine that sets IN_RENAME can clear it */ + in_rename_flag = 1; oldparent = dp->i_number; doingdirectory = 1; } @@ -1293,7 +1296,8 @@ abortit: cache_purge(fdvp); } error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0); - xp->i_flag &= ~IN_RENAME; + if (in_rename_flag) + xp->i_flag &= ~IN_RENAME; } VN_KNOTE(fvp, NOTE_RENAME); if (dp) @@ -1308,13 +1312,14 @@ bad: vput(ITOV(xp)); vput(ITOV(dp)); out: - if (doingdirectory) + if (doingdirectory && in_rename_flag) ip->i_flag &= ~IN_RENAME; if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) { ip->i_effnlink--; ip->i_nlink--; ip->i_flag |= IN_CHANGE; - ip->i_flag &= ~IN_RENAME; + if (in_rename_flag) + ip->i_flag &= ~IN_RENAME; /* XXX huh? Why again? */ if (DOINGSOFTDEP(fvp)) softdep_change_linkcnt(ip); vput(fvp); |