aboutsummaryrefslogtreecommitdiffstats
path: root/features/rt/tcp-Remove-superfluous-BH-disable-around-listening_h.patch
diff options
context:
space:
mode:
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.patch108
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
+