Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Aug 1998 18:01:00 -0400 (EDT)
From:      Brian Feldman <green@zone.syracuse.net>
To:        Kirk McKusick <mckusick@McKusick.COM>
Cc:        Julian Elischer <julian@whistle.com>, Luoqi Chen <luoqi@watermarkgroup.com>, kkennawa@physics.adelaide.edu.au, dg@root.com, current@FreeBSD.ORG
Subject:   Re: Softupdates panic (fwd) 
Message-ID:  <Pine.BSF.4.02.9808081757560.17846-100000@zone.syracuse.net>
In-Reply-To: <199808081852.LAA06087@flamingo.McKusick.COM>

next in thread | previous in thread | raw e-mail | index | archive | help
In the current ufs_vnops.c I have, the correct line 1146 is:
                    IFTODT(ip->i_mode), newparent ? newparent :
doingdirectory);
My version is $Id: ufs_vnops.c,v 1.97 1998/07/27 15:37:00 bde Exp $, I
guess we've got a non-committed version on our hands.

Cheers,
Brian Feldman
green@unixhelp.org

On Sat, 8 Aug 1998, Kirk McKusick wrote:

> The problem occured when renaming a directory to a new parent, but
> not when renaming a directory within the same parent (write a one
> line C program that does ``rename("d1", "d2");''). Luoqi Chen's
> fix (forwarded message below) for the broken case, breaks the same
> directory rename case. Thus, the soft update code needs to be aware of
> which case it is handling. I now pass this information through and do the
> right thing for both cases. Affected files are /sys/ufs/ufs/ufs_vnops.c
> and /sys/ufs/ffs/ffs_softdep.c. Note there is a related one line fix
> if ffs_softdep.c which sometimes caused the rename to fail with an
> EINVAL error (compounding the difficulty of trying to track down this
> bug). The diffs follow.
> 
> 	Kirk McKusick
> 
> Index: ffs_softdep.c
> ===================================================================
> RCS file: /master/sys/ufs/ffs/ffs_softdep.c,v
> retrieving revision 2.21
> diff -c -r2.21 ffs_softdep.c
> *** ffs_softdep.c	1998/06/12 17:54:33	2.21
> --- ffs_softdep.c	1998/08/08 18:32:36
> ***************
> *** 52,58 ****
>    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>    * SUCH DAMAGE.
>    *
> !  *	@(#)ffs_softdep.c	9.27 (McKusick) 6/12/98
>    */
>   
>   /*
> --- 52,58 ----
>    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>    * SUCH DAMAGE.
>    *
> !  *	@(#)ffs_softdep.c	9.28 (McKusick) 8/8/98
>    */
>   
>   /*
> ***************
> *** 2205,2210 ****
> --- 2205,2211 ----
>   	} else {
>   		dirrem = dap->da_previous;
>   		pagedep = dirrem->dm_pagedep;
> + 		dirrem->dm_dirinum = pagedep->pd_ino;
>   		add_to_worklist(&dirrem->dm_list);
>   	}
>   	if (inodedep_lookup(VFSTOUFS(pagedep->pd_mnt)->um_fs, dap->da_newinum,
> ***************
> *** 2384,2389 ****
> --- 2385,2404 ----
>   	 */
>   	dirrem = newdirrem(bp, dp, ip, isrmdir);
>   	pagedep = dirrem->dm_pagedep;
> + 	/*
> + 	 * The possible values for isrmdir:
> + 	 *	0 - non-directory file rename
> + 	 *	1 - directory rename within same directory
> + 	 *   inum - directory rename to new directory of given inode number
> + 	 * When renaming to a new directory, we are both deleting and
> + 	 * creating a new directory entry, so the link count on the new
> + 	 * directory should not change. Thus we do not need the followup
> + 	 * dirrem which is usually done in handle_workitem_remove. We set
> + 	 * the DIRCHG flag to tell handle_workitem_remove to skip the 
> + 	 * followup dirrem.
> + 	 */
> + 	if (isrmdir > 1)
> + 		dirrem->dm_state |= DIRCHG;
>   
>   	/*
>   	 * Whiteouts have no additional dependencies,
> ***************
> *** 2493,2498 ****
> --- 2508,2523 ----
>   	ip->i_flag |= IN_CHANGE;
>   	if ((error = VOP_TRUNCATE(vp, (off_t)0, 0, p->p_ucred, p)) != 0)
>   		softdep_error("handle_workitem_remove: truncate", error);
> + 	/*
> + 	 * Rename a directory to a new parent. Since, we are both deleting
> + 	 * and creating a new directory entry, the link count on the new
> + 	 * directory should not change. Thus we skip the followup dirrem.
> + 	 */
> + 	if (dirrem->dm_state & DIRCHG) {
> + 		vput(vp);
> + 		WORKITEM_FREE(dirrem, D_DIRREM);
> + 		return;
> + 	}
>   	ACQUIRE_LOCK(&lk);
>   	(void) inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, DEPALLOC,
>   	    &inodedep);
> Index: ufs_vnops.c
> ===================================================================
> RCS file: /master/sys/ufs/ufs/ufs_vnops.c,v
> retrieving revision 2.29
> diff -c -r2.29 ufs_vnops.c
> *** ufs_vnops.c	1998/06/08 18:52:11	2.29
> --- ufs_vnops.c	1998/08/08 18:20:28
> ***************
> *** 930,936 ****
>   		}
>   		ip->i_flag |= IN_RENAME;
>   		oldparent = dp->i_number;
> ! 		doingdirectory++;
>   	}
>   
>   	/*
> --- 930,936 ----
>   		}
>   		ip->i_flag |= IN_RENAME;
>   		oldparent = dp->i_number;
> ! 		doingdirectory = 1;
>   	}
>   
>   	/*
> ***************
> *** 1073,1079 ****
>   			goto bad;
>   		}
>   		if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
> ! 		    IFTODT(ip->i_mode), doingdirectory)) != 0)
>   			goto bad;
>   		if (doingdirectory) {
>   			if (!newparent) {
> --- 1073,1080 ----
>   			goto bad;
>   		}
>   		if ((error = ufs_dirrewrite(dp, xp, ip->i_number,
> ! 		    IFTODT(ip->i_mode),
> ! 		    newparent ? newparent : doingdirectory)) != 0)
>   			goto bad;
>   		if (doingdirectory) {
>   			if (!newparent) {
> 
> ---------- Forwarded message ----------
> Date: Fri, 7 Aug 1998 12:09:03 -0400 (EDT)
> From: Luoqi Chen <luoqi@watermarkgroup.com>
> To: julian@whistle.com, kkennawa@physics.adelaide.edu.au
> Cc: current@FreeBSD.ORG
> Subject: Re: Softupdates panic
> 
> > Well, here's the problem simplified:
> > 
> > cd /tmp (assuming mounted soft-updates)
> > mkdir d1
> > mkdir d1/d2
> > mkdir d2
> > mv d2 d1
> > rmdir d1/d2
> > rmdir d1
> > [system will panic in 15 seconds at 'sync' of that data.]
> > 
> > fix to follow. (and checked in I guess)
> > 
> > julian
> > 
> I looked at the problem and figured out what went wrong. During the rename
> step (mv d2 d1), the target directory d1/d2 is deleted and a dirrem
> dependency is generated. Normally, a dirrem dependency would decrease
> the parent's link count by 1 and subdirectory's link count by 2. But for
> this particular dirrem, we don't want to decrement the parent's link count,
> otherwise we would the panic above. The solution would be mark this dirrem
> as such, and don't decrement the parent's link count when it's handled.
> Attached is a fix.
> 
> -lq
> 
> Index: ffs_softdep.c
> ===================================================================
> RCS file: /fun/cvs/src/contrib/sys/softupdates/ffs_softdep.c,v
> retrieving revision 1.12
> diff -u -r1.12 ffs_softdep.c
> --- ffs_softdep.c	1998/06/12 21:21:26	1.12
> +++ ffs_softdep.c	1998/08/07 15:37:57
> @@ -2436,6 +2436,7 @@
>  	 * Allocate a new dirrem and ACQUIRE_LOCK.
>  	 */
>  	dirrem = newdirrem(bp, dp, ip, isrmdir);
> +	dirrem->dm_state |= DIRCHG;
>  	pagedep = dirrem->dm_pagedep;
>  
>  	/*
> @@ -2546,6 +2547,15 @@
>  	ip->i_flag |= IN_CHANGE;
>  	if ((error = UFS_TRUNCATE(vp, (off_t)0, 0, p->p_ucred, p)) != 0)
>  		softdep_error("handle_workitem_remove: truncate", error);
> +	/*
> +	 * Target directory deletion during a directory rename. The
> +	 * parent directory's link count doesn't need to be decremented.
> +	 */
> +	if (dirrem->dm_state & DIRCHG) {
> +		vput(vp);
> +		WORKITEM_FREE(dirrem, D_DIRREM);
> +		return;
> +	}
>  	ACQUIRE_LOCK(&lk);
>  	(void) inodedep_lookup(ip->i_fs, dirrem->dm_oldinum, DEPALLOC,
>  	    &inodedep);
> -------- End Forwarded message --------
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-current" in the body of the message
> 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.02.9808081757560.17846-100000>