Merge branch 'remove-most-callers-of-kernel_setsockopt-v3'

Christoph Hellwig says:

====================
remove most callers of kernel_setsockopt v3

this series removes most callers of the kernel_setsockopt functions, and
instead switches their users to small functions that implement setting a
sockopt directly using a normal kernel function call with type safety and
all the other benefits of not having a function call.

In some cases these functions seem pretty heavy handed as they do
a lock_sock even for just setting a single variable, but this mirrors
the real setsockopt implementation unlike a few drivers that just set
set the fields directly.

Changes since v2:
 - drop the separately merged kernel_getopt_removal
 - drop the sctp patches, as there is conflicting cleanup going on
 - add an additional ACK for the rxrpc changes

Changes since v1:
 - use ->getname for sctp sockets in dlm
 - add a new ->bind_add struct proto method for dlm/sctp
 - switch the ipv6 and remaining sctp helpers to inline function so that
   the ipv6 and sctp modules are not pulled in by any module that could
   potentially use ipv6 or sctp connections
 - remove arguments to various sock_* helpers that are always used with
   the same constant arguments
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-05-28 11:11:46 -07:00
commit 1e372dbd68
40 changed files with 613 additions and 643 deletions

View File

@ -477,7 +477,7 @@ AF_RXRPC sockets support a few socket options at the SOL_RXRPC level:
Encrypted checksum plus packet padded and first eight bytes of packet Encrypted checksum plus packet padded and first eight bytes of packet
encrypted - which includes the actual packet length. encrypted - which includes the actual packet length.
(c) RXRPC_SECURITY_ENCRYPTED (c) RXRPC_SECURITY_ENCRYPT
Encrypted checksum plus entire packet padded and encrypted, including Encrypted checksum plus entire packet padded and encrypted, including
actual packet length. actual packet length.
@ -578,7 +578,7 @@ A client would issue an operation by:
This issues a request_key() to get the key representing the security This issues a request_key() to get the key representing the security
context. The minimum security level can be set:: context. The minimum security level can be set::
unsigned int sec = RXRPC_SECURITY_ENCRYPTED; unsigned int sec = RXRPC_SECURITY_ENCRYPT;
setsockopt(client, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, setsockopt(client, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL,
&sec, sizeof(sec)); &sec, sizeof(sec));
@ -1090,6 +1090,15 @@ The kernel interface functions are as follows:
jiffies). In the event of the timeout occurring, the call will be jiffies). In the event of the timeout occurring, the call will be
aborted and -ETIME or -ETIMEDOUT will be returned. aborted and -ETIME or -ETIMEDOUT will be returned.
(#) Apply the RXRPC_MIN_SECURITY_LEVEL sockopt to a socket from within in the
kernel::
int rxrpc_sock_set_min_security_level(struct sock *sk,
unsigned int val);
This specifies the minimum security level required for calls on this
socket.
Configurable Parameters Configurable Parameters
======================= =======================

View File

@ -1570,34 +1570,6 @@ extern void drbd_set_recv_tcq(struct drbd_device *device, int tcq_enabled);
extern void _drbd_clear_done_ee(struct drbd_device *device, struct list_head *to_be_freed); extern void _drbd_clear_done_ee(struct drbd_device *device, struct list_head *to_be_freed);
extern int drbd_connected(struct drbd_peer_device *); extern int drbd_connected(struct drbd_peer_device *);
static inline void drbd_tcp_cork(struct socket *sock)
{
int val = 1;
(void) kernel_setsockopt(sock, SOL_TCP, TCP_CORK,
(char*)&val, sizeof(val));
}
static inline void drbd_tcp_uncork(struct socket *sock)
{
int val = 0;
(void) kernel_setsockopt(sock, SOL_TCP, TCP_CORK,
(char*)&val, sizeof(val));
}
static inline void drbd_tcp_nodelay(struct socket *sock)
{
int val = 1;
(void) kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
(char*)&val, sizeof(val));
}
static inline void drbd_tcp_quickack(struct socket *sock)
{
int val = 2;
(void) kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
(char*)&val, sizeof(val));
}
/* sets the number of 512 byte sectors of our virtual device */ /* sets the number of 512 byte sectors of our virtual device */
void drbd_set_my_capacity(struct drbd_device *device, sector_t size); void drbd_set_my_capacity(struct drbd_device *device, sector_t size);

View File

@ -660,7 +660,7 @@ static int __send_command(struct drbd_connection *connection, int vnr,
/* DRBD protocol "pings" are latency critical. /* DRBD protocol "pings" are latency critical.
* This is supposed to trigger tcp_push_pending_frames() */ * This is supposed to trigger tcp_push_pending_frames() */
if (!err && (cmd == P_PING || cmd == P_PING_ACK)) if (!err && (cmd == P_PING || cmd == P_PING_ACK))
drbd_tcp_nodelay(sock->socket); tcp_sock_set_nodelay(sock->socket->sk);
return err; return err;
} }

View File

@ -1051,8 +1051,8 @@ randomize:
/* we don't want delays. /* we don't want delays.
* we use TCP_CORK where appropriate, though */ * we use TCP_CORK where appropriate, though */
drbd_tcp_nodelay(sock.socket); tcp_sock_set_nodelay(sock.socket->sk);
drbd_tcp_nodelay(msock.socket); tcp_sock_set_nodelay(msock.socket->sk);
connection->data.socket = sock.socket; connection->data.socket = sock.socket;
connection->meta.socket = msock.socket; connection->meta.socket = msock.socket;
@ -1223,7 +1223,7 @@ static int drbd_recv_header_maybe_unplug(struct drbd_connection *connection, str
* quickly as possible, and let remote TCP know what we have * quickly as possible, and let remote TCP know what we have
* received so far. */ * received so far. */
if (err == -EAGAIN) { if (err == -EAGAIN) {
drbd_tcp_quickack(connection->data.socket); tcp_sock_set_quickack(connection->data.socket->sk, 2);
drbd_unplug_all_devices(connection); drbd_unplug_all_devices(connection);
} }
if (err > 0) { if (err > 0) {
@ -4959,8 +4959,7 @@ static int receive_UnplugRemote(struct drbd_connection *connection, struct packe
{ {
/* Make sure we've acked all the TCP data associated /* Make sure we've acked all the TCP data associated
* with the data requests being unplugged */ * with the data requests being unplugged */
drbd_tcp_quickack(connection->data.socket); tcp_sock_set_quickack(connection->data.socket->sk, 2);
return 0; return 0;
} }
@ -6162,7 +6161,7 @@ void drbd_send_acks_wf(struct work_struct *ws)
rcu_read_unlock(); rcu_read_unlock();
if (tcp_cork) if (tcp_cork)
drbd_tcp_cork(connection->meta.socket); tcp_sock_set_cork(connection->meta.socket->sk, true);
err = drbd_finish_peer_reqs(device); err = drbd_finish_peer_reqs(device);
kref_put(&device->kref, drbd_destroy_device); kref_put(&device->kref, drbd_destroy_device);
@ -6175,7 +6174,7 @@ void drbd_send_acks_wf(struct work_struct *ws)
} }
if (tcp_cork) if (tcp_cork)
drbd_tcp_uncork(connection->meta.socket); tcp_sock_set_cork(connection->meta.socket->sk, false);
return; return;
} }

View File

@ -2098,7 +2098,7 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head *
if (uncork) { if (uncork) {
mutex_lock(&connection->data.mutex); mutex_lock(&connection->data.mutex);
if (connection->data.socket) if (connection->data.socket)
drbd_tcp_uncork(connection->data.socket); tcp_sock_set_cork(connection->data.socket->sk, false);
mutex_unlock(&connection->data.mutex); mutex_unlock(&connection->data.mutex);
} }
@ -2153,9 +2153,9 @@ static void wait_for_work(struct drbd_connection *connection, struct list_head *
mutex_lock(&connection->data.mutex); mutex_lock(&connection->data.mutex);
if (connection->data.socket) { if (connection->data.socket) {
if (cork) if (cork)
drbd_tcp_cork(connection->data.socket); tcp_sock_set_cork(connection->data.socket->sk, true);
else if (!uncork) else if (!uncork)
drbd_tcp_uncork(connection->data.socket); tcp_sock_set_cork(connection->data.socket->sk, false);
} }
mutex_unlock(&connection->data.mutex); mutex_unlock(&connection->data.mutex);
} }

View File

