Commit ea35a200 authored by Dave Chinner's avatar Dave Chinner Committed by Alex Elder

xfs: exit AIL push work correctly when AIL is empty

The recent conversion of the xfsaild functionality to a work queue
introduced a hard-to-hit log space grant hang. The main cause is a
regression where a work exit path fails to clear the PUSHING state
and recheck the target correctly.

Make both exit paths do the same PUSHING bit clearing and target
checking when the "no more work to be done" condition is hit.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarAlex Elder <aelder@sgi.com>
parent b2232219
...@@ -346,18 +346,20 @@ xfs_ail_delete( ...@@ -346,18 +346,20 @@ xfs_ail_delete(
*/ */
STATIC void STATIC void
xfs_ail_worker( xfs_ail_worker(
struct work_struct *work) struct work_struct *work)
{ {
struct xfs_ail *ailp = container_of(to_delayed_work(work), struct xfs_ail *ailp = container_of(to_delayed_work(work),
struct xfs_ail, xa_work); struct xfs_ail, xa_work);
long tout; xfs_mount_t *mp = ailp->xa_mount;
xfs_lsn_t target = ailp->xa_target;
xfs_lsn_t lsn;
xfs_log_item_t *lip;
int flush_log, count, stuck;
xfs_mount_t *mp = ailp->xa_mount;
struct xfs_ail_cursor *cur = &ailp->xa_cursors; struct xfs_ail_cursor *cur = &ailp->xa_cursors;
int push_xfsbufd = 0; xfs_log_item_t *lip;
xfs_lsn_t lsn;
xfs_lsn_t target = ailp->xa_target;
long tout = 10;
int flush_log = 0;
int stuck = 0;
int count = 0;
int push_xfsbufd = 0;
spin_lock(&ailp->xa_lock); spin_lock(&ailp->xa_lock);
xfs_trans_ail_cursor_init(ailp, cur); xfs_trans_ail_cursor_init(ailp, cur);
...@@ -368,8 +370,7 @@ xfs_ail_worker( ...@@ -368,8 +370,7 @@ xfs_ail_worker(
*/ */
xfs_trans_ail_cursor_done(ailp, cur); xfs_trans_ail_cursor_done(ailp, cur);
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
ailp->xa_last_pushed_lsn = 0; goto out_done;
return;
} }
XFS_STATS_INC(xs_push_ail); XFS_STATS_INC(xs_push_ail);
...@@ -386,7 +387,6 @@ xfs_ail_worker( ...@@ -386,7 +387,6 @@ xfs_ail_worker(
* lots of contention on the AIL lists. * lots of contention on the AIL lists.
*/ */
lsn = lip->li_lsn; lsn = lip->li_lsn;
flush_log = stuck = count = 0;
while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) { while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) {
int lock_result; int lock_result;
/* /*
...@@ -480,7 +480,7 @@ xfs_ail_worker( ...@@ -480,7 +480,7 @@ xfs_ail_worker(
} }
/* assume we have more work to do in a short while */ /* assume we have more work to do in a short while */
tout = 10; out_done:
if (!count) { if (!count) {
/* We're past our target or empty, so idle */ /* We're past our target or empty, so idle */
ailp->xa_last_pushed_lsn = 0; ailp->xa_last_pushed_lsn = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment