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

net: add sock_set_reuseaddr

Add a helper to directly set the SO_REUSEADDR sockopt from kernel space
without going through a fake uaccess.

For this the iscsi target now has to formally depend on inet to avoid
a mostly theoretical compile failure. For actual operation it already
did depend on having ipv4 or ipv6 support.

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
b58f0e8f 1eba1110

+19 -34
+5 -13
drivers/infiniband/sw/siw/siw_cm.c
··· 1312 1312 static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr, 1313 1313 struct sockaddr *raddr) 1314 1314 { 1315 - int rv, flags = 0, s_val = 1; 1315 + int rv, flags = 0; 1316 1316 size_t size = laddr->sa_family == AF_INET ? 1317 1317 sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); 1318 1318 1319 1319 /* 1320 1320 * Make address available again asap. 1321 1321 */ 1322 - rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val, 1323 - sizeof(s_val)); 1324 - if (rv < 0) 1325 - return rv; 1322 + sock_set_reuseaddr(s->sk); 1326 1323 1327 1324 rv = s->ops->bind(s, laddr, size); 1328 1325 if (rv < 0) ··· 1778 1781 struct siw_cep *cep = NULL; 1779 1782 struct siw_device *sdev = to_siw_dev(id->device); 1780 1783 int addr_family = id->local_addr.ss_family; 1781 - int rv = 0, s_val; 1784 + int rv = 0; 1782 1785 1783 1786 if (addr_family != AF_INET && addr_family != AF_INET6) 1784 1787 return -EAFNOSUPPORT; ··· 1790 1793 /* 1791 1794 * Allow binding local port when still in TIME_WAIT from last close. 1792 1795 */ 1793 - s_val = 1; 1794 - rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val, 1795 - sizeof(s_val)); 1796 - if (rv) { 1797 - siw_dbg(id->device, "setsockopt error: %d\n", rv); 1798 - goto error; 1799 - } 1796 + sock_set_reuseaddr(s->sk); 1797 + 1800 1798 if (addr_family == AF_INET) { 1801 1799 struct sockaddr_in *laddr = &to_sockaddr_in(id->local_addr); 1802 1800
+1 -7
drivers/nvme/target/tcp.c
··· 1632 1632 port->sock->sk->sk_user_data = port; 1633 1633 port->data_ready = port->sock->sk->sk_data_ready; 1634 1634 port->sock->sk->sk_data_ready = nvmet_tcp_listen_data_ready; 1635 + sock_set_reuseaddr(port->sock->sk); 1635 1636 1636 1637 opt = 1; 1637 1638 ret = kernel_setsockopt(port->sock, IPPROTO_TCP, 1638 1639 TCP_NODELAY, (char *)&opt, sizeof(opt)); 1639 1640 if (ret) { 1640 1641 pr_err("failed to set TCP_NODELAY sock opt %d\n", ret); 1641 - goto err_sock; 1642 - } 1643 - 1644 - ret = kernel_setsockopt(port->sock, SOL_SOCKET, SO_REUSEADDR, 1645 - (char *)&opt, sizeof(opt)); 1646 - if (ret) { 1647 - pr_err("failed to set SO_REUSEADDR sock opt %d\n", ret); 1648 1642 goto err_sock; 1649 1643 } 1650 1644
+1 -1
drivers/target/iscsi/Kconfig
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 config ISCSI_TARGET 3 3 tristate "Linux-iSCSI.org iSCSI Target Mode Stack" 4 - depends on NET 4 + depends on INET 5 5 select CRYPTO 6 6 select CRYPTO_CRC32C 7 7 select CRYPTO_CRC32C_INTEL if X86
+1 -8
drivers/target/iscsi/iscsi_target_login.c
··· 909 909 } 910 910 } 911 911 912 - /* FIXME: Someone please explain why this is endian-safe */ 913 - ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 914 - (char *)&opt, sizeof(opt)); 915 - if (ret < 0) { 916 - pr_err("kernel_setsockopt() for SO_REUSEADDR" 917 - " failed\n"); 918 - goto fail; 919 - } 912 + sock_set_reuseaddr(sock->sk); 920 913 921 914 ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND, 922 915 (char *)&opt, sizeof(opt));
+1 -5
fs/dlm/lowcomms.c
··· 1127 1127 kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one, 1128 1128 sizeof(one)); 1129 1129 1130 - result = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1131 - (char *)&one, sizeof(one)); 1130 + sock_set_reuseaddr(sock->sk); 1132 1131 1133 - if (result < 0) { 1134 - log_print("Failed to set SO_REUSEADDR on socket: %d", result); 1135 - } 1136 1132 write_lock_bh(&sock->sk->sk_callback_lock); 1137 1133 sock->sk->sk_user_data = con; 1138 1134 save_listen_callbacks(sock);
+2
include/net/sock.h
··· 2688 2688 2689 2689 void sock_def_readable(struct sock *sk); 2690 2690 2691 + void sock_set_reuseaddr(struct sock *sk); 2692 + 2691 2693 #endif /* _SOCK_H */
+8
net/core/sock.c
··· 712 712 } 713 713 EXPORT_SYMBOL(sk_mc_loop); 714 714 715 + void sock_set_reuseaddr(struct sock *sk) 716 + { 717 + lock_sock(sk); 718 + sk->sk_reuse = SK_CAN_REUSE; 719 + release_sock(sk); 720 + } 721 + EXPORT_SYMBOL(sock_set_reuseaddr); 722 + 715 723 /* 716 724 * This is meant for all protocols to use and covers goings on 717 725 * at the socket level. Everything here is generic.