[PATCH v4 2/4] nvme-tcp: unify sockopt with do_sock_setsockopt
From: Geliang Tang <geliang@kernel.org>
Date: 2026-08-18 06:03:48
Also in:
linux-nvme, mptcp
Subsystem:
nvm express driver, the rest · Maintainers:
Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg, Linus Torvalds
From: Geliang Tang <redacted> This patch consolidates socket option settings in nvme-tcp by utilizing the generic do_sock_setsockopt() helper for options including SO_LINGER, SO_PRIORITY, TCP_NODELAY, IP_TOS, SO_BINDTODEVICE, and TCP_SYNCNT. Compared to the target-side implementation, this patch additionally converts SO_BINDTODEVICE and TCP_SYNCNT to use the same unified mechanism. This change eliminates the need to export and use specialized helpers for each individual socket option. Signed-off-by: Geliang Tang <redacted> --- drivers/nvme/host/tcp.c | 91 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 10 deletions(-)
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index ba5c7b3e2a7c..025cade370b2 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c@@ -1774,6 +1774,47 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl, return ret; } +static int nvme_tcp_sock_no_linger(struct sock *sk) +{ + struct linger ling = { .l_onoff = 1, .l_linger = 0 }; + + return do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_LINGER, + KERNEL_SOCKPTR(&ling), sizeof(ling)); +} + +static int nvme_tcp_sock_set_priority(struct sock *sk, u32 priority) +{ + return do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, SO_PRIORITY, + KERNEL_SOCKPTR(&priority), sizeof(priority)); +} + +static int nvme_tcp_sock_set_bindtodevice(struct sock *sk, char *iface) +{ + return do_sock_setsockopt(sk->sk_socket, false, SOL_SOCKET, + SO_BINDTODEVICE, KERNEL_SOCKPTR(iface), + strlen(iface)); +} + +static int nvme_tcp_sock_set_nodelay(struct sock *sk) +{ + int val = 1; + + return do_sock_setsockopt(sk->sk_socket, false, SOL_TCP, TCP_NODELAY, + KERNEL_SOCKPTR(&val), sizeof(val)); +} + +static int nvme_tcp_sock_set_syncnt(struct sock *sk, int val) +{ + return do_sock_setsockopt(sk->sk_socket, false, SOL_TCP, TCP_SYNCNT, + KERNEL_SOCKPTR(&val), sizeof(val)); +} + +static int nvme_tcp_sock_set_tos(struct sock *sk, int tos) +{ + return do_sock_setsockopt(sk->sk_socket, false, SOL_IP, IP_TOS, + KERNEL_SOCKPTR(&tos), sizeof(tos)); +} + static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid, key_serial_t pskid) {
@@ -1819,24 +1860,56 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid, #endif /* Single syn retry */ - tcp_sock_set_syncnt(queue->sock->sk, 1); + ret = nvme_tcp_sock_set_syncnt(queue->sock->sk, 1); + if (ret) { + dev_err(nctrl->device, + "failed to set TCP_SYNCNT on queue %d err %d\n", + qid, ret); + goto err_sock; + } /* Set TCP no delay */ - tcp_sock_set_nodelay(queue->sock->sk); + ret = nvme_tcp_sock_set_nodelay(queue->sock->sk); + if (ret) { + dev_err(nctrl->device, + "failed to set TCP_NODELAY on queue %d err %d\n", + qid, ret); + goto err_sock; + } /* * Cleanup whatever is sitting in the TCP transmit queue on socket * close. This is done to prevent stale data from being sent should * the network connection be restored before TCP times out. */ - sock_no_linger(queue->sock->sk); + ret = nvme_tcp_sock_no_linger(queue->sock->sk); + if (ret) { + dev_err(nctrl->device, + "failed to set SO_LINGER on queue %d err %d\n", + qid, ret); + goto err_sock; + } - if (so_priority > 0) - sock_set_priority(queue->sock->sk, so_priority); + if (so_priority > 0) { + ret = nvme_tcp_sock_set_priority(queue->sock->sk, so_priority); + if (ret) { + dev_err(nctrl->device, + "failed to set SO_PRIORITY on queue %d err %d\n", + qid, ret); + goto err_sock; + } + } /* Set socket type of service */ - if (nctrl->opts->tos >= 0) - ip_sock_set_tos(queue->sock->sk, nctrl->opts->tos); + if (nctrl->opts->tos >= 0) { + ret = nvme_tcp_sock_set_tos(queue->sock->sk, nctrl->opts->tos); + if (ret) { + dev_err(nctrl->device, + "failed to set IP_TOS on queue %d err %d\n", + qid, ret); + goto err_sock; + } + } /* Set 10 seconds timeout for icresp recvmsg */ queue->sock->sk->sk_rcvtimeo = 10 * HZ;
@@ -1864,10 +1937,8 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid, if (nctrl->opts->mask & NVMF_OPT_HOST_IFACE) { char *iface = nctrl->opts->host_iface; - sockptr_t optval = KERNEL_SOCKPTR(iface); - ret = sock_setsockopt(queue->sock, SOL_SOCKET, SO_BINDTODEVICE, - optval, strlen(iface)); + ret = nvme_tcp_sock_set_bindtodevice(queue->sock->sk, iface); if (ret) { dev_err(nctrl->device, "failed to bind to interface %s queue %d err %d\n",
--
2.53.0