btrfs: always scan a single device when mounted
Subsystems (2)
David Sterba
maintainerPATCH 1/1 btrfs: always scan a single device when mounted
There are reports that since version 6.7 update-grub fails to find the device of the root on systems without initrd and on a single device.
This looks like the device name changed in the output of /proc/self/mountinfo:
6.5-rc5 working
18 1 0:16 / / rw,noatime - btrfs /dev/sda8 ...
6.7 not working:
17 1 0:15 / / rw,noatime - btrfs /dev/root ...
and "update-grub" shows this error:
/usr/sbin/grub-probe: error: cannot find a device for / (is /dev mounted?)
This looks like it's related to the device name, but grub-probe recognizes the "/dev/root" path and tries to find the underlying device. However there's a special case for some filesystems, for btrfs in particular.
The generic root device detection heuristic is not done and it all relies on reading the device infos by a btrfs specific ioctl. This ioctl returns the device name as it was saved at the time of device scan (in this case it's /dev/root).
The change in 6.7 for temp_fsid to allow several single device filesystem to exist with the same fsid (and transparently generate a new UUID at mount time) was to skip caching/registering such devices.
This also skipped mounted device. One step of scanning is to check if the device name hasn't changed, and if yes then update the cached value.
This broke the grub-probe as it always read the device /dev/root and couldn't find it in the system. A temporary workaround is to create a symlink but this does not survive reboot.
The right fix is to allow updating the device path of a mounted filesystem even if this is a single device one. This does not affect the temp_fsid feature, the UUID of the mounted filesystem remains the same and the matching is based on device major:minor which is unique per mounted filesystem.
As the main part of device scanning and list update is done in device_list_add() that handles all corner cases and locking, it is extended to take a parameter that tells it to do everything as before, except adding a new device entry.
This covers the path when the device (that exists for all mounted devices) name changes, updating /dev/root to /dev/sdx. Any other single device with filesystem is skipped.
Note that if a system is booted and initial mount is done on the /dev/root device, this will be the cached name of the device. Only after the command "btrfs device rescan" it will change as it triggers the rename.
The fix was verified by users whose systems were affected.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=218353
--- fs/btrfs/volumes.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)
fs/btrfs/volumes.c +14 -16
@@ -738,6 +738,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,bool same_fsid_diff_dev = false;bool has_metadata_uuid = (btrfs_super_incompat_flags (disk_super) &BTRFS_FEATURE_INCOMPAT_METADATA_UUID ); +bool can_create_new = *new_device_added;if (btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_CHANGING_FSID_V2 ) { btrfs_err(NULL,
@@ -753,6 +754,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (error); } + *new_device_added = false; fs_devices =find_fsid_by_device (disk_super, path_devt, &same_fsid_diff_dev);if (!fs_devices) {
@@ -804,6 +806,15 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (-EBUSY ); } +if (!can_create_new) { +pr_info ( +"BTRFS: device fsid %pU devid %llu transid %llu %s skip registration scanned by %s (%d)\n" , + disk_super->fsid, devid, found_transid, path, + current->comm,task_pid_nr (current)); +mutex_unlock (&fs_devices->device_list_mutex); +return NULL ; + } + nofs_flag =memalloc_nofs_save (); device =btrfs_alloc_device (NULL , &devid, disk_super->dev_item.uuid, path);
@@ -1355,27 +1366,14 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags, goto error_bdev_put; } -if (!mount_arg_dev &&btrfs_super_num_devices (disk_super) ==1 && - !(btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_SEEDING )) { -dev_t devt; - - ret =lookup_bdev (path, &devt); -if (ret) -btrfs_warn (NULL ,"lookup bdev failed for path %s: %d" , - path, ret); -else -btrfs_free_stale_devices (devt,NULL ); - -pr_debug ("BTRFS: skip registering single non-seed device %s\n" , path); - device =NULL ; - goto free_disk_super; - } +if (mount_arg_dev ||btrfs_super_num_devices (disk_super) !=1 || + (btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_SEEDING )) + new_device_added = true; device =device_list_add (path, disk_super, &new_device_added);if (!IS_ERR (device) && new_device_added)btrfs_free_stale_devices (device->devt, device); -free_disk_super:btrfs_release_disk_super (disk_super); error_bdev_put:
Signature · 1 line
2.42.1
Quoted 59 lines · David Sterba
There are reports that since version 6.7 update-grub fails to find the device of the root on systems without initrd and on a single device.
This looks like the device name changed in the output of
/proc/self/mountinfo:6.5-rc5 working
18 1 0:16 / / rw,noatime - btrfs
/dev/sda8...6.7 not working:
17 1 0:15 / / rw,noatime - btrfs
/dev/root...and "update-grub" shows this error:
/usr/sbin/grub-probe: error: cannot find a device for / (is /dev mounted?)This looks like it's related to the device name, but grub-probe recognizes the "
/dev/root" path and tries to find the underlying device. However there's a special case for some filesystems, for btrfs in particular.The generic root device detection heuristic is not done and it all relies on reading the device infos by a btrfs specific ioctl. This ioctl returns the device name as it was saved at the time of device scan (in this case it's
/dev/root).The change in 6.7 for
temp_fsidto allow several single device filesystem to exist with the same fsid (and transparently generate a new UUID at mount time) was to skip caching/registering such devices.This also skipped mounted device. One step of scanning is to check if the device name hasn't changed, and if yes then update the cached value.
This broke the grub-probe as it always read the device
/dev/rootand couldn't find it in the system. A temporary workaround is to create a symlink but this does not survive reboot.The right fix is to allow updating the device path of a mounted filesystem even if this is a single device one. This does not affect the
temp_fsidfeature, the UUID of the mounted filesystem remains the same and the matching is based on device major:minor which is unique per mounted filesystem.As the main part of device scanning and list update is done in
device_list_add()that handles all corner cases and locking, it is extended to take a parameter that tells it to do everything as before, except adding a new device entry.This covers the path when the device (that exists for all mounted devices) name changes, updating
/dev/rootto/dev/sdx. Any other single device with filesystem is skipped.Note that if a system is booted and initial mount is done on the
/dev/rootdevice, this will be the cached name of the device. Only after the command "btrfs device rescan" it will change as it triggers the rename.
Quoted 7 lines
The fix was verified by users whose systems were affected.
CC [email protected] # 6.7+Fixes bc27d6f0aa0e ("btrfs: scan but don't register device on single device filesystem")Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=218353
fs/btrfs/volumes.c static noinline struct btrfs_device *device_list_add(const char *path, · line 741
Quoted 13 lines
--- fs/btrfs/volumes.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)fs/btrfs/volumes.c +1
-0@@ -738,6 +738,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,bool same_fsid_diff_dev = false;bool has_metadata_uuid = (btrfs_super_incompat_flags (disk_super) &BTRFS_FEATURE_INCOMPAT_METADATA_UUID ); +bool can_create_new = *new_device_added;
It took me quite a while to figure out all the intended logic with the now in/out parameter. I think it's probably too cute? Why not just add another parameter "can_create_new_device"? I think it feels kind of weird on the caller side too, to set "new_device_added" to true, but then still rely on it to actually get set to true.
Once I got past this, the logic made sense, so definitely don't block yourself on this nit.
Quoted 39 lines
fs/btrfs/volumes.c +10
-8if (btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_CHANGING_FSID_V2 ) { btrfs_err(NULL,@@ -753,6 +754,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (error); } + *new_device_added = false; fs_devices =find_fsid_by_device (disk_super, path_devt, &same_fsid_diff_dev);if (!fs_devices) {@@ -804,6 +806,15 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (-EBUSY ); } +if (!can_create_new) { +pr_info ( +"BTRFS: device fsid %pU devid %llu transid %llu %s skip registration scanned by %s (%d)\n" , + disk_super->fsid, devid, found_transid, path, + current->comm,task_pid_nr (current)); +mutex_unlock (&fs_devices->device_list_mutex); +return NULL ; + } + nofs_flag =memalloc_nofs_save (); device =btrfs_alloc_device (NULL , &devid, disk_super->dev_item.uuid, path);@@ -1355,27 +1366,14 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags, goto error_bdev_put; } -if (!mount_arg_dev &&btrfs_super_num_devices (disk_super) ==1 && - !(btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_SEEDING )) { -dev_t devt; - - ret =lookup_bdev (path, &devt); -if (ret) -btrfs_warn (NULL ,"lookup bdev failed for path %s: %d" , - path, ret);
fs/btrfs/volumes.c struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags, · line 1371
Quoted 10 lines
fs/btrfs/volumes.c +3
-7-else -btrfs_free_stale_devices (devt,NULL ); - -pr_debug ("BTRFS: skip registering single non-seed device %s\n" , path); - device =NULL ; - goto free_disk_super; - } +if (mount_arg_dev ||btrfs_super_num_devices (disk_super) !=1 || + (btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_SEEDING )) + new_device_added = true;
This is the line I was referring to in the comment above, fwiw.
Quoted 13 lines
fs/btrfs/volumes.c +0
-1device =device_list_add (path, disk_super, &new_device_added);if (!IS_ERR (device) && new_device_added)btrfs_free_stale_devices (device->devt, device); -free_disk_super:btrfs_release_disk_super (disk_super); error_bdev_put:Signature · 1 line
2.42.1
Quoted 15 lines · Boris Burkov
fs/btrfs/volumes.c static noinline struct btrfs_device *device_list_add(const char *path, · line 741
Quoted 7 lines · David Sterba
fs/btrfs/volumes.c +1
-0@@ -738,6 +738,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,bool same_fsid_diff_dev = false;bool has_metadata_uuid = (btrfs_super_incompat_flags (disk_super) &BTRFS_FEATURE_INCOMPAT_METADATA_UUID ); +bool can_create_new = *new_device_added;It took me quite a while to figure out all the intended logic with the now in/out parameter. I think it's probably too cute? Why not just add another parameter "
can_create_new_device"? I think it feels kind of weird on the caller side too, to set "new_device_added" to true, but then still rely on it to actually get set to true.
Quoted 2 lines
Once I got past this, the logic made sense, so definitely don't block yourself on this nit.
I had the separate parameter for the debugging version and removed for the final but I agree that it makes things less clear. Also there's something wrong with the device matching so the meaning of the parameter will be unchanged.
Quoted 28 lines · David Sterba
There are reports that since version 6.7 update-grub fails to find the device of the root on systems without initrd and on a single device.
This looks like the device name changed in the output of
/proc/self/mountinfo:6.5-rc5 working
18 1 0:16 / / rw,noatime - btrfs /dev/sda8 ...6.7 not working:
17 1 0:15 / / rw,noatime - btrfs /dev/root ...and "update-grub" shows this error:
/usr/sbin/grub-probe: error: cannot find a device for / (is /dev mounted?)This looks like it's related to the device name, but grub-probe recognizes the "
/dev/root" path and tries to find the underlying device. However there's a special case for some filesystems, for btrfs in particular.The generic root device detection heuristic is not done and it all relies on reading the device infos by a btrfs specific ioctl. This ioctl returns the device name as it was saved at the time of device scan (in this case it's
/dev/root).
Quoted 6 lines
The change in 6.7 for
temp_fsidto allow several single device filesystem to exist with the same fsid (and transparently generate a new UUID at mount time) was to skip caching/registering such devices.This also skipped mounted device.
It's reasonable. However is there any logs from the debug message to confirm?
Quoted 11 lines
One step of scanning is to check if
the device name hasn't changed, and if yes then update the cached value.This broke the grub-probe as it always read the device
/dev/rootand couldn't find it in the system. A temporary workaround is to create a symlink but this does not survive reboot.The right fix is to allow updating the device path of a mounted filesystem even if this is a single device one.
And at the same time, if the device is not mounted, it still does not register the single device. As in the original design.
Quoted 5 lines
This does not affect the
temp_fsidfeature, the UUID of the mounted filesystem remains the same and the matching is based on device major:minor which is unique per mounted filesystem.
It looks like the logic in find_fsid_by_device() does not verify if the %fsid_fs_devices and %devt_fs_devices are the same. I am concerned that if they aren't, and %devt_fs_devices is matched by devt only, it implies
that the rest of the populated values in fs_devices may be inconsistent
(from the super).
I had a bunch of test cases for temp-fsid, I need to (find them) and send it out.
Quoted 4 lines
As the main part of device scanning and list update is done in
device_list_add()that handles all corner cases and locking, it is extended to take a parameter that tells it to do everything as before, except adding a new device entry.
Hm. %new_device_added was for btrfs_scan_one_device() so that it can call btrfs_free_stale_devices(), removing any stale devices if present. However, theoretically, there shouldn't be any stale devices. Let's keep it for now, as the find_fsid_by_device() logic might return incorrect fs_devices (I need to confirm this again).
Quoted 8 lines
This covers the path when the device (that exists for all mounted devices) name changes, updating
/dev/rootto/dev/sdx. Any other single device with filesystem is skipped.Note that if a system is booted and initial mount is done on the
/dev/rootdevice, this will be the cached name of the device. Only after the command "btrfs device rescan" it will change as it triggers the
"btrfs device scan"
Quoted 48 lines
rename.
The fix was verified by users whose systems were affected.
CC [email protected] # 6.7+Fixes bc27d6f0aa0e ("btrfs: scan but don't register device on single device filesystem")Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=218353
Link https://lore.kernel.org/lkml/CAKLYgeJ1tUuqLcsquwuFqjDXPSJpEiokrWK2gisPKDZLs8Y2TQ@mail.gmail.com/ open hereSigned-off-by David Sterba <[email protected]>--- fs/btrfs/volumes.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)fs/btrfs/volumes.c +1
-0@@ -738,6 +738,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,bool same_fsid_diff_dev = false;bool has_metadata_uuid = (btrfs_super_incompat_flags (disk_super) &BTRFS_FEATURE_INCOMPAT_METADATA_UUID ); +bool can_create_new = *new_device_added;if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_CHANGING_FSID_V2) { btrfs_err(NULL,fs/btrfs/volumes.c +1
-0@@ -753,6 +754,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (error); } + *new_device_added = false;fs_devices = find_fsid_by_device(disk_super, path_devt, &same_fsid_diff_dev); if (!fs_devices) {fs/btrfs/volumes.c +1
-0@@ -804,6 +806,15 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (-EBUSY ); } +if (!can_create_new) {
fs/btrfs/volumes.c static noinline struct btrfs_device *device_list_add(const char *path, · line 820
Quoted 10 lines
fs/btrfs/volumes.c +8
-0+pr_info ( +"BTRFS: device fsid %pU devid %llu transid %llu %s skip registration scanned by %s (%d)\n" , + disk_super->fsid, devid, found_transid, path, + current->comm,task_pid_nr (current)); +mutex_unlock (&fs_devices->device_list_mutex); +return NULL ; + } +
I just ran the temp-fsid test cases attached here. Comparing the output with and without this patch seems to be breaking something in the temp-fsid feature. I need to further verify. I will convert this test to fstests. However, in the meantime, it can be used to verify.
The testcases need to 'run' command from [email protected]:asj/run.git. sb command is also attached here.
To run-the-test case:
save attahced 'sb' and 'run' command from github to a BIN directory. update the devices in the file 't' and run it.
./t (with and without patch)
Sorry for the messy self use testscripts for now. I am converting them to fstests.
Thanks, Anand
Quoted 34 lines
nofs_flag=memalloc_nofs_save();
device = btrfs_alloc_device(NULL, &devid,
disk_super->dev_item.uuid, path);fs/btrfs/volumes.c +3
-16@@ -1355,27 +1366,14 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags, goto error_bdev_put; } -if (!mount_arg_dev &&btrfs_super_num_devices (disk_super) ==1 && - !(btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_SEEDING )) { -dev_t devt; - - ret =lookup_bdev (path, &devt); -if (ret) -btrfs_warn (NULL ,"lookup bdev failed for path %s: %d" , - path, ret); -else -btrfs_free_stale_devices (devt,NULL ); - -pr_debug ("BTRFS: skip registering single non-seed device %s\n" , path); - device =NULL ; - goto free_disk_super; - } +if (mount_arg_dev ||btrfs_super_num_devices (disk_super) !=1 || + (btrfs_super_flags (disk_super) &BTRFS_SUPER_FLAG_SEEDING )) + new_device_added = true; device =device_list_add (path, disk_super, &new_device_added);if (!IS_ERR (device) && new_device_added)btrfs_free_stale_devices (device->devt, device); -free_disk_super:btrfs_release_disk_super (disk_super); error_bdev_put:
Quoted 63 lines · Anand Jain
Quoted 28 lines · David Sterba
There are reports that since version 6.7 update-grub fails to find the device of the root on systems without initrd and on a single device.
This looks like the device name changed in the output of
/proc/self/mountinfo:6.5-rc5 working
18 1 0:16 / / rw,noatime - btrfs /dev/sda8 ...6.7 not working:
17 1 0:15 / / rw,noatime - btrfs /dev/root ...and "update-grub" shows this error:
/usr/sbin/grub-probe: error: cannot find a device for / (is /dev mounted?)This looks like it's related to the device name, but grub-probe recognizes the "
/dev/root" path and tries to find the underlying device. However there's a special case for some filesystems, for btrfs in particular.The generic root device detection heuristic is not done and it all relies on reading the device infos by a btrfs specific ioctl. This ioctl returns the device name as it was saved at the time of device scan (in this case it's
/dev/root).Quoted 6 lines
The change in 6.7 for
temp_fsidto allow several single device filesystem to exist with the same fsid (and transparently generate a new UUID at mount time) was to skip caching/registering such devices.This also skipped mounted device.
It's reasonable. However is there any logs from the debug message to confirm?
Quoted 11 lines
One step of scanning is to check if
the device name hasn't changed, and if yes then update the cached value.This broke the grub-probe as it always read the device
/dev/rootand couldn't find it in the system. A temporary workaround is to create a symlink but this does not survive reboot.The right fix is to allow updating the device path of a mounted filesystem even if this is a single device one.
And at the same time, if the device is not mounted, it still does not register the single device. As in the original design.
Quoted 5 lines
This does not affect the
temp_fsidfeature, the UUID of the mounted filesystem remains the same and the matching is based on device major:minor which is unique per mounted filesystem.
Quoted 5 lines
It looks like the logic in
find_fsid_by_device()does not verify if the %fsid_fs_devices and %devt_fs_devices are the same. I am concerned that if they aren't, and %devt_fs_devices is matched by devt only, it implies that the rest of the populated values infs_devicesmay be inconsistent (from the super).
And this actually a problem, a lot of fstests fail with messages like:
btrfs/004 [22:53:33][ 346.883630] run fstests btrfs/004 at 2024-02-06 22:53:34
[ 347.513164] BTRFS: device fsid e161b391-e959-419b-b6a6-9c1a371a6c15 devid 1 transid 11 /dev/vda scanned by mount (30014) [ 347.515665] BTRFS info (device vda): first mount of filesystem e161b391-e959-419b-b6a6-9c1a371a6c15 [ 347.516597] BTRFS info (device vda): using crc32c (crc32c-generic) checksum algorithm [ 347.517716] BTRFS info (device vda): using free-space-tree [ 347.996843] BTRFS: device fsid d9f25a27-92c4-4ff3-a2da-634546711e68 devid 1 transid 6 /dev/vdb skip registration scanned by mkfs.btrfs (30078) [ 348.009943] BTRFS: device fsid d9f25a27-92c4-4ff3-a2da-634546711e68 devid 1 transid 6 /dev/vdb scanned by mount (30082) [ 348.013764] BTRFS info (device vdb): first mount of filesystem d9f25a27-92c4-4ff3-a2da-634546711e68 [ 348.014943] BTRFS info (device vdb): using crc32c (crc32c-generic) checksum algorithm [ 348.015949] BTRFS error (device vdb): superblock fsid doesn't match fsid of fs_devices: d9f25a27-92c4-4ff3-a2da-634546711e68 != 3fb9009e-b1d5-46ac-ba94-8120384610e4 [ 348.017653] BTRFS error (device vdb): superblock metadata_uuid doesn't match metadata uuid of fs_devices: d9f25a27-92c4-4ff3-a2da-634546711e68 != 3fb9009e-b1d5-46ac-ba94-8120384610e4
this
[ 348.019590] BTRFS error (device vdb): dev_item UUID does not match metadata fsid: 3fb9009e-b1d5-46ac-ba94-8120384610e4 != d9f25a27-92c4-4ff3-a2da-634546711e68 [ 348.021313] BTRFS error (device vdb): superblock contains fatal errors [ 348.022263] BTRFS error (device vdb): open_ctree failed
[failed, exit status 1][ 348.058344] BTRFS info (device vda): last unmount of filesystem e161b391-e959-419b-b6a6-9c1a371a6c15
and there are messages about using temp-fsid feature but that's not what I'd expect, apparently the uuids get totally mixed up:
btrfs/002 [22:52:24][ 276.908253] run fstests btrfs/002 at 2024-02-06 22:52:24
[ 277.531910] BTRFS: device fsid e161b391-e959-419b-b6a6-9c1a371a6c15 devid 1 transid 9 /dev/vda scanned by mount (15065) [ 277.534162] BTRFS info (device vda): first mount of filesystem e161b391-e959-419b-b6a6-9c1a371a6c15 [ 277.535108] BTRFS info (device vda): using crc32c (crc32c-generic) checksum algorithm [ 277.535913] BTRFS info (device vda): using free-space-tree [ 277.782925] BTRFS: device fsid c69cb0c6-6ca1-4e07-9e4e-c5b5cc09b2c9 devid 1 transid 6 /dev/vdb skip registration scanned by mkfs.btrfs (15109) [ 277.824885] BTRFS: device /dev/vdb using temp-fsid d1299d0e-92d4-47a5-b6e7-5f998f86c5f0 [ 277.827699] BTRFS: device fsid c69cb0c6-6ca1-4e07-9e4e-c5b5cc09b2c9 devid 1 transid 6 /dev/vdb scanned by mount (15117) [ 277.830983] BTRFS info (device vdb): first mount of filesystem c69cb0c6-6ca1-4e07-9e4e-c5b5cc09b2c9 [ 277.832252] BTRFS info (device vdb): using crc32c (crc32c-generic) checksum algorithm [ 277.833325] BTRFS info (device vdb): using free-space-tree [ 277.847045] BTRFS info (device vdb): checking UUID tree [ 294.727566] grep (19725) used greatest stack depth: 24816 bytes left [ 294.788244] dd (19697) used greatest stack depth: 24544 bytes left [ 295.631873] dd (19752) used greatest stack depth: 24328 bytes left [ 317.755256] BTRFS info (device vdb): last unmount of filesystem d1299d0e-92d4-47a5-b6e7-5f998f86c5f0 [ 317.820227] BTRFS info (device vda): last unmount of filesystem e161b391-e959-419b-b6a6-9c1a371a6c15
Quoted 8 lines
I had a bunch of test cases for temp-fsid, I need to (find them) and send it out.
Quoted 4 lines
As the main part of device scanning and list update is done in
device_list_add()that handles all corner cases and locking, it is extended to take a parameter that tells it to do everything as before, except adding a new device entry.
Quoted 5 lines
Hm. %new_device_added was for
btrfs_scan_one_device()so that it can callbtrfs_free_stale_devices(), removing any stale devices if present. However, theoretically, there shouldn't be any stale devices. Let's keep it for now, as thefind_fsid_by_device()logic might return incorrectfs_devices(I need to confirm this again).
Ok, that's a reasonable idea.
Quoted 60 lines
Quoted 7 lines
This covers the path when the device (that exists for all mounted devices) name changes, updating
/dev/rootto/dev/sdx. Any other single device with filesystem is skipped.Note that if a system is booted and initial mount is done on the
/dev/rootdevice, this will be the cached name of the device. Only after the command "btrfs device rescan" it will change as it triggers the"btrfs device scan"
Quoted 47 lines
rename.
The fix was verified by users whose systems were affected.
CC [email protected] # 6.7+Fixes bc27d6f0aa0e ("btrfs: scan but don't register device on single device filesystem")Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=218353
Link https://lore.kernel.org/lkml/CAKLYgeJ1tUuqLcsquwuFqjDXPSJpEiokrWK2gisPKDZLs8Y2TQ@mail.gmail.com/ open hereSigned-off-by David Sterba <[email protected]>--- fs/btrfs/volumes.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)fs/btrfs/volumes.c +1
-0@@ -738,6 +738,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,bool same_fsid_diff_dev = false;bool has_metadata_uuid = (btrfs_super_incompat_flags (disk_super) &BTRFS_FEATURE_INCOMPAT_METADATA_UUID ); +bool can_create_new = *new_device_added;if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_CHANGING_FSID_V2) { btrfs_err(NULL,fs/btrfs/volumes.c +1
-0@@ -753,6 +754,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (error); } + *new_device_added = false;fs_devices = find_fsid_by_device(disk_super, path_devt, &same_fsid_diff_dev); if (!fs_devices) {fs/btrfs/volumes.c +1
-0@@ -804,6 +806,15 @@ static noinline struct btrfs_device *device_list_add(const char *path,return ERR_PTR (-EBUSY ); } +if (!can_create_new) {
Quoted 14 lines
fs/btrfs/volumes.c static noinline struct btrfs_device *device_list_add(const char *path, · line 817
Quoted 8 lines
fs/btrfs/volumes.c +8
-0+pr_info ( +"BTRFS: device fsid %pU devid %llu transid %llu %s skip registration scanned by %s (%d)\n" , + disk_super->fsid, devid, found_transid, path, + current->comm,task_pid_nr (current)); +mutex_unlock (&fs_devices->device_list_mutex); +return NULL ; + } +I just ran the temp-fsid test cases attached here. Comparing the output with and without this patch seems to be breaking something in the temp-fsid feature. I need to further verify. I will convert this test to fstests. However, in the meantime, it can be used to verify.
Yeah, at this state the patch is broken.