From: Nilay Shroff <nilay@linux.ibm.com>
To: linux-nvme@lists.infradead.org
Cc: kbusch@kernel.org, hch@lst.de, hare@suse.de, sagi@grimberg.me,
chaitanyak@nvidia.com, gjoyce@linux.ibm.com,
Nilay Shroff <nilay@linux.ibm.com>
Subject: [RFC PATCH 4/4] nvme: expose queue information via debugfs
Date: Mon, 20 Apr 2026 17:19:36 +0530 [thread overview]
Message-ID: <20260420115716.3071293-5-nilay@linux.ibm.com> (raw)
In-Reply-To: <20260420115716.3071293-1-nilay@linux.ibm.com>
Add a new debugfs attribute "io_queue_info" to expose per-queue
information for NVMe controllers. For NVMe-TCP, this includes the
CPU handling each I/O queue and the associated TCP flow (source and
destination address/port).
This information can be useful for understanding and tuning the
interaction between NVMe-TCP I/O queues and network stack components,
such as IRQ affinity, RPS/RFS, XPS, or NIC flow steering (ntuple).
The data is exported using seq_file interfaces to allow iteration
over all controller queues.
Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
---
drivers/nvme/host/core.c | 3 +++
drivers/nvme/host/debugfs.c | 53 ++++++++++++++++++++++++++++++++++++-
drivers/nvme/host/nvme.h | 2 ++
drivers/nvme/host/tcp.c | 52 ++++++++++++++++++++++++++++++++++++
4 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 1e33af94c24b..1b0d13374d45 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -4207,6 +4207,8 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info)
if (device_add_disk(ctrl->device, ns->disk, nvme_ns_attr_groups))
goto out_cleanup_ns_from_list;
+ nvme_debugfs_register(ns->disk);
+
if (!nvme_ns_head_multipath(ns->head))
nvme_add_ns_cdev(ns);
@@ -4285,6 +4287,7 @@ static void nvme_ns_remove(struct nvme_ns *ns)
nvme_mpath_remove_sysfs_link(ns);
+ nvme_debugfs_unregister(ns->disk);
del_gendisk(ns->disk);
mutex_lock(&ns->ctrl->namespaces_lock);
diff --git a/drivers/nvme/host/debugfs.c b/drivers/nvme/host/debugfs.c
index ee86138487d0..68c40582fa97 100644
--- a/drivers/nvme/host/debugfs.c
+++ b/drivers/nvme/host/debugfs.c
@@ -22,6 +22,56 @@ struct nvme_debugfs_ctx {
struct nvme_debugfs_attr *attr;
};
+static void *nvme_io_queue_info_start(struct seq_file *m, loff_t *pos)
+{
+ struct nvme_debugfs_ctx *ctx = m->private;
+ struct nvme_ns *ns = ctx->data;
+ struct nvme_ctrl *ctrl = ns->ctrl;
+
+ nvme_get_ctrl(ctrl);
+ /*
+ * IO queues starts at offset 1.
+ */
+ return (++*pos < ctrl->queue_count) ? pos : NULL;
+}
+
+static void *nvme_io_queue_info_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct nvme_debugfs_ctx *ctx = m->private;
+ struct nvme_ns *ns = ctx->data;
+ struct nvme_ctrl *ctrl = ns->ctrl;
+
+ return (++*pos < ctrl->queue_count) ? pos : NULL;
+}
+
+static void nvme_io_queue_info_stop(struct seq_file *m, void *v)
+{
+ struct nvme_debugfs_ctx *ctx = m->private;
+ struct nvme_ns *ns = ctx->data;
+ struct nvme_ctrl *ctrl = ns->ctrl;
+
+ nvme_put_ctrl(ctrl);
+}
+
+static int nvme_io_queue_info_show(struct seq_file *m, void *v)
+{
+ struct nvme_debugfs_ctx *ctx = m->private;
+ struct nvme_ns *ns = ctx->data;
+ struct nvme_ctrl *ctrl = ns->ctrl;
+
+ if (ctrl->ops->print_io_queue_info)
+ return ctrl->ops->print_io_queue_info(m, ctrl, *(loff_t *)v);
+
+ return 0;
+}
+
+const struct seq_operations nvme_io_queue_info_seq_ops = {
+ .start = nvme_io_queue_info_start,
+ .next = nvme_io_queue_info_next,
+ .stop = nvme_io_queue_info_stop,
+ .show = nvme_io_queue_info_show
+};
+
static int nvme_debugfs_show(struct seq_file *m, void *v)
{
struct nvme_debugfs_ctx *ctx = m->private;
@@ -90,7 +140,8 @@ static const struct file_operations nvme_debugfs_fops = {
};
static const struct nvme_debugfs_attr nvme_ns_debugfs_attrs[] = {
- {},
+ {"io_queue_info", 0400, .seq_ops = &nvme_io_queue_info_seq_ops},
+ {}
};
static void nvme_debugfs_create_files(struct request_queue *q,
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 2f3f1d2d19b9..d7ff82971136 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -650,6 +650,8 @@ struct nvme_ctrl_ops {
void (*print_device_info)(struct nvme_ctrl *ctrl);
bool (*supports_pci_p2pdma)(struct nvme_ctrl *ctrl);
unsigned long (*get_virt_boundary)(struct nvme_ctrl *ctrl, bool is_admin);
+ int (*print_io_queue_info)(struct seq_file *m, struct nvme_ctrl *ctrl,
+ int qid);
};
/*
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 9239495122fc..6d06e984de47 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -2723,6 +2723,57 @@ static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
kfree(ctrl);
}
+static int nvme_tcp_print_io_queue_info(struct seq_file *m,
+ struct nvme_ctrl *ctrl, int qid)
+{
+ int cpu;
+ struct sockaddr_storage src, dst;
+ struct nvme_tcp_ctrl *tctrl = to_tcp_ctrl(ctrl);
+ struct nvme_tcp_queue *queue = &tctrl->queues[qid];
+ int ret = -EINVAL;
+
+ if (!qid || qid >= ctrl->queue_count ||
+ !test_bit(NVME_TCP_Q_LIVE, &queue->flags))
+ return -EINVAL;
+
+ mutex_lock(&queue->queue_lock);
+ if (!queue->sock)
+ goto unlock;
+
+ ret = kernel_getsockname(queue->sock, (struct sockaddr *)&src);
+ if (ret <= 0)
+ goto unlock;
+
+ ret = kernel_getpeername(queue->sock, (struct sockaddr *)&dst);
+ if (ret <= 0)
+ goto unlock;
+
+ cpu = (queue->io_cpu == WORK_CPU_UNBOUND) ? -1 : queue->io_cpu;
+
+ if (src.ss_family == AF_INET) {
+ struct sockaddr_in *sip = (struct sockaddr_in *)&src;
+ struct sockaddr_in *dip = (struct sockaddr_in *)&dst;
+
+ seq_printf(m, "qid=%d cpu=%d src_ip=%pI4 src_port=%u dst_ip=%pI4 dst_port=%u\n",
+ qid, cpu,
+ &sip->sin_addr.s_addr, ntohs(sip->sin_port),
+ &dip->sin_addr.s_addr, ntohs(dip->sin_port));
+ ret = 0;
+ } else if (src.ss_family == AF_INET6) {
+ struct sockaddr_in6 *sip6 = (struct sockaddr_in6 *)&src;
+ struct sockaddr_in6 *dip6 = (struct sockaddr_in6 *)&dst;
+
+ seq_printf(m, "qid=%d cpu=%d src_ip=%pI6c src_port=%u dst_ip=%pI6c dst_port=%u\n",
+ qid, cpu,
+ &sip6->sin6_addr, ntohs(sip6->sin6_port),
+ &dip6->sin6_addr, ntohs(dip6->sin6_port));
+ ret = 0;
+ }
+unlock:
+ mutex_unlock(&queue->queue_lock);
+ return ret;
+}
+
static void nvme_tcp_set_sg_null(struct nvme_command *c)
{
struct nvme_sgl_desc *sg = &c->common.dptr.sgl;
@@ -3023,6 +3074,7 @@ static const struct nvme_ctrl_ops nvme_tcp_ctrl_ops = {
.get_address = nvme_tcp_get_address,
.stop_ctrl = nvme_tcp_stop_ctrl,
.get_virt_boundary = nvmf_get_virt_boundary,
+ .print_io_queue_info = nvme_tcp_print_io_queue_info,
};
static bool
--
2.53.0
next prev parent reply other threads:[~2026-04-20 11:57 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-20 11:49 [RFC PATCH 0/4] nvme-tcp: NIC topology aware I/O queue scaling and queue info export Nilay Shroff
2026-04-20 11:49 ` [RFC PATCH 1/4] nvme-tcp: optionally limit I/O queue count based on NIC queues Nilay Shroff
2026-04-24 13:46 ` Christoph Hellwig
2026-04-27 7:37 ` Nilay Shroff
2026-04-24 22:10 ` Sagi Grimberg
2026-04-27 11:57 ` Nilay Shroff
2026-04-20 11:49 ` [RFC PATCH 2/4] nvme-tcp: add a diagnostic message when NIC queues are underutilized Nilay Shroff
2026-04-24 22:15 ` Sagi Grimberg
2026-04-27 12:14 ` Nilay Shroff
2026-04-20 11:49 ` [RFC PATCH 3/4] nvme: add debugfs helpers for NVMe drivers Nilay Shroff
2026-04-20 11:49 ` Nilay Shroff [this message]
2026-04-24 22:23 ` [RFC PATCH 4/4] nvme: expose queue information via debugfs Sagi Grimberg
2026-04-27 12:12 ` Nilay Shroff
2026-04-22 11:10 ` [RFC PATCH 0/4] nvme-tcp: NIC topology aware I/O queue scaling and queue info export Hannes Reinecke
2026-04-24 22:30 ` Sagi Grimberg
2026-04-27 12:11 ` Nilay Shroff
2026-04-27 6:13 ` Nilay Shroff
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=20260420115716.3071293-5-nilay@linux.ibm.com \
--to=nilay@linux.ibm.com \
--cc=chaitanyak@nvidia.com \
--cc=gjoyce@linux.ibm.com \
--cc=hare@suse.de \
--cc=hch@lst.de \
--cc=kbusch@kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=sagi@grimberg.me \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.