Skip to content

Commit 1a9e218

Browse files
committed
nvme: split device add from initialization
Combining both creates an ambiguous cleanup scenario for the caller if an error is returned: does the device reference need to be dropped or did the error occur before the device was initialized? If an error occurs after the device is added, then the existing cleanup routines will leak memory. Furthermore, the nvme core is taking it upon itself to free the device's kobj name under certain conditions rather than go through the core device API. We shouldn't be peaking into these implementation details. Split the device initialization from the addition to make it easier to know the error handling actions, fix the existing memory leaks, and stop the device layering violations. Link: https://lore.kernel.org/linux-nvme/[email protected]/ Tested-by: Yi Zhang <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Chaitanya Kulkarni <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 72cded7 commit 1a9e218

File tree

8 files changed

+66
-23
lines changed

8 files changed

+66
-23
lines changed

drivers/nvme/host/apple.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,10 @@ static int apple_nvme_probe(struct platform_device *pdev)
15311531
if (IS_ERR(anv))
15321532
return PTR_ERR(anv);
15331533

1534+
ret = nvme_add_ctrl(&anv->ctrl);
1535+
if (ret)
1536+
goto out_put_ctrl;
1537+
15341538
anv->ctrl.admin_q = blk_mq_alloc_queue(&anv->admin_tagset, NULL, NULL);
15351539
if (IS_ERR(anv->ctrl.admin_q)) {
15361540
ret = -ENOMEM;
@@ -1545,6 +1549,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
15451549

15461550
out_uninit_ctrl:
15471551
nvme_uninit_ctrl(&anv->ctrl);
1552+
out_put_ctrl:
15481553
nvme_put_ctrl(&anv->ctrl);
15491554
return ret;
15501555
}

drivers/nvme/host/core.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4667,6 +4667,9 @@ static void nvme_free_ctrl(struct device *dev)
46674667
* Initialize a NVMe controller structures. This needs to be called during
46684668
* earliest initialization so that we have the initialized structured around
46694669
* during probing.
4670+
*
4671+
* On success, the caller must use the nvme_put_ctrl() to release this when
4672+
* needed, which also invokes the ops->free_ctrl() callback.
46704673
*/
46714674
int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
46724675
const struct nvme_ctrl_ops *ops, unsigned long quirks)
@@ -4715,6 +4718,12 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
47154718
goto out;
47164719
ctrl->instance = ret;
47174720

