diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-03-17 23:08:28 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-04-22 15:26:22 -0400 |
commit | d29cee120eb890027c69f5fe7cce8bd6a663900a (patch) | |
tree | d427aa25124dc9a83002432d92d8063874c7b5a8 | |
parent | e32bc729a3a486e20443db3379ecf67240b20616 (diff) |
libnvdimm, blk: use devm_add_action to release bdev resources
Register a callback to clean up the request_queue and put the gendisk at
driver disable time.
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/nvdimm/blk.c | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index c8215dc356cc..27ff32a5e9cf 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include "nd.h" | 22 | #include "nd.h" |
23 | 23 | ||
24 | struct nd_blk_device { | 24 | struct nd_blk_device { |
25 | struct request_queue *queue; | ||
26 | struct gendisk *disk; | ||
27 | struct nd_namespace_blk *nsblk; | 25 | struct nd_namespace_blk *nsblk; |
28 | struct nd_blk_region *ndbr; | 26 | struct nd_blk_region *ndbr; |
29 | size_t disk_size; | 27 | size_t disk_size; |
@@ -235,29 +233,47 @@ static const struct block_device_operations nd_blk_fops = { | |||
235 | .revalidate_disk = nvdimm_revalidate_disk, | 233 | .revalidate_disk = nvdimm_revalidate_disk, |
236 | }; | 234 | }; |
237 | 235 | ||
238 | static int nd_blk_attach_disk(struct nd_namespace_common *ndns, | 236 | static void nd_blk_release_queue(void *q) |
239 | struct nd_blk_device *blk_dev) | 237 | { |
238 | blk_cleanup_queue(q); | ||
239 | } | ||
240 | |||
241 | static void nd_blk_release_disk(void *disk) | ||
242 | { | ||
243 | del_gendisk(disk); | ||
244 | put_disk(disk); | ||
245 | } | ||
246 | |||
247 | static int nd_blk_attach_disk(struct device *dev, | ||
248 | struct nd_namespace_common *ndns, struct nd_blk_device *blk_dev) | ||
240 | { | 249 | { |
241 | resource_size_t available_disk_size; | 250 | resource_size_t available_disk_size; |
251 | struct request_queue *q; | ||
242 | struct gendisk *disk; | 252 | struct gendisk *disk; |
243 | u64 internal_nlba; | 253 | u64 internal_nlba; |
244 | 254 | ||
245 | internal_nlba = div_u64(blk_dev->disk_size, blk_dev->internal_lbasize); | 255 | internal_nlba = div_u64(blk_dev->disk_size, blk_dev->internal_lbasize); |
246 | available_disk_size = internal_nlba * blk_dev->sector_size; | 256 | available_disk_size = internal_nlba * blk_dev->sector_size; |
247 | 257 | ||
248 | blk_dev->queue = blk_alloc_queue(GFP_KERNEL); | 258 | q = blk_alloc_queue(GFP_KERNEL); |
249 | if (!blk_dev->queue) | 259 | if (!q) |
260 | return -ENOMEM; | ||
261 | if (devm_add_action(dev, nd_blk_release_queue, q)) { | ||
262 | blk_cleanup_queue(q); | ||
250 | return -ENOMEM; | 263 | return -ENOMEM; |
264 | } | ||
251 | 265 | ||
252 | blk_queue_make_request(blk_dev->queue, nd_blk_make_request); | 266 | blk_queue_make_request(q, nd_blk_make_request); |
253 | blk_queue_max_hw_sectors(blk_dev->queue, UINT_MAX); | 267 | blk_queue_max_hw_sectors(q, UINT_MAX); |
254 | blk_queue_bounce_limit(blk_dev->queue, BLK_BOUNCE_ANY); | 268 | blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); |
255 | blk_queue_logical_block_size(blk_dev->queue, blk_dev->sector_size); | 269 | blk_queue_logical_block_size(q, blk_dev->sector_size); |
256 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, blk_dev->queue); | 270 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); |
257 | 271 | ||
258 | disk = blk_dev->disk = alloc_disk(0); | 272 | disk = alloc_disk(0); |
259 | if (!disk) { | 273 | if (!disk) |
260 | blk_cleanup_queue(blk_dev->queue); | 274 | return -ENOMEM; |
275 | if (devm_add_action(dev, nd_blk_release_disk, disk)) { | ||
276 | put_disk(disk); | ||
261 | return -ENOMEM; | 277 | return -ENOMEM; |
262 | } | 278 | } |
263 | 279 | ||
@@ -265,7 +281,7 @@ static int nd_blk_attach_disk(struct nd_namespace_common *ndns, | |||
265 | disk->first_minor = 0; | 281 | disk->first_minor = 0; |
266 | disk->fops = &nd_blk_fops; | 282 | disk->fops = &nd_blk_fops; |
267 | disk->private_data = blk_dev; | 283 | disk->private_data = blk_dev; |
268 | disk->queue = blk_dev->queue; | 284 | disk->queue = q; |
269 | disk->flags = GENHD_FL_EXT_DEVT; | 285 | disk->flags = GENHD_FL_EXT_DEVT; |
270 | nvdimm_namespace_disk_name(ndns, disk->disk_name); | 286 | nvdimm_namespace_disk_name(ndns, disk->disk_name); |
271 | set_capacity(disk, 0); | 287 | set_capacity(disk, 0); |
@@ -274,12 +290,8 @@ static int nd_blk_attach_disk(struct nd_namespace_common *ndns, | |||
274 | if (nd_blk_meta_size(blk_dev)) { | 290 | if (nd_blk_meta_size(blk_dev)) { |
275 | int rc = nd_integrity_init(disk, nd_blk_meta_size(blk_dev)); | 291 | int rc = nd_integrity_init(disk, nd_blk_meta_size(blk_dev)); |
276 | 292 | ||
277 | if (rc) { | 293 | if (rc) |
278 | del_gendisk(disk); | ||
279 | put_disk(disk); | ||
280 | blk_cleanup_queue(blk_dev->queue); | ||
281 | return rc; | 294 | return rc; |
282 | } | ||
283 | } | 295 | } |
284 | 296 | ||
285 | set_capacity(disk, available_disk_size >> SECTOR_SHIFT); | 297 | set_capacity(disk, available_disk_size >> SECTOR_SHIFT); |
@@ -292,13 +304,12 @@ static int nd_blk_probe(struct device *dev) | |||
292 | struct nd_namespace_common *ndns; | 304 | struct nd_namespace_common *ndns; |
293 | struct nd_namespace_blk *nsblk; | 305 | struct nd_namespace_blk *nsblk; |
294 | struct nd_blk_device *blk_dev; | 306 | struct nd_blk_device *blk_dev; |
295 | int rc; | ||
296 | 307 | ||
297 | ndns = nvdimm_namespace_common_probe(dev); | 308 | ndns = nvdimm_namespace_common_probe(dev); |
298 | if (IS_ERR(ndns)) | 309 | if (IS_ERR(ndns)) |
299 | return PTR_ERR(ndns); | 310 | return PTR_ERR(ndns); |
300 | 311 | ||
301 | blk_dev = kzalloc(sizeof(*blk_dev), GFP_KERNEL); | 312 | blk_dev = devm_kzalloc(dev, sizeof(*blk_dev), GFP_KERNEL); |
302 | if (!blk_dev) | 313 | if (!blk_dev) |
303 | return -ENOMEM; | 314 | return -ENOMEM; |
304 | 315 | ||
@@ -313,34 +324,18 @@ static int nd_blk_probe(struct device *dev) | |||
313 | 324 | ||
314 | ndns->rw_bytes = nd_blk_rw_bytes; | 325 | ndns->rw_bytes = nd_blk_rw_bytes; |
315 | if (is_nd_btt(dev)) | 326 | if (is_nd_btt(dev)) |
316 | rc = nvdimm_namespace_attach_btt(ndns); | 327 | return nvdimm_namespace_attach_btt(ndns); |
317 | else if (nd_btt_probe(dev, ndns, blk_dev) == 0) { | 328 | else if (nd_btt_probe(dev, ndns, blk_dev) == 0) { |
318 | /* we'll come back as btt-blk */ | 329 | /* we'll come back as btt-blk */ |
319 | rc = -ENXIO; | 330 | return -ENXIO; |
320 | } else | 331 | } else |
321 | rc = nd_blk_attach_disk(ndns, blk_dev); | 332 | return nd_blk_attach_disk(dev, ndns, blk_dev); |
322 | if (rc) | ||
323 | kfree(blk_dev); | ||
324 | return rc; | ||
325 | } | ||
326 | |||
327 | static void nd_blk_detach_disk(struct nd_blk_device *blk_dev) | ||
328 | { | ||
329 | del_gendisk(blk_dev->disk); | ||
330 | put_disk(blk_dev->disk); | ||
331 | blk_cleanup_queue(blk_dev->queue); | ||
332 | } | 333 | } |
333 | 334 | ||
334 | static int nd_blk_remove(struct device *dev) | 335 | static int nd_blk_remove(struct device *dev) |
335 | { | 336 | { |
336 | struct nd_blk_device *blk_dev = dev_get_drvdata(dev); | ||
337 | |||
338 | if (is_nd_btt(dev)) | 337 | if (is_nd_btt(dev)) |
339 | nvdimm_namespace_detach_btt(to_nd_btt(dev)); | 338 | nvdimm_namespace_detach_btt(to_nd_btt(dev)); |
340 | else | ||
341 | nd_blk_detach_disk(blk_dev); | ||
342 | kfree(blk_dev); | ||
343 | |||
344 | return 0; | 339 | return 0; |
345 | } | 340 | } |
346 | 341 | ||