diff mbox series

[2/2] btrfs-progs: change-csum: handle finished dev-replace correctly

Message ID 9de738a44fa38169541ca97ab9994585b5104fe1.1717299366.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: btrfstune: fix false alerts on dev-replace when changing csum | expand

Commit Message

Qu Wenruo June 2, 2024, 3:45 a.m. UTC
[BUG]
If a btrfs experienced dev-replace, even it's already finished,
btrfstune would refuse to change its csum:

  WARNING: Experimental build with unstable or unfinished features
  WARNING: Switching checksums is experimental, do not use for valuable data!

  Proceed to switch checksums
  ERROR: running dev-replace detected, please finish or cancel it.
  ERROR: btrfstune failed

[CAUSE]
The current dev-replace detection is only checking if we have
DEV_REPLACE item in device tree.
However DEV_REPLACE item will also exist even if a dev-replace finished,
so the existing check can not handle such case at all.

[FIX]
If an dev-replace item is found, further check the state of the item to
prevent false alerts.

Fixes: #798
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 tune/change-csum.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/tune/change-csum.c b/tune/change-csum.c
index 0780a18b090b..c2972a509914 100644
--- a/tune/change-csum.c
+++ b/tune/change-csum.c
@@ -73,16 +73,28 @@  static int check_csum_change_requreiment(struct btrfs_fs_info *fs_info, u16 new_
 	key.type = BTRFS_DEV_REPLACE_KEY;
 	key.offset = 0;
 	ret = btrfs_search_slot(NULL, dev_root, &key, &path, 0, 0);
-	btrfs_release_path(&path);
 	if (ret < 0) {
+		btrfs_release_path(&path);
 		errno = -ret;
 		error("failed to check the dev-reaplce status: %m");
 		return ret;
 	}
 	if (ret == 0) {
-		error("running dev-replace detected, please finish or cancel it.");
-		return -EINVAL;
+		struct btrfs_dev_replace_item *ptr;
+		u64 state;
+
+		ptr = btrfs_item_ptr(path.nodes[0], path.slots[0],
+				     struct btrfs_dev_replace_item);
+		state = btrfs_dev_replace_replace_state(path.nodes[0], ptr);
+		if (state == BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED ||
+		    state == BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED) {
+			btrfs_release_path(&path);
+			error(
+	"running/suspended dev-replace detected, please finish or cancel it");
+			return -EINVAL;
+		}
 	}
+	btrfs_release_path(&path);
 
 	if (fs_info->csum_type == new_csum_type) {
 		error("the fs is already using csum type %s (%u)",