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>