From: Mathias Krause <minipli@grsecurity.net>
To: "Vincent Guittot" <vincent.guittot@linaro.org>,
"Michal Koutný" <mkoutny@suse.com>
Cc: Benjamin Segall <bsegall@google.com>,
Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Juri Lelli <juri.lelli@redhat.com>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Mel Gorman <mgorman@suse.de>,
Daniel Bristot de Oliveira <bristot@redhat.com>,
Valentin Schneider <Valentin.Schneider@arm.com>,
linux-kernel@vger.kernel.org, Odin Ugedal <odin@uged.al>,
Kevin Tanguy <kevin.tanguy@corp.ovh.com>,
Brad Spengler <spender@grsecurity.net>,
Mathias Krause <minipli@grsecurity.net>
Subject: Re: [PATCH] sched/fair: Prevent dead task groups from regaining cfs_rq's
Date: Fri, 5 Nov 2021 17:29:14 +0100 [thread overview]
Message-ID: <20211105162914.215420-1-minipli@grsecurity.net> (raw)
In-Reply-To: <8f4ed996-e6e5-75f4-b5fa-dffb7b7da05b@grsecurity.net>
> Looks like it needs to be the kfree_rcu() one in this case. I'll prepare
> a patch.
Testing the below patch right now. Looking good so far. Will prepare a
proper patch later, if we all can agree that this covers all cases.
But the basic idea is to defer the kfree()'s to after the next RCU GP,
which also means we need to free the tg object itself later. Slightly
ugly. :/
Thanks,
Mathias
--8<--
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 978460f891a1..8b4c849bc892 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9439,12 +9439,19 @@ static inline void alloc_uclamp_sched_group(struct task_group *tg,
#endif
}
+void tg_free(struct task_group *tg)
+{
+ kmem_cache_free(task_group_cache, tg);
+}
+
static void sched_free_group(struct task_group *tg)
{
- free_fair_sched_group(tg);
+ bool delayed_free;
+ delayed_free = free_fair_sched_group(tg);
free_rt_sched_group(tg);
autogroup_free(tg);
- kmem_cache_free(task_group_cache, tg);
+ if (!delayed_free)
+ tg_free(tg);
}
/* allocate runqueue etc for a new task group */
@@ -9506,9 +9513,19 @@ void sched_offline_group(struct task_group *tg)
{
unsigned long flags;
- /* End participation in shares distribution: */
- unregister_fair_sched_group(tg);
-
+ /*
+ * Unlink first, to avoid walk_tg_tree_from() from finding us (via
+ * sched_cfs_period_timer()).
+ *
+ * For this to be effective, we have to wait for all pending users of
+ * this task group to leave their RCU critical section to ensure no new
+ * user will see our dying task group any more. Specifically ensure
+ * that tg_unthrottle_up() won't add decayed cfs_rq's to it.
+ *
+ * We therefore defer calling unregister_fair_sched_group() to
+ * sched_free_group() which is guarantied to get called only after the
+ * current RCU grace period has expired.
+ */
spin_lock_irqsave(&task_group_lock, flags);
list_del_rcu(&tg->list);
list_del_rcu(&tg->siblings);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 567c571d624f..54c1f7b571e4 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -11287,12 +11287,11 @@ static void task_change_group_fair(struct task_struct *p, int type)
}
}
-void free_fair_sched_group(struct task_group *tg)
+static void free_tg(struct rcu_head *rcu)
{
+ struct task_group *tg = container_of(rcu, struct task_group, rcu);
int i;
- destroy_cfs_bandwidth(tg_cfs_bandwidth(tg));
-
for_each_possible_cpu(i) {
if (tg->cfs_rq)
kfree(tg->cfs_rq[i]);
@@ -11302,6 +11301,19 @@ void free_fair_sched_group(struct task_group *tg)
kfree(tg->cfs_rq);
kfree(tg->se);
+ tg_free(tg);
+}
+
+bool free_fair_sched_group(struct task_group *tg)
+{
+ destroy_cfs_bandwidth(tg_cfs_bandwidth(tg));
+ unregister_fair_sched_group(tg);
+ /*
+ * We have to wait for yet another RCU grace period to expire, as
+ * print_cfs_stats() might run concurrently.
+ */
+ call_rcu(&tg->rcu, free_tg);
+ return true;
}
int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
@@ -11459,7 +11471,10 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
}
#else /* CONFIG_FAIR_GROUP_SCHED */
-void free_fair_sched_group(struct task_group *tg) { }
+bool free_fair_sched_group(struct task_group *tg)
+{
+ return false;
+}
int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
{
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index eaca971a3ee2..b45ba45d8bdc 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -437,6 +437,8 @@ struct task_group {
};
+extern void tg_free(struct task_group *tg);
+
#ifdef CONFIG_FAIR_GROUP_SCHED
#define ROOT_TASK_GROUP_LOAD NICE_0_LOAD
@@ -470,7 +472,7 @@ static inline int walk_tg_tree(tg_visitor down, tg_visitor up, void *data)
extern int tg_nop(struct task_group *tg, void *data);
-extern void free_fair_sched_group(struct task_group *tg);
+extern bool free_fair_sched_group(struct task_group *tg);
extern int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent);
extern void online_fair_sched_group(struct task_group *tg);
extern void unregister_fair_sched_group(struct task_group *tg);
next prev parent reply other threads:[~2021-11-05 16:29 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-11 17:22 [PATCH] sched/fair: Use rq->lock when checking cfs_rq list presence Michal Koutný
2021-10-11 19:12 ` Odin Ugedal
2021-10-12 18:32 ` Tao Zhou
2021-10-13 18:52 ` Odin Ugedal
2021-10-13 14:39 ` Michal Koutný
2021-10-13 18:45 ` Odin Ugedal
2021-10-13 7:57 ` Vincent Guittot
2021-10-13 14:26 ` Michal Koutný
2021-11-02 16:02 ` task_group unthrottling and removal race (was Re: [PATCH] sched/fair: Use rq->lock when checking cfs_rq list) presence Michal Koutný
2021-11-02 20:20 ` Odin Ugedal
2021-11-03 9:51 ` Mathias Krause
2021-11-03 10:51 ` Mathias Krause
2021-11-03 11:10 ` Michal Koutný
2021-11-03 14:16 ` Mathias Krause
2021-11-03 19:06 ` [PATCH] sched/fair: Prevent dead task groups from regaining cfs_rq's Mathias Krause
2021-11-03 22:03 ` Benjamin Segall
2021-11-04 8:50 ` Vincent Guittot
2021-11-04 15:13 ` Mathias Krause
2021-11-04 16:49 ` Vincent Guittot
2021-11-04 17:37 ` Mathias Krause
2021-11-05 14:25 ` Vincent Guittot
2021-11-05 14:44 ` Mathias Krause
2021-11-05 16:29 ` Mathias Krause [this message]
2021-11-05 16:58 ` Peter Zijlstra
2021-11-05 17:14 ` Mathias Krause
2021-11-05 17:27 ` Peter Zijlstra
2021-11-05 17:40 ` Mathias Krause
2021-11-06 10:48 ` Peter Zijlstra
2021-11-08 10:27 ` Mathias Krause
2021-11-08 11:40 ` Peter Zijlstra
2021-11-08 15:06 ` Mathias Krause
2021-11-10 15:14 ` Vincent Guittot
2021-11-09 18:47 ` Michal Koutný
2021-11-10 15:17 ` Vincent Guittot
2021-11-04 20:46 ` Benjamin Segall
2021-11-04 18:49 ` Michal Koutný
2021-11-05 14:55 ` Mathias Krause
2021-11-05 14:58 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211105162914.215420-1-minipli@grsecurity.net \
--to=minipli@grsecurity.net \
--cc=Valentin.Schneider@arm.com \
--cc=bristot@redhat.com \
--cc=bsegall@google.com \
--cc=dietmar.eggemann@arm.com \
--cc=juri.lelli@redhat.com \
--cc=kevin.tanguy@corp.ovh.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=mkoutny@suse.com \
--cc=odin@uged.al \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=spender@grsecurity.net \
--cc=vincent.guittot@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®