Skip to content

Commit 030b99e

Browse files
committed
libnvdimm, pmem: 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 <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: Dan Williams <[email protected]>
1 parent 9d90725 commit 030b99e

File tree

1 file changed

+39
-49
lines changed

1 file changed

+39
-49
lines changed

drivers/nvdimm/pmem.c

Lines changed: 39 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,17 @@ static const struct block_device_operations pmem_fops = {
198198
.revalidate_disk = nvdimm_revalidate_disk,
199199
};
200200

201+
static void pmem_release_queue(void *q)
202+
{
203+
blk_cleanup_queue(q);
204+
}
205+
206+
void pmem_release_disk(void *disk)
207+
{
208+
del_gendisk(disk);
209+
put_disk(disk);
210+
}
211+
201212
static struct pmem_device *pmem_alloc(struct device *dev,
202213
struct resource *res, int id)
203214
{
@@ -234,25 +245,22 @@ static struct pmem_device *pmem_alloc(struct device *dev,
234245
pmem->phys_addr, pmem->size,
235246
ARCH_MEMREMAP_PMEM);
236247

237-
if (IS_ERR(pmem->virt_addr)) {
248+
/*
249+
* At release time the queue must be dead before
250+
* devm_memremap_pages is unwound
251+
*/
252+
if (devm_add_action(dev, pmem_release_queue, q)) {
238253
blk_cleanup_queue(q);
239-
return (void __force *) pmem->virt_addr;
254+
return ERR_PTR(-ENOMEM);
240255
}
241256

257+
if (IS_ERR(pmem->virt_addr))
258+
return (void __force *) pmem->virt_addr;
259+
242260
pmem->pmem_queue = q;
243261
return pmem;
244262
}
245263

246-
static void pmem_detach_disk(struct pmem_device *pmem)
247-
{
248-
if (!pmem->pmem_disk)
249-
return;
250-
251-
del_gendisk(pmem->pmem_disk);
252-
put_disk(pmem->pmem_disk);
253-
blk_cleanup_queue(pmem->pmem_queue);
254-
}
255-
256264
static int pmem_attach_disk(struct device *dev,
257265
struct nd_namespace_common *ndns, struct pmem_device *pmem)
258266
{
@@ -269,8 +277,10 @@ static int pmem_attach_disk(struct device *dev,
269277
pmem->pmem_queue->queuedata = pmem;
270278

271279
disk = alloc_disk_node(0, nid);
272-
if (!disk) {
273-
blk_cleanup_queue(pmem->pmem_queue);
280+
if (!disk)
281+
return -ENOMEM;
282+
if (devm_add_action(dev, pmem_release_disk, disk)) {
283+
put_disk(disk);
274284
return -ENOMEM;
275285
}
276286

@@ -427,15 +437,6 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
427437
return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb));
428438
}
429439

430-
static void nvdimm_namespace_detach_pfn(struct nd_pfn *nd_pfn)
431-
{
432-
struct pmem_device *pmem;
433-
434-
/* free pmem disk */
435-
pmem = dev_get_drvdata(&nd_pfn->dev);
436-
pmem_detach_disk(pmem);
437-
}
438-
439440
/*
440441
* We hotplug memory at section granularity, pad the reserved area from
441442
* the previous section base to the namespace base address.
@@ -458,7 +459,6 @@ static unsigned long init_altmap_reserve(resource_size_t base)
458459

459460
static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn)
460461
{
461-
int rc;
462462
struct resource res;
463463
struct request_queue *q;
464464
struct pmem_device *pmem;
@@ -495,35 +495,33 @@ static int __nvdimm_namespace_attach_pfn(struct nd_pfn *nd_pfn)
495495
altmap = & __altmap;
496496
altmap->free = PHYS_PFN(pmem->data_offset - SZ_8K);
497497
altmap->alloc = 0;
498-
} else {
499-
rc = -ENXIO;
500-
goto err;
501-
}
498+
} else
499+
return -ENXIO;
502500

503501
/* establish pfn range for lookup, and switch to direct map */
504502
q = pmem->pmem_queue;
505503
memcpy(&res, &nsio->res, sizeof(res));
506504
res.start += start_pad;
507505
res.end -= end_trunc;
506+
devm_remove_action(dev, pmem_release_queue, q);
508507
devm_memunmap(dev, (void __force *) pmem->virt_addr);
509508
pmem->virt_addr = (void __pmem *) devm_memremap_pages(dev, &res,
510509
&q->q_usage_counter, altmap);
511510
pmem->pfn_flags |= PFN_MAP;
512-
if (IS_ERR(pmem->virt_addr)) {
513-
rc = PTR_ERR(pmem->virt_addr);
514-
goto err;
511+
512+
/*
513+
* At release time the queue must be dead before
514+
* devm_memremap_pages is unwound
515+
*/
516+
if (devm_add_action(dev, pmem_release_queue, q)) {
517+
blk_cleanup_queue(q);
518+
return -ENOMEM;
515519
}
520+
if (IS_ERR(pmem->virt_addr))
521+
return PTR_ERR(pmem->virt_addr);
516522

517523
/* attach pmem disk in "pfn-mode" */
518-
rc = pmem_attach_disk(dev, ndns, pmem);
519-
if (rc)
520-
goto err;
521-
522-
return rc;
523-
err:
524-
nvdimm_namespace_detach_pfn(nd_pfn);
525-
return rc;
526-
524+
return pmem_attach_disk(dev, ndns, pmem);
527525
}
528526

529527
static int nvdimm_namespace_attach_pfn(struct nd_namespace_common *ndns)
@@ -565,8 +563,8 @@ static int nd_pmem_probe(struct device *dev)
565563

566564
if (is_nd_btt(dev)) {
567565
/* btt allocates its own request_queue */
566+
devm_remove_action(dev, pmem_release_queue, pmem->pmem_queue);
568567
blk_cleanup_queue(pmem->pmem_queue);
569-
pmem->pmem_queue = NULL;
570568
return nvdimm_namespace_attach_btt(ndns);
571569
}
572570

@@ -579,7 +577,6 @@ static int nd_pmem_probe(struct device *dev)
579577
* We'll come back as either btt-pmem, or pfn-pmem, so
580578
* drop the queue allocation for now.
581579
*/
582-
blk_cleanup_queue(pmem->pmem_queue);
583580
return -ENXIO;
584581
}
585582

@@ -588,15 +585,8 @@ static int nd_pmem_probe(struct device *dev)
588585

589586
static int nd_pmem_remove(struct device *dev)
590587
{
591-
struct pmem_device *pmem = dev_get_drvdata(dev);
592-
593588
if (is_nd_btt(dev))
594589
nvdimm_namespace_detach_btt(to_nd_btt(dev));
595-
else if (is_nd_pfn(dev))
596-
nvdimm_namespace_detach_pfn(to_nd_pfn(dev));
597-
else
598-
pmem_detach_disk(pmem);
599-
600590
return 0;
601591
}
602592

0 commit comments

Comments
 (0)