Commit 5fb4aac7 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Keith Busch
Browse files

nvme: release namespace SRCU protection before performing controller ioctls



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: default avatarKenneth Heitke <kenneth.heitke@intel.com>
Reviewed-by: default avatarChaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Reviewed-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 90ec611a
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -1394,14 +1394,31 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
	if (unlikely(!ns))
		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) {
	case NVME_IOCTL_ID:
		force_successful_syscall_return();
		ret = ns->head->ns_id;
		break;
	case NVME_IOCTL_ADMIN_CMD:
		ret = nvme_user_cmd(ns->ctrl, NULL, argp);
		break;
	case NVME_IOCTL_IO_CMD:
		ret = nvme_user_cmd(ns->ctrl, ns, argp);
		break;
@@ -1411,8 +1428,6 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
	default:
		if (ns->ndev)
			ret = nvme_nvm_ioctl(ns, cmd, arg);
		else if (is_sed_ioctl(cmd))
			ret = sed_ioctl(ns->ctrl->opal_dev, cmd, argp);
		else
			ret = -ENOTTY;
	}