Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: add sock_no_linger

Add a helper to directly set the SO_LINGER sockopt from kernel space
with onoff set to true and a linger time of 0 without going through a
fake uaccess.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Christoph Hellwig and committed by
David S. Miller
c433594c b58f0e8f

+16 -37
+1 -8
drivers/nvme/host/tcp.c
··· 1313 1313 { 1314 1314 struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); 1315 1315 struct nvme_tcp_queue *queue = &ctrl->queues[qid]; 1316 - struct linger sol = { .l_onoff = 1, .l_linger = 0 }; 1317 1316 int ret, opt, rcv_pdu_size; 1318 1317 1319 1318 queue->ctrl = ctrl; ··· 1360 1361 * close. This is done to prevent stale data from being sent should 1361 1362 * the network connection be restored before TCP times out. 1362 1363 */ 1363 - ret = kernel_setsockopt(queue->sock, SOL_SOCKET, SO_LINGER, 1364 - (char *)&sol, sizeof(sol)); 1365 - if (ret) { 1366 - dev_err(nctrl->device, 1367 - "failed to set SO_LINGER sock opt %d\n", ret); 1368 - goto err_sock; 1369 - } 1364 + sock_no_linger(queue->sock->sk); 1370 1365 1371 1366 if (so_priority > 0) { 1372 1367 ret = kernel_setsockopt(queue->sock, SOL_SOCKET, SO_PRIORITY,
+1 -5
drivers/nvme/target/tcp.c
··· 1429 1429 { 1430 1430 struct socket *sock = queue->sock; 1431 1431 struct inet_sock *inet = inet_sk(sock->sk); 1432 - struct linger sol = { .l_onoff = 1, .l_linger = 0 }; 1433 1432 int ret; 1434 1433 1435 1434 ret = kernel_getsockname(sock, ··· 1446 1447 * close. This is done to prevent stale data from being sent should 1447 1448 * the network connection be restored before TCP times out. 1448 1449 */ 1449 - ret = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, 1450 - (char *)&sol, sizeof(sol)); 1451 - if (ret) 1452 - return ret; 1450 + sock_no_linger(sock->sk); 1453 1451 1454 1452 if (so_priority > 0) { 1455 1453 ret = kernel_setsockopt(sock, SOL_SOCKET, SO_PRIORITY,
+1
include/net/sock.h
··· 2688 2688 2689 2689 void sock_def_readable(struct sock *sk); 2690 2690 2691 + void sock_no_linger(struct sock *sk); 2691 2692 void sock_set_reuseaddr(struct sock *sk); 2692 2693 2693 2694 #endif /* _SOCK_H */
+9
net/core/sock.c
··· 720 720 } 721 721 EXPORT_SYMBOL(sock_set_reuseaddr); 722 722 723 + void sock_no_linger(struct sock *sk) 724 + { 725 + lock_sock(sk); 726 + sk->sk_lingertime = 0; 727 + sock_set_flag(sk, SOCK_LINGER); 728 + release_sock(sk); 729 + } 730 + EXPORT_SYMBOL(sock_no_linger); 731 + 723 732 /* 724 733 * This is meant for all protocols to use and covers goings on 725 734 * at the socket level. Everything here is generic.
-1
net/rds/tcp.h
··· 73 73 int rds_tcp_accept_one(struct socket *sock); 74 74 int rds_tcp_keepalive(struct socket *sock); 75 75 void *rds_tcp_listen_sock_def_readable(struct net *net); 76 - void rds_tcp_set_linger(struct socket *sock); 77 76 78 77 /* tcp_recv.c */ 79 78 int rds_tcp_recv_init(void);
+1 -1
net/rds/tcp_connect.c
··· 207 207 208 208 if (sock) { 209 209 if (rds_destroy_pending(cp->cp_conn)) 210 - rds_tcp_set_linger(sock); 210 + sock_no_linger(sock->sk); 211 211 sock->ops->shutdown(sock, RCV_SHUTDOWN | SEND_SHUTDOWN); 212 212 lock_sock(sock->sk); 213 213 rds_tcp_restore_callbacks(sock, tc); /* tc->tc_sock = NULL */
+1 -12
net/rds/tcp_listen.c
··· 111 111 return NULL; 112 112 } 113 113 114 - void rds_tcp_set_linger(struct socket *sock) 115 - { 116 - struct linger no_linger = { 117 - .l_onoff = 1, 118 - .l_linger = 0, 119 - }; 120 - 121 - kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, 122 - (char *)&no_linger, sizeof(no_linger)); 123 - } 124 - 125 114 int rds_tcp_accept_one(struct socket *sock) 126 115 { 127 116 struct socket *new_sock = NULL; ··· 230 241 * be pending on it. By setting linger, we achieve the side-effect 231 242 * of avoiding TIME_WAIT state on new_sock. 232 243 */ 233 - rds_tcp_set_linger(new_sock); 244 + sock_no_linger(new_sock->sk); 234 245 kernel_sock_shutdown(new_sock, SHUT_RDWR); 235 246 ret = 0; 236 247 out:
+2 -10
net/sunrpc/svcsock.c
··· 323 323 324 324 static void svc_tcp_kill_temp_xprt(struct svc_xprt *xprt) 325 325 { 326 - struct svc_sock *svsk; 327 - struct socket *sock; 328 - struct linger no_linger = { 329 - .l_onoff = 1, 330 - .l_linger = 0, 331 - }; 326 + struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); 332 327 333 - svsk = container_of(xprt, struct svc_sock, sk_xprt); 334 - sock = svsk->sk_sock; 335 - kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, 336 - (char *)&no_linger, sizeof(no_linger)); 328 + sock_no_linger(svsk->sk_sock->sk); 337 329 } 338 330 339 331 /*