diff options
author | Alex Elder <aelder@sgi.com> | 2011-10-17 16:42:02 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2011-10-17 16:42:02 -0400 |
commit | 9508534c5f170ada5a745cde0df49732718440e9 (patch) | |
tree | 2b0f1e19aa529e77720522d13541adedbc46564e /fs/xfs/xfs_trans_ail.c | |
parent | 5a93a064d27b42e4af1772b0599b53e3241191ac (diff) | |
parent | a84a79e4d369a73c0130b5858199e949432da4c6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
Resolved conflicts:
fs/xfs/xfs_trans_priv.h:
- deleted struct xfs_ail field xa_flags
- kept field xa_log_flush in struct xfs_ail
fs/xfs/xfs_trans_ail.c:
- in xfsaild_push(), in XFS_ITEM_PUSHBUF case, replaced
"flush_log = 1" with "ailp->xa_log_flush++"
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_trans_ail.c')
-rw-r--r-- | fs/xfs/xfs_trans_ail.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 9df7f9f1b5ee..512ff646d01c 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; |
@@ -439,8 +431,13 @@ xfs_ail_worker( | |||
439 | 431 | ||
440 | case XFS_ITEM_PUSHBUF: | 432 | case XFS_ITEM_PUSHBUF: |
441 | XFS_STATS_INC(xs_push_ail_pushbuf); | 433 | XFS_STATS_INC(xs_push_ail_pushbuf); |
442 | IOP_PUSHBUF(lip); | 434 | |
443 | ailp->xa_last_pushed_lsn = lsn; | 435 | if (!IOP_PUSHBUF(lip)) { |
436 | stuck++; | ||
437 | flush_log = 1; | ||
438 | } else { | ||
439 | ailp->xa_last_pushed_lsn = lsn; | ||
440 | } | ||
444 | push_xfsbufd = 1; | 441 | push_xfsbufd = 1; |
445 | break; | 442 | break; |
446 | 443 | ||
@@ -452,7 +449,6 @@ xfs_ail_worker( | |||
452 | 449 | ||
453 | case XFS_ITEM_LOCKED: | 450 | case XFS_ITEM_LOCKED: |
454 | XFS_STATS_INC(xs_push_ail_locked); | 451 | XFS_STATS_INC(xs_push_ail_locked); |
455 | ailp->xa_last_pushed_lsn = lsn; | ||
456 | stuck++; | 452 | stuck++; |
457 | break; | 453 | break; |
458 | 454 | ||
@@ -504,20 +500,6 @@ out_done: | |||
504 | ailp->xa_last_pushed_lsn = 0; | 500 | ailp->xa_last_pushed_lsn = 0; |
505 | ailp->xa_log_flush = 0; | 501 | ailp->xa_log_flush = 0; |
506 | 502 | ||
507 | /* | ||
508 | * We clear the XFS_AIL_PUSHING_BIT first before checking | ||
509 | * whether the target has changed. If the target has changed, | ||
510 | * this pushes the requeue race directly onto the result of the | ||
511 | * atomic test/set bit, so we are guaranteed that either the | ||
512 | * the pusher that changed the target or ourselves will requeue | ||
513 | * the work (but not both). | ||
514 | */ | ||
515 | clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags); | ||
516 | smp_rmb(); | ||
517 | if (XFS_LSN_CMP(ailp->xa_target, target) == 0 || | ||
518 | test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) | ||
519 | return; | ||
520 | |||
521 | tout = 50; | 503 | tout = 50; |
522 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { | 504 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { |
523 | /* | 505 | /* |
@@ -544,9 +526,30 @@ out_done: | |||
544 | ailp->xa_last_pushed_lsn = 0; | 526 | ailp->xa_last_pushed_lsn = 0; |
545 | } | 527 | } |
546 | 528 | ||
547 | /* There is more to do, requeue us. */ | 529 | return tout; |
548 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, | 530 | } |
549 | msecs_to_jiffies(tout)); | 531 | |
532 | static int | ||
533 | xfsaild( | ||
534 | void *data) | ||
535 | { | ||
536 | struct xfs_ail *ailp = data; | ||
537 | long tout = 0; /* milliseconds */ | ||
538 | |||
539 | while (!kthread_should_stop()) { | ||
540 | if (tout && tout <= 20) | ||
541 | __set_current_state(TASK_KILLABLE); | ||
542 | else | ||
543 | __set_current_state(TASK_INTERRUPTIBLE); | ||
544 | schedule_timeout(tout ? | ||
545 | msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT); | ||
546 | |||
547 | try_to_freeze(); | ||
548 | |||
549 | tout = xfsaild_push(ailp); | ||
550 | } | ||
551 | |||
552 | return 0; | ||
550 | } | 553 | } |
551 | 554 | ||
552 | /* | 555 | /* |
@@ -581,8 +584,9 @@ xfs_ail_push( | |||
581 | */ | 584 | */ |
582 | smp_wmb(); | 585 | smp_wmb(); |
583 | xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); | 586 | xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn); |
584 | if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags)) | 587 | smp_wmb(); |
585 | queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0); | 588 | |
589 | wake_up_process(ailp->xa_task); | ||
586 | } | 590 | } |
587 | 591 | ||
588 | /* | 592 | /* |
@@ -820,9 +824,18 @@ xfs_trans_ail_init( | |||
820 | INIT_LIST_HEAD(&ailp->xa_ail); | 824 | INIT_LIST_HEAD(&ailp->xa_ail); |
821 | INIT_LIST_HEAD(&ailp->xa_cursors); | 825 | INIT_LIST_HEAD(&ailp->xa_cursors); |
822 | spin_lock_init(&ailp->xa_lock); | 826 | spin_lock_init(&ailp->xa_lock); |
823 | INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker); | 827 | |
828 | ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s", | ||
829 | ailp->xa_mount->m_fsname); | ||
830 | if (IS_ERR(ailp->xa_task)) | ||
831 | goto out_free_ailp; | ||
832 | |||
824 | mp->m_ail = ailp; | 833 | mp->m_ail = ailp; |
825 | return 0; | 834 | return 0; |
835 | |||
836 | out_free_ailp: | ||
837 | kmem_free(ailp); | ||
838 | return ENOMEM; | ||
826 | } | 839 | } |
827 | 840 | ||
828 | void | 841 | void |
@@ -831,6 +844,6 @@ xfs_trans_ail_destroy( | |||
831 | { | 844 | { |
832 | struct xfs_ail *ailp = mp->m_ail; | 845 | struct xfs_ail *ailp = mp->m_ail; |
833 | 846 | ||
834 | cancel_delayed_work_sync(&ailp->xa_work); | 847 | kthread_stop(ailp->xa_task); |
835 | kmem_free(ailp); | 848 | kmem_free(ailp); |
836 | } | 849 | } |