From owner-freebsd-bugs Thu Oct 31 09:10:05 1996 Return-Path: owner-bugs Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id JAA21241 for bugs-outgoing; Thu, 31 Oct 1996 09:10:05 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id JAA21233; Thu, 31 Oct 1996 09:10:02 -0800 (PST) Date: Thu, 31 Oct 1996 09:10:02 -0800 (PST) Message-Id: <199610311710.JAA21233@freefall.freebsd.org> To: freebsd-bugs Cc: From: Bruce Evans Subject: Re: kern/1930: rename() cause panic: page fault Reply-To: Bruce Evans Sender: owner-bugs@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk The following reply was made to PR kern/1930; it has been noted by GNATS. From: Bruce Evans 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)); }