btrfs: Handle another split brain scenario with metadata uuid feature
commit5.4-rM2-2.2.x-imx-squashed0584071014
upstream. 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:cc5de4e702
("btrfs: Handle final split-brain possibility during fsid change") Reviewed-by: Josef Bacik <josef@toxicpanda.com> Reported-by: Su Yue <Damenly_Su@gmx.com> Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
parent
dd9837259d
commit
f3107a3c9b
|
@ -881,17 +881,28 @@ static struct btrfs_fs_devices *find_fsid_changed(
|
||||||
/*
|
/*
|
||||||
* Handles the case where scanned device is part of an fs that had
|
* Handles the case where scanned device is part of an fs that had
|
||||||
* multiple successful changes of FSID but curently device didn't
|
* multiple successful changes of FSID but curently device didn't
|
||||||
* observe it. Meaning our fsid will be different than theirs.
|
* observe it. Meaning our fsid will be different than theirs. We need
|
||||||
|
* to handle two subcases :
|
||||||
|
* 1 - The fs still continues to have different METADATA/FSID uuids.
|
||||||
|
* 2 - The fs is switched back to its original FSID (METADATA/FSID
|
||||||
|
* are equal).
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
|
list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
|
||||||
|
/* Changed UUIDs */
|
||||||
if (memcmp(fs_devices->metadata_uuid, fs_devices->fsid,
|
if (memcmp(fs_devices->metadata_uuid, fs_devices->fsid,
|
||||||
BTRFS_FSID_SIZE) != 0 &&
|
BTRFS_FSID_SIZE) != 0 &&
|
||||||
memcmp(fs_devices->metadata_uuid, disk_super->metadata_uuid,
|
memcmp(fs_devices->metadata_uuid, disk_super->metadata_uuid,
|
||||||
BTRFS_FSID_SIZE) == 0 &&
|
BTRFS_FSID_SIZE) == 0 &&
|
||||||
memcmp(fs_devices->fsid, disk_super->fsid,
|
memcmp(fs_devices->fsid, disk_super->fsid,
|
||||||
BTRFS_FSID_SIZE) != 0) {
|
BTRFS_FSID_SIZE) != 0)
|
||||||
|
return fs_devices;
|
||||||
|
|
||||||
|
/* Unchanged UUIDs */
|
||||||
|
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)
|
||||||
return fs_devices;
|
return fs_devices;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue