diff options
-rw-r--r-- | fs/xfs/xfs_linux.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_super.c | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_ail.c | 73 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_priv.h | 8 |
4 files changed, 45 insertions, 51 deletions
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h index 1e8a45e74c3e..828662f70d64 100644 --- a/fs/xfs/xfs_linux.h +++ b/fs/xfs/xfs_linux.h | |||
@@ -68,6 +68,8 @@ | |||
68 | #include <linux/ctype.h> | 68 | #include <linux/ctype.h> |
69 | #include <linux/writeback.h> | 69 | #include <linux/writeback.h> |
70 | #include <linux/capability.h> | 70 | #include <linux/capability.h> |
71 | #include <linux/kthread.h> | ||
72 | #include <linux/freezer.h> | ||
71 | #include <linux/list_sort.h> | 73 | #include <linux/list_sort.h> |
72 | 74 | ||
73 | #include <asm/page.h> | 75 | #include <asm/page.h> |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 2366c54cc4fa..5cf06b85fd9d 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -1652,24 +1652,13 @@ xfs_init_workqueues(void) | |||
1652 | */ | 1652 | */ |
1653 | xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8); | 1653 | xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8); |
1654 | if (!xfs_syncd_wq) | 1654 | if (!xfs_syncd_wq) |
1655 | goto out; | 1655 | return -ENOMEM; |
1656 | |||
1657 | xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8); | ||
1658 | if (!xfs_ail_wq) | ||
1659 | goto out_destroy_syncd; | ||
1660 | |||
1661 | return 0; | 1656 | return 0; |
1662 | |||
1663 | out_destroy_syncd: | ||
1664 | destroy_workqueue(xfs_syncd_wq); | ||
1665 | out: | ||
1666 | return -ENOMEM; | ||
1667 | } | 1657 | } |
1668 | 1658 | ||
1669 | STATIC void | 1659 | STATIC void |
1670 | xfs_destroy_workqueues(void) | 1660 | xfs_destroy_workqueues(void) |
1671 | { | 1661 | { |
1672 | destroy_workqueue(xfs_ail_wq); | ||
1673 | destroy_workqueue(xfs_syncd_wq); | 1662 | destroy_workqueue(xfs_syncd_wq); |
1674 | } | 1663 | } |
1675 | 1664 | ||
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index e4cd9180d33a..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 | ||
31 | struct 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 | /* | 357 | static long |
360 | * xfs_ail_worker does the work of pushing on the AIL. It will requeue itself | 358 | xfsaild_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 | */ | ||
363 | STATIC void | ||
364 | xfs_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; |
@@ -505,20 +497,6 @@ out_done: | |||
505 | /* We're past our target or empty, so idle */ | 497 | /* We're past our target or empty, so idle */ |
506 | ailp->xa_last_pushed_lsn = 0; | 498 | ailp->xa_last_pushed_lsn = 0; |
507 | 499 | ||
508 | /* | ||
509 | * We clear the XFS_AIL_PUSHING_BIT first before checking | ||
510 | * whether the target has changed. If the target has changed, | ||
511 | * this pushes the requeue race directly onto the result of the | ||
512 | * atomic test/set bit, so we are guaranteed that either the | ||
513 | * the pusher that changed the target or ourselves will requeue | ||
514 | * the work (but not both). | ||
515 | */ | ||
516 | clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); | ||
517 | smp_rmb(); | ||
518 | if (XFS_LSN_CMP(ailp->xa_target, target) == 0 || | ||
519 | test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) | ||
520 | return; | ||
521 | |||
522 | tout = 50; | 500 | tout = 50; |
523 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { | 501 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { |
524 | /* | 502 | /* |
@@ -541,9 +519,30 @@ out_done: | |||
541 | tout = 20; | 519 | tout = 20; |
542 | } | 520 | } |
543 | 521 | ||
544 | /* There is more to do, requeue us. */ | 522 | return tout; |
545 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, | 523 | } |
546 | msecs_to_jiffies(tout)); | 524 | |
525 | static int | ||
526 | xfsaild( | ||
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; | ||
547 | } | 546 | } |
548 | 547 | ||
549 | /* | 548 | /* |
@@ -578,8 +577,9 @@ xfs_ail_push( | |||
578 | */ | 577 | */ |
579 | smp_wmb(); | 578 | smp_wmb(); |
580 | xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); | 579 | xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); |
581 | if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) | 580 | smp_wmb(); |
582 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); | 581 | |
582 | wake_up_process(ailp->xa_task); | ||
583 | } | 583 | } |
584 | 584 | ||
585 | /* | 585 | /* |
@@ -817,9 +817,18 @@ xfs_trans_ail_init( | |||
817 | INIT_LIST_HEAD(&ailp->xa_ail); | 817 | INIT_LIST_HEAD(&ailp->xa_ail); |
818 | INIT_LIST_HEAD(&ailp->xa_cursors); | 818 | INIT_LIST_HEAD(&ailp->xa_cursors); |
819 | spin_lock_init(&ailp->xa_lock); | 819 | spin_lock_init(&ailp->xa_lock); |
820 | 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 | |||
821 | mp->m_ail = ailp; | 826 | mp->m_ail = ailp; |
822 | return 0; | 827 | return 0; |
828 | |||
829 | out_free_ailp: | ||
830 | kmem_free(ailp); | ||
831 | return ENOMEM; | ||
823 | } | 832 | } |
824 | 833 | ||
825 | void | 834 | void |
@@ -828,6 +837,6 @@ xfs_trans_ail_destroy( | |||
828 | { | 837 | { |
829 | struct xfs_ail *ailp = mp->m_ail; | 838 | struct xfs_ail *ailp = mp->m_ail; |
830 | 839 | ||
831 | cancel_delayed_work_sync(&ailp->xa_work); | 840 | kthread_stop(ailp->xa_task); |
832 | kmem_free(ailp); | 841 | kmem_free(ailp); |
833 | } | 842 | } |
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 212946b97239..22750b5e4a8f 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h | |||
@@ -64,23 +64,17 @@ struct xfs_ail_cursor { | |||
64 | */ | 64 | */ |
65 | struct xfs_ail { | 65 | struct xfs_ail { |
66 | struct xfs_mount *xa_mount; | 66 | struct xfs_mount *xa_mount; |
67 | struct task_struct *xa_task; | ||
67 | struct list_head xa_ail; | 68 | struct list_head xa_ail; |
68 | xfs_lsn_t xa_target; | 69 | xfs_lsn_t xa_target; |
69 | struct list_head xa_cursors; | 70 | struct list_head xa_cursors; |
70 | spinlock_t xa_lock; | 71 | spinlock_t xa_lock; |
71 | struct delayed_work xa_work; | ||
72 | xfs_lsn_t xa_last_pushed_lsn; | 72 | xfs_lsn_t xa_last_pushed_lsn; |
73 | unsigned long xa_flags; | ||
74 | }; | 73 | }; |
75 | 74 | ||
76 | #define XFS_AIL_PUSHING_BIT 0 | ||
77 | |||
78 | /* | 75 | /* |
79 | * From xfs_trans_ail.c | 76 | * From xfs_trans_ail.c |
80 | */ | 77 | */ |
81 | |||
82 | extern struct workqueue_struct *xfs_ail_wq; /* AIL workqueue */ | ||
83 | |||
84 | void xfs_trans_ail_update_bulk(struct xfs_ail *ailp, | 78 | void xfs_trans_ail_update_bulk(struct xfs_ail *ailp, |
85 | struct xfs_ail_cursor *cur, | 79 | struct xfs_ail_cursor *cur, |
86 | struct xfs_log_item **log_items, int nr_items, | 80 | struct xfs_log_item **log_items, int nr_items, |