@@ -3978,6 +3978,14 @@ int prepare_to_relocate(struct reloc_control *rc)
return 0;
}
+/*
+ * Return 0 if current balance stage is finished without problem.
+ * For MOVE_DATA_EXTENTS stage, we need to progress to UPDATE_DATA_PTRS stage.
+ *
+ * Return >0 if there is no extents to relocate anymore.
+ *
+ * Return <0 for fatal error.
+ */
static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
{
struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
@@ -3988,6 +3996,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
struct btrfs_extent_item *ei;
u64 flags;
u32 item_size;
+ bool no_more_extent = true;
int ret;
int err = 0;
int progress = 0;
@@ -4033,6 +4042,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
break;
rc->extents_found++;
+ no_more_extent = false;
ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_extent_item);
@@ -4154,7 +4164,9 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
err = ret;
btrfs_free_block_rsv(fs_info, rc->block_rsv);
btrfs_free_path(path);
- return err;
+ if (err)
+ return err;
+ return no_more_extent;
}
static int __insert_orphan_inode(struct btrfs_trans_handle *trans,
@@ -4374,6 +4386,8 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start)
if (ret < 0)
err = ret;
+ if (ret > 0)
+ break;
finishes_stage = rc->stage;
/*
* We may have gotten ENOSPC after we already dirtied some
There are several reported runaway balance, some of them are even unable to be canceled with latest kernel. Current balance only exit if rc::found_extents is 0, but there is a more obvious condition to terminate relocation: is there any new extents to relocate. This patch will make balance to check such condition, as an final safe net to catch the runaway balance. Signed-off-by: Qu Wenruo <wqu@suse.com> --- This is definitely not the right solution, as we should find the root cause, e.g. where we missed a rc->found_extents--;, but this would provide a quick test to determine if it's rc::found_extents get un-synced from the real situation. And an extra safenet is never a bad thing. --- fs/btrfs/relocation.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)