Skip to content

Commit 9f079dd

Browse files
alanpeteradkeithbusch
authored andcommitted
nvme: allow passthru cmd error logging
Commit d7ac8dc ("nvme: quiet user passthrough command errors") disabled error logging for user passthrough commands. This commit adds the ability to opt-in to passthrough admin error logging. IO commands initiated as passthrough will always be logged. The logging output for passthrough commands (Admin and IO) has been changed to include CDWXX fields. nvme0n1: Read(0x2), LBA Out of Range (sct 0x0 / sc 0x80) DNR cdw10=0x0 cdw11=0x1 cdw12=0x70000 cdw13=0x0 cdw14=0x0 cdw15=0x0 Add a helper function nvme_log_err_passthru() which allows us to log error for passthru commands by decoding cdw10-cdw15 values of nvme command. Add a new sysfs attr passthru_err_log_enabled that allows user to conditionally enable passthrough command logging for either passthrough Admin commands sent to the controller or passthrough IO commands sent to a namespace. By default, passthrough error logging is disabled. To enable passthrough admin error logging: echo 1 > /sys/class/nvme/nvme0/passthru_err_log_enabled To disable passthrough admin error logging: echo 0 > /sys/class/nvme/nvme0/passthru_err_log_enabled To enable passthrough io error logging: echo 1 > /sys/class/nvme/nvme0/nvme0n1/passthru_err_log_enabled To disable passthrough io error logging: echo 0 > /sys/class/nvme/nvme0/nvme0n1/passthru_err_log_enabled Signed-off-by: Alan Adamson <alan.adamson@oracle.com> Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent c3a846f commit 9f079dd

File tree

3 files changed

+113
-7
lines changed

3 files changed

+113
-7
lines changed

drivers/nvme/host/core.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,30 @@ static void nvme_log_error(struct request *req)
338338
nr->status & NVME_SC_DNR ? "DNR " : "");
339339
}
340340

341+
static void nvme_log_err_passthru(struct request *req)
342+
{
343+
struct nvme_ns *ns = req->q->queuedata;
344+
struct nvme_request *nr = nvme_req(req);
345+
346+
pr_err_ratelimited("%s: %s(0x%x), %s (sct 0x%x / sc 0x%x) %s%s"
347+
"cdw10=0x%x cdw11=0x%x cdw12=0x%x cdw13=0x%x cdw14=0x%x cdw15=0x%x\n",
348+
ns ? ns->disk->disk_name : dev_name(nr->ctrl->device),
349+
ns ? nvme_get_opcode_str(nr->cmd->common.opcode) :
350+
nvme_get_admin_opcode_str(nr->cmd->common.opcode),
351+
nr->cmd->common.opcode,
352+
nvme_get_error_status_str(nr->status),
353+
nr->status >> 8 & 7, /* Status Code Type */
354+
nr->status & 0xff, /* Status Code */
355+
nr->status & NVME_SC_MORE ? "MORE " : "",
356+
nr->status & NVME_SC_DNR ? "DNR " : "",
357+
nr->cmd->common.cdw10,
358+
nr->cmd->common.cdw11,
359+
nr->cmd->common.cdw12,
360+
nr->cmd->common.cdw13,
361+
nr->cmd->common.cdw14,
362+
nr->cmd->common.cdw14);
363+
}
364+
341365
enum nvme_disposition {
342366
COMPLETE,
343367
RETRY,
@@ -385,8 +409,12 @@ static inline void nvme_end_req(struct request *req)
385409
{
386410
blk_status_t status = nvme_error_status(nvme_req(req)->status);
387411

388-
if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET)))
389-
nvme_log_error(req);
412+
if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) {
413+
if (blk_rq_is_passthrough(req))
414+
nvme_log_err_passthru(req);
415+
else
416+
nvme_log_error(req);
417+
}
390418
nvme_end_req_zoned(req);
391419
nvme_trace_bio_complete(req);
392420
if (req->cmd_flags & REQ_NVME_MPATH)
@@ -679,10 +707,21 @@ static inline void nvme_clear_nvme_request(struct request *req)
679707
/* initialize a passthrough request */
680708
void nvme_init_request(struct request *req, struct nvme_command *cmd)
681709
{
682-
if (req->q->queuedata)
710+
struct nvme_request *nr = nvme_req(req);
711+
bool logging_enabled;
712+
713+
if (req->q->queuedata) {
714+
struct nvme_ns *ns = req->q->disk->private_data;
715+
716+
logging_enabled = ns->passthru_err_log_enabled;
683717
req->timeout = NVME_IO_TIMEOUT;
684-
else /* no queuedata implies admin queue */
718+
} else { /* no queuedata implies admin queue */
719+
logging_enabled = nr->ctrl->passthru_err_log_enabled;
685720
req->timeout = NVME_ADMIN_TIMEOUT;
721+
}
722+
723+
if (!logging_enabled)
724+
req->rq_flags |= RQF_QUIET;
686725

687726
/* passthru commands should let the driver set the SGL flags */
688727
cmd->common.flags &= ~NVME_CMD_SGL_ALL;
@@ -691,8 +730,7 @@ void nvme_init_request(struct request *req, struct nvme_command *cmd)
691730
if (req->mq_hctx->type == HCTX_TYPE_POLL)
692731
req->cmd_flags |= REQ_POLLED;
693732
nvme_clear_nvme_request(req);
694-
req->rq_flags |= RQF_QUIET;
695-
memcpy(nvme_req(req)->cmd, cmd, sizeof(*cmd));
733+
memcpy(nr->cmd, cmd, sizeof(*cmd));
696734
}
697735
EXPORT_SYMBOL_GPL(nvme_init_request);
698736

