aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2015-05-20 09:01:55 -0400
committerChris Mason <clm@fb.com>2015-06-03 07:03:05 -0400
commit39c2d7faccc5ca5a1be682b01c0db5fafa8adeda (patch)
treea9abe19e20cfeb3177c50ddc1df85ae2d1f9d1a1 /fs/btrfs/extent-tree.c
parent4fbcdf6694544fd9d2aedbc1e73e52b90a4fcc20 (diff)
Btrfs: fix -ENOSPC on block group removal
Unlike when attempting to allocate a new block group, where we check that we have enough space in the system space_info to update the device items and insert a new chunk item in the chunk tree, we were not checking if the system space_info had enough space for updating the device items and deleting the chunk item in the chunk tree. This often lead to -ENOSPC error when attempting to allocate blocks for the chunk tree (during btree node/leaf COW operations) while updating the device items or deleting the chunk item, which resulted in the current transaction being aborted and turning the filesystem into read-only mode. While running fstests generic/038, which stresses allocation of block groups and removal of unused block groups, with a large scratch device (750Gb) this happened often, despite more than enough unallocated space, and resulted in the following trace: [68663.586604] WARNING: CPU: 3 PID: 1521 at fs/btrfs/super.c:260 __btrfs_abort_transaction+0x52/0x114 [btrfs]() [68663.600407] BTRFS: Transaction aborted (error -28) (...) [68663.730829] Call Trace: [68663.732585] [<ffffffff8142fa46>] dump_stack+0x4f/0x7b [68663.734334] [<ffffffff8108b6a2>] ? console_unlock+0x361/0x3ad [68663.739980] [<ffffffff81045ea5>] warn_slowpath_common+0xa1/0xbb [68663.757153] [<ffffffffa036ca6d>] ? __btrfs_abort_transaction+0x52/0x114 [btrfs] [68663.760925] [<ffffffff81045f05>] warn_slowpath_fmt+0x46/0x48 [68663.762854] [<ffffffffa03b159d>] ? btrfs_update_device+0x15a/0x16c [btrfs] [68663.764073] [<ffffffffa036ca6d>] __btrfs_abort_transaction+0x52/0x114 [btrfs] [68663.765130] [<ffffffffa03b3638>] btrfs_remove_chunk+0x597/0x5ee [btrfs] [68663.765998] [<ffffffffa0384663>] ? btrfs_delete_unused_bgs+0x245/0x296 [btrfs] [68663.767068] [<ffffffffa0384676>] btrfs_delete_unused_bgs+0x258/0x296 [btrfs] [68663.768227] [<ffffffff8143527f>] ? _raw_spin_unlock_irq+0x2d/0x4c [68663.769081] [<ffffffffa038b109>] cleaner_kthread+0x13d/0x16c [btrfs] [68663.799485] [<ffffffffa038afcc>] ? btrfs_alloc_root+0x28/0x28 [btrfs] [68663.809208] [<ffffffff8105f367>] kthread+0xef/0xf7 [68663.828795] [<ffffffff810e603f>] ? time_hardirqs_on+0x15/0x28 [68663.844942] [<ffffffff8105f278>] ? __kthread_parkme+0xad/0xad [68663.846486] [<ffffffff81435a88>] ret_from_fork+0x58/0x90 [68663.847760] [<ffffffff8105f278>] ? __kthread_parkme+0xad/0xad [68663.849503] ---[ end trace 798477c6d6dbaad6 ]--- [68663.850525] BTRFS: error (device sdc) in btrfs_remove_chunk:2652: errno=-28 No space left So fix this by verifying that enough space exists in system space_info, and reserving the space in the chunk block reserve, before attempting to delete the block group and allocate a new system chunk if we don't have enough space to perform the necessary updates and delete in the chunk tree. Like for the block group creation case, we don't error our if we fail to allocate a new system chunk, since we might end up not needing it (no node/leaf splits happen during the COW operations and/or we end up not needing to COW any btree nodes or leafs because they were already COWed in the current transaction and their writeback didn't start yet). Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4e08e47ace30..e78ab29f8f1b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4092,7 +4092,7 @@ static int should_alloc_chunk(struct btrfs_root *root,
4092 return 1; 4092 return 1;
4093} 4093}
4094 4094
4095static u64 get_system_chunk_thresh(struct btrfs_root *root, u64 type) 4095static u64 get_profile_num_devs(struct btrfs_root *root, u64 type)
4096{ 4096{
4097 u64 num_dev; 4097 u64 num_dev;
4098 4098
@@ -4106,17 +4106,24 @@ static u64 get_system_chunk_thresh(struct btrfs_root *root, u64 type)
4106 else 4106 else
4107 num_dev = 1; /* DUP or single */ 4107 num_dev = 1; /* DUP or single */
4108 4108
4109 /* metadata for updaing devices and chunk tree */ 4109 return num_dev;
4110 return btrfs_calc_trans_metadata_size(root, num_dev + 1);
4111} 4110}
4112 4111
4113static void check_system_chunk(struct btrfs_trans_handle *trans, 4112/*
4114 struct btrfs_root *root, u64 type) 4113 * If @is_allocation is true, reserve space in the system space info necessary
4114 * for allocating a chunk, otherwise if it's false, reserve space necessary for
4115 * removing a chunk.
4116 */
4117void check_system_chunk(struct btrfs_trans_handle *trans,
4118 struct btrfs_root *root,
4119 u64 type,
4120 const bool is_allocation)
4115{ 4121{
4116 struct btrfs_space_info *info; 4122 struct btrfs_space_info *info;
4117 u64 left; 4123 u64 left;
4118 u64 thresh; 4124 u64 thresh;
4119 int ret = 0; 4125 int ret = 0;
4126 u64 num_devs;
4120 4127
4121 /* 4128 /*
4122 * Needed because we can end up allocating a system chunk and for an 4129 * Needed because we can end up allocating a system chunk and for an
@@ -4131,7 +4138,15 @@ static void check_system_chunk(struct btrfs_trans_handle *trans,
4131 info->bytes_may_use; 4138 info->bytes_may_use;
4132 spin_unlock(&info->lock); 4139 spin_unlock(&info->lock);
4133 4140
4134 thresh = get_system_chunk_thresh(root, type); 4141 num_devs = get_profile_num_devs(root, type);
4142
4143 /* num_devs device items to update and 1 chunk item to add or remove */
4144 if (is_allocation)
4145 thresh = btrfs_calc_trans_metadata_size(root, num_devs + 1);
4146 else
4147 thresh = btrfs_calc_trans_metadata_size(root, num_devs) +
4148 btrfs_calc_trunc_metadata_size(root, 1);
4149
4135 if (left < thresh && btrfs_test_opt(root, ENOSPC_DEBUG)) { 4150 if (left < thresh && btrfs_test_opt(root, ENOSPC_DEBUG)) {
4136 btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu", 4151 btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu",
4137 left, thresh, type); 4152 left, thresh, type);
@@ -4243,7 +4258,7 @@ again:
4243 * Check if we have enough space in SYSTEM chunk because we may need 4258 * Check if we have enough space in SYSTEM chunk because we may need
4244 * to update devices. 4259 * to update devices.
4245 */ 4260 */
4246 check_system_chunk(trans, extent_root, flags); 4261 check_system_chunk(trans, extent_root, flags, true);
4247 4262
4248 ret = btrfs_alloc_chunk(trans, extent_root, flags); 4263 ret = btrfs_alloc_chunk(trans, extent_root, flags);
4249 trans->allocating_chunk = false; 4264 trans->allocating_chunk = false;
@@ -8905,7 +8920,7 @@ out:
8905 if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { 8920 if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
8906 alloc_flags = update_block_group_flags(root, cache->flags); 8921 alloc_flags = update_block_group_flags(root, cache->flags);
8907 lock_chunks(root->fs_info->chunk_root); 8922 lock_chunks(root->fs_info->chunk_root);
8908 check_system_chunk(trans, root, alloc_flags); 8923 check_system_chunk(trans, root, alloc_flags, true);
8909 unlock_chunks(root->fs_info->chunk_root); 8924 unlock_chunks(root->fs_info->chunk_root);
8910 } 8925 }
8911 mutex_unlock(&root->fs_info->ro_block_group_mutex); 8926 mutex_unlock(&root->fs_info->ro_block_group_mutex);