Skip to contentSkip to conversation

nvme 4.17 patch series

PATCH New Keith Busch 2 participants 15 messages Apr 12, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover nvme 4.17 patch series

This series merges cleanly with linux-block/for-linus.

Arnd Bergmann (1):
nvme: target: fix buffer overflow

Daniel Verkamp (1):
nvmet: fix space padding in serial number

James Smart (1):
nvme: expand nvmf_check_if_ready checks

Johannes Thumshirn (2):
nvme: unexport nvme_start_keep_alive
nvme: don't send keep-alives to the discovery controller

Keith Busch (4):
nvme-pci: Skip queue deletion if there are no queues
nvme-pci: Remove unused queue parameter
nvme-pci: Separate IO and admin queue IRQ vectors
nvme: Use admin command effects for admin commands

Matias Bj?rling (1):
nvme: enforce 64bit offset for nvme_get_log_ext fn

Max Gurtovoy (1):
nvme: check return value of init_srcu_struct function

Ming Lei (1):
nvme-loop: fix kernel oops in case of unhandled command

Rodrigo R. Galvao (1):
nvmet: Fix nvmet_execute_write_zeroes sector count

 drivers/nvme/host/core.c        | 33 ++++++++++------
 drivers/nvme/host/fabrics.c     | 83 ++++++++++++++++++++++++++++++++++++++++-
 drivers/nvme/host/fabrics.h     | 33 +---------------
 drivers/nvme/host/fc.c          | 12 ++----
 drivers/nvme/host/nvme.h        |  4 +-
 drivers/nvme/host/pci.c         | 35 ++++++++++-------
 drivers/nvme/host/rdma.c        | 14 +------
 drivers/nvme/target/admin-cmd.c |  1 +
 drivers/nvme/target/discovery.c |  2 +-
 drivers/nvme/target/io-cmd.c    |  4 +-
 drivers/nvme/target/loop.c      | 20 ++--------
 11 files changed, 141 insertions(+), 100 deletions(-)
Signature · 1 line
2.14.3
#1 lore raw

PATCH 1/13 nvme: enforce 64bit offset for nvme_get_log_ext fn

From: Matias Bj?rling <[email protected]>

Compiling on 32 bits system produces a warning for the shift width when shifting 32 bit integer with 64bit integer.

Make sure that offset always is 64bit, and use macros for retrieving lower and upper bits of the offset.

Signed-off-by Matias Bj?rling <mb at lightnvm.io>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/core.c | 6 +++---
 drivers/nvme/host/nvme.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/nvme/host/core.c +3 -3
index 197a6ba9700f..1bdd010a0cf5 100644
@@ -2220,7 +2220,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
 
 int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 		     u8 log_page, void *log,
-		     size_t size, size_t offset)
+		     size_t size, u64 offset)
 {
 	struct nvme_command c = { };
 	unsigned long dwlen = size / 4 - 1;
@@ -2235,8 +2235,8 @@ int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	c.get_log_page.lid = log_page;
 	c.get_log_page.numdl = cpu_to_le16(dwlen & ((1 << 16) - 1));
 	c.get_log_page.numdu = cpu_to_le16(dwlen >> 16);
-	c.get_log_page.lpol = cpu_to_le32(offset & ((1ULL << 32) - 1));
-	c.get_log_page.lpou = cpu_to_le32(offset >> 32ULL);
+	c.get_log_page.lpol = cpu_to_le32(lower_32_bits(offset));
+	c.get_log_page.lpou = cpu_to_le32(upper_32_bits(offset));
 
 	return nvme_submit_sync_cmd(ctrl->admin_q, &c, log, size);
 }
drivers/nvme/host/nvme.h +1 -1
index cf93690b3ffc..09d47b1937ff 100644
@@ -430,7 +430,7 @@ int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl);
 
 int nvme_get_log_ext(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-		u8 log_page, void *log, size_t size, size_t offset);
+		u8 log_page, void *log, size_t size, u64 offset);
 
 extern const struct attribute_group nvme_ns_id_attr_group;
 extern const struct block_device_operations nvme_ns_head_ops;
Signature · 1 line
2.14.3
#2 lore raw