@ -947,16 +947,8 @@ static void siw_accept_newconn(struct siw_cep *cep)
siw_cep_get(new_cep); siw_cep_get(new_cep);
new_s->sk->sk_user_data = new_cep; new_s->sk->sk_user_data = new_cep;
if (siw_tcp_nagle == false) { if (siw_tcp_nagle == false)
int val = 1; tcp_sock_set_nodelay(new_s->sk);
rv = kernel_setsockopt(new_s, SOL_TCP, TCP_NODELAY,
(char *)&val, sizeof(val));
if (rv) {
siw_dbg_cep(cep, "setsockopt NODELAY error: %d\n", rv);
goto error;
}
}
new_cep->state = SIW_EPSTATE_AWAIT_MPAREQ; new_cep->state = SIW_EPSTATE_AWAIT_MPAREQ;
rv = siw_cm_queue_work(new_cep, SIW_CM_WORK_MPATIMEOUT); rv = siw_cm_queue_work(new_cep, SIW_CM_WORK_MPATIMEOUT);
@ -1312,17 +1304,14 @@ static void siw_cm_llp_state_change(struct sock *sk)
static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr, static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr,
struct sockaddr *raddr) struct sockaddr *raddr)
{ {
int rv, flags = 0, s_val = 1; int rv, flags = 0;
size_t size = laddr->sa_family == AF_INET ? size_t size = laddr->sa_family == AF_INET ?
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
/* /*
* Make address available again asap. * Make address available again asap.
*/ */
rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val, sock_set_reuseaddr(s->sk);
sizeof(s_val));
if (rv < 0)
return rv;
rv = s->ops->bind(s, laddr, size); rv = s->ops->bind(s, laddr, size);
if (rv < 0) if (rv < 0)
@ -1389,16 +1378,8 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
siw_dbg_qp(qp, "kernel_bindconnect: error %d\n", rv); siw_dbg_qp(qp, "kernel_bindconnect: error %d\n", rv);
goto error; goto error;
} }
if (siw_tcp_nagle == false) { if (siw_tcp_nagle == false)
int val = 1; tcp_sock_set_nodelay(s->sk);
rv = kernel_setsockopt(s, SOL_TCP, TCP_NODELAY, (char *)&val,
sizeof(val));
if (rv) {
siw_dbg_qp(qp, "setsockopt NODELAY error: %d\n", rv);
goto error;
}
}
cep = siw_cep_alloc(sdev); cep = siw_cep_alloc(sdev);
if (!cep) { if (!cep) {
rv = -ENOMEM; rv = -ENOMEM;
@ -1781,7 +1762,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct siw_cep *cep = NULL; struct siw_cep *cep = NULL;
struct siw_device *sdev = to_siw_dev(id->device); struct siw_device *sdev = to_siw_dev(id->device);
int addr_family = id->local_addr.ss_family; int addr_family = id->local_addr.ss_family;
int rv = 0, s_val; int rv = 0;
if (addr_family != AF_INET && addr_family != AF_INET6) if (addr_family != AF_INET && addr_family != AF_INET6)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
@ -1793,13 +1774,8 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
/* /*
* Allow binding local port when still in TIME_WAIT from last close. * Allow binding local port when still in TIME_WAIT from last close.
*/ */
s_val = 1; sock_set_reuseaddr(s->sk);
rv = kernel_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&s_val,
sizeof(s_val));
if (rv) {
siw_dbg(id->device, "setsockopt error: %d\n", rv);
goto error;
}
if (addr_family == AF_INET) { if (addr_family == AF_INET) {
struct sockaddr_in *laddr = &to_sockaddr_in(id->local_addr); struct sockaddr_in *laddr = &to_sockaddr_in(id->local_addr);

View File

@ -1313,8 +1313,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
{ {
struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
struct nvme_tcp_queue *queue = &ctrl->queues[qid]; struct nvme_tcp_queue *queue = &ctrl->queues[qid];
struct linger sol = { .l_onoff = 1, .l_linger = 0 }; int ret, rcv_pdu_size;
int ret, opt, rcv_pdu_size;
queue->ctrl = ctrl; queue->ctrl = ctrl;
INIT_LIST_HEAD(&queue->send_list); INIT_LIST_HEAD(&queue->send_list);
@ -1337,60 +1336,24 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
} }
/* Single syn retry */ /* Single syn retry */
opt = 1; tcp_sock_set_syncnt(queue->sock->sk, 1);
ret = kernel_setsockopt(queue->sock, IPPROTO_TCP, TCP_SYNCNT,
(char *)&opt, sizeof(opt));
if (ret) {
dev_err(nctrl->device,
"failed to set TCP_SYNCNT sock opt %d\n", ret);
goto err_sock;
}
/* Set TCP no delay */ /* Set TCP no delay */
opt = 1; tcp_sock_set_nodelay(queue->sock->sk);
ret = kernel_setsockopt(queue->sock, IPPROTO_TCP,
TCP_NODELAY, (char *)&opt, sizeof(opt));
if (ret) {
dev_err(nctrl->device,
"failed to set TCP_NODELAY sock opt %d\n", ret);
goto err_sock;
}
/* /*
* Cleanup whatever is sitting in the TCP transmit queue on socket * Cleanup whatever is sitting in the TCP transmit queue on socket
* close. This is done to prevent stale data from being sent should * close. This is done to prevent stale data from being sent should
* the network connection be restored before TCP times out. * the network connection be restored before TCP times out.
*/ */
ret = kernel_setsockopt(queue->sock, SOL_SOCKET, SO_LINGER, sock_no_linger(queue->sock->sk);
(char *)&sol, sizeof(sol));
if (ret) {
dev_err(nctrl->device,
"failed to set SO_LINGER sock opt %d\n", ret);
goto err_sock;
}
if (so_priority > 0) { if (so_priority > 0)
ret = kernel_setsockopt(queue->sock, SOL_SOCKET, SO_PRIORITY, sock_set_priority(queue->sock->sk, so_priority);
(char *)&so_priority, sizeof(so_priority));
if (ret) {
dev_err(ctrl->ctrl.device,
"failed to set SO_PRIORITY sock opt, ret %d\n",
ret);
goto err_sock;
}
}
/* Set socket type of service */ /* Set socket type of service */
if (nctrl->opts->tos >= 0) { if (nctrl->opts->tos >= 0)
opt = nctrl->opts->tos; ip_sock_set_tos(queue->sock->sk, nctrl->opts->tos);
ret = kernel_setsockopt(queue->sock, SOL_IP, IP_TOS,
(char *)&opt, sizeof(opt));
if (ret) {
dev_err(nctrl->device,
"failed to set IP_TOS sock opt %d\n", ret);
goto err_sock;
}
}
queue->sock->sk->sk_allocation = GFP_ATOMIC; queue->sock->sk->sk_allocation = GFP_ATOMIC;
nvme_tcp_set_queue_io_cpu(queue); nvme_tcp_set_queue_io_cpu(queue);

View File

@ -1429,7 +1429,6 @@ static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
{ {
struct socket *sock = queue->sock; struct socket *sock = queue->sock;
struct inet_sock *inet = inet_sk(sock->sk); struct inet_sock *inet = inet_sk(sock->sk);
struct linger sol = { .l_onoff = 1, .l_linger = 0 };
int ret; int ret;
ret = kernel_getsockname(sock, ret = kernel_getsockname(sock,
@ -1447,27 +1446,14 @@ static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
* close. This is done to prevent stale data from being sent should * close. This is done to prevent stale data from being sent should
* the network connection be restored before TCP times out. * the network connection be restored before TCP times out.
*/ */
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, sock_no_linger(sock->sk);
(char *)&sol, sizeof(sol));
if (ret)
return ret;
if (so_priority > 0) { if (so_priority > 0)
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_PRIORITY, sock_set_priority(sock->sk, so_priority);
(char *)&so_priority, sizeof(so_priority));
if (ret)
return ret;
}
/* Set socket type of service */ /* Set socket type of service */
if (inet->rcv_tos > 0) { if (inet->rcv_tos > 0)
int tos = inet->rcv_tos; ip_sock_set_tos(sock->sk, inet->rcv_tos);
ret = kernel_setsockopt(sock, SOL_IP, IP_TOS,
(char *)&tos, sizeof(tos));
if (ret)
return ret;
}
write_lock_bh(&sock->sk->sk_callback_lock); write_lock_bh(&sock->sk->sk_callback_lock);
sock->sk->sk_user_data = queue; sock->sk->sk_user_data = queue;
@ -1588,7 +1574,7 @@ static int nvmet_tcp_add_port(struct nvmet_port *nport)
{ {
struct nvmet_tcp_port *port; struct nvmet_tcp_port *port;
__kernel_sa_family_t af; __kernel_sa_family_t af;
int opt, ret; int ret;
port = kzalloc(sizeof(*port), GFP_KERNEL); port = kzalloc(sizeof(*port), GFP_KERNEL);
if (!port) if (!port)
@ -1632,30 +1618,10 @@ static int nvmet_tcp_add_port(struct nvmet_port *nport)
port->sock->sk->sk_user_data = port; port->sock->sk->sk_user_data = port;
port->data_ready = port->sock->sk->sk_data_ready; port->data_ready = port->sock->sk->sk_data_ready;
port->sock->sk->sk_data_ready = nvmet_tcp_listen_data_ready; port->sock->sk->sk_data_ready = nvmet_tcp_listen_data_ready;
sock_set_reuseaddr(port->sock->sk);
opt = 1; tcp_sock_set_nodelay(port->sock->sk);
ret = kernel_setsockopt(port->sock, IPPROTO_TCP, if (so_priority > 0)
TCP_NODELAY, (char *)&opt, sizeof(opt)); sock_set_priority(port->sock->sk, so_priority);
if (ret) {
pr_err("failed to set TCP_NODELAY sock opt %d\n", ret);
goto err_sock;
}
ret = kernel_setsockopt(port->sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&opt, sizeof(opt));
if (ret) {
pr_err("failed to set SO_REUSEADDR sock opt %d\n", ret);
goto err_sock;
}
if (so_priority > 0) {
ret = kernel_setsockopt(port->sock, SOL_SOCKET, SO_PRIORITY,
(char *)&so_priority, sizeof(so_priority));
if (ret) {
pr_err("failed to set SO_PRIORITY sock opt %d\n", ret);
goto err_sock;
}
}
ret = kernel_bind(port->sock, (struct sockaddr *)&port->addr, ret = kernel_bind(port->sock, (struct sockaddr *)&port->addr,
sizeof(port->addr)); sizeof(port->addr));

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
config ISCSI_TARGET config ISCSI_TARGET
tristate "Linux-iSCSI.org iSCSI Target Mode Stack" tristate "Linux-iSCSI.org iSCSI Target Mode Stack"
depends on NET depends on INET
select CRYPTO select CRYPTO
select CRYPTO_CRC32C select CRYPTO_CRC32C
select CRYPTO_CRC32C_INTEL if X86 select CRYPTO_CRC32C_INTEL if X86

View File

@ -15,6 +15,7 @@
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/tcp.h> /* TCP_NODELAY */ #include <linux/tcp.h> /* TCP_NODELAY */
#include <net/ip.h>
#include <net/ipv6.h> /* ipv6_addr_v4mapped() */ #include <net/ipv6.h> /* ipv6_addr_v4mapped() */
#include <scsi/iscsi_proto.h> #include <scsi/iscsi_proto.h>
#include <target/target_core_base.h> #include <target/target_core_base.h>
@ -855,7 +856,7 @@ int iscsit_setup_np(
struct sockaddr_storage *sockaddr) struct sockaddr_storage *sockaddr)
{ {
struct socket *sock = NULL; struct socket *sock = NULL;
int backlog = ISCSIT_TCP_BACKLOG, ret, opt = 0, len; int backlog = ISCSIT_TCP_BACKLOG, ret, len;
switch (np->np_network_transport) { switch (np->np_network_transport) {
case ISCSI_TCP: case ISCSI_TCP:
@ -897,34 +898,10 @@ int iscsit_setup_np(
/* /*
* Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY. * Set SO_REUSEADDR, and disable Nagel Algorithm with TCP_NODELAY.
*/ */
/* FIXME: Someone please explain why this is endian-safe */ if (np->np_network_transport == ISCSI_TCP)
opt = 1; tcp_sock_set_nodelay(sock->sk);
if (np->np_network_transport == ISCSI_TCP) { sock_set_reuseaddr(sock->sk);
ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ip_sock_set_freebind(sock->sk);
(char *)&opt, sizeof(opt));
if (ret < 0) {
pr_err("kernel_setsockopt() for TCP_NODELAY"
" failed: %d\n", ret);
goto fail;
}
}
/* FIXME: Someone please explain why this is endian-safe */
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&opt, sizeof(opt));
if (ret < 0) {
pr_err("kernel_setsockopt() for SO_REUSEADDR"
" failed\n");
goto fail;
}
ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
(char *)&opt, sizeof(opt));
if (ret < 0) {
pr_err("kernel_setsockopt() for IP_FREEBIND"
" failed\n");
goto fail;
}
ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len); ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
if (ret < 0) { if (ret < 0) {

View File

@ -37,7 +37,6 @@ int afs_open_socket(struct afs_net *net)
{ {
struct sockaddr_rxrpc srx; struct sockaddr_rxrpc srx;
struct socket *socket; struct socket *socket;
unsigned int min_level;
int ret; int ret;
_enter(""); _enter("");
@ -57,9 +56,8 @@ int afs_open_socket(struct afs_net *net)
srx.transport.sin6.sin6_family = AF_INET6; srx.transport.sin6.sin6_family = AF_INET6;
srx.transport.sin6.sin6_port = htons(AFS_CM_PORT); srx.transport.sin6.sin6_port = htons(AFS_CM_PORT);
min_level = RXRPC_SECURITY_ENCRYPT; ret = rxrpc_sock_set_min_security_level(socket->sk,
ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, RXRPC_SECURITY_ENCRYPT);
(void *)&min_level, sizeof(min_level));
if (ret < 0) if (ret < 0)
goto error_2; goto error_2;

View File

@ -3929,14 +3929,8 @@ generic_ip_connect(struct TCP_Server_Info *server)
socket->sk->sk_rcvbuf = 140 * 1024; socket->sk->sk_rcvbuf = 140 * 1024;
} }
if (server->tcp_nodelay) { if (server->tcp_nodelay)
int val = 1; tcp_sock_set_nodelay(socket->sk);
rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
(char *)&val, sizeof(val));
if (rc)
cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
rc);
}
cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n", cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
socket->sk->sk_sndbuf, socket->sk->sk_sndbuf,

View File

@ -325,7 +325,6 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
size_t total_len = 0, sent, size; size_t total_len = 0, sent, size;
struct socket *ssocket = server->ssocket; struct socket *ssocket = server->ssocket;
struct msghdr smb_msg; struct msghdr smb_msg;
int val = 1;
__be32 rfc1002_marker; __be32 rfc1002_marker;
if (cifs_rdma_enabled(server)) { if (cifs_rdma_enabled(server)) {
@ -345,8 +344,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
} }
/* cork the socket */ /* cork the socket */
kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK, tcp_sock_set_cork(ssocket->sk, true);
(char *)&val, sizeof(val));
for (j = 0; j < num_rqst; j++) for (j = 0; j < num_rqst; j++)
send_length += smb_rqst_len(server, &rqst[j]); send_length += smb_rqst_len(server, &rqst[j]);
@ -435,9 +433,7 @@ unmask:
} }
/* uncork it */ /* uncork it */
val = 0; tcp_sock_set_cork(ssocket->sk, false);
kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
(char *)&val, sizeof(val));
if ((total_len > 0) && (total_len != send_length)) { if ((total_len > 0) && (total_len != send_length)) {
cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n", cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",

View File

@ -918,7 +918,6 @@ static void sctp_connect_to_sock(struct connection *con)
int result; int result;
int addr_len; int addr_len;
struct socket *sock; struct socket *sock;
struct __kernel_sock_timeval tv = { .tv_sec = 5, .tv_usec = 0 };
if (con->nodeid == 0) { if (con->nodeid == 0) {
log_print("attempt to connect sock 0 foiled"); log_print("attempt to connect sock 0 foiled");
@ -970,13 +969,10 @@ static void sctp_connect_to_sock(struct connection *con)
* since O_NONBLOCK argument in connect() function does not work here, * since O_NONBLOCK argument in connect() function does not work here,
* then, we should restore the default value of this attribute. * then, we should restore the default value of this attribute.
*/ */
kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_NEW, (char *)&tv, sock_set_sndtimeo(sock->sk, 5);
sizeof(tv));
result = sock->ops->connect(sock, (struct sockaddr *)&daddr, addr_len, result = sock->ops->connect(sock, (struct sockaddr *)&daddr, addr_len,
0); 0);
memset(&tv, 0, sizeof(tv)); sock_set_sndtimeo(sock->sk, 0);
kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_NEW, (char *)&tv,
sizeof(tv));
if (result == -EINPROGRESS) if (result == -EINPROGRESS)
result = 0; result = 0;
@ -1015,7 +1011,6 @@ static void tcp_connect_to_sock(struct connection *con)
struct sockaddr_storage saddr, src_addr; struct sockaddr_storage saddr, src_addr;
int addr_len; int addr_len;
struct socket *sock = NULL; struct socket *sock = NULL;
int one = 1;
int result; int result;
if (con->nodeid == 0) { if (con->nodeid == 0) {
@ -1064,8 +1059,7 @@ static void tcp_connect_to_sock(struct connection *con)
log_print("connecting to %d", con->nodeid); log_print("connecting to %d", con->nodeid);
/* Turn off Nagle's algorithm */ /* Turn off Nagle's algorithm */
kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one, tcp_sock_set_nodelay(sock->sk);
sizeof(one));
result = sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len, result = sock->ops->connect(sock, (struct sockaddr *)&saddr, addr_len,
O_NONBLOCK); O_NONBLOCK);
@ -1107,7 +1101,6 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
{ {
struct socket *sock = NULL; struct socket *sock = NULL;
int result = 0; int result = 0;
int one = 1;
int addr_len; int addr_len;
if (dlm_local_addr[0]->ss_family == AF_INET) if (dlm_local_addr[0]->ss_family == AF_INET)
@ -1124,15 +1117,10 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
} }
/* Turn off Nagle's algorithm */ /* Turn off Nagle's algorithm */
kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&one, tcp_sock_set_nodelay(sock->sk);
sizeof(one));
result = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, sock_set_reuseaddr(sock->sk);
(char *)&one, sizeof(one));
if (result < 0) {
log_print("Failed to set SO_REUSEADDR on socket: %d", result);
}
write_lock_bh(&sock->sk->sk_callback_lock); write_lock_bh(&sock->sk->sk_callback_lock);
sock->sk->sk_user_data = con; sock->sk->sk_user_data = con;
save_listen_callbacks(sock); save_listen_callbacks(sock);
@ -1150,11 +1138,7 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
con->sock = NULL; con->sock = NULL;
goto create_out; goto create_out;
} }
result = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, sock_set_keepalive(sock->sk);
(char *)&one, sizeof(one));
if (result < 0) {
log_print("Set keepalive failed: %d", result);
}
result = sock->ops->listen(sock, 5); result = sock->ops->listen(sock, 5);
if (result < 0) { if (result < 0) {
@ -1192,7 +1176,6 @@ static int sctp_listen_for_all(void)
struct socket *sock = NULL; struct socket *sock = NULL;
int result = -EINVAL; int result = -EINVAL;
struct connection *con = nodeid2con(0, GFP_NOFS); struct connection *con = nodeid2con(0, GFP_NOFS);
int bufsize = NEEDED_RMEM;
int one = 1; int one = 1;
if (!con) if (!con)
@ -1207,11 +1190,7 @@ static int sctp_listen_for_all(void)
goto out; goto out;
} }
result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, sock_set_rcvbuf(sock->sk, NEEDED_RMEM);
(char *)&bufsize, sizeof(bufsize));
if (result)
log_print("Error increasing buffer space on socket %d", result);
result = kernel_setsockopt(sock, SOL_SCTP, SCTP_NODELAY, (char *)&one, result = kernel_setsockopt(sock, SOL_SCTP, SCTP_NODELAY, (char *)&one,
sizeof(one)); sizeof(one));
if (result < 0) if (result < 0)

