nvme: release namespace SRCU protection before performing controller ioctls
[ Upstream commit 5fb4aac756acacf260b9ebd88747251effa3a2f2 ] Holding the SRCU critical section protecting the namespace list can cause deadlocks when using the per-namespace admin passthrough ioctl to delete as namespace. Release it earlier when performing per-controller ioctls to avoid that. Reported-by: Kenneth Heitke <kenneth.heitke@intel.com> Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Reviewed-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
3188fcebbc
commit
ddda7e850b
1 changed files with 20 additions and 5 deletions
|
@ -1310,14 +1310,31 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
|
||||||
if (unlikely(!ns))
|
if (unlikely(!ns))
|
||||||
return -EWOULDBLOCK;
|
return -EWOULDBLOCK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle ioctls that apply to the controller instead of the namespace
|
||||||
|
* seperately and drop the ns SRCU reference early. This avoids a
|
||||||
|
* deadlock when deleting namespaces using the passthrough interface.
|
||||||
|
*/
|
||||||
|
if (cmd == NVME_IOCTL_ADMIN_CMD || is_sed_ioctl(cmd)) {
|
||||||
|
struct nvme_ctrl *ctrl = ns->ctrl;
|
||||||
|
|
||||||
|
nvme_get_ctrl(ns->ctrl);
|
||||||
|
nvme_put_ns_from_disk(head, srcu_idx);
|
||||||
|
|
||||||
|
if (cmd == NVME_IOCTL_ADMIN_CMD)
|
||||||
|
ret = nvme_user_cmd(ctrl, NULL, argp);
|
||||||
|
else
|
||||||
|
ret = sed_ioctl(ctrl->opal_dev, cmd, argp);
|
||||||
|
|
||||||
|
nvme_put_ctrl(ctrl);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case NVME_IOCTL_ID:
|
case NVME_IOCTL_ID:
|
||||||
force_successful_syscall_return();
|
force_successful_syscall_return();
|
||||||
ret = ns->head->ns_id;
|
ret = ns->head->ns_id;
|
||||||
break;
|
break;
|
||||||
case NVME_IOCTL_ADMIN_CMD:
|
|
||||||
ret = nvme_user_cmd(ns->ctrl, NULL, argp);
|
|
||||||
break;
|
|
||||||
case NVME_IOCTL_IO_CMD:
|
case NVME_IOCTL_IO_CMD:
|
||||||
ret = nvme_user_cmd(ns->ctrl, ns, argp);
|
ret = nvme_user_cmd(ns->ctrl, ns, argp);
|
||||||
break;
|
break;
|
||||||
|
@ -1327,8 +1344,6 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
|
||||||
default:
|
default:
|
||||||
if (ns->ndev)
|
if (ns->ndev)
|
||||||
ret = nvme_nvm_ioctl(ns, cmd, arg);
|
ret = nvme_nvm_ioctl(ns, cmd, arg);
|
||||||
else if (is_sed_ioctl(cmd))
|
|
||||||
ret = sed_ioctl(ns->ctrl->opal_dev, cmd, argp);
|
|
||||||
else
|
else
|
||||||
ret = -ENOTTY;
|
ret = -ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue