@@ -147,6 +147,12 @@ typedef enum {
147147 CS_SPREAD_SLAB ,
148148} cpuset_flagbits_t ;
149149
150+ /* the type of hotplug event */
151+ enum hotplug_event {
152+ CPUSET_CPU_OFFLINE ,
153+ CPUSET_MEM_OFFLINE ,
154+ };
155+
150156/* convenient tests for these bits */
151157static inline int is_cpu_exclusive (const struct cpuset * cs )
152158{
@@ -2016,8 +2022,10 @@ static struct cpuset *cpuset_next(struct list_head *queue)
20162022
20172023
20182024/*
2019- * Walk the specified cpuset subtree and look for empty cpusets.
2020- * The tasks of such cpuset must be moved to a parent cpuset.
2025+ * Walk the specified cpuset subtree upon a hotplug operation (CPU/Memory
2026+ * online/offline) and update the cpusets accordingly.
2027+ * For regular CPU/Mem hotplug, look for empty cpusets; the tasks of such
2028+ * cpuset must be moved to a parent cpuset.
20212029 *
20222030 * Called with cgroup_mutex held. We take callback_mutex to modify
20232031 * cpus_allowed and mems_allowed.
@@ -2030,38 +2038,58 @@ static struct cpuset *cpuset_next(struct list_head *queue)
20302038 * that has tasks along with an empty 'mems'. But if we did see such
20312039 * a cpuset, we'd handle it just like we do if its 'cpus' was empty.
20322040 */
2033- static void scan_for_empty_cpusets (struct cpuset * root )
2041+ static void
2042+ scan_cpusets_upon_hotplug (struct cpuset * root , enum hotplug_event event )
20342043{
20352044 LIST_HEAD (queue );
2036- struct cpuset * cp ; /* scans cpusets being updated */
2045+ struct cpuset * cp ; /* scans cpusets being updated */
20372046 static nodemask_t oldmems ; /* protected by cgroup_mutex */
20382047
20392048 list_add_tail ((struct list_head * )& root -> stack_list , & queue );
20402049
2041- while ((cp = cpuset_next (& queue )) != NULL ) {
2050+ switch (event ) {
2051+ case CPUSET_CPU_OFFLINE :
2052+ while ((cp = cpuset_next (& queue )) != NULL ) {
2053+
2054+ /* Continue past cpusets with all cpus online */
2055+ if (cpumask_subset (cp -> cpus_allowed , cpu_active_mask ))
2056+ continue ;
2057+
2058+ /* Remove offline cpus from this cpuset. */
2059+ mutex_lock (& callback_mutex );
2060+ cpumask_and (cp -> cpus_allowed , cp -> cpus_allowed ,
2061+ cpu_active_mask );
2062+ mutex_unlock (& callback_mutex );
2063+
2064+ /* Move tasks from the empty cpuset to a parent */
2065+ if (cpumask_empty (cp -> cpus_allowed ))
2066+ remove_tasks_in_empty_cpuset (cp );
2067+ else
2068+ update_tasks_cpumask (cp , NULL );
2069+ }
2070+ break ;
20422071
2043- /* Continue past cpusets with all cpus, mems online */
2044- if (cpumask_subset (cp -> cpus_allowed , cpu_active_mask ) &&
2045- nodes_subset (cp -> mems_allowed , node_states [N_HIGH_MEMORY ]))
2046- continue ;
2072+ case CPUSET_MEM_OFFLINE :
2073+ while ((cp = cpuset_next (& queue )) != NULL ) {
20472074
2048- oldmems = cp -> mems_allowed ;
2075+ /* Continue past cpusets with all mems online */
2076+ if (nodes_subset (cp -> mems_allowed ,
2077+ node_states [N_HIGH_MEMORY ]))
2078+ continue ;
20492079
2050- /* Remove offline cpus and mems from this cpuset. */
2051- mutex_lock ( & callback_mutex );
2052- cpumask_and ( cp -> cpus_allowed , cp -> cpus_allowed ,
2053- cpu_active_mask );
2054- nodes_and (cp -> mems_allowed , cp -> mems_allowed ,
2080+ oldmems = cp -> mems_allowed ;
2081+
2082+ /* Remove offline mems from this cpuset. */
2083+ mutex_lock ( & callback_mutex );
2084+ nodes_and (cp -> mems_allowed , cp -> mems_allowed ,
20552085 node_states [N_HIGH_MEMORY ]);
2056- mutex_unlock (& callback_mutex );
2086+ mutex_unlock (& callback_mutex );
20572087
2058- /* Move tasks from the empty cpuset to a parent */
2059- if (cpumask_empty (cp -> cpus_allowed ) ||
2060- nodes_empty (cp -> mems_allowed ))
2061- remove_tasks_in_empty_cpuset (cp );
2062- else {
2063- update_tasks_cpumask (cp , NULL );
2064- update_tasks_nodemask (cp , & oldmems , NULL );
2088+ /* Move tasks from the empty cpuset to a parent */
2089+ if (nodes_empty (cp -> mems_allowed ))
2090+ remove_tasks_in_empty_cpuset (cp );
2091+ else
2092+ update_tasks_nodemask (cp , & oldmems , NULL );
20652093 }
20662094 }
20672095}
@@ -2080,8 +2108,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
20802108 *
20812109 * Called within get_online_cpus(). Needs to call cgroup_lock()
20822110 * before calling generate_sched_domains().
2111+ *
2112+ * @cpu_online: Indicates whether this is a CPU online event (true) or
2113+ * a CPU offline event (false).
20832114 */
2084- void cpuset_update_active_cpus (void )
2115+ void cpuset_update_active_cpus (bool cpu_online )
20852116{
20862117 struct sched_domain_attr * attr ;
20872118 cpumask_var_t * doms ;
@@ -2091,7 +2122,10 @@ void cpuset_update_active_cpus(void)
20912122 mutex_lock (& callback_mutex );
20922123 cpumask_copy (top_cpuset .cpus_allowed , cpu_active_mask );
20932124 mutex_unlock (& callback_mutex );
2094- scan_for_empty_cpusets (& top_cpuset );
2125+
2126+ if (!cpu_online )
2127+ scan_cpusets_upon_hotplug (& top_cpuset , CPUSET_CPU_OFFLINE );
2128+
20952129 ndoms = generate_sched_domains (& doms , & attr );
20962130 cgroup_unlock ();
20972131
@@ -2122,9 +2156,9 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
21222156 case MEM_OFFLINE :
21232157 /*
21242158 * needn't update top_cpuset.mems_allowed explicitly because
2125- * scan_for_empty_cpusets () will update it.
2159+ * scan_cpusets_upon_hotplug () will update it.
21262160 */
2127- scan_for_empty_cpusets (& top_cpuset );
2161+ scan_cpusets_upon_hotplug (& top_cpuset , CPUSET_MEM_OFFLINE );
21282162 break ;
21292163 default :
21302164 break ;
0 commit comments