View File

@ -1441,22 +1441,6 @@ static void o2net_rx_until_empty(struct work_struct *work)
sc_put(sc); sc_put(sc);
} }
static int o2net_set_nodelay(struct socket *sock)
{
int val = 1;
return kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
(void *)&val, sizeof(val));
}
static int o2net_set_usertimeout(struct socket *sock)
{
int user_timeout = O2NET_TCP_USER_TIMEOUT;
return kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
(void *)&user_timeout, sizeof(user_timeout));
}
static void o2net_initialize_handshake(void) static void o2net_initialize_handshake(void)
{ {
o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32( o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32(
@ -1636,17 +1620,8 @@ static void o2net_start_connect(struct work_struct *work)
goto out; goto out;
} }
ret = o2net_set_nodelay(sc->sc_sock); tcp_sock_set_nodelay(sc->sc_sock->sk);
if (ret) { tcp_sock_set_user_timeout(sock->sk, O2NET_TCP_USER_TIMEOUT);
mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret);
goto out;
}
ret = o2net_set_usertimeout(sock);
if (ret) {
mlog(ML_ERROR, "set TCP_USER_TIMEOUT failed with %d\n", ret);
goto out;
}
o2net_register_callbacks(sc->sc_sock->sk, sc); o2net_register_callbacks(sc->sc_sock->sk, sc);
@ -1832,17 +1807,8 @@ static int o2net_accept_one(struct socket *sock, int *more)
*more = 1; *more = 1;
new_sock->sk->sk_allocation = GFP_ATOMIC; new_sock->sk->sk_allocation = GFP_ATOMIC;
ret = o2net_set_nodelay(new_sock); tcp_sock_set_nodelay(new_sock->sk);
if (ret) { tcp_sock_set_user_timeout(new_sock->sk, O2NET_TCP_USER_TIMEOUT);
mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret);
goto out;
}
ret = o2net_set_usertimeout(new_sock);
if (ret) {
mlog(ML_ERROR, "set TCP_USER_TIMEOUT failed with %d\n", ret);
goto out;
}
ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin, 1); ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin, 1);
if (ret < 0) if (ret < 0)

