Skip to content

Commit faa775c

Browse files
josefbacikkdave
authored andcommitted
btrfs: add a btrfs_get_dev_args_from_path helper
We are going to want to populate our device lookup args outside of any locks and then do the actual device lookup later, so add a helper to do this work and make btrfs_find_device_by_devspec() use this helper for now. Reviewed-by: Nikolay Borisov <[email protected]> Reviewed-by: Anand Jain <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 562d7b1 commit faa775c

File tree

2 files changed

+68
-32
lines changed

2 files changed

+68
-32
lines changed

fs/btrfs/volumes.c

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,45 +2325,81 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
23252325
btrfs_free_device(tgtdev);
23262326
}
23272327

2328-
static struct btrfs_device *btrfs_find_device_by_path(
2329-
struct btrfs_fs_info *fs_info, const char *device_path)
2328+
/**
2329+
* Populate args from device at path
2330+
*
2331+
* @fs_info: the filesystem
2332+
* @args: the args to populate
2333+
* @path: the path to the device
2334+
*
2335+
* This will read the super block of the device at @path and populate @args with
2336+
* the devid, fsid, and uuid. This is meant to be used for ioctls that need to
2337+
* lookup a device to operate on, but need to do it before we take any locks.
2338+
* This properly handles the special case of "missing" that a user may pass in,
2339+
* and does some basic sanity checks. The caller must make sure that @path is
2340+
* properly NUL terminated before calling in, and must call
2341+
* btrfs_put_dev_args_from_path() in order to free up the temporary fsid and
2342+
* uuid buffers.
2343+
*
2344+
* Return: 0 for success, -errno for failure
2345+
*/
2346+
int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
2347+
struct btrfs_dev_lookup_args *args,
2348+
const char *path)
23302349
{
2331-
BTRFS_DEV_LOOKUP_ARGS(args);
2332-
int ret = 0;
23332350
struct btrfs_super_block *disk_super;
23342351
struct block_device *bdev;
2335-
struct btrfs_device *device;
2352+
int ret;
23362353

2337-
ret = btrfs_get_bdev_and_sb(device_path, FMODE_READ,
2338-
fs_info->bdev_holder, 0, &bdev, &disk_super);
2339-
if (ret)
2340-
return ERR_PTR(ret);
2354+
if (!path || !path[0])
2355+
return -EINVAL;
2356+
if (!strcmp(path, "missing")) {
2357+
args->missing = true;
2358+
return 0;
2359+
}
2360+
2361+
args->uuid = kzalloc(BTRFS_UUID_SIZE, GFP_KERNEL);
2362+
args->fsid = kzalloc(BTRFS_FSID_SIZE, GFP_KERNEL);
2363+
if (!args->uuid || !args->fsid) {
2364+
btrfs_put_dev_args_from_path(args);
2365+
return -ENOMEM;
2366+
}
23412367

2342-
args.devid = btrfs_stack_device_id(&disk_super->dev_item);
2343-
args.uuid = disk_super->dev_item.uuid;
2368+
ret = btrfs_get_bdev_and_sb(path, FMODE_READ, fs_info->bdev_holder, 0,
2369+
&bdev, &disk_super);
2370+
if (ret)
2371+
return ret;
2372+
args->devid = btrfs_stack_device_id(&disk_super->dev_item);
2373+
memcpy(args->uuid, disk_super->dev_item.uuid, BTRFS_UUID_SIZE);
23442374
if (btrfs_fs_incompat(fs_info, METADATA_UUID))
2345-
args.fsid = disk_super->metadata_uuid;
2375+
memcpy(args->fsid, disk_super->metadata_uuid, BTRFS_FSID_SIZE);
23462376
else
2347-
args.fsid = disk_super->fsid;
2348-
2349-
device = btrfs_find_device(fs_info->fs_devices, &args);
2350-
2377+
memcpy(args->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
23512378
btrfs_release_disk_super(disk_super);
2352-
if (!device)
2353-
device = ERR_PTR(-ENOENT);
23542379
blkdev_put(bdev, FMODE_READ);
2355-
return device;
2380+
return 0;
23562381
}
23572382

23582383
/*
2359-
* Lookup a device given by device id, or the path if the id is 0.
2384+
* Only use this jointly with btrfs_get_dev_args_from_path() because we will
2385+
* allocate our ->uuid and ->fsid pointers, everybody else uses local variables
2386+
* that don't need to be freed.
23602387
*/
2388+
void btrfs_put_dev_args_from_path(struct btrfs_dev_lookup_args *args)
2389+
{
2390+
kfree(args->uuid);
2391+
kfree(args->fsid);
2392+
args->uuid = NULL;
2393+
args->fsid = NULL;
2394+
}
2395+
23612396
struct btrfs_device *btrfs_find_device_by_devspec(
23622397
struct btrfs_fs_info *fs_info, u64 devid,
23632398
const char *device_path)
23642399
{
23652400
BTRFS_DEV_LOOKUP_ARGS(args);
23662401
struct btrfs_device *device;
2402+
int ret;
23672403

23682404
if (devid) {
23692405
args.devid = devid;
@@ -2373,18 +2409,14 @@ struct btrfs_device *btrfs_find_device_by_devspec(
23732409
return device;
23742410
}
23752411

2376-
if (!device_path || !device_path[0])
2377-
return ERR_PTR(-EINVAL);
2378-
2379-
if (strcmp(device_path, "missing") == 0) {
2380-
args.missing = true;
2381-
device = btrfs_find_device(fs_info->fs_devices, &args);
2382-
if (!device)
2383-
return ERR_PTR(-ENOENT);
2384-
return device;
2385-
}
2386-
2387-
return btrfs_find_device_by_path(fs_info, device_path);
2412+
ret = btrfs_get_dev_args_from_path(fs_info, &args, device_path);
2413+
if (ret)
2414+
return ERR_PTR(ret);
2415+
device = btrfs_find_device(fs_info->fs_devices, &args);
2416+
btrfs_put_dev_args_from_path(&args);
2417+
if (!device)
2418+
return ERR_PTR(-ENOENT);
2419+
return device;
23882420
}
23892421

23902422
/*

fs/btrfs/volumes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,9 +520,13 @@ void btrfs_assign_next_active_device(struct btrfs_device *device,
520520
struct btrfs_device *btrfs_find_device_by_devspec(struct btrfs_fs_info *fs_info,
521521
u64 devid,
522522
const char *devpath);
523+
int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
524+
struct btrfs_dev_lookup_args *args,
525+
const char *path);
523526
struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
524527
const u64 *devid,
525528
const u8 *uuid);
529+
void btrfs_put_dev_args_from_path(struct btrfs_dev_lookup_args *args);
526530
void btrfs_free_device(struct btrfs_device *device);
527531
int btrfs_rm_device(struct btrfs_fs_info *fs_info,
528532
const char *device_path, u64 devid,

0 commit comments

Comments
 (0)