Re: Livelock / softdep_flush "loop"

From: Peter Holm <peter_at_holm.cc>
Date: Mon, 3 Apr 2006 21:28:08 +0200
On Sun, Apr 02, 2006 at 08:48:51PM +0000, Tor Egge wrote:
> > > The enclosed patch might help.
> > > 
> > 
> > I'm testing it right now.
> 
> Similarly to the softdepflush process looping in softdep_flush(), the process
> creating a snapshot might loop in ffs_sync().
> 

I ran the same test with your first patch for two hours and your
second patch for 7 hours, without seeing any livelocks.

I added snapshots to the test and still did not get any livelocks, but
I'm not certain that this last test covers your change.

- Peter

> - Tor Egge

> Index: sys/ufs/ffs/ffs_softdep.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_softdep.c,v
> retrieving revision 1.193
> diff -u -r1.193 ffs_softdep.c
> --- sys/ufs/ffs/ffs_softdep.c	12 Mar 2006 05:25:16 -0000	1.193
> +++ sys/ufs/ffs/ffs_softdep.c	2 Apr 2006 20:20:15 -0000
> _at__at_ -718,6 +718,7 _at__at_
>  {
>  	struct mount *nmp;
>  	struct mount *mp;
> +	struct ufsmount *ump;
>  	struct thread *td;
>  	int remaining;
>  	int vfslocked;
> _at__at_ -752,7 +753,9 _at__at_
>  				continue;
>  			vfslocked = VFS_LOCK_GIANT(mp);
>  			softdep_process_worklist(mp, 0);
> -			remaining += VFSTOUFS(mp)->softdep_on_worklist;
> +			ump = VFSTOUFS(mp);
> +			remaining += ump->softdep_on_worklist -
> +				ump->softdep_on_worklist_inprogress;
>  			VFS_UNLOCK_GIANT(vfslocked);
>  			mtx_lock(&mountlist_mtx);
>  			nmp = TAILQ_NEXT(mp, mnt_list);
> _at__at_ -914,11 +917,17 _at__at_
>  		if ((flags & LK_NOWAIT) == 0 || wk->wk_type != D_DIRREM)
>  			break;
>  		wk->wk_state |= INPROGRESS;
> +		ump->softdep_on_worklist_inprogress++;
>  		FREE_LOCK(&lk);
>  		ffs_vget(mp, WK_DIRREM(wk)->dm_oldinum,
>  		    LK_NOWAIT | LK_EXCLUSIVE, &vp);
>  		ACQUIRE_LOCK(&lk);
>  		wk->wk_state &= ~INPROGRESS;
> +		if (--ump->softdep_on_worklist_inprogress == 0 &&
> +		    ump->softdep_on_worklist_inprogress_req != 0) {
> +			ump->softdep_on_worklist_inprogress_req = 0;
> +			wakeup(&ump->softdep_on_worklist_inprogress);
> +		}
>  		if (vp != NULL)
>  			break;
>  	}
> _at__at_ -6099,6 +6108,17 _at__at_
>  			VI_LOCK(devvp);
>  			continue;
>  		}
> +		if (ump->softdep_on_worklist_inprogress != 0) {
> +			VI_UNLOCK(devvp);
> +			ump->softdep_on_worklist_inprogress_req = 1;
> +			msleep(&ump->softdep_on_worklist_inprogress,
> +			       &lk,
> +			       (PUSER - 1) | PDROP,
> +			       "sdipdr" /* soft dep in progress drain */,
> +			       0);
> +			VI_LOCK(devvp);
> +			continue;
> +		}
>  		if (!MNT_ITRYLOCK(mp)) {
>  			FREE_LOCK(&lk);
>  			VI_UNLOCK(devvp);
> Index: sys/ufs/ufs/ufsmount.h
> ===================================================================
> RCS file: /home/ncvs/src/sys/ufs/ufs/ufsmount.h,v
> retrieving revision 1.36
> diff -u -r1.36 ufsmount.h
> --- sys/ufs/ufs/ufsmount.h	8 Mar 2006 23:43:39 -0000	1.36
> +++ sys/ufs/ufs/ufsmount.h	2 Apr 2006 20:20:15 -0000
> _at__at_ -76,6 +76,8 _at__at_
>  	struct workhead softdep_workitem_pending; /* softdep work queue */
>  	struct worklist *softdep_worklist_tail;	/* Tail pointer for above */
>  	int	softdep_on_worklist;		/* Items on the worklist */
> +	int	softdep_on_worklist_inprogress;	/* Busy items on worklist */
> +	int	softdep_on_worklist_inprogress_req;/* Wakeup when not busy */
>  	int	softdep_deps;			/* Total dependency count */
>  	int	softdep_accdeps;		/* accumulated dep count */
>  	int	softdep_req;			/* Wakeup when deps hits 0. */


-- 
Peter Holm
Received on Mon Apr 03 2006 - 17:28:16 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:54 UTC