[RFC v2 2/3] nvme: add error logging opt-in

Alan Adamson
2023-03-23T23:04:19Z

Commit d7ac8dca938c ("nvme: quiet user passthrough command errors") disabled error
logging for user passthrough commands. This commit adds the ability to opt-in
to passthrough error logging.

To enable passthrough error logging:
echo 1 > /sys/kernel/debug/nvme0/error-logging

To disable passthrough error logging:
echo 0 > /sys/kernel/debug/nvme0/error-logging

By default, passthrough error logging will remain disabled.

CONFIG_NVME_ERROR_LOGGING_DEBUG_FS needs to be enabled to
to enable passthrough error logging.

Signed-off-by: Alan Adamson <alan.adamson@oracle.com>
---
drivers/nvme/host/Kconfig | 6 ++++++
drivers/nvme/host/core.c | 14 ++++++++++++--
drivers/nvme/host/nvme-debugfs.c | 7 +++++--
drivers/nvme/host/nvme.h | 2 ++
4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
index 70f380c1ccae..def7940f6444 100644
--- a/drivers/nvme/host/Kconfig
+++ b/drivers/nvme/host/Kconfig
@@ -38,6 +38,12 @@ config NVME_FAULT_INJECTION_DEBUG_FS
help
This enables NVMe Fault Injection through debugfs.

+config NVME_ERROR_LOGGING_DEBUG_FS
+ bool "NVMe Passthrough Error Logging"
+ depends on FAULT_INJECTION_DEBUG_FS
+ help
+ This enables NVMe Passthrough command error logging.
+
config NVME_HWMON
bool "NVMe hardware monitoring"
depends on (NVME_CORE=y && HWMON=y) || (NVME_CORE=m && HWMON)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 679d87d4f5e8..48e9abacd80b 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -666,6 +666,8 @@ static inline void nvme_clear_nvme_request(struct request *req)
/* initialize a passthrough request */
void nvme_init_request(struct request *req, struct nvme_command *cmd)
{
+ struct nvme_request *nr = nvme_req(req);
+
if (req->q->queuedata)
req->timeout = NVME_IO_TIMEOUT;
else /* no queuedata implies admin queue */
@@ -678,8 +680,11 @@ void nvme_init_request(struct request *req, struct nvme_command *cmd)
if (req->mq_hctx->type == HCTX_TYPE_POLL)
req->cmd_flags |= REQ_POLLED;
nvme_clear_nvme_request(req);
- req->rq_flags |= RQF_QUIET;
- memcpy(nvme_req(req)->cmd, cmd, sizeof(*cmd));
+
+ if (!nr->ctrl->error_logging)
+ req->rq_flags |= RQF_QUIET;
+
+ memcpy(nr->cmd, cmd, sizeof(*cmd));
}
EXPORT_SYMBOL_GPL(nvme_init_request);

@@ -5193,6 +5198,11 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,

nvme_debugfs_init(&ctrl->debugfs, dev_name(ctrl->device));
nvme_fault_inject_init(&ctrl->debugfs);
+
+ ctrl->error_logging = false;
+ if (IS_ENABLED(CONFIG_NVME_ERROR_LOGGING_DEBUG_FS))
+ nvme_error_logging_init(ctrl);
+
nvme_mpath_init_ctrl(ctrl);
ret = nvme_auth_init_ctrl(ctrl);
if (ret)
diff --git a/drivers/nvme/host/nvme-debugfs.c b/drivers/nvme/host/nvme-debugfs.c
index 87f78b864225..58dadbbfd67c 100644
--- a/drivers/nvme/host/nvme-debugfs.c
+++ b/drivers/nvme/host/nvme-debugfs.c
@@ -8,7 +8,6 @@
#include <linux/moduleparam.h>
#include "nvme.h"

-#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
void nvme_debugfs_init(struct nvme_debugfs *debugfs,
const char *dev_name)
{
@@ -77,4 +76,8 @@ void nvme_should_fail(struct request *req)
}
EXPORT_SYMBOL_GPL(nvme_should_fail);
#endif /* CONFIG_NVME_FAULT_INJECTION_DEBUG_FS */
-#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
+void nvme_error_logging_init(struct nvme_ctrl *ctrl)
+{
+ debugfs_create_bool("error-logging", 0600, ctrl->debugfs.parent,
+ &ctrl->error_logging);
+}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 53d61723ca59..30eb9715e086 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -252,6 +252,7 @@ struct nvme_ctrl {
bool comp_seen;
enum nvme_ctrl_state state;
bool identified;
+ bool error_logging;
spinlock_t lock;
struct mutex scan_lock;
const struct nvme_ctrl_ops *ops;
@@ -618,6 +619,7 @@ static inline void nvme_fault_inject_init(struct nvme_debugfs *debugfs)
}
static inline void nvme_should_fail(struct request *req) {}
#endif
+void nvme_error_logging_init(struct nvme_ctrl *ctrl);
bool nvme_wait_reset(struct nvme_ctrl *ctrl);
int nvme_try_sched_reset(struct nvme_ctrl *ctrl);

--
2.31.1