diff options
Diffstat (limited to 'fs/xfs/xfs_log_cil.c')
-rw-r--r-- | fs/xfs/xfs_log_cil.c | 253 |
1 files changed, 154 insertions, 99 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index d4fadbe8ac9..7d6197c5849 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -18,9 +18,7 @@ | |||
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
21 | #include "xfs_bit.h" | ||
22 | #include "xfs_log.h" | 21 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | ||
24 | #include "xfs_trans.h" | 22 | #include "xfs_trans.h" |
25 | #include "xfs_trans_priv.h" | 23 | #include "xfs_trans_priv.h" |
26 | #include "xfs_log_priv.h" | 24 | #include "xfs_log_priv.h" |
@@ -29,61 +27,10 @@ | |||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_error.h" | 28 | #include "xfs_error.h" |
31 | #include "xfs_alloc.h" | 29 | #include "xfs_alloc.h" |
30 | #include "xfs_extent_busy.h" | ||
32 | #include "xfs_discard.h" | 31 | #include "xfs_discard.h" |
33 | 32 | ||
34 | /* | 33 | /* |
35 | * Perform initial CIL structure initialisation. | ||
36 | */ | ||
37 | int | ||
38 | xlog_cil_init( | ||
39 | struct log *log) | ||
40 | { | ||
41 | struct xfs_cil *cil; | ||
42 | struct xfs_cil_ctx *ctx; | ||
43 | |||
44 | cil = kmem_zalloc(sizeof(*cil), KM_SLEEP|KM_MAYFAIL); | ||
45 | if (!cil) | ||
46 | return ENOMEM; | ||
47 | |||
48 | ctx = kmem_zalloc(sizeof(*ctx), KM_SLEEP|KM_MAYFAIL); | ||
49 | if (!ctx) { | ||
50 | kmem_free(cil); | ||
51 | return ENOMEM; | ||
52 | } | ||
53 | |||
54 | INIT_LIST_HEAD(&cil->xc_cil); | ||
55 | INIT_LIST_HEAD(&cil->xc_committing); | ||
56 | spin_lock_init(&cil->xc_cil_lock); | ||
57 | init_rwsem(&cil->xc_ctx_lock); | ||
58 | init_waitqueue_head(&cil->xc_commit_wait); | ||
59 | |||
60 | INIT_LIST_HEAD(&ctx->committing); | ||
61 | INIT_LIST_HEAD(&ctx->busy_extents); | ||
62 | ctx->sequence = 1; | ||
63 | ctx->cil = cil; | ||
64 | cil->xc_ctx = ctx; | ||
65 | cil->xc_current_sequence = ctx->sequence; | ||
66 | |||
67 | cil->xc_log = log; | ||
68 | log->l_cilp = cil; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | void | ||
73 | xlog_cil_destroy( | ||
74 | struct log *log) | ||
75 | { | ||
76 | if (log->l_cilp->xc_ctx) { | ||
77 | if (log->l_cilp->xc_ctx->ticket) | ||
78 | xfs_log_ticket_put(log->l_cilp->xc_ctx->ticket); | ||
79 | kmem_free(log->l_cilp->xc_ctx); | ||
80 | } | ||
81 | |||
82 | ASSERT(list_empty(&log->l_cilp->xc_cil)); | ||
83 | kmem_free(log->l_cilp); | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * Allocate a new ticket. Failing to get a new ticket makes it really hard to | 34 | * Allocate a new ticket. Failing to get a new ticket makes it really hard to |
88 | * recover, so we don't allow failure here. Also, we allocate in a context that | 35 | * recover, so we don't allow failure here. Also, we allocate in a context that |
89 | * we don't want to be issuing transactions from, so we need to tell the | 36 | * we don't want to be issuing transactions from, so we need to tell the |
@@ -390,8 +337,8 @@ xlog_cil_committed( | |||
390 | xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain, | 337 | xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain, |
391 | ctx->start_lsn, abort); | 338 | ctx->start_lsn, abort); |
392 | 339 | ||
393 | xfs_alloc_busy_sort(&ctx->busy_extents); | 340 | xfs_extent_busy_sort(&ctx->busy_extents); |
394 | xfs_alloc_busy_clear(mp, &ctx->busy_extents, | 341 | xfs_extent_busy_clear(mp, &ctx->busy_extents, |
395 | (mp->m_flags & XFS_MOUNT_DISCARD) && !abort); | 342 | (mp->m_flags & XFS_MOUNT_DISCARD) && !abort); |
396 | 343 | ||
397 | spin_lock(&ctx->cil->xc_cil_lock); | 344 | spin_lock(&ctx->cil->xc_cil_lock); |
@@ -404,7 +351,7 @@ xlog_cil_committed( | |||
404 | ASSERT(mp->m_flags & XFS_MOUNT_DISCARD); | 351 | ASSERT(mp->m_flags & XFS_MOUNT_DISCARD); |
405 | 352 | ||
406 | xfs_discard_extents(mp, &ctx->busy_extents); | 353 | xfs_discard_extents(mp, &ctx->busy_extents); |
407 | xfs_alloc_busy_clear(mp, &ctx->busy_extents, false); | 354 | xfs_extent_busy_clear(mp, &ctx->busy_extents, false); |
408 | } | 355 | } |
409 | 356 | ||
410 | kmem_free(ctx); | 357 | kmem_free(ctx); |
@@ -426,8 +373,7 @@ xlog_cil_committed( | |||
426 | */ | 373 | */ |
427 | STATIC int | 374 | STATIC int |
428 | xlog_cil_push( | 375 | xlog_cil_push( |
429 | struct log *log, | 376 | struct log *log) |
430 | xfs_lsn_t push_seq) | ||
431 | { | 377 | { |
432 | struct xfs_cil *cil = log->l_cilp; | 378 | struct xfs_cil *cil = log->l_cilp; |
433 | struct xfs_log_vec *lv; | 379 | struct xfs_log_vec *lv; |
@@ -443,39 +389,36 @@ xlog_cil_push( | |||
443 | struct xfs_log_iovec lhdr; | 389 | struct xfs_log_iovec lhdr; |
444 | struct xfs_log_vec lvhdr = { NULL }; | 390 | struct xfs_log_vec lvhdr = { NULL }; |
445 | xfs_lsn_t commit_lsn; | 391 | xfs_lsn_t commit_lsn; |
392 | xfs_lsn_t push_seq; | ||
446 | 393 | ||
447 | if (!cil) | 394 | if (!cil) |
448 | return 0; | 395 | return 0; |
449 | 396 | ||
450 | ASSERT(!push_seq || push_seq <= cil->xc_ctx->sequence); | ||
451 | |||
452 | new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS); | 397 | new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS); |
453 | new_ctx->ticket = xlog_cil_ticket_alloc(log); | 398 | new_ctx->ticket = xlog_cil_ticket_alloc(log); |
454 | 399 | ||
455 | /* | 400 | down_write(&cil->xc_ctx_lock); |
456 | * Lock out transaction commit, but don't block for background pushes | ||
457 | * unless we are well over the CIL space limit. See the definition of | ||
458 | * XLOG_CIL_HARD_SPACE_LIMIT() for the full explanation of the logic | ||
459 | * used here. | ||
460 | */ | ||
461 | if (!down_write_trylock(&cil->xc_ctx_lock)) { | ||
462 | if (!push_seq && | ||
463 | cil->xc_ctx->space_used < XLOG_CIL_HARD_SPACE_LIMIT(log)) | ||
464 | goto out_free_ticket; | ||
465 | down_write(&cil->xc_ctx_lock); | ||
466 | } | ||
467 | ctx = cil->xc_ctx; | 401 | ctx = cil->xc_ctx; |
468 | 402 | ||
469 | /* check if we've anything to push */ | 403 | spin_lock(&cil->xc_cil_lock); |
470 | if (list_empty(&cil->xc_cil)) | 404 | push_seq = cil->xc_push_seq; |
471 | goto out_skip; | 405 | ASSERT(push_seq <= ctx->sequence); |
472 | 406 | ||
473 | /* check for spurious background flush */ | 407 | /* |
474 | if (!push_seq && cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log)) | 408 | * Check if we've anything to push. If there is nothing, then we don't |
409 | * move on to a new sequence number and so we have to be able to push | ||
410 | * this sequence again later. | ||
411 | */ | ||
412 | if (list_empty(&cil->xc_cil)) { | ||
413 | cil->xc_push_seq = 0; | ||
414 | spin_unlock(&cil->xc_cil_lock); | ||
475 | goto out_skip; | 415 | goto out_skip; |
416 | } | ||
417 | spin_unlock(&cil->xc_cil_lock); | ||
418 | |||
476 | 419 | ||
477 | /* check for a previously pushed seqeunce */ | 420 | /* check for a previously pushed seqeunce */ |
478 | if (push_seq && push_seq < cil->xc_ctx->sequence) | 421 | if (push_seq < cil->xc_ctx->sequence) |
479 | goto out_skip; | 422 | goto out_skip; |
480 | 423 | ||
481 | /* | 424 | /* |
@@ -629,7 +572,6 @@ restart: | |||
629 | 572 | ||
630 | out_skip: | 573 | out_skip: |
631 | up_write(&cil->xc_ctx_lock); | 574 | up_write(&cil->xc_ctx_lock); |
632 | out_free_ticket: | ||
633 | xfs_log_ticket_put(new_ctx->ticket); | 575 | xfs_log_ticket_put(new_ctx->ticket); |
634 | kmem_free(new_ctx); | 576 | kmem_free(new_ctx); |
635 | return 0; | 577 | return 0; |
@@ -641,6 +583,82 @@ out_abort: | |||
641 | return XFS_ERROR(EIO); | 583 | return XFS_ERROR(EIO); |
642 | } | 584 | } |
643 | 585 | ||
586 | static void | ||
587 | xlog_cil_push_work( | ||
588 | struct work_struct *work) | ||
589 | { | ||
590 | struct xfs_cil *cil = container_of(work, struct xfs_cil, | ||
591 | xc_push_work); | ||
592 | xlog_cil_push(cil->xc_log); | ||
593 | } | ||
594 | |||
595 | /* | ||
596 | * We need to push CIL every so often so we don't cache more than we can fit in | ||
597 | * the log. The limit really is that a checkpoint can't be more than half the | ||
598 | * log (the current checkpoint is not allowed to overwrite the previous | ||
599 | * checkpoint), but commit latency and memory usage limit this to a smaller | ||
600 | * size. | ||
601 | */ | ||
602 | static void | ||
603 | xlog_cil_push_background( | ||
604 | struct log *log) | ||
605 | { | ||
606 | struct xfs_cil *cil = log->l_cilp; | ||
607 | |||
608 | /* | ||
609 | * The cil won't be empty because we are called while holding the | ||
610 | * context lock so whatever we added to the CIL will still be there | ||
611 | */ | ||
612 | ASSERT(!list_empty(&cil->xc_cil)); | ||
613 | |||
614 | /* | ||
615 | * don't do a background push if we haven't used up all the | ||
616 | * space available yet. | ||
617 | */ | ||
618 | if (cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log)) | ||
619 | return; | ||
620 | |||
621 | spin_lock(&cil->xc_cil_lock); | ||
622 | if (cil->xc_push_seq < cil->xc_current_sequence) { | ||
623 | cil->xc_push_seq = cil->xc_current_sequence; | ||
624 | queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work); | ||
625 | } | ||
626 | spin_unlock(&cil->xc_cil_lock); | ||
627 | |||
628 | } | ||
629 | |||
630 | static void | ||
631 | xlog_cil_push_foreground( | ||
632 | struct log *log, | ||
633 | xfs_lsn_t push_seq) | ||
634 | { | ||
635 | struct xfs_cil *cil = log->l_cilp; | ||
636 | |||
637 | if (!cil) | ||
638 | return; | ||
639 | |||
640 | ASSERT(push_seq && push_seq <= cil->xc_current_sequence); | ||
641 | |||
642 | /* start on any pending background push to minimise wait time on it */ | ||
643 | flush_work(&cil->xc_push_work); | ||
644 | |||
645 | /* | ||
646 | * If the CIL is empty or we've already pushed the sequence then | ||
647 | * there's no work we need to do. | ||
648 | */ | ||
649 | spin_lock(&cil->xc_cil_lock); | ||
650 | if (list_empty(&cil->xc_cil) || push_seq <= cil->xc_push_seq) { | ||
651 | spin_unlock(&cil->xc_cil_lock); | ||
652 | return; | ||
653 | } | ||
654 | |||
655 | cil->xc_push_seq = push_seq; | ||
656 | spin_unlock(&cil->xc_cil_lock); | ||
657 | |||
658 | /* do the push now */ | ||
659 | xlog_cil_push(log); | ||
660 | } | ||
661 | |||
644 | /* | 662 | /* |
645 | * Commit a transaction with the given vector to the Committed Item List. | 663 | * Commit a transaction with the given vector to the Committed Item List. |
646 | * | 664 | * |
@@ -667,7 +685,6 @@ xfs_log_commit_cil( | |||
667 | { | 685 | { |
668 | struct log *log = mp->m_log; | 686 | struct log *log = mp->m_log; |
669 | int log_flags = 0; | 687 | int log_flags = 0; |
670 | int push = 0; | ||
671 | struct xfs_log_vec *log_vector; | 688 | struct xfs_log_vec *log_vector; |
672 | 689 | ||
673 | if (flags & XFS_TRANS_RELEASE_LOG_RES) | 690 | if (flags & XFS_TRANS_RELEASE_LOG_RES) |
@@ -719,21 +736,9 @@ xfs_log_commit_cil( | |||
719 | */ | 736 | */ |
720 | xfs_trans_free_items(tp, *commit_lsn, 0); | 737 | xfs_trans_free_items(tp, *commit_lsn, 0); |
721 | 738 | ||
722 | /* check for background commit before unlock */ | 739 | xlog_cil_push_background(log); |
723 | if (log->l_cilp->xc_ctx->space_used > XLOG_CIL_SPACE_LIMIT(log)) | ||
724 | push = 1; | ||
725 | 740 | ||
726 | up_read(&log->l_cilp->xc_ctx_lock); | 741 | up_read(&log->l_cilp->xc_ctx_lock); |
727 | |||
728 | /* | ||
729 | * We need to push CIL every so often so we don't cache more than we | ||
730 | * can fit in the log. The limit really is that a checkpoint can't be | ||
731 | * more than half the log (the current checkpoint is not allowed to | ||
732 | * overwrite the previous checkpoint), but commit latency and memory | ||
733 | * usage limit this to a smaller size in most cases. | ||
734 | */ | ||
735 | if (push) | ||
736 | xlog_cil_push(log, 0); | ||
737 | return 0; | 742 | return 0; |
738 | } | 743 | } |
739 | 744 | ||
@@ -746,9 +751,6 @@ xfs_log_commit_cil( | |||
746 | * | 751 | * |
747 | * We return the current commit lsn to allow the callers to determine if a | 752 | * We return the current commit lsn to allow the callers to determine if a |
748 | * iclog flush is necessary following this call. | 753 | * iclog flush is necessary following this call. |
749 | * | ||
750 | * XXX: Initially, just push the CIL unconditionally and return whatever | ||
751 | * commit lsn is there. It'll be empty, so this is broken for now. | ||
752 | */ | 754 | */ |
753 | xfs_lsn_t | 755 | xfs_lsn_t |
754 | xlog_cil_force_lsn( | 756 | xlog_cil_force_lsn( |
@@ -766,8 +768,7 @@ xlog_cil_force_lsn( | |||
766 | * xlog_cil_push() handles racing pushes for the same sequence, | 768 | * xlog_cil_push() handles racing pushes for the same sequence, |
767 | * so no need to deal with it here. | 769 | * so no need to deal with it here. |
768 | */ | 770 | */ |
769 | if (sequence == cil->xc_current_sequence) | 771 | xlog_cil_push_foreground(log, sequence); |
770 | xlog_cil_push(log, sequence); | ||
771 | 772 | ||
772 | /* | 773 | /* |
773 | * See if we can find a previous sequence still committing. | 774 | * See if we can find a previous sequence still committing. |
@@ -826,3 +827,57 @@ xfs_log_item_in_current_chkpt( | |||
826 | return false; | 827 | return false; |
827 | return true; | 828 | return true; |
828 | } | 829 | } |
830 | |||
831 | /* | ||
832 | * Perform initial CIL structure initialisation. | ||
833 | */ | ||
834 | int | ||
835 | xlog_cil_init( | ||
836 | struct log *log) | ||
837 | { | ||
838 | struct xfs_cil *cil; | ||
839 | struct xfs_cil_ctx *ctx; | ||
840 | |||
841 | cil = kmem_zalloc(sizeof(*cil), KM_SLEEP|KM_MAYFAIL); | ||
842 | if (!cil) | ||
843 | return ENOMEM; | ||
844 | |||
845 | ctx = kmem_zalloc(sizeof(*ctx), KM_SLEEP|KM_MAYFAIL); | ||
846 | if (!ctx) { | ||
847 | kmem_free(cil); | ||
848 | return ENOMEM; | ||
849 | } | ||
850 | |||
851 | INIT_WORK(&cil->xc_push_work, xlog_cil_push_work); | ||
852 | INIT_LIST_HEAD(&cil->xc_cil); | ||
853 | INIT_LIST_HEAD(&cil->xc_committing); | ||
854 | spin_lock_init(&cil->xc_cil_lock); | ||
855 | init_rwsem(&cil->xc_ctx_lock); | ||
856 | init_waitqueue_head(&cil->xc_commit_wait); | ||
857 | |||
858 | INIT_LIST_HEAD(&ctx->committing); | ||
859 | INIT_LIST_HEAD(&ctx->busy_extents); | ||
860 | ctx->sequence = 1; | ||
861 | ctx->cil = cil; | ||
862 | cil->xc_ctx = ctx; | ||
863 | cil->xc_current_sequence = ctx->sequence; | ||
864 | |||
865 | cil->xc_log = log; | ||
866 | log->l_cilp = cil; | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | void | ||
871 | xlog_cil_destroy( | ||
872 | struct log *log) | ||
873 | { | ||
874 | if (log->l_cilp->xc_ctx) { | ||
875 | if (log->l_cilp->xc_ctx->ticket) | ||
876 | xfs_log_ticket_put(log->l_cilp->xc_ctx->ticket); | ||
877 | kmem_free(log->l_cilp->xc_ctx); | ||
878 | } | ||
879 | |||
880 | ASSERT(list_empty(&log->l_cilp->xc_cil)); | ||
881 | kmem_free(log->l_cilp); | ||
882 | } | ||
883 | |||