PATCH 2/13 nvme-loop: fix kernel oops in case of unhandled command

In reply to Keith Busch

From: Ming Lei <[email protected]>

When nvmet_req_init() fails, __nvmet_req_complete() is called to handle the target request via .queue_response(), so nvme_loop_queue_response() shouldn't be called again for handling the failure.

This patch fixes this case by the following way:

- move blk_mq_start_request() before nvmet_req_init(), so nvme_loop_queue_response() may work well to complete this host request

- don't call nvme_cleanup_cmd() which is done in nvme_loop_complete_rq()

- don't call nvme_loop_queue_response() which is done via .queue_response()

Signed-off-by Ming Lei <ming.lei at redhat.com>
Reviewed-by Christoph Hellwig <hch at lst.de>
[trimmed changelog]
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/target/loop.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/nvme/target/loop.c +2 -7
index a350765d2d5c..b9d5b69d8548 100644
@@ -174,15 +174,12 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 	if (ret)
 		return ret;
 
+	blk_mq_start_request(req);
 	iod->cmd.common.flags |= NVME_CMD_SGL_METABUF;
 	iod->req.port = nvmet_loop_port;
 	if (!nvmet_req_init(&iod->req, &queue->nvme_cq,
-			&queue->nvme_sq, &nvme_loop_ops)) {
-		nvme_cleanup_cmd(req);
-		blk_mq_start_request(req);
-		nvme_loop_queue_response(&iod->req);
+			&queue->nvme_sq, &nvme_loop_ops))
 		return BLK_STS_OK;
-	}
 
 	if (blk_rq_payload_bytes(req)) {
 		iod->sg_table.sgl = iod->first_sgl;
@@ -196,8 +193,6 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 		iod->req.transfer_len = blk_rq_payload_bytes(req);
 	}
 
-	blk_mq_start_request(req);
-
 	schedule_work(&iod->work);
 	return BLK_STS_OK;
 }
Signature · 1 line
2.14.3
#3 lore raw

PATCH 3/13 nvme: unexport nvme_start_keep_alive

In reply to Keith Busch

From: Johannes Thumshirn <[email protected]>

nvme_start_keep_alive() isn't used outside core.c so unexport it and make it static.

Signed-off-by Johannes Thumshirn <jthumshirn at suse.de>
Reviewed-by Christoph Hellwig <hch at lst.de>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/core.c | 3 +--
 drivers/nvme/host/nvme.h | 1 -
 2 files changed, 1 insertion(+), 3 deletions(-)
drivers/nvme/host/core.c +1 -2
index 1bdd010a0cf5..695e52ae22fd 100644
@@ -826,7 +826,7 @@ static void nvme_keep_alive_work(struct work_struct *work)
 	}
 }
 
-void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
+static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
 {
 	if (unlikely(ctrl->kato == 0))
 		return;
@@ -836,7 +836,6 @@ void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
 	ctrl->ka_cmd.common.opcode = nvme_admin_keep_alive;
 	schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
 }
-EXPORT_SYMBOL_GPL(nvme_start_keep_alive);
 
 void nvme_stop_keep_alive(struct nvme_ctrl *ctrl)
 {
drivers/nvme/host/nvme.h +0 -1
index 09d47b1937ff..08c4cff79cde 100644
@@ -422,7 +422,6 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
 		unsigned timeout, int qid, int at_head,
 		blk_mq_req_flags_t flags);
 int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count);
-void nvme_start_keep_alive(struct nvme_ctrl *ctrl);
 void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
Signature · 1 line
2.14.3
#4 lore raw

PATCH 4/13 nvme: don't send keep-alives to the discovery controller

In reply to Keith Busch

From: Johannes Thumshirn <[email protected]>

NVMe over Fabrics 1.0 Section 5.2 "Discovery Controller Properties and Command Support" Figure 31 "Discovery Controller ? Admin Commands" explicitly listst all commands but "Get Log Page" and "Identify" as reserved, but NetApp report the Linux host is sending Keep Alive commands to the discovery controller, which is a violation of the Spec.

We're already checking for discovery controllers when configuring the keep alive timeout but when creating a discovery controller we're not hard wiring the keep alive timeout to 0 and thus remain on NVME_DEFAULT_KATO for the discovery controller.

