nvme: add nvme io error/timeout log

Add io error and timeout log to nvme devices

Signed-off-by: brookxu <brookxu@tencent.com>
This commit is contained in:
brookxu 2019-09-29 14:39:53 +08:00 committed by Xiaoming Gao
parent de2e1a582c
commit b81976658c
3 changed files with 73 additions and 0 deletions

View File

@ -308,6 +308,7 @@ struct request *nvme_alloc_request(struct request_queue *q,
req->cmd_flags |= REQ_FAILFAST_DRIVER;
nvme_req(req)->cmd = cmd;
nvme_req(req)->opcode = cmd->common.opcode;
return req;
}
@ -650,6 +651,11 @@ static int nvme_submit_user_cmd(struct request_queue *q,
return PTR_ERR(req);
req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
if (cmd->common.opcode == nvme_cmd_read ||
cmd->common.opcode == nvme_cmd_write) {
req->__sector = meta_seed;
req->__data_len = bufflen;
}
if (ubuffer && bufflen) {
ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,

View File

@ -97,6 +97,7 @@ struct nvme_request {
u8 retries;
u8 flags;
u16 status;
u8 opcode;
};
enum {

View File

@ -732,6 +732,7 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_dev *dev = nvmeq->dev;
struct request *req = bd->rq;
struct nvme_command cmnd;
struct nvme_request *rq;
blk_status_t ret;
ret = nvme_setup_cmd(ns, req, &cmnd);
@ -742,6 +743,9 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
if (ret)
goto out_free_cmd;
rq = blk_mq_rq_to_pdu(req);
rq->opcode = cmnd.common.opcode;
if (blk_rq_nr_phys_segments(req)) {
ret = nvme_map_data(dev, req, &cmnd);
if (ret)
@ -793,6 +797,64 @@ static inline void nvme_ring_cq_doorbell(struct nvme_queue *nvmeq)
}
}
static inline void nvme_eh_io_timeout(struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct nvme_ctrl *ctrl = &iod->nvmeq->dev->ctrl;
struct nvme_request *rq = nvme_req(req);
/* admin command error */
if (req->q == ctrl->admin_q || req->q == ctrl->connect_q) {
dev_warn_ratelimited(ctrl->device,
"Admin command timeout, CMD: %d(+%d)",
rq->opcode, rq->retries);
return;
}
/* io command timeout */
if (rq->opcode == nvme_cmd_write || rq->opcode == nvme_cmd_read)
dev_warn_ratelimited(ctrl->device,
"I/O timeout, QID: %d, CMD: %d(+%d), Sector: %llu+%u",
iod->nvmeq->qid, rq->opcode, rq->retries,
(unsigned long long)blk_rq_pos(req),
blk_rq_sectors(req));
else
dev_warn_ratelimited(ctrl->device,
"I/O timeout, QID: %d, CMD: %d(+%d)",
iod->nvmeq->qid, rq->opcode, rq->retries);
}
static inline void nvme_eh_io_error(struct request *req, __le16 status)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct nvme_ctrl *ctrl = &iod->nvmeq->dev->ctrl;
struct nvme_request *rq = nvme_req(req);
if (status == NVME_SC_SUCCESS || rq->opcode == nvme_admin_abort_cmd)
return;
/* admin command error */
if (req->q == ctrl->admin_q || req->q == ctrl->connect_q) {
dev_warn_ratelimited(ctrl->device,
"Admin command error, CMD: %d(+%d), Status: 0x%x",
rq->opcode, rq->retries, status);
return;
}
/* io command error */
if (rq->opcode == nvme_cmd_write || rq->opcode == nvme_cmd_read)
dev_warn_ratelimited(ctrl->device,
"I/O error, QID: %d, CMD: %d(+%d), Sector: %llu+%u, Status: 0x%x",
iod->nvmeq->qid, rq->opcode, rq->retries,
(unsigned long long)blk_rq_pos(req),
blk_rq_sectors(req), status);
else
dev_warn_ratelimited(ctrl->device,
"I/O error, QID: %d, CMD: %d(+%d), Status: 0x%x",
iod->nvmeq->qid, rq->opcode, rq->retries,
status);
}
static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
struct nvme_completion *cqe)
{
@ -820,6 +882,7 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
nvmeq->cqe_seen = 1;
req = blk_mq_tag_to_rq(*nvmeq->tags, cqe->command_id);
nvme_eh_io_error(req, le16_to_cpu(cqe->status) >> 1);
nvme_end_request(req, cqe->status, cqe->result);
}
@ -1051,6 +1114,9 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
struct nvme_command cmd;
u32 csts = readl(dev->bar + NVME_REG_CSTS);
/* log error memset */
nvme_eh_io_timeout(req);
/* If PCI error recovery process is happening, we cannot reset or
* the recovery mechanism will surely fail.
*/