diff options
author | Anand Jain <anand.jain@oracle.com> | 2022-01-12 06:06:01 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2022-03-14 13:13:47 +0100 |
commit | 4889bc05a96e039b055bbd11438c40bf956f057b (patch) | |
tree | 161cbf1dca6d039fb8528da67d395e93adbd43ca | |
parent | btrfs: match stale devices by dev_t (diff) | |
download | linux-4889bc05a96e039b055bbd11438c40bf956f057b.tar.xz linux-4889bc05a96e039b055bbd11438c40bf956f057b.zip |
btrfs: add device major-minor info in the struct btrfs_device
Internally it is common to use the major-minor number to identify a
device and, at a few locations in btrfs, we use the major-minor number
to match the device.
So when we identify a new btrfs device through device add or device
replace or device-scan/ready save the device's major-minor (dev_t) in the
struct btrfs_device so that we don't have to call lookup_bdev() again.
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | fs/btrfs/dev-replace.c | 3 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 40 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 5 |
3 files changed, 23 insertions, 25 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 1bd1bcee95c9..71fd99b48283 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -303,6 +303,9 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, goto error; } rcu_assign_pointer(device->name, name); + ret = lookup_bdev(device_path, &device->devt); + if (ret) + goto error; set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); device->generation = 0; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b47dd1387766..ebe655eb8b4d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -808,11 +808,17 @@ static noinline struct btrfs_device *device_list_add(const char *path, struct rcu_string *name; u64 found_transid = btrfs_super_generation(disk_super); u64 devid = btrfs_stack_device_id(&disk_super->dev_item); + dev_t path_devt; + int error; bool has_metadata_uuid = (btrfs_super_incompat_flags(disk_super) & BTRFS_FEATURE_INCOMPAT_METADATA_UUID); bool fsid_change_in_progress = (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_CHANGING_FSID_V2); + error = lookup_bdev(path, &path_devt); + if (error) + return ERR_PTR(error); + if (fsid_change_in_progress) { if (!has_metadata_uuid) fs_devices = find_fsid_inprogress(disk_super); @@ -895,6 +901,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, return ERR_PTR(-ENOMEM); } rcu_assign_pointer(device->name, name); + device->devt = path_devt; list_add_rcu(&device->dev_list, &fs_devices->devices); fs_devices->num_devices++; @@ -957,16 +964,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, * make sure it's the same device if the device is mounted */ if (device->bdev) { - int error; - dev_t path_dev; - - error = lookup_bdev(path, &path_dev); - if (error) { - mutex_unlock(&fs_devices->device_list_mutex); - return ERR_PTR(error); - } - - if (device->bdev->bd_dev != path_dev) { + if (device->devt != path_devt) { mutex_unlock(&fs_devices->device_list_mutex); /* * device->fs_info may not be reliable here, so @@ -999,6 +997,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, fs_devices->missing_devices--; clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); } + device->devt = path_devt; } /* @@ -1412,16 +1411,8 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags, } device = device_list_add(path, disk_super, &new_device_added); - if (!IS_ERR(device) && new_device_added) { - dev_t devt; - - /* - * It is ok to ignore if we fail to free the stale device (if - * any). As there is nothing much that can be done about it. - */ - if (lookup_bdev(path, &devt) == 0) - btrfs_free_stale_devices(devt, device); - } + if (!IS_ERR(device) && new_device_added) + btrfs_free_stale_devices(device->devt, device); btrfs_release_disk_super(disk_super); @@ -2652,7 +2643,6 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path int ret = 0; bool seeding_dev = false; bool locked = false; - dev_t devt; if (sb_rdonly(sb) && !fs_devices->seeding) return -EROFS; @@ -2702,6 +2692,9 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path device->fs_info = fs_info; device->bdev = bdev; + ret = lookup_bdev(device_path, &device->devt); + if (ret) + goto error_free_device; ret = btrfs_get_dev_zone_info(device, false); if (ret) @@ -2845,13 +2838,10 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path * Now that we have written a new super block to this device, check all * other fs_devices list if device_path alienates any other scanned * device. - * Skip forget_deivces if lookup_bdev() fails as there is nothing much - * that can be done about it. * We can ignore the return value as it typically returns -EINVAL and * only succeeds if the device was an alien. */ - if (lookup_bdev(device_path, &devt) == 0) - btrfs_forget_devices(devt); + btrfs_forget_devices(device->devt); /* Update ctime/mtime for blkid or udev */ update_dev_time(device_path); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 38b898bc5f0e..bd297f23d19e 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -72,6 +72,11 @@ struct btrfs_device { /* the mode sent to blkdev_get */ fmode_t mode; + /* + * Device's major-minor number. Must be set even if the device is not + * opened (bdev == NULL), unless the device is missing. + */ + dev_t devt; unsigned long dev_state; blk_status_t last_flush_error; |