diff options
| -rw-r--r-- | fs/btrfs/extent-tree.c | 28 |
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 | ||
| 6529 | static int set_block_group_ro(struct btrfs_block_group_cache *cache) | 6529 | static 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); |
| 6585 | out: | 6599 | out: |
| 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); |
