[PATCH v4 2/4] nvme-tcp: unify sockopt with do_sock_setsockopt

Geliang Tang <[email protected]>
Newsgroups dev.linux.lists.mptcp,org.infradead.lists.linux-nvme,org.kernel.vger.netdev
Message-ID <5d77334ae43750d8c12923148d71077301242c89.1786947923.git.tanggeliang@kylinos.cn>
From: Geliang Tang <[email protected]>

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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.