public inbox for linux-block@vger.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: Jens Axboe <axboe@kernel.dk>
Cc: "Josef Bacik" <jbacik@fb.com>,
	"James Smart" <james.smart@broadcom.com>,
	"Konrad Rzeszutek Wilk" <konrad.wilk@oracle.com>,
	"Roger Pau Monné" <roger.pau@citrix.com>,
	linux-scsi@vger.kernel.org, linux-nvme@lists.infradead.org,
	linux-block@vger.kernel.org, dm-devel@redhat.com
Subject: [PATCH 04/25] nvme: split nvme status from block req->errors
Date: Thu,  6 Apr 2017 17:39:23 +0200	[thread overview]
Message-ID: <20170406153944.10058-5-hch@lst.de> (raw)
In-Reply-To: <20170406153944.10058-1-hch@lst.de>

We want our own clearly defined error field for NVMe passthrough commands,
and the request errors field is going away in its current form.

Just store the status and result field in the nvme_request field from
hardirq completion context (using a new helper) and then generate a
Linux errno for the block layer only when we actually need it.

Because we can't overload the status value with a negative error code
for cancelled command we now have a flags filed in struct nvme_request
that contains a bit for this condition.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 drivers/nvme/host/core.c     | 50 +++++++++++++++++++++++++++-----------------
 drivers/nvme/host/fc.c       | 10 ++++-----
 drivers/nvme/host/lightnvm.c |  9 +++++---
 drivers/nvme/host/nvme.h     | 33 +++++++++++++----------------
 drivers/nvme/host/pci.c      | 11 +++++-----
 drivers/nvme/host/rdma.c     |  5 ++---
 drivers/nvme/target/loop.c   |  7 ++-----
 7 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index dc05f41c3992..b73a86a78379 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -66,11 +66,24 @@ static DEFINE_SPINLOCK(dev_list_lock);
 
 static struct class *nvme_class;
 
