mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-19 02:34:01 +08:00
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:
parent
ce3d9544ce
commit
26cfabf9cd
@ -1180,7 +1180,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)
|
||||||
@ -1195,11 +1194,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)
|
||||||
|
@ -2693,6 +2693,7 @@ void sock_enable_timestamps(struct sock *sk);
|
|||||||
void sock_no_linger(struct sock *sk);
|
void sock_no_linger(struct sock *sk);
|
||||||
void sock_set_keepalive(struct sock *sk);
|
void sock_set_keepalive(struct sock *sk);
|
||||||
void sock_set_priority(struct sock *sk, u32 priority);
|
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_reuseaddr(struct sock *sk);
|
||||||
void sock_set_sndtimeo(struct sock *sk, s64 secs);
|
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);
|
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.
|
||||||
@ -885,30 +914,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:
|
||||||
@ -920,9 +926,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)
|
||||||
|
Loading…
Reference in New Issue
Block a user