Skip to contentSkip to conversation

Linux 5.4.74-rt42-rc1

PATCH In review Steven Rostedt 2 participants 11 messages Nov 7, 2020 – Nov 9, 2020

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover Linux 5.4.74-rt42-rc1

Dear RT Folks,

This is the RT stable review cycle of patch 5.4.74-rt42-rc1.

Please scream at me if I messed something up. Please test the patches too.

The -rc release will be uploaded to kernel.org and will be deleted when the final release is out. This is just a review release (or release candidate).

The pre-releases will not be pushed to the git repository, only the final release is.

If all goes well, this patch will be converted to the next main release on 11/10/2020.

Enjoy,

-- Steve

To build 5.4.74-rt42-rc1 directly, the following patches should be applied:

http://www.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.xz

http://www.kernel.org/pub/linux/kernel/v5.x/patch-5.4.74.xz

http://www.kernel.org/pub/linux/kernel/projects/rt/5.4/patch-5.4.74-rt42-rc1.patch.xz

You can also build from 5.4.74-rt41 by applying the incremental patch:

http://www.kernel.org/pub/linux/kernel/projects/rt/5.4/incr/patch-5.4.74-rt41-rt42-rc1.patch.xz

Changes from 5.4.74-rt41:

---

Oleg Nesterov (1):
ptrace: fix ptrace_unfreeze_traced() race with rt-lock

Sebastian Andrzej Siewior (4):
net: Properly annotate the try-lock for the seqlock
tcp: Remove superfluous BH-disable around listening_hash mm/memcontrol: Disable preemption in __mod_memcg_lruvec_state()
timers: Don't block on ->expiry_lock for TIMER_IRQSAFE

Steven Rostedt (VMware) (1):

      Linux 5.4.74-rt42-rc1

----

 include/linux/seqlock.h     |  9 ---------
 include/net/sch_generic.h   | 10 +++++++++-
 kernel/ptrace.c             | 23 +++++++++++++++--------
 kernel/time/timer.c         |  9 ++++++++-
 localversion-rt             |  2 +-
 mm/memcontrol.c             |  2 ++
 net/ipv4/inet_hashtables.c  | 19 ++++++++++++-------
 net/ipv6/inet6_hashtables.c |  5 +----
 8 files changed, 48 insertions(+), 31 deletions(-)
#1 lore raw

PATCH 1/6 net: Properly annotate the try-lock for the seqlock

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

In patch
("net/Qdisc: use a seqlock instead seqcount")

the seqcount has been replaced with a seqlock to allow to reader to boost the preempted writer.
The try_write_seqlock() acquired the lock with a try-lock but the seqcount annotation was "lock".

Opencode write_seqcount_t_begin() and use the try-lock annotation for lockdep.

---
 include/linux/seqlock.h   |  9 ---------
 include/net/sch_generic.h | 10 +++++++++-
 2 files changed, 9 insertions(+), 10 deletions(-)
include/linux/seqlock.h +0 -9
index e5207897c33e..f390293974ea 100644
@@ -489,15 +489,6 @@ static inline void write_seqlock(seqlock_t *sl)
 	__raw_write_seqcount_begin(&sl->seqcount);
 }
 
-static inline int try_write_seqlock(seqlock_t *sl)
-{
-	if (spin_trylock(&sl->lock)) {
-		__raw_write_seqcount_begin(&sl->seqcount);
-		return 1;
-	}
-	return 0;
-}
-
 static inline void write_sequnlock(seqlock_t *sl)
 {
 	__raw_write_seqcount_end(&sl->seqcount);
include/net/sch_generic.h +9 -1
index e6afb4b9cede..112d2dca8b08 100644
@@ -168,8 +168,16 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc)
 		return false;
 	}
 #ifdef CONFIG_PREEMPT_RT
