@@ -2361,45 +2361,81 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
23612361 btrfs_free_device (tgtdev );
23622362}
23632363
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 )
23662385{
2367- BTRFS_DEV_LOOKUP_ARGS (args );
2368- int ret = 0 ;
23692386 struct btrfs_super_block * disk_super ;
23702387 struct block_device * bdev ;
2371- struct btrfs_device * device ;
2388+ int ret ;
23722389
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+ }
23772403
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 );
23802410 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 ) ;
23822412 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 );
23872414 btrfs_release_disk_super (disk_super );
2388- if (!device )
2389- device = ERR_PTR (- ENOENT );
23902415 blkdev_put (bdev , FMODE_READ );
2391- return device ;
2416+ return 0 ;
23922417}
23932418
23942419/*
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.
23962423 */
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+
23972432struct btrfs_device * btrfs_find_device_by_devspec (
23982433 struct btrfs_fs_info * fs_info , u64 devid ,
23992434 const char * device_path )
24002435{
24012436 BTRFS_DEV_LOOKUP_ARGS (args );
24022437 struct btrfs_device * device ;
2438+ int ret ;
24032439
24042440 if (devid ) {
24052441 args .devid = devid ;
@@ -2409,18 +2445,14 @@ struct btrfs_device *btrfs_find_device_by_devspec(
24092445 return device ;
24102446 }
24112447
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 ;
24242456}
24252457
24262458/*
0 commit comments