All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005)
@ 2018-11-14 18:25 Sagi Grimberg
  2018-11-14 18:25 ` [PATCH v3 1/4] nvmet: support fabrics sq flow control Sagi Grimberg
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-14 18:25 UTC (permalink / raw)


Technical proposal 8005 adds a mode where sq head pointer updates can be
omitted based on the controller capability. When a host connects to
a controller it can request it to turn off SQ flow control (e.g. omit
sq head pointer updates). If the controller supports it, it returns
0xffff sq_head in the connect capsule response cqe.

Supporting this mode in nvmet means we can skip an atomic update in
the data path so we don't mind. Note that the host side still ignores
sq head pointer updates and flow controls based on completion accounting
alone. This TP at least gives us a mode that it is compliant.

When a controller implementation comes along that relies on sq head pointer
updates to flow control the host, we will probably need to address that, but
until then, we can start by micro-optimizing nvmet.

nvmet also exposes this capability in transport requirement field in the
discovery lof entry for host implementations that may want to talk to a
controller based on this capability, we use it to have our host to connect
with sq flow control disabled if the controller supports it, otherwise the
host connects normally as its doing today.

A nvme-cli patch is also attached sent together with the series.

Changes from v2:
- fix nested if condition in nvmet_update_sq_head
- introduce meaningful define for fabrics secure channel mask
- added explicit disable_sqflow flag in nvme-cli

Changes from v1:
- changed define names (disable_sqflow) as hannes suggested
- changed the mode to not be used by default and keep the existing
  behavior, the host will only try to disable sq flow control when
  userspace asked it to.
- added nvme-cli patch that adds --disable-sqflow if the controller
  exposes support.

Sagi Grimberg (4):
  nvmet: support fabrics sq flow control
  nvmet: don't override treq upon modification.
  nvmet: expose support for fabrics SQ flow control disable in treq
  nvme: disable fabrics SQ flow control when asked by the user

 drivers/nvme/host/fabrics.c       | 13 +++++++++++++
 drivers/nvme/host/fabrics.h       |  2 ++
 drivers/nvme/target/configfs.c    | 12 ++++++++----
 drivers/nvme/target/core.c        | 21 ++++++++++++++-------
 drivers/nvme/target/fabrics-cmd.c |  8 +++++++-
 drivers/nvme/target/nvmet.h       |  5 ++++-
 include/linux/nvme.h              | 11 ++++++++---
 7 files changed, 56 insertions(+), 16 deletions(-)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 1/4] nvmet: support fabrics sq flow control
  2018-11-14 18:25 [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005) Sagi Grimberg
@ 2018-11-14 18:25 ` Sagi Grimberg
  2018-11-15 11:40   ` Christoph Hellwig
  2018-11-14 18:25 ` [PATCH v3 2/4] nvmet: don't override treq upon modification Sagi Grimberg
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-14 18:25 UTC (permalink / raw)


Technical proposal 8005 "fabrics SQ flow control" introduces a mode
where a host and controller agree to omit sq_head pointer updates
when sending nvme completions.

In case the host indicated desire to operate in this mode (connect attribute)
the controller will return back a connect completion with sq_head value
of 0xffff as indication that it will omit sq_head pointer updates.

This mode saves us an atomic update in the I/O path.

Reviewed-by: Hannes Reinecke <hare at suse.com>
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/target/core.c        | 21 ++++++++++++++-------
 drivers/nvme/target/fabrics-cmd.c |  8 +++++++-
 drivers/nvme/target/nvmet.h       |  3 ++-
 include/linux/nvme.h              |  4 ++++
 4 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index e3e158ff207a..9240b0a245a1 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -597,15 +597,12 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
 	return ns;
 }
 
