Message ID | 1bf56a77b8b57cc3b993fda00752e79830685ffc.1674772170.git.josef@toxicpanda.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3] btrfs: allow single disk devices to mount with older generations | expand |
Josef, An alternative approach is to free the device allocation for a single device filesystem during the close_ctree() [1]. In my opinion, this solution is more elegant. I would appreciate your thoughts on this. [1] https://patchwork.kernel.org/project/linux-btrfs/patch/faf1de6f88707dbf0406ab85e094e72107b30637.1674221591.git.anand.jain@oracle.com/ Thanks, Anand On 1/27/23 06:31, Josef Bacik wrote: > We have this check to make sure we don't accidentally add older devices > that may have disappeared and re-appeared with an older generation from > being added to an fs_devices. This makes sense, we don't want stale > disks in our file system. However for single disks this doesn't really > make sense. I've seen this in testing, but I was provided a reproducer > from a project that builds btrfs images on loopback devices. The > loopback device gets cached with the new generation, and then if it is > re-used to generate a new file system we'll fail to mount it because the > new fs is "older" than what we have in cache. > > Fix this by simply ignoring this check if we're a single disk file > system, as we're not going to cause problems for the fs by allowing the > disk to be mounted with an older generation than what is in our cache. > > I've also added a error message for this case, as it was kind of > annoying to find originally. > > Reviewed-by: Anand Jain <anand.jain@oracle.com> > Reported-by: Daan De Meyer <daandemeyer@fb.com> > Signed-off-by: Josef Bacik <josef@toxicpanda.com> > --- > v2->v3: > - Dropped the printk as we now have a printk here to indicate that something > went wrong. > - Validated that it still fixes btrfs/219. That test validates a few corner > cases that I could think of at the time, and looking at it again I've covered > everything that comes to mind. > > fs/btrfs/volumes.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c > index 707dd0456cea..b17b4a66a8d4 100644 > --- a/fs/btrfs/volumes.c > +++ b/fs/btrfs/volumes.c > @@ -766,6 +766,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, > BTRFS_FEATURE_INCOMPAT_METADATA_UUID); > bool fsid_change_in_progress = (btrfs_super_flags(disk_super) & > BTRFS_SUPER_FLAG_CHANGING_FSID_V2); > + bool multi_disk = btrfs_super_num_devices(disk_super) > 1; > > error = lookup_bdev(path, &path_devt); > if (error) { > @@ -902,7 +903,8 @@ static noinline struct btrfs_device *device_list_add(const char *path, > * tracking a problem where systems fail mount by subvolume id > * when we reject replacement on a mounted FS. > */ > - if (!fs_devices->opened && found_transid < device->generation) { > + if (multi_disk && !fs_devices->opened && > + found_transid < device->generation) { > /* > * That is if the FS is _not_ mounted and if you > * are here, that means there is more than one
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 707dd0456cea..b17b4a66a8d4 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -766,6 +766,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, BTRFS_FEATURE_INCOMPAT_METADATA_UUID); bool fsid_change_in_progress = (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_CHANGING_FSID_V2); + bool multi_disk = btrfs_super_num_devices(disk_super) > 1; error = lookup_bdev(path, &path_devt); if (error) { @@ -902,7 +903,8 @@ static noinline struct btrfs_device *device_list_add(const char *path, * tracking a problem where systems fail mount by subvolume id * when we reject replacement on a mounted FS. */ - if (!fs_devices->opened && found_transid < device->generation) { + if (multi_disk && !fs_devices->opened && + found_transid < device->generation) { /* * That is if the FS is _not_ mounted and if you * are here, that means there is more than one