@@ -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+
23612396struct 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/*
0 commit comments