-static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
+static void nvmet_update_sq_head(struct nvmet_req *req)
 {
 	u32 old_sqhd, new_sqhd;
 	u16 sqhd;
 
-	if (status)
-		nvmet_set_status(req, status);
-
-	if (req->sq->size) {
+	if (!req->sq->sqhd_disabled && req->sq->size) {
 		do {
 			old_sqhd = req->sq->sqhd;
 			new_sqhd = (old_sqhd + 1) % req->sq->size;
@@ -614,9 +611,18 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 	}
 	sqhd = req->sq->sqhd & 0x0000FFFF;
 	req->rsp->sq_head = cpu_to_le16(sqhd);
+}
+
+static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
+{
+	if (status)
+		nvmet_set_status(req, status);
+
 	req->rsp->sq_id = cpu_to_le16(req->sq->qid);
 	req->rsp->command_id = req->cmd->common.command_id;
 
+	nvmet_update_sq_head(req);
+
 	if (req->ns)
 		nvmet_put_namespace(req->ns);
 	req->ops->queue_response(req);
@@ -639,9 +645,10 @@ void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq,
 }
 
 void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq,
-		u16 qid, u16 size)
+		u16 qid, u16 size, bool sqhd_disabled)
 {
-	sq->sqhd = 0;
+	sq->sqhd_disabled = sqhd_disabled;
+	sq->sqhd = sq->sqhd_disabled ? 0xffff : 0;
 	sq->qid = qid;
 	sq->size = size;
 
diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index d84ae004cb85..1f05d8507e35 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -114,7 +114,9 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
 
 	/* note: convert queue size from 0's-based value to 1's-based value */
 	nvmet_cq_setup(ctrl, req->cq, qid, sqsize + 1);
-	nvmet_sq_setup(ctrl, req->sq, qid, sqsize + 1);
+	nvmet_sq_setup(ctrl, req->sq, qid, sqsize + 1,
+			!!(c->cattr & NVME_CONNECT_DISABLE_SQFLOW));
+
 	return 0;
 }
 
@@ -173,6 +175,8 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
 	kfree(d);
 complete:
 	nvmet_req_complete(req, status);
+	if (req->sq->sqhd_disabled)
+		req->sq->sqhd = 0;
 }
 
 static void nvmet_execute_io_connect(struct nvmet_req *req)
@@ -229,6 +233,8 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
 	kfree(d);
 complete:
 	nvmet_req_complete(req, status);
+	if (req->sq->sqhd_disabled)
+		req->sq->sqhd = 0;
 	return;
 
 out_ctrl_put:
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 31474940e373..613a37683eae 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -106,6 +106,7 @@ struct nvmet_sq {
 	u16			qid;
 	u16			size;
 	u32			sqhd;
+	bool			sqhd_disabled;
 	struct completion	free_done;
 	struct completion	confirm_done;
 };
@@ -386,7 +387,7 @@ void nvmet_execute_keep_alive(struct nvmet_req *req);
 void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid,
 		u16 size);
 void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, u16 qid,
-		u16 size);
+		u16 size, bool sqhd_disabled);
 void nvmet_sq_destroy(struct nvmet_sq *sq);
 int nvmet_sq_init(struct nvmet_sq *sq);
 
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 77d320d32ee5..e7d731776f62 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -1044,6 +1044,10 @@ struct nvmf_disc_rsp_page_hdr {
 	struct nvmf_disc_rsp_page_entry entries[0];
 };
 
+enum {
+	NVME_CONNECT_DISABLE_SQFLOW	= (1 << 2),
+};
+
 struct nvmf_connect_command {
 	__u8		opcode;
 	__u8		resv1;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 2/4] nvmet: don't override treq upon modification.
  2018-11-14 18:25 [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005) Sagi Grimberg
  2018-11-14 18:25 ` [PATCH v3 1/4] nvmet: support fabrics sq flow control Sagi Grimberg
@ 2018-11-14 18:25 ` Sagi Grimberg
  2018-11-15 11:40   ` Christoph Hellwig
  2018-11-14 18:25 ` [PATCH v3 3/4] nvmet: expose support for fabrics SQ flow control disable in treq Sagi Grimberg
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-14 18:25 UTC (permalink / raw)


Only override the allowed parts of it.

