Skip site navigation (1)Skip section navigation (2)
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>