diff options
| author | Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com> | 2026-10-27 16:47:10 -0300 |
|---|---|---|
| committer | Keith Busch <kbusch@kernel.org> | 2026-10-28 08:25:36 -0700 |
| commit | cf54a0dff38435bb3b7652872717cd02fdbac0ca (patch) | |
| tree | fb3834c9b6c1f7c967bdbfe9ac9936483d8a9294 | |
| parent | 12c20e2903563acfb949342967adb900310a24d4 (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.c | 8 |
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); |
