]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
cgroup/cpuset: move legacy hotplug update to cpuset-v1.c
authorChen Ridong <chenridong@huawei.com>
Fri, 30 Aug 2024 10:02:24 +0000 (10:02 +0000)
committerTejun Heo <tj@kernel.org>
Fri, 30 Aug 2024 20:00:16 +0000 (10:00 -1000)
There are some differents about hotplug update between cpuset v1 and
cpuset v2. Move the legacy code to cpuset-v1.c.

'update_tasks_cpumask' and 'update_tasks_nodemask' are both used in cpuset
v1 and cpuset v2, declare them in cpuset-internal.h.

The change from original code is that use callback_lock helpers to get
callback_lock lock/unlock.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
Acked-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/cgroup/cpuset-internal.h
kernel/cgroup/cpuset-v1.c
kernel/cgroup/cpuset.c

index 9a60dd6681e47594d07a1563c14d79a69f432a58..7cd30ad809d51f22144de53a47433b22267196b7 100644 (file)
@@ -241,6 +241,8 @@ static inline int is_spread_slab(const struct cpuset *cs)
 void rebuild_sched_domains_locked(void);
 void callback_lock_irq(void);
 void callback_unlock_irq(void);
+void update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus);
+void update_tasks_nodemask(struct cpuset *cs);
 
 /*
  * cpuset-v1.c
@@ -253,5 +255,8 @@ s64 cpuset_read_s64(struct cgroup_subsys_state *css, struct cftype *cft);
 void cpuset_update_task_spread_flags(struct cpuset *cs,
                                        struct task_struct *tsk);
 void update_tasks_flags(struct cpuset *cs);
+void hotplug_update_tasks_legacy(struct cpuset *cs,
+                           struct cpumask *new_cpus, nodemask_t *new_mems,
+                           bool cpus_updated, bool mems_updated);
 
 #endif /* __CPUSET_INTERNAL_H */
index ca973b4de38a9cee607f60edd2e96718dabbe90c..ebc71c5d25682cfa88ec581c846bd6862f759276 100644 (file)
@@ -2,6 +2,14 @@
 
 #include "cpuset-internal.h"
 
+/*
+ * Legacy hierarchy call to cgroup_transfer_tasks() is handled asynchrously
+ */
+struct cpuset_remove_tasks_struct {
+       struct work_struct work;
+       struct cpuset *cs;
+};
+
 /*
  * Frequency meter - How fast is some event occurring?
  *
@@ -236,3 +244,86 @@ void update_tasks_flags(struct cpuset *cs)
                cpuset_update_task_spread_flags(cs, task);
        css_task_iter_end(&it);
 }
+
+/*
+ * If CPU and/or memory hotplug handlers, below, unplug any CPUs
+ * or memory nodes, we need to walk over the cpuset hierarchy,
+ * removing that CPU or node from all cpusets.  If this removes the
+ * last CPU or node from a cpuset, then move the tasks in the empty
+ * cpuset to its next-highest non-empty parent.
+ */
+static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
+{
+       struct cpuset *parent;
+
+       /*
+        * Find its next-highest non-empty parent, (top cpuset
+        * has online cpus, so can't be empty).
+        */
+       parent = parent_cs(cs);
+       while (cpumask_empty(parent->cpus_allowed) ||
+                       nodes_empty(parent->mems_allowed))
+               parent = parent_cs(parent);
+
+       if (cgroup_transfer_tasks(parent->css.cgroup, cs->css.cgroup)) {
+               pr_err("cpuset: failed to transfer tasks out of empty cpuset ");
+               pr_cont_cgroup_name(cs->css.cgroup);
+               pr_cont("\n");
+       }
+}
+
+static void cpuset_migrate_tasks_workfn(struct work_struct *work)
+{
+       struct cpuset_remove_tasks_struct *s;
+
+       s = container_of(work, struct cpuset_remove_tasks_struct, work);
+       remove_tasks_in_empty_cpuset(s->cs);
+       css_put(&s->cs->css);
+       kfree(s);
+}
+
+void hotplug_update_tasks_legacy(struct cpuset *cs,
+                           struct cpumask *new_cpus, nodemask_t *new_mems,
+                           bool cpus_updated, bool mems_updated)
+{
+       bool is_empty;
+
+       callback_lock_irq();
+       cpumask_copy(cs->cpus_allowed, new_cpus);
+       cpumask_copy(cs->effective_cpus, new_cpus);
+       cs->mems_allowed = *new_mems;
+       cs->effective_mems = *new_mems;
+       callback_unlock_irq();
+
+       /*
+        * Don't call update_tasks_cpumask() if the cpuset becomes empty,
+        * as the tasks will be migrated to an ancestor.
+        */
+       if (cpus_updated && !cpumask_empty(cs->cpus_allowed))
+               update_tasks_cpumask(cs, new_cpus);
+       if (mems_updated && !nodes_empty(cs->mems_allowed))
+               update_tasks_nodemask(cs);
+
+       is_empty = cpumask_empty(cs->cpus_allowed) ||
+                  nodes_empty(cs->mems_allowed);
+
+       /*
+        * Move tasks to the nearest ancestor with execution resources,
+        * This is full cgroup operation which will also call back into
+        * cpuset. Execute it asynchronously using workqueue.
+        */
+       if (is_empty && cs->css.cgroup->nr_populated_csets &&
+           css_tryget_online(&cs->css)) {
+               struct cpuset_remove_tasks_struct *s;
+
+               s = kzalloc(sizeof(*s), GFP_KERNEL);
+               if (WARN_ON_ONCE(!s)) {
+                       css_put(&cs->css);
+                       return;
+               }
+
+               s->cs = cs;
+               INIT_WORK(&s->work, cpuset_migrate_tasks_workfn);
+               schedule_work(&s->work);
+       }
+}
index 8a9a7fe1ec1e4006216ff0cf6893cefec9636b83..1270c7913af9d2aefe6e25ab4afa5a4c75a32391 100644 (file)
@@ -65,14 +65,6 @@ static const char * const perr_strings[] = {
        [PERR_ACCESS]    = "Enable partition not permitted",
 };
 