Reviewed-by: Hannes Reinecke <hare at suse.com>
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/target/configfs.c | 11 +++++++----
 drivers/nvme/target/nvmet.h    |  2 ++
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index d37fd7713bbc..a98ab935b537 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -153,7 +153,8 @@ CONFIGFS_ATTR(nvmet_, addr_traddr);
 static ssize_t nvmet_addr_treq_show(struct config_item *item,
 		char *page)
 {
-	switch (to_nvmet_port(item)->disc_addr.treq) {
+	switch (to_nvmet_port(item)->disc_addr.treq &
+		NVMET_TREQ_SECURE_CHANNEL_MASK) {
 	case NVMF_TREQ_NOT_SPECIFIED:
 		return sprintf(page, "not specified\n");
 	case NVMF_TREQ_REQUIRED:
@@ -169,6 +170,7 @@ static ssize_t nvmet_addr_treq_store(struct config_item *item,
 		const char *page, size_t count)
 {
 	struct nvmet_port *port = to_nvmet_port(item);
+	u8 treq = port->disc_addr.treq & ~NVMET_TREQ_SECURE_CHANNEL_MASK;
 
 	if (port->enabled) {
 		pr_err("Cannot modify address while enabled\n");
@@ -177,15 +179,16 @@ static ssize_t nvmet_addr_treq_store(struct config_item *item,
 	}
 
 	if (sysfs_streq(page, "not specified")) {
-		port->disc_addr.treq = NVMF_TREQ_NOT_SPECIFIED;
+		treq |= NVMF_TREQ_NOT_SPECIFIED;
 	} else if (sysfs_streq(page, "required")) {
-		port->disc_addr.treq = NVMF_TREQ_REQUIRED;
+		treq |= NVMF_TREQ_REQUIRED;
 	} else if (sysfs_streq(page, "not required")) {
-		port->disc_addr.treq = NVMF_TREQ_NOT_REQUIRED;
+		treq |= NVMF_TREQ_NOT_REQUIRED;
 	} else {
 		pr_err("Invalid value '%s' for treq\n", page);
 		return -EINVAL;
 	}
+	port->disc_addr.treq = treq;
 
 	return count;
 }
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 613a37683eae..abc603fa725d 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -56,6 +56,8 @@
 #define IPO_IATTR_CONNECT_SQE(x)	\
 	(cpu_to_le32(offsetof(struct nvmf_connect_command, x)))
 
+#define NVMET_TREQ_SECURE_CHANNEL_MASK 0x3
+
 struct nvmet_ns {
 	struct list_head	dev_link;
 	struct percpu_ref	ref;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 3/4] nvmet: expose support for fabrics SQ flow control disable in treq
  2018-11-14 18:25 [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005) Sagi Grimberg
  2018-11-14 18:25 ` [PATCH v3 1/4] nvmet: support fabrics sq flow control Sagi Grimberg
  2018-11-14 18:25 ` [PATCH v3 2/4] nvmet: don't override treq upon modification Sagi Grimberg
@ 2018-11-14 18:25 ` Sagi Grimberg
  2018-11-14 18:25 ` [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user Sagi Grimberg
  2018-11-14 18:25 ` [PATCH v3 nvme-cli 5/4] fabrics: support fabrics sq flow control disable Sagi Grimberg
  4 siblings, 0 replies; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-14 18:25 UTC (permalink / raw)


Technical Proposal introduces an indication for SQ flow control
disable support. Expose it since we are able to operate in this mode.

Reviewed-by: Hannes Reinecke <hare at suse.com>
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/target/configfs.c | 1 +
 include/linux/nvme.h           | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index a98ab935b537..c2df205096ec 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1214,6 +1214,7 @@ static struct config_group *nvmet_ports_make(struct config_group *group,
 	port->inline_data_size = -1;	/* < 0 == let the transport choose */
 
 	port->disc_addr.portid = cpu_to_le16(portid);
+	port->disc_addr.treq = NVMF_TREQ_DISABLE_SQFLOW;
 	config_group_init_type_name(&port->group, name, &nvmet_port_type);
 
 	config_group_init_type_name(&port->subsys_group,
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index e7d731776f62..4a560ea04d7c 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -58,9 +58,10 @@ enum {
 
 /* Transport Requirements codes for Discovery Log Page entry TREQ field */
 enum {
-	NVMF_TREQ_NOT_SPECIFIED	= 0,	/* Not specified */
-	NVMF_TREQ_REQUIRED	= 1,	/* Required */
-	NVMF_TREQ_NOT_REQUIRED	= 2,	/* Not Required */
+	NVMF_TREQ_NOT_SPECIFIED	= 0,		/* Not specified */
+	NVMF_TREQ_REQUIRED	= 1,		/* Required */
+	NVMF_TREQ_NOT_REQUIRED	= 2,		/* Not Required */
+	NVMF_TREQ_DISABLE_SQFLOW = (1 << 2),	/* Supports SQ flow control disable */
 };
 
 /* RDMA QP Service Type codes for Discovery Log Page entry TSAS
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user
  2018-11-14 18:25 [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005) Sagi Grimberg
                   ` (2 preceding siblings ...)
  2018-11-14 18:25 ` [PATCH v3 3/4] nvmet: expose support for fabrics SQ flow control disable in treq Sagi Grimberg
@ 2018-11-14 18:25 ` Sagi Grimberg
  2018-11-15 11:40   ` Christoph Hellwig
  2018-11-14 18:25 ` [PATCH v3 nvme-cli 5/4] fabrics: support fabrics sq flow control disable Sagi Grimberg
  4 siblings, 1 reply; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-14 18:25 UTC (permalink / raw)


As for now, we don't care about sq_head pointer updates anyway, so
at least allow the controller to micro-optimize by omiting this update.

Note that we will probably need to support it when a controller
that requires this comes along.

Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 drivers/nvme/host/fabrics.c | 13 +++++++++++++
 drivers/nvme/host/fabrics.h |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index bd0969db6225..b78d1a674abc 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -392,6 +392,9 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
 	cmd.connect.kato = ctrl->opts->discovery_nqn ? 0 :
 		cpu_to_le32((ctrl->kato + NVME_KATO_GRACE) * 1000);
 
+	if (ctrl->opts->disable_sqflow)
+		cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
+
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -451,6 +454,9 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
 	cmd.connect.qid = cpu_to_le16(qid);
 	cmd.connect.sqsize = cpu_to_le16(ctrl->sqsize);
 
+	if (ctrl->opts->disable_sqflow)
+		cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
+
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -607,6 +613,7 @@ static const match_table_t opt_tokens = {
 	{ NVMF_OPT_HOST_TRADDR,		"host_traddr=%s"	},
 	{ NVMF_OPT_HOST_ID,		"hostid=%s"		},
 	{ NVMF_OPT_DUP_CONNECT,		"duplicate_connect"	},
+	{ NVMF_OPT_DISABLE_SQFLOW,	"disable_sqflow"	},
 	{ NVMF_OPT_ERR,			NULL			}
 };
 
@@ -817,6 +824,9 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
 		case NVMF_OPT_DUP_CONNECT:
 			opts->duplicate_connect = true;
 			break;
+		case NVMF_OPT_DISABLE_SQFLOW:
+			opts->disable_sqflow = true;
+			break;
 		default:
 			pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
 				p);
@@ -901,6 +911,9 @@ EXPORT_SYMBOL_GPL(nvmf_ip_options_match);
 static int nvmf_check_allowed_opts(struct nvmf_ctrl_options *opts,
 		unsigned int allowed_opts)
 {
+	/* fabrics parameter, allowed regardless of the transport */
+	allowed_opts |= NVMF_OPT_DISABLE_SQFLOW;
+
 	if (opts->mask & ~allowed_opts) {
 		int i;
 
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index 6ea6275f332a..ecd9a006a091 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -58,6 +58,7 @@ enum {
 	NVMF_OPT_CTRL_LOSS_TMO	= 1 << 11,
 	NVMF_OPT_HOST_ID	= 1 << 12,
 	NVMF_OPT_DUP_CONNECT	= 1 << 13,
+	NVMF_OPT_DISABLE_SQFLOW = 1 << 14,
 };
 
 /**
@@ -101,6 +102,7 @@ struct nvmf_ctrl_options {
 	unsigned int		kato;
 	struct nvmf_host	*host;
 	int			max_reconnects;
+	bool			disable_sqflow;
 };
 
 /*
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 nvme-cli 5/4] fabrics: support fabrics sq flow control disable
  2018-11-14 18:25 [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005) Sagi Grimberg
                   ` (3 preceding siblings ...)
  2018-11-14 18:25 ` [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user Sagi Grimberg
@ 2018-11-14 18:25 ` Sagi Grimberg
  4 siblings, 0 replies; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-14 18:25 UTC (permalink / raw)


If the discovery log entry indicates that the subsystem supports
disabling sq flow control, we ask the host to connect and disable
sq flow control (omit sq_head pointer updates). Also add an option
to explicitly ask for disable_sqflow.

Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
 fabrics.c    | 15 ++++++++++++++-
 linux/nvme.h |  7 ++++---
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/fabrics.c b/fabrics.c
index 711a755a79e1..f6b060607b26 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -60,6 +60,7 @@ static struct config {
 	char *raw;
 	char *device;
 	int  duplicate_connect;
+	int  disable_sqflow;
 } cfg = { NULL };
 
 #define BUF_SIZE		4096
@@ -129,6 +130,8 @@ static const char * const treqs[] = {
 	[NVMF_TREQ_NOT_SPECIFIED]	= "not specified",
 	[NVMF_TREQ_REQUIRED]		= "required",
 	[NVMF_TREQ_NOT_REQUIRED]	= "not required",
+	[NVMF_TREQ_DISABLE_SQFLOW]	= "not specified, "
+					  "sq flow control disable supported",
 };
 
 static inline const char *treq_str(__u8 treq)
@@ -595,7 +598,9 @@ static int build_options(char *argstr, int max_len)
 	    add_int_argument(&argstr, &max_len, "ctrl_loss_tmo",
 				cfg.ctrl_loss_tmo) ||
 	    add_bool_argument(&argstr, &max_len, "duplicate_connect",
-				cfg.duplicate_connect))
+				cfg.duplicate_connect) ||
+	    add_bool_argument(&argstr, &max_len, "disable_sqflow",
+				cfg.disable_sqflow))
 		return -EINVAL;
 
 	return 0;
@@ -732,6 +737,13 @@ static int connect_ctrl(struct nvmf_disc_rsp_page_entry *e)
 		return -EINVAL;
 	}
 
+	if (e->treq & NVMF_TREQ_DISABLE_SQFLOW) {
+		len = sprintf(p, ",disable_sqflow");
+		if (len < 0)
+			return -EINVAL;
+		p += len;
+	}
+
 	if (discover)
 		return do_discover(argstr, true);
 	else
@@ -935,6 +947,7 @@ int connect(const char *desc, int argc, char **argv)
 		{"reconnect-delay", 'c', "LIST", CFG_INT, &cfg.reconnect_delay, required_argument, "reconnect timeout period in seconds" },
 		{"ctrl-loss-tmo",   'l', "LIST", CFG_INT, &cfg.ctrl_loss_tmo,   required_argument, "controller loss timeout period in seconds" },
 		{"duplicate_connect", 'D', "", CFG_NONE, &cfg.duplicate_connect, no_argument, "allow duplicate connections between same transport host and subsystem port" },
+		{"disable_sqflow", 'd', "", CFG_NONE, &cfg.disable_sqflow, no_argument, "disable controller sq flow control (default false)" },
 		{NULL},
 	};
 
diff --git a/linux/nvme.h b/linux/nvme.h
index 1ad970a4c89a..a6a44b066267 100644
--- a/linux/nvme.h
+++ b/linux/nvme.h
@@ -58,9 +58,10 @@ enum {
 
 /* Transport Requirements codes for Discovery Log Page entry TREQ field */
 enum {
-	NVMF_TREQ_NOT_SPECIFIED	= 0,	/* Not specified */
-	NVMF_TREQ_REQUIRED	= 1,	/* Required */
-	NVMF_TREQ_NOT_REQUIRED	= 2,	/* Not Required */
+	NVMF_TREQ_NOT_SPECIFIED	= 0,		/* Not specified */
+	NVMF_TREQ_REQUIRED	= 1,		/* Required */
+	NVMF_TREQ_NOT_REQUIRED	= 2,		/* Not Required */
+	NVMF_TREQ_DISABLE_SQFLOW = (1 << 2),	/* SQ flow control disable supported */
 };
 
 /* RDMA QP Service Type codes for Discovery Log Page entry TSAS
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 1/4] nvmet: support fabrics sq flow control
  2018-11-14 18:25 ` [PATCH v3 1/4] nvmet: support fabrics sq flow control Sagi Grimberg
@ 2018-11-15 11:40   ` Christoph Hellwig
  2018-11-15 17:31     ` Sagi Grimberg
  0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2018-11-15 11:40 UTC (permalink / raw)


>  complete:
>  	nvmet_req_complete(req, status);
> +	if (req->sq->sqhd_disabled)
> +		req->sq->sqhd = 0;

We drop the sq ref in nvmet_req_complete, so this introduces a
use-after-free.  What about this variant instead:

diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index e3e158ff207a..74e253eb873f 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -597,25 +597,29 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
 	return ns;
 }
 
-static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
+static void nvmet_update_sq_head(struct nvmet_req *req)
 {
-	u32 old_sqhd, new_sqhd;
-	u16 sqhd;
-
-	if (status)
-		nvmet_set_status(req, status);
-
 	if (req->sq->size) {
+		u32 old_sqhd, new_sqhd;
+
 		do {
 			old_sqhd = req->sq->sqhd;
 			new_sqhd = (old_sqhd + 1) % req->sq->size;
 		} while (cmpxchg(&req->sq->sqhd, old_sqhd, new_sqhd) !=
 					old_sqhd);
 	}
-	sqhd = req->sq->sqhd & 0x0000FFFF;
-	req->rsp->sq_head = cpu_to_le16(sqhd);
+
+	req->rsp->sq_head = cpu_to_le16(req->sq->sqhd & 0x0000FFFF);
+}
+
+static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
+{
+	if (!req->sq->sqhd_disabled)
+		nvmet_update_sq_head(req);
 	req->rsp->sq_id = cpu_to_le16(req->sq->qid);
 	req->rsp->command_id = req->cmd->common.command_id;
+	if (status)
+		nvmet_set_status(req, status);
 
 	if (req->ns)
 		nvmet_put_namespace(req->ns);
@@ -765,6 +769,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
 	req->sg_cnt = 0;
 	req->transfer_len = 0;
 	req->rsp->status = 0;
+	req->rsp->sq_head = 0;
 	req->ns = NULL;
 
 	/* no support for fused commands yet */
diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
index d84ae004cb85..328ae46d8344 100644
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -115,6 +115,12 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
 	/* note: convert queue size from 0's-based value to 1's-based value */
 	nvmet_cq_setup(ctrl, req->cq, qid, sqsize + 1);
 	nvmet_sq_setup(ctrl, req->sq, qid, sqsize + 1);
+
+	if (c->cattr & NVME_CONNECT_DISABLE_SQFLOW) {
+		req->sq->sqhd_disabled = true;
+		req->rsp->sq_head = cpu_to_le16(0xffff);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 31474940e373..ab8e68966e73 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -106,6 +106,7 @@ struct nvmet_sq {
 	u16			qid;
 	u16			size;
 	u32			sqhd;
+	bool			sqhd_disabled;
 	struct completion	free_done;
 	struct completion	confirm_done;
 };
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 77d320d32ee5..e7d731776f62 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -1044,6 +1044,10 @@ struct nvmf_disc_rsp_page_hdr {
 	struct nvmf_disc_rsp_page_entry entries[0];
 };
 
+enum {
+	NVME_CONNECT_DISABLE_SQFLOW	= (1 << 2),
+};
+
 struct nvmf_connect_command {
 	__u8		opcode;
 	__u8		resv1;

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v3 2/4] nvmet: don't override treq upon modification.
  2018-11-14 18:25 ` [PATCH v3 2/4] nvmet: don't override treq upon modification Sagi Grimberg
@ 2018-11-15 11:40   ` Christoph Hellwig
  2018-11-15 17:32     ` Sagi Grimberg
  0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2018-11-15 11:40 UTC (permalink / raw)


> index 613a37683eae..abc603fa725d 100644
> --- a/drivers/nvme/target/nvmet.h
> +++ b/drivers/nvme/target/nvmet.h
> @@ -56,6 +56,8 @@
>  #define IPO_IATTR_CONNECT_SQE(x)	\
>  	(cpu_to_le32(offsetof(struct nvmf_connect_command, x)))
>  
> +#define NVMET_TREQ_SECURE_CHANNEL_MASK 0x3

Shouldn't this go with the other NVMET_TREQ_ symbols in the enum?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user
  2018-11-14 18:25 ` [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user Sagi Grimberg
@ 2018-11-15 11:40   ` Christoph Hellwig
  2018-11-15 17:33     ` Sagi Grimberg
  0 siblings, 1 reply; 12+ messages in thread
From: Christoph Hellwig @ 2018-11-15 11:40 UTC (permalink / raw)


> +	/* fabrics parameter, allowed regardless of the transport */
> +	allowed_opts |= NVMF_OPT_DISABLE_SQFLOW;

This should got into NVMF_ALLOWED_OPTS instead.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 1/4] nvmet: support fabrics sq flow control
  2018-11-15 11:40   ` Christoph Hellwig
@ 2018-11-15 17:31     ` Sagi Grimberg
  0 siblings, 0 replies; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-15 17:31 UTC (permalink / raw)



> We drop the sq ref in nvmet_req_complete, so this introduces a
> use-after-free.  What about this variant instead:

That is definitely better. I'll give it a test drive.

> 
> diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
> index e3e158ff207a..74e253eb873f 100644
> --- a/drivers/nvme/target/core.c
> +++ b/drivers/nvme/target/core.c
> @@ -597,25 +597,29 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
>   	return ns;
>   }
>   
> -static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
> +static void nvmet_update_sq_head(struct nvmet_req *req)
>   {
> -	u32 old_sqhd, new_sqhd;
> -	u16 sqhd;
> -
> -	if (status)
> -		nvmet_set_status(req, status);
> -
>   	if (req->sq->size) {
> +		u32 old_sqhd, new_sqhd;
> +
>   		do {
>   			old_sqhd = req->sq->sqhd;
>   			new_sqhd = (old_sqhd + 1) % req->sq->size;
>   		} while (cmpxchg(&req->sq->sqhd, old_sqhd, new_sqhd) !=
>   					old_sqhd);
>   	}
> -	sqhd = req->sq->sqhd & 0x0000FFFF;
> -	req->rsp->sq_head = cpu_to_le16(sqhd);
> +
> +	req->rsp->sq_head = cpu_to_le16(req->sq->sqhd & 0x0000FFFF);
> +}
> +
> +static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
> +{
> +	if (!req->sq->sqhd_disabled)
> +		nvmet_update_sq_head(req);
>   	req->rsp->sq_id = cpu_to_le16(req->sq->qid);
>   	req->rsp->command_id = req->cmd->common.command_id;
> +	if (status)
> +		nvmet_set_status(req, status);
>   
>   	if (req->ns)
>   		nvmet_put_namespace(req->ns);
> @@ -765,6 +769,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
>   	req->sg_cnt = 0;
>   	req->transfer_len = 0;
>   	req->rsp->status = 0;
> +	req->rsp->sq_head = 0;
>   	req->ns = NULL;
>   
>   	/* no support for fused commands yet */
> diff --git a/drivers/nvme/target/fabrics-cmd.c b/drivers/nvme/target/fabrics-cmd.c
> index d84ae004cb85..328ae46d8344 100644
> --- a/drivers/nvme/target/fabrics-cmd.c
> +++ b/drivers/nvme/target/fabrics-cmd.c
> @@ -115,6 +115,12 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
>   	/* note: convert queue size from 0's-based value to 1's-based value */
>   	nvmet_cq_setup(ctrl, req->cq, qid, sqsize + 1);
>   	nvmet_sq_setup(ctrl, req->sq, qid, sqsize + 1);
> +
> +	if (c->cattr & NVME_CONNECT_DISABLE_SQFLOW) {
> +		req->sq->sqhd_disabled = true;
> +		req->rsp->sq_head = cpu_to_le16(0xffff);
> +	}
> +
>   	return 0;
>   }
>   
> diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
> index 31474940e373..ab8e68966e73 100644
> --- a/drivers/nvme/target/nvmet.h
> +++ b/drivers/nvme/target/nvmet.h
> @@ -106,6 +106,7 @@ struct nvmet_sq {
>   	u16			qid;
>   	u16			size;
>   	u32			sqhd;
> +	bool			sqhd_disabled;
>   	struct completion	free_done;
>   	struct completion	confirm_done;
>   };
> diff --git a/include/linux/nvme.h b/include/linux/nvme.h
> index 77d320d32ee5..e7d731776f62 100644
> --- a/include/linux/nvme.h
> +++ b/include/linux/nvme.h
> @@ -1044,6 +1044,10 @@ struct nvmf_disc_rsp_page_hdr {
>   	struct nvmf_disc_rsp_page_entry entries[0];
>   };
>   
> +enum {
> +	NVME_CONNECT_DISABLE_SQFLOW	= (1 << 2),
> +};
> +
>   struct nvmf_connect_command {
>   	__u8		opcode;
>   	__u8		resv1;
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 2/4] nvmet: don't override treq upon modification.
  2018-11-15 11:40   ` Christoph Hellwig
@ 2018-11-15 17:32     ` Sagi Grimberg
  0 siblings, 0 replies; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-15 17:32 UTC (permalink / raw)



>> index 613a37683eae..abc603fa725d 100644
>> --- a/drivers/nvme/target/nvmet.h
>> +++ b/drivers/nvme/target/nvmet.h
>> @@ -56,6 +56,8 @@
>>   #define IPO_IATTR_CONNECT_SQE(x)	\
>>   	(cpu_to_le32(offsetof(struct nvmf_connect_command, x)))
>>   
>> +#define NVMET_TREQ_SECURE_CHANNEL_MASK 0x3
> 
> Shouldn't this go with the other NVMET_TREQ_ symbols in the enum?

You mean NVME_TREQ_ enum in nvme.h, I can place it there, but probably
still as a define as it is a mask and not an enumeration.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user
  2018-11-15 11:40   ` Christoph Hellwig
@ 2018-11-15 17:33     ` Sagi Grimberg
  0 siblings, 0 replies; 12+ messages in thread
From: Sagi Grimberg @ 2018-11-15 17:33 UTC (permalink / raw)



>> +	/* fabrics parameter, allowed regardless of the transport */
>> +	allowed_opts |= NVMF_OPT_DISABLE_SQFLOW;
> 
> This should got into NVMF_ALLOWED_OPTS instead.

Agreed.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-11-15 17:33 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-14 18:25 [PATCH v3 0/4] Support SQ flow control disabled mode (TP 8005) Sagi Grimberg
2018-11-14 18:25 ` [PATCH v3 1/4] nvmet: support fabrics sq flow control Sagi Grimberg
2018-11-15 11:40   ` Christoph Hellwig
2018-11-15 17:31     ` Sagi Grimberg
2018-11-14 18:25 ` [PATCH v3 2/4] nvmet: don't override treq upon modification Sagi Grimberg
2018-11-15 11:40   ` Christoph Hellwig
2018-11-15 17:32     ` Sagi Grimberg
2018-11-14 18:25 ` [PATCH v3 3/4] nvmet: expose support for fabrics SQ flow control disable in treq Sagi Grimberg
2018-11-14 18:25 ` [PATCH v3 4/4] nvme: disable fabrics SQ flow control when asked by the user Sagi Grimberg
2018-11-15 11:40   ` Christoph Hellwig
2018-11-15 17:33     ` Sagi Grimberg
2018-11-14 18:25 ` [PATCH v3 nvme-cli 5/4] fabrics: support fabrics sq flow control disable Sagi Grimberg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.