aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-06-12 13:56:06 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-07-01 08:52:28 -0400
commit1be41b78bc688fc634bf30965d2be692c99fd11d (patch)
treeca8e1c5dc3b74b867d2e68215ff7f3d8526457d5 /fs
parent501407aab8c947911b10cf5a0e0043019d5a4f17 (diff)
Btrfs: fix transaction throttling for delayed refs
Dave has this fs_mark script that can make btrfs abort with sufficient amount of ram. This is because with more ram we can keep more dirty metadata in cache which in a round about way makes for many more pending delayed refs. What happens is we end up not throttling the transaction enough so when we go to commit the transaction when we've completely filled the file system we'll abort() because we use all of the space in the global reserve and we still have delayed refs to run. To fix this we need to make the delayed ref flushing and the transaction throttling dependant upon the number of delayed refs that we have instead of how much reserved space is left in the global reserve. With this patch we not only stop aborting transactions but we also get a smoother run speed with fs_mark and it makes us about 10% faster. Thanks, Reported-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c61
-rw-r--r--fs/btrfs/transaction.c24
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
3059int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans,
3060 struct btrfs_root *root);
3059void btrfs_put_block_group(struct btrfs_block_group_cache *cache); 3061void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
3060int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, 3062int 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
2529static 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
2545int 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)
615static int should_end_transaction(struct btrfs_trans_handle *trans, 615static 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
624int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, 625int 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);