diff options
Diffstat (limited to 'fs/xfs/xfs_trans_ail.c')
| -rw-r--r-- | fs/xfs/xfs_trans_ail.c | 93 | 
1 files changed, 60 insertions, 33 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 00cc5b8734be..564253550b75 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -32,6 +32,7 @@ STATIC void  xfs_ail_check(  	struct xfs_ail		*ailp,  	struct xfs_log_item	*lip) +	__must_hold(&ailp->ail_lock)  {  	struct xfs_log_item	*prev_lip;  	struct xfs_log_item	*next_lip; @@ -108,17 +109,25 @@ xfs_ail_next(   * We need the AIL lock in order to get a coherent read of the lsn of the last   * item in the AIL.   */ +static xfs_lsn_t +__xfs_ail_min_lsn( +	struct xfs_ail		*ailp) +{ +	struct xfs_log_item	*lip = xfs_ail_min(ailp); + +	if (lip) +		return lip->li_lsn; +	return 0; +} +  xfs_lsn_t  xfs_ail_min_lsn(  	struct xfs_ail		*ailp)  { -	xfs_lsn_t		lsn = 0; -	struct xfs_log_item	*lip; +	xfs_lsn_t		lsn;  	spin_lock(&ailp->ail_lock); -	lip = xfs_ail_min(ailp); -	if (lip) -		lsn = lip->li_lsn; +	lsn = __xfs_ail_min_lsn(ailp);  	spin_unlock(&ailp->ail_lock);  	return lsn; @@ -529,8 +538,9 @@ xfsaild(  {  	struct xfs_ail	*ailp = data;  	long		tout = 0;	/* milliseconds */ +	unsigned int	noreclaim_flag; -	current->flags |= PF_MEMALLOC; +	noreclaim_flag = memalloc_noreclaim_save();  	set_freezable();  	while (1) { @@ -601,6 +611,7 @@ xfsaild(  		tout = xfsaild_push(ailp);  	} +	memalloc_noreclaim_restore(noreclaim_flag);  	return 0;  } @@ -678,6 +689,28 @@ xfs_ail_push_all_sync(  	finish_wait(&ailp->ail_empty, &wait);  } +void +xfs_ail_update_finish( +	struct xfs_ail		*ailp, +	xfs_lsn_t		old_lsn) __releases(ailp->ail_lock) +{ +	struct xfs_mount	*mp = ailp->ail_mount; + +	/* if the tail lsn hasn't changed, don't do updates or wakeups. */ +	if (!old_lsn || old_lsn == __xfs_ail_min_lsn(ailp)) { +		spin_unlock(&ailp->ail_lock); +		return; +	} + +	if (!XFS_FORCED_SHUTDOWN(mp)) +		xlog_assign_tail_lsn_locked(mp); + +	if (list_empty(&ailp->ail_head)) +		wake_up_all(&ailp->ail_empty); +	spin_unlock(&ailp->ail_lock); +	xfs_log_space_wake(mp); +} +  /*   * xfs_trans_ail_update - bulk AIL insertion operation.   * @@ -709,7 +742,7 @@ xfs_trans_ail_update_bulk(  	xfs_lsn_t		lsn) __releases(ailp->ail_lock)  {  	struct xfs_log_item	*mlip; -	int			mlip_changed = 0; +	xfs_lsn_t		tail_lsn = 0;  	int			i;  	LIST_HEAD(tmp); @@ -724,9 +757,10 @@ xfs_trans_ail_update_bulk(  				continue;  			trace_xfs_ail_move(lip, lip->li_lsn, lsn); +			if (mlip == lip && !tail_lsn) +				tail_lsn = lip->li_lsn; +  			xfs_ail_delete(ailp, lip); -			if (mlip == lip) -				mlip_changed = 1;  		} else {  			trace_xfs_ail_insert(lip, 0, lsn);  		} @@ -737,23 +771,23 @@ xfs_trans_ail_update_bulk(  	if (!list_empty(&tmp))  		xfs_ail_splice(ailp, cur, &tmp, lsn); -	if (mlip_changed) { -		if (!XFS_FORCED_SHUTDOWN(ailp->ail_mount)) -			xlog_assign_tail_lsn_locked(ailp->ail_mount); -		spin_unlock(&ailp->ail_lock); - -		xfs_log_space_wake(ailp->ail_mount); -	} else { -		spin_unlock(&ailp->ail_lock); -	} +	xfs_ail_update_finish(ailp, tail_lsn);  } -bool +/* + * Delete one log item from the AIL. + * + * If this item was at the tail of the AIL, return the LSN of the log item so + * that we can use it to check if the LSN of the tail of the log has moved + * when finishing up the AIL delete process in xfs_ail_update_finish(). + */ +xfs_lsn_t  xfs_ail_delete_one(  	struct xfs_ail		*ailp,  	struct xfs_log_item	*lip)  {  	struct xfs_log_item	*mlip = xfs_ail_min(ailp); +	xfs_lsn_t		lsn = lip->li_lsn;  	trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);  	xfs_ail_delete(ailp, lip); @@ -761,7 +795,9 @@ xfs_ail_delete_one(  	clear_bit(XFS_LI_IN_AIL, &lip->li_flags);  	lip->li_lsn = 0; -	return mlip == lip; +	if (mlip == lip) +		return lsn; +	return 0;  }  /** @@ -789,10 +825,10 @@ void  xfs_trans_ail_delete(  	struct xfs_ail		*ailp,  	struct xfs_log_item	*lip, -	int			shutdown_type) __releases(ailp->ail_lock) +	int			shutdown_type)  {  	struct xfs_mount	*mp = ailp->ail_mount; -	bool			mlip_changed; +	xfs_lsn_t		tail_lsn;  	if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {  		spin_unlock(&ailp->ail_lock); @@ -805,17 +841,8 @@ xfs_trans_ail_delete(  		return;  	} -	mlip_changed = xfs_ail_delete_one(ailp, lip); -	if (mlip_changed) { -		if (!XFS_FORCED_SHUTDOWN(mp)) -			xlog_assign_tail_lsn_locked(mp); -		if (list_empty(&ailp->ail_head)) -			wake_up_all(&ailp->ail_empty); -	} - -	spin_unlock(&ailp->ail_lock); -	if (mlip_changed) -		xfs_log_space_wake(ailp->ail_mount); +	tail_lsn = xfs_ail_delete_one(ailp, lip); +	xfs_ail_update_finish(ailp, tail_lsn);  }  int  |