aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cpuset.c69
1 files changed, 16 insertions, 53 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index e902473f76bf..608fe1308b22 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -101,8 +101,6 @@ struct cpuset {
101 101
102 /* for custom sched domain */ 102 /* for custom sched domain */
103 int relax_domain_level; 103 int relax_domain_level;
104
105 struct work_struct hotplug_work;
106}; 104};
107 105
108/* Retrieve the cpuset for a cgroup */ 106/* Retrieve the cpuset for a cgroup */
@@ -268,12 +266,7 @@ static DEFINE_MUTEX(callback_mutex);
268/* 266/*
269 * CPU / memory hotplug is handled asynchronously. 267 * CPU / memory hotplug is handled asynchronously.
270 */ 268 */
271static struct workqueue_struct *cpuset_propagate_hotplug_wq;
272
273static void cpuset_hotplug_workfn(struct work_struct *work); 269static void cpuset_hotplug_workfn(struct work_struct *work);
274static void cpuset_propagate_hotplug_workfn(struct work_struct *work);
275static void schedule_cpuset_propagate_hotplug(struct cpuset *cs);
276
277static DECLARE_WORK(cpuset_hotplug_work, cpuset_hotplug_workfn); 270static DECLARE_WORK(cpuset_hotplug_work, cpuset_hotplug_workfn);
278 271
279static DECLARE_WAIT_QUEUE_HEAD(cpuset_attach_wq); 272static DECLARE_WAIT_QUEUE_HEAD(cpuset_attach_wq);
@@ -1554,7 +1547,6 @@ static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft,
1554 * after execution capability is restored. 1547 * after execution capability is restored.
1555 */ 1548 */
1556 flush_work(&cpuset_hotplug_work); 1549 flush_work(&cpuset_hotplug_work);
1557 flush_workqueue(cpuset_propagate_hotplug_wq);
1558 1550
1559 mutex_lock(&cpuset_mutex); 1551 mutex_lock(&cpuset_mutex);
1560 if (!is_cpuset_online(cs)) 1552 if (!is_cpuset_online(cs))
@@ -1821,7 +1813,6 @@ static struct cgroup_subsys_state *cpuset_css_alloc(struct cgroup *cont)
1821 cpumask_clear(cs->cpus_allowed); 1813 cpumask_clear(cs->cpus_allowed);
1822 nodes_clear(cs->mems_allowed); 1814 nodes_clear(cs->mems_allowed);
1823 fmeter_init(&cs->fmeter); 1815 fmeter_init(&cs->fmeter);
1824 INIT_WORK(&cs->hotplug_work, cpuset_propagate_hotplug_workfn);
1825 cs->relax_domain_level = -1; 1816 cs->relax_domain_level = -1;
1826 1817
1827 return &cs->css; 1818 return &cs->css;
@@ -1984,18 +1975,17 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
1984} 1975}
1985 1976
1986/** 1977/**
1987 * cpuset_propagate_hotplug_workfn - propagate CPU/memory hotplug to a cpuset 1978 * cpuset_hotplug_update_tasks - update tasks in a cpuset for hotunplug
1988 * @cs: cpuset in interest 1979 * @cs: cpuset in interest
1989 * 1980 *
1990 * Compare @cs's cpu and mem masks against top_cpuset and if some have gone 1981 * Compare @cs's cpu and mem masks against top_cpuset and if some have gone
1991 * offline, update @cs accordingly. If @cs ends up with no CPU or memory, 1982 * offline, update @cs accordingly. If @cs ends up with no CPU or memory,
1992 * all its tasks are moved to the nearest ancestor with both resources. 1983 * all its tasks are moved to the nearest ancestor with both resources.
1993 */ 1984 */
1994static void cpuset_propagate_hotplug_workfn(struct work_struct *work) 1985static void cpuset_hotplug_update_tasks(struct cpuset *cs)
1995{ 1986{
1996 static cpumask_t off_cpus; 1987 static cpumask_t off_cpus;
1997 static nodemask_t off_mems, tmp_mems; 1988 static nodemask_t off_mems, tmp_mems;
1998 struct cpuset *cs = container_of(work, struct cpuset, hotplug_work);
1999 bool is_empty; 1989 bool is_empty;
2000 1990
2001retry: 1991retry:
@@ -2044,34 +2034,6 @@ retry:
2044 */ 2034 */
2045 if (is_empty) 2035 if (is_empty)
2046 remove_tasks_in_empty_cpuset(cs); 2036 remove_tasks_in_empty_cpuset(cs);
2047
2048 /* the following may free @cs, should be the last operation */
2049 css_put(&cs->css);
2050}
2051
2052/**
2053 * schedule_cpuset_propagate_hotplug - schedule hotplug propagation to a cpuset
2054 * @cs: cpuset of interest
2055 *
2056 * Schedule cpuset_propagate_hotplug_workfn() which will update CPU and
2057 * memory masks according to top_cpuset.
2058 */
2059static void schedule_cpuset_propagate_hotplug(struct cpuset *cs)
2060{
2061 /*
2062 * Pin @cs. The refcnt will be released when the work item
2063 * finishes executing.
2064 */
2065 if (!css_tryget(&cs->css))
2066 return;
2067
2068 /*
2069 * Queue @cs->hotplug_work. If already pending, lose the css ref.
2070 * cpuset_propagate_hotplug_wq is ordered and propagation will
2071 * happen in the order this function is called.
2072 */
2073 if (!queue_work(cpuset_propagate_hotplug_wq, &cs->hotplug_work))
2074 css_put(&cs->css);
2075} 2037}
2076 2038
2077/** 2039/**
@@ -2084,8 +2046,8 @@ static void schedule_cpuset_propagate_hotplug(struct cpuset *cs)
2084 * actively using CPU hotplug but making no active use of cpusets. 2046 * actively using CPU hotplug but making no active use of cpusets.
2085 * 2047 *
2086 * Non-root cpusets are only affected by offlining. If any CPUs or memory 2048 * Non-root cpusets are only affected by offlining. If any CPUs or memory
2087 * nodes have been taken down, cpuset_propagate_hotplug() is invoked on all 2049 * nodes have been taken down, cpuset_hotplug_update_tasks() is invoked on
2088 * descendants. 2050 * all descendants.
2089 * 2051 *
2090 * Note that CPU offlining during suspend is ignored. We don't modify 2052 * Note that CPU offlining during suspend is ignored. We don't modify
2091 * cpusets across suspend/resume cycles at all. 2053 * cpusets across suspend/resume cycles at all.
@@ -2128,21 +2090,26 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
2128 update_tasks_nodemask(&top_cpuset, &tmp_mems, NULL); 2090 update_tasks_nodemask(&top_cpuset, &tmp_mems, NULL);
2129 } 2091 }
2130 2092
2093 mutex_unlock(&cpuset_mutex);
2094
2131 /* if cpus or mems went down, we need to propagate to descendants */ 2095 /* if cpus or mems went down, we need to propagate to descendants */
2132 if (cpus_offlined || mems_offlined) { 2096 if (cpus_offlined || mems_offlined) {
2133 struct cpuset *cs; 2097 struct cpuset *cs;
2134 struct cgroup *pos_cgrp; 2098 struct cgroup *pos_cgrp;
2135 2099
2136 rcu_read_lock(); 2100 rcu_read_lock();
2137 cpuset_for_each_descendant_pre(cs, pos_cgrp, &top_cpuset) 2101 cpuset_for_each_descendant_pre(cs, pos_cgrp, &top_cpuset) {
2138 schedule_cpuset_propagate_hotplug(cs); 2102 if (!css_tryget(&cs->css))
2139 rcu_read_unlock(); 2103 continue;
2140 } 2104 rcu_read_unlock();
2141 2105
2142 mutex_unlock(&cpuset_mutex); 2106 cpuset_hotplug_update_tasks(cs);
2143 2107
2144 /* wait for propagations to finish */ 2108 rcu_read_lock();
2145 flush_workqueue(cpuset_propagate_hotplug_wq); 2109 css_put(&cs->css);
2110 }
2111 rcu_read_unlock();
2112 }
2146 2113
2147 /* rebuild sched domains if cpus_allowed has changed */ 2114 /* rebuild sched domains if cpus_allowed has changed */
2148 if (cpus_updated) 2115 if (cpus_updated)
@@ -2193,10 +2160,6 @@ void __init cpuset_init_smp(void)
2193 top_cpuset.mems_allowed = node_states[N_MEMORY]; 2160 top_cpuset.mems_allowed = node_states[N_MEMORY];
2194 2161
2195 register_hotmemory_notifier(&cpuset_track_online_nodes_nb); 2162 register_hotmemory_notifier(&cpuset_track_online_nodes_nb);
2196
2197 cpuset_propagate_hotplug_wq =
2198 alloc_ordered_workqueue("cpuset_hotplug", 0);
2199 BUG_ON(!cpuset_propagate_hotplug_wq);
2200} 2163}
2201 2164
2202/** 2165/**