net: add sock_set_rcvbuf
Add a helper to directly set the SO_RCVBUFFORCE sockopt from kernel space without going through a fake uaccess. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
ce3d9544ce
Коммит
26cfabf9cd
|
@ -1180,7 +1180,6 @@ static int sctp_listen_for_all(void)
|
|||
struct socket *sock = NULL;
|
||||
int result = -EINVAL;
|
||||
struct connection *con = nodeid2con(0, GFP_NOFS);
|
||||
int bufsize = NEEDED_RMEM;
|
||||
int one = 1;
|
||||
|
||||
if (!con)
|
||||
|
@ -1195,11 +1194,7 @@ static int sctp_listen_for_all(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE,
|
||||
(char *)&bufsize, sizeof(bufsize));
|
||||
if (result)
|
||||
log_print("Error increasing buffer space on socket %d", result);
|
||||
|
||||
sock_set_rcvbuf(sock->sk, NEEDED_RMEM);
|
||||
result = kernel_setsockopt(sock, SOL_SCTP, SCTP_NODELAY, (char *)&one,
|
||||
sizeof(one));
|
||||
if (result < 0)
|
||||
|
|
|
@ -2693,6 +2693,7 @@ 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_sndtimeo(struct sock *sk, s64 secs);
|
||||
|
||||
|
|
|
@ -789,6 +789,35 @@ void sock_set_keepalive(struct 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
|
||||
* at the socket level. Everything here is generic.
|
||||
|
@ -885,30 +914,7 @@ set_sndbuf:
|
|||
* play 'guess the biggest size' games. RCVBUF/SNDBUF
|
||||
* are treated in BSD as hints
|
||||
*/
|
||||
val = 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));
|
||||
__sock_set_rcvbuf(sk, min_t(u32, val, sysctl_rmem_max));
|
||||
break;
|
||||
|
||||
case SO_RCVBUFFORCE:
|
||||
|
@ -920,9 +926,8 @@ set_rcvbuf:
|
|||
/* No negative values (to prevent underflow, as val will be
|
||||
* multiplied by 2).
|
||||
*/
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
goto set_rcvbuf;
|
||||
__sock_set_rcvbuf(sk, max(val, 0));
|
||||
break;
|
||||
|
||||
case SO_KEEPALIVE:
|
||||
if (sk->sk_prot->keepalive)
|
||||
|
|
Загрузка…
Ссылка в новой задаче