View File

@ -497,4 +497,13 @@ static inline u16 tcp_mss_clamp(const struct tcp_sock *tp, u16 mss)
int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount, int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount,
int shiftlen); int shiftlen);
void tcp_sock_set_cork(struct sock *sk, bool on);
int tcp_sock_set_keepcnt(struct sock *sk, int val);
int tcp_sock_set_keepidle(struct sock *sk, int val);
int tcp_sock_set_keepintvl(struct sock *sk, int val);
void tcp_sock_set_nodelay(struct sock *sk);
void tcp_sock_set_quickack(struct sock *sk, int val);
int tcp_sock_set_syncnt(struct sock *sk, int val);
void tcp_sock_set_user_timeout(struct sock *sk, u32 val);
#endif /* _LINUX_TCP_H */ #endif /* _LINUX_TCP_H */

View File

@ -72,4 +72,6 @@ bool rxrpc_kernel_call_is_complete(struct rxrpc_call *);
void rxrpc_kernel_set_max_life(struct socket *, struct rxrpc_call *, void rxrpc_kernel_set_max_life(struct socket *, struct rxrpc_call *,
unsigned long); unsigned long);
int rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val);
#endif /* _NET_RXRPC_H */ #endif /* _NET_RXRPC_H */

View File

@ -765,4 +765,10 @@ static inline bool inetdev_valid_mtu(unsigned int mtu)
return likely(mtu >= IPV4_MIN_MTU); return likely(mtu >= IPV4_MIN_MTU);
} }
void ip_sock_set_freebind(struct sock *sk);
int ip_sock_set_mtu_discover(struct sock *sk, int val);
void ip_sock_set_pktinfo(struct sock *sk);
void ip_sock_set_recverr(struct sock *sk);
void ip_sock_set_tos(struct sock *sk, int val);
#endif /* _IP_H */ #endif /* _IP_H */

View File

@ -1177,4 +1177,96 @@ int ipv6_sock_mc_join_ssm(struct sock *sk, int ifindex,
const struct in6_addr *addr, unsigned int mode); const struct in6_addr *addr, unsigned int mode);
int ipv6_sock_mc_drop(struct sock *sk, int ifindex, int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
const struct in6_addr *addr); const struct in6_addr *addr);
static inline int ip6_sock_set_v6only(struct sock *sk)
{
if (inet_sk(sk)->inet_num)
return -EINVAL;
lock_sock(sk);
sk->sk_ipv6only = true;
release_sock(sk);
return 0;
}
static inline void ip6_sock_set_recverr(struct sock *sk)
{
lock_sock(sk);
inet6_sk(sk)->recverr = true;
release_sock(sk);
}
static inline int __ip6_sock_set_addr_preferences(struct sock *sk, int val)
{
unsigned int pref = 0;
unsigned int prefmask = ~0;
/* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
switch (val & (IPV6_PREFER_SRC_PUBLIC |
IPV6_PREFER_SRC_TMP |
IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
case IPV6_PREFER_SRC_PUBLIC:
pref |= IPV6_PREFER_SRC_PUBLIC;
prefmask &= ~(IPV6_PREFER_SRC_PUBLIC |
IPV6_PREFER_SRC_TMP);
break;
case IPV6_PREFER_SRC_TMP:
pref |= IPV6_PREFER_SRC_TMP;
prefmask &= ~(IPV6_PREFER_SRC_PUBLIC |
IPV6_PREFER_SRC_TMP);
break;
case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
prefmask &= ~(IPV6_PREFER_SRC_PUBLIC |
IPV6_PREFER_SRC_TMP);
break;
case 0:
break;
default:
return -EINVAL;
}
/* check HOME/COA conflicts */
switch (val & (IPV6_PREFER_SRC_HOME | IPV6_PREFER_SRC_COA)) {
case IPV6_PREFER_SRC_HOME:
prefmask &= ~IPV6_PREFER_SRC_COA;
break;
case IPV6_PREFER_SRC_COA:
pref |= IPV6_PREFER_SRC_COA;
break;
case 0:
break;
default:
return -EINVAL;
}
/* check CGA/NONCGA conflicts */
switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
case IPV6_PREFER_SRC_CGA:
case IPV6_PREFER_SRC_NONCGA:
case 0:
break;
default:
return -EINVAL;
}
inet6_sk(sk)->srcprefs = (inet6_sk(sk)->srcprefs & prefmask) | pref;
return 0;
}
static inline int ip6_sock_set_addr_preferences(struct sock *sk, bool val)
{
int ret;
lock_sock(sk);
ret = __ip6_sock_set_addr_preferences(sk, val);
release_sock(sk);
return ret;
}
static inline void ip6_sock_set_recvpktinfo(struct sock *sk)
{
lock_sock(sk);
inet6_sk(sk)->rxopt.bits.rxinfo = true;
release_sock(sk);
}
#endif /* _NET_IPV6_H */ #endif /* _NET_IPV6_H */

View File

@ -2688,4 +2688,14 @@ static inline bool sk_dev_equal_l3scope(struct sock *sk, int dif)
void sock_def_readable(struct sock *sk); void sock_def_readable(struct sock *sk);
int sock_bindtoindex(struct sock *sk, int ifindex);
void sock_enable_timestamps(struct sock *sk);
void sock_no_linger(struct sock *sk);
void sock_set_keepalive(struct sock *sk);
void sock_set_priority(struct sock *sk, u32 priority);
void sock_set_rcvbuf(struct sock *sk, int val);
void sock_set_reuseaddr(struct sock *sk);
void sock_set_reuseport(struct sock *sk);
void sock_set_sndtimeo(struct sock *sk, s64 secs);
#endif /* _SOCK_H */ #endif /* _SOCK_H */

View File

@ -490,15 +490,8 @@ static int ceph_tcp_connect(struct ceph_connection *con)
return ret; return ret;
} }
if (ceph_test_opt(from_msgr(con->msgr), TCP_NODELAY)) { if (ceph_test_opt(from_msgr(con->msgr), TCP_NODELAY))
int optval = 1; tcp_sock_set_nodelay(sock->sk);
ret = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
(char *)&optval, sizeof(optval));
if (ret)
pr_err("kernel_setsockopt(TCP_NODELAY) failed: %d",
ret);
}
con->sock = sock; con->sock = sock;
return 0; return 0;

View File