@@ -3658,6 +3696,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
36583696

36593697
ns->disk = disk;
36603698
ns->queue = disk->queue;
3699+
ns->passthru_err_log_enabled = false;
36613700

36623701
if (ctrl->opts && ctrl->opts->data_digest)
36633702
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->queue);
@@ -3721,6 +3760,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
37213760
nvme_mpath_add_disk(ns, info->anagrpid);
37223761
nvme_fault_inject_init(&ns->fault_inject, ns->disk->disk_name);
37233762

3763+
/*
3764+
* Set ns->disk->device->driver_data to ns so we can access
3765+
* ns->logging_enabled in nvme_passthru_err_log_enabled_store() and
3766+
* nvme_passthru_err_log_enabled_show().
3767+
*/
3768+
dev_set_drvdata(disk_to_dev(ns->disk), ns);
3769+
37243770
return;
37253771

37263772
out_cleanup_ns_from_list:
@@ -4521,6 +4567,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
45214567
int ret;
45224568

45234569
WRITE_ONCE(ctrl->state, NVME_CTRL_NEW);
4570+
ctrl->passthru_err_log_enabled = false;
45244571
clear_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags);
45254572
spin_lock_init(&ctrl->lock);
45264573
mutex_init(&ctrl->scan_lock);

drivers/nvme/host/nvme.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ enum nvme_ctrl_flags {
263263
struct nvme_ctrl {
264264
bool comp_seen;
265265
bool identified;
266+
bool passthru_err_log_enabled;
266267
enum nvme_ctrl_state state;
267268
spinlock_t lock;
268269
struct mutex scan_lock;
@@ -522,7 +523,7 @@ struct nvme_ns {
522523
struct device cdev_device;
523524

524525
struct nvme_fault_inject fault_inject;
525-
526+
bool passthru_err_log_enabled;
526527
};
527528

528529
/* NVMe ns supports metadata actions by the controller (generate/strip) */

drivers/nvme/host/sysfs.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,62 @@ static ssize_t nvme_sysfs_rescan(struct device *dev,
3535
}
3636
static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan);
3737

38+
static ssize_t nvme_adm_passthru_err_log_enabled_show(struct device *dev,
39+
struct device_attribute *attr, char *buf)
40+
{
41+
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
42+
43+
return sysfs_emit(buf,
44+
ctrl->passthru_err_log_enabled ? "on\n" : "off\n");
45+
}
46+
47+
static ssize_t nvme_adm_passthru_err_log_enabled_store(struct device *dev,
48+
struct device_attribute *attr, const char *buf, size_t count)
49+
{
50+
struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
51+
int err;
52+
bool passthru_err_log_enabled;
53+
54+
err = kstrtobool(buf, &passthru_err_log_enabled);
55+
if (err)
56+
return -EINVAL;
57+
58+
ctrl->passthru_err_log_enabled = passthru_err_log_enabled;
59+
60+
return count;
61+
}
62+
63+
static ssize_t nvme_io_passthru_err_log_enabled_show(struct device *dev,
64+
struct device_attribute *attr, char *buf)
65+
{
66+
struct nvme_ns *n = dev_get_drvdata(dev);
67+
68+
return sysfs_emit(buf, n->passthru_err_log_enabled ? "on\n" : "off\n");
69+
}
70+
71+
static ssize_t nvme_io_passthru_err_log_enabled_store(struct device *dev,
72+
struct device_attribute *attr, const char *buf, size_t count)
73+
{
74+
struct nvme_ns *ns = dev_get_drvdata(dev);
75+
int err;
76+
bool passthru_err_log_enabled;
77+
78+
err = kstrtobool(buf, &passthru_err_log_enabled);
79+
if (err)
80+
return -EINVAL;
81+
ns->passthru_err_log_enabled = passthru_err_log_enabled;
82+
83+
return count;
84+
}
85+
86+
static struct device_attribute dev_attr_adm_passthru_err_log_enabled = \
87+
__ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \
88+
nvme_adm_passthru_err_log_enabled_show, nvme_adm_passthru_err_log_enabled_store);
89+
90+
static struct device_attribute dev_attr_io_passthru_err_log_enabled = \
91+
__ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \
92+
nvme_io_passthru_err_log_enabled_show, nvme_io_passthru_err_log_enabled_store);
93+
3894
static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev)
3995
{
4096
struct gendisk *disk = dev_to_disk(dev);
@@ -208,6 +264,7 @@ static struct attribute *nvme_ns_attrs[] = {
208264
&dev_attr_ana_grpid.attr,
209265
&dev_attr_ana_state.attr,
210266
#endif
267+
&dev_attr_io_passthru_err_log_enabled.attr,
211268
NULL,
212269
};
213270

@@ -655,6 +712,7 @@ static struct attribute *nvme_dev_attrs[] = {
655712
#ifdef CONFIG_NVME_TCP_TLS
656713
&dev_attr_tls_key.attr,
657714
#endif
715+
&dev_attr_adm_passthru_err_log_enabled.attr,
658716
NULL
659717
};
660718

0 commit comments

Comments
 (0)