This can be easily remproduced when issuing a direct connect to the discovery susbsystem using:
'nvme connect [...] --nqn=nqn.2014-08.org.nvmexpress.discovery'

Signed-off-by Johannes Thumshirn <jthumshirn at suse.de>
Fixes 07bfcd09a288 ("nvme-fabrics: add a generic NVMe over Fabrics library")
Reported-by Martin George <marting at netapp.com>
Reviewed-by Christoph Hellwig <hch at lst.de>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/fabrics.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/nvme/host/fabrics.c +3 -1
index 8f0f34d06d46..3583f9492a45 100644
@@ -608,8 +608,10 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
 			opts->discovery_nqn =
 				!(strcmp(opts->subsysnqn,
 					 NVME_DISC_SUBSYS_NAME));
-			if (opts->discovery_nqn)
+			if (opts->discovery_nqn) {
+				opts->kato = 0;
 				opts->nr_io_queues = 0;
+			}
 			break;
 		case NVMF_OPT_TRADDR:
 			p = match_strdup(args);
Signature · 1 line
2.14.3
#5 lore raw

PATCH 5/13 nvme: target: fix buffer overflow

In reply to Keith Busch

From: Arnd Bergmann <[email protected]>

nvmet_execute_get_disc_log_page() passes a fixed-length string into nvmet_format_discovery_entry(), which then does a longer memcpy() on it, as pointed out by gcc-8:

In function 'nvmet_format_discovery_entry',
inlined from 'nvmet_execute_get_disc_log_page' at drivers/nvme/target/discovery.c:126:4:
drivers/nvme/target/discovery.c:62:2: error: 'memcpy' forming offset [38, 223] is out of the bounds [0, 37] [-Werror=array-bounds]
memcpy(e->subnqn, subsys_nqn, NVMF_NQN_SIZE);

Using strncpy() will make this well-defined, filling the rest of the buffer with zeroes, under the assumption that the input is either a NUL-terminated string, or a byte sequence containing no zeroes. If the input is a string that is longer than NVMF_NQN_SIZE, we continue to have no NUL-termination in the output.

