linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Anand Jain <anand.jain@oracle.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 10/11] btrfs-progs: add helper to reunite devices with same metadata_uuid
Date: Fri,  7 Jul 2023 23:52:40 +0800	[thread overview]
Message-ID: <c6bcdb95195fd91c8250a9d2240bc05d298615db.1688724045.git.anand.jain@oracle.com> (raw)
In-Reply-To: <cover.1688724045.git.anand.jain@oracle.com>

The btrfstune -m|M option allows the user to change the fsid of the
filesystem. However, in a multi-device filesystem, if the fsid is not
successfully changed simultaneously on all devices, problems may arise.
In such cases, the user cannot use btrfstune again to resolve the
incomplete fsid change.

This patch provides helper function to find other devices having the
the same metadata_uuid and have them reunited with the given scanned
device so that btrfstune can fix the fsid.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 common/device-scan.c    | 42 ++++++++++++++++++++++++
 common/device-scan.h    |  1 +
 kernel-shared/volumes.c | 73 +++++++++++++++++++++++++++++++++++++++++
 kernel-shared/volumes.h |  2 ++
 4 files changed, 118 insertions(+)

diff --git a/common/device-scan.c b/common/device-scan.c
index 00ce15244a09..512754c01adb 100644
--- a/common/device-scan.c
+++ b/common/device-scan.c
@@ -541,6 +541,48 @@ int btrfs_scan_argv_devices(int dev_optind, int dev_argc, char **dev_argv)
 	return 0;
 }
 
+int scan_reunite_fs_devices(char *path)
+{
+	int ret;
+	int fd;
+	u64 total_devs;
+	struct btrfs_fs_devices *fs_devices;
+
+	ret = check_arg_type(path);
+	if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) {
+		if (ret < 0) {
+			errno = -ret;
+			error("invalid argument %s: %m", path);
+		} else {
+			error("not a block device or regular file: %s", path);
+		}
+	}
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		error("cannot open %s: %m", path);
+		return -errno;
+	}
+	ret = btrfs_scan_one_device(fd, path, &fs_devices, &total_devs,
+				    BTRFS_SUPER_INFO_OFFSET, SBREAD_DEFAULT);
+	close(fd);
+	if (ret < 0) {
+		errno = -ret;
+		error("device scan of %s failed: %m", path);
+		return ret;
+	}
+
+	ret = 0;
+	/* Check for missing device */
+	if (fs_devices->num_devices != total_devs)
+		ret = reunite_fs_devices(fs_devices);
+
+	if (!ret)
+		fs_devices->sanitized = true;
+
+	return ret;
+}
+
 bool array_append(char **dest, char *src, int *cnt)
 {
 	char *this_tok = strtok(src, ",");
diff --git a/common/device-scan.h b/common/device-scan.h
index 7a6874298051..a1193e7f7020 100644
--- a/common/device-scan.h
+++ b/common/device-scan.h
@@ -61,5 +61,6 @@ void free_seen_fsid(struct seen_fsid *seen_fsid_hash[]);
 int test_uuid_unique(const char *uuid_str);
 bool array_append(char **dest, char *src, int *cnt);
 void free_array(char **prt, int cnt);
+int scan_reunite_fs_devices(char *path);
 
 #endif
diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c
index ac9e711a994f..642f7084cf63 100644
--- a/kernel-shared/volumes.c
+++ b/kernel-shared/volumes.c
@@ -2958,3 +2958,76 @@ int btrfs_fix_device_and_super_size(struct btrfs_fs_info *fs_info)
 	}
 	return ret;
 }