+int nvme_error_status(struct request *req)
+{
+	switch (nvme_req(req)->status & 0x7ff) {
+	case NVME_SC_SUCCESS:
+		return 0;
+	case NVME_SC_CAP_EXCEEDED:
+		return -ENOSPC;
+	default:
+		return -EIO;
+	}
+}
+EXPORT_SYMBOL_GPL(nvme_error_status);
+
 static inline bool nvme_req_needs_retry(struct request *req)
 {
 	if (blk_noretry_request(req))
 		return false;
-	if (req->errors & NVME_SC_DNR)
+	if (nvme_req(req)->status & NVME_SC_DNR)
 		return false;
 	if (jiffies - req->start_time >= req->timeout)
 		return false;
@@ -81,23 +94,13 @@ static inline bool nvme_req_needs_retry(struct request *req)
 
 void nvme_complete_rq(struct request *req)
 {
-	int error = 0;
-
-	if (unlikely(req->errors)) {
-		if (nvme_req_needs_retry(req)) {
-			nvme_req(req)->retries++;
-			blk_mq_requeue_request(req,
-					!blk_mq_queue_stopped(req->q));
-			return;
-		}
-
-		if (blk_rq_is_passthrough(req))
-			error = req->errors;
-		else
-			error = nvme_error_status(req->errors);
+	if (unlikely(nvme_req(req)->status && nvme_req_needs_retry(req))) {
+		nvme_req(req)->retries++;
+		blk_mq_requeue_request(req, !blk_mq_queue_stopped(req->q));
+		return;
 	}
 
-	blk_mq_end_request(req, error);
+	blk_mq_end_request(req, nvme_error_status(req));
 }
 EXPORT_SYMBOL_GPL(nvme_complete_rq);
 
@@ -114,7 +117,9 @@ void nvme_cancel_request(struct request *req, void *data, bool reserved)
 	status = NVME_SC_ABORT_REQ;
 	if (blk_queue_dying(req->q))
 		status |= NVME_SC_DNR;
-	blk_mq_complete_request(req, status);
+	nvme_req(req)->status = status;
+	blk_mq_complete_request(req, 0);
+
 }
 EXPORT_SYMBOL_GPL(nvme_cancel_request);
 
@@ -357,6 +362,7 @@ int nvme_setup_cmd(struct nvme_ns *ns, struct request *req,
 
 	if (!(req->rq_flags & RQF_DONTPREP)) {
 		nvme_req(req)->retries = 0;
+		nvme_req(req)->flags = 0;
 		req->rq_flags |= RQF_DONTPREP;
 	}
 
@@ -411,7 +417,10 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd,
 	blk_execute_rq(req->q, NULL, req, at_head);
 	if (result)
 		*result = nvme_req(req)->result;
-	ret = req->errors;
+	if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
+		ret = -EINTR;
+	else
+		ret = nvme_req(req)->status;
  out:
 	blk_mq_free_request(req);
 	return ret;
@@ -496,7 +505,10 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
 	}
  submit:
 	blk_execute_rq(req->q, disk, req, 0);
-	ret = req->errors;
+	if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
+		ret = -EINTR;
+	else
+		ret = nvme_req(req)->status;
 	if (result)
 		*result = le32_to_cpu(nvme_req(req)->result.u32);
 	if (meta && !ret && !write) {
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index aad7f9c0be32..450733c8cd24 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1148,6 +1148,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
 	struct nvme_fc_queue *queue = op->queue;
 	struct nvme_completion *cqe = &op->rsp_iu.cqe;
 	__le16 status = cpu_to_le16(NVME_SC_SUCCESS << 1);
+	union nvme_result result;
 
 	/*
 	 * WARNING:
@@ -1215,7 +1216,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
 			status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1);
 			goto done;
 		}
-		op->nreq.result.u64 = 0;
+		result.u64 = 0;
 		break;
 
 	case sizeof(struct nvme_fc_ersp_iu):
@@ -1232,7 +1233,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
 			status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1);
 			goto done;
 		}
-		op->nreq.result = cqe->result;
+		result = cqe->result;
 		status = cqe->status;
 		break;
 
@@ -1243,13 +1244,12 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
 
 done:
 	if (!queue->qnum && op->rqno >= AEN_CMDID_BASE) {
-		nvme_complete_async_event(&queue->ctrl->ctrl, status,
-					&op->nreq.result);
+		nvme_complete_async_event(&queue->ctrl->ctrl, status, &result);
 		nvme_fc_ctrl_put(ctrl);
 		return;
 	}
 
-	blk_mq_complete_request(rq, le16_to_cpu(status) >> 1);
+	nvme_end_request(rq, status, result);
 }
 
 static int
diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c
index 21cac8523bd8..3d7b92c4c577 100644
--- a/drivers/nvme/host/lightnvm.c
+++ b/drivers/nvme/host/lightnvm.c
@@ -484,7 +484,7 @@ static void nvme_nvm_end_io(struct request *rq, int error)
 	struct nvm_rq *rqd = rq->end_io_data;
 
 	rqd->ppa_status = nvme_req(rq)->result.u64;
-	rqd->error = error;
+	rqd->error = nvme_req(req)->status;
 	nvm_end_io(rqd);
 
 	kfree(nvme_req(rq)->cmd);
@@ -681,9 +681,12 @@ static int nvme_nvm_submit_user_cmd(struct request_queue *q,
 
 	wait_for_completion_io(&wait);
 
-	ret = nvme_error_status(rq->errors);
+	if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
+		ret = -EINTR;
+	else
+		ret = nvme_error_status(rq);
 	if (result)
-		*result = rq->errors & 0x7ff;
+		*result = nvme_req(rq)->status & 0x7ff;
 	if (status)
 		*status = le64_to_cpu(nvme_req(rq)->result.u64);
 
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 9eecb67177df..7a03a0897e0b 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -21,16 +21,6 @@
 #include <linux/lightnvm.h>
 #include <linux/sed-opal.h>
 
-enum {
-	/*
-	 * Driver internal status code for commands that were cancelled due
-	 * to timeouts or controller shutdown.  The value is negative so
-	 * that it a) doesn't overlap with the unsigned hardware error codes,
-	 * and b) can easily be tested for.
-	 */
-	NVME_SC_CANCELLED		= -EINTR,
-};
-
 extern unsigned char nvme_io_timeout;
 #define NVME_IO_TIMEOUT	(nvme_io_timeout * HZ)
 
@@ -91,6 +81,12 @@ struct nvme_request {
 	struct nvme_command	*cmd;
 	union nvme_result	result;
 	u8			retries;
+	u8			flags;
+	u16			status;
+};
+
+enum {
+	NVME_REQ_CANCELLED		= (1 << 0),
 };
 
 static inline struct nvme_request *nvme_req(struct request *req)
@@ -248,18 +244,17 @@ static inline void nvme_cleanup_cmd(struct request *req)
 	}
 }
 
-static inline int nvme_error_status(u16 status)
+static inline void nvme_end_request(struct request *req, __le16 status,
+		union nvme_result result)
 {
-	switch (status & 0x7ff) {
-	case NVME_SC_SUCCESS:
-		return 0;
-	case NVME_SC_CAP_EXCEEDED:
-		return -ENOSPC;
-	default:
-		return -EIO;
-	}
+	struct nvme_request *rq = nvme_req(req);
+
+	rq->status = le16_to_cpu(status) >> 1;
+	rq->result = result;
+	blk_mq_complete_request(req, 0);
 }
 
