@@ -418,8 +418,6 @@ MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (d
418
418
419
419
static int rbd_img_request_submit (struct rbd_img_request * img_request );
420
420
421
- static void rbd_dev_device_release (struct device * dev );
422
-
423
421
static ssize_t rbd_add (struct bus_type * bus , const char * buf ,
424
422
size_t count );
425
423
static ssize_t rbd_remove (struct bus_type * bus , const char * buf ,
@@ -3991,14 +3989,12 @@ static const struct attribute_group *rbd_attr_groups[] = {
3991
3989
NULL
3992
3990
};
3993
3991
3994
- static void rbd_sysfs_dev_release (struct device * dev )
3995
- {
3996
- }
3992
+ static void rbd_dev_release (struct device * dev );
3997
3993
3998
3994
static struct device_type rbd_device_type = {
3999
3995
.name = "rbd" ,
4000
3996
.groups = rbd_attr_groups ,
4001
- .release = rbd_sysfs_dev_release ,
3997
+ .release = rbd_dev_release ,
4002
3998
};
4003
3999
4004
4000
static struct rbd_spec * rbd_spec_get (struct rbd_spec * spec )
@@ -4041,6 +4037,25 @@ static void rbd_spec_free(struct kref *kref)
4041
4037
kfree (spec );
4042
4038
}
4043
4039
4040
+ static void rbd_dev_release (struct device * dev )
4041
+ {
4042
+ struct rbd_device * rbd_dev = dev_to_rbd_dev (dev );
4043
+ bool need_put = !!rbd_dev -> opts ;
4044
+
4045
+ rbd_put_client (rbd_dev -> rbd_client );
4046
+ rbd_spec_put (rbd_dev -> spec );
4047
+ kfree (rbd_dev -> opts );
4048
+ kfree (rbd_dev );
4049
+
4050
+ /*
4051
+ * This is racy, but way better than putting module outside of
4052
+ * the release callback. The race window is pretty small, so
4053
+ * doing something similar to dm (dm-builtin.c) is overkill.
4054
+ */
4055
+ if (need_put )
4056
+ module_put (THIS_MODULE );
4057
+ }
4058
+
4044
4059
static struct rbd_device * rbd_dev_create (struct rbd_client * rbdc ,
4045
4060
struct rbd_spec * spec ,
4046
4061
struct rbd_options * opts )
@@ -4057,6 +4072,11 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
4057
4072
INIT_LIST_HEAD (& rbd_dev -> node );
4058
4073
init_rwsem (& rbd_dev -> header_rwsem );
4059
4074
4075
+ rbd_dev -> dev .bus = & rbd_bus_type ;
4076
+ rbd_dev -> dev .type = & rbd_device_type ;
4077
+ rbd_dev -> dev .parent = & rbd_root_dev ;
4078
+ device_initialize (& rbd_dev -> dev );
4079
+
4060
4080
rbd_dev -> rbd_client = rbdc ;
4061
4081
rbd_dev -> spec = spec ;
4062
4082
rbd_dev -> opts = opts ;
@@ -4068,15 +4088,21 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
4068
4088
rbd_dev -> layout .fl_object_size = cpu_to_le32 (1 << RBD_MAX_OBJ_ORDER );
4069
4089
rbd_dev -> layout .fl_pg_pool = cpu_to_le32 ((u32 ) spec -> pool_id );
4070
4090
4091
+ /*
4092
+ * If this is a mapping rbd_dev (as opposed to a parent one),
4093
+ * pin our module. We have a ref from do_rbd_add(), so use
4094
+ * __module_get().
4095
+ */
4096
+ if (rbd_dev -> opts )
4097
+ __module_get (THIS_MODULE );
4098
+
4071
4099
return rbd_dev ;
4072
4100
}
4073
4101
4074
4102
static void rbd_dev_destroy (struct rbd_device * rbd_dev )
4075
4103
{
4076
- rbd_put_client (rbd_dev -> rbd_client );
4077
- rbd_spec_put (rbd_dev -> spec );
4078
- kfree (rbd_dev -> opts );
4079
- kfree (rbd_dev );
4104
+ if (rbd_dev )
4105
+ put_device (& rbd_dev -> dev );
4080
4106
}
4081
4107
4082
4108
/*
@@ -4702,27 +4728,6 @@ static int rbd_dev_header_info(struct rbd_device *rbd_dev)
4702
4728
return rbd_dev_v2_header_info (rbd_dev );
4703
4729
}
4704
4730
4705
- static int rbd_bus_add_dev (struct rbd_device * rbd_dev )
4706
- {
4707
- struct device * dev ;
4708
- int ret ;
4709
-
4710
- dev = & rbd_dev -> dev ;
4711
- dev -> bus = & rbd_bus_type ;
4712
- dev -> type = & rbd_device_type ;
4713
- dev -> parent = & rbd_root_dev ;
4714
- dev -> release = rbd_dev_device_release ;
4715
- dev_set_name (dev , "%d" , rbd_dev -> dev_id );
4716
- ret = device_register (dev );
4717
-
4718
- return ret ;
4719
- }
4720
-
4721
- static void rbd_bus_del_dev (struct rbd_device * rbd_dev )
4722
- {
4723
- device_unregister (& rbd_dev -> dev );
4724
- }
4725
-
4726
4731
/*
4727
4732
* Get a unique rbd identifier for the given new rbd_dev, and add
4728
4733
* the rbd_dev to the global list.
@@ -5225,7 +5230,8 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
5225
5230
set_capacity (rbd_dev -> disk , rbd_dev -> mapping .size / SECTOR_SIZE );
5226
5231
set_disk_ro (rbd_dev -> disk , rbd_dev -> mapping .read_only );
5227
5232
5228
- ret = rbd_bus_add_dev (rbd_dev );
5233
+ dev_set_name (& rbd_dev -> dev , "%d" , rbd_dev -> dev_id );
5234
+ ret = device_add (& rbd_dev -> dev );
5229
5235
if (ret )
5230
5236
goto err_out_mapping ;
5231
5237
@@ -5248,8 +5254,6 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
5248
5254
unregister_blkdev (rbd_dev -> major , rbd_dev -> name );
5249
5255
err_out_id :
5250
5256
rbd_dev_id_put (rbd_dev );
5251
- rbd_dev_mapping_clear (rbd_dev );
5252
-
5253
5257
return ret ;
5254
5258
}
5255
5259
@@ -5397,15 +5401,15 @@ static ssize_t do_rbd_add(struct bus_type *bus,
5397
5401
struct rbd_spec * spec = NULL ;
5398
5402
struct rbd_client * rbdc ;
5399
5403
bool read_only ;
5400
- int rc = - ENOMEM ;
5404
+ int rc ;
5401
5405
5402
5406
if (!try_module_get (THIS_MODULE ))
5403
5407
return - ENODEV ;
5404
5408
5405
5409
/* parse add command */
5406
5410
rc = rbd_add_parse_args (buf , & ceph_opts , & rbd_opts , & spec );
5407
5411
if (rc < 0 )
5408
- goto err_out_module ;
5412
+ goto out ;
5409
5413
5410
5414
rbdc = rbd_get_client (ceph_opts );
5411
5415
if (IS_ERR (rbdc )) {
@@ -5432,8 +5436,10 @@ static ssize_t do_rbd_add(struct bus_type *bus,
5432
5436
}
5433
5437
5434
5438
rbd_dev = rbd_dev_create (rbdc , spec , rbd_opts );
5435
- if (!rbd_dev )
5439
+ if (!rbd_dev ) {
5440
+ rc = - ENOMEM ;
5436
5441
goto err_out_client ;
5442
+ }
5437
5443
rbdc = NULL ; /* rbd_dev now owns this */
5438
5444
spec = NULL ; /* rbd_dev now owns this */
5439
5445
rbd_opts = NULL ; /* rbd_dev now owns this */
@@ -5458,10 +5464,13 @@ static ssize_t do_rbd_add(struct bus_type *bus,
5458
5464
*/
5459
5465
rbd_dev_header_unwatch_sync (rbd_dev );
5460
5466
rbd_dev_image_release (rbd_dev );
5461
- goto err_out_module ;
5467
+ goto out ;
5462
5468
}
5463
5469
5464
- return count ;
5470
+ rc = count ;
5471
+ out :
5472
+ module_put (THIS_MODULE );
5473
+ return rc ;
5465
5474
5466
5475
err_out_rbd_dev :
5467
5476
rbd_dev_destroy (rbd_dev );
@@ -5470,12 +5479,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
5470
5479
err_out_args :
5471
5480
rbd_spec_put (spec );
5472
5481
kfree (rbd_opts );
5473
- err_out_module :
5474
- module_put (THIS_MODULE );
5475
-
5476
- dout ("Error adding device %s\n" , buf );
5477
-
5478
- return (ssize_t )rc ;
5482
+ goto out ;
5479
5483
}
5480
5484
5481
5485
static ssize_t rbd_add (struct bus_type * bus ,
@@ -5495,17 +5499,15 @@ static ssize_t rbd_add_single_major(struct bus_type *bus,
5495
5499
return do_rbd_add (bus , buf , count );
5496
5500
}
5497
5501
5498
- static void rbd_dev_device_release (struct device * dev )
5502
+ static void rbd_dev_device_release (struct rbd_device * rbd_dev )
5499
5503
{
5500
- struct rbd_device * rbd_dev = dev_to_rbd_dev (dev );
5501
-
5502
5504
rbd_free_disk (rbd_dev );
5503
5505
clear_bit (RBD_DEV_FLAG_EXISTS , & rbd_dev -> flags );
5506
+ device_del (& rbd_dev -> dev );
5504
5507
rbd_dev_mapping_clear (rbd_dev );
5505
5508
if (!single_major )
5506
5509
unregister_blkdev (rbd_dev -> major , rbd_dev -> name );
5507
5510
rbd_dev_id_put (rbd_dev );
5508
- rbd_dev_mapping_clear (rbd_dev );
5509
5511
}
5510
5512
5511
5513
static void rbd_dev_remove_parent (struct rbd_device * rbd_dev )
@@ -5590,9 +5592,8 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
5590
5592
* rbd_bus_del_dev() will race with rbd_watch_cb(), resulting
5591
5593
* in a potential use after free of rbd_dev->disk or rbd_dev.
5592
5594
*/
5593
- rbd_bus_del_dev (rbd_dev );
5595
+ rbd_dev_device_release (rbd_dev );
5594
5596
rbd_dev_image_release (rbd_dev );
5595
- module_put (THIS_MODULE );
5596
5597
5597
5598
return count ;
5598
5599
}
@@ -5663,10 +5664,8 @@ static int rbd_slab_init(void)
5663
5664
if (rbd_segment_name_cache )
5664
5665
return 0 ;
5665
5666
out_err :
5666
- if (rbd_obj_request_cache ) {
5667
- kmem_cache_destroy (rbd_obj_request_cache );
5668
- rbd_obj_request_cache = NULL ;
5669
- }
5667
+ kmem_cache_destroy (rbd_obj_request_cache );
5668
+ rbd_obj_request_cache = NULL ;
5670
5669
5671
5670
kmem_cache_destroy (rbd_img_request_cache );
5672
5671
rbd_img_request_cache = NULL ;
0 commit comments