Fixes a07b4970f464 ("nvmet: add a generic NVMe target")
Signed-off-by Arnd Bergmann <arnd at arndb.de>
Reviewed-by Christoph Hellwig <hch at lst.de>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/target/discovery.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/target/discovery.c +1 -1
index a72425d8bce0..231e04e0a496 100644
@@ -59,7 +59,7 @@ static void nvmet_format_discovery_entry(struct nvmf_disc_rsp_page_hdr *hdr,
 	memcpy(e->trsvcid, port->disc_addr.trsvcid, NVMF_TRSVCID_SIZE);
 	memcpy(e->traddr, traddr, NVMF_TRADDR_SIZE);
 	memcpy(e->tsas.common, port->disc_addr.tsas.common, NVMF_TSAS_SIZE);
-	memcpy(e->subnqn, subsys_nqn, NVMF_NQN_SIZE);
+	strncpy(e->subnqn, subsys_nqn, NVMF_NQN_SIZE);
 }
 
 /*
Signature · 1 line
2.14.3
#6 lore raw

PATCH 6/13 nvme-pci: Skip queue deletion if there are no queues

In reply to Keith Busch

User reported controller always retains CSTS.RDY to 1, which fails controller disabling when resetting the controller. This is also before the admin queue is allocated, and trying to disable an unallocated queue results in a NULL dereference.

Reported-by Alex Gagniuc <Alex_Gagniuc at Dellteam.com>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/pci.c +1 -1
index 295fbec1e5f2..22403aa7dc60 100644
@@ -2201,7 +2201,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
 
 	nvme_stop_queues(&dev->ctrl);
 
-	if (!dead) {
+	if (!dead && dev->ctrl.queue_count > 0) {
 		/*
 		 * If the controller is still alive tell it to stop using the
 		 * host memory buffer.  In theory the shutdown / reset should
Signature · 1 line
2.14.3
#7 lore raw

PATCH 7/13 nvme-pci: Remove unused queue parameter

In reply to Keith Busch

All the queue memory is allocated up front. We don't take the node into consideration when creating queues anymore, so removing the unused parameter.

Signed-off-by Keith Busch <keith.busch at intel.com>
Reviewed-by Christoph Hellwig <hch at lst.de>
Reviewed-by Ming Lei <ming.lei at redhat.com>
---
 drivers/nvme/host/pci.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/nvme/host/pci.c +3 -7
index 22403aa7dc60..0b3b4d9fd423 100644
@@ -1380,8 +1380,7 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
 	return 0;
 }
 
-static int nvme_alloc_queue(struct nvme_dev *dev, int qid,
-		int depth, int node)
+static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
 {
 	struct nvme_queue *nvmeq = &dev->queues[qid];
 
@@ -1596,8 +1595,7 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev)
 	if (result < 0)
 		return result;
 
-	result = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH,
-			dev_to_node(dev->dev));
+	result = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH);
 	if (result)
 		return result;
 
@@ -1630,9 +1628,7 @@ static int nvme_create_io_queues(struct nvme_dev *dev)
 	int ret = 0;
 
 	for (i = dev->ctrl.queue_count; i <= dev->max_qid; i++) {
-		/* vector == qid - 1, match nvme_create_queue */
-		if (nvme_alloc_queue(dev, i, dev->q_depth,
-		     pci_irq_get_node(to_pci_dev(dev->dev), i - 1))) {
+		if (nvme_alloc_queue(dev, i, dev->q_depth)) {
 			ret = -ENOMEM;
 			break;
 		}
Signature · 1 line
2.14.3
#8 lore raw

PATCH 8/13 nvme-pci: Separate IO and admin queue IRQ vectors

In reply to Keith Busch

The admin and first IO queues shared the first irq vector, which has an affinity mask including cpu0. If a system allows cpu0 to be offlined, the admin queue may not be usable if no other CPUs in the affinity mask are online. This is a problem since unlike IO queues, there is only one admin queue that always needs to be usable.

To fix, this patch allocates one pre_vector for the admin queue that is assigned all CPUs, so will always be accessible. The IO queues are assigned the remaining managed vectors.

In case a controller has only one interrupt vector available, the admin and IO queues will share the pre_vector with all CPUs assigned.

Cc Jianchao Wang <jianchao.w.wang at oracle.com>
Cc Ming Lei <ming.lei at redhat.com>
Signed-off-by Keith Busch <keith.busch at intel.com>
Reviewed-by Christoph Hellwig <hch at lst.de>
Reviewed-by Ming Lei <ming.lei at redhat.com>
---
 drivers/nvme/host/pci.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)
