aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-03-17 23:08:28 -0400
committerDan Williams <dan.j.williams@intel.com>2016-04-22 15:26:22 -0400
commitd29cee120eb890027c69f5fe7cce8bd6a663900a (patch)
treed427aa25124dc9a83002432d92d8063874c7b5a8
parente32bc729a3a486e20443db3379ecf67240b20616 (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.c77
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
24struct nd_blk_device { 24struct 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
238static int nd_blk_attach_disk(struct nd_namespace_common *ndns, 236static void nd_blk_release_queue(void *q)
239 struct nd_blk_device *blk_dev) 237{
238 blk_cleanup_queue(q);
239}
240
241static void nd_blk_release_disk(void *disk)
242{
243 del_gendisk(disk);
244 put_disk(disk);
245}
246
247static 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
327static 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
334static int nd_blk_remove(struct device *dev) 335static 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