Date: Thu, 31 Oct 1996 09:10:02 -0800 (PST) From: Bruce Evans <bde@zeta.org.au> To: freebsd-bugs Subject: Re: kern/1930: rename() cause panic: page fault Message-ID: <199610311710.JAA21233@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/1930; it has been noted by GNATS.
From: Bruce Evans <bde@zeta.org.au>
To: FreeBSD-gnats-submit@freebsd.org, Tor.Egge@idt.ntnu.no
Cc: Subject: Re: kern/1930: rename() cause panic: page fault
Date: Fri, 1 Nov 1996 03:55:55 +1100
> simultaneous calls to rename() with the same arguments
> cause a system crash with the message panic: page fault
Try this fix. I've spent a lot of time looking for the bug reported
by the second printf and had forgotten about the problem with directories.
There also seems to be a bunch of very rarely active bugs involving
ufs_checkpath(). It seems to be possible for ufs_checkpath() to
block and another process to rearrange the tree(s) so that rename()
does bad things when it restarts. I've verified this by faking a
block in the VFS_VGET() operation in ufs_lookup.c and rearranging
the trees using ordinary renames.
Bruce
diff -c2 ufs_vnops.c~ ufs_vnops.c
*** ufs_vnops.c~ Fri Sep 20 13:17:29 1996
--- ufs_vnops.c Mon Oct 14 20:20:52 1996
***************
*** 843,849 ****
}
- /*
- * Check if just deleting a link name.
- */
if (tvp && ((VTOI(tvp)->i_flags & (IMMUTABLE | APPEND)) ||
(VTOI(tdvp)->i_flags & APPEND))) {
--- 848,851 ----
***************
*** 851,857 ****
goto abortit;
}
if (fvp == tvp) {
if (fvp->v_type == VDIR) {
! error = EINVAL;
goto abortit;
}
--- 853,876 ----
goto 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.
+ */
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.
! */
! #define UFS_RENAME_DEBUG
! #ifdef UFS_RENAME_DEBUG
! printf("ufs_rename: fvp == tvp for directories\n");
! #endif
! error = ENOENT;
goto abortit;
}
***************
*** 862,866 ****
vput(tvp);
! /* Delete source. */
vrele(fdvp);
vrele(fvp);
--- 881,890 ----
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);
***************
*** 874,877 ****
--- 898,907 ----
if (error == 0)
vrele(fdvp);
+ if (fvp == NULL) {
+ #ifdef UFS_RENAME_DEBUG
+ printf("ufs_rename: from name disappeared\n");
+ #endif
+ return (ENOENT);
+ }
return (VOP_REMOVE(fdvp, fvp, fcnp));
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199610311710.JAA21233>