drivers/nvme/host/pci.c +17 -6
index 0b3b4d9fd423..fbc71fac6f1e 100644
@@ -84,6 +84,7 @@ struct nvme_dev {
 	struct dma_pool *prp_small_pool;
 	unsigned online_queues;
 	unsigned max_qid;
+	unsigned int num_vecs;
 	int q_depth;
 	u32 db_stride;
 	void __iomem *bar;
@@ -414,7 +415,8 @@ static int nvme_pci_map_queues(struct blk_mq_tag_set *set)
 {
 	struct nvme_dev *dev = set->driver_data;
 
-	return blk_mq_pci_map_queues(set, to_pci_dev(dev->dev), 0);
+	return blk_mq_pci_map_queues(set, to_pci_dev(dev->dev),
+			dev->num_vecs > 1 ? 1 /* admin queue */ : 0);
 }
 
 /**
@@ -1456,7 +1458,11 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
 		nvmeq->sq_cmds_io = dev->cmb + offset;
 	}
 
-	nvmeq->cq_vector = qid - 1;
+	/*
+	 * A queue's vector matches the queue identifier unless the controller
+	 * has only one vector available.
+	 */
+	nvmeq->cq_vector = dev->num_vecs == 1 ? 0 : qid;
 	result = adapter_alloc_cq(dev, qid, nvmeq);
 	if (result < 0)
 		goto release_vector;
@@ -1910,6 +1916,10 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
 	int result, nr_io_queues;
 	unsigned long size;
 
+	struct irq_affinity affd = {
+		.pre_vectors = 1
+	};
+
 	nr_io_queues = num_possible_cpus();
 	result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
 	if (result < 0)
@@ -1945,11 +1955,12 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
 	 * setting up the full range we need.
 	 */
 	pci_free_irq_vectors(pdev);
-	nr_io_queues = pci_alloc_irq_vectors(pdev, 1, nr_io_queues,
-			PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY);
-	if (nr_io_queues <= 0)
+	result = pci_alloc_irq_vectors_affinity(pdev, 1, nr_io_queues + 1,
+			PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
+	if (result <= 0)
 		return -EIO;
-	dev->max_qid = nr_io_queues;
+	dev->num_vecs = result;
+	dev->max_qid = max(result - 1, 1);
 
 	/*
 	 * Should investigate if there's a performance win from allocating
Signature · 1 line
2.14.3
#9 lore raw

PATCH 9/13 nvmet: Fix nvmet_execute_write_zeroes sector count

In reply to Keith Busch

From: "Rodrigo R. Galvao" <[email protected]>

We have to increment the number of logical blocks to a 1's based value in the native format prior to converting to 512b units.

Signed-off-by Rodrigo R. Galvao <rosattig at linux.vnet.ibm.com>
[changelog]
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/target/io-cmd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/nvme/target/io-cmd.c +2 -2
index 28bbdff4a88b..cd2344179673 100644
@@ -173,8 +173,8 @@ static void nvmet_execute_write_zeroes(struct nvmet_req *req)
 
 	sector = le64_to_cpu(write_zeroes->slba) <<
 		(req->ns->blksize_shift - 9);
-	nr_sector = (((sector_t)le16_to_cpu(write_zeroes->length)) <<
-		(req->ns->blksize_shift - 9)) + 1;
+	nr_sector = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) <<
+		(req->ns->blksize_shift - 9));
 
 	if (__blkdev_issue_zeroout(req->ns->bdev, sector, nr_sector,
 				GFP_KERNEL, &bio, 0))
Signature · 1 line
2.14.3
#10 lore raw

PATCH 10/13 nvme: check return value of init_srcu_struct function

In reply to Keith Busch

From: Max Gurtovoy <[email protected]>

Also add error flow in case srcu initialization function fails.

Signed-off-by Max Gurtovoy <maxg at mellanox.com>
Reviewed-by Christoph Hellwig <hch at lst.de>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/core.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/nvme/host/core.c +4 -1
index 695e52ae22fd..b09940c556d0 100644
@@ -2832,7 +2832,9 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
 		goto out_free_head;
 	head->instance = ret;
 	INIT_LIST_HEAD(&head->list);
-	init_srcu_struct(&head->srcu);
+	ret = init_srcu_struct(&head->srcu);
+	if (ret)
+		goto out_ida_remove;
 	head->subsys = ctrl->subsys;
 	head->ns_id = nsid;
 	kref_init(&head->ref);
@@ -2854,6 +2856,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
 	return head;
 out_cleanup_srcu:
 	cleanup_srcu_struct(&head->srcu);
+out_ida_remove:
 	ida_simple_remove(&ctrl->subsys->ns_ida, head->instance);
 out_free_head:
 	kfree(head);
Signature · 1 line
2.14.3
#11 lore raw

PATCH 11/13 nvmet: fix space padding in serial number

In reply to Keith Busch

From: Daniel Verkamp <[email protected]>

Commit 42de82a8b544 previously attempted to fix this, and it did correctly pad the MN and FR fields with spaces, but the SN field still contains 0 bytes. The current code fills out the first 16 bytes with hex2bin, leaving the last 4 bytes zeroed. Rather than adding a lot of error-prone math to avoid overwriting SN twice, just set the whole thing to spaces up front (it's only 20 bytes).

Fixes 42de82a8b544 ("nvmet: don't report 0-bytes in serial number")
Signed-off-by Daniel Verkamp <daniel.verkamp at intel.com>
Reviewed-by Martin Wilck <mwilck at suse.com>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/target/admin-cmd.c | 1 +
 1 file changed, 1 insertion(+)
drivers/nvme/target/admin-cmd.c +1 -0
index 90dcdc40ac71..5e0e9fcc0d4d 100644
@@ -178,6 +178,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
 	id->vid = 0;
 	id->ssvid = 0;
 
+	memset(id->sn, ' ', sizeof(id->sn));
 	bin2hex(id->sn, &ctrl->subsys->serial,
 		min(sizeof(ctrl->subsys->serial), sizeof(id->sn) / 2));
 	memcpy_and_pad(id->mn, sizeof(id->mn), model, sizeof(model) - 1, ' ');
Signature · 1 line
2.14.3
#12 lore raw

PATCH 12/13 nvme: Use admin command effects for admin commands

In reply to Keith Busch
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/core.c +1 -1
index b09940c556d0..aac3c1d2b2a2 100644
@@ -1102,7 +1102,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	}
 
 	if (ctrl->effects)
-		effects = le32_to_cpu(ctrl->effects->iocs[opcode]);
+		effects = le32_to_cpu(ctrl->effects->acs[opcode]);
 	else
 		effects = nvme_known_admin_effects(opcode);
 
Signature · 1 line
2.14.3
#13 lore raw

PATCH 13/13 nvme: expand nvmf_check_if_ready checks

In reply to Keith Busch

From: James Smart <[email protected]>

The nvmf_check_if_ready() checks that were added are very simplistic. As such, the routine allows a lot of cases to fail ios during windows of reset or re-connection. In cases where there are not multi-path options present, the error goes back to the callee - the filesystem or application. Not good.

The common routine was rewritten and calling syntax slightly expanded so that per-transport is_ready routines don't need to be present. The transports now call the routine directly. The routine is now a fabrics routine rather than an inline function.

The routine now looks at controller state to decide the action to take. Some states mandate io failure. Others define the condition where a command can be accepted. When the decision is unclear, a generic queue-or-reject check is made to look for failfast or multipath ios and only fails the io if it is so marked. Otherwise, the io will be queued and wait for the controller state to resolve.

Admin commands issued via ioctl share a live admin queue with commands from the transport for controller init. The ioctls could be intermixed with the initialization commands. It's possible for the ioctl cmd to be issued prior to the controller being enabled. To block this, the ioctl admin commands need to be distinguished from admin commands used for controller init. Added a USERCMD nvme_req(req)->rq_flags bit to reflect this division and set it on ioctls requests. As the nvmf_check_if_ready() routine is called prior to nvme_setup_cmd(), ensure that commands allocated by the ioctl path (actually anything in core.c) preps the nvme_req(req) before starting the io. This will preserve the USERCMD flag during execution and/or retry.

Signed-off-by James Smart <james.smart at broadcom.com>
Reviewed-by Sagi Grimberg <sagi at grimberg.e>
Reviewed-by Johannes Thumshirn <jthumshirn at suse.de>
Signed-off-by Keith Busch <keith.busch at intel.com>
---
 drivers/nvme/host/core.c    | 17 +++++++---
 drivers/nvme/host/fabrics.c | 79 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/fabrics.h | 33 ++-----------------
 drivers/nvme/host/fc.c      | 12 ++-----
 drivers/nvme/host/nvme.h    |  1 +
 drivers/nvme/host/rdma.c    | 14 ++------
 drivers/nvme/target/loop.c  | 11 ++-----
 7 files changed, 101 insertions(+), 66 deletions(-)
drivers/nvme/host/core.c +12 -5
index aac3c1d2b2a2..9df4f71e58ca 100644
@@ -376,6 +376,15 @@ static void nvme_put_ns(struct nvme_ns *ns)
 	kref_put(&ns->kref, nvme_free_ns);
 }
 
+static inline void nvme_clear_nvme_request(struct request *req)
+{
+	if (!(req->rq_flags & RQF_DONTPREP)) {
+		nvme_req(req)->retries = 0;
+		nvme_req(req)->flags = 0;
+		req->rq_flags |= RQF_DONTPREP;
+	}
+}
+
 struct request *nvme_alloc_request(struct request_queue *q,
 		struct nvme_command *cmd, blk_mq_req_flags_t flags, int qid)
 {
@@ -392,6 +401,7 @@ struct request *nvme_alloc_request(struct request_queue *q,
 		return req;
 
 	req->cmd_flags |= REQ_FAILFAST_DRIVER;
+	nvme_clear_nvme_request(req);
 	nvme_req(req)->cmd = cmd;
 
 	return req;
@@ -608,11 +618,7 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
 {
 	blk_status_t ret = BLK_STS_OK;
 
-	if (!(req->rq_flags & RQF_DONTPREP)) {
-		nvme_req(req)->retries = 0;
-		nvme_req(req)->flags = 0;
-		req->rq_flags |= RQF_DONTPREP;
-	}
+	nvme_clear_nvme_request(req);
 
 	switch (req_op(req)) {
 	case REQ_OP_DRV_IN:
@@ -742,6 +748,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
 		return PTR_ERR(req);
 
 	req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
+	nvme_req(req)->flags |= NVME_REQ_USERCMD;
 
 	if (ubuffer && bufflen) {
 		ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
drivers/nvme/host/fabrics.c +79 -0

85 lines not on this page · raw message

drivers/nvme/host/fabrics.h +2 -31
index a3145d90c1d2..ef46c915b7b5 100644
@@ -157,36 +157,7 @@ void nvmf_unregister_transport(struct nvmf_transport_ops *ops);
 void nvmf_free_options(struct nvmf_ctrl_options *opts);
 int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
 bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
-
-static inline blk_status_t nvmf_check_init_req(struct nvme_ctrl *ctrl,
-		struct request *rq)
-{
-	struct nvme_command *cmd = nvme_req(rq)->cmd;
-
-	/*
-	 * We cannot accept any other command until the connect command has
-	 * completed, so only allow connect to pass.
-	 */
-	if (!blk_rq_is_passthrough(rq) ||
-	    cmd->common.opcode != nvme_fabrics_command ||
-	    cmd->fabrics.fctype != nvme_fabrics_type_connect) {
-		/*
-		 * Connecting state means transport disruption or initial
-		 * establishment, which can take a long time and even might
-		 * fail permanently, fail fast to give upper layers a chance
-		 * to failover.
-		 * Deleting state means that the ctrl will never accept commands
-		 * again, fail it permanently.
-		 */
-		if (ctrl->state == NVME_CTRL_CONNECTING ||
-		    ctrl->state == NVME_CTRL_DELETING) {
-			nvme_req(rq)->status = NVME_SC_ABORT_REQ;
-			return BLK_STS_IOERR;
-		}
-		return BLK_STS_RESOURCE; /* try again later */
-	}
-
-	return BLK_STS_OK;
-}
+blk_status_t nvmf_check_if_ready(struct nvme_ctrl *ctrl,
+	struct request *rq, bool queue_live, bool is_connected);
 
 #endif /* _NVME_FABRICS_H */
drivers/nvme/host/fc.c +3 -9
index c6e719b2f3ca..6cb26bcf6ec0 100644
@@ -2277,14 +2277,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
 	return BLK_STS_OK;
 }
 