-	if (try_write_seqlock(&qdisc->running))
+	if (spin_trylock(&qdisc->running.lock)) {
+		seqcount_t *s = &qdisc->running.seqcount;
+		/*
+		 * Variant of write_seqcount_t_begin() telling lockdep that a
+		 * trylock was attempted.
+		 */
+		__raw_write_seqcount_begin(s);
+		seqcount_acquire(&s->dep_map, 0, 1, _RET_IP_);
 		return true;
+	}
 	return false;
 #else
 	/* Variant of write_seqcount_begin() telling lockdep a trylock
Signature · 1 line
2.28.0
#2 lore raw

PATCH 2/6 tcp: Remove superfluous BH-disable around listening_hash

In reply to Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

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.

---
 net/ipv4/inet_hashtables.c  | 19 ++++++++++++-------
 net/ipv6/inet6_hashtables.c |  5 +----
 2 files changed, 13 insertions(+), 11 deletions(-)
net/ipv4/inet_hashtables.c +12 -7
index 006a34b18537..4c8565d6624c 100644
@@ -543,7 +543,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);
+		local_bh_enable();
 		return 0;
 	}
 	WARN_ON(!sk_unhashed(sk));
@@ -575,11 +577,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;
 }
@@ -590,17 +589,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;
 
@@ -613,7 +615,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);
 
net/ipv6/inet6_hashtables.c +1 -4
index fbe9d4295eac..5d1c1c6967cb 100644
@@ -287,11 +287,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;
 }
Signature · 1 line
2.28.0
#3 lore raw

Re: [PATCH RT 2/6] tcp: Remove superfluous BH-disable around listening_hash

Quoted 2 lines · Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

Please drop that one. Lockep complains on RT with newer softirq code. Older RT and mainline does not complain here unless it observes inet_listen_hashbucket::lock in serving-softirq context (which is not the case).

Sebastian

#4 lore raw

Re: [PATCH RT 2/6] tcp: Remove superfluous BH-disable around listening_hash

Quoted 9 lines · On Mon, 9 Nov 2020 10:22:31 +0100 Sebastian Andrzej Siewior…
Quoted 2 lines · Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

Please drop that one. Lockep complains on RT with newer softirq code. Older RT and mainline does not complain here unless it observes inet_listen_hashbucket::lock in serving-softirq context (which is not the case).

Note, I took this because it mentioned:

"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."

And that commit was added in 4.10.

I will remove it and release a rc2.

Thanks!

-- Steve

#5 lore raw

Re: [PATCH RT 2/6] tcp: Remove superfluous BH-disable around listening_hash

Quoted 10 lines · Steven Rostedt

Note, I took this because it mentioned:

"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."

And that commit was added in 4.10.

Yes. I was aiming to sell this as an optimisation to upstream but that patch isn't exactly a beauty queen and that optimisation isn't enormous so they may not want to buy it.
Also: upstream's lockdep isn't complaining here so the alternative route is to get RT's lockdep to be quiet here as well and then drop that patch.

Sebastian

#6 lore raw

PATCH 3/6 mm/memcontrol: Disable preemption in __mod_memcg_lruvec_state()

In reply to Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

The callers expect disabled preemption/interrupts while invoking __mod_memcg_lruvec_state(). This works mainline because a lock of somekind is acquired.

Use preempt_disable_rt() where per-CPU variables are accessed and a stable pointer is expected. This is also done in __mod_zone_page_state() for the same reason.

---
 mm/memcontrol.c | 2 ++
 1 file changed, 2 insertions(+)
mm/memcontrol.c +2 -0
index 9bdb75ef6d62..c9d02e2272e1 100644
@@ -752,6 +752,7 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
 	pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
 	memcg = pn->memcg;
 
+	preempt_disable_rt();
 	/* Update memcg */
 	__mod_memcg_state(memcg, idx, val);
 
@@ -767,6 +768,7 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
 		x = 0;
 	}
 	__this_cpu_write(pn->lruvec_stat_cpu->count[idx], x);
+	preempt_enable_rt();
 }
 
 void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
Signature · 1 line
2.28.0
#7 lore raw

PATCH 4/6 ptrace: fix ptrace_unfreeze_traced() race with rt-lock

In reply to Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Oleg Nesterov <[email protected]>

The patch "ptrace: fix ptrace vs tasklist_lock race" changed ptrace_freeze_traced() to take task->saved_state into account, but ptrace_unfreeze_traced() has the same problem and needs a similar fix:
it should check/update both ->state and ->saved_state.

