@@ -2361,45 +2361,81 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
2361
2361
btrfs_free_device (tgtdev );
2362
2362
}
2363
2363
2364
- static struct btrfs_device * btrfs_find_device_by_path (
2365
- struct btrfs_fs_info * fs_info , const char * device_path )
2364
+ /**
2365
+ * Populate args from device at path
2366
+ *
2367
+ * @fs_info: the filesystem
2368
+ * @args: the args to populate
2369
+ * @path: the path to the device
2370
+ *
2371
+ * This will read the super block of the device at @path and populate @args with
2372
+ * the devid, fsid, and uuid. This is meant to be used for ioctls that need to
2373
+ * lookup a device to operate on, but need to do it before we take any locks.
2374
+ * This properly handles the special case of "missing" that a user may pass in,
2375
+ * and does some basic sanity checks. The caller must make sure that @path is
2376
+ * properly NUL terminated before calling in, and must call
2377
+ * btrfs_put_dev_args_from_path() in order to free up the temporary fsid and
2378
+ * uuid buffers.
2379
+ *
2380
+ * Return: 0 for success, -errno for failure
2381
+ */
2382
+ int btrfs_get_dev_args_from_path (struct btrfs_fs_info * fs_info ,
2383
+ struct btrfs_dev_lookup_args * args ,
2384
+ const char * path )
2366
2385
{
2367
- BTRFS_DEV_LOOKUP_ARGS (args );
2368
- int ret = 0 ;
2369
2386
struct btrfs_super_block * disk_super ;
2370
2387
struct block_device * bdev ;
2371
- struct btrfs_device * device ;
2388
+ int ret ;
2372
2389
2373
- ret = btrfs_get_bdev_and_sb (device_path , FMODE_READ ,
2374
- fs_info -> bdev_holder , 0 , & bdev , & disk_super );
2375
- if (ret )
2376
- return ERR_PTR (ret );
2390
+ if (!path || !path [0 ])
2391
+ return - EINVAL ;
2392
+ if (!strcmp (path , "missing" )) {
2393
+ args -> missing = true;
2394
+ return 0 ;
2395
+ }
2396
+
2397
+ args -> uuid = kzalloc (BTRFS_UUID_SIZE , GFP_KERNEL );
2398
+ args -> fsid = kzalloc (BTRFS_FSID_SIZE , GFP_KERNEL );
2399
+ if (!args -> uuid || !args -> fsid ) {
2400
+ btrfs_put_dev_args_from_path (args );
2401
+ return - ENOMEM ;
2402
+ }
2377
2403
2378
- args .devid = btrfs_stack_device_id (& disk_super -> dev_item );
2379
- args .uuid = disk_super -> dev_item .uuid ;
2404
+ ret = btrfs_get_bdev_and_sb (path , FMODE_READ , fs_info -> bdev_holder , 0 ,
2405
+ & bdev , & disk_super );
2406
+ if (ret )
2407
+ return ret ;
2408
+ args -> devid = btrfs_stack_device_id (& disk_super -> dev_item );
2409
+ memcpy (args -> uuid , disk_super -> dev_item .uuid , BTRFS_UUID_SIZE );
2380
2410
if (btrfs_fs_incompat (fs_info , METADATA_UUID ))
2381
- args . fsid = disk_super -> metadata_uuid ;
2411
+ memcpy ( args -> fsid , disk_super -> metadata_uuid , BTRFS_FSID_SIZE ) ;
2382
2412
else
2383
- args .fsid = disk_super -> fsid ;
2384
-
2385
- device = btrfs_find_device (fs_info -> fs_devices , & args );
2386
-
2413
+ memcpy (args -> fsid , disk_super -> fsid , BTRFS_FSID_SIZE );
2387
2414
btrfs_release_disk_super (disk_super );
2388
- if (!device )
2389
- device = ERR_PTR (- ENOENT );
2390
2415
blkdev_put (bdev , FMODE_READ );
2391
- return device ;
2416
+ return 0 ;
2392
2417
}
2393
2418
2394
2419
/*
2395
- * Lookup a device given by device id, or the path if the id is 0.
2420
+ * Only use this jointly with btrfs_get_dev_args_from_path() because we will
2421
+ * allocate our ->uuid and ->fsid pointers, everybody else uses local variables
2422
+ * that don't need to be freed.
2396
2423
*/
2424
+ void btrfs_put_dev_args_from_path (struct btrfs_dev_lookup_args * args )
2425
+ {
2426
+ kfree (args -> uuid );
2427
+ kfree (args -> fsid );
2428
+ args -> uuid = NULL ;
2429
+ args -> fsid = NULL ;
2430
+ }
2431
+
2397
2432
struct btrfs_device * btrfs_find_device_by_devspec (
2398
2433
struct btrfs_fs_info * fs_info , u64 devid ,
2399
2434
const char * device_path )
2400
2435
{
2401
2436
BTRFS_DEV_LOOKUP_ARGS (args );
2402
2437
struct btrfs_device * device ;
2438
+ int ret ;
2403
2439
2404
2440
if (devid ) {
2405
2441
args .devid = devid ;
@@ -2409,18 +2445,14 @@ struct btrfs_device *btrfs_find_device_by_devspec(
2409
2445
return device ;
2410
2446
}
2411
2447
2412
- if (!device_path || !device_path [0 ])
2413
- return ERR_PTR (- EINVAL );
2414
-
2415
- if (strcmp (device_path , "missing" ) == 0 ) {
2416
- args .missing = true;
2417
- device = btrfs_find_device (fs_info -> fs_devices , & args );
2418
- if (!device )
2419
- return ERR_PTR (- ENOENT );
2420
- return device ;
2421
- }
2422
-
2423
- return btrfs_find_device_by_path (fs_info , device_path );
2448
+ ret = btrfs_get_dev_args_from_path (fs_info , & args , device_path );
2449
+ if (ret )
2450
+ return ERR_PTR (ret );
2451
+ device = btrfs_find_device (fs_info -> fs_devices , & args );
2452
+ btrfs_put_dev_args_from_path (& args );
2453
+ if (!device )
2454
+ return ERR_PTR (- ENOENT );
2455
+ return device ;
2424
2456
}
2425
2457
2426
2458
/*
0 commit comments