aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-05-05 22:54:05 -0400
committerAlex Elder <aelder@sgi.com>2011-05-09 19:35:03 -0400
commit9e7004e741de0b2daabbbadafbaf11ff1a94e00c (patch)
tree86ed6be6bd95114e6bf3a2680d21d35dcd0a335e
parent228d62dd3f74734b9801c789b5addc57fdfc208f (diff)
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: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com> (cherry picked from commit ea35a20021f8497390d05b93271b4d675516c654)
-rw-r--r--fs/xfs/xfs_trans_ail.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index acdb92f14d51..226c58bd62e0 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -346,18 +346,20 @@ xfs_ail_delete(
346 */ 346 */
347STATIC void 347STATIC void
348xfs_ail_worker( 348xfs_ail_worker(
349 struct work_struct *work) 349 struct work_struct *work)
350{ 350{
351 struct xfs_ail *ailp = container_of(to_delayed_work(work), 351 struct xfs_ail *ailp = container_of(to_delayed_work(work),
352 struct xfs_ail, xa_work); 352 struct xfs_ail, xa_work);
353 long tout; 353 xfs_mount_t *mp = ailp->xa_mount;
354 xfs_lsn_t target = ailp->xa_target;
355 xfs_lsn_t lsn;
356 xfs_log_item_t *lip;
357 int flush_log, count, stuck;
358 xfs_mount_t *mp = ailp->xa_mount;
359 struct xfs_ail_cursor *cur = &ailp->xa_cursors; 354 struct xfs_ail_cursor *cur = &ailp->xa_cursors;
360 int push_xfsbufd = 0; 355 xfs_log_item_t *lip;
356 xfs_lsn_t lsn;
357 xfs_lsn_t target = ailp->xa_target;
358 long tout = 10;
359 int flush_log = 0;
360 int stuck = 0;
361 int count = 0;
362 int push_xfsbufd = 0;
361 363
362 spin_lock(&ailp->xa_lock); 364 spin_lock(&ailp->xa_lock);
363 xfs_trans_ail_cursor_init(ailp, cur); 365 xfs_trans_ail_cursor_init(ailp, cur);
@@ -368,8 +370,7 @@ xfs_ail_worker(
368 */ 370 */
369 xfs_trans_ail_cursor_done(ailp, cur); 371 xfs_trans_ail_cursor_done(ailp, cur);
370 spin_unlock(&ailp->xa_lock); 372 spin_unlock(&ailp->xa_lock);
371 ailp->xa_last_pushed_lsn = 0; 373 goto out_done;
372 return;
373 } 374 }
374 375
375 XFS_STATS_INC(xs_push_ail); 376 XFS_STATS_INC(xs_push_ail);
@@ -386,7 +387,6 @@ xfs_ail_worker(
386 * lots of contention on the AIL lists. 387 * lots of contention on the AIL lists.
387 */ 388 */
388 lsn = lip->li_lsn; 389 lsn = lip->li_lsn;
389 flush_log = stuck = count = 0;
390 while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) { 390 while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) {
391 int lock_result; 391 int lock_result;
392 /* 392 /*
@@ -480,7 +480,7 @@ xfs_ail_worker(
480 } 480 }
481 481
482 /* assume we have more work to do in a short while */ 482 /* assume we have more work to do in a short while */
483 tout = 10; 483out_done:
484 if (!count) { 484 if (!count) {
485 /* We're past our target or empty, so idle */ 485 /* We're past our target or empty, so idle */
486 ailp->xa_last_pushed_lsn = 0; 486 ailp->xa_last_pushed_lsn = 0;