Commit 4889bc05 authored by Anand Jain's avatar Anand Jain Committed by David Sterba

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: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 16cab91a
...@@ -303,6 +303,9 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, ...@@ -303,6 +303,9 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
goto error; goto error;
} }
rcu_assign_pointer(device->name, name); 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); set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
device->generation = 0; device->generation = 0;
......
...@@ -808,11 +808,17 @@ static noinline struct btrfs_device *device_list_add(const char *path, ...@@ -808,11 +808,17 @@ static noinline struct btrfs_device *device_list_add(const char *path,
struct rcu_string *name; struct rcu_string *name;
u64 found_transid = btrfs_super_generation(disk_super); u64 found_transid = btrfs_super_generation(disk_super);
u64 devid = btrfs_stack_device_id(&disk_super->dev_item); 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) & bool has_metadata_uuid = (btrfs_super_incompat_flags(disk_super) &
BTRFS_FEATURE_INCOMPAT_METADATA_UUID); BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
bool fsid_change_in_progress = (btrfs_super_flags(disk_super) & bool fsid_change_in_progress = (btrfs_super_flags(disk_super) &
BTRFS_SUPER_FLAG_CHANGING_FSID_V2); BTRFS_SUPER_FLAG_CHANGING_FSID_V2);
error = lookup_bdev(path, &path_devt);
if (error)
return ERR_PTR(error);
if (fsid_change_in_progress) { if (fsid_change_in_progress) {
if (!has_metadata_uuid) if (!has_metadata_uuid)
fs_devices = find_fsid_inprogress(disk_super); fs_devices = find_fsid_inprogress(disk_super);
...@@ -895,6 +901,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, ...@@ -895,6 +901,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
rcu_assign_pointer(device->name, name); rcu_assign_pointer(device->name, name);
device->devt = path_devt;
list_add_rcu(&device->dev_list, &fs_devices->devices); list_add_rcu(&device->dev_list, &fs_devices->devices);
fs_devices->num_devices++; fs_devices->num_devices++;
...@@ -957,16 +964,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, ...@@ -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 * make sure it's the same device if the device is mounted
*/ */
if (device->bdev) { if (device->bdev) {
int error; if (device->devt != path_devt) {
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) {
mutex_unlock(&fs_devices->device_list_mutex); mutex_unlock(&fs_devices->device_list_mutex);
/* /*
* device->fs_info may not be reliable here, so * device->fs_info may not be reliable here, so
...@@ -999,6 +997,7 @@ static noinline struct btrfs_device *device_list_add(const char *path, ...@@ -999,6 +997,7 @@ static noinline struct btrfs_device *device_list_add(const char *path,
fs_devices->missing_devices--; fs_devices->missing_devices--;
clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); 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, ...@@ -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); device = device_list_add(path, disk_super, &new_device_added);
if (!IS_ERR(device) && new_device_added) { if (!IS_ERR(device) && new_device_added)
dev_t devt; btrfs_free_stale_devices(device->devt, device);
/*
* 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);
}
btrfs_release_disk_super(disk_super); 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 ...@@ -2652,7 +2643,6 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
int ret = 0; int ret = 0;
bool seeding_dev = false; bool seeding_dev = false;
bool locked = false; bool locked = false;
dev_t devt;
if (sb_rdonly(sb) && !fs_devices->seeding) if (sb_rdonly(sb) && !fs_devices->seeding)
return -EROFS; return -EROFS;
...@@ -2702,6 +2692,9 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path ...@@ -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->fs_info = fs_info;
device->bdev = bdev; device->bdev = bdev;
ret = lookup_bdev(device_path, &device->devt);
if (ret)
goto error_free_device;
ret = btrfs_get_dev_zone_info(device, false); ret = btrfs_get_dev_zone_info(device, false);
if (ret) if (ret)
...@@ -2845,13 +2838,10 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path ...@@ -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 * 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 * other fs_devices list if device_path alienates any other scanned
* device. * 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 * We can ignore the return value as it typically returns -EINVAL and
* only succeeds if the device was an alien. * only succeeds if the device was an alien.
*/ */
if (lookup_bdev(device_path, &devt) == 0) btrfs_forget_devices(device->devt);
btrfs_forget_devices(devt);
/* Update ctime/mtime for blkid or udev */ /* Update ctime/mtime for blkid or udev */
update_dev_time(device_path); update_dev_time(device_path);
......
...@@ -72,6 +72,11 @@ struct btrfs_device { ...@@ -72,6 +72,11 @@ struct btrfs_device {
/* the mode sent to blkdev_get */ /* the mode sent to blkdev_get */
fmode_t mode; 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; unsigned long dev_state;
blk_status_t last_flush_error; blk_status_t last_flush_error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment