aboutsummaryrefslogtreecommitdiff
path: root/sys/gnu/fs/ext2fs/ext2_vnops.c
diff options
context:
space:
mode:
authorBruce Evans <bde@FreeBSD.org>2002-09-10 11:09:13 +0000
committerBruce Evans <bde@FreeBSD.org>2002-09-10 11:09:13 +0000
commitd3a7b5e70e4f8338bc2b3556df238e6ffb79a2ae (patch)
treefbf60a21a76d1e310c894136153d8d3364de0a27 /sys/gnu/fs/ext2fs/ext2_vnops.c
parent3e30ca7b1cc48afdaf4fd24adeebe08eaff8a47c (diff)
downloadsrc-d3a7b5e70e4f8338bc2b3556df238e6ffb79a2ae.tar.gz
src-d3a7b5e70e4f8338bc2b3556df238e6ffb79a2ae.zip
vfs_syscalls.c:
Changed rename(2) to follow the letter of the POSIX spec. POSIX requires rename() to have no effect if its args "resolve to the same existing file". I think "file" can only reasonably be read as referring to the inode, although the rationale and "resolve" seem to say that sameness is at the level of (resolved) directory entries. ext2fs_vnops.c, ufs_vnops.c: Replaced code that gave the historical BSD behaviour of removing one link name by checks that this code is now unreachable. This fixes some races. All vnodes needed to be unlocked for the removal, and locking at another level using something like IN_RENAME was not even attempted, so it was possible for rename(x, y) to return with both x and y removed even without any unlink(2) syscalls (one process can remove x using rename(x, y) and another process can remove y using rename(y, x)). Prodded by: alfred MFC after: 8 weeks PR: 42617
Notes
Notes: svn path=/head/; revision=103180
Diffstat (limited to 'sys/gnu/fs/ext2fs/ext2_vnops.c')
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c57
1 files changed, 6 insertions, 51 deletions
diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c
index 8c93c0778cbf..22030b58ecea 100644
--- a/sys/gnu/fs/ext2fs/ext2_vnops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vnops.c
@@ -925,60 +925,15 @@ abortit:
}
/*
- * Check if just deleting a link name or if we've lost a race.
- * If another process completes the same rename after we've looked
- * up the source and have blocked looking up the target, then the
- * source and target inodes may be identical now although the
- * names were never linked.
+ * Renaming a file to itself has no effect. The upper layers should
+ * not call us in that case. Temporarily just warn if they do.
*/
if (fvp == tvp) {
- if (fvp->v_type == VDIR) {
- /*
- * Linked directories are impossible, so we must
- * have lost the race. Pretend that the rename
- * completed before the lookup.
- */
-#ifdef UFS_RENAME_DEBUG
- printf("ext2_rename: fvp == tvp for directories\n");
-#endif
- error = ENOENT;
- goto abortit;
- }
-
- /* Release destination completely. */
- vput(tdvp);
- vput(tvp);
-
- /*
- * Delete source. There is another race now that everything
- * is unlocked, but this doesn't cause any new complications.
- * Relookup() may find a file that is unrelated to the
- * original one, or it may fail. Too bad.
- */
- vrele(fdvp);
- vrele(fvp);
- fcnp->cn_flags &= ~MODMASK;
- fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
- fcnp->cn_nameiop = DELETE;
- VREF(fdvp);
- error = relookup(fdvp, &fvp, fcnp);
- if (error == 0)
- vrele(fdvp);
- if (fvp == NULL) {
-#ifdef UFS_RENAME_DEBUG
- printf("ext2_rename: from name disappeared\n");
-#endif
- return (ENOENT);
- }
- error = VOP_REMOVE(fdvp, fvp, fcnp);
- if (fdvp == fvp)
- vrele(fdvp);
- else
- vput(fdvp);
- if (fvp != NULLVP)
- vput(fvp);
- return (error);
+ printf("ext2_rename: fvp == tvp (can't happen)\n");
+ error = 0;
+ goto abortit;
}
+
if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0)
goto abortit;
dp = VTOI(fdvp);