4721+
ret = nvme_auth_init_ctrl(ctrl);
4722+
if (ret)
4723+
goto out_release_instance;
4724+
4725+
nvme_mpath_init_ctrl(ctrl);
4726+
47184727
device_initialize(&ctrl->ctrl_device);
47194728
ctrl->device = &ctrl->ctrl_device;
47204729
ctrl->device->devt = MKDEV(MAJOR(nvme_ctrl_base_chr_devt),
@@ -4727,16 +4736,36 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
47274736
ctrl->device->groups = nvme_dev_attr_groups;
47284737
ctrl->device->release = nvme_free_ctrl;
47294738
dev_set_drvdata(ctrl->device, ctrl);
4739+
4740+
return ret;
4741+
4742+
out_release_instance:
4743+
ida_free(&nvme_instance_ida, ctrl->instance);
4744+
out:
4745+
if (ctrl->discard_page)
4746+
__free_page(ctrl->discard_page);
4747+
cleanup_srcu_struct(&ctrl->srcu);
4748+
return ret;
4749+
}
4750+
EXPORT_SYMBOL_GPL(nvme_init_ctrl);
4751+
4752+
/*
4753+
* On success, returns with an elevated controller reference and caller must
4754+
* use nvme_uninit_ctrl() to properly free resources associated with the ctrl.
4755+
*/
4756+
int nvme_add_ctrl(struct nvme_ctrl *ctrl)
4757+
{
4758+
int ret;
4759+
47304760
ret = dev_set_name(ctrl->device, "nvme%d", ctrl->instance);
47314761
if (ret)
4732-
goto out_release_instance;
4762+
return ret;
47334763

4734-
nvme_get_ctrl(ctrl);
47354764
cdev_init(&ctrl->cdev, &nvme_dev_fops);
4736-
ctrl->cdev.owner = ops->module;
4765+
ctrl->cdev.owner = ctrl->ops->module;
47374766
ret = cdev_device_add(&ctrl->cdev, ctrl->device);
47384767
if (ret)
4739-
goto out_free_name;
4768+
return ret;
47404769

47414770
/*
47424771
* Initialize latency tolerance controls. The sysfs files won't
@@ -4747,28 +4776,11 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
47474776
min(default_ps_max_latency_us, (unsigned long)S32_MAX));
47484777

47494778
nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device));
4750-
nvme_mpath_init_ctrl(ctrl);
4751-
ret = nvme_auth_init_ctrl(ctrl);
4752-
if (ret)
4753-
goto out_free_cdev;
4779+
nvme_get_ctrl(ctrl);
47544780

47554781
return 0;
4756-
out_free_cdev:
4757-
nvme_fault_inject_fini(&ctrl->fault_inject);
4758-
dev_pm_qos_hide_latency_tolerance(ctrl->device);
4759-
cdev_device_del(&ctrl->cdev, ctrl->device);
4760-
out_free_name:
4761-
nvme_put_ctrl(ctrl);
4762-
kfree_const(ctrl->device->kobj.name);
4763-
out_release_instance:
4764-
ida_free(&nvme_instance_ida, ctrl->instance);
4765-
out:
4766-
if (ctrl->discard_page)
4767-
__free_page(ctrl->discard_page);
4768-
cleanup_srcu_struct(&ctrl->srcu);
4769-
return ret;
47704782
}
4771-
EXPORT_SYMBOL_GPL(nvme_init_ctrl);
4783+
EXPORT_SYMBOL_GPL(nvme_add_ctrl);
47724784

47734785
/* let I/O to all namespaces fail in preparation for surprise removal */
47744786
void nvme_mark_namespaces_dead(struct nvme_ctrl *ctrl)

drivers/nvme/host/fc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3563,6 +3563,10 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
35633563
if (IS_ERR(ctrl))
35643564
return ERR_CAST(ctrl);
35653565

3566+
ret = nvme_add_ctrl(&ctrl->ctrl);
3567+
if (ret)
3568+
goto out_put_ctrl;
3569+
35663570
ret = nvme_alloc_admin_tag_set(&ctrl->ctrl, &ctrl->admin_tag_set,
35673571
&nvme_fc_admin_mq_ops,
35683572
struct_size_t(struct nvme_fcp_op_w_sgl, priv,
@@ -3607,6 +3611,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
36073611
/* initiate nvme ctrl ref counting teardown */
36083612
nvme_uninit_ctrl(&ctrl->ctrl);
36093613

3614+
out_put_ctrl:
36103615
/* Remove core ctrl ref. */
36113616
nvme_put_ctrl(&ctrl->ctrl);
36123617

drivers/nvme/host/nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl, bool shutdown);
792792
int nvme_enable_ctrl(struct nvme_ctrl *ctrl);
793793
int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
794794
const struct nvme_ctrl_ops *ops, unsigned long quirks);
795+
int nvme_add_ctrl(struct nvme_ctrl *ctrl);
795796
void nvme_uninit_ctrl(struct nvme_ctrl *ctrl);
796797
void nvme_start_ctrl(struct nvme_ctrl *ctrl);
797798
void nvme_stop_ctrl(struct nvme_ctrl *ctrl);

drivers/nvme/host/pci.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,6 +3015,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
30153015
if (IS_ERR(dev))
30163016
return PTR_ERR(dev);
30173017

3018+
result = nvme_add_ctrl(&dev->ctrl);
3019+
if (result)
3020+
goto out_put_ctrl;
3021+
30183022
result = nvme_dev_map(dev);
30193023
if (result)
30203024
goto out_uninit_ctrl;
@@ -3101,6 +3105,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
31013105
nvme_dev_unmap(dev);
31023106
out_uninit_ctrl:
31033107
nvme_uninit_ctrl(&dev->ctrl);
3108+
out_put_ctrl:
31043109
nvme_put_ctrl(&dev->ctrl);
31053110
return result;
31063111
}

drivers/nvme/host/rdma.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,6 +2323,10 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
23232323
if (IS_ERR(ctrl))
23242324
return ERR_CAST(ctrl);
23252325

2326+
ret = nvme_add_ctrl(&ctrl->ctrl);
2327+
if (ret)
2328+
goto out_put_ctrl;
2329+
23262330
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING);
23272331
WARN_ON_ONCE(!changed);
23282332

@@ -2341,6 +2345,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
23412345

23422346
out_uninit_ctrl:
23432347
nvme_uninit_ctrl(&ctrl->ctrl);
2348+
out_put_ctrl:
23442349
nvme_put_ctrl(&ctrl->ctrl);
23452350
if (ret > 0)
23462351
ret = -EIO;

drivers/nvme/host/tcp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2779,6 +2779,10 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
27792779
if (IS_ERR(ctrl))
27802780
return ERR_CAST(ctrl);
27812781

2782+
ret = nvme_add_ctrl(&ctrl->ctrl);
2783+
if (ret)
2784+
goto out_put_ctrl;
2785+
27822786
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
27832787
WARN_ON_ONCE(1);
27842788
ret = -EINTR;
@@ -2800,6 +2804,7 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
28002804

28012805
out_uninit_ctrl:
28022806
nvme_uninit_ctrl(&ctrl->ctrl);
2807+
out_put_ctrl:
28032808
nvme_put_ctrl(&ctrl->ctrl);
28042809
if (ret > 0)
28052810
ret = -EIO;

drivers/nvme/target/loop.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,10 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
555555
goto out;
556556
}
557557

558+
ret = nvme_add_ctrl(&ctrl->ctrl);
559+
if (ret)
560+
goto out_put_ctrl;
561+
558562
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
559563
WARN_ON_ONCE(1);
560564

@@ -611,6 +615,7 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
611615
kfree(ctrl->queues);
612616
out_uninit_ctrl:
613617
nvme_uninit_ctrl(&ctrl->ctrl);
618+
out_put_ctrl:
614619
nvme_put_ctrl(&ctrl->ctrl);
615620
out:
616621
if (ret > 0)

0 commit comments

Comments
 (0)