Skip to content

Commit 0584071

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Handle another split brain scenario with metadata uuid feature
There is one more cases which isn't handled by the original metadata uuid work. Namely, when a filesystem has METADATA_UUID incompat bit and the user decides to change the FSID to the original one e.g. have metadata_uuid and fsid match. In case of power failure while this operation is in progress we could end up in a situation where some of the disks have the incompat bit removed and the other half have both METADATA_UUID_INCOMPAT and FSID_CHANGING_IN_PROGRESS flags. This patch handles the case where a disk that has successfully changed its FSID such that it equals METADATA_UUID is scanned first. Subsequently when a disk with both METADATA_UUID_INCOMPAT/FSID_CHANGING_IN_PROGRESS flags is scanned find_fsid_changed won't be able to find an appropriate btrfs_fs_devices. This is done by extending find_fsid_changed to correctly find btrfs_fs_devices whose metadata_uuid/fsid are the same and they match the metadata_uuid of the currently scanned device. Fixes: cc5de4e ("btrfs: Handle final split-brain possibility during fsid change") Reviewed-by: Josef Bacik <[email protected]> Reported-by: Su Yue <[email protected]> Signed-off-by: Nikolay Borisov <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent c6730a0 commit 0584071

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

fs/btrfs/volumes.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -710,17 +710,28 @@ static struct btrfs_fs_devices *find_fsid_changed(
710710
/*
711711
* Handles the case where scanned device is part of an fs that had
712712
* multiple successful changes of FSID but curently device didn't
713-
* observe it. Meaning our fsid will be different than theirs.
713+
* observe it. Meaning our fsid will be different than theirs. We need
714+
* to handle two subcases :
715+
* 1 - The fs still continues to have different METADATA/FSID uuids.
716+
* 2 - The fs is switched back to its original FSID (METADATA/FSID
717+
* are equal).
714718
*/
715719
list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
720+
/* Changed UUIDs */
716721
if (memcmp(fs_devices->metadata_uuid, fs_devices->fsid,
717722
BTRFS_FSID_SIZE) != 0 &&
718723
memcmp(fs_devices->metadata_uuid, disk_super->metadata_uuid,
719724
BTRFS_FSID_SIZE) == 0 &&
720725
memcmp(fs_devices->fsid, disk_super->fsid,
721-
BTRFS_FSID_SIZE) != 0) {
726+
BTRFS_FSID_SIZE) != 0)
727+
return fs_devices;
728+
729+
/* Unchanged UUIDs */
730+
if (memcmp(fs_devices->metadata_uuid, fs_devices->fsid,
731+
BTRFS_FSID_SIZE) == 0 &&
732+
memcmp(fs_devices->fsid, disk_super->metadata_uuid,
733+
BTRFS_FSID_SIZE) == 0)
722734
return fs_devices;
723-
}
724735
}
725736

726737
return NULL;

0 commit comments

Comments
 (0)