diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 45 |
1 files changed, 9 insertions, 36 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9ef8f99d5a2a..7c644f810816 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -5615,48 +5615,21 @@ void btrfs_block_rsv_release(struct btrfs_root *root, | |||
5615 | num_bytes); | 5615 | num_bytes); |
5616 | } | 5616 | } |
5617 | 5617 | ||
5618 | /* | ||
5619 | * helper to calculate size of global block reservation. | ||
5620 | * the desired value is sum of space used by extent tree, | ||
5621 | * checksum tree and root tree | ||
5622 | */ | ||
5623 | static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info) | ||
5624 | { | ||
5625 | struct btrfs_space_info *sinfo; | ||
5626 | u64 num_bytes; | ||
5627 | u64 meta_used; | ||
5628 | u64 data_used; | ||
5629 | int csum_size = btrfs_super_csum_size(fs_info->super_copy); | ||
5630 | |||
5631 | sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA); | ||
5632 | spin_lock(&sinfo->lock); | ||
5633 | data_used = sinfo->bytes_used; | ||
5634 | spin_unlock(&sinfo->lock); | ||
5635 | |||
5636 | sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA); | ||
5637 | spin_lock(&sinfo->lock); | ||
5638 | if (sinfo->flags & BTRFS_BLOCK_GROUP_DATA) | ||
5639 | data_used = 0; | ||
5640 | meta_used = sinfo->bytes_used; | ||
5641 | spin_unlock(&sinfo->lock); | ||
5642 | |||
5643 | num_bytes = (data_used >> fs_info->sb->s_blocksize_bits) * | ||
5644 | csum_size * 2; | ||
5645 | num_bytes += div_u64(data_used + meta_used, 50); | ||
5646 | |||
5647 | if (num_bytes * 3 > meta_used) | ||
5648 | num_bytes = div_u64(meta_used, 3); | ||
5649 | |||
5650 | return ALIGN(num_bytes, fs_info->extent_root->nodesize << 10); | ||
5651 | } | ||
5652 | |||
5653 | static void update_global_block_rsv(struct btrfs_fs_info *fs_info) | 5618 | static void update_global_block_rsv(struct btrfs_fs_info *fs_info) |
5654 | { | 5619 | { |
5655 | struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; | 5620 | struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; |
5656 | struct btrfs_space_info *sinfo = block_rsv->space_info; | 5621 | struct btrfs_space_info *sinfo = block_rsv->space_info; |
5657 | u64 num_bytes; | 5622 | u64 num_bytes; |
5658 | 5623 | ||
5659 | num_bytes = calc_global_metadata_size(fs_info); | 5624 | /* |
5625 | * The global block rsv is based on the size of the extent tree, the | ||
5626 | * checksum tree and the root tree. If the fs is empty we want to set | ||
5627 | * it to a minimal amount for safety. | ||
5628 | */ | ||
5629 | num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) + | ||
5630 | btrfs_root_used(&fs_info->csum_root->root_item) + | ||
5631 | btrfs_root_used(&fs_info->tree_root->root_item); | ||
5632 | num_bytes = max_t(u64, num_bytes, SZ_16M); | ||
5660 | 5633 | ||
5661 | spin_lock(&sinfo->lock); | 5634 | spin_lock(&sinfo->lock); |
5662 | spin_lock(&block_rsv->lock); | 5635 | spin_lock(&block_rsv->lock); |