@ -566,7 +566,7 @@ struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
} }
EXPORT_SYMBOL(sk_dst_check); EXPORT_SYMBOL(sk_dst_check);
static int sock_setbindtodevice_locked(struct sock *sk, int ifindex) static int sock_bindtoindex_locked(struct sock *sk, int ifindex)
{ {
int ret = -ENOPROTOOPT; int ret = -ENOPROTOOPT;
#ifdef CONFIG_NETDEVICES #ifdef CONFIG_NETDEVICES
@ -594,6 +594,18 @@ out:
return ret; return ret;
} }
int sock_bindtoindex(struct sock *sk, int ifindex)
{
int ret;
lock_sock(sk);
ret = sock_bindtoindex_locked(sk, ifindex);
release_sock(sk);
return ret;
}
EXPORT_SYMBOL(sock_bindtoindex);
static int sock_setbindtodevice(struct sock *sk, char __user *optval, static int sock_setbindtodevice(struct sock *sk, char __user *optval,
int optlen) int optlen)
{ {
@ -634,10 +646,7 @@ static int sock_setbindtodevice(struct sock *sk, char __user *optval,
goto out; goto out;
} }
lock_sock(sk); return sock_bindtoindex(sk, index);
ret = sock_setbindtodevice_locked(sk, index);
release_sock(sk);
out: out:
#endif #endif
@ -712,6 +721,111 @@ bool sk_mc_loop(struct sock *sk)
} }
EXPORT_SYMBOL(sk_mc_loop); EXPORT_SYMBOL(sk_mc_loop);
void sock_set_reuseaddr(struct sock *sk)
{
lock_sock(sk);
sk->sk_reuse = SK_CAN_REUSE;
release_sock(sk);
}
EXPORT_SYMBOL(sock_set_reuseaddr);
void sock_set_reuseport(struct sock *sk)
{
lock_sock(sk);
sk->sk_reuseport = true;
release_sock(sk);
}
EXPORT_SYMBOL(sock_set_reuseport);
void sock_no_linger(struct sock *sk)
{
lock_sock(sk);
sk->sk_lingertime = 0;
sock_set_flag(sk, SOCK_LINGER);
release_sock(sk);
}
EXPORT_SYMBOL(sock_no_linger);
void sock_set_priority(struct sock *sk, u32 priority)
{
lock_sock(sk);
sk->sk_priority = priority;
release_sock(sk);
}
EXPORT_SYMBOL(sock_set_priority);
void sock_set_sndtimeo(struct sock *sk, s64 secs)
{
lock_sock(sk);
if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
sk->sk_sndtimeo = secs * HZ;
else
sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
release_sock(sk);
}
EXPORT_SYMBOL(sock_set_sndtimeo);
static void __sock_set_timestamps(struct sock *sk, bool val, bool new, bool ns)
{
if (val) {
sock_valbool_flag(sk, SOCK_TSTAMP_NEW, new);
sock_valbool_flag(sk, SOCK_RCVTSTAMPNS, ns);
sock_set_flag(sk, SOCK_RCVTSTAMP);
sock_enable_timestamp(sk, SOCK_TIMESTAMP);
} else {
sock_reset_flag(sk, SOCK_RCVTSTAMP);
sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
sock_reset_flag(sk, SOCK_TSTAMP_NEW);
}
}
void sock_enable_timestamps(struct sock *sk)
{
lock_sock(sk);
__sock_set_timestamps(sk, true, false, true);
release_sock(sk);
}
EXPORT_SYMBOL(sock_enable_timestamps);
void sock_set_keepalive(struct sock *sk)
{
lock_sock(sk);
if (sk->sk_prot->keepalive)
sk->sk_prot->keepalive(sk, true);
sock_valbool_flag(sk, SOCK_KEEPOPEN, true);
release_sock(sk);
}
EXPORT_SYMBOL(sock_set_keepalive);
static void __sock_set_rcvbuf(struct sock *sk, int val)
{
/* Ensure val * 2 fits into an int, to prevent max_t() from treating it
* as a negative value.
*/
val = min_t(int, val, INT_MAX / 2);
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
/* We double it on the way in to account for "struct sk_buff" etc.
* overhead. Applications assume that the SO_RCVBUF setting they make
* will allow that much actual data to be received on that socket.
*
* Applications are unaware that "struct sk_buff" and other overheads
* allocate from the receive buffer during socket buffer allocation.
*
* And after considering the possible alternatives, returning the value
* we actually used in getsockopt is the most desirable behavior.
*/
WRITE_ONCE(sk->sk_rcvbuf, max_t(int, val * 2, SOCK_MIN_RCVBUF));
}
void sock_set_rcvbuf(struct sock *sk, int val)
{
lock_sock(sk);
__sock_set_rcvbuf(sk, val);
release_sock(sk);
}
EXPORT_SYMBOL(sock_set_rcvbuf);
/* /*
* This is meant for all protocols to use and covers goings on * This is meant for all protocols to use and covers goings on
* at the socket level. Everything here is generic. * at the socket level. Everything here is generic.
@ -808,30 +922,7 @@ set_sndbuf:
* play 'guess the biggest size' games. RCVBUF/SNDBUF * play 'guess the biggest size' games. RCVBUF/SNDBUF
* are treated in BSD as hints * are treated in BSD as hints
*/ */
val = min_t(u32, val, sysctl_rmem_max); __sock_set_rcvbuf(sk, min_t(u32, val, sysctl_rmem_max));
set_rcvbuf:
/* Ensure val * 2 fits into an int, to prevent max_t()
* from treating it as a negative value.
*/
val = min_t(int, val, INT_MAX / 2);
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
/*
* We double it on the way in to account for
* "struct sk_buff" etc. overhead. Applications
* assume that the SO_RCVBUF setting they make will
* allow that much actual data to be received on that
* socket.
*
* Applications are unaware that "struct sk_buff" and
* other overheads allocate from the receive buffer
* during socket buffer allocation.
*
* And after considering the possible alternatives,
* returning the value we actually used in getsockopt
* is the most desirable behavior.
*/
WRITE_ONCE(sk->sk_rcvbuf,
max_t(int, val * 2, SOCK_MIN_RCVBUF));
break; break;
case SO_RCVBUFFORCE: case SO_RCVBUFFORCE:
@ -843,9 +934,8 @@ set_rcvbuf:
/* No negative values (to prevent underflow, as val will be /* No negative values (to prevent underflow, as val will be
* multiplied by 2). * multiplied by 2).
*/ */
if (val < 0) __sock_set_rcvbuf(sk, max(val, 0));
val = 0; break;
goto set_rcvbuf;
case SO_KEEPALIVE: case SO_KEEPALIVE:
if (sk->sk_prot->keepalive) if (sk->sk_prot->keepalive)
@ -903,28 +993,17 @@ set_rcvbuf:
break; break;
case SO_TIMESTAMP_OLD: case SO_TIMESTAMP_OLD:
case SO_TIMESTAMP_NEW: __sock_set_timestamps(sk, valbool, false, false);
case SO_TIMESTAMPNS_OLD: break;
case SO_TIMESTAMPNS_NEW: case SO_TIMESTAMP_NEW:
if (valbool) { __sock_set_timestamps(sk, valbool, true, false);
if (optname == SO_TIMESTAMP_NEW || optname == SO_TIMESTAMPNS_NEW) break;
sock_set_flag(sk, SOCK_TSTAMP_NEW); case SO_TIMESTAMPNS_OLD:
else __sock_set_timestamps(sk, valbool, false, true);
sock_reset_flag(sk, SOCK_TSTAMP_NEW); break;
case SO_TIMESTAMPNS_NEW:
if (optname == SO_TIMESTAMP_OLD || optname == SO_TIMESTAMP_NEW) __sock_set_timestamps(sk, valbool, true, true);
sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
else
sock_set_flag(sk, SOCK_RCVTSTAMPNS);
sock_set_flag(sk, SOCK_RCVTSTAMP);
sock_enable_timestamp(sk, SOCK_TIMESTAMP);
} else {
sock_reset_flag(sk, SOCK_RCVTSTAMP);
sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
sock_reset_flag(sk, SOCK_TSTAMP_NEW);
}
break; break;
case SO_TIMESTAMPING_NEW: case SO_TIMESTAMPING_NEW:
sock_set_flag(sk, SOCK_TSTAMP_NEW); sock_set_flag(sk, SOCK_TSTAMP_NEW);
/* fall through */ /* fall through */
@ -1180,7 +1259,7 @@ set_rcvbuf:
break; break;
case SO_BINDTOIFINDEX: case SO_BINDTOIFINDEX:
ret = sock_setbindtodevice_locked(sk, val); ret = sock_bindtoindex_locked(sk, val);
break; break;
default: default:

View File

@ -560,6 +560,61 @@ out:
return err; return err;
} }
static void __ip_sock_set_tos(struct sock *sk, int val)
{
if (sk->sk_type == SOCK_STREAM) {
val &= ~INET_ECN_MASK;
val |= inet_sk(sk)->tos & INET_ECN_MASK;
}
if (inet_sk(sk)->tos != val) {
inet_sk(sk)->tos = val;
sk->sk_priority = rt_tos2priority(val);
sk_dst_reset(sk);
}
}
void ip_sock_set_tos(struct sock *sk, int val)
{
lock_sock(sk);
__ip_sock_set_tos(sk, val);
release_sock(sk);
}
EXPORT_SYMBOL(ip_sock_set_tos);
void ip_sock_set_freebind(struct sock *sk)
{
lock_sock(sk);
inet_sk(sk)->freebind = true;
release_sock(sk);
}
EXPORT_SYMBOL(ip_sock_set_freebind);
void ip_sock_set_recverr(struct sock *sk)
{
lock_sock(sk);
inet_sk(sk)->recverr = true;
release_sock(sk);
}
EXPORT_SYMBOL(ip_sock_set_recverr);
int ip_sock_set_mtu_discover(struct sock *sk, int val)
{
if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT)
return -EINVAL;
lock_sock(sk);
inet_sk(sk)->pmtudisc = val;
release_sock(sk);
return 0;
}
EXPORT_SYMBOL(ip_sock_set_mtu_discover);
void ip_sock_set_pktinfo(struct sock *sk)
{
lock_sock(sk);
inet_sk(sk)->cmsg_flags |= IP_CMSG_PKTINFO;
release_sock(sk);
}
EXPORT_SYMBOL(ip_sock_set_pktinfo);
/* /*
* Socket option code for IP. This is the end of the line after any * Socket option code for IP. This is the end of the line after any
@ -823,15 +878,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE; inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
break; break;
case IP_TOS: /* This sets both TOS and Precedence */ case IP_TOS: /* This sets both TOS and Precedence */
if (sk->sk_type == SOCK_STREAM) { __ip_sock_set_tos(sk, val);
val &= ~INET_ECN_MASK;
val |= inet->tos & INET_ECN_MASK;
}
if (inet->tos != val) {
inet->tos = val;
sk->sk_priority = rt_tos2priority(val);
sk_dst_reset(sk);
}
break; break;
case IP_TTL: case IP_TTL:
if (optlen < 1) if (optlen < 1)

View File

