Commit ce151813 authored by Israel Rukshin's avatar Israel Rukshin Committed by Keith Busch

nvme: Fix controller creation races with teardown flow

Calling nvme_sysfs_delete() when the controller is in the middle of
creation may cause several bugs. If the controller is in NEW state we
remove delete_controller file and don't delete the controller. The user
will not be able to use nvme disconnect command on that controller again,
although the controller may be active. Other bugs may happen if the
controller is in the middle of create_ctrl callback and
nvme_do_delete_ctrl() starts. For example, freeing I/O tagset at
nvme_do_delete_ctrl() before it was allocated at create_ctrl callback.

To fix all those races don't allow the user to delete the controller
before it was fully created.
Signed-off-by: default avatarIsrael Rukshin <israelr@mellanox.com>
Reviewed-by: default avatarMax Gurtovoy <maxg@mellanox.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
parent 726612b6
...@@ -3228,6 +3228,10 @@ static ssize_t nvme_sysfs_delete(struct device *dev, ...@@ -3228,6 +3228,10 @@ static ssize_t nvme_sysfs_delete(struct device *dev,
{ {
struct nvme_ctrl *ctrl = dev_get_drvdata(dev); struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
/* Can't delete non-created controllers */
if (!ctrl->created)
return -EBUSY;
if (device_remove_file_self(dev, attr)) if (device_remove_file_self(dev, attr))
nvme_delete_ctrl_sync(ctrl); nvme_delete_ctrl_sync(ctrl);
return count; return count;
...@@ -4039,6 +4043,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl) ...@@ -4039,6 +4043,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl)
nvme_queue_scan(ctrl); nvme_queue_scan(ctrl);
nvme_start_queues(ctrl); nvme_start_queues(ctrl);
} }
ctrl->created = true;
} }
EXPORT_SYMBOL_GPL(nvme_start_ctrl); EXPORT_SYMBOL_GPL(nvme_start_ctrl);
......
...@@ -259,6 +259,7 @@ struct nvme_ctrl { ...@@ -259,6 +259,7 @@ struct nvme_ctrl {
struct nvme_command ka_cmd; struct nvme_command ka_cmd;
struct work_struct fw_act_work; struct work_struct fw_act_work;
unsigned long events; unsigned long events;
bool created;
#ifdef CONFIG_NVME_MULTIPATH #ifdef CONFIG_NVME_MULTIPATH
/* asymmetric namespace access: */ /* asymmetric namespace access: */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment