On 4/17/23 04:04, gregkh@linuxfoundation.org wrote:
The patch below does not apply to the 6.1-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to stable@vger.kernel.org.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y git checkout FETCH_HEAD git cherry-pick -x eee87853794187f6adbe19533ed79c8b44b36a91 # <resolve conflicts, build, test, etc.> git commit -s git send-email --to 'stable@vger.kernel.org' --in-reply-to '2023041702-vertebrae-bonsai-f1de@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
eee878537941 ("cgroup/cpuset: Add cpuset_can_fork() and cpuset_cancel_fork() methods") 42a11bf5c543 ("cgroup/cpuset: Make cpuset_fork() handle CLONE_INTO_CGROUP properly") 18f9a4d47527 ("cgroup/cpuset: Skip spread flags update on v2")
I have posted a patch series that also include commit 18f9a4d47527 ("cgroup/cpuset: Skip spread flags update on v2") which is not technically a fix but is relative simple and low risk.
Cheers, Longman
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From eee87853794187f6adbe19533ed79c8b44b36a91 Mon Sep 17 00:00:00 2001 From: Waiman Long longman@redhat.com Date: Tue, 11 Apr 2023 09:35:59 -0400 Subject: [PATCH] cgroup/cpuset: Add cpuset_can_fork() and cpuset_cancel_fork() methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit
In the case of CLONE_INTO_CGROUP, not all cpusets are ready to accept new tasks. It is too late to check that in cpuset_fork(). So we need to add the cpuset_can_fork() and cpuset_cancel_fork() methods to pre-check it before we can allow attachment to a different cpuset.
We also need to set the attach_in_progress flag to alert other code that a new task is going to be added to the cpuset.
Fixes: ef2c41cf38a7 ("clone3: allow spawning processes into cgroups") Suggested-by: Michal Koutný mkoutny@suse.com Signed-off-by: Waiman Long longman@redhat.com Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Tejun Heo tj@kernel.org
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 2ccfae74acf9..166a45019f66 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -2453,6 +2453,20 @@ static int fmeter_getrate(struct fmeter *fmp) static struct cpuset *cpuset_attach_old_cs; +/*
- Check to see if a cpuset can accept a new task
- For v1, cpus_allowed and mems_allowed can't be empty.
- For v2, effective_cpus can't be empty.
- Note that in v1, effective_cpus = cpus_allowed.
- */
+static int cpuset_can_attach_check(struct cpuset *cs) +{
- if (cpumask_empty(cs->effective_cpus) ||
(!is_in_v2_mode() && nodes_empty(cs->mems_allowed)))
return -ENOSPC;
- return 0;
+}
- /* Called by cgroups to determine if a cpuset is usable; cpuset_rwsem held */ static int cpuset_can_attach(struct cgroup_taskset *tset) {
@@ -2467,16 +2481,9 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) percpu_down_write(&cpuset_rwsem);
- /* allow moving tasks into an empty cpuset if on default hierarchy */
- ret = -ENOSPC;
- if (!is_in_v2_mode() &&
(cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
goto out_unlock;
- /*
* Task cannot be moved to a cpuset with empty effective cpus.
*/
- if (cpumask_empty(cs->effective_cpus))
- /* Check to see if task is allowed in the cpuset */
- ret = cpuset_can_attach_check(cs);
- if (ret) goto out_unlock;
cgroup_taskset_for_each(task, css, tset) { @@ -2493,7 +2500,6 @@ static int cpuset_can_attach(struct cgroup_taskset *tset) * changes which zero cpus/mems_allowed. */ cs->attach_in_progress++;
- ret = 0; out_unlock: percpu_up_write(&cpuset_rwsem); return ret;
@@ -3264,6 +3270,68 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css) percpu_up_write(&cpuset_rwsem); } +/*
- In case the child is cloned into a cpuset different from its parent,
- additional checks are done to see if the move is allowed.
- */
+static int cpuset_can_fork(struct task_struct *task, struct css_set *cset) +{
- struct cpuset *cs = css_cs(cset->subsys[cpuset_cgrp_id]);
- bool same_cs;
- int ret;
- rcu_read_lock();
- same_cs = (cs == task_cs(current));
- rcu_read_unlock();
- if (same_cs)
return 0;
- lockdep_assert_held(&cgroup_mutex);
- percpu_down_write(&cpuset_rwsem);
- /* Check to see if task is allowed in the cpuset */
- ret = cpuset_can_attach_check(cs);
- if (ret)
goto out_unlock;
- ret = task_can_attach(task, cs->effective_cpus);
- if (ret)
goto out_unlock;
- ret = security_task_setscheduler(task);
- if (ret)
goto out_unlock;
- /*
* Mark attach is in progress. This makes validate_change() fail
* changes which zero cpus/mems_allowed.
*/
- cs->attach_in_progress++;
+out_unlock:
- percpu_up_write(&cpuset_rwsem);
- return ret;
+}
+static void cpuset_cancel_fork(struct task_struct *task, struct css_set *cset) +{
- struct cpuset *cs = css_cs(cset->subsys[cpuset_cgrp_id]);
- bool same_cs;
- rcu_read_lock();
- same_cs = (cs == task_cs(current));
- rcu_read_unlock();
- if (same_cs)
return;
- percpu_down_write(&cpuset_rwsem);
- cs->attach_in_progress--;
- if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
- percpu_up_write(&cpuset_rwsem);
+}
- /*
- Make sure the new task conform to the current state of its parent,
- which could have been changed by cpuset just after it inherits the
@@ -3292,6 +3360,11 @@ static void cpuset_fork(struct task_struct *task) percpu_down_write(&cpuset_rwsem); guarantee_online_mems(cs, &cpuset_attach_nodemask_to); cpuset_attach_task(cs, task);
- cs->attach_in_progress--;
- if (!cs->attach_in_progress)
wake_up(&cpuset_attach_wq);
- percpu_up_write(&cpuset_rwsem); }
@@ -3305,6 +3378,8 @@ struct cgroup_subsys cpuset_cgrp_subsys = { .attach = cpuset_attach, .post_attach = cpuset_post_attach, .bind = cpuset_bind,
- .can_fork = cpuset_can_fork,
- .cancel_fork = cpuset_cancel_fork, .fork = cpuset_fork, .legacy_cftypes = legacy_files, .dfl_cftypes = dfl_files,