---
 kernel/ptrace.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)
kernel/ptrace.c +15 -8
index 3075006d720e..3f7156f06b6c 100644
@@ -197,8 +197,8 @@ static bool ptrace_freeze_traced(struct task_struct *task)
 
 static void ptrace_unfreeze_traced(struct task_struct *task)
 {
-	if (task->state != __TASK_TRACED)
-		return;
+	unsigned long flags;
+	bool frozen = true;
 
 	WARN_ON(!task->ptrace || task->parent != current);
 
@@ -207,12 +207,19 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
 	 * Recheck state under the lock to close this race.
 	 */
 	spin_lock_irq(&task->sighand->siglock);
-	if (task->state == __TASK_TRACED) {
-		if (__fatal_signal_pending(task))
-			wake_up_state(task, __TASK_TRACED);
-		else
-			task->state = TASK_TRACED;
-	}
+
+	raw_spin_lock_irqsave(&task->pi_lock, flags);
+	if (task->state == __TASK_TRACED)
+		task->state = TASK_TRACED;
+	else if (task->saved_state == __TASK_TRACED)
+		task->saved_state = TASK_TRACED;
+	else
+		frozen = false;
+	raw_spin_unlock_irqrestore(&task->pi_lock, flags);
+
+	if (frozen && __fatal_signal_pending(task))
+		wake_up_state(task, __TASK_TRACED);
+
 	spin_unlock_irq(&task->sighand->siglock);
 }
 
Signature · 1 line
2.28.0
#8 lore raw

PATCH 5/6 timers: Dont block on ->expiry_lock for TIMER_IRQSAFE

In reply to Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: Sebastian Andrzej Siewior <[email protected]>

PREEMPT_RT does not spin and wait until a running timer completes its callback but instead it blocks on a sleeping lock to prevent a deadlock.

This blocking can not be done for workqueue's IRQ_SAFE timer which will be canceled in an IRQ-off region. It has to happen to in IRQ-off region because changing the PENDING bit and clearing the timer must not be interrupted to avoid a busy-loop.

The callback invocation of IRQSAFE timer is not preempted on PREEMPT_RT so there is no need to synchronize on timer_base::expiry_lock.

Don't acquire the timer_base::expiry_lock for TIMER_IRQSAFE flagged timer.
Add a lockdep annotation to ensure that this function is always invoked in preemptible context on PREEMPT_RT.

---
 kernel/time/timer.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
kernel/time/timer.c +8 -1
index 89078fd848b9..3e9d7f227a5c 100644
@@ -1289,7 +1289,7 @@ static void del_timer_wait_running(struct timer_list *timer)
 	u32 tf;
 
 	tf = READ_ONCE(timer->flags);
-	if (!(tf & TIMER_MIGRATING)) {
+	if (!(tf & (TIMER_MIGRATING | TIMER_IRQSAFE))) {
 		struct timer_base *base = get_timer_base(tf);
 
 		/*
@@ -1373,6 +1373,13 @@ int del_timer_sync(struct timer_list *timer)
 	 */
 	WARN_ON(in_irq() && !(timer->flags & TIMER_IRQSAFE));
 
+	/*
+	 * Must be able to sleep on PREEMPT_RT because of the slowpath in
+	 * del_timer_wait_running().
+	 */
+	if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(timer->flags & TIMER_IRQSAFE))
+		might_sleep();
+
 	do {
 		ret = try_to_del_timer_sync(timer);
 
Signature · 1 line
2.28.0
#9 lore raw

PATCH 6/6 Linux 5.4.74-rt42-rc1

In reply to Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

------------------

From: "Steven Rostedt (VMware)" <[email protected]>

---
 localversion-rt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
localversion-rt +1 -1
index 629e0b4384b8..31c892a05e4d 100644
@@ -1 +1 @@
--rt41
+-rt42-rc1
Signature · 1 line
2.28.0
#10 lore raw
Quoted 2 lines · Steven Rostedt

5.4.74-rt42-rc1 stable review patch.
If anyone has any objections, please let me know.

The remaining queue looks good.

Sebastian