BACKPORT: tcp: add tcp_sock_set_keepidle

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

Change-Id: I57286ea8efb618476bac4d8d74f16e01b17e12aa
Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
Christoph Hellwig 2020-05-28 07:12:23 +02:00 • committed by basamaryan
commit 259e678a87
No known key found for this signature in database
GPG key ID: 210D5384FB2A5885
4 changed files with 38 additions and 21 deletions

View file

@ -2837,6 +2837,39 @@ static void tcp_enable_tx_delay(void)
}
}
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);
/*
* Socket option code for TCP.
*/
@ -3044,21 +3077,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
break;
case TCP_KEEPIDLE:
if (val < 1 || val > MAX_TCP_KEEPIDLE)
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);
}
}
err = __tcp_sock_set_keepidle(sk, val);
break;
case TCP_KEEPINTVL:
if (val < 1 || val > MAX_TCP_KEEPINTVL)