On 2019/12/12 9:34 PM, Nikolay Borisov wrote:
On 12.12.19 г. 13:01 ч., damenly.su@xxxxxxxxx wrote:
From: Su Yue <Damenly_Su@xxxxxxx>
This patch adds the case for scanned changing device with
INCOMPAT_METADATA_UUID.
For this situation, the origin code only handles the case
the devices already pulled into disk with INCOMPAT_METADATA_UUID set.
There is an another case that the successful changed devices synced
without INCOMPAT_METADATA_UUID.
So add the check of Heather fsid of scanned device equals
metadata_uuid of fs_devices which is with INCOMPAT_METADATA_UUID
feature.
This is hard for me to parse and correctly understand what you mean.
Sorry..
Signed-off-by: Su Yue <Damenly_Su@xxxxxxx>
---
fs/btrfs/volumes.c | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index b08b06a89a77..61b4a107bb58 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -654,7 +654,6 @@ static struct btrfs_fs_devices *find_fsid_inprogress(
return NULL;
}
-
static struct btrfs_fs_devices *find_fsid_changed(
struct btrfs_super_block *disk_super)
find_fsid_changed handles the case where a device belongs to a
filesystem which had multiple successful fsid changed but it failed on
the last one.
I go it while reading code. And "the last one" is the one where the
@disk_super read from. It has the metadata_uuid and FSID_CHANGING_V2.
Right?
What I want to express in changelog is that those successful changed
devices *may*
not have the metadata_uuid feature. The code in btrfstune.c: line 141
if (new_uuid && uuid_changed && memcmp(disk_super->metadata_uuid,
new_fsid,
BTRFS_FSID_SIZE) == 0) {
/*
* Changing fsid to be the same as metadata uuid, so just
* disable the flag
*/
memcpy(disk_super->fsid, &new_fsid, BTRFS_FSID_SIZE);
incompat_flags &= ~BTRFS_FEATURE_INCOMPAT_METADATA_UUID;
btrfs_set_super_incompat_flags(disk_super, incompat_flags);
memset(disk_super->metadata_uuid, 0, BTRFS_FSID_SIZE);
The INCOMPAT_METADATA_UUID can be cleared if changing fsid is same with
the metadata_uuid in deivce.
{
@@ -663,9 +662,14 @@ static struct btrfs_fs_devices *find_fsid_changed(
/*
* Handles the case where scanned device is part of an fs that had
* multiple successful changes of FSID but curently device didn't
- * observe it. Meaning our fsid will be different than theirs.
+ * observe it.
+ *
+ * Case 1: the devices already changed still owns the feature, their
+ * fsid must differ from the disk_super->fsid.
What do you mean by device to still owns the feature? Has the bit set or
something else?
The metadata_uuid feature.
*/
list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
+ if (fs_devices->fsid_change)
+ continue;
Why do you do this?
Just make cases separated.
if (memcmp(fs_devices->metadata_uuid, fs_devices->fsid,
BTRFS_FSID_SIZE) != 0 &&
memcmp(fs_devices->metadata_uuid, disk_super->metadata_uuid,
@@ -676,7 +680,26 @@ static struct btrfs_fs_devices *find_fsid_changed(
}
}
- return NULL;
+ /*
+ * Case 2: the synced devices doesn't have the metadata_uuid feature.
+ * NOTE: the fs_devices has same metadata_uuid and fsid in memory, but
+ * they differs in disk, because fs_id is copied to
+ * fs_devices->metadata_id while alloc_fs_devices if no metadata
It's not possible for the device to have metadata_uuid feature because
this function is called from device_list_add iff the device has
METADATA_UUID flag:
Get and agree what you mean. As the reply above, the fs_devices already
allocated there(not the device scanning) may not have METADATA_UUID flag.
if (fsid_change_in_progress) {
if (!has_metadata_uuid) {
} else {
find_fsid_changed <-- here we are sure our device has METADATA_UUID set.
}
}
+ * feature.
+ */
+ list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
+ if (memcmp(fs_devices->metadata_uuid, fs_devices->fsid,
+ BTRFS_FSID_SIZE) == 0 &&
+ memcmp(fs_devices->fsid, disk_super->metadata_uuid,
+ BTRFS_FSID_SIZE) == 0 && !fs_devices->fsid_change)
+ return fs_devices;
+ }
+
+ /*
+ * Okay, can't found any fs_devices already synced, back to
+ * search devices unchanged or changing like the device.
+ */
+ return find_fsid(disk_super->fsid, disk_super->metadata_uuid);
}
static struct btrfs_fs_devices *find_fsid_changing_metada_uuid(