diff options
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 1 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans_ail.c | 47 |
2 files changed, 27 insertions, 21 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index e4f9c1b0836c..3e898a48122d 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
| @@ -926,6 +926,7 @@ restart: | |||
| 926 | XFS_LOOKUP_BATCH, | 926 | XFS_LOOKUP_BATCH, |
| 927 | XFS_ICI_RECLAIM_TAG); | 927 | XFS_ICI_RECLAIM_TAG); |
| 928 | if (!nr_found) { | 928 | if (!nr_found) { |
| 929 | done = 1; | ||
| 929 | rcu_read_unlock(); | 930 | rcu_read_unlock(); |
| 930 | break; | 931 | break; |
| 931 | } | 932 | } |
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index acdb92f14d51..5fc2380092c8 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
| @@ -346,20 +346,23 @@ xfs_ail_delete( | |||
| 346 | */ | 346 | */ |
| 347 | STATIC void | 347 | STATIC void |
| 348 | xfs_ail_worker( | 348 | xfs_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; | ||
| 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); |
| 365 | target = ailp->xa_target; | ||
| 363 | xfs_trans_ail_cursor_init(ailp, cur); | 366 | xfs_trans_ail_cursor_init(ailp, cur); |
| 364 | lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn); | 367 | lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn); |
| 365 | if (!lip || XFS_FORCED_SHUTDOWN(mp)) { | 368 | if (!lip || XFS_FORCED_SHUTDOWN(mp)) { |
| @@ -368,8 +371,7 @@ xfs_ail_worker( | |||
| 368 | */ | 371 | */ |
| 369 | xfs_trans_ail_cursor_done(ailp, cur); | 372 | xfs_trans_ail_cursor_done(ailp, cur); |
| 370 | spin_unlock(&ailp->xa_lock); | 373 | spin_unlock(&ailp->xa_lock); |
| 371 | ailp->xa_last_pushed_lsn = 0; | 374 | goto out_done; |
| 372 | return; | ||
| 373 | } | 375 | } |
| 374 | 376 | ||
| 375 | XFS_STATS_INC(xs_push_ail); | 377 | XFS_STATS_INC(xs_push_ail); |
| @@ -386,8 +388,7 @@ xfs_ail_worker( | |||
| 386 | * lots of contention on the AIL lists. | 388 | * lots of contention on the AIL lists. |
| 387 | */ | 389 | */ |
| 388 | lsn = lip->li_lsn; | 390 | lsn = lip->li_lsn; |
| 389 | flush_log = stuck = count = 0; | 391 | while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) { |
| 390 | while ((XFS_LSN_CMP(lip->li_lsn, target) < 0)) { | ||
| 391 | int lock_result; | 392 | int lock_result; |
| 392 | /* | 393 | /* |
| 393 | * If we can lock the item without sleeping, unlock the AIL | 394 | * If we can lock the item without sleeping, unlock the AIL |
| @@ -480,21 +481,25 @@ xfs_ail_worker( | |||
| 480 | } | 481 | } |
| 481 | 482 | ||
| 482 | /* assume we have more work to do in a short while */ | 483 | /* assume we have more work to do in a short while */ |
| 483 | tout = 10; | 484 | out_done: |
| 484 | if (!count) { | 485 | if (!count) { |
| 485 | /* We're past our target or empty, so idle */ | 486 | /* We're past our target or empty, so idle */ |
| 486 | ailp->xa_last_pushed_lsn = 0; | 487 | ailp->xa_last_pushed_lsn = 0; |
| 487 | 488 | ||
| 488 | /* | 489 | /* |
| 489 | * Check for an updated push target before clearing the | 490 | * We clear the XFS_AIL_PUSHING_BIT first before checking |
| 490 | * XFS_AIL_PUSHING_BIT. If the target changed, we've got more | 491 | * whether the target has changed. If the target has changed, |
| 491 | * work to do. Wait a bit longer before starting that work. | 492 | * this pushes the requeue race directly onto the result of the |
| 493 | * atomic test/set bit, so we are guaranteed that either the | ||
| 494 | * the pusher that changed the target or ourselves will requeue | ||
| 495 | * the work (but not both). | ||
| 492 | */ | 496 | */ |
| 497 | clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); | ||
| 493 | smp_rmb(); | 498 | smp_rmb(); |
| 494 | if (ailp->xa_target == target) { | 499 | if (XFS_LSN_CMP(ailp->xa_target, target) == 0 || |
| 495 | clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); | 500 | test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) |
| 496 | return; | 501 | return; |
| 497 | } | 502 | |
| 498 | tout = 50; | 503 | tout = 50; |
| 499 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { | 504 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { |
| 500 | /* | 505 | /* |
| @@ -553,7 +558,7 @@ xfs_ail_push( | |||
| 553 | * the XFS_AIL_PUSHING_BIT. | 558 | * the XFS_AIL_PUSHING_BIT. |
| 554 | */ | 559 | */ |
| 555 | smp_wmb(); | 560 | smp_wmb(); |
| 556 | ailp->xa_target = threshold_lsn; | 561 | xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); |
| 557 | if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) | 562 | if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) |
| 558 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); | 563 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); |
| 559 | } | 564 | } |
