From: Nilay Shroff <nilay@linux.ibm.com>
To: linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.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: [PATCH v2 2/4] nvme-tcp: limit I/O queue count based on NIC queue count
Date: Mon, 27 Jul 2026 20:46:45 +0530 [thread overview]
Message-ID: <20260727151652.3660476-3-nilay@linux.ibm.com> (raw)
In-Reply-To: <20260727151652.3660476-1-nilay@linux.ibm.com>
NVMe-TCP currently provisions I/O queues based primarily on the number
of online CPUs. On systems where the CPU count significantly exceeds the
number of NIC hardware queues, multiple NVMe-TCP I/O queues end up
sharing the same NIC TX/RX queues. This increases lock contention,
cacheline bouncing, and inter-processor interrupts (IPIs), reducing I/O
efficiency.
Limit the number of NVMe-TCP default I/O queues to the smaller of the
number of online CPUs and the number of NIC hardware queues. Aligning
the number of NVMe-TCP I/O queues with the NIC queue topology reduces
queue sharing, improves locality, and can improve throughput while
reducing tail latency.
The number of NVMe-TCP I/O queues is now limited to:
min(num_online_cpus, num_nic_queues)
Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
---
drivers/nvme/host/tcp.c | 61 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index ba5c7b3e2a7c..a2110287099e 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1774,6 +1774,50 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl,
return ret;
}
+static struct net_device *nvme_tcp_get_netdev(struct nvme_ctrl *ctrl,
+ netdevice_tracker *tracker, gfp_t gfp)
+{
+ struct net_device *dev = NULL;
+
+ if (ctrl->opts->mask & NVMF_OPT_HOST_IFACE)
+ dev = netdev_get_by_name(&init_net, ctrl->opts->host_iface,
+ tracker, gfp);
+ else {
+ struct nvme_tcp_ctrl *tctrl = to_tcp_ctrl(ctrl);
+ struct sockaddr_storage *src = NULL, *dest = NULL;
+
+ if (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)
+ src = &tctrl->src_addr;
+
+ dest = &tctrl->addr;
+
+ dev = netdev_get_by_addr(&init_net, src, dest, tracker, gfp);
+ }
+ return dev;
+}
+
+/*
+ * Returns number of active NIC queues (min of TX/RX), or 0 if device cannot
+ * be determined.
+ */
+static int nvme_tcp_get_netdev_current_queue_count(struct nvme_ctrl *ctrl)
+{
+ struct net_device *dev;
+ int tx_queues, rx_queues;
+ netdevice_tracker tracker;
+
+ dev = nvme_tcp_get_netdev(ctrl, &tracker, GFP_KERNEL);
+ if (!dev)
+ return 0;
+
+ tx_queues = dev->real_num_tx_queues;
+ rx_queues = dev->real_num_rx_queues;
+
+ netdev_put(dev, &tracker);
+
+ return min(tx_queues, rx_queues);
+}
+
static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
key_serial_t pskid)
{
@@ -2165,6 +2209,23 @@ static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
unsigned int nr_io_queues;
int ret;
+ if (!(ctrl->opts->mask & NVMF_OPT_NR_IO_QUEUES)) {
+ int nr_hw_queues;
+
+ nr_hw_queues = nvme_tcp_get_netdev_current_queue_count(ctrl);
+ if (nr_hw_queues <= 0)
+ goto init_queue;
+
+ ctrl->opts->nr_io_queues = min(nr_hw_queues, num_online_cpus());
+
+ if (ctrl->opts->nr_io_queues < num_online_cpus())
+ dev_info(ctrl->device,
+ "limiting I/O queues to %u (NIC queues %d, CPUs %u)\n",
+ ctrl->opts->nr_io_queues, nr_hw_queues,
+ num_online_cpus());
+ }
+
+init_queue:
nr_io_queues = nvmf_nr_io_queues(ctrl->opts);
ret = nvme_set_queue_count(ctrl, &nr_io_queues);
if (ret)
--
2.53.0
next prev parent reply other threads:[~2026-07-27 15:17 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 15:16 [PATCH v2 0/4] nvme-tcp: NIC topology aware I/O queue scaling and queue info export Nilay Shroff
2026-07-27 15:16 ` [PATCH v2 1/4] net: add helper for device lookup by destination address Nilay Shroff
2026-07-27 15:16 ` Nilay Shroff [this message]
2026-07-27 15:16 ` [PATCH v2 3/4] nvme: add debugfs helpers for NVMe drivers Nilay Shroff
2026-07-27 15:16 ` [PATCH v2 4/4] nvme: expose queue information via debugfs 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=20260727151652.3660476-3-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-kernel@vger.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.