From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Nikolay Borisov <nborisov@suse.com>, Su Yue <Damenly_Su@gmx.com>,
Josef Bacik <josef@toxicpanda.com>,
David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>,
linux-btrfs@vger.kernel.org
Subject: [PATCH AUTOSEL 5.5 449/542] btrfs: Fix split-brain handling when changing FSID to metadata uuid
Date: Fri, 14 Feb 2020 10:47:21 -0500 [thread overview]
Message-ID: <20200214154854.6746-449-sashal@kernel.org> (raw)
In-Reply-To: <20200214154854.6746-1-sashal@kernel.org>
From: Nikolay Borisov <nborisov@suse.com>
[ Upstream commit 1362089d2ad7e20d16371b39d3c11990d4ec23e4 ]
Current code doesn't correctly handle the situation which arises when
a file system that has METADATA_UUID_INCOMPAT flag set and has its FSID
changed to the one in metadata uuid. This causes the incompat flag to
disappear.
In case of a power failure we could end up in a situation where part of
the disks in a multi-disk filesystem are correctly reverted to
METADATA_UUID_INCOMPAT flag unset state, while others have
METADATA_UUID_INCOMPAT set and CHANGING_FSID_V2_IN_PROGRESS.
This patch corrects the behavior required to handle the case where a
disk of the second type is scanned first, creating the necessary
btrfs_fs_devices. Subsequently, when a disk which has already completed
the transition is scanned it should overwrite the data in
btrfs_fs_devices.
Reported-by: Su Yue <Damenly_Su@gmx.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.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: Sasha Levin <sashal@kernel.org>
---
fs/btrfs/volumes.c | 42 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index c5c0dc0cbf517..a8b71ded4d212 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -723,6 +723,32 @@ static struct btrfs_fs_devices *find_fsid_changed(
return NULL;
}
+
+static struct btrfs_fs_devices *find_fsid_reverted_metadata(
+ struct btrfs_super_block *disk_super)
+{
+ struct btrfs_fs_devices *fs_devices;
+
+ /*
+ * Handle the case where the scanned device is part of an fs whose last
+ * metadata UUID change reverted it to the original FSID. At the same
+ * time * fs_devices was first created by another constitutent device
+ * which didn't fully observe the operation. This results in an
+ * btrfs_fs_devices created with metadata/fsid different AND
+ * btrfs_fs_devices::fsid_change set AND the metadata_uuid of the
+ * fs_devices equal to the FSID of the disk.
+ */
+ list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
+ if (memcmp(fs_devices->fsid, fs_devices->metadata_uuid,
+ BTRFS_FSID_SIZE) != 0 &&
+ memcmp(fs_devices->metadata_uuid, disk_super->fsid,
+ BTRFS_FSID_SIZE) == 0 &&
+ fs_devices->fsid_change)
+ return fs_devices;
+ }
+
+ return NULL;
+}
/*
* Add new device to list of registered devices
*
@@ -762,7 +788,9 @@ static noinline struct btrfs_device *device_list_add(const char *path,
fs_devices = find_fsid(disk_super->fsid,
disk_super->metadata_uuid);
} else {
- fs_devices = find_fsid(disk_super->fsid, NULL);
+ fs_devices = find_fsid_reverted_metadata(disk_super);
+ if (!fs_devices)
+ fs_devices = find_fsid(disk_super->fsid, NULL);
}
@@ -792,12 +820,18 @@ static noinline struct btrfs_device *device_list_add(const char *path,
* a device which had the CHANGING_FSID_V2 flag then replace the
* metadata_uuid/fsid values of the fs_devices.
*/
- if (has_metadata_uuid && fs_devices->fsid_change &&
+ if (fs_devices->fsid_change &&
found_transid > fs_devices->latest_generation) {
memcpy(fs_devices->fsid, disk_super->fsid,
BTRFS_FSID_SIZE);
- memcpy(fs_devices->metadata_uuid,
- disk_super->metadata_uuid, BTRFS_FSID_SIZE);
+
+ if (has_metadata_uuid)
+ memcpy(fs_devices->metadata_uuid,
+ disk_super->metadata_uuid,
+ BTRFS_FSID_SIZE);
+ else
+ memcpy(fs_devices->metadata_uuid,
+ disk_super->fsid, BTRFS_FSID_SIZE);
fs_devices->fsid_change = false;
}
--
2.20.1
next prev parent reply other threads:[~2020-02-14 17:52 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20200214154854.6746-1-sashal@kernel.org>
2020-02-14 15:41 ` [PATCH AUTOSEL 5.5 123/542] Btrfs: keep pages dirty when using btrfs_writepage_fixup_worker Sasha Levin
2020-02-14 15:46 ` [PATCH AUTOSEL 5.5 419/542] btrfs: fix possible NULL-pointer dereference in integrity checks Sasha Levin
2020-02-14 15:46 ` [PATCH AUTOSEL 5.5 420/542] btrfs: safely advance counter when looking up bio csums Sasha Levin
2020-02-14 15:46 ` [PATCH AUTOSEL 5.5 421/542] btrfs: device stats, log when stats are zeroed Sasha Levin
2020-02-14 15:47 ` [PATCH AUTOSEL 5.5 448/542] btrfs: separate definition of assertion failure handlers Sasha Levin
2020-02-14 15:47 ` Sasha Levin [this message]
2020-02-14 15:48 ` [PATCH AUTOSEL 5.5 503/542] btrfs: do not do delalloc reservation under page lock Sasha Levin
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=20200214154854.6746-449-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=Damenly_Su@gmx.com \
--cc=dsterba@suse.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nborisov@suse.com \
--cc=stable@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).