diff options
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 61 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 24 |
3 files changed, 69 insertions, 18 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 0049fe0f3f74..76e4983b39ea 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3056,6 +3056,8 @@ static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_root *root, | |||
3056 | num_items; | 3056 | num_items; |
3057 | } | 3057 | } |
3058 | 3058 | ||
3059 | int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, | ||
3060 | struct btrfs_root *root); | ||
3059 | void btrfs_put_block_group(struct btrfs_block_group_cache *cache); | 3061 | void btrfs_put_block_group(struct btrfs_block_group_cache *cache); |
3060 | int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | 3062 | int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, |
3061 | struct btrfs_root *root, unsigned long count); | 3063 | struct btrfs_root *root, unsigned long count); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index ca1893edda52..6d5c5f73ad64 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2526,6 +2526,51 @@ static int refs_newer(struct btrfs_delayed_ref_root *delayed_refs, int seq, | |||
2526 | return 0; | 2526 | return 0; |
2527 | } | 2527 | } |
2528 | 2528 | ||
2529 | static inline u64 heads_to_leaves(struct btrfs_root *root, u64 heads) | ||
2530 | { | ||
2531 | u64 num_bytes; | ||
2532 | |||
2533 | num_bytes = heads * (sizeof(struct btrfs_extent_item) + | ||
2534 | sizeof(struct btrfs_extent_inline_ref)); | ||
2535 | if (!btrfs_fs_incompat(root->fs_info, SKINNY_METADATA)) | ||
2536 | num_bytes += heads * sizeof(struct btrfs_tree_block_info); | ||
2537 | |||
2538 | /* | ||
2539 | * We don't ever fill up leaves all the way so multiply by 2 just to be | ||
2540 | * closer to what we're really going to want to ouse. | ||
2541 | */ | ||
2542 | return div64_u64(num_bytes, BTRFS_LEAF_DATA_SIZE(root)); | ||
2543 | } | ||
2544 | |||
2545 | int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans, | ||
2546 | struct btrfs_root *root) | ||
2547 | { | ||
2548 | struct btrfs_block_rsv *global_rsv; | ||
2549 | u64 num_heads = trans->transaction->delayed_refs.num_heads_ready; | ||
2550 | u64 num_bytes; | ||
2551 | int ret = 0; | ||
2552 | |||
2553 | num_bytes = btrfs_calc_trans_metadata_size(root, 1); | ||
2554 | num_heads = heads_to_leaves(root, num_heads); | ||
2555 | if (num_heads > 1) | ||
2556 | num_bytes += (num_heads - 1) * root->leafsize; | ||
2557 | num_bytes <<= 1; | ||
2558 | global_rsv = &root->fs_info->global_block_rsv; | ||
2559 | |||
2560 | /* | ||
2561 | * If we can't allocate any more chunks lets make sure we have _lots_ of | ||
2562 | * wiggle room since running delayed refs can create more delayed refs. | ||
2563 | */ | ||
2564 | if (global_rsv->space_info->full) | ||
2565 | num_bytes <<= 1; | ||
2566 | |||
2567 | spin_lock(&global_rsv->lock); | ||
2568 | if (global_rsv->reserved <= num_bytes) | ||
2569 | ret = 1; | ||
2570 | spin_unlock(&global_rsv->lock); | ||
2571 | return ret; | ||
2572 | } | ||
2573 | |||
2529 | /* | 2574 | /* |
2530 | * this starts processing the delayed reference count updates and | 2575 | * this starts processing the delayed reference count updates and |
2531 | * extent insertions we have queued up so far. count can be | 2576 | * extent insertions we have queued up so far. count can be |
@@ -2573,7 +2618,8 @@ progress: | |||
2573 | old = atomic_cmpxchg(&delayed_refs->procs_running_refs, 0, 1); | 2618 | old = atomic_cmpxchg(&delayed_refs->procs_running_refs, 0, 1); |
2574 | if (old) { | 2619 | if (old) { |
2575 | DEFINE_WAIT(__wait); | 2620 | DEFINE_WAIT(__wait); |
2576 | if (delayed_refs->num_entries < 16348) | 2621 | if (delayed_refs->flushing || |
2622 | !btrfs_should_throttle_delayed_refs(trans, root)) | ||
2577 | return 0; | 2623 | return 0; |
2578 | 2624 | ||
2579 | prepare_to_wait(&delayed_refs->wait, &__wait, | 2625 | prepare_to_wait(&delayed_refs->wait, &__wait, |
@@ -2608,7 +2654,7 @@ again: | |||
2608 | 2654 | ||
2609 | while (1) { | 2655 | while (1) { |
2610 | if (!(run_all || run_most) && | 2656 | if (!(run_all || run_most) && |
2611 | delayed_refs->num_heads_ready < 64) | 2657 | !btrfs_should_throttle_delayed_refs(trans, root)) |
2612 | break; | 2658 | break; |
2613 | 2659 | ||
2614 | /* | 2660 | /* |
@@ -8665,8 +8711,15 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) | |||
8665 | if (end - start >= range->minlen) { | 8711 | if (end - start >= range->minlen) { |
8666 | if (!block_group_cache_done(cache)) { | 8712 | if (!block_group_cache_done(cache)) { |
8667 | ret = cache_block_group(cache, 0); | 8713 | ret = cache_block_group(cache, 0); |
8668 | if (!ret) | 8714 | if (ret) { |
8669 | wait_block_group_cache_done(cache); | 8715 | btrfs_put_block_group(cache); |
8716 | break; | ||
8717 | } | ||
8718 | ret = wait_block_group_cache_done(cache); | ||
8719 | if (ret) { | ||
8720 | btrfs_put_block_group(cache); | ||
8721 | break; | ||
8722 | } | ||
8670 | } | 8723 | } |
8671 | ret = btrfs_trim_block_group(cache, | 8724 | ret = btrfs_trim_block_group(cache, |
8672 | &group_trimmed, | 8725 | &group_trimmed, |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c11b7efcc561..c916ebdc689a 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -615,10 +615,11 @@ void btrfs_throttle(struct btrfs_root *root) | |||
615 | static int should_end_transaction(struct btrfs_trans_handle *trans, | 615 | static int should_end_transaction(struct btrfs_trans_handle *trans, |
616 | struct btrfs_root *root) | 616 | struct btrfs_root *root) |
617 | { | 617 | { |
618 | int ret; | 618 | if (root->fs_info->global_block_rsv.space_info->full && |
619 | btrfs_should_throttle_delayed_refs(trans, root)) | ||
620 | return 1; | ||
619 | 621 | ||
620 | ret = btrfs_block_rsv_check(root, &root->fs_info->global_block_rsv, 5); | 622 | return !!btrfs_block_rsv_check(root, &root->fs_info->global_block_rsv, 5); |
621 | return ret ? 1 : 0; | ||
622 | } | 623 | } |
623 | 624 | ||
624 | int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | 625 | int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, |
@@ -649,7 +650,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
649 | { | 650 | { |
650 | struct btrfs_transaction *cur_trans = trans->transaction; | 651 | struct btrfs_transaction *cur_trans = trans->transaction; |
651 | struct btrfs_fs_info *info = root->fs_info; | 652 | struct btrfs_fs_info *info = root->fs_info; |
652 | int count = 0; | 653 | unsigned long cur = trans->delayed_ref_updates; |
653 | int lock = (trans->type != TRANS_JOIN_NOLOCK); | 654 | int lock = (trans->type != TRANS_JOIN_NOLOCK); |
654 | int err = 0; | 655 | int err = 0; |
655 | 656 | ||
@@ -678,17 +679,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
678 | if (!list_empty(&trans->new_bgs)) | 679 | if (!list_empty(&trans->new_bgs)) |
679 | btrfs_create_pending_block_groups(trans, root); | 680 | btrfs_create_pending_block_groups(trans, root); |
680 | 681 | ||
681 | while (count < 1) { | 682 | trans->delayed_ref_updates = 0; |
682 | unsigned long cur = trans->delayed_ref_updates; | 683 | if (btrfs_should_throttle_delayed_refs(trans, root)) { |
684 | cur = max_t(unsigned long, cur, 1); | ||
683 | trans->delayed_ref_updates = 0; | 685 | trans->delayed_ref_updates = 0; |
684 | if (cur && | 686 | btrfs_run_delayed_refs(trans, root, cur); |
685 | trans->transaction->delayed_refs.num_heads_ready > 64) { | ||
686 | trans->delayed_ref_updates = 0; | ||
687 | btrfs_run_delayed_refs(trans, root, cur); | ||
688 | } else { | ||
689 | break; | ||
690 | } | ||
691 | count++; | ||
692 | } | 687 | } |
693 | 688 | ||
694 | btrfs_trans_release_metadata(trans, root); | 689 | btrfs_trans_release_metadata(trans, root); |
@@ -1626,6 +1621,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1626 | * start sending their work down. | 1621 | * start sending their work down. |
1627 | */ | 1622 | */ |
1628 | cur_trans->delayed_refs.flushing = 1; | 1623 | cur_trans->delayed_refs.flushing = 1; |
1624 | smp_wmb(); | ||
1629 | 1625 | ||
1630 | if (!list_empty(&trans->new_bgs)) | 1626 | if (!list_empty(&trans->new_bgs)) |
1631 | btrfs_create_pending_block_groups(trans, root); | 1627 | btrfs_create_pending_block_groups(trans, root); |