aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans_ail.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_trans_ail.c')
-rw-r--r--fs/xfs/xfs_trans_ail.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index d7eebbf71362..5fc2380092c8 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -487,15 +487,19 @@ out_done:
487 ailp->xa_last_pushed_lsn = 0; 487 ailp->xa_last_pushed_lsn = 0;
488 488
489 /* 489 /*
490 * Check for an updated push target before clearing the 490 * We clear the XFS_AIL_PUSHING_BIT first before checking
491 * XFS_AIL_PUSHING_BIT. If the target changed, we've got more 491 * whether the target has changed. If the target has changed,
492 * 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).
493 */ 496 */
497 clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
494 smp_rmb(); 498 smp_rmb();
495 if (XFS_LSN_CMP(ailp->xa_target, target) == 0) { 499 if (XFS_LSN_CMP(ailp->xa_target, target) == 0 ||
496 clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); 500 test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
497 return; 501 return;
498 } 502
499 tout = 50; 503 tout = 50;
500 } else if (XFS_LSN_CMP(lsn, target) >= 0) { 504 } else if (XFS_LSN_CMP(lsn, target) >= 0) {
501 /* 505 /*