aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Aurich Zanettini Martins <christian.aurichzm@gmail.com>2026-10-27 16:47:10 -0300
committerKeith Busch <kbusch@kernel.org>2026-10-28 08:25:36 -0700
commitcf54a0dff38435bb3b7652872717cd02fdbac0ca (patch)
treefb3834c9b6c1f7c967bdbfe9ac9936483d8a9294
parent12c20e2903563acfb949342967adb900310a24d4 (diff)
nvme-tcp: fix request PDU size when header digest is enabled
Since commit 61b0ed3be81b ("nvme-tcp: parallelize I/O queue allocation and startup") the I/O tag set is allocated before the I/O queues. nvme_tcp_init_request() sizes the PDU with nvme_tcp_hdgst_len(queue), but queue->hdr_digest is only set later by nvme_tcp_alloc_queue(), so every I/O PDU is allocated without room for the header digest. With hdr_digest enabled, the digest is then written 4 bytes past the PDU, over the header of the next PDU in the page_frag cache, and the target drops the connection on the first I/O: nvmet_tcp: unexpected pdu type 159 nvmet: ctrl 1 fatal error occurred! Queues that a later reconnect adds for the first time have the same problem. Set queue->hdr_digest when allocating the controller, together with pf_cache_lock, so it is valid before any request is initialized. Fixes: 61b0ed3be81b ("nvme-tcp: parallelize I/O queue allocation and startup") Signed-off-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com> Signed-off-by: Keith Busch <kbusch@kernel.org>
-rw-r--r--drivers/nvme/host/tcp.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index dbefe36b0575..191e5811d25e 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -2079,7 +2079,6 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid,
}
}
- queue->hdr_digest = nctrl->opts->hdr_digest;
queue->data_digest = nctrl->opts->data_digest;
rcv_pdu_size = sizeof(struct nvme_tcp_rsp_pdu) +
@@ -3229,10 +3228,13 @@ static struct nvme_tcp_ctrl *nvme_tcp_alloc_ctrl(struct device *dev,
/*
* The I/O tag set is allocated before the I/O queues, and initializing
* its requests already allocates the PDUs from the page frag caches of
- * the queues, so initialize their locks here.
+ * the queues, sized by their header digest setting, so set up the
+ * locks and hdr_digest here.
*/
- for (i = 0; i < ctrl->ctrl.queue_count; i++)
+ for (i = 0; i < ctrl->ctrl.queue_count; i++) {
mutex_init(&ctrl->queues[i].pf_cache_lock);
+ ctrl->queues[i].hdr_digest = opts->hdr_digest;
+ }
ctrl->net = get_net(current->nsproxy->net_ns);