-/*
- * Legacy hierarchy call to cgroup_transfer_tasks() is handled asynchrously
- */
-struct cpuset_remove_tasks_struct {
-       struct work_struct work;
-       struct cpuset *cs;
-};
-
 /*
  * Exclusive CPUs distributed out to sub-partitions of top_cpuset
  */
@@ -1144,7 +1136,7 @@ void rebuild_sched_domains(void)
  * is used instead of effective_cpus to make sure all offline CPUs are also
  * included as hotplug code won't update cpumasks for tasks in top_cpuset.
  */
-static void update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus)
+void update_tasks_cpumask(struct cpuset *cs, struct cpumask *new_cpus)
 {
        struct css_task_iter it;
        struct task_struct *task;
@@ -2597,7 +2589,7 @@ static void *cpuset_being_rebound;
  * effective cpuset's.  As this function is called with cpuset_mutex held,
  * cpuset membership stays stable.
  */
-static void update_tasks_nodemask(struct cpuset *cs)
+void update_tasks_nodemask(struct cpuset *cs)
 {
        static nodemask_t newmems;      /* protected by cpuset_mutex */
        struct css_task_iter it;
@@ -3936,90 +3928,6 @@ int __init cpuset_init(void)
        return 0;
 }
 
-/*
- * If CPU and/or memory hotplug handlers, below, unplug any CPUs
- * or memory nodes, we need to walk over the cpuset hierarchy,
- * removing that CPU or node from all cpusets.  If this removes the
- * last CPU or node from a cpuset, then move the tasks in the empty
- * cpuset to its next-highest non-empty parent.
- */
-static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
-{
-       struct cpuset *parent;
-
-       /*
-        * Find its next-highest non-empty parent, (top cpuset
-        * has online cpus, so can't be empty).
-        */
-       parent = parent_cs(cs);
-       while (cpumask_empty(parent->cpus_allowed) ||
-                       nodes_empty(parent->mems_allowed))
-               parent = parent_cs(parent);
-
-       if (cgroup_transfer_tasks(parent->css.cgroup, cs->css.cgroup)) {
-               pr_err("cpuset: failed to transfer tasks out of empty cpuset ");
-               pr_cont_cgroup_name(cs->css.cgroup);
-               pr_cont("\n");
-       }
-}
-
-static void cpuset_migrate_tasks_workfn(struct work_struct *work)
-{
-       struct cpuset_remove_tasks_struct *s;
-
-       s = container_of(work, struct cpuset_remove_tasks_struct, work);
-       remove_tasks_in_empty_cpuset(s->cs);
-       css_put(&s->cs->css);
-       kfree(s);
-}
-
-static void
-hotplug_update_tasks_legacy(struct cpuset *cs,
-                           struct cpumask *new_cpus, nodemask_t *new_mems,
-                           bool cpus_updated, bool mems_updated)
-{
-       bool is_empty;
-
-       spin_lock_irq(&callback_lock);
-       cpumask_copy(cs->cpus_allowed, new_cpus);
-       cpumask_copy(cs->effective_cpus, new_cpus);
-       cs->mems_allowed = *new_mems;
-       cs->effective_mems = *new_mems;
-       spin_unlock_irq(&callback_lock);
-
-       /*
-        * Don't call update_tasks_cpumask() if the cpuset becomes empty,
-        * as the tasks will be migrated to an ancestor.
-        */
-       if (cpus_updated && !cpumask_empty(cs->cpus_allowed))
-               update_tasks_cpumask(cs, new_cpus);
-       if (mems_updated && !nodes_empty(cs->mems_allowed))
-               update_tasks_nodemask(cs);
-
-       is_empty = cpumask_empty(cs->cpus_allowed) ||
-                  nodes_empty(cs->mems_allowed);
-
-       /*
-        * Move tasks to the nearest ancestor with execution resources,
-        * This is full cgroup operation which will also call back into
-        * cpuset. Execute it asynchronously using workqueue.
-        */
-       if (is_empty && cs->css.cgroup->nr_populated_csets &&
-           css_tryget_online(&cs->css)) {
-               struct cpuset_remove_tasks_struct *s;
-
-               s = kzalloc(sizeof(*s), GFP_KERNEL);
-               if (WARN_ON_ONCE(!s)) {
-                       css_put(&cs->css);
-                       return;
-               }
-
-               s->cs = cs;
-               INIT_WORK(&s->work, cpuset_migrate_tasks_workfn);
-               schedule_work(&s->work);
-       }
-}
-
 static void
 hotplug_update_tasks(struct cpuset *cs,
                     struct cpumask *new_cpus, nodemask_t *new_mems,