diff mbox series

[9,09/12] btrfs: volumes: call btrfs_update_per_profile_avail() for chunk allocation and removal

Message ID 20201001055744.103261-10-wqu@suse.com
State New, archived
Headers show
Series Introduce per-profile available space array to avoid over-confident can_overcommit() | expand

Commit Message

Qu Wenruo Oct. 1, 2020, 5:57 a.m. UTC
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(+)
diff mbox series

Patch

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e28d6a304f87..12c08648f5b6 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -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);