@ -2801,6 +2801,163 @@ static void tcp_enable_tx_delay(void)
} }
} }
/* When set indicates to always queue non-full frames. Later the user clears
* this option and we transmit any pending partial frames in the queue. This is
* meant to be used alongside sendfile() to get properly filled frames when the
* user (for example) must write out headers with a write() call first and then
* use sendfile to send out the data parts.
*
* TCP_CORK can be set together with TCP_NODELAY and it is stronger than
* TCP_NODELAY.
*/
static void __tcp_sock_set_cork(struct sock *sk, bool on)
{
struct tcp_sock *tp = tcp_sk(sk);
if (on) {
tp->nonagle |= TCP_NAGLE_CORK;
} else {
tp->nonagle &= ~TCP_NAGLE_CORK;
if (tp->nonagle & TCP_NAGLE_OFF)
tp->nonagle |= TCP_NAGLE_PUSH;
tcp_push_pending_frames(sk);
}
}
void tcp_sock_set_cork(struct sock *sk, bool on)
{
lock_sock(sk);
__tcp_sock_set_cork(sk, on);
release_sock(sk);
}
EXPORT_SYMBOL(tcp_sock_set_cork);
/* TCP_NODELAY is weaker than TCP_CORK, so that this option on corked socket is
* remembered, but it is not activated until cork is cleared.
*
* However, when TCP_NODELAY is set we make an explicit push, which overrides
* even TCP_CORK for currently queued segments.
*/
static void __tcp_sock_set_nodelay(struct sock *sk, bool on)
{
if (on) {
tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF|TCP_NAGLE_PUSH;
tcp_push_pending_frames(sk);
} else {
tcp_sk(sk)->nonagle &= ~TCP_NAGLE_OFF;
}
}
void tcp_sock_set_nodelay(struct sock *sk)
{
lock_sock(sk);
__tcp_sock_set_nodelay(sk, true);
release_sock(sk);
}
EXPORT_SYMBOL(tcp_sock_set_nodelay);
static void __tcp_sock_set_quickack(struct sock *sk, int val)
{
if (!val) {
inet_csk_enter_pingpong_mode(sk);
return;
}
inet_csk_exit_pingpong_mode(sk);
if ((1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
inet_csk_ack_scheduled(sk)) {
inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_PUSHED;
tcp_cleanup_rbuf(sk, 1);
if (!(val & 1))
inet_csk_enter_pingpong_mode(sk);
}
}
void tcp_sock_set_quickack(struct sock *sk, int val)
{
lock_sock(sk);
__tcp_sock_set_quickack(sk, val);
release_sock(sk);
}
EXPORT_SYMBOL(tcp_sock_set_quickack);
int tcp_sock_set_syncnt(struct sock *sk, int val)
{
if (val < 1 || val > MAX_TCP_SYNCNT)
return -EINVAL;
lock_sock(sk);
inet_csk(sk)->icsk_syn_retries = val;
release_sock(sk);
return 0;
}
EXPORT_SYMBOL(tcp_sock_set_syncnt);
void tcp_sock_set_user_timeout(struct sock *sk, u32 val)
{
lock_sock(sk);
inet_csk(sk)->icsk_user_timeout = val;
release_sock(sk);
}
EXPORT_SYMBOL(tcp_sock_set_user_timeout);
static int __tcp_sock_set_keepidle(struct sock *sk, int val)
{
struct tcp_sock *tp = tcp_sk(sk);
if (val < 1 || val > MAX_TCP_KEEPIDLE)
return -EINVAL;
tp->keepalive_time = val * HZ;
if (sock_flag(sk, SOCK_KEEPOPEN) &&
!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
u32 elapsed = keepalive_time_elapsed(tp);
if (tp->keepalive_time > elapsed)
elapsed = tp->keepalive_time - elapsed;
else
elapsed = 0;
inet_csk_reset_keepalive_timer(sk, elapsed);
}
return 0;
}
int tcp_sock_set_keepidle(struct sock *sk, int val)
{
int err;
lock_sock(sk);
err = __tcp_sock_set_keepidle(sk, val);
release_sock(sk);
return err;
}
EXPORT_SYMBOL(tcp_sock_set_keepidle);
int tcp_sock_set_keepintvl(struct sock *sk, int val)
{
if (val < 1 || val > MAX_TCP_KEEPINTVL)
return -EINVAL;
lock_sock(sk);
tcp_sk(sk)->keepalive_intvl = val * HZ;
release_sock(sk);
return 0;
}
EXPORT_SYMBOL(tcp_sock_set_keepintvl);
int tcp_sock_set_keepcnt(struct sock *sk, int val)
{
if (val < 1 || val > MAX_TCP_KEEPCNT)
return -EINVAL;
lock_sock(sk);
tcp_sk(sk)->keepalive_probes = val;
release_sock(sk);
return 0;
}
EXPORT_SYMBOL(tcp_sock_set_keepcnt);
/* /*
* Socket option code for TCP. * Socket option code for TCP.
*/ */
@ -2898,20 +3055,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
break; break;
case TCP_NODELAY: case TCP_NODELAY:
if (val) { __tcp_sock_set_nodelay(sk, val);
/* TCP_NODELAY is weaker than TCP_CORK, so that
* this option on corked socket is remembered, but
* it is not activated until cork is cleared.
*
* However, when TCP_NODELAY is set we make
* an explicit push, which overrides even TCP_CORK
* for currently queued segments.
*/
tp->nonagle |= TCP_NAGLE_OFF|TCP_NAGLE_PUSH;
tcp_push_pending_frames(sk);
} else {
tp->nonagle &= ~TCP_NAGLE_OFF;
}
break; break;
case TCP_THIN_LINEAR_TIMEOUTS: case TCP_THIN_LINEAR_TIMEOUTS:
@ -2979,43 +3123,11 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
break; break;
case TCP_CORK: case TCP_CORK:
/* When set indicates to always queue non-full frames. __tcp_sock_set_cork(sk, val);
* Later the user clears this option and we transmit
* any pending partial frames in the queue. This is
* meant to be used alongside sendfile() to get properly
* filled frames when the user (for example) must write
* out headers with a write() call first and then use
* sendfile to send out the data parts.
*
* TCP_CORK can be set together with TCP_NODELAY and it is
* stronger than TCP_NODELAY.
*/
if (val) {
tp->nonagle |= TCP_NAGLE_CORK;
} else {
tp->nonagle &= ~TCP_NAGLE_CORK;
if (tp->nonagle&TCP_NAGLE_OFF)
tp->nonagle |= TCP_NAGLE_PUSH;
tcp_push_pending_frames(sk);
}
break; break;
case TCP_KEEPIDLE: case TCP_KEEPIDLE:
if (val < 1 || val > MAX_TCP_KEEPIDLE) err = __tcp_sock_set_keepidle(sk, val);
err = -EINVAL;
else {
tp->keepalive_time = val * HZ;
if (sock_flag(sk, SOCK_KEEPOPEN) &&
!((1 << sk->sk_state) &
(TCPF_CLOSE | TCPF_LISTEN))) {
u32 elapsed = keepalive_time_elapsed(tp);
if (tp->keepalive_time > elapsed)
elapsed = tp->keepalive_time - elapsed;
else
elapsed = 0;
inet_csk_reset_keepalive_timer(sk, elapsed);
}
}
break; break;
case TCP_KEEPINTVL: case TCP_KEEPINTVL:
if (val < 1 || val > MAX_TCP_KEEPINTVL) if (val < 1 || val > MAX_TCP_KEEPINTVL)
@ -3072,19 +3184,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
break; break;
case TCP_QUICKACK: case TCP_QUICKACK:
if (!val) { __tcp_sock_set_quickack(sk, val);
inet_csk_enter_pingpong_mode(sk);
} else {
inet_csk_exit_pingpong_mode(sk);
if ((1 << sk->sk_state) &
(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
inet_csk_ack_scheduled(sk)) {
icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
tcp_cleanup_rbuf(sk, 1);
if (!(val & 1))
inet_csk_enter_pingpong_mode(sk);
}
}
break; break;
#ifdef CONFIG_TCP_MD5SIG #ifdef CONFIG_TCP_MD5SIG

View File

@ -22,9 +22,7 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
goto error; goto error;
if (cfg->bind_ifindex) { if (cfg->bind_ifindex) {
err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTOIFINDEX, err = sock_bindtoindex(sock->sk, cfg->bind_ifindex);
(void *)&cfg->bind_ifindex,
sizeof(cfg->bind_ifindex));
if (err < 0) if (err < 0)
goto error; goto error;
} }

View File

@ -25,17 +25,12 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
goto error; goto error;
if (cfg->ipv6_v6only) { if (cfg->ipv6_v6only) {
int val = 1; err = ip6_sock_set_v6only(sock->sk);
err = kernel_setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
(char *) &val, sizeof(val));
if (err < 0) if (err < 0)
goto error; goto error;
} }
if (cfg->bind_ifindex) { if (cfg->bind_ifindex) {
err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTOIFINDEX, err = sock_bindtoindex(sock->sk, cfg->bind_ifindex);
(void *)&cfg->bind_ifindex,
sizeof(cfg->bind_ifindex));
if (err < 0) if (err < 0)
goto error; goto error;
} }

View File

@ -845,67 +845,10 @@ done:
break; break;
case IPV6_ADDR_PREFERENCES: case IPV6_ADDR_PREFERENCES:
{
unsigned int pref = 0;
unsigned int prefmask = ~0;
if (optlen < sizeof(int)) if (optlen < sizeof(int))
goto e_inval; goto e_inval;
retv = __ip6_sock_set_addr_preferences(sk, val);
retv = -EINVAL;
/* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */
switch (val & (IPV6_PREFER_SRC_PUBLIC|
IPV6_PREFER_SRC_TMP|
IPV6_PREFER_SRC_PUBTMP_DEFAULT)) {
case IPV6_PREFER_SRC_PUBLIC:
pref |= IPV6_PREFER_SRC_PUBLIC;
break;
case IPV6_PREFER_SRC_TMP:
pref |= IPV6_PREFER_SRC_TMP;
break;
case IPV6_PREFER_SRC_PUBTMP_DEFAULT:
break;
case 0:
goto pref_skip_pubtmp;
default:
goto e_inval;
}
prefmask &= ~(IPV6_PREFER_SRC_PUBLIC|
IPV6_PREFER_SRC_TMP);
pref_skip_pubtmp:
/* check HOME/COA conflicts */
switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) {
case IPV6_PREFER_SRC_HOME:
break;
case IPV6_PREFER_SRC_COA:
pref |= IPV6_PREFER_SRC_COA;
case 0:
goto pref_skip_coa;
default:
goto e_inval;
}
prefmask &= ~IPV6_PREFER_SRC_COA;
pref_skip_coa:
/* check CGA/NONCGA conflicts */
switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) {
case IPV6_PREFER_SRC_CGA:
case IPV6_PREFER_SRC_NONCGA:
case 0:
break;
default:
goto e_inval;
}
np->srcprefs = (np->srcprefs & prefmask) | pref;
retv = 0;
break; break;
}
case IPV6_MINHOPCOUNT: case IPV6_MINHOPCOUNT:
if (optlen < sizeof(int)) if (optlen < sizeof(int))
goto e_inval; goto e_inval;

View File

