aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent-tree.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d7031e7dfd76..7021dde74d81 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6526,15 +6526,28 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
6526 return flags; 6526 return flags;
6527} 6527}
6528 6528
6529static int set_block_group_ro(struct btrfs_block_group_cache *cache) 6529static int set_block_group_ro(struct btrfs_block_group_cache *cache, int force)
6530{ 6530{
6531 struct btrfs_space_info *sinfo = cache->space_info; 6531 struct btrfs_space_info *sinfo = cache->space_info;
6532 u64 num_bytes; 6532 u64 num_bytes;
6533 u64 min_allocable_bytes;
6533 int ret = -ENOSPC; 6534 int ret = -ENOSPC;
6534 6535
6535 if (cache->ro) 6536 if (cache->ro)
6536 return 0; 6537 return 0;
6537 6538
6539 /*
6540 * We need some metadata space and system metadata space for
6541 * allocating chunks in some corner cases until we force to set
6542 * it to be readonly.
6543 */
6544 if ((sinfo->flags &
6545 (BTRFS_BLOCK_GROUP_SYSTEM | BTRFS_BLOCK_GROUP_METADATA)) &&
6546 !force)
6547 min_allocable_bytes = 1 * 1024 * 1024;
6548 else
6549 min_allocable_bytes = 0;
6550
6538 spin_lock(&sinfo->lock); 6551 spin_lock(&sinfo->lock);
6539 spin_lock(&cache->lock); 6552 spin_lock(&cache->lock);
6540 num_bytes = cache->key.offset - cache->reserved - cache->pinned - 6553 num_bytes = cache->key.offset - cache->reserved - cache->pinned -
@@ -6542,7 +6555,8 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache)
6542 6555
6543 if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned + 6556 if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned +
6544 sinfo->bytes_may_use + sinfo->bytes_readonly + 6557 sinfo->bytes_may_use + sinfo->bytes_readonly +
6545 cache->reserved_pinned + num_bytes <= sinfo->total_bytes) { 6558 cache->reserved_pinned + num_bytes + min_allocable_bytes <=
6559 sinfo->total_bytes) {
6546 sinfo->bytes_readonly += num_bytes; 6560 sinfo->bytes_readonly += num_bytes;
6547 sinfo->bytes_reserved += cache->reserved_pinned; 6561 sinfo->bytes_reserved += cache->reserved_pinned;
6548 cache->reserved_pinned = 0; 6562 cache->reserved_pinned = 0;
@@ -6573,7 +6587,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
6573 do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 6587 do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
6574 CHUNK_ALLOC_FORCE); 6588 CHUNK_ALLOC_FORCE);
6575 6589
6576 ret = set_block_group_ro(cache); 6590 ret = set_block_group_ro(cache, 0);
6577 if (!ret) 6591 if (!ret)
6578 goto out; 6592 goto out;
6579 alloc_flags = get_alloc_profile(root, cache->space_info->flags); 6593 alloc_flags = get_alloc_profile(root, cache->space_info->flags);
@@ -6581,7 +6595,7 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
6581 CHUNK_ALLOC_FORCE); 6595 CHUNK_ALLOC_FORCE);
6582 if (ret < 0) 6596 if (ret < 0)
6583 goto out; 6597 goto out;
6584 ret = set_block_group_ro(cache); 6598 ret = set_block_group_ro(cache, 0);
6585out: 6599out:
6586 btrfs_end_transaction(trans, root); 6600 btrfs_end_transaction(trans, root);
6587 return ret; 6601 return ret;
@@ -7018,7 +7032,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
7018 7032
7019 set_avail_alloc_bits(root->fs_info, cache->flags); 7033 set_avail_alloc_bits(root->fs_info, cache->flags);
7020 if (btrfs_chunk_readonly(root, cache->key.objectid)) 7034 if (btrfs_chunk_readonly(root, cache->key.objectid))
7021 set_block_group_ro(cache); 7035 set_block_group_ro(cache, 1);
7022 } 7036 }
7023 7037
7024 list_for_each_entry_rcu(space_info, &root->fs_info->space_info, list) { 7038 list_for_each_entry_rcu(space_info, &root->fs_info->space_info, list) {
@@ -7032,9 +7046,9 @@ int btrfs_read_block_groups(struct btrfs_root *root)
7032 * mirrored block groups. 7046 * mirrored block groups.
7033 */ 7047 */
7034 list_for_each_entry(cache, &space_info->block_groups[3], list) 7048 list_for_each_entry(cache, &space_info->block_groups[3], list)
7035 set_block_group_ro(cache); 7049 set_block_group_ro(cache, 1);
7036 list_for_each_entry(cache, &space_info->block_groups[4], list) 7050 list_for_each_entry(cache, &space_info->block_groups[4], list)
7037 set_block_group_ro(cache); 7051 set_block_group_ro(cache, 1);
7038 } 7052 }
7039 7053
7040 init_global_block_rsv(info); 7054 init_global_block_rsv(info);