summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-10-02 02:58:48 +0000
committerdillon <dillon@FreeBSD.org>2001-10-02 02:58:48 +0000
commit5eaf310a1439cccfda44f9c31ede278744fa6ad1 (patch)
tree5ff2dedec8cbd27b9a91947d59195c4cf2f1bb54 /sys/ufs
parent808dd020941e08b291f0009b33a409b03bd2a39b (diff)
downloadFreeBSD-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.c11
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);
OpenPOWER on IntegriCloud