2024-02-14 16:43:16

by Johannes Thumshirn

[permalink] [raw]
Subject: [PATCH 1/5] btrfs: always open the device read-only in btrfs_scan_one_device

From: Christoph Hellwig <[email protected]>

btrfs_scan_one_device opens the block device only to read the super
block. Instead of passing a blk_mode_t argument to sometimes open
it for writing, just hard code BLK_OPEN_READ as it will never write
to the device or hand the block_device out to someone else.

Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Johannes Thumshirn <[email protected]>
---
fs/btrfs/super.c | 9 ++++-----
fs/btrfs/volumes.c | 4 ++--
fs/btrfs/volumes.h | 2 +-
3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 40ae264fd3ed..b6cadf4f21b8 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -299,10 +299,9 @@ static int btrfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
break;
case Opt_device: {
struct btrfs_device *device;
- blk_mode_t mode = btrfs_open_mode(fc);

mutex_lock(&uuid_mutex);
- device = btrfs_scan_one_device(param->string, mode, false);
+ device = btrfs_scan_one_device(param->string, false);
mutex_unlock(&uuid_mutex);
if (IS_ERR(device))
return PTR_ERR(device);
@@ -1808,7 +1807,7 @@ static int btrfs_get_tree_super(struct fs_context *fc)
* With 'true' passed to btrfs_scan_one_device() (mount time) we expect
* either a valid device or an error.
*/
- device = btrfs_scan_one_device(fc->source, mode, true);
+ device = btrfs_scan_one_device(fc->source, true);
ASSERT(device != NULL);
if (IS_ERR(device)) {
mutex_unlock(&uuid_mutex);
@@ -2210,7 +2209,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
* Scanning outside of mount can return NULL which would turn
* into 0 error code.
*/
- device = btrfs_scan_one_device(vol->name, BLK_OPEN_READ, false);
+ device = btrfs_scan_one_device(vol->name, false);
ret = PTR_ERR_OR_ZERO(device);
mutex_unlock(&uuid_mutex);
break;
@@ -2228,7 +2227,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
* Scanning outside of mount can return NULL which would turn
* into 0 error code.
*/
- device = btrfs_scan_one_device(vol->name, BLK_OPEN_READ, false);
+ device = btrfs_scan_one_device(vol->name, false);
if (IS_ERR_OR_NULL(device)) {
mutex_unlock(&uuid_mutex);
ret = PTR_ERR(device);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4ad9eca9b46c..44caf1a48d33 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1308,7 +1308,7 @@ int btrfs_forget_devices(dev_t devt)
* the device or return an error. Multi-device and seeding devices are registered
* in both cases.
*/
-struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
+struct btrfs_device *btrfs_scan_one_device(const char *path,
bool mount_arg_dev)
{
struct btrfs_super_block *disk_super;
@@ -1337,7 +1337,7 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
* values temporarily, as the device paths of the fsid are the only
* required information for assembling the volume.
*/
- bdev_handle = bdev_open_by_path(path, flags, NULL, NULL);
+ bdev_handle = bdev_open_by_path(path, BLK_OPEN_READ, NULL, NULL);
if (IS_ERR(bdev_handle))
return ERR_CAST(bdev_handle);

diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 21d4de0e3f1f..97c7284e7565 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -655,7 +655,7 @@ struct btrfs_block_group *btrfs_create_chunk(struct btrfs_trans_handle *trans,
void btrfs_mapping_tree_free(struct btrfs_fs_info *fs_info);
int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
blk_mode_t flags, void *holder);
-struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
+struct btrfs_device *btrfs_scan_one_device(const char *path,
bool mount_arg_dev);
int btrfs_forget_devices(dev_t devt);
void btrfs_close_devices(struct btrfs_fs_devices *fs_devices);

--
2.43.0



2024-02-19 20:36:49

by David Sterba

[permalink] [raw]
Subject: Re: [PATCH 1/5] btrfs: always open the device read-only in btrfs_scan_one_device

On Wed, Feb 14, 2024 at 08:42:12AM -0800, Johannes Thumshirn wrote:
> From: Christoph Hellwig <[email protected]>
>
> btrfs_scan_one_device opens the block device only to read the super
> block. Instead of passing a blk_mode_t argument to sometimes open
> it for writing, just hard code BLK_OPEN_READ as it will never write
> to the device or hand the block_device out to someone else.

Opening for write was not meant to be for writing but also to exclude
other attempted writes.

That it's always for read seems OK, this has changed at some point and
is explained in btrfs_scan_one_device():

1356 /*
1357 * Avoid an exclusive open here, as the systemd-udev may initiate the
1358 * device scan which may race with the user's mount or mkfs command,
1359 * resulting in failure.
1360 * Since the device scan is solely for reading purposes, there is no
1361 * need for an exclusive open. Additionally, the devices are read again
1362 * during the mount process. It is ok to get some inconsistent
1363 * values temporarily, as the device paths of the fsid are the only
1364 * required information for assembling the volume.
1365 */
1366 bdev_handle = bdev_open_by_path(path, flags, NULL, NULL);