Skip to content

Commit 50d281f

Browse files
asjkdave
authored andcommitted
btrfs: scan device in non-exclusive mode
This fixes mkfs/mount/check failures due to race with systemd-udevd scan. During the device scan initiated by systemd-udevd, other user space EXCL operations such as mkfs, mount, or check may get blocked and result in a "Device or resource busy" error. This is because the device scan process opens the device with the EXCL flag in the kernel. Two reports were received: - btrfs/179 test case, where the fsck command failed with the -EBUSY error - LTP pwritev03 test case, where mkfs.vfs failed with the -EBUSY error, when mkfs.vfs tried to overwrite old btrfs filesystem on the device. In both cases, fsck and mkfs (respectively) were racing with a systemd-udevd device scan, and systemd-udevd won, resulting in the -EBUSY error for fsck and mkfs. Reproducing the problem has been difficult because there is a very small window during which these userspace threads can race to acquire the exclusive device open. Even on the system where the problem was observed, the problem occurrences were anywhere between 10 to 400 iterations and chances of reproducing decreases with debug printk()s. However, an exclusive device open is unnecessary for the scan process, as there are no write operations on the device during scan. Furthermore, during the mount process, the superblock is re-read in the below function call chain: btrfs_mount_root btrfs_open_devices open_fs_devices btrfs_open_one_device btrfs_get_bdev_and_sb So, to fix this issue, removes the FMODE_EXCL flag from the scan operation, and add a comment. The case where mkfs may still write to the device and a scan is running, the btrfs signature is not written at that time so scan will not recognize such device. Reported-by: Sherry Yang <sherry.yang@oracle.com> Reported-by: kernel test robot <oliver.sang@intel.com> Link: https://lore.kernel.org/oe-lkp/202303170839.fdf23068-oliver.sang@intel.com CC: stable@vger.kernel.org # 5.4+ Signed-off-by: Anand Jain <anand.jain@oracle.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 2f1a6be commit 50d281f

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

fs/btrfs/volumes.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1366,8 +1366,17 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
13661366
* So, we need to add a special mount option to scan for
13671367
* later supers, using BTRFS_SUPER_MIRROR_MAX instead
13681368
*/
1369-
flags |= FMODE_EXCL;
13701369

1370+
/*
1371+
* Avoid using flag |= FMODE_EXCL here, as the systemd-udev may
1372+
* initiate the device scan which may race with the user's mount
1373+
* or mkfs command, resulting in failure.
1374+
* Since the device scan is solely for reading purposes, there is
1375+
* no need for FMODE_EXCL. Additionally, the devices are read again
1376+
* during the mount process. It is ok to get some inconsistent
1377+
* values temporarily, as the device paths of the fsid are the only
1378+
* required information for assembling the volume.
1379+
*/
13711380
bdev = blkdev_get_by_path(path, flags, holder);
13721381
if (IS_ERR(bdev))
13731382
return ERR_CAST(bdev);

0 commit comments

Comments
 (0)