-static inline blk_status_t nvme_fc_is_ready(struct nvme_fc_queue *queue,
-		struct request *rq)
-{
-	if (unlikely(!test_bit(NVME_FC_Q_LIVE, &queue->flags)))
-		return nvmf_check_init_req(&queue->ctrl->ctrl, rq);
-	return BLK_STS_OK;
-}
-
 static blk_status_t
 nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
 			const struct blk_mq_queue_data *bd)
@@ -2300,7 +2292,9 @@ nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
 	u32 data_len;
 	blk_status_t ret;
 
-	ret = nvme_fc_is_ready(queue, rq);
+	ret = nvmf_check_if_ready(&queue->ctrl->ctrl, rq,
+		test_bit(NVME_FC_Q_LIVE, &queue->flags),
+		ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE);
 	if (unlikely(ret))
 		return ret;
 
drivers/nvme/host/nvme.h +1 -0
index 08c4cff79cde..061fecfd44f5 100644
@@ -105,6 +105,7 @@ struct nvme_request {
 
 enum {
 	NVME_REQ_CANCELLED		= (1 << 0),
+	NVME_REQ_USERCMD		= (1 << 1),
 };
 
 static inline struct nvme_request *nvme_req(struct request *req)
drivers/nvme/host/rdma.c +2 -12
index 758537e9ba07..1eb4438a8763 100644
@@ -1601,17 +1601,6 @@ nvme_rdma_timeout(struct request *rq, bool reserved)
 	return BLK_EH_HANDLED;
 }
 