+int nvme_error_status(struct request *req);
 void nvme_complete_rq(struct request *req);
 void nvme_cancel_request(struct request *req, void *data, bool reserved);
 bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 3818ab15a26e..f7b313e0cec8 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -679,8 +679,7 @@ static void __nvme_process_cq(struct nvme_queue *nvmeq, unsigned int *tag)
 		}
 
 		req = blk_mq_tag_to_rq(*nvmeq->tags, cqe.command_id);
-		nvme_req(req)->result = cqe.result;
-		blk_mq_complete_request(req, le16_to_cpu(cqe.status) >> 1);
+		nvme_end_request(req, cqe.status, cqe.result);
 	}
 
 	if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
@@ -817,9 +816,9 @@ static void abort_endio(struct request *req, int error)
 {
 	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
 	struct nvme_queue *nvmeq = iod->nvmeq;
-	u16 status = req->errors;
 
-	dev_warn(nvmeq->dev->ctrl.device, "Abort status: 0x%x", status);
+	dev_warn(nvmeq->dev->ctrl.device,
+		 "Abort status: 0x%x", nvme_req(req)->status);
 	atomic_inc(&nvmeq->dev->ctrl.abort_limit);
 	blk_mq_free_request(req);
 }
@@ -843,7 +842,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
 			 "I/O %d QID %d timeout, disable controller\n",
 			 req->tag, nvmeq->qid);
 		nvme_dev_disable(dev, false);
-		req->errors = NVME_SC_CANCELLED;
+		nvme_req(req)->flags |= NVME_REQ_CANCELLED;
 		return BLK_EH_HANDLED;
 	}
 
@@ -863,7 +862,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
 		 * Mark the request as handled, since the inline shutdown
 		 * forces all outstanding requests to complete.
 		 */
-		req->errors = NVME_SC_CANCELLED;
+		nvme_req(req)->flags |= NVME_REQ_CANCELLED;
 		return BLK_EH_HANDLED;
 	}
 
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 4aae363943e3..53b611f9ba5d 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -1178,8 +1178,7 @@ static int nvme_rdma_process_nvme_rsp(struct nvme_rdma_queue *queue,
 	    wc->ex.invalidate_rkey == req->mr->rkey)
 		req->mr->need_inval = false;
 
-	req->req.result = cqe->result;
-	blk_mq_complete_request(rq, le16_to_cpu(cqe->status) >> 1);
+	nvme_end_request(rq, cqe->status, cqe->result);
 	return ret;
 }
 
@@ -1416,7 +1415,7 @@ nvme_rdma_timeout(struct request *rq, bool reserved)
 	nvme_rdma_error_recovery(req->queue->ctrl);
 
 	/* fail with DNR on cmd timeout */
-	rq->errors = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+	nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
 
 	return BLK_EH_HANDLED;
 }
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index 33b431e4eec3..8260ee1f8e48 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -124,7 +124,6 @@ static void nvme_loop_queue_response(struct nvmet_req *req)
 				&cqe->result);
 	} else {
 		struct request *rq;
-		struct nvme_loop_iod *iod;
 
 		rq = blk_mq_tag_to_rq(nvme_loop_tagset(queue), cqe->command_id);
 		if (!rq) {
@@ -134,9 +133,7 @@ static void nvme_loop_queue_response(struct nvmet_req *req)
 			return;
 		}
 
-		iod = blk_mq_rq_to_pdu(rq);
-		iod->nvme_req.result = cqe->result;
-		blk_mq_complete_request(rq, le16_to_cpu(cqe->status) >> 1);
+		nvme_end_request(rq, cqe->status, cqe->result);
 	}
 }
 
@@ -157,7 +154,7 @@ nvme_loop_timeout(struct request *rq, bool reserved)
 	schedule_work(&iod->queue->ctrl->reset_work);
 
 	/* fail with DNR on admin cmd timeout */
-	rq->errors = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+	nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
 
 	return BLK_EH_HANDLED;
 }
