diff options
author | Alex Elder <elder@inktank.com> | 2012-10-26 18:25:24 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-11-01 08:55:41 -0400 |
commit | 8b8fb99c5c93a0bdfe7b0c0c9fd2d41a3244555e (patch) | |
tree | 2d94f2e8a322f80c4f1a3e98d353c8c13f6dd082 | |
parent | 0d7dbfce9d6e3a57a6946fadf7f92b1792b8acc0 (diff) |
rbd: add reference counting to rbd_spec
With layered images we'll share rbd_spec structures, so add a
reference count to it. It neatens up some code also.
A silly get/put pair is added to the alloc routine just to avoid
"defined but not used" warnings. It will go away soon.
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r-- | drivers/block/rbd.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 2049810fcdc2..86206a75017d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -2134,6 +2134,45 @@ static struct device_type rbd_snap_device_type = { | |||
2134 | .release = rbd_snap_dev_release, | 2134 | .release = rbd_snap_dev_release, |
2135 | }; | 2135 | }; |
2136 | 2136 | ||
2137 | static struct rbd_spec *rbd_spec_get(struct rbd_spec *spec) | ||
2138 | { | ||
2139 | kref_get(&spec->kref); | ||
2140 | |||
2141 | return spec; | ||
2142 | } | ||
2143 | |||
2144 | static void rbd_spec_free(struct kref *kref); | ||
2145 | static void rbd_spec_put(struct rbd_spec *spec) | ||
2146 | { | ||
2147 | if (spec) | ||
2148 | kref_put(&spec->kref, rbd_spec_free); | ||
2149 | } | ||
2150 | |||
2151 | static struct rbd_spec *rbd_spec_alloc(void) | ||
2152 | { | ||
2153 | struct rbd_spec *spec; | ||
2154 | |||
2155 | spec = kzalloc(sizeof (*spec), GFP_KERNEL); | ||
2156 | if (!spec) | ||
2157 | return NULL; | ||
2158 | kref_init(&spec->kref); | ||
2159 | |||
2160 | rbd_spec_put(rbd_spec_get(spec)); /* TEMPORARY */ | ||
2161 | |||
2162 | return spec; | ||
2163 | } | ||
2164 | |||
2165 | static void rbd_spec_free(struct kref *kref) | ||
2166 | { | ||
2167 | struct rbd_spec *spec = container_of(kref, struct rbd_spec, kref); | ||
2168 | |||
2169 | kfree(spec->pool_name); | ||
2170 | kfree(spec->image_id); | ||
2171 | kfree(spec->image_name); | ||
2172 | kfree(spec->snap_name); | ||
2173 | kfree(spec); | ||
2174 | } | ||
2175 | |||
2137 | static bool rbd_snap_registered(struct rbd_snap *snap) | 2176 | static bool rbd_snap_registered(struct rbd_snap *snap) |
2138 | { | 2177 | { |
2139 | bool ret = snap->dev.type == &rbd_snap_device_type; | 2178 | bool ret = snap->dev.type == &rbd_snap_device_type; |
@@ -3165,7 +3204,7 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
3165 | rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL); | 3204 | rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL); |
3166 | if (!rbd_dev) | 3205 | if (!rbd_dev) |
3167 | return -ENOMEM; | 3206 | return -ENOMEM; |
3168 | rbd_dev->spec = kzalloc(sizeof (*rbd_dev->spec), GFP_KERNEL); | 3207 | rbd_dev->spec = rbd_spec_alloc(); |
3169 | if (!rbd_dev->spec) | 3208 | if (!rbd_dev->spec) |
3170 | goto err_out_mem; | 3209 | goto err_out_mem; |
3171 | 3210 | ||
@@ -3278,16 +3317,12 @@ err_out_probe: | |||
3278 | err_out_client: | 3317 | err_out_client: |
3279 | kfree(rbd_dev->header_name); | 3318 | kfree(rbd_dev->header_name); |
3280 | rbd_put_client(rbd_dev); | 3319 | rbd_put_client(rbd_dev); |
3281 | kfree(rbd_dev->spec->image_id); | ||
3282 | err_out_args: | 3320 | err_out_args: |
3283 | if (ceph_opts) | 3321 | if (ceph_opts) |
3284 | ceph_destroy_options(ceph_opts); | 3322 | ceph_destroy_options(ceph_opts); |
3285 | kfree(rbd_dev->spec->snap_name); | ||
3286 | kfree(rbd_dev->spec->image_name); | ||
3287 | kfree(rbd_dev->spec->pool_name); | ||
3288 | kfree(rbd_opts); | 3323 | kfree(rbd_opts); |
3289 | err_out_mem: | 3324 | err_out_mem: |
3290 | kfree(rbd_dev->spec); | 3325 | rbd_spec_put(rbd_dev->spec); |
3291 | kfree(rbd_dev); | 3326 | kfree(rbd_dev); |
3292 | 3327 | ||
3293 | dout("Error adding device %s\n", buf); | 3328 | dout("Error adding device %s\n", buf); |
@@ -3336,12 +3371,9 @@ static void rbd_dev_release(struct device *dev) | |||
3336 | rbd_header_free(&rbd_dev->header); | 3371 | rbd_header_free(&rbd_dev->header); |
3337 | 3372 | ||
3338 | /* done with the id, and with the rbd_dev */ | 3373 | /* done with the id, and with the rbd_dev */ |
3339 | kfree(rbd_dev->spec->snap_name); | ||
3340 | kfree(rbd_dev->spec->image_id); | ||
3341 | kfree(rbd_dev->header_name); | 3374 | kfree(rbd_dev->header_name); |
3342 | kfree(rbd_dev->spec->pool_name); | ||
3343 | kfree(rbd_dev->spec->image_name); | ||
3344 | rbd_dev_id_put(rbd_dev); | 3375 | rbd_dev_id_put(rbd_dev); |
3376 | rbd_spec_put(rbd_dev->spec); | ||
3345 | kfree(rbd_dev); | 3377 | kfree(rbd_dev); |
3346 | 3378 | ||
3347 | /* release module ref */ | 3379 | /* release module ref */ |