Skip to content

Commit ebad6d0

Browse files
Sebastian Andrzej Siewiorkuba-moo
authored andcommitted
net/ipv4: Use nested-BH locking for ipv4_tcp_sk.
ipv4_tcp_sk is a per-CPU variable and relies on disabled BH for its locking. Without per-CPU locking in local_bh_disable() on PREEMPT_RT this data structure requires explicit locking. Make a struct with a sock member (original ipv4_tcp_sk) and a local_lock_t and use local_lock_nested_bh() for locking. This change adds only lockdep coverage and does not alter the functional behaviour for !PREEMPT_RT. Cc: David Ahern <[email protected]> Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 585aa62 commit ebad6d0

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

include/net/sock.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,11 @@ struct sock {
544544
netns_tracker ns_tracker;
545545
};
546546

547+
struct sock_bh_locked {
548+
struct sock *sock;
549+
local_lock_t bh_lock;
550+
};
551+
547552
enum sk_pacing {
548553
SK_PACING_NONE = 0,
549554
SK_PACING_NEEDED = 1,

net/ipv4/tcp_ipv4.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
9393
struct inet_hashinfo tcp_hashinfo;
9494
EXPORT_SYMBOL(tcp_hashinfo);
9595

96-
static DEFINE_PER_CPU(struct sock *, ipv4_tcp_sk);
96+
static DEFINE_PER_CPU(struct sock_bh_locked, ipv4_tcp_sk) = {
97+
.bh_lock = INIT_LOCAL_LOCK(bh_lock),
98+
};
9799

98100
static u32 tcp_v4_init_seq(const struct sk_buff *skb)
99101
{
@@ -882,7 +884,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb,
882884
arg.tos = ip_hdr(skb)->tos;
883885
arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
884886
local_bh_disable();
885-
ctl_sk = this_cpu_read(ipv4_tcp_sk);
887+
local_lock_nested_bh(&ipv4_tcp_sk.bh_lock);
888+
ctl_sk = this_cpu_read(ipv4_tcp_sk.sock);
889+
886890
sock_net_set(ctl_sk, net);
887891
if (sk) {
888892
ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
@@ -907,6 +911,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb,
907911
sock_net_set(ctl_sk, &init_net);
908912
__TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
909913
__TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
914+
local_unlock_nested_bh(&ipv4_tcp_sk.bh_lock);
910915
local_bh_enable();
911916

912917
#ifdef CONFIG_TCP_MD5SIG
@@ -1002,7 +1007,8 @@ static void tcp_v4_send_ack(const struct sock *sk,
10021007
arg.tos = tos;
10031008
arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
10041009
local_bh_disable();
1005-
ctl_sk = this_cpu_read(ipv4_tcp_sk);
1010+
local_lock_nested_bh(&ipv4_tcp_sk.bh_lock);
1011+
ctl_sk = this_cpu_read(ipv4_tcp_sk.sock);
10061012
sock_net_set(ctl_sk, net);
10071013
ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
10081014
inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark);
@@ -1017,6 +1023,7 @@ static void tcp_v4_send_ack(const struct sock *sk,
10171023

10181024
sock_net_set(ctl_sk, &init_net);
10191025
__TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
1026+
local_unlock_nested_bh(&ipv4_tcp_sk.bh_lock);
10201027
local_bh_enable();
10211028
}
10221029

@@ -3615,7 +3622,7 @@ void __init tcp_v4_init(void)
36153622

36163623
sk->sk_clockid = CLOCK_MONOTONIC;
36173624

3618-
per_cpu(ipv4_tcp_sk, cpu) = sk;
3625+
per_cpu(ipv4_tcp_sk.sock, cpu) = sk;
36193626
}
36203627
if (register_pernet_subsys(&tcp_sk_ops))
36213628
panic("Failed to create the TCP control socket.\n");

0 commit comments

Comments
 (0)