-/*
- * We cannot accept any other command until the Connect command has completed.
- */
-static inline blk_status_t
-nvme_rdma_is_ready(struct nvme_rdma_queue *queue, struct request *rq)
-{
-	if (unlikely(!test_bit(NVME_RDMA_Q_LIVE, &queue->flags)))
-		return nvmf_check_init_req(&queue->ctrl->ctrl, rq);
-	return BLK_STS_OK;
-}
-
 static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
 		const struct blk_mq_queue_data *bd)
 {
@@ -1627,7 +1616,8 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
 
 	WARN_ON_ONCE(rq->tag < 0);
 
-	ret = nvme_rdma_is_ready(queue, rq);
+	ret = nvmf_check_if_ready(&queue->ctrl->ctrl, rq,
+		test_bit(NVME_RDMA_Q_LIVE, &queue->flags), true);
 	if (unlikely(ret))
 		return ret;
 
drivers/nvme/target/loop.c +2 -9
index b9d5b69d8548..31fdfba556a8 100644
@@ -149,14 +149,6 @@ nvme_loop_timeout(struct request *rq, bool reserved)
 	return BLK_EH_HANDLED;
 }
 
-static inline blk_status_t nvme_loop_is_ready(struct nvme_loop_queue *queue,
-		struct request *rq)
-{
-	if (unlikely(!test_bit(NVME_LOOP_Q_LIVE, &queue->flags)))
-		return nvmf_check_init_req(&queue->ctrl->ctrl, rq);
-	return BLK_STS_OK;
-}
-
 static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 		const struct blk_mq_queue_data *bd)
 {
@@ -166,7 +158,8 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 	struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(req);
 	blk_status_t ret;
 
-	ret = nvme_loop_is_ready(queue, req);
+	ret = nvmf_check_if_ready(&queue->ctrl->ctrl, req,
+		test_bit(NVME_LOOP_Q_LIVE, &queue->flags), true);
 	if (unlikely(ret))
 		return ret;
 
Signature · 1 line
2.14.3
maintainer Applied
#14 lore raw

cover nvme 4.17 patch series

In reply to Keith Busch
Quoted 33 lines · Keith Busch

This series merges cleanly with linux-block/for-linus.

Arnd Bergmann (1):
nvme: target: fix buffer overflow

Daniel Verkamp (1):
nvmet: fix space padding in serial number

James Smart (1):
nvme: expand nvmf_check_if_ready checks

Johannes Thumshirn (2):
nvme: unexport nvme_start_keep_alive
nvme: don't send keep-alives to the discovery controller

Keith Busch (4):
nvme-pci: Skip queue deletion if there are no queues
nvme-pci: Remove unused queue parameter
nvme-pci: Separate IO and admin queue IRQ vectors
nvme: Use admin command effects for admin commands

Matias Bj?rling (1):
nvme: enforce 64bit offset for nvme_get_log_ext fn

Max Gurtovoy (1):
nvme: check return value of init_srcu_struct function

Ming Lei (1):
nvme-loop: fix kernel oops in case of unhandled command

Rodrigo R. Galvao (1):
nvmet: Fix nvmet_execute_write_zeroes sector count

Quoted 12 lines
 drivers/nvme/host/core.c        | 33 ++++++++++------
 drivers/nvme/host/fabrics.c     | 83 ++++++++++++++++++++++++++++++++++++++++-
 drivers/nvme/host/fabrics.h     | 33 +---------------
 drivers/nvme/host/fc.c          | 12 ++----
 drivers/nvme/host/nvme.h        |  4 +-
 drivers/nvme/host/pci.c         | 35 ++++++++++-------
 drivers/nvme/host/rdma.c        | 14 +------
 drivers/nvme/target/admin-cmd.c |  1 +
 drivers/nvme/target/discovery.c |  2 +-
 drivers/nvme/target/io-cmd.c    |  4 +-
 drivers/nvme/target/loop.c      | 20 ++--------
 11 files changed, 141 insertions(+), 100 deletions(-)

Thanks, applied.

Signature · 1 line
Jens Axboe