+
+static int find_unifiable(struct btrfs_fs_devices *fsinfo_fs_devices,
+			  struct btrfs_fs_devices **ret_fs_devices)
+{
+	u8 *orig_uuid = fsinfo_fs_devices->metadata_uuid;
+	u8 *orig_fsid = fsinfo_fs_devices->fsid;
+	struct btrfs_fs_devices *fs_devices = NULL;
+	int ret = 0;
+
+	list_for_each_entry(fs_devices, &fs_uuids, list) {
+		/* skip the same fs_info fsid */
+		if (!memcmp(fs_devices->fsid, orig_fsid, BTRFS_FSID_SIZE))
+			continue;
+
+		/* skip the metadata_uuid which isn't fs_info metadata_uuid */
+		if (memcmp(fs_devices->metadata_uuid, orig_uuid, BTRFS_FSID_SIZE))
+			continue;
+
+		ret++;
+		*ret_fs_devices = fs_devices;
+	}
+
+	return ret;
+}
+
+int reunite_fs_devices(struct btrfs_fs_devices *fs_devices)
+{
+	struct btrfs_fs_devices *other_fs_devices = NULL;
+	struct btrfs_device *tmp_device;
+	struct btrfs_device *device;
+	int other_fsid_cnt = 0;
+	int missing_devs;
+
+	missing_devs = fs_devices->total_devices - fs_devices->num_devices;
+	other_fsid_cnt = find_unifiable(fs_devices, &other_fs_devices);
+
+	if (other_fsid_cnt == 0) {
+		error("No missing device(s) found");
+		return -EINVAL;
+	} else if (other_fsid_cnt > 1) {
+		error("Found more than one fsid with the same metadata_uuid");
+		error("Try use --device and --noscan options");
+		return -EINVAL;
+	}
+
+	/* Missing count in the fs_info should match with the scanned devices */
+	if (missing_devs != other_fs_devices->num_devices) {
+		error("Missing device(s) found %d expected %d",
+		      other_fs_devices->num_devices, missing_devs);
+		return -EINVAL;
+	}
+
+	list_for_each_entry_safe(device, tmp_device, &other_fs_devices->devices,
+				 dev_list) {
+		/* We have found the missing device, bring it in */
+		list_move(&device->dev_list, &fs_devices->devices);
+		fs_devices->num_devices++;
+		missing_devs--;
+	}
+
+	if (!list_empty(&other_fs_devices->devices) || missing_devs != 0 ||
+	    fs_devices->total_devices != fs_devices->num_devices) {
+		error("Found more or fewer missing devices");
+		return -EINVAL;
+	}
+
+	if (other_fs_devices->changing_fsid)
+		fs_devices->changing_fsid = true;
+	if (other_fs_devices->active_metadata_uuid)
+		fs_devices->active_metadata_uuid = true;
+
+	return 0;
+}
diff --git a/kernel-shared/volumes.h b/kernel-shared/volumes.h
index 13d08cc7eea5..9f755dfa9015 100644
--- a/kernel-shared/volumes.h
+++ b/kernel-shared/volumes.h
@@ -104,6 +104,7 @@ struct btrfs_fs_devices {
 
 	bool changing_fsid;
 	bool active_metadata_uuid;
+	bool sanitized;
 };
 
 struct btrfs_bio_stripe {
@@ -318,5 +319,6 @@ int btrfs_bg_type_to_nparity(u64 flags);
 int btrfs_bg_type_to_sub_stripes(u64 flags);
 u64 btrfs_bg_flags_for_device_num(int number);
 bool btrfs_bg_type_is_stripey(u64 flags);
+int reunite_fs_devices(struct btrfs_fs_devices *fs_devices);
 
 #endif
-- 
2.39.3


  parent reply	other threads:[~2023-07-07 15:54 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-07 15:52 [PATCH 00/11] btrfs-progs: fix bugs and CHANGING_FSID_V2 flag Anand Jain
2023-07-07 15:52 ` [PATCH 01/11] btrfs-progs: fix duplicate missing device Anand Jain
2023-07-07 15:52 ` [PATCH 02/11] btrfs-progs: call warn() for " Anand Jain
2023-07-13 18:48   ` David Sterba
2023-07-17 18:22     ` Anand Jain
2023-07-19 14:34       ` Anand Jain
2023-07-07 15:52 ` [PATCH 03/11] btrfs-progs: track missing device counter Anand Jain
2023-07-07 15:52 ` [PATCH 04/11] btrfs-progs: NULL initialize device name for missing Anand Jain
2023-07-07 15:52 ` [PATCH 05/11] btrfs-progs: tune: check for missing device Anand Jain
2023-07-13 18:49   ` David Sterba
2023-07-17 19:02     ` Anand Jain
2023-07-07 15:52 ` [PATCH 06/11] btrfs-progs: track changing_fsid flag in fs_devices Anand Jain
2023-07-07 15:52 ` [PATCH 07/11] btrfs-progs: track num_devices per fs_devices Anand Jain
2023-07-07 15:52 ` [PATCH 08/11] btrfs-progs: track total_devs in fs devices Anand Jain
2023-07-13 18:58   ` David Sterba
2023-07-17 19:28     ` Anand Jain
2023-07-07 15:52 ` [PATCH 09/11] btrfs-progs: track active metadata_uuid per fs_devices Anand Jain
2023-07-07 15:52 ` Anand Jain [this message]
2023-07-07 15:52 ` [PATCH 11/11] btrfs-progs: tune: fix incomplete fsid_change Anand Jain
2023-07-13 18:57   ` David Sterba
2023-07-17 19:25     ` Anand Jain
2023-07-20 14:33       ` Anand Jain

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c6bcdb95195fd91c8250a9d2240bc05d298615db.1688724045.git.anand.jain@oracle.com \
    --to=anand.jain@oracle.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).