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.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index c15aa29fa169..3a1e7ca54c2d 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -28,8 +28,6 @@
28#include "xfs_trans_priv.h" 28#include "xfs_trans_priv.h"
29#include "xfs_error.h" 29#include "xfs_error.h"
30 30
31struct workqueue_struct *xfs_ail_wq; /* AIL workqueue */
32
33#ifdef DEBUG 31#ifdef DEBUG
34/* 32/*
35 * Check that the list is sorted as it should be. 33 * Check that the list is sorted as it should be.
@@ -356,16 +354,10 @@ xfs_ail_delete(
356 xfs_trans_ail_cursor_clear(ailp, lip); 354 xfs_trans_ail_cursor_clear(ailp, lip);
357} 355}
358 356
359/* 357static long
360 * xfs_ail_worker does the work of pushing on the AIL. It will requeue itself 358xfsaild_push(
361 * to run at a later time if there is more work to do to complete the push. 359 struct xfs_ail *ailp)
362 */
363STATIC void
364xfs_ail_worker(
365 struct work_struct *work)
366{ 360{
367 struct xfs_ail *ailp = container_of(to_delayed_work(work),
368 struct xfs_ail, xa_work);
369 xfs_mount_t *mp = ailp->xa_mount; 361 xfs_mount_t *mp = ailp->xa_mount;
370 struct xfs_ail_cursor cur; 362 struct xfs_ail_cursor cur;
371 xfs_log_item_t *lip; 363 xfs_log_item_t *lip;
@@ -427,8 +419,13 @@ xfs_ail_worker(
427 419
428 case XFS_ITEM_PUSHBUF: 420 case XFS_ITEM_PUSHBUF:
429 XFS_STATS_INC(xs_push_ail_pushbuf); 421 XFS_STATS_INC(xs_push_ail_pushbuf);
430 IOP_PUSHBUF(lip); 422
431 ailp->xa_last_pushed_lsn = lsn; 423 if (!IOP_PUSHBUF(lip)) {
424 stuck++;
425 flush_log = 1;
426 } else {
427 ailp->xa_last_pushed_lsn = lsn;
428 }
432 push_xfsbufd = 1; 429 push_xfsbufd = 1;
433 break; 430 break;
434 431
@@ -440,7 +437,6 @@ xfs_ail_worker(
440 437
441 case XFS_ITEM_LOCKED: 438 case XFS_ITEM_LOCKED:
442 XFS_STATS_INC(xs_push_ail_locked); 439 XFS_STATS_INC(xs_push_ail_locked);
443 ailp->xa_last_pushed_lsn = lsn;
444 stuck++; 440 stuck++;
445 break; 441 break;
446 442
@@ -501,20 +497,6 @@ out_done:
501 /* We're past our target or empty, so idle */ 497 /* We're past our target or empty, so idle */
502 ailp->xa_last_pushed_lsn = 0; 498 ailp->xa_last_pushed_lsn = 0;
503 499
504 /*
505 * We clear the XFS_AIL_PUSHING_BIT first before checking
506 * whether the target has changed. If the target has changed,
507 * this pushes the requeue race directly onto the result of the
508 * atomic test/set bit, so we are guaranteed that either the
509 * the pusher that changed the target or ourselves will requeue
510 * the work (but not both).
511 */
512 clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
513 smp_rmb();
514 if (XFS_LSN_CMP(ailp->xa_target, target) == 0 ||
515 test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
516 return;
517
518 tout = 50; 500 tout = 50;
519 } else if (XFS_LSN_CMP(lsn, target) >= 0) { 501 } else if (XFS_LSN_CMP(lsn, target) >= 0) {
520 /* 502 /*
@@ -537,9 +519,30 @@ out_done:
537 tout = 20; 519 tout = 20;
538 } 520 }
539 521
540 /* There is more to do, requeue us. */ 522 return tout;
541 queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 523}
542 msecs_to_jiffies(tout)); 524
525static int
526xfsaild(
527 void *data)
528{
529 struct xfs_ail *ailp = data;
530 long tout = 0; /* milliseconds */
531
532 while (!kthread_should_stop()) {
533 if (tout && tout <= 20)
534 __set_current_state(TASK_KILLABLE);
535 else
536 __set_current_state(TASK_INTERRUPTIBLE);
537 schedule_timeout(tout ?
538 msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT);
539
540 try_to_freeze();
541
542 tout = xfsaild_push(ailp);
543 }
544
545 return 0;
543} 546}
544 547
545/* 548/*
@@ -574,8 +577,9 @@ xfs_ail_push(
574 */ 577 */
575 smp_wmb(); 578 smp_wmb();
576 xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); 579 xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn);
577 if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) 580 smp_wmb();
578 queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); 581
582 wake_up_process(ailp->xa_task);
579} 583}
580 584
581/* 585/*
@@ -813,9 +817,18 @@ xfs_trans_ail_init(
813 INIT_LIST_HEAD(&ailp->xa_ail); 817 INIT_LIST_HEAD(&ailp->xa_ail);
814 INIT_LIST_HEAD(&ailp->xa_cursors); 818 INIT_LIST_HEAD(&ailp->xa_cursors);
815 spin_lock_init(&ailp->xa_lock); 819 spin_lock_init(&ailp->xa_lock);
816 INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker); 820
821 ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
822 ailp->xa_mount->m_fsname);
823 if (IS_ERR(ailp->xa_task))
824 goto out_free_ailp;
825
817 mp->m_ail = ailp; 826 mp->m_ail = ailp;
818 return 0; 827 return 0;
828
829out_free_ailp:
830 kmem_free(ailp);
831 return ENOMEM;
819} 832}
820 833
821void 834void
@@ -824,6 +837,6 @@ xfs_trans_ail_destroy(
824{ 837{
825 struct xfs_ail *ailp = mp->m_ail; 838 struct xfs_ail *ailp = mp->m_ail;
826 839
827 cancel_delayed_work_sync(&ailp->xa_work); 840 kthread_stop(ailp->xa_task);
828 kmem_free(ailp); 841 kmem_free(ailp);
829} 842}