[PATCH v4 2/4] nvme-tcp: unify sockopt with do_sock_setsockopt
Geliang Tang
geliang at kernel.org
Mon Aug 17 23:03:01 PDT 2026
From: Geliang Tang <tanggeliang at kylinos.cn>
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 <tanggeliang at kylinos.cn>
---
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
More information about the Linux-nvme
mailing list