[RFC v3 8/9] nvme: move queue flags to middle layer

Sagi Grimberg sagi at grimberg.me
Thu May 4 02:42:03 PDT 2023


> The queue flags are used to track the state of the queue (deleted, live,
> ...). Move this generic feature into the fabric middle layer.
> 
> Unfortunately, rdma uses an transport flag (TR_READY) which is not used
> in the generic part of the state machine.

This would be a transport specific flag, it is only accessed in a
transport specific function. So this would need to be in a
nvme_rdma_queue flags field.

But I don't think that we need queues array in the core nvme_ctrl.
I think that all the transports will have an admin queue and io queues.
Representing a queue in the core would be difficult IMO

> 
> Signed-off-by: Daniel Wagner <dwagner at suse.de>
> ---
>   drivers/nvme/host/fabrics.c | 157 +++++++++++++++++++++++++++++-------
>   drivers/nvme/host/nvme.h    |  19 ++++-
>   drivers/nvme/host/rdma.c    |  75 ++++++-----------
>   drivers/nvme/host/tcp.c     |  87 +++++++-------------
>   4 files changed, 197 insertions(+), 141 deletions(-)
> 
> diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
> index 3d2cde17338d..5f212cb9421a 100644
> --- a/drivers/nvme/host/fabrics.c
> +++ b/drivers/nvme/host/fabrics.c
> @@ -1134,13 +1134,117 @@ nvmf_create_ctrl(struct device *dev, const char *buf)
>   	return ERR_PTR(ret);
>   }
>   
> +static int __nvmf_alloc_admin_queue(struct nvme_ctrl *ctrl)
> +{
> +	int ret;
> +
> +	ret = ctrl->fabrics_ops->alloc_admin_queue(ctrl);
> +	if (ret)
> +		return ret;
> +
> +	set_bit(NVME_FABRICS_Q_ALLOCATED, ctrl->queues[0].flags);
> +
> +	return 0;
> +}
> +
> +static void __nvmf_free_admin_queue(struct nvme_ctrl *ctrl)
> +{
> +	if (!test_and_clear_bit(NVME_FABRICS_Q_ALLOCATED,
> +				ctrl->queues[0].flags))
> +		return;
> +
> +	ctrl->fabrics_ops->free_admin_queue(ctrl);
> +}
> +
> +static int __nvmf_start_admin_queue(struct nvme_ctrl *ctrl)
> +{
> +	int ret;
> +
> +	if (!test_bit(NVME_FABRICS_Q_ALLOCATED, ctrl->queues[0].flags))
> +		return -EINVAL;
> +
> +	ret = ctrl->fabrics_ops->start_admin_queue(ctrl);
> +	if (ret) {
> +		dev_err(ctrl->device,
> +			"failed to start admin queue: ret=%d\n", ret);
> +		return ret;
> +	}
> +
> +	set_bit(NVME_FABRICS_Q_LIVE, ctrl->queues[0].flags);
> +
> +	return 0;
> +}
> +
> +static void __nvmf_stop_admin_queue(struct nvme_ctrl *ctrl)
> +{
> +	if (!test_bit(NVME_FABRICS_Q_ALLOCATED, ctrl->queues[0].flags))
> +		return;
> +
> +	mutex_lock(ctrl->queues[0].queue_lock);
> +	if (test_and_clear_bit(NVME_FABRICS_Q_LIVE, ctrl->queues[0].flags))
> +		ctrl->fabrics_ops->stop_admin_queue(ctrl);
> +	mutex_unlock(ctrl->queues[0].queue_lock);
> +}
> +
> +static int __nvmf_alloc_io_queue(struct nvme_ctrl *ctrl, int qid)
> +{
> +	int ret;
> +
> +	ret = ctrl->fabrics_ops->alloc_io_queue(ctrl, qid);
> +	if (ret) {
> +		dev_err(ctrl->device,
> +			"failed to start I/O queue: %d ret=%d\n", qid, ret);
> +		return ret;
> +	}
> +
> +	set_bit(NVME_FABRICS_Q_ALLOCATED, ctrl->queues[qid].flags);
> +
> +	return 0;
> +}
> +
> +static void __nvmf_free_io_queue(struct nvme_ctrl *ctrl, int qid)
> +{
> +	if (!test_and_clear_bit(NVME_FABRICS_Q_ALLOCATED,
> +				ctrl->queues[qid].flags))
> +		return;
> +
> +	ctrl->fabrics_ops->free_io_queue(ctrl, qid);
> +}
> +
> +static int __nvmf_start_io_queue(struct nvme_ctrl *ctrl, int qid)
> +{
> +	int ret;
> +
> +	if (!test_bit(NVME_FABRICS_Q_ALLOCATED, ctrl->queues[0].flags))
> +		return -EINVAL;
> +
> +	ret = ctrl->fabrics_ops->start_io_queue(ctrl, qid);
> +	if (ret)
> +		return ret;
> +
> +	set_bit(NVME_FABRICS_Q_LIVE, ctrl->queues[qid].flags);
> +
> +	return 0;
> +}
> +
> +static void __nvmf_stop_io_queue(struct nvme_ctrl *ctrl, int qid)
> +{
> +	if (!test_bit(NVME_FABRICS_Q_ALLOCATED, ctrl->queues[qid].flags))
> +		return;
> +
> +	mutex_lock(ctrl->queues[qid].queue_lock);
> +	if (test_and_clear_bit(NVME_FABRICS_Q_LIVE, ctrl->queues[qid].flags))
> +		ctrl->fabrics_ops->stop_io_queue(ctrl, qid);
> +	mutex_unlock(ctrl->queues[qid].queue_lock);
> +}
> +
>   static int nvmf_start_io_queues(struct nvme_ctrl *ctrl,
>   				    int first, int last)
>   {
>   	int i, ret;
>   
>   	for (i = first; i < last; i++) {
> -		ret = ctrl->fabrics_ops->start_io_queue(ctrl, i);
> +		ret = __nvmf_start_io_queue(ctrl, i);
>   		if (ret)
>   			goto out_stop_queues;
>   	}
> @@ -1149,7 +1253,7 @@ static int nvmf_start_io_queues(struct nvme_ctrl *ctrl,
>   
>   out_stop_queues:
>   	for (i--; i >= first; i--)
> -		ctrl->fabrics_ops->stop_io_queue(ctrl, i);
> +		__nvmf_stop_io_queue(ctrl, i);
>   	return ret;
>   }
>   
> @@ -1158,7 +1262,7 @@ static void nvmf_stop_io_queues(struct nvme_ctrl *ctrl)
>   	int i;
>   
>   	for (i = 1; i < ctrl->queue_count; i++)
> -		ctrl->fabrics_ops->stop_io_queue(ctrl, i);
> +		__nvmf_stop_io_queue(ctrl, i);
>   }
>   
>   static int __nvmf_alloc_io_queues(struct nvme_ctrl *ctrl)
> @@ -1166,7 +1270,7 @@ static int __nvmf_alloc_io_queues(struct nvme_ctrl *ctrl)
>   	int i, ret;
>   
>   	for (i = 1; i < ctrl->queue_count; i++) {
> -		ret = ctrl->fabrics_ops->alloc_io_queue(ctrl, i);
> +		ret = __nvmf_alloc_io_queue(ctrl, i);
>   		if (ret)
>   			goto out_free_queues;
>   	}
> @@ -1175,7 +1279,7 @@ static int __nvmf_alloc_io_queues(struct nvme_ctrl *ctrl)
>   
>   out_free_queues:
>   	for (i--; i >= 1; i--)
> -		ctrl->fabrics_ops->free_io_queue(ctrl, i);
> +		__nvmf_free_io_queue(ctrl, i);
>   
>   	return ret;
>   }
> @@ -1198,7 +1302,7 @@ static int nvmf_alloc_io_queues(struct nvme_ctrl *ctrl)
>   
>   	ctrl->queue_count = nr_io_queues + 1;
>   	dev_info(ctrl->device,
> -		"creating %d I/O queues.\n", nr_io_queues);
> +		 "creating %d I/O queues.\n", nr_io_queues);
>   
>   	ctrl->fabrics_ops->set_io_queues(ctrl, nr_io_queues);
>   
> @@ -1210,7 +1314,7 @@ static void nvmf_free_io_queues(struct nvme_ctrl *ctrl)
>   	int i;
>   
>   	for (i = 1; i < ctrl->queue_count; i++)
> -		ctrl->fabrics_ops->free_io_queue(ctrl, i);
> +		__nvmf_free_io_queue(ctrl, i);
>   }
>   
>   static int nvmf_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
> @@ -1279,31 +1383,31 @@ static int nvmf_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
>   
>   static int nvmf_configure_admin_queue(struct nvme_ctrl *ctrl, bool new)
>   {
> -	int error;
> +	int ret;
>   
> -	error = ctrl->fabrics_ops->alloc_admin_queue(ctrl);
> -	if (error)
> -		return error;
> +	ret = __nvmf_alloc_admin_queue(ctrl);
> +	if (ret)
> +		return ret;
>   
>   	if (new) {
> -		error = ctrl->fabrics_ops->alloc_admin_tag_set(ctrl);
> -		if (error)
> +		ret = ctrl->fabrics_ops->alloc_admin_tag_set(ctrl);
> +		if (ret)
>   			goto out_free_admin_queue;
>   
>   	}
>   
> -	error = ctrl->fabrics_ops->start_admin_queue(ctrl);
> -	if (error)
> +	ret = __nvmf_start_admin_queue(ctrl);
> +	if (ret)
>   		goto out_remove_admin_tag_set;
>   
> -	error = nvme_enable_ctrl(ctrl);
> -	if (error)
> +	ret = nvme_enable_ctrl(ctrl);
> +	if (ret)
>   		goto out_stop_queue;
>   
>   	nvme_unquiesce_admin_queue(ctrl);
>   
> -	error = nvme_init_ctrl_finish(ctrl, false);
> -	if (error)
> +	ret = nvme_init_ctrl_finish(ctrl, false);
> +	if (ret)
>   		goto out_quiesce_queue;
>   
>   	return 0;
> @@ -1312,14 +1416,14 @@ static int nvmf_configure_admin_queue(struct nvme_ctrl *ctrl, bool new)
>   	nvme_quiesce_admin_queue(ctrl);
>   	blk_sync_queue(ctrl->admin_q);
>   out_stop_queue:
> -	ctrl->fabrics_ops->stop_admin_queue(ctrl);
> +	__nvmf_stop_admin_queue(ctrl);
>   	nvme_cancel_admin_tagset(ctrl);
>   out_remove_admin_tag_set:
>   	if (new)
>   		nvme_remove_admin_tag_set(ctrl);
>   out_free_admin_queue:
> -	ctrl->fabrics_ops->free_admin_queue(ctrl);
> -	return error;
> +	__nvmf_free_admin_queue(ctrl);
> +	return ret;
>   }
>   
>   static void nvmf_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove)
> @@ -1332,18 +1436,17 @@ static void nvmf_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove)
>   
>   static void nvmf_destroy_admin_queue(struct nvme_ctrl *ctrl, bool remove)
>   {
> -	ctrl->fabrics_ops->stop_admin_queue(ctrl);
> +	__nvmf_stop_admin_queue(ctrl);
>   	if (remove)
>   		nvme_remove_admin_tag_set(ctrl);
> -
> -	ctrl->fabrics_ops->free_admin_queue(ctrl);
> +	__nvmf_free_admin_queue(ctrl);
>   }
>   
>   static void nvmf_teardown_admin_queue(struct nvme_ctrl *ctrl, bool remove)
>   {
>   	nvme_quiesce_admin_queue(ctrl);
>   	blk_sync_queue(ctrl->admin_q);
> -	ctrl->fabrics_ops->stop_admin_queue(ctrl);
> +	__nvmf_stop_admin_queue(ctrl);
>   	nvme_cancel_admin_tagset(ctrl);
>   	if (remove)
>   		nvme_unquiesce_admin_queue(ctrl);
> @@ -1447,7 +1550,7 @@ int nvmf_setup_ctrl(struct nvme_ctrl *ctrl, bool new)
>   destroy_admin:
>   	nvme_quiesce_admin_queue(ctrl);
>   	blk_sync_queue(ctrl->admin_q);
> -	ctrl->fabrics_ops->stop_admin_queue(ctrl);
> +	__nvmf_stop_admin_queue(ctrl);
>   	nvme_cancel_admin_tagset(ctrl);
>   	nvmf_destroy_admin_queue(ctrl, new);
>   	return ret;
> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
> index fcea2678094c..0810bc2a9e13 100644
> --- a/drivers/nvme/host/nvme.h
> +++ b/drivers/nvme/host/nvme.h
> @@ -246,6 +246,18 @@ enum nvme_ctrl_flags {
>   
>   struct nvme_fabrics_ops;
>   
> +enum nvme_fabrics_queue_flags {
> +	NVME_FABRICS_Q_ALLOCATED		= 0,
> +	NVME_FABRICS_Q_TR_READY			= 1,
> +	NVME_FABRICS_Q_LIVE			= 2,
> +	NVME_FABRICS_Q_POLLING			= 3,
> +};
> +
> +struct nvme_fabrics_queue {
> +	unsigned long *flags;
> +	struct mutex *queue_lock;
> +};
> +
>   struct nvme_ctrl {
>   	bool comp_seen;
>   	enum nvme_ctrl_state state;
> @@ -253,7 +265,6 @@ struct nvme_ctrl {
>   	spinlock_t lock;
>   	struct mutex scan_lock;
>   	const struct nvme_ctrl_ops *ops;
> -	const struct nvme_fabrics_ops *fabrics_ops;
>   	struct request_queue *admin_q;
>   	struct request_queue *connect_q;
>   	struct request_queue *fabrics_q;
> @@ -342,8 +353,10 @@ struct nvme_ctrl {
>   	struct work_struct ana_work;
>   #endif
>   
> -	struct work_struct	err_work;
> -	struct delayed_work	connect_work;
> +	const struct nvme_fabrics_ops *fabrics_ops;
> +	struct nvme_fabrics_queue *queues;
> +	struct work_struct err_work;
> +	struct delayed_work connect_work;
>   
>   #ifdef CONFIG_NVME_AUTH
>   	struct work_struct dhchap_auth_work;
> diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
> index 1fde65e8c2b5..023316fdc2c6 100644
> --- a/drivers/nvme/host/rdma.c
> +++ b/drivers/nvme/host/rdma.c
> @@ -3,6 +3,7 @@
>    * NVMe over Fabrics RDMA host code.
>    * Copyright (c) 2015-2016 HGST, a Western Digital Company.
>    */
> +#include "linux/gfp_types.h"
>   #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>   #include <linux/module.h>
>   #include <linux/init.h>
> @@ -76,12 +77,6 @@ struct nvme_rdma_request {
>   	bool			use_sig_mr;
>   };
>   
> -enum nvme_rdma_queue_flags {
> -	NVME_RDMA_Q_ALLOCATED		= 0,
> -	NVME_RDMA_Q_LIVE		= 1,
> -	NVME_RDMA_Q_TR_READY		= 2,
> -};
> -
>   struct nvme_rdma_queue {
>   	struct nvme_rdma_qe	*rsp_ring;
>   	int			queue_size;
> @@ -425,7 +420,7 @@ static void nvme_rdma_destroy_queue_ib(struct nvme_rdma_queue *queue)
>   	struct nvme_rdma_device *dev;
>   	struct ib_device *ibdev;
>   
> -	if (!test_and_clear_bit(NVME_RDMA_Q_TR_READY, &queue->flags))
> +	if (!test_and_clear_bit(NVME_FABRICS_Q_TR_READY, &queue->flags))
>   		return;
>   
>   	dev = queue->device;
> @@ -550,7 +545,7 @@ static int nvme_rdma_create_queue_ib(struct nvme_rdma_queue *queue)
>   		}
>   	}
>   
> -	set_bit(NVME_RDMA_Q_TR_READY, &queue->flags);
> +	set_bit(NVME_FABRICS_Q_TR_READY, &queue->flags);
>   
>   	return 0;
>   
> @@ -572,12 +567,17 @@ static int __nvme_rdma_alloc_queue(struct nvme_rdma_ctrl *ctrl,
>   				   struct nvme_rdma_queue *queue)
>   {
>   	struct sockaddr *src_addr = NULL;
> +	struct nvme_fabrics_queue *fqueue;
>   	int ret;
>   
>   	mutex_init(&queue->queue_lock);
>   	queue->ctrl = ctrl;
>   	init_completion(&queue->cm_done);
>   
> +	fqueue = &ctrl->ctrl.queues[nvme_rdma_queue_id(queue)];
> +	fqueue->flags = &queue->flags;
> +	fqueue->queue_lock = &queue->queue_lock;
> +
>   	queue->cm_id = rdma_create_id(&init_net, nvme_rdma_cm_handler, queue,
>   			RDMA_PS_TCP, IB_QPT_RC);
>   	if (IS_ERR(queue->cm_id)) {
> @@ -607,8 +607,6 @@ static int __nvme_rdma_alloc_queue(struct nvme_rdma_ctrl *ctrl,
>   		goto out_destroy_cm_id;
>   	}
>   
> -	set_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags);
> -
>   	return 0;
>   
>   out_destroy_cm_id:
> @@ -622,9 +620,6 @@ static int __nvme_rdma_alloc_queue(struct nvme_rdma_ctrl *ctrl,
>   static void __nvme_rdma_free_queue(struct nvme_rdma_ctrl *ctrl,
>   				   struct nvme_rdma_queue *queue)
>   {
> -	if (!test_and_clear_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags))
> -		return;
> -
>   	rdma_destroy_id(queue->cm_id);
>   	nvme_rdma_destroy_queue_ib(queue);
>   	mutex_destroy(&queue->queue_lock);
> @@ -718,49 +713,18 @@ static void nvme_rdma_free_io_queue(struct nvme_ctrl *nctrl, int qid)
>   
>   static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue)
>   {
> -	mutex_lock(&queue->queue_lock);
> -	if (test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags)) {
> -		rdma_disconnect(queue->cm_id);
> -		ib_drain_qp(queue->qp);
> -	}
> -	mutex_unlock(&queue->queue_lock);
> +	rdma_disconnect(queue->cm_id);
> +	ib_drain_qp(queue->qp);
>   }
>   
> -static int nvme_rdma_start_admin_queue(struct nvme_ctrl *nctrl)
> +static int nvme_rdma_start_admin_queue(struct nvme_ctrl *ctrl)
>   {
> -	struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
> -	struct nvme_rdma_queue *queue = &ctrl->queues[0];
> -	int ret;
> -
> -	ret = nvmf_connect_admin_queue(nctrl);
> -
> -	if (!ret) {
> -		set_bit(NVME_RDMA_Q_LIVE, &queue->flags);
> -	} else {
> -		if (test_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags))
> -			__nvme_rdma_stop_queue(queue);
> -		dev_info(ctrl->ctrl.device,
> -			"failed to connect queue: %d ret=%d\n", 0, ret);
> -	}
> -	return ret;
> +	return nvmf_connect_admin_queue(ctrl);
>   }
>   
> -static int nvme_rdma_start_io_queue(struct nvme_ctrl *nctrl, int idx)
> +static int nvme_rdma_start_io_queue(struct nvme_ctrl *ctrl, int idx)
>   {
> -	struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
> -	struct nvme_rdma_queue *queue = &ctrl->queues[idx];
> -	int ret;
> -
> -	ret = nvmf_connect_io_queue(nctrl, idx);
> -	if (!ret) {
> -		set_bit(NVME_RDMA_Q_LIVE, &queue->flags);
> -	} else {
> -		if (test_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags))
> -			__nvme_rdma_stop_queue(queue);
> -		dev_info(ctrl->ctrl.device,
> -			"failed to connect queue: %d ret=%d\n", idx, ret);
> -	}
> -	return ret;
> +	return nvmf_connect_io_queue(ctrl, idx);
>   }
>   
>   static void nvme_rdma_stop_admin_queue(struct nvme_ctrl *nctrl)
> @@ -1715,7 +1679,7 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
>   	struct nvme_rdma_qe *sqe = &req->sqe;
>   	struct nvme_command *c = nvme_req(rq)->cmd;
>   	struct ib_device *dev;
> -	bool queue_ready = test_bit(NVME_RDMA_Q_LIVE, &queue->flags);
> +	bool queue_ready = test_bit(NVME_FABRICS_Q_LIVE, &queue->flags);
>   	blk_status_t ret;
>   	int err;
>   
> @@ -2027,6 +1991,12 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
>   	if (!ctrl->queues)
>   		goto out_free_ctrl;
>   
> +	ctrl->ctrl.queues = kcalloc(ctrl->ctrl.queue_count,
> +				    sizeof(*ctrl->ctrl.queues),
> +				    GFP_KERNEL);
> +	if (!ctrl->ctrl.queues)
> +		goto out_free_ctrl_queues;
> +
>   	ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_rdma_ctrl_ops,
>   				0 /* no quirks, we're perfect! */);
>   	if (ret)
> @@ -2054,7 +2024,10 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
>   	if (ret > 0)
>   		ret = -EIO;
>   	return ERR_PTR(ret);
> +	kfree(ctrl->queues);
>   out_kfree_queues:
> +	kfree(ctrl->ctrl.queues);
> +out_free_ctrl_queues:
>   	kfree(ctrl->queues);
>   out_free_ctrl:
>   	kfree(ctrl);
> diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
> index 32c4346b7322..dfdf35b32adc 100644
> --- a/drivers/nvme/host/tcp.c
> +++ b/drivers/nvme/host/tcp.c
> @@ -100,12 +100,6 @@ struct nvme_tcp_request {
>   	enum nvme_tcp_send_state state;
>   };
>   
> -enum nvme_tcp_queue_flags {
> -	NVME_TCP_Q_ALLOCATED	= 0,
> -	NVME_TCP_Q_LIVE		= 1,
> -	NVME_TCP_Q_POLLING	= 2,
> -};
> -
>   enum nvme_tcp_recv_state {
>   	NVME_TCP_RECV_PDU = 0,
>   	NVME_TCP_RECV_DATA,
> @@ -903,7 +897,7 @@ static void nvme_tcp_data_ready(struct sock *sk)
>   	read_lock_bh(&sk->sk_callback_lock);
>   	queue = sk->sk_user_data;
>   	if (likely(queue && queue->rd_enabled) &&
> -	    !test_bit(NVME_TCP_Q_POLLING, &queue->flags))
> +	    !test_bit(NVME_FABRICS_Q_POLLING, &queue->flags))
>   		queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work);
>   	read_unlock_bh(&sk->sk_callback_lock);
>   }
> @@ -1454,6 +1448,7 @@ static void nvme_tcp_set_queue_io_cpu(struct nvme_tcp_queue *queue)
>   static int __nvme_tcp_alloc_queue(struct nvme_tcp_ctrl *ctrl,
>   				 struct nvme_tcp_queue *queue)
>   {
> +	struct nvme_fabrics_queue *fqueue;
>   	int ret, rcv_pdu_size;
>   
>   	mutex_init(&queue->queue_lock);
> @@ -1463,6 +1458,10 @@ static int __nvme_tcp_alloc_queue(struct nvme_tcp_ctrl *ctrl,
>   	mutex_init(&queue->send_mutex);
>   	INIT_WORK(&queue->io_work, nvme_tcp_io_work);
>   
> +	fqueue = &ctrl->ctrl.queues[nvme_tcp_queue_id(queue)];
> +	fqueue->flags = &queue->flags;
> +	fqueue->queue_lock = &queue->queue_lock;
> +
>   	ret = sock_create(ctrl->addr.ss_family, SOCK_STREAM,
>   			IPPROTO_TCP, &queue->sock);
>   	if (ret) {
> @@ -1567,7 +1566,6 @@ static int __nvme_tcp_alloc_queue(struct nvme_tcp_ctrl *ctrl,
>   		goto err_init_connect;
>   
>   	queue->rd_enabled = true;
> -	set_bit(NVME_TCP_Q_ALLOCATED, &queue->flags);
>   	nvme_tcp_init_recv_ctx(queue);
>   
>   	write_lock_bh(&queue->sock->sk->sk_callback_lock);
> @@ -1607,9 +1605,6 @@ static void __nvme_tcp_free_queue(struct nvme_tcp_ctrl *ctrl,
>   	struct page *page;
>   	unsigned int noreclaim_flag;
>   
> -	if (!test_and_clear_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
> -		return;
> -
>   	if (queue->hdr_digest || queue->data_digest)
>   		nvme_tcp_free_crypto(queue);
>   
> @@ -1699,40 +1694,14 @@ static void __nvme_tcp_stop_queue(struct nvme_tcp_queue *queue)
>   	cancel_work_sync(&queue->io_work);
>   }
>   
> -static int nvme_tcp_start_admin_queue(struct nvme_ctrl *nctrl)
> +static int nvme_tcp_start_admin_queue(struct nvme_ctrl *ctrl)
>   {
> -	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
> -	struct nvme_tcp_queue *queue = &ctrl->queues[0];
> -	int ret;
> -
> -	ret = nvmf_connect_admin_queue(nctrl);
> -	if (!ret) {
> -		set_bit(NVME_TCP_Q_LIVE, &queue->flags);
> -	} else {
> -		if (test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
> -			__nvme_tcp_stop_queue(queue);
> -		dev_err(nctrl->device,
> -			"failed to connect queue: %d ret=%d\n", 0, ret);
> -	}
> -	return ret;
> +	return nvmf_connect_admin_queue(ctrl);
>   }
>   
> -static int nvme_tcp_start_io_queue(struct nvme_ctrl *nctrl, int qid)
> +static int nvme_tcp_start_io_queue(struct nvme_ctrl *ctrl, int qid)
>   {
> -	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
> -	struct nvme_tcp_queue *queue = &ctrl->queues[qid];
> -	int ret;
> -
> -	ret = nvmf_connect_io_queue(nctrl, qid);
> -	if (!ret) {
> -		set_bit(NVME_TCP_Q_LIVE, &queue->flags);
> -	} else {
> -		if (test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
> -			__nvme_tcp_stop_queue(queue);
> -		dev_err(nctrl->device,
> -			"failed to connect queue: %d ret=%d\n", qid, ret);
> -	}
> -	return ret;
> +	return nvmf_connect_io_queue(ctrl, qid);
>   }
>   
>   static void nvme_tcp_stop_admin_queue(struct nvme_ctrl *nctrl)
> @@ -1740,13 +1709,7 @@ static void nvme_tcp_stop_admin_queue(struct nvme_ctrl *nctrl)
>   	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
>   	struct nvme_tcp_queue *queue = &ctrl->queues[0];
>   
> -	if (!test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
> -		return;
> -
> -	mutex_lock(&queue->queue_lock);
> -	if (test_and_clear_bit(NVME_TCP_Q_LIVE, &queue->flags))
> -		__nvme_tcp_stop_queue(queue);
> -	mutex_unlock(&queue->queue_lock);
> +	__nvme_tcp_stop_queue(queue);
>   }
>   
>   static void nvme_tcp_stop_io_queue(struct nvme_ctrl *nctrl, int qid)
> @@ -1754,13 +1717,7 @@ static void nvme_tcp_stop_io_queue(struct nvme_ctrl *nctrl, int qid)
>   	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
>   	struct nvme_tcp_queue *queue = &ctrl->queues[qid];
>   
> -	if (!test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
> -		return;
> -
> -	mutex_lock(&queue->queue_lock);
> -	if (test_and_clear_bit(NVME_TCP_Q_LIVE, &queue->flags))
> -		__nvme_tcp_stop_queue(queue);
> -	mutex_unlock(&queue->queue_lock);
> +	__nvme_tcp_stop_queue(queue);
>   }
>   
>   static int nvme_tcp_alloc_admin_tag_set(struct nvme_ctrl *ctrl)
> @@ -1843,6 +1800,7 @@ static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
>   
>   	nvmf_free_options(nctrl->opts);
>   free_ctrl:
> +	kfree(ctrl->ctrl.queues);
>   	kfree(ctrl->queues);
>   	kfree(ctrl);
>   }
> @@ -2043,7 +2001,7 @@ static blk_status_t nvme_tcp_queue_rq(struct blk_mq_hw_ctx *hctx,
>   	struct nvme_tcp_queue *queue = hctx->driver_data;
>   	struct request *rq = bd->rq;
>   	struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
> -	bool queue_ready = test_bit(NVME_TCP_Q_LIVE, &queue->flags);
> +	bool queue_ready = test_bit(NVME_FABRICS_Q_LIVE, &queue->flags);
>   	blk_status_t ret;
>   
>   	if (!nvme_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
> @@ -2108,14 +2066,14 @@ static int nvme_tcp_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
>   	struct nvme_tcp_queue *queue = hctx->driver_data;
>   	struct sock *sk = queue->sock->sk;
>   
> -	if (!test_bit(NVME_TCP_Q_LIVE, &queue->flags))
> +	if (!test_bit(NVME_FABRICS_Q_LIVE, &queue->flags))
>   		return 0;
>   
> -	set_bit(NVME_TCP_Q_POLLING, &queue->flags);
> +	set_bit(NVME_FABRICS_Q_POLLING, &queue->flags);
>   	if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue))
>   		sk_busy_loop(sk, true);
>   	nvme_tcp_try_recv(queue);
> -	clear_bit(NVME_TCP_Q_POLLING, &queue->flags);
> +	clear_bit(NVME_FABRICS_Q_POLLING, &queue->flags);
>   	return queue->nr_cqe;
>   }
>   
> @@ -2129,7 +2087,7 @@ static int nvme_tcp_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
>   
>   	mutex_lock(&queue->queue_lock);
>   
> -	if (!test_bit(NVME_TCP_Q_LIVE, &queue->flags))
> +	if (!test_bit(NVME_CTRL_LIVE, &queue->flags))
>   		goto done;
>   	ret = kernel_getsockname(queue->sock, (struct sockaddr *)&src_addr);
>   	if (ret > 0) {
> @@ -2282,6 +2240,13 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
>   		ret = -ENOMEM;
>   		goto out_free_ctrl;
>   	}
> +	ctrl->ctrl.queues = kcalloc(ctrl->ctrl.queue_count,
> +				    sizeof(*ctrl->ctrl.queues),
> +				    GFP_KERNEL);
> +	if (!ctrl->ctrl.queues) {
> +		ret = -ENOMEM;
> +		goto out_free_ctrl_queue;
> +	}
>   
>   	ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_tcp_ctrl_ops, 0);
>   	if (ret)
> @@ -2313,6 +2278,8 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
>   		ret = -EIO;
>   	return ERR_PTR(ret);
>   out_kfree_queues:
> +	kfree(ctrl->ctrl.queues);
> +out_free_ctrl_queue:
>   	kfree(ctrl->queues);
>   out_free_ctrl:
>   	kfree(ctrl);



More information about the Linux-nvme mailing list