@@ -3135,7 +3135,13 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset)
device->bytes_used - dev_extent_len);
atomic64_add(dev_extent_len, &fs_info->free_chunk_space);
btrfs_clear_space_info_full(fs_info);
+ ret = btrfs_update_per_profile_avail(fs_info);
mutex_unlock(&fs_info->chunk_mutex);
+ if (ret < 0) {
+ mutex_unlock(&fs_devices->device_list_mutex);
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+ }
}
ret = btrfs_update_device(trans, device);
@@ -5275,6 +5281,12 @@ static int create_chunk(struct btrfs_trans_handle *trans,
&trans->transaction->dev_update_list);
}
+ ret = btrfs_update_per_profile_avail(info);
+ if (ret < 0) {
+ btrfs_revert_block_group(trans, start);
+ goto error_revert_devices;
+ }
+
atomic64_sub(ctl->stripe_size * map->num_stripes,
&info->free_chunk_space);
@@ -5284,6 +5296,13 @@ static int create_chunk(struct btrfs_trans_handle *trans,
return 0;
+error_revert_devices:
+ for (i = 0; i < map->num_stripes; i++) {
+ struct btrfs_device *dev = map->stripes[i].dev;
+
+ btrfs_device_set_bytes_used(dev,
+ dev->bytes_used - ctl->stripe_size);
+ }
error_del_extent:
write_lock(&em_tree->lock);
remove_extent_mapping(em_tree, em);
For chunk allocation, if we failed to update per profile available space, we need to revert the newly created block group, revert the device status, then return error. For chunk removal, if we failed we just abort transaction, like all error patterns in btrfs_remove_chunk(). Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/volumes.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)