blktests nvme 041,042 leak memory

Keith Busch kbusch at kernel.org
Wed May 29 09:25:18 PDT 2024


On Wed, May 29, 2024 at 03:51:09PM +0300, Sagi Grimberg wrote:
> 
> But this is ugly...

I agree. Could we not work around the device model instead? Once we call
device_add successfully, we really need to pair that with a device_del.

I see two ways we might be able to do this.

First suggestion: move the device_add to the end so we don't have to
worry about cleaning up if subsequence actions fail. And auth_init_ctrl
doesn't appear to have any dependency on the ctrl->device anyway.

---
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f5d150c62955d..d86db6a193fcb 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -4675,12 +4675,16 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 	if (ret)
 		goto out_release_instance;
 
+	ret = nvme_auth_init_ctrl(ctrl);
+	if (ret)
+		goto out_free_name;
+
 	nvme_get_ctrl(ctrl);
 	cdev_init(&ctrl->cdev, &nvme_dev_fops);
 	ctrl->cdev.owner = ops->module;
 	ret = cdev_device_add(&ctrl->cdev, ctrl->device);
 	if (ret)
-		goto out_free_name;
+		goto auth_free;
 
 	/*
 	 * Initialize latency tolerance controls.  The sysfs files won't
@@ -4692,15 +4696,10 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 
 	nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device));
 	nvme_mpath_init_ctrl(ctrl);
-	ret = nvme_auth_init_ctrl(ctrl);
-	if (ret)
-		goto out_free_cdev;
 
 	return 0;
-out_free_cdev:
-	nvme_fault_inject_fini(&ctrl->fault_inject);
-	dev_pm_qos_hide_latency_tolerance(ctrl->device);
-	cdev_device_del(&ctrl->cdev, ctrl->device);
+auth_free:
+	nvme_auth_free(ctrl);
 out_free_name:
 	nvme_put_ctrl(ctrl);
 	kfree_const(ctrl->device->kobj.name);
--

Second suggestion, let the error handling release the last reference.
The trick here is to not call the "free_ctrl" callback on "new"
controllers, and don't take a ctrl reference until the end.

---
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index f5d150c62955d..72c9693e1df61 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -4601,7 +4601,8 @@ static void nvme_free_ctrl(struct device *dev)
 		mutex_unlock(&nvme_subsystems_lock);
 	}
 
-	ctrl->ops->free_ctrl(ctrl);
+	if (nvme_ctrl_state(ctrl) != NVME_CTRL_NEW)
+		ctrl->ops->free_ctrl(ctrl);
 
 	if (subsys)
 		nvme_put_subsystem(subsys);
@@ -4675,7 +4676,6 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 	if (ret)
 		goto out_release_instance;
 
-	nvme_get_ctrl(ctrl);
 	cdev_init(&ctrl->cdev, &nvme_dev_fops);
 	ctrl->cdev.owner = ops->module;
 	ret = cdev_device_add(&ctrl->cdev, ctrl->device);
@@ -4696,13 +4696,16 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 	if (ret)
 		goto out_free_cdev;
 
+	nvme_get_ctrl(ctrl);
 	return 0;
 out_free_cdev:
 	nvme_fault_inject_fini(&ctrl->fault_inject);
 	dev_pm_qos_hide_latency_tolerance(ctrl->device);
 	cdev_device_del(&ctrl->cdev, ctrl->device);
-out_free_name:
 	nvme_put_ctrl(ctrl);
+	return ret;
+
+out_free_name:
 	kfree_const(ctrl->device->kobj.name);
 out_release_instance:
 	ida_free(&nvme_instance_ida, ctrl->instance);
--



More information about the Linux-nvme mailing list