@ -89,15 +89,6 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
{ } { }
}; };
/* doing it this way avoids calling tcp_sk() */
void rds_tcp_nonagle(struct socket *sock)
{
int val = 1;
kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (void *)&val,
sizeof(val));
}
u32 rds_tcp_write_seq(struct rds_tcp_connection *tc) u32 rds_tcp_write_seq(struct rds_tcp_connection *tc)
{ {
/* seq# of the last byte of data in tcp send buffer */ /* seq# of the last byte of data in tcp send buffer */
@ -502,7 +493,7 @@ void rds_tcp_tune(struct socket *sock)
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid); struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
rds_tcp_nonagle(sock); tcp_sock_set_nodelay(sock->sk);
lock_sock(sk); lock_sock(sk);
if (rtn->sndbuf_size > 0) { if (rtn->sndbuf_size > 0) {
sk->sk_sndbuf = rtn->sndbuf_size; sk->sk_sndbuf = rtn->sndbuf_size;

View File

@ -50,7 +50,6 @@ struct rds_tcp_statistics {
/* tcp.c */ /* tcp.c */
void rds_tcp_tune(struct socket *sock); void rds_tcp_tune(struct socket *sock);
void rds_tcp_nonagle(struct socket *sock);
void rds_tcp_set_callbacks(struct socket *sock, struct rds_conn_path *cp); void rds_tcp_set_callbacks(struct socket *sock, struct rds_conn_path *cp);
void rds_tcp_reset_callbacks(struct socket *sock, struct rds_conn_path *cp); void rds_tcp_reset_callbacks(struct socket *sock, struct rds_conn_path *cp);
void rds_tcp_restore_callbacks(struct socket *sock, void rds_tcp_restore_callbacks(struct socket *sock,
@ -71,9 +70,8 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6);
void rds_tcp_listen_stop(struct socket *sock, struct work_struct *acceptor); void rds_tcp_listen_stop(struct socket *sock, struct work_struct *acceptor);
void rds_tcp_listen_data_ready(struct sock *sk); void rds_tcp_listen_data_ready(struct sock *sk);
int rds_tcp_accept_one(struct socket *sock); int rds_tcp_accept_one(struct socket *sock);
int rds_tcp_keepalive(struct socket *sock); void rds_tcp_keepalive(struct socket *sock);
void *rds_tcp_listen_sock_def_readable(struct net *net); void *rds_tcp_listen_sock_def_readable(struct net *net);
void rds_tcp_set_linger(struct socket *sock);
/* tcp_recv.c */ /* tcp_recv.c */
int rds_tcp_recv_init(void); int rds_tcp_recv_init(void);

View File

@ -207,7 +207,7 @@ void rds_tcp_conn_path_shutdown(struct rds_conn_path *cp)
if (sock) { if (sock) {
if (rds_destroy_pending(cp->cp_conn)) if (rds_destroy_pending(cp->cp_conn))
rds_tcp_set_linger(sock); sock_no_linger(sock->sk);
sock->ops->shutdown(sock, RCV_SHUTDOWN | SEND_SHUTDOWN); sock->ops->shutdown(sock, RCV_SHUTDOWN | SEND_SHUTDOWN);
lock_sock(sock->sk); lock_sock(sock->sk);
rds_tcp_restore_callbacks(sock, tc); /* tc->tc_sock = NULL */ rds_tcp_restore_callbacks(sock, tc); /* tc->tc_sock = NULL */

View File

@ -38,36 +38,19 @@
#include "rds.h" #include "rds.h"
#include "tcp.h" #include "tcp.h"
int rds_tcp_keepalive(struct socket *sock) void rds_tcp_keepalive(struct socket *sock)
{ {
/* values below based on xs_udp_default_timeout */ /* values below based on xs_udp_default_timeout */
int keepidle = 5; /* send a probe 'keepidle' secs after last data */ int keepidle = 5; /* send a probe 'keepidle' secs after last data */
int keepcnt = 5; /* number of unack'ed probes before declaring dead */ int keepcnt = 5; /* number of unack'ed probes before declaring dead */
int keepalive = 1;
int ret = 0;
ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
(char *)&keepalive, sizeof(keepalive));
if (ret < 0)
goto bail;
ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT,
(char *)&keepcnt, sizeof(keepcnt));
if (ret < 0)
goto bail;
ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE,
(char *)&keepidle, sizeof(keepidle));
if (ret < 0)
goto bail;
sock_set_keepalive(sock->sk);
tcp_sock_set_keepcnt(sock->sk, keepcnt);
tcp_sock_set_keepidle(sock->sk, keepidle);
/* KEEPINTVL is the interval between successive probes. We follow /* KEEPINTVL is the interval between successive probes. We follow
* the model in xs_tcp_finish_connecting() and re-use keepidle. * the model in xs_tcp_finish_connecting() and re-use keepidle.
*/ */
ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, tcp_sock_set_keepintvl(sock->sk, keepidle);
(char *)&keepidle, sizeof(keepidle));
bail:
return ret;
} }
/* rds_tcp_accept_one_path(): if accepting on cp_index > 0, make sure the /* rds_tcp_accept_one_path(): if accepting on cp_index > 0, make sure the
@ -111,17 +94,6 @@ struct rds_tcp_connection *rds_tcp_accept_one_path(struct rds_connection *conn)
return NULL; return NULL;
} }
void rds_tcp_set_linger(struct socket *sock)
{
struct linger no_linger = {
.l_onoff = 1,
.l_linger = 0,
};
kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
(char *)&no_linger, sizeof(no_linger));
}
int rds_tcp_accept_one(struct socket *sock) int rds_tcp_accept_one(struct socket *sock)
{ {
struct socket *new_sock = NULL; struct socket *new_sock = NULL;
@ -160,10 +132,7 @@ int rds_tcp_accept_one(struct socket *sock)
new_sock->ops = sock->ops; new_sock->ops = sock->ops;
__module_get(new_sock->ops->owner); __module_get(new_sock->ops->owner);
ret = rds_tcp_keepalive(new_sock); rds_tcp_keepalive(new_sock);
if (ret < 0)
goto out;
rds_tcp_tune(new_sock); rds_tcp_tune(new_sock);
inet = inet_sk(new_sock->sk); inet = inet_sk(new_sock->sk);
@ -241,7 +210,7 @@ rst_nsk:
* be pending on it. By setting linger, we achieve the side-effect * be pending on it. By setting linger, we achieve the side-effect
* of avoiding TIME_WAIT state on new_sock. * of avoiding TIME_WAIT state on new_sock.
*/ */
rds_tcp_set_linger(new_sock); sock_no_linger(new_sock->sk);
kernel_sock_shutdown(new_sock, SHUT_RDWR); kernel_sock_shutdown(new_sock, SHUT_RDWR);
ret = 0; ret = 0;
out: out:
@ -303,7 +272,7 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6)
} }
sock->sk->sk_reuse = SK_CAN_REUSE; sock->sk->sk_reuse = SK_CAN_REUSE;
rds_tcp_nonagle(sock); tcp_sock_set_nodelay(sock->sk);
write_lock_bh(&sock->sk->sk_callback_lock); write_lock_bh(&sock->sk->sk_callback_lock);
sock->sk->sk_user_data = sock->sk->sk_data_ready; sock->sk->sk_user_data = sock->sk->sk_data_ready;

View File

@ -38,23 +38,18 @@
#include "rds.h" #include "rds.h"
#include "tcp.h" #include "tcp.h"
static void rds_tcp_cork(struct socket *sock, int val)
{
kernel_setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&val, sizeof(val));
}
void rds_tcp_xmit_path_prepare(struct rds_conn_path *cp) void rds_tcp_xmit_path_prepare(struct rds_conn_path *cp)
{ {
struct rds_tcp_connection *tc = cp->cp_transport_data; struct rds_tcp_connection *tc = cp->cp_transport_data;
rds_tcp_cork(tc->t_sock, 1); tcp_sock_set_cork(tc->t_sock->sk, true);
} }
void rds_tcp_xmit_path_complete(struct rds_conn_path *cp) void rds_tcp_xmit_path_complete(struct rds_conn_path *cp)
{ {
struct rds_tcp_connection *tc = cp->cp_transport_data; struct rds_tcp_connection *tc = cp->cp_transport_data;
rds_tcp_cork(tc->t_sock, 0); tcp_sock_set_cork(tc->t_sock->sk, false);
} }
/* the core send_sem serializes this with other xmit and shutdown */ /* the core send_sem serializes this with other xmit and shutdown */

View File

@ -571,6 +571,19 @@ out:
return ret; return ret;
} }
int rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val)
{
if (sk->sk_state != RXRPC_UNBOUND)
return -EISCONN;
if (val > RXRPC_SECURITY_MAX)
return -EINVAL;
lock_sock(sk);
rxrpc_sk(sk)->min_sec_level = val;
release_sock(sk);
return 0;
}
EXPORT_SYMBOL(rxrpc_sock_set_min_security_level);
/* /*
* set RxRPC socket options * set RxRPC socket options
*/ */

View File

