aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2016-05-27 12:58:35 -0400
committerDavid Sterba <dsterba@suse.com>2016-07-07 12:45:53 -0400
commitae2e4728816510ae4e8ed2b732b34ea0aba05a34 (patch)
treea420e171bc10700c7863b459919c767bcdc2f9a9 /fs/btrfs
parent87241c2e68451c4d50b60af84f9a3ab119001b4c (diff)
Btrfs: change how we calculate the global block rsv
Traditionally we've calculated the global block rsv by guessing how much of the metadata used amount was the extent tree, and then taking the data size and figuring out how large the csum tree would have to be to hold that much data. This is imprecise and falls down on MIXED file systems as we can't trust the data used amount. This resulted in failures for xfstests generic/333 because it creates lots of clones, which explodes out the extent tree. Our global reserve calculations were woefully inaccurate in this case which meant we got into a situation where we did not have enough reserved to do our work. We know we only use the global block rsv for the extent, csum, and root trees, so just get the bytes used for these trees and use that as the basis of our global reserve. Since these are not reference counted trees the bytes_used value will be accurate. This fixed the transaction aborts seen with generic/333. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/extent-tree.c45
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 */
5623static 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
5653static void update_global_block_rsv(struct btrfs_fs_info *fs_info) 5618static 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);