diff options
author | Alex Elder <elder@inktank.com> | 2012-10-26 00:34:42 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-11-01 08:55:42 -0400 |
commit | c53d589337e9a211413484a604c76072e8474dc0 (patch) | |
tree | bd9718b7d7648e80f64e09d6ee483d262815b340 /drivers/block/rbd.c | |
parent | bd4ba6554dcbae652b8b27a44f5a7795c9f3178a (diff) |
rbd: define rbd_dev_{create,destroy}() helpers
Encapsulate the creation/initialization and destruction of rbd
device structures. The rbd_client and the rbd_spec structures
provided on creation hold references whose ownership is transferred
to the new rbd_device structure.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r-- | drivers/block/rbd.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4771de2fba8a..a8ad8f8370b6 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -504,7 +504,8 @@ static void rbd_client_release(struct kref *kref) | |||
504 | */ | 504 | */ |
505 | static void rbd_put_client(struct rbd_client *rbdc) | 505 | static void rbd_put_client(struct rbd_client *rbdc) |
506 | { | 506 | { |
507 | kref_put(&rbdc->kref, rbd_client_release); | 507 | if (rbdc) |
508 | kref_put(&rbdc->kref, rbd_client_release); | ||
508 | } | 509 | } |
509 | 510 | ||
510 | /* | 511 | /* |
@@ -2166,6 +2167,34 @@ static void rbd_spec_free(struct kref *kref) | |||
2166 | kfree(spec); | 2167 | kfree(spec); |
2167 | } | 2168 | } |
2168 | 2169 | ||
2170 | struct rbd_device *rbd_dev_create(struct rbd_client *rbdc, | ||
2171 | struct rbd_spec *spec) | ||
2172 | { | ||
2173 | struct rbd_device *rbd_dev; | ||
2174 | |||
2175 | rbd_dev = kzalloc(sizeof (*rbd_dev), GFP_KERNEL); | ||
2176 | if (!rbd_dev) | ||
2177 | return NULL; | ||
2178 | |||
2179 | spin_lock_init(&rbd_dev->lock); | ||
2180 | INIT_LIST_HEAD(&rbd_dev->node); | ||
2181 | INIT_LIST_HEAD(&rbd_dev->snaps); | ||
2182 | init_rwsem(&rbd_dev->header_rwsem); | ||
2183 | |||
2184 | rbd_dev->spec = spec; | ||
2185 | rbd_dev->rbd_client = rbdc; | ||
2186 | |||
2187 | return rbd_dev; | ||
2188 | } | ||
2189 | |||
2190 | static void rbd_dev_destroy(struct rbd_device *rbd_dev) | ||
2191 | { | ||
2192 | kfree(rbd_dev->header_name); | ||
2193 | rbd_put_client(rbd_dev->rbd_client); | ||
2194 | rbd_spec_put(rbd_dev->spec); | ||
2195 | kfree(rbd_dev); | ||
2196 | } | ||
2197 | |||
2169 | static bool rbd_snap_registered(struct rbd_snap *snap) | 2198 | static bool rbd_snap_registered(struct rbd_snap *snap) |
2170 | { | 2199 | { |
2171 | bool ret = snap->dev.type == &rbd_snap_device_type; | 2200 | bool ret = snap->dev.type == &rbd_snap_device_type; |
@@ -3242,7 +3271,7 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
3242 | rc = PTR_ERR(rbdc); | 3271 | rc = PTR_ERR(rbdc); |
3243 | goto err_out_args; | 3272 | goto err_out_args; |
3244 | } | 3273 | } |
3245 | ceph_opts = NULL; /* ceph_opts now owned by rbd_dev client */ | 3274 | ceph_opts = NULL; /* rbd_dev client now owns this */ |
3246 | 3275 | ||
3247 | /* pick the pool */ | 3276 | /* pick the pool */ |
3248 | osdc = &rbdc->client->osdc; | 3277 | osdc = &rbdc->client->osdc; |
@@ -3251,22 +3280,19 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
3251 | goto err_out_client; | 3280 | goto err_out_client; |
3252 | spec->pool_id = (u64) rc; | 3281 | spec->pool_id = (u64) rc; |
3253 | 3282 | ||
3254 | rbd_dev = kzalloc(sizeof (*rbd_dev), GFP_KERNEL); | 3283 | rbd_dev = rbd_dev_create(rbdc, spec); |
3255 | if (!rbd_dev) | 3284 | if (!rbd_dev) |
3256 | goto err_out_client; | 3285 | goto err_out_client; |
3257 | 3286 | rbdc = NULL; /* rbd_dev now owns this */ | |
3258 | spin_lock_init(&rbd_dev->lock); | 3287 | spec = NULL; /* rbd_dev now owns this */ |
3259 | INIT_LIST_HEAD(&rbd_dev->node); | ||
3260 | INIT_LIST_HEAD(&rbd_dev->snaps); | ||
3261 | init_rwsem(&rbd_dev->header_rwsem); | ||
3262 | rbd_dev->rbd_client = rbdc; | ||
3263 | rbd_dev->spec = spec; | ||
3264 | 3288 | ||
3265 | rbd_dev->mapping.read_only = rbd_opts->read_only; | 3289 | rbd_dev->mapping.read_only = rbd_opts->read_only; |
3290 | kfree(rbd_opts); | ||
3291 | rbd_opts = NULL; /* done with this */ | ||
3266 | 3292 | ||
3267 | rc = rbd_dev_probe(rbd_dev); | 3293 | rc = rbd_dev_probe(rbd_dev); |
3268 | if (rc < 0) | 3294 | if (rc < 0) |
3269 | goto err_out_mem; | 3295 | goto err_out_rbd_dev; |
3270 | 3296 | ||
3271 | /* no need to lock here, as rbd_dev is not registered yet */ | 3297 | /* no need to lock here, as rbd_dev is not registered yet */ |
3272 | rc = rbd_dev_snaps_update(rbd_dev); | 3298 | rc = rbd_dev_snaps_update(rbd_dev); |
@@ -3317,8 +3343,6 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
3317 | if (rc) | 3343 | if (rc) |
3318 | goto err_out_bus; | 3344 | goto err_out_bus; |
3319 | 3345 | ||
3320 | kfree(rbd_opts); | ||
3321 | |||
3322 | /* Everything's ready. Announce the disk to the world. */ | 3346 | /* Everything's ready. Announce the disk to the world. */ |
3323 | 3347 | ||
3324 | add_disk(rbd_dev->disk); | 3348 | add_disk(rbd_dev->disk); |
@@ -3332,7 +3356,6 @@ err_out_bus: | |||
3332 | /* this will also clean up rest of rbd_dev stuff */ | 3356 | /* this will also clean up rest of rbd_dev stuff */ |
3333 | 3357 | ||
3334 | rbd_bus_del_dev(rbd_dev); | 3358 | rbd_bus_del_dev(rbd_dev); |
3335 | kfree(rbd_opts); | ||
3336 | 3359 | ||
3337 | return rc; | 3360 | return rc; |
3338 | 3361 | ||
@@ -3346,9 +3369,8 @@ err_out_snaps: | |||
3346 | rbd_remove_all_snaps(rbd_dev); | 3369 | rbd_remove_all_snaps(rbd_dev); |
3347 | err_out_probe: | 3370 | err_out_probe: |
3348 | rbd_header_free(&rbd_dev->header); | 3371 | rbd_header_free(&rbd_dev->header); |
3349 | kfree(rbd_dev->header_name); | 3372 | err_out_rbd_dev: |
3350 | err_out_mem: | 3373 | rbd_dev_destroy(rbd_dev); |
3351 | kfree(rbd_dev); | ||
3352 | err_out_client: | 3374 | err_out_client: |
3353 | rbd_put_client(rbdc); | 3375 | rbd_put_client(rbdc); |
3354 | err_out_args: | 3376 | err_out_args: |
@@ -3394,7 +3416,6 @@ static void rbd_dev_release(struct device *dev) | |||
3394 | if (rbd_dev->watch_event) | 3416 | if (rbd_dev->watch_event) |
3395 | rbd_req_sync_unwatch(rbd_dev); | 3417 | rbd_req_sync_unwatch(rbd_dev); |
3396 | 3418 | ||
3397 | rbd_put_client(rbd_dev->rbd_client); | ||
3398 | 3419 | ||
3399 | /* clean up and free blkdev */ | 3420 | /* clean up and free blkdev */ |
3400 | rbd_free_disk(rbd_dev); | 3421 | rbd_free_disk(rbd_dev); |
@@ -3404,10 +3425,9 @@ static void rbd_dev_release(struct device *dev) | |||
3404 | rbd_header_free(&rbd_dev->header); | 3425 | rbd_header_free(&rbd_dev->header); |
3405 | 3426 | ||
3406 | /* done with the id, and with the rbd_dev */ | 3427 | /* done with the id, and with the rbd_dev */ |
3407 | kfree(rbd_dev->header_name); | ||
3408 | rbd_dev_id_put(rbd_dev); | 3428 | rbd_dev_id_put(rbd_dev); |
3409 | rbd_spec_put(rbd_dev->spec); | 3429 | rbd_assert(rbd_dev->rbd_client != NULL); |
3410 | kfree(rbd_dev); | 3430 | rbd_dev_destroy(rbd_dev); |
3411 | 3431 | ||
3412 | /* release module ref */ | 3432 | /* release module ref */ |
3413 | module_put(THIS_MODULE); | 3433 | module_put(THIS_MODULE); |