@ -107,7 +107,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
{ {
struct sock *usk; struct sock *usk;
int ret, opt; int ret;
_enter("%p{%d,%d}", _enter("%p{%d,%d}",
local, local->srx.transport_type, local->srx.transport.family); local, local->srx.transport_type, local->srx.transport.family);
@ -157,13 +157,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
switch (local->srx.transport.family) { switch (local->srx.transport.family) {
case AF_INET6: case AF_INET6:
/* we want to receive ICMPv6 errors */ /* we want to receive ICMPv6 errors */
opt = 1; ip6_sock_set_recverr(local->socket->sk);
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
/* Fall through and set IPv4 options too otherwise we don't get /* Fall through and set IPv4 options too otherwise we don't get
* errors from IPv4 packets sent through the IPv6 socket. * errors from IPv4 packets sent through the IPv6 socket.
@ -171,31 +165,13 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
/* Fall through */ /* Fall through */
case AF_INET: case AF_INET:
/* we want to receive ICMP errors */ /* we want to receive ICMP errors */
opt = 1; ip_sock_set_recverr(local->socket->sk);
ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
/* we want to set the don't fragment bit */ /* we want to set the don't fragment bit */
opt = IP_PMTUDISC_DO; ip_sock_set_mtu_discover(local->socket->sk, IP_PMTUDISC_DO);
ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
/* We want receive timestamps. */ /* We want receive timestamps. */
opt = 1; sock_enable_timestamps(local->socket->sk);
ret = kernel_setsockopt(local->socket, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
(char *)&opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
break; break;
default: default:

View File

@ -321,7 +321,7 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
struct kvec iov[2]; struct kvec iov[2];
rxrpc_serial_t serial; rxrpc_serial_t serial;
size_t len; size_t len;
int ret, opt; int ret;
_enter(",{%d}", skb->len); _enter(",{%d}", skb->len);
@ -473,18 +473,14 @@ send_fragmentable:
switch (conn->params.local->srx.transport.family) { switch (conn->params.local->srx.transport.family) {
case AF_INET6: case AF_INET6:
case AF_INET: case AF_INET:
opt = IP_PMTUDISC_DONT; ip_sock_set_mtu_discover(conn->params.local->socket->sk,
kernel_setsockopt(conn->params.local->socket, IP_PMTUDISC_DONT);
SOL_IP, IP_MTU_DISCOVER,
(char *)&opt, sizeof(opt));
ret = kernel_sendmsg(conn->params.local->socket, &msg, ret = kernel_sendmsg(conn->params.local->socket, &msg,
iov, 2, len); iov, 2, len);
conn->params.peer->last_tx_at = ktime_get_seconds(); conn->params.peer->last_tx_at = ktime_get_seconds();
opt = IP_PMTUDISC_DO; ip_sock_set_mtu_discover(conn->params.local->socket->sk,
kernel_setsockopt(conn->params.local->socket, IP_PMTUDISC_DO);
SOL_IP, IP_MTU_DISCOVER,
(char *)&opt, sizeof(opt));
break; break;
default: default:

View File

@ -323,17 +323,9 @@ static int svc_tcp_has_wspace(struct svc_xprt *xprt)
static void svc_tcp_kill_temp_xprt(struct svc_xprt *xprt) static void svc_tcp_kill_temp_xprt(struct svc_xprt *xprt)
{ {
struct svc_sock *svsk; struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
struct socket *sock;
struct linger no_linger = {
.l_onoff = 1,
.l_linger = 0,
};
svsk = container_of(xprt, struct svc_sock, sk_xprt); sock_no_linger(svsk->sk_sock->sk);
sock = svsk->sk_sock;
kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
(char *)&no_linger, sizeof(no_linger));
} }
/* /*
@ -603,8 +595,6 @@ static struct svc_xprt_class svc_udp_class = {
static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
{ {
int err, level, optname, one = 1;
svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class, svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class,
&svsk->sk_xprt, serv); &svsk->sk_xprt, serv);
clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags);
@ -624,19 +614,14 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
/* make sure we get destination address info */ /* make sure we get destination address info */
switch (svsk->sk_sk->sk_family) { switch (svsk->sk_sk->sk_family) {
case AF_INET: case AF_INET:
level = SOL_IP; ip_sock_set_pktinfo(svsk->sk_sock->sk);
optname = IP_PKTINFO;
break; break;
case AF_INET6: case AF_INET6:
level = SOL_IPV6; ip6_sock_set_recvpktinfo(svsk->sk_sock->sk);
optname = IPV6_RECVPKTINFO;
break; break;
default: default:
BUG(); BUG();
} }
err = kernel_setsockopt(svsk->sk_sock, level, optname,
(char *)&one, sizeof(one));
dprintk("svc: kernel_setsockopt returned %d\n", err);
} }
/* /*
@ -1337,7 +1322,6 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
struct sockaddr *newsin = (struct sockaddr *)&addr; struct sockaddr *newsin = (struct sockaddr *)&addr;
int newlen; int newlen;
int family; int family;
int val;
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
dprintk("svc: svc_create_socket(%s, %d, %s)\n", dprintk("svc: svc_create_socket(%s, %d, %s)\n",
@ -1373,11 +1357,8 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
* getting requests from IPv4 remotes. Those should * getting requests from IPv4 remotes. Those should
* be shunted to a PF_INET listener via rpcbind. * be shunted to a PF_INET listener via rpcbind.
*/ */
val = 1;
if (family == PF_INET6) if (family == PF_INET6)
kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, ip6_sock_set_v6only(sock->sk);
(char *)&val, sizeof(val));
if (type == SOCK_STREAM) if (type == SOCK_STREAM)
sock->sk->sk_reuse = SK_CAN_REUSE; /* allow address reuse */ sock->sk->sk_reuse = SK_CAN_REUSE; /* allow address reuse */
error = kernel_bind(sock, sin, len); error = kernel_bind(sock, sin, len);

View File

@ -1594,21 +1594,6 @@ static int xs_get_random_port(void)
return rand + min; return rand + min;
} }
/**
* xs_set_reuseaddr_port - set the socket's port and address reuse options
* @sock: socket
*
* Note that this function has to be called on all sockets that share the
* same port, and it must be called before binding.
*/
static void xs_sock_set_reuseport(struct socket *sock)
{
int opt = 1;
kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
(char *)&opt, sizeof(opt));
}
static unsigned short xs_sock_getport(struct socket *sock) static unsigned short xs_sock_getport(struct socket *sock)
{ {
struct sockaddr_storage buf; struct sockaddr_storage buf;
@ -1801,7 +1786,7 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt,
xs_reclassify_socket(family, sock); xs_reclassify_socket(family, sock);
if (reuseport) if (reuseport)
xs_sock_set_reuseport(sock); sock_set_reuseport(sock->sk);
err = xs_bind(transport, sock); err = xs_bind(transport, sock);
if (err) { if (err) {
@ -2110,7 +2095,6 @@ static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
unsigned int keepidle; unsigned int keepidle;
unsigned int keepcnt; unsigned int keepcnt;
unsigned int opt_on = 1;
unsigned int timeo; unsigned int timeo;
spin_lock(&xprt->transport_lock); spin_lock(&xprt->transport_lock);
@ -2122,18 +2106,13 @@ static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
spin_unlock(&xprt->transport_lock); spin_unlock(&xprt->transport_lock);
/* TCP Keepalive options */ /* TCP Keepalive options */
kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, sock_set_keepalive(sock->sk);
(char *)&opt_on, sizeof(opt_on)); tcp_sock_set_keepidle(sock->sk, keepidle);
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, tcp_sock_set_keepintvl(sock->sk, keepidle);
(char *)&keepidle, sizeof(keepidle)); tcp_sock_set_keepcnt(sock->sk, keepcnt);
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
(char *)&keepidle, sizeof(keepidle));
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
(char *)&keepcnt, sizeof(keepcnt));
/* TCP user timeout (see RFC5482) */ /* TCP user timeout (see RFC5482) */
kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, tcp_sock_set_user_timeout(sock->sk, timeo);
(char *)&timeo, sizeof(timeo));
} }
static void xs_tcp_set_connect_timeout(struct rpc_xprt *xprt, static void xs_tcp_set_connect_timeout(struct rpc_xprt *xprt,
@ -2171,7 +2150,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
if (!transport->inet) { if (!transport->inet) {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
unsigned int addr_pref = IPV6_PREFER_SRC_PUBLIC;
/* Avoid temporary address, they are bad for long-lived /* Avoid temporary address, they are bad for long-lived
* connections such as NFS mounts. * connections such as NFS mounts.
@ -2180,8 +2158,10 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
* knowledge about the normal duration of connections, * knowledge about the normal duration of connections,
* MAY override this as appropriate. * MAY override this as appropriate.
*/ */
kernel_setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES, if (xs_addr(xprt)->sa_family == PF_INET6) {
(char *)&addr_pref, sizeof(addr_pref)); ip6_sock_set_addr_preferences(sk,
IPV6_PREFER_SRC_PUBLIC);
}
xs_tcp_set_socket_timeouts(xprt, sock); xs_tcp_set_socket_timeouts(xprt, sock);

View File

@ -196,19 +196,19 @@ static int tsk_importance(struct tipc_sock *tsk)
return msg_importance(&tsk->phdr); return msg_importance(&tsk->phdr);
} }
static int tsk_set_importance(struct tipc_sock *tsk, int imp)
{
if (imp > TIPC_CRITICAL_IMPORTANCE)
return -EINVAL;
msg_set_importance(&tsk->phdr, (u32)imp);
return 0;
}
static struct tipc_sock *tipc_sk(const struct sock *sk) static struct tipc_sock *tipc_sk(const struct sock *sk)
{ {
return container_of(sk, struct tipc_sock, sk); return container_of(sk, struct tipc_sock, sk);
} }
int tsk_set_importance(struct sock *sk, int imp)
{
if (imp > TIPC_CRITICAL_IMPORTANCE)
return -EINVAL;
msg_set_importance(&tipc_sk(sk)->phdr, (u32)imp);
return 0;
}
static bool tsk_conn_cong(struct tipc_sock *tsk) static bool tsk_conn_cong(struct tipc_sock *tsk)
{ {
return tsk->snt_unacked > tsk->snd_win; return tsk->snt_unacked > tsk->snd_win;
@ -2721,7 +2721,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
/* Connect new socket to it's peer */ /* Connect new socket to it's peer */
tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg)); tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
tsk_set_importance(new_tsock, msg_importance(msg)); tsk_set_importance(new_sk, msg_importance(msg));
if (msg_named(msg)) { if (msg_named(msg)) {
new_tsock->conn_type = msg_nametype(msg); new_tsock->conn_type = msg_nametype(msg);
new_tsock->conn_instance = msg_nameinst(msg); new_tsock->conn_instance = msg_nameinst(msg);
@ -3139,7 +3139,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
switch (opt) { switch (opt) {
case TIPC_IMPORTANCE: case TIPC_IMPORTANCE:
res = tsk_set_importance(tsk, value); res = tsk_set_importance(sk, value);
break; break;
case TIPC_SRC_DROPPABLE: case TIPC_SRC_DROPPABLE:
if (sock->type != SOCK_STREAM) if (sock->type != SOCK_STREAM)

View File

@ -75,4 +75,6 @@ u32 tipc_sock_get_portid(struct sock *sk);
bool tipc_sk_overlimit1(struct sock *sk, struct sk_buff *skb); bool tipc_sk_overlimit1(struct sock *sk, struct sk_buff *skb);
bool tipc_sk_overlimit2(struct sock *sk, struct sk_buff *skb); bool tipc_sk_overlimit2(struct sock *sk, struct sk_buff *skb);
int tsk_set_importance(struct sock *sk, int imp);
#endif #endif

View File

@ -497,7 +497,6 @@ static void tipc_topsrv_listener_data_ready(struct sock *sk)
static int tipc_topsrv_create_listener(struct tipc_topsrv *srv) static int tipc_topsrv_create_listener(struct tipc_topsrv *srv)
{ {
int imp = TIPC_CRITICAL_IMPORTANCE;
struct socket *lsock = NULL; struct socket *lsock = NULL;
struct sockaddr_tipc saddr; struct sockaddr_tipc saddr;
struct sock *sk; struct sock *sk;
@ -514,8 +513,9 @@ static int tipc_topsrv_create_listener(struct tipc_topsrv *srv)
sk->sk_user_data = srv; sk->sk_user_data = srv;
write_unlock_bh(&sk->sk_callback_lock); write_unlock_bh(&sk->sk_callback_lock);
rc = kernel_setsockopt(lsock, SOL_TIPC, TIPC_IMPORTANCE, lock_sock(sk);
(char *)&imp, sizeof(imp)); rc = tsk_set_importance(sk, TIPC_CRITICAL_IMPORTANCE);
release_sock(sk);
if (rc < 0) if (rc < 0)
goto err; goto err;