Skip to content

Commit 5f58d78

Browse files
asjkdave
authored andcommitted
btrfs: free device in btrfs_close_devices for a single device filesystem
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 (such as a replace source device). 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 freeing the cache when closing the device for a single device filesystem. This will ensure that the mount command passed device path is scanned successfully during the next mount. CC: [email protected] # 5.10+ Reported-by: Daan De Meyer <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: Anand Jain <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 519b7e1 commit 5f58d78

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

fs/btrfs/volumes.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ void btrfs_free_device(struct btrfs_device *device)
403403
static void free_fs_devices(struct btrfs_fs_devices *fs_devices)
404404
{
405405
struct btrfs_device *device;
406+
406407
WARN_ON(fs_devices->opened);
407408
while (!list_empty(&fs_devices->devices)) {
408409
device = list_entry(fs_devices->devices.next,
@@ -1181,9 +1182,22 @@ void btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
11811182

11821183
mutex_lock(&uuid_mutex);
11831184
close_fs_devices(fs_devices);
1184-
if (!fs_devices->opened)
1185+
if (!fs_devices->opened) {
11851186
list_splice_init(&fs_devices->seed_list, &list);
11861187

1188+
/*
1189+
* If the struct btrfs_fs_devices is not assembled with any
1190+
* other device, it can be re-initialized during the next mount
1191+
* without the needing device-scan step. Therefore, it can be
1192+
* fully freed.
1193+
*/
1194+
if (fs_devices->num_devices == 1) {
1195+
list_del(&fs_devices->fs_list);
1196+
free_fs_devices(fs_devices);
1197+
}
1198+
}
1199+
1200+
11871201
list_for_each_entry_safe(fs_devices, tmp, &list, seed_list) {
11881202
close_fs_devices(fs_devices);
11891203
list_del(&fs_devices->seed_list);

0 commit comments

Comments
 (0)