@@ -2325,45 +2325,81 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
2325
2325
btrfs_free_device (tgtdev );
2326
2326
}
2327
2327
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 )
2330
2349
{
2331
- BTRFS_DEV_LOOKUP_ARGS (args );
2332
- int ret = 0 ;
2333
2350
struct btrfs_super_block * disk_super ;
2334
2351
struct block_device * bdev ;
2335
- struct btrfs_device * device ;
2352
+ int ret ;
2336
2353
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
+ }
2341
2367
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 );
2344
2374
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 ) ;
2346
2376
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 );
2351
2378
btrfs_release_disk_super (disk_super );
2352
- if (!device )
2353
- device = ERR_PTR (- ENOENT );
2354
2379
blkdev_put (bdev , FMODE_READ );
2355
- return device ;
2380
+ return 0 ;
2356
2381
}
2357
2382
2358
2383
/*
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.
2360
2387
*/
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
+
2361
2396
struct btrfs_device * btrfs_find_device_by_devspec (
2362
2397
struct btrfs_fs_info * fs_info , u64 devid ,
2363
2398
const char * device_path )
2364
2399
{
2365
2400
BTRFS_DEV_LOOKUP_ARGS (args );
2366
2401
struct btrfs_device * device ;
2402
+ int ret ;
2367
2403
2368
2404
if (devid ) {
2369
2405
args .devid = devid ;
@@ -2373,18 +2409,14 @@ struct btrfs_device *btrfs_find_device_by_devspec(
2373
2409
return device ;
2374
2410
}
2375
2411
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 ;
2388
2420
}
2389
2421
2390
2422
/*
0 commit comments