diff options
Diffstat (limited to 'features/rt/tcp-Remove-superfluous-BH-disable-around-listening_h.patch')
-rw-r--r-- | features/rt/tcp-Remove-superfluous-BH-disable-around-listening_h.patch | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/features/rt/tcp-Remove-superfluous-BH-disable-around-listening_h.patch b/features/rt/tcp-Remove-superfluous-BH-disable-around-listening_h.patch new file mode 100644 index 00000000..0f158b80 --- /dev/null +++ b/features/rt/tcp-Remove-superfluous-BH-disable-around-listening_h.patch @@ -0,0 +1,108 @@ +From fcb2e8b29c71939fca604cb4e527c14fd83cc683 Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Date: Mon, 12 Oct 2020 17:33:54 +0200 +Subject: [PATCH 039/191] tcp: Remove superfluous BH-disable around + listening_hash + +Commit + 9652dc2eb9e40 ("tcp: relax listening_hash operations") + +removed the need to disable bottom half while acquiring +listening_hash.lock. There are still two callers left which disable +bottom half before the lock is acquired. + +Drop local_bh_disable() around __inet_hash() which acquires +listening_hash->lock, invoke inet_ehash_nolisten() with disabled BH. +inet_unhash() conditionally acquires listening_hash->lock. + +Reported-by: Mike Galbraith <efault@gmx.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Link: https://lore.kernel.org/linux-rt-users/12d6f9879a97cd56c09fb53dee343cbb14f7f1f7.camel@gmx.de/ +Link: https://lkml.kernel.org/r/X9CheYjuXWc75Spa@hirez.programming.kicks-ass.net +--- + net/ipv4/inet_hashtables.c | 19 ++++++++++++------- + net/ipv6/inet6_hashtables.c | 5 +---- + 2 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index c96866a53a66..388e3ebb7f57 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -635,7 +635,9 @@ int __inet_hash(struct sock *sk, struct sock *osk) + int err = 0; + + if (sk->sk_state != TCP_LISTEN) { ++ local_bh_disable(); + inet_ehash_nolisten(sk, osk, NULL); ++ local_bh_enable(); + return 0; + } + WARN_ON(!sk_unhashed(sk)); +@@ -667,11 +669,8 @@ int inet_hash(struct sock *sk) + { + int err = 0; + +- if (sk->sk_state != TCP_CLOSE) { +- local_bh_disable(); ++ if (sk->sk_state != TCP_CLOSE) + err = __inet_hash(sk, NULL); +- local_bh_enable(); +- } + + return err; + } +@@ -682,17 +681,20 @@ void inet_unhash(struct sock *sk) + struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; + struct inet_listen_hashbucket *ilb = NULL; + spinlock_t *lock; ++ bool state_listen; + + if (sk_unhashed(sk)) + return; + + if (sk->sk_state == TCP_LISTEN) { ++ state_listen = true; + ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)]; +- lock = &ilb->lock; ++ spin_lock(&ilb->lock); + } else { ++ state_listen = false; + lock = inet_ehash_lockp(hashinfo, sk->sk_hash); ++ spin_lock_bh(lock); + } +- spin_lock_bh(lock); + if (sk_unhashed(sk)) + goto unlock; + +@@ -705,7 +707,10 @@ void inet_unhash(struct sock *sk) + __sk_nulls_del_node_init_rcu(sk); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + unlock: +- spin_unlock_bh(lock); ++ if (state_listen) ++ spin_unlock(&ilb->lock); ++ else ++ spin_unlock_bh(lock); + } + EXPORT_SYMBOL_GPL(inet_unhash); + +diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c +index 55c290d55605..9bad345cba9a 100644 +--- a/net/ipv6/inet6_hashtables.c ++++ b/net/ipv6/inet6_hashtables.c +@@ -333,11 +333,8 @@ int inet6_hash(struct sock *sk) + { + int err = 0; + +- if (sk->sk_state != TCP_CLOSE) { +- local_bh_disable(); ++ if (sk->sk_state != TCP_CLOSE) + err = __inet_hash(sk, NULL); +- local_bh_enable(); +- } + + return err; + } +-- +2.19.1 + |