aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2016-03-25 13:25:47 -0400
committerDavid Sterba <dsterba@suse.com>2016-07-07 12:45:53 -0400
commite40edf2da4fc6ab10c707b0522372b08b38171e6 (patch)
tree085dfa71d90bfc25cc563439544b84417169c9d1
parenta99cde438de0c4c0cecc1d1af1a55a75b10bfdef (diff)
Btrfs: add bytes_readonly to the spaceinfo at once
For some reason we're adding bytes_readonly to the space info after we update the space info with the block group info. This creates a tiny race where we could over-reserve space because we haven't yet taken out the bytes_readonly bit. Since we already know this information at the time we call update_space_info, just pass it along so it can be updated all at once. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/extent-tree.c29
1 files changed, 11 insertions, 18 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 82b912a293ab..777d9a5aa83f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3913,6 +3913,7 @@ static const char *alloc_name(u64 flags)
3913 3913
3914static int update_space_info(struct btrfs_fs_info *info, u64 flags, 3914static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3915 u64 total_bytes, u64 bytes_used, 3915 u64 total_bytes, u64 bytes_used,
3916 u64 bytes_readonly,
3916 struct btrfs_space_info **space_info) 3917 struct btrfs_space_info **space_info)
3917{ 3918{
3918 struct btrfs_space_info *found; 3919 struct btrfs_space_info *found;
@@ -3933,6 +3934,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3933 found->disk_total += total_bytes * factor; 3934 found->disk_total += total_bytes * factor;
3934 found->bytes_used += bytes_used; 3935 found->bytes_used += bytes_used;
3935 found->disk_used += bytes_used * factor; 3936 found->disk_used += bytes_used * factor;
3937 found->bytes_readonly += bytes_readonly;
3936 if (total_bytes > 0) 3938 if (total_bytes > 0)
3937 found->full = 0; 3939 found->full = 0;
3938 spin_unlock(&found->lock); 3940 spin_unlock(&found->lock);
@@ -3960,7 +3962,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3960 found->disk_used = bytes_used * factor; 3962 found->disk_used = bytes_used * factor;
3961 found->bytes_pinned = 0; 3963 found->bytes_pinned = 0;
3962 found->bytes_reserved = 0; 3964 found->bytes_reserved = 0;
3963 found->bytes_readonly = 0; 3965 found->bytes_readonly = bytes_readonly;
3964 found->bytes_may_use = 0; 3966 found->bytes_may_use = 0;
3965 found->full = 0; 3967 found->full = 0;
3966 found->max_extent_size = 0; 3968 found->max_extent_size = 0;
@@ -4470,7 +4472,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
4470 space_info = __find_space_info(extent_root->fs_info, flags); 4472 space_info = __find_space_info(extent_root->fs_info, flags);
4471 if (!space_info) { 4473 if (!space_info) {
4472 ret = update_space_info(extent_root->fs_info, flags, 4474 ret = update_space_info(extent_root->fs_info, flags,
4473 0, 0, &space_info); 4475 0, 0, 0, &space_info);
4474 BUG_ON(ret); /* -ENOMEM */ 4476 BUG_ON(ret); /* -ENOMEM */
4475 } 4477 }
4476 BUG_ON(!space_info); /* Logic error */ 4478 BUG_ON(!space_info); /* Logic error */
@@ -10007,7 +10009,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
10007 10009
10008 ret = update_space_info(info, cache->flags, found_key.offset, 10010 ret = update_space_info(info, cache->flags, found_key.offset,
10009 btrfs_block_group_used(&cache->item), 10011 btrfs_block_group_used(&cache->item),
10010 &space_info); 10012 cache->bytes_super, &space_info);
10011 if (ret) { 10013 if (ret) {
10012 btrfs_remove_free_space_cache(cache); 10014 btrfs_remove_free_space_cache(cache);
10013 spin_lock(&info->block_group_cache_lock); 10015 spin_lock(&info->block_group_cache_lock);
@@ -10020,9 +10022,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
10020 } 10022 }
10021 10023
10022 cache->space_info = space_info; 10024 cache->space_info = space_info;
10023 spin_lock(&cache->space_info->lock);
10024 cache->space_info->bytes_readonly += cache->bytes_super;
10025 spin_unlock(&cache->space_info->lock);
10026 10025
10027 __link_block_group(space_info, cache); 10026 __link_block_group(space_info, cache);
10028 10027
@@ -10114,7 +10113,6 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
10114 int ret; 10113 int ret;
10115 struct btrfs_root *extent_root; 10114 struct btrfs_root *extent_root;
10116 struct btrfs_block_group_cache *cache; 10115 struct btrfs_block_group_cache *cache;
10117
10118 extent_root = root->fs_info->extent_root; 10116 extent_root = root->fs_info->extent_root;
10119 10117
10120 btrfs_set_log_full_commit(root->fs_info, trans); 10118 btrfs_set_log_full_commit(root->fs_info, trans);
@@ -10160,7 +10158,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
10160 * assigned to our block group, but don't update its counters just yet. 10158 * assigned to our block group, but don't update its counters just yet.
10161 * We want our bg to be added to the rbtree with its ->space_info set. 10159 * We want our bg to be added to the rbtree with its ->space_info set.
10162 */ 10160 */
10163 ret = update_space_info(root->fs_info, cache->flags, 0, 0, 10161 ret = update_space_info(root->fs_info, cache->flags, 0, 0, 0,
10164 &cache->space_info); 10162 &cache->space_info);
10165 if (ret) { 10163 if (ret) {
10166 btrfs_remove_free_space_cache(cache); 10164 btrfs_remove_free_space_cache(cache);
@@ -10180,7 +10178,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
10180 * the rbtree, update the space info's counters. 10178 * the rbtree, update the space info's counters.
10181 */ 10179 */
10182 ret = update_space_info(root->fs_info, cache->flags, size, bytes_used, 10180 ret = update_space_info(root->fs_info, cache->flags, size, bytes_used,
10183 &cache->space_info); 10181 cache->bytes_super, &cache->space_info);
10184 if (ret) { 10182 if (ret) {
10185 btrfs_remove_free_space_cache(cache); 10183 btrfs_remove_free_space_cache(cache);
10186 spin_lock(&root->fs_info->block_group_cache_lock); 10184 spin_lock(&root->fs_info->block_group_cache_lock);
@@ -10193,16 +10191,11 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
10193 } 10191 }
10194 update_global_block_rsv(root->fs_info); 10192 update_global_block_rsv(root->fs_info);
10195 10193
10196 spin_lock(&cache->space_info->lock);
10197 cache->space_info->bytes_readonly += cache->bytes_super;
10198 spin_unlock(&cache->space_info->lock);
10199
10200 __link_block_group(cache->space_info, cache); 10194 __link_block_group(cache->space_info, cache);
10201 10195
10202 list_add_tail(&cache->bg_list, &trans->new_bgs); 10196 list_add_tail(&cache->bg_list, &trans->new_bgs);
10203 10197
10204 set_avail_alloc_bits(extent_root->fs_info, type); 10198 set_avail_alloc_bits(extent_root->fs_info, type);
10205
10206 return 0; 10199 return 0;
10207} 10200}
10208 10201
@@ -10747,21 +10740,21 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
10747 mixed = 1; 10740 mixed = 1;
10748 10741
10749 flags = BTRFS_BLOCK_GROUP_SYSTEM; 10742 flags = BTRFS_BLOCK_GROUP_SYSTEM;
10750 ret = update_space_info(fs_info, flags, 0, 0, &space_info); 10743 ret = update_space_info(fs_info, flags, 0, 0, 0, &space_info);
10751 if (ret) 10744 if (ret)
10752 goto out; 10745 goto out;
10753 10746
10754 if (mixed) { 10747 if (mixed) {
10755 flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA; 10748 flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
10756 ret = update_space_info(fs_info, flags, 0, 0, &space_info); 10749 ret = update_space_info(fs_info, flags, 0, 0, 0, &space_info);
10757 } else { 10750 } else {
10758 flags = BTRFS_BLOCK_GROUP_METADATA; 10751 flags = BTRFS_BLOCK_GROUP_METADATA;
10759 ret = update_space_info(fs_info, flags, 0, 0, &space_info); 10752 ret = update_space_info(fs_info, flags, 0, 0, 0, &space_info);
10760 if (ret) 10753 if (ret)
10761 goto out; 10754 goto out;
10762 10755
10763 flags = BTRFS_BLOCK_GROUP_DATA; 10756 flags = BTRFS_BLOCK_GROUP_DATA;
10764 ret = update_space_info(fs_info, flags, 0, 0, &space_info); 10757 ret = update_space_info(fs_info, flags, 0, 0, 0, &space_info);
10765 } 10758 }
10766out: 10759out:
10767 return ret; 10760 return ret;