Skip to contentSkip to conversation

Patch "sched/rt: Up the root domain ref count when passing it around via IPIs" has been added to the 4.9-stable tree

PATCH [email protected] 1 participant 1 message Feb 13, 2018

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

sched/rt: Up the root domain ref count when passing it around via IPIs

to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
sched-rt-up-the-root-domain-ref-count-when-passing-it-around-via-ipis.patch
and it can be found in the queue-4.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 364f56653708ba8bcdefd4f0da2a42904baa8eeb Mon Sep 17 00:00:00 2001

From: "Steven Rostedt (VMware)" <[email protected]>
Date: Tue, 23 Jan 2018 20:45:38 -0500
Subject: sched/rt: Up the root domain ref count when passing it around via IPIs

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

commit 364f56653708ba8bcdefd4f0da2a42904baa8eeb upstream.

When issuing an IPI RT push, where an IPI is sent to each CPU that has more than one RT task scheduled on it, it references the root domain's rto_mask, that contains all the CPUs within the root domain that has more than one RT task in the runable state. The problem is, after the IPIs are initiated, the rq->lock is released. This means that the root domain that is associated to the run queue could be freed while the IPIs are going around.

Add a sched_get_rd() and a sched_put_rd() that will increment and decrement the root domain's ref count respectively. This way when initiating the IPIs, the scheduler will up the root domain's ref count before releasing the rq->lock, ensuring that the root domain does not go away until the IPI round is complete.

---
 kernel/sched/core.c  |   13 +++++++++++++
 kernel/sched/rt.c    |    9 +++++++--
 kernel/sched/sched.h |    2 ++
 3 files changed, 22 insertions(+), 2 deletions(-)
kernel/sched/core.c +13 -0
@@ -5864,6 +5864,19 @@ static void rq_attach_root(struct rq *rq
 		call_rcu_sched(&old_rd->rcu, free_rootdomain);
 }
 
+void sched_get_rd(struct root_domain *rd)
+{
+	atomic_inc(&rd->refcount);
+}
+
+void sched_put_rd(struct root_domain *rd)
+{
+	if (!atomic_dec_and_test(&rd->refcount))
+		return;
+
+	call_rcu_sched(&rd->rcu, free_rootdomain);
+}
+
 static int init_rootdomain(struct root_domain *rd)
 {
 	memset(rd, 0, sizeof(*rd));
kernel/sched/rt.c +7 -2
@@ -1978,8 +1978,11 @@ static void tell_cpu_to_push(struct rq *
 
 	rto_start_unlock(&rq->rd->rto_loop_start);
 
-	if (cpu >= 0)
+	if (cpu >= 0) {
+		/* Make sure the rd does not get freed while pushing */
+		sched_get_rd(rq->rd);
 		irq_work_queue_on(&rq->rd->rto_push_work, cpu);
+	}
 }
 
 /* Called from hardirq context */
@@ -2009,8 +2012,10 @@ void rto_push_irq_work_func(struct irq_w
 
 	raw_spin_unlock(&rd->rto_lock);
 
-	if (cpu < 0)
+	if (cpu < 0) {
+		sched_put_rd(rd);
 		return;
+	}
 
 	/* Try the next RT overloaded CPU */
 	irq_work_queue_on(&rd->rto_push_work, cpu);
kernel/sched/sched.h +2 -0
@@ -590,6 +590,8 @@ struct root_domain {
 };
 
 extern struct root_domain def_root_domain;
+extern void sched_get_rd(struct root_domain *rd);
+extern void sched_put_rd(struct root_domain *rd);
 
 #ifdef HAVE_RT_PUSH_IPI
 extern void rto_push_irq_work_func(struct irq_work *work);

Patches currently in stable-queue which might be from [email protected] are

queue-4.9/sched-rt-use-container_of-to-get-root-domain-in-rto_push_irq_work_func.patch queue-4.9/sched-rt-up-the-root-domain-ref-count-when-passing-it-around-via-ipis.patch