-- 
2.11.0

  parent reply	other threads:[~2017-04-06 15:39 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-06 15:39 kill req->errors Christoph Hellwig
2017-04-06 15:39 ` [PATCH 01/25] remove the mg_disk driver Christoph Hellwig
2017-04-13 19:58   ` Bart Van Assche
2017-04-14  8:21     ` hch
2017-04-06 15:39 ` [PATCH 02/25] block: remove the blk_execute_rq return value Christoph Hellwig
2017-04-06 18:38   ` Johannes Thumshirn
2017-04-13 20:03   ` Bart Van Assche
2017-04-14  8:22     ` hch
2017-04-17 16:01       ` Jens Axboe
2017-04-18  7:50         ` hch
2017-04-06 15:39 ` [PATCH 03/25] nvme-fc: fix status code handling in nvme_fc_fcpio_done Christoph Hellwig
2017-04-06 18:50   ` Johannes Thumshirn
2017-04-06 15:39 ` Christoph Hellwig [this message]
2017-04-06 18:47   ` [PATCH 04/25] nvme: split nvme status from block req->errors Johannes Thumshirn
2017-04-06 15:39 ` [PATCH 05/25] nvme: make nvme_error_status private Christoph Hellwig
2017-04-06 15:39 ` [PATCH 06/25] virtio: fix spelling of virtblk_scsi_request_done Christoph Hellwig
2017-04-06 18:53   ` Johannes Thumshirn
2017-04-13 20:05   ` Bart Van Assche
2017-04-06 15:39 ` [PATCH 07/25] virtio_blk: don't use req->errors Christoph Hellwig
2017-04-06 18:55   ` Johannes Thumshirn
2017-04-06 15:39 ` [PATCH 08/25] scsi: fix fast-fail for non-passthrough requests Christoph Hellwig
2017-04-13 20:41   ` Bart Van Assche
2017-04-06 15:39 ` [PATCH 09/25] scsi: introduce a new result field in struct scsi_request Christoph Hellwig
2017-04-06 15:39 ` [PATCH 10/25] loop: zero-fill bio on the submitting cpu Christoph Hellwig
2017-04-12 10:24   ` Ming Lei
2017-04-06 15:39 ` [PATCH 11/25] null_blk: don't pass always-0 req->errors to blk_mq_complete_request Christoph Hellwig
2017-04-06 15:39 ` [PATCH 12/25] dm rq: don't pass irrelevant error code " Christoph Hellwig
2017-04-06 15:39 ` [PATCH 13/25] dm mpath: don't check for req->errors Christoph Hellwig
2017-04-06 15:39 ` [PATCH 14/25] nbd: don't use req->errors Christoph Hellwig
2017-04-06 21:11   ` Josef Bacik
2017-04-06 15:39 ` [PATCH 15/25] mtip32xx: add a status field to struct mtip_cmd Christoph Hellwig
2017-04-06 15:39 ` [PATCH 16/25] xen-blkfront: don't use req->errors Christoph Hellwig
2017-04-18 15:00   ` Roger Pau Monné
2017-04-18 15:05     ` Konrad Rzeszutek Wilk
2017-04-06 15:39 ` [PATCH 17/25] blk-mq: remove the error argument to blk_mq_complete_request Christoph Hellwig
2017-04-18 15:03   ` Roger Pau Monné
2017-04-18 15:06     ` Konrad Rzeszutek Wilk
2017-04-06 15:39 ` [PATCH 18/25] blk-mq: simplify __blk_mq_complete_request Christoph Hellwig
2017-04-06 15:39 ` [PATCH 19/25] block: add a error_count field to struct request Christoph Hellwig
2017-04-06 15:39 ` [PATCH 20/25] floppy: switch from req->errors to req->error_count Christoph Hellwig
2017-04-06 15:39 ` [PATCH 21/25] ataflop: " Christoph Hellwig
2017-04-06 15:39 ` [PATCH 22/25] swim3: remove (commented out) printing of req->errors Christoph Hellwig
2017-04-06 15:39 ` [PATCH 23/25] pd: remove bogus check for req->errors Christoph Hellwig
2017-04-06 15:39 ` [PATCH 24/25] blktrace: remove the unused block_rq_abort tracepoint Christoph Hellwig
2017-04-06 15:39 ` [PATCH 25/25] block: remove the errors field from struct request Christoph Hellwig
2017-04-06 20:00 ` kill req->errors Konrad Rzeszutek Wilk
2017-04-07  7:11   ` Christoph Hellwig
2017-04-18 14:33     ` Konrad Rzeszutek Wilk
2017-04-12  8:37   ` Christoph Hellwig
2017-04-12  8:38 ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170406153944.10058-5-hch@lst.de \
    --to=hch@lst.de \
    --cc=axboe@kernel.dk \
    --cc=dm-devel@redhat.com \
    --cc=james.smart@broadcom.com \
    --cc=jbacik@fb.com \
    --cc=konrad.wilk@oracle.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=roger.pau@citrix.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox