* [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
@ 2012-05-24 14:16 Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume Srivatsa S. Bhat
` (5 more replies)
0 siblings, 6 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-05-24 14:16 UTC (permalink / raw)
To: a.p.zijlstra, mingo, pjt, paul, akpm
Cc: rjw, nacc, rientjes, paulmck, tglx, seto.hidetoshi, tj, mschmidt,
berrange, nikunj, vatsa, liuj97, linux-kernel, linux-pm,
srivatsa.bhat
Currently the kernel doesn't handle cpusets properly during suspend/resume.
After a resume, all non-root cpusets end up having only 1 cpu (the boot cpu),
causing massive performance degradation of workloads. One major user of cpusets
is libvirt, which means that after a suspend/hibernation cycle, all VMs
suddenly end up running terribly slow!
Also, the kernel moves the tasks from one cpuset to another during CPU hotplug
in the suspend/resume path, leading to a task-management nightmare after
resume.
Patch 1 fixes this by keeping cpusets unmodified in the suspend/resume path.
But to ensure we don't trip over, it keeps the sched domains updated during
every CPU hotplug in the s/r path.
This is a long standing issue and we need to fix up stable kernels too.
The rest of the patches in the series are mostly cleanups/optimizations.
Changelog:
v6: Drop patch 4 (cpusets: Update tasks' cpus_allowed mask upon updates to
root cpuset) considering how tasks in the root cpuset must be dealt with.
No changes to other patches.
v5 : Don't do explicit save/restore of cpusets' cpu masks during s/r, to avoid
the overhead of a new per-cpuset cpu mask to help with that. Also, ensure
that the sched domains are updated on each hotplug.
The s/r fix (patch 1) is now distinct from the cleanups (patches 2-5).
v4 : (Never had this version. I skipped from v3 to v5 accidentally).
v3 : Explicitly save and restore cpusets' cpu masks during s/r. Don't alter
the semantics of regular cpu hotplug.
http://thread.gmane.org/gmane.linux.kernel/1296339
v2 : http://thread.gmane.org/gmane.linux.documentation/4805/
v1 : thread.gmane.org/gmane.linux.kernel/1250097/
--
Srivatsa S. Bhat (4):
CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume
cpusets, hotplug: Implement cpuset tree traversal in a helper function
cpusets, hotplug: Restructure functions that are invoked during hotplug
cpusets: Remove/update outdated comments
include/linux/cpuset.h | 4 +
kernel/cpuset.c | 130 ++++++++++++++++++++++++++++++++++--------------
kernel/sched/core.c | 44 ++++++++++++++--
3 files changed, 132 insertions(+), 46 deletions(-)
Thanks,
Srivatsa S. Bhat
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
@ 2012-05-24 14:16 ` Srivatsa S. Bhat
2012-06-20 10:44 ` [tip:sched/core] CPU hotplug, cpusets, suspend: Don' t " tip-bot for Srivatsa S. Bhat
2012-07-24 14:14 ` tip-bot for Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 2/4] cpusets, hotplug: Implement cpuset tree traversal in a helper function Srivatsa S. Bhat
` (4 subsequent siblings)
5 siblings, 2 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-05-24 14:16 UTC (permalink / raw)
To: a.p.zijlstra, mingo, pjt, paul, akpm
Cc: rjw, nacc, rientjes, paulmck, tglx, seto.hidetoshi, tj, mschmidt,
berrange, nikunj, vatsa, liuj97, linux-kernel, linux-pm,
srivatsa.bhat
In the event of CPU hotplug, the kernel modifies the cpusets' cpus_allowed
masks as and when necessary to ensure that the tasks belonging to the cpusets
have some place (online CPUs) to run on. And regular CPU hotplug is
destructive in the sense that the kernel doesn't remember the original cpuset
configurations set by the user, across hotplug operations.
However, suspend/resume (which uses CPU hotplug) is a special case in which
the kernel has the responsibility to restore the system (during resume), to
exactly the same state it was in before suspend.
In order to achieve that, do the following:
1. Don't modify cpusets during suspend/resume. At all.
In particular, don't move the tasks from one cpuset to another, and
don't modify any cpuset's cpus_allowed mask. So, simply ignore cpusets
during the CPU hotplug operations that are carried out in the
suspend/resume path.
2. However, cpusets and sched domains are related. We just want to avoid
altering cpusets alone. So, to keep the sched domains updated, build
a single sched domain (containing all active cpus) during each of the
CPU hotplug operations carried out in s/r path, effectively ignoring
the cpusets' cpus_allowed masks.
(Since userspace is frozen while doing all this, it will go unnoticed.)
3. During the last CPU online operation during resume, build the sched
domains by looking up the (unaltered) cpusets' cpus_allowed masks.
That will bring back the system to the same original state as it was in
before suspend.
Ultimately, this will not only solve the cpuset problem related to suspend
resume (ie., restores the cpusets to exactly what it was before suspend, by
not touching it at all) but also speeds up suspend/resume because we avoid
running cpuset update code for every CPU being offlined/onlined.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org
---
kernel/cpuset.c | 3 +++
kernel/sched/core.c | 40 ++++++++++++++++++++++++++++++++++++----
2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 8c8bd65..746d1ee 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2054,6 +2054,9 @@ static void scan_for_empty_cpusets(struct cpuset *root)
* (of no affect) on systems that are actively using CPU hotplug
* but making no active use of cpusets.
*
+ * The only exception to this is suspend/resume, where we don't
+ * modify cpusets at all.
+ *
* This routine ensures that top_cpuset.cpus_allowed tracks
* cpu_active_mask on each CPU hotplug (cpuhp) event.
*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 39eb601..59a1591 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6816,34 +6816,66 @@ match2:
mutex_unlock(&sched_domains_mutex);
}
+static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */
+
/*
* Update cpusets according to cpu_active mask. If cpusets are
* disabled, cpuset_update_active_cpus() becomes a simple wrapper
* around partition_sched_domains().
+ *
+ * If we come here as part of a suspend/resume, don't touch cpusets because we
+ * want to restore it back to its original state upon resume anyway.
*/
static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
+ case CPU_ONLINE_FROZEN:
+ case CPU_DOWN_FAILED_FROZEN:
+
+ /*
+ * num_cpus_frozen tracks how many CPUs are involved in suspend
+ * resume sequence. As long as this is not the last online
+ * operation in the resume sequence, just build a single sched
+ * domain, ignoring cpusets.
+ */
+ num_cpus_frozen--;
+ if (likely(num_cpus_frozen)) {
+ partition_sched_domains(1, NULL, NULL);
+ break;
+ }
+
+ /*
+ * This is the last CPU online operation. So fall through and
+ * restore the original sched domains by considering the
+ * cpuset configurations.
+ */
+
case CPU_ONLINE:
case CPU_DOWN_FAILED:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
case CPU_DOWN_PREPARE:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
+ case CPU_DOWN_PREPARE_FROZEN:
+ num_cpus_frozen++;
+ partition_sched_domains(1, NULL, NULL);
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
void __init sched_init_smp(void)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 2/4] cpusets, hotplug: Implement cpuset tree traversal in a helper function
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume Srivatsa S. Bhat
@ 2012-05-24 14:16 ` Srivatsa S. Bhat
2012-06-20 10:45 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
2012-07-24 14:15 ` tip-bot for Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 3/4] cpusets, hotplug: Restructure functions that are invoked during hotplug Srivatsa S. Bhat
` (3 subsequent siblings)
5 siblings, 2 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-05-24 14:16 UTC (permalink / raw)
To: a.p.zijlstra, mingo, pjt, paul, akpm
Cc: rjw, nacc, rientjes, paulmck, tglx, seto.hidetoshi, tj, mschmidt,
berrange, nikunj, vatsa, liuj97, linux-kernel, linux-pm,
srivatsa.bhat
At present, the functions that deal with cpusets during CPU/Mem hotplug
are quite messy, since a lot of the functionality is mixed up without clear
separation. And this takes a toll on optimization as well. For example,
the function cpuset_update_active_cpus() is called on both CPU offline and CPU
online events; and it invokes scan_for_empty_cpusets(), which makes sense
only for CPU offline events. And hence, the current code ends up unnecessarily
traversing the cpuset tree during CPU online also.
As a first step towards cleaning up those functions, encapsulate the cpuset
tree traversal in a helper function, so as to facilitate upcoming changes.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
kernel/cpuset.c | 36 +++++++++++++++++++++++++++---------
1 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 746d1ee..ba96349 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1990,6 +1990,32 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
}
/*
+ * Helper function to traverse cpusets.
+ * It can be used to walk the cpuset tree from top to bottom, completing
+ * one layer before dropping down to the next (thus always processing a
+ * node before any of its children).
+ */
+static struct cpuset *cpuset_next(struct list_head *queue)
+{
+ struct cpuset *cp;
+ struct cpuset *child; /* scans child cpusets of cp */
+ struct cgroup *cont;
+
+ if (list_empty(queue))
+ return NULL;
+
+ cp = list_first_entry(queue, struct cpuset, stack_list);
+ list_del(queue->next);
+ list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
+ child = cgroup_cs(cont);
+ list_add_tail(&child->stack_list, queue);
+ }
+
+ return cp;
+}
+
+
+/*
* Walk the specified cpuset subtree and look for empty cpusets.
* The tasks of such cpuset must be moved to a parent cpuset.
*
@@ -2008,19 +2034,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
{
LIST_HEAD(queue);
struct cpuset *cp; /* scans cpusets being updated */
- struct cpuset *child; /* scans child cpusets of cp */
- struct cgroup *cont;
static nodemask_t oldmems; /* protected by cgroup_mutex */
list_add_tail((struct list_head *)&root->stack_list, &queue);
- while (!list_empty(&queue)) {
- cp = list_first_entry(&queue, struct cpuset, stack_list);
- list_del(queue.next);
- list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
- child = cgroup_cs(cont);
- list_add_tail(&child->stack_list, &queue);
- }
+ while ((cp = cpuset_next(&queue)) != NULL) {
/* Continue past cpusets with all cpus, mems online */
if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 3/4] cpusets, hotplug: Restructure functions that are invoked during hotplug
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 2/4] cpusets, hotplug: Implement cpuset tree traversal in a helper function Srivatsa S. Bhat
@ 2012-05-24 14:16 ` Srivatsa S. Bhat
2012-06-20 10:46 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
2012-07-24 14:16 ` tip-bot for Srivatsa S. Bhat
2012-05-24 14:17 ` [PATCH v6 4/4] cpusets: Remove/update outdated comments Srivatsa S. Bhat
` (2 subsequent siblings)
5 siblings, 2 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-05-24 14:16 UTC (permalink / raw)
To: a.p.zijlstra, mingo, pjt, paul, akpm
Cc: rjw, nacc, rientjes, paulmck, tglx, seto.hidetoshi, tj, mschmidt,
berrange, nikunj, vatsa, liuj97, linux-kernel, linux-pm,
srivatsa.bhat
Separate out the cpuset related handling for CPU/Memory online/offline.
This also helps us exploit the most obvious and basic level of optimization
that any notification mechanism (CPU/Mem online/offline) has to offer us:
"We *know* why we have been invoked. So stop pretending that we are lost,
and do only the necessary amount of processing!".
And while at it, rename scan_for_empty_cpusets() to
scan_cpusets_upon_hotplug(), which is more appropriate considering how
it is restructured.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
include/linux/cpuset.h | 4 +-
kernel/cpuset.c | 88 +++++++++++++++++++++++++++++++++---------------
kernel/sched/core.c | 4 +-
3 files changed, 65 insertions(+), 31 deletions(-)
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 668f66b..838320f 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -20,7 +20,7 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */
extern int cpuset_init(void);
extern void cpuset_init_smp(void);
-extern void cpuset_update_active_cpus(void);
+extern void cpuset_update_active_cpus(bool cpu_online);
extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
@@ -124,7 +124,7 @@ static inline void set_mems_allowed(nodemask_t nodemask)
static inline int cpuset_init(void) { return 0; }
static inline void cpuset_init_smp(void) {}
-static inline void cpuset_update_active_cpus(void)
+static inline void cpuset_update_active_cpus(bool cpu_online)
{
partition_sched_domains(1, NULL, NULL);
}
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ba96349..ba0a4d7 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -147,6 +147,12 @@ typedef enum {
CS_SPREAD_SLAB,
} cpuset_flagbits_t;
+/* the type of hotplug event */
+enum hotplug_event {
+ CPUSET_CPU_OFFLINE,
+ CPUSET_MEM_OFFLINE,
+};
+
/* convenient tests for these bits */
static inline int is_cpu_exclusive(const struct cpuset *cs)
{
@@ -2016,8 +2022,10 @@ static struct cpuset *cpuset_next(struct list_head *queue)
/*
- * Walk the specified cpuset subtree and look for empty cpusets.
- * The tasks of such cpuset must be moved to a parent cpuset.
+ * Walk the specified cpuset subtree upon a hotplug operation (CPU/Memory
+ * online/offline) and update the cpusets accordingly.
+ * For regular CPU/Mem hotplug, look for empty cpusets; the tasks of such
+ * cpuset must be moved to a parent cpuset.
*
* Called with cgroup_mutex held. We take callback_mutex to modify
* cpus_allowed and mems_allowed.
@@ -2030,38 +2038,58 @@ static struct cpuset *cpuset_next(struct list_head *queue)
* that has tasks along with an empty 'mems'. But if we did see such
* a cpuset, we'd handle it just like we do if its 'cpus' was empty.
*/
-static void scan_for_empty_cpusets(struct cpuset *root)
+static void
+scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
{
LIST_HEAD(queue);
- struct cpuset *cp; /* scans cpusets being updated */
+ struct cpuset *cp; /* scans cpusets being updated */
static nodemask_t oldmems; /* protected by cgroup_mutex */
list_add_tail((struct list_head *)&root->stack_list, &queue);
- while ((cp = cpuset_next(&queue)) != NULL) {
+ switch (event) {
+ case CPUSET_CPU_OFFLINE:
+ while ((cp = cpuset_next(&queue)) != NULL) {
- /* Continue past cpusets with all cpus, mems online */
- if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
- nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
- continue;
+ /* Continue past cpusets with all cpus online */
+ if (cpumask_subset(cp->cpus_allowed, cpu_active_mask))
+ continue;
- oldmems = cp->mems_allowed;
+ /* Remove offline cpus from this cpuset. */
+ mutex_lock(&callback_mutex);
+ cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
+ cpu_active_mask);
+ mutex_unlock(&callback_mutex);
- /* Remove offline cpus and mems from this cpuset. */
- mutex_lock(&callback_mutex);
- cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
- cpu_active_mask);
- nodes_and(cp->mems_allowed, cp->mems_allowed,
+ /* Move tasks from the empty cpuset to a parent */
+ if (cpumask_empty(cp->cpus_allowed))
+ remove_tasks_in_empty_cpuset(cp);
+ else
+ update_tasks_cpumask(cp, NULL);
+ }
+ break;
+
+ case CPUSET_MEM_OFFLINE:
+ while ((cp = cpuset_next(&queue)) != NULL) {
+
+ /* Continue past cpusets with all mems online */
+ if (nodes_subset(cp->mems_allowed,
+ node_states[N_HIGH_MEMORY]))
+ continue;
+
+ oldmems = cp->mems_allowed;
+
+ /* Remove offline mems from this cpuset. */
+ mutex_lock(&callback_mutex);
+ nodes_and(cp->mems_allowed, cp->mems_allowed,
node_states[N_HIGH_MEMORY]);
- mutex_unlock(&callback_mutex);
+ mutex_unlock(&callback_mutex);
- /* Move tasks from the empty cpuset to a parent */
- if (cpumask_empty(cp->cpus_allowed) ||
- nodes_empty(cp->mems_allowed))
- remove_tasks_in_empty_cpuset(cp);
- else {
- update_tasks_cpumask(cp, NULL);
- update_tasks_nodemask(cp, &oldmems, NULL);
+ /* Move tasks from the empty cpuset to a parent */
+ if (nodes_empty(cp->mems_allowed))
+ remove_tasks_in_empty_cpuset(cp);
+ else
+ update_tasks_nodemask(cp, &oldmems, NULL);
}
}
}
@@ -2080,8 +2108,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
*
* Called within get_online_cpus(). Needs to call cgroup_lock()
* before calling generate_sched_domains().
+ *
+ * @cpu_online: Indicates whether this is a CPU online event (true) or
+ * a CPU offline event (false).
*/
-void cpuset_update_active_cpus(void)
+void cpuset_update_active_cpus(bool cpu_online)
{
struct sched_domain_attr *attr;
cpumask_var_t *doms;
@@ -2091,7 +2122,10 @@ void cpuset_update_active_cpus(void)
mutex_lock(&callback_mutex);
cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
mutex_unlock(&callback_mutex);
- scan_for_empty_cpusets(&top_cpuset);
+
+ if (!cpu_online)
+ scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_CPU_OFFLINE);
+
ndoms = generate_sched_domains(&doms, &attr);
cgroup_unlock();
@@ -2122,9 +2156,9 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
case MEM_OFFLINE:
/*
* needn't update top_cpuset.mems_allowed explicitly because
- * scan_for_empty_cpusets() will update it.
+ * scan_cpusets_upon_hotplug() will update it.
*/
- scan_for_empty_cpusets(&top_cpuset);
+ scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_MEM_OFFLINE);
break;
default:
break;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 59a1591..62f3fb2 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6853,7 +6853,7 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
case CPU_ONLINE:
case CPU_DOWN_FAILED:
- cpuset_update_active_cpus();
+ cpuset_update_active_cpus(true);
break;
default:
return NOTIFY_DONE;
@@ -6866,7 +6866,7 @@ static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
{
switch (action) {
case CPU_DOWN_PREPARE:
- cpuset_update_active_cpus();
+ cpuset_update_active_cpus(false);
break;
case CPU_DOWN_PREPARE_FROZEN:
num_cpus_frozen++;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v6 4/4] cpusets: Remove/update outdated comments
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
` (2 preceding siblings ...)
2012-05-24 14:16 ` [PATCH v6 3/4] cpusets, hotplug: Restructure functions that are invoked during hotplug Srivatsa S. Bhat
@ 2012-05-24 14:17 ` Srivatsa S. Bhat
2012-06-20 10:47 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
2012-07-24 14:17 ` tip-bot for Srivatsa S. Bhat
2012-05-25 9:38 ` [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Peter Zijlstra
2012-06-20 9:36 ` Srivatsa S. Bhat
5 siblings, 2 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-05-24 14:17 UTC (permalink / raw)
To: a.p.zijlstra, mingo, pjt, paul, akpm
Cc: rjw, nacc, rientjes, paulmck, tglx, seto.hidetoshi, tj, mschmidt,
berrange, nikunj, vatsa, liuj97, linux-kernel, linux-pm,
srivatsa.bhat
cpuset_track_online_cpus() is no longer present. So remove the
outdated comment and replace it with reference to cpuset_update_active_cpus()
which is its equivalent.
Also, we don't lack memory hot-unplug anymore. And David Rientjes pointed
out how it is dealt with. So update that comment as well.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
kernel/cpuset.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ba0a4d7..f33c715 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2034,9 +2034,8 @@ static struct cpuset *cpuset_next(struct list_head *queue)
* before dropping down to the next. It always processes a node before
* any of its children.
*
- * For now, since we lack memory hot unplug, we'll never see a cpuset
- * that has tasks along with an empty 'mems'. But if we did see such
- * a cpuset, we'd handle it just like we do if its 'cpus' was empty.
+ * In the case of memory hot-unplug, it will remove nodes from N_HIGH_MEMORY
+ * if all present pages from a node are offlined.
*/
static void
scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
@@ -2137,7 +2136,7 @@ void cpuset_update_active_cpus(bool cpu_online)
/*
* Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
* Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
- * See also the previous routine cpuset_track_online_cpus().
+ * See cpuset_update_active_cpus() for CPU hotplug handling.
*/
static int cpuset_track_online_nodes(struct notifier_block *self,
unsigned long action, void *arg)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
` (3 preceding siblings ...)
2012-05-24 14:17 ` [PATCH v6 4/4] cpusets: Remove/update outdated comments Srivatsa S. Bhat
@ 2012-05-25 9:38 ` Peter Zijlstra
2012-05-25 11:22 ` Srivatsa S. Bhat
2012-06-20 9:36 ` Srivatsa S. Bhat
5 siblings, 1 reply; 21+ messages in thread
From: Peter Zijlstra @ 2012-05-25 9:38 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: mingo, pjt, paul, akpm, rjw, nacc, rientjes, paulmck, tglx,
seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa, liuj97,
linux-kernel, linux-pm
Thanks, queued them.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-05-25 9:38 ` [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Peter Zijlstra
@ 2012-05-25 11:22 ` Srivatsa S. Bhat
0 siblings, 0 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-05-25 11:22 UTC (permalink / raw)
To: Peter Zijlstra
Cc: mingo, pjt, paul, akpm, rjw, nacc, rientjes, paulmck, tglx,
seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa, liuj97,
linux-kernel, linux-pm
On 05/25/2012 03:08 PM, Peter Zijlstra wrote:
>
> Thanks, queued them.
>
Thanks a lot Peter!
Regards,
Srivatsa S. Bhat
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
` (4 preceding siblings ...)
2012-05-25 9:38 ` [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Peter Zijlstra
@ 2012-06-20 9:36 ` Srivatsa S. Bhat
2012-06-20 11:39 ` Ingo Molnar
5 siblings, 1 reply; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-06-20 9:36 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Srivatsa S. Bhat, mingo, pjt, paul, akpm, rjw, nacc, rientjes,
paulmck, tglx, seto.hidetoshi, tj, mschmidt, berrange, nikunj,
vatsa, liuj97, linux-kernel, linux-pm
On 05/24/2012 07:46 PM, Srivatsa S. Bhat wrote:
> Currently the kernel doesn't handle cpusets properly during suspend/resume.
> After a resume, all non-root cpusets end up having only 1 cpu (the boot cpu),
> causing massive performance degradation of workloads. One major user of cpusets
> is libvirt, which means that after a suspend/hibernation cycle, all VMs
> suddenly end up running terribly slow!
>
> Also, the kernel moves the tasks from one cpuset to another during CPU hotplug
> in the suspend/resume path, leading to a task-management nightmare after
> resume.
>
> Patch 1 fixes this by keeping cpusets unmodified in the suspend/resume path.
> But to ensure we don't trip over, it keeps the sched domains updated during
> every CPU hotplug in the s/r path.
> This is a long standing issue and we need to fix up stable kernels too.
>
> The rest of the patches in the series are mostly cleanups/optimizations.
>
Hi Peter,
Would you be taking these patches through -tip for 3.6?
Regards,
Srivatsa S. Bhat
^ permalink raw reply [flat|nested] 21+ messages in thread
* [tip:sched/core] CPU hotplug, cpusets, suspend: Don' t modify cpusets during suspend/resume
2012-05-24 14:16 ` [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume Srivatsa S. Bhat
@ 2012-06-20 10:44 ` tip-bot for Srivatsa S. Bhat
2012-07-24 14:14 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-06-20 10:44 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: 0c1508129adc051fabaf8debefea79baa2f1a81b
Gitweb: http://git.kernel.org/tip/0c1508129adc051fabaf8debefea79baa2f1a81b
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:46:26 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 18 Jun 2012 11:45:02 +0200
CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume
In the event of CPU hotplug, the kernel modifies the cpusets' cpus_allowed
masks as and when necessary to ensure that the tasks belonging to the cpusets
have some place (online CPUs) to run on. And regular CPU hotplug is
destructive in the sense that the kernel doesn't remember the original cpuset
configurations set by the user, across hotplug operations.
However, suspend/resume (which uses CPU hotplug) is a special case in which
the kernel has the responsibility to restore the system (during resume), to
exactly the same state it was in before suspend.
In order to achieve that, do the following:
1. Don't modify cpusets during suspend/resume. At all.
In particular, don't move the tasks from one cpuset to another, and
don't modify any cpuset's cpus_allowed mask. So, simply ignore cpusets
during the CPU hotplug operations that are carried out in the
suspend/resume path.
2. However, cpusets and sched domains are related. We just want to avoid
altering cpusets alone. So, to keep the sched domains updated, build
a single sched domain (containing all active cpus) during each of the
CPU hotplug operations carried out in s/r path, effectively ignoring
the cpusets' cpus_allowed masks.
(Since userspace is frozen while doing all this, it will go unnoticed.)
3. During the last CPU online operation during resume, build the sched
domains by looking up the (unaltered) cpusets' cpus_allowed masks.
That will bring back the system to the same original state as it was in
before suspend.
Ultimately, this will not only solve the cpuset problem related to suspend
resume (ie., restores the cpusets to exactly what it was before suspend, by
not touching it at all) but also speeds up suspend/resume because we avoid
running cpuset update code for every CPU being offlined/onlined.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141611.3692.20155.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/cpuset.c | 3 +++
kernel/sched/core.c | 40 ++++++++++++++++++++++++++++++++++++----
2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 47de450..77abe1a 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2054,6 +2054,9 @@ static void scan_for_empty_cpusets(struct cpuset *root)
* (of no affect) on systems that are actively using CPU hotplug
* but making no active use of cpusets.
*
+ * The only exception to this is suspend/resume, where we don't
+ * modify cpusets at all.
+ *
* This routine ensures that top_cpuset.cpus_allowed tracks
* cpu_active_mask on each CPU hotplug (cpuhp) event.
*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ca07ee0..e368731 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7014,34 +7014,66 @@ match2:
mutex_unlock(&sched_domains_mutex);
}
+static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */
+
/*
* Update cpusets according to cpu_active mask. If cpusets are
* disabled, cpuset_update_active_cpus() becomes a simple wrapper
* around partition_sched_domains().
+ *
+ * If we come here as part of a suspend/resume, don't touch cpusets because we
+ * want to restore it back to its original state upon resume anyway.
*/
static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
+ case CPU_ONLINE_FROZEN:
+ case CPU_DOWN_FAILED_FROZEN:
+
+ /*
+ * num_cpus_frozen tracks how many CPUs are involved in suspend
+ * resume sequence. As long as this is not the last online
+ * operation in the resume sequence, just build a single sched
+ * domain, ignoring cpusets.
+ */
+ num_cpus_frozen--;
+ if (likely(num_cpus_frozen)) {
+ partition_sched_domains(1, NULL, NULL);
+ break;
+ }
+
+ /*
+ * This is the last CPU online operation. So fall through and
+ * restore the original sched domains by considering the
+ * cpuset configurations.
+ */
+
case CPU_ONLINE:
case CPU_DOWN_FAILED:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
case CPU_DOWN_PREPARE:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
+ case CPU_DOWN_PREPARE_FROZEN:
+ num_cpus_frozen++;
+ partition_sched_domains(1, NULL, NULL);
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
void __init sched_init_smp(void)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:sched/core] cpusets, hotplug: Implement cpuset tree traversal in a helper function
2012-05-24 14:16 ` [PATCH v6 2/4] cpusets, hotplug: Implement cpuset tree traversal in a helper function Srivatsa S. Bhat
@ 2012-06-20 10:45 ` tip-bot for Srivatsa S. Bhat
2012-07-24 14:15 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-06-20 10:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: b451c38428c5682348b6f661d767e358d1d70c41
Gitweb: http://git.kernel.org/tip/b451c38428c5682348b6f661d767e358d1d70c41
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:46:41 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 18 Jun 2012 11:45:04 +0200
cpusets, hotplug: Implement cpuset tree traversal in a helper function
At present, the functions that deal with cpusets during CPU/Mem hotplug
are quite messy, since a lot of the functionality is mixed up without clear
separation. And this takes a toll on optimization as well. For example,
the function cpuset_update_active_cpus() is called on both CPU offline and CPU
online events; and it invokes scan_for_empty_cpusets(), which makes sense
only for CPU offline events. And hence, the current code ends up unnecessarily
traversing the cpuset tree during CPU online also.
As a first step towards cleaning up those functions, encapsulate the cpuset
tree traversal in a helper function, so as to facilitate upcoming changes.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141635.3692.893.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/cpuset.c | 36 +++++++++++++++++++++++++++---------
1 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 77abe1a..e0b29bb 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1990,6 +1990,32 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
}
/*
+ * Helper function to traverse cpusets.
+ * It can be used to walk the cpuset tree from top to bottom, completing
+ * one layer before dropping down to the next (thus always processing a
+ * node before any of its children).
+ */
+static struct cpuset *cpuset_next(struct list_head *queue)
+{
+ struct cpuset *cp;
+ struct cpuset *child; /* scans child cpusets of cp */
+ struct cgroup *cont;
+
+ if (list_empty(queue))
+ return NULL;
+
+ cp = list_first_entry(queue, struct cpuset, stack_list);
+ list_del(queue->next);
+ list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
+ child = cgroup_cs(cont);
+ list_add_tail(&child->stack_list, queue);
+ }
+
+ return cp;
+}
+
+
+/*
* Walk the specified cpuset subtree and look for empty cpusets.
* The tasks of such cpuset must be moved to a parent cpuset.
*
@@ -2008,19 +2034,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
{
LIST_HEAD(queue);
struct cpuset *cp; /* scans cpusets being updated */
- struct cpuset *child; /* scans child cpusets of cp */
- struct cgroup *cont;
static nodemask_t oldmems; /* protected by cgroup_mutex */
list_add_tail((struct list_head *)&root->stack_list, &queue);
- while (!list_empty(&queue)) {
- cp = list_first_entry(&queue, struct cpuset, stack_list);
- list_del(queue.next);
- list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
- child = cgroup_cs(cont);
- list_add_tail(&child->stack_list, &queue);
- }
+ while ((cp = cpuset_next(&queue)) != NULL) {
/* Continue past cpusets with all cpus, mems online */
if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:sched/core] cpusets, hotplug: Restructure functions that are invoked during hotplug
2012-05-24 14:16 ` [PATCH v6 3/4] cpusets, hotplug: Restructure functions that are invoked during hotplug Srivatsa S. Bhat
@ 2012-06-20 10:46 ` tip-bot for Srivatsa S. Bhat
2012-07-24 14:16 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-06-20 10:46 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: 6ac72b5dc395fa8b5f347d82679b9fc9d946deb4
Gitweb: http://git.kernel.org/tip/6ac72b5dc395fa8b5f347d82679b9fc9d946deb4
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:46:55 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 18 Jun 2012 11:45:04 +0200
cpusets, hotplug: Restructure functions that are invoked during hotplug
Separate out the cpuset related handling for CPU/Memory online/offline.
This also helps us exploit the most obvious and basic level of optimization
that any notification mechanism (CPU/Mem online/offline) has to offer us:
"We *know* why we have been invoked. So stop pretending that we are lost,
and do only the necessary amount of processing!".
And while at it, rename scan_for_empty_cpusets() to
scan_cpusets_upon_hotplug(), which is more appropriate considering how
it is restructured.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141650.3692.48637.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
include/linux/cpuset.h | 4 +-
kernel/cpuset.c | 88 +++++++++++++++++++++++++++++++++---------------
kernel/sched/core.c | 4 +-
3 files changed, 65 insertions(+), 31 deletions(-)
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 4052564..119be3a 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -20,7 +20,7 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */
extern int cpuset_init(void);
extern void cpuset_init_smp(void);
-extern void cpuset_update_active_cpus(void);
+extern void cpuset_update_active_cpus(bool cpu_online);
extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
@@ -125,7 +125,7 @@ static inline void set_mems_allowed(nodemask_t nodemask)
static inline int cpuset_init(void) { return 0; }
static inline void cpuset_init_smp(void) {}
-static inline void cpuset_update_active_cpus(void)
+static inline void cpuset_update_active_cpus(bool cpu_online)
{
partition_sched_domains(1, NULL, NULL);
}
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index e0b29bb..3780a9e 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -147,6 +147,12 @@ typedef enum {
CS_SPREAD_SLAB,
} cpuset_flagbits_t;
+/* the type of hotplug event */
+enum hotplug_event {
+ CPUSET_CPU_OFFLINE,
+ CPUSET_MEM_OFFLINE,
+};
+
/* convenient tests for these bits */
static inline int is_cpu_exclusive(const struct cpuset *cs)
{
@@ -2016,8 +2022,10 @@ static struct cpuset *cpuset_next(struct list_head *queue)
/*
- * Walk the specified cpuset subtree and look for empty cpusets.
- * The tasks of such cpuset must be moved to a parent cpuset.
+ * Walk the specified cpuset subtree upon a hotplug operation (CPU/Memory
+ * online/offline) and update the cpusets accordingly.
+ * For regular CPU/Mem hotplug, look for empty cpusets; the tasks of such
+ * cpuset must be moved to a parent cpuset.
*
* Called with cgroup_mutex held. We take callback_mutex to modify
* cpus_allowed and mems_allowed.
@@ -2030,38 +2038,58 @@ static struct cpuset *cpuset_next(struct list_head *queue)
* that has tasks along with an empty 'mems'. But if we did see such
* a cpuset, we'd handle it just like we do if its 'cpus' was empty.
*/
-static void scan_for_empty_cpusets(struct cpuset *root)
+static void
+scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
{
LIST_HEAD(queue);
- struct cpuset *cp; /* scans cpusets being updated */
+ struct cpuset *cp; /* scans cpusets being updated */
static nodemask_t oldmems; /* protected by cgroup_mutex */
list_add_tail((struct list_head *)&root->stack_list, &queue);
- while ((cp = cpuset_next(&queue)) != NULL) {
+ switch (event) {
+ case CPUSET_CPU_OFFLINE:
+ while ((cp = cpuset_next(&queue)) != NULL) {
+
+ /* Continue past cpusets with all cpus online */
+ if (cpumask_subset(cp->cpus_allowed, cpu_active_mask))
+ continue;
+
+ /* Remove offline cpus from this cpuset. */
+ mutex_lock(&callback_mutex);
+ cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
+ cpu_active_mask);
+ mutex_unlock(&callback_mutex);
+
+ /* Move tasks from the empty cpuset to a parent */
+ if (cpumask_empty(cp->cpus_allowed))
+ remove_tasks_in_empty_cpuset(cp);
+ else
+ update_tasks_cpumask(cp, NULL);
+ }
+ break;
- /* Continue past cpusets with all cpus, mems online */
- if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
- nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
- continue;
+ case CPUSET_MEM_OFFLINE:
+ while ((cp = cpuset_next(&queue)) != NULL) {
- oldmems = cp->mems_allowed;
+ /* Continue past cpusets with all mems online */
+ if (nodes_subset(cp->mems_allowed,
+ node_states[N_HIGH_MEMORY]))
+ continue;
- /* Remove offline cpus and mems from this cpuset. */
- mutex_lock(&callback_mutex);
- cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
- cpu_active_mask);
- nodes_and(cp->mems_allowed, cp->mems_allowed,
+ oldmems = cp->mems_allowed;
+
+ /* Remove offline mems from this cpuset. */
+ mutex_lock(&callback_mutex);
+ nodes_and(cp->mems_allowed, cp->mems_allowed,
node_states[N_HIGH_MEMORY]);
- mutex_unlock(&callback_mutex);
+ mutex_unlock(&callback_mutex);
- /* Move tasks from the empty cpuset to a parent */
- if (cpumask_empty(cp->cpus_allowed) ||
- nodes_empty(cp->mems_allowed))
- remove_tasks_in_empty_cpuset(cp);
- else {
- update_tasks_cpumask(cp, NULL);
- update_tasks_nodemask(cp, &oldmems, NULL);
+ /* Move tasks from the empty cpuset to a parent */
+ if (nodes_empty(cp->mems_allowed))
+ remove_tasks_in_empty_cpuset(cp);
+ else
+ update_tasks_nodemask(cp, &oldmems, NULL);
}
}
}
@@ -2080,8 +2108,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
*
* Called within get_online_cpus(). Needs to call cgroup_lock()
* before calling generate_sched_domains().
+ *
+ * @cpu_online: Indicates whether this is a CPU online event (true) or
+ * a CPU offline event (false).
*/
-void cpuset_update_active_cpus(void)
+void cpuset_update_active_cpus(bool cpu_online)
{
struct sched_domain_attr *attr;
cpumask_var_t *doms;
@@ -2091,7 +2122,10 @@ void cpuset_update_active_cpus(void)
mutex_lock(&callback_mutex);
cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
mutex_unlock(&callback_mutex);
- scan_for_empty_cpusets(&top_cpuset);
+
+ if (!cpu_online)
+ scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_CPU_OFFLINE);
+
ndoms = generate_sched_domains(&doms, &attr);
cgroup_unlock();
@@ -2122,9 +2156,9 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
case MEM_OFFLINE:
/*
* needn't update top_cpuset.mems_allowed explicitly because
- * scan_for_empty_cpusets() will update it.
+ * scan_cpusets_upon_hotplug() will update it.
*/
- scan_for_empty_cpusets(&top_cpuset);
+ scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_MEM_OFFLINE);
break;
default:
break;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index e368731..eee1908 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7051,7 +7051,7 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
case CPU_ONLINE:
case CPU_DOWN_FAILED:
- cpuset_update_active_cpus();
+ cpuset_update_active_cpus(true);
break;
default:
return NOTIFY_DONE;
@@ -7064,7 +7064,7 @@ static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
{
switch (action) {
case CPU_DOWN_PREPARE:
- cpuset_update_active_cpus();
+ cpuset_update_active_cpus(false);
break;
case CPU_DOWN_PREPARE_FROZEN:
num_cpus_frozen++;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:sched/core] cpusets: Remove/update outdated comments
2012-05-24 14:17 ` [PATCH v6 4/4] cpusets: Remove/update outdated comments Srivatsa S. Bhat
@ 2012-06-20 10:47 ` tip-bot for Srivatsa S. Bhat
2012-07-24 14:17 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-06-20 10:47 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: c78888daa68238f3943d54a2dae7c9b18a71cae7
Gitweb: http://git.kernel.org/tip/c78888daa68238f3943d54a2dae7c9b18a71cae7
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:47:03 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 18 Jun 2012 11:45:05 +0200
cpusets: Remove/update outdated comments
cpuset_track_online_cpus() is no longer present. So remove the
outdated comment and replace it with reference to cpuset_update_active_cpus()
which is its equivalent.
Also, we don't lack memory hot-unplug anymore. And David Rientjes pointed
out how it is dealt with. So update that comment as well.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141700.3692.98192.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/cpuset.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 3780a9e..0cbc631 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2034,9 +2034,8 @@ static struct cpuset *cpuset_next(struct list_head *queue)
* before dropping down to the next. It always processes a node before
* any of its children.
*
- * For now, since we lack memory hot unplug, we'll never see a cpuset
- * that has tasks along with an empty 'mems'. But if we did see such
- * a cpuset, we'd handle it just like we do if its 'cpus' was empty.
+ * In the case of memory hot-unplug, it will remove nodes from N_HIGH_MEMORY
+ * if all present pages from a node are offlined.
*/
static void
scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
@@ -2137,7 +2136,7 @@ void cpuset_update_active_cpus(bool cpu_online)
/*
* Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
* Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
- * See also the previous routine cpuset_track_online_cpus().
+ * See cpuset_update_active_cpus() for CPU hotplug handling.
*/
static int cpuset_track_online_nodes(struct notifier_block *self,
unsigned long action, void *arg)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-06-20 9:36 ` Srivatsa S. Bhat
@ 2012-06-20 11:39 ` Ingo Molnar
2012-06-20 14:17 ` Srivatsa S. Bhat
0 siblings, 1 reply; 21+ messages in thread
From: Ingo Molnar @ 2012-06-20 11:39 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: Peter Zijlstra, pjt, paul, akpm, rjw, nacc, rientjes, paulmck,
tglx, seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa,
liuj97, linux-kernel, linux-pm
* Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
> On 05/24/2012 07:46 PM, Srivatsa S. Bhat wrote:
>
> > Currently the kernel doesn't handle cpusets properly during
> > suspend/resume. After a resume, all non-root cpusets end up
> > having only 1 cpu (the boot cpu), causing massive
> > performance degradation of workloads. One major user of
> > cpusets is libvirt, which means that after a
> > suspend/hibernation cycle, all VMs suddenly end up running
> > terribly slow!
> >
> > Also, the kernel moves the tasks from one cpuset to another
> > during CPU hotplug in the suspend/resume path, leading to a
> > task-management nightmare after resume.
> >
> > Patch 1 fixes this by keeping cpusets unmodified in the
> > suspend/resume path. But to ensure we don't trip over, it
> > keeps the sched domains updated during every CPU hotplug in
> > the s/r path. This is a long standing issue and we need to
> > fix up stable kernels too.
> >
> > The rest of the patches in the series are mostly
> > cleanups/optimizations.
>
> Hi Peter,
>
> Would you be taking these patches through -tip for 3.6?
They are now in tip:sched/core.
Note that I removed the Cc:stable tag - it's not a regression
fix and such it is not eligible for immediate -stable backports.
( Once they are upstream and have been problem-free upstream for
several weeks then *maybe* we could forward the first commit
to -stable, as a super special exception. )
Thanks,
Ingo
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-06-20 11:39 ` Ingo Molnar
@ 2012-06-20 14:17 ` Srivatsa S. Bhat
2012-06-20 14:26 ` Srivatsa S. Bhat
2012-06-20 14:47 ` Ingo Molnar
0 siblings, 2 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-06-20 14:17 UTC (permalink / raw)
To: Ingo Molnar
Cc: Peter Zijlstra, pjt, paul, akpm, rjw, nacc, rientjes, paulmck,
tglx, seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa,
liuj97, linux-kernel, linux-pm
On 06/20/2012 05:09 PM, Ingo Molnar wrote:
> * Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>
>> On 05/24/2012 07:46 PM, Srivatsa S. Bhat wrote:
>>
>>> Currently the kernel doesn't handle cpusets properly during
>>> suspend/resume. After a resume, all non-root cpusets end up
>>> having only 1 cpu (the boot cpu), causing massive
>>> performance degradation of workloads. One major user of
>>> cpusets is libvirt, which means that after a
>>> suspend/hibernation cycle, all VMs suddenly end up running
>>> terribly slow!
>>>
>>> Also, the kernel moves the tasks from one cpuset to another
>>> during CPU hotplug in the suspend/resume path, leading to a
>>> task-management nightmare after resume.
>>>
>>> Patch 1 fixes this by keeping cpusets unmodified in the
>>> suspend/resume path. But to ensure we don't trip over, it
>>> keeps the sched domains updated during every CPU hotplug in
>>> the s/r path. This is a long standing issue and we need to
>>> fix up stable kernels too.
>>>
>>> The rest of the patches in the series are mostly
>>> cleanups/optimizations.
>>
>> Hi Peter,
>>
>> Would you be taking these patches through -tip for 3.6?
>
> They are now in tip:sched/core.
>
> Note that I removed the Cc:stable tag - it's not a regression
> fix and such it is not eligible for immediate -stable backports.
>
> ( Once they are upstream and have been problem-free upstream for
> several weeks then *maybe* we could forward the first commit
> to -stable, as a super special exception. )
>
OK, I get the point of allowing it to cook in the mainline for a
while before backporting to -stable and I totally agree with that,
but why so much of uncertainty about whether the first commit should
(eventually) even land in -stable or not? Distros have been struggling
to deal with this bug in userspace and have failed, and AFAIK they are
waiting for a proper kernel fix for this bug. Agreed, this is not a
regression per se, but isn't this bug critical enough to qualify for
-stable?
Regards,
Srivatsa S. Bhat
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-06-20 14:17 ` Srivatsa S. Bhat
@ 2012-06-20 14:26 ` Srivatsa S. Bhat
2012-06-20 14:47 ` Ingo Molnar
1 sibling, 0 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-06-20 14:26 UTC (permalink / raw)
To: Ingo Molnar
Cc: Peter Zijlstra, pjt, paul, akpm, rjw, nacc, rientjes, paulmck,
tglx, seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa,
liuj97, linux-kernel, linux-pm
On 06/20/2012 07:47 PM, Srivatsa S. Bhat wrote:
> On 06/20/2012 05:09 PM, Ingo Molnar wrote:
>
>> * Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>
>>> On 05/24/2012 07:46 PM, Srivatsa S. Bhat wrote:
>>>
>>>> Currently the kernel doesn't handle cpusets properly during
>>>> suspend/resume. After a resume, all non-root cpusets end up
>>>> having only 1 cpu (the boot cpu), causing massive
>>>> performance degradation of workloads. One major user of
>>>> cpusets is libvirt, which means that after a
>>>> suspend/hibernation cycle, all VMs suddenly end up running
>>>> terribly slow!
>>>>
>>>> Also, the kernel moves the tasks from one cpuset to another
>>>> during CPU hotplug in the suspend/resume path, leading to a
>>>> task-management nightmare after resume.
>>>>
>>>> Patch 1 fixes this by keeping cpusets unmodified in the
>>>> suspend/resume path. But to ensure we don't trip over, it
>>>> keeps the sched domains updated during every CPU hotplug in
>>>> the s/r path. This is a long standing issue and we need to
>>>> fix up stable kernels too.
>>>>
>>>> The rest of the patches in the series are mostly
>>>> cleanups/optimizations.
>>>
>>> Hi Peter,
>>>
>>> Would you be taking these patches through -tip for 3.6?
>>
>> They are now in tip:sched/core.
>>
>> Note that I removed the Cc:stable tag - it's not a regression
>> fix and such it is not eligible for immediate -stable backports.
>>
>> ( Once they are upstream and have been problem-free upstream for
>> several weeks then *maybe* we could forward the first commit
>> to -stable, as a super special exception. )
>>
>
>
> OK, I get the point of allowing it to cook in the mainline for a
> while before backporting to -stable and I totally agree with that,
> but why so much of uncertainty about whether the first commit should
> (eventually) even land in -stable or not? Distros have been struggling
> to deal with this bug in userspace and have failed, and AFAIK they are
> waiting for a proper kernel fix for this bug. Agreed, this is not a
> regression per se, but isn't this bug critical enough to qualify for
> -stable?
>
IOW, I was just wondering what that "super special exception" was
all about ;-)
Regards,
Srivatsa S. Bhat
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-06-20 14:17 ` Srivatsa S. Bhat
2012-06-20 14:26 ` Srivatsa S. Bhat
@ 2012-06-20 14:47 ` Ingo Molnar
2012-06-20 16:06 ` Srivatsa S. Bhat
1 sibling, 1 reply; 21+ messages in thread
From: Ingo Molnar @ 2012-06-20 14:47 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: Peter Zijlstra, pjt, paul, akpm, rjw, nacc, rientjes, paulmck,
tglx, seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa,
liuj97, linux-kernel, linux-pm
* Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
> On 06/20/2012 05:09 PM, Ingo Molnar wrote:
>
> > * Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
> >
> >> On 05/24/2012 07:46 PM, Srivatsa S. Bhat wrote:
> >>
> >>> Currently the kernel doesn't handle cpusets properly during
> >>> suspend/resume. After a resume, all non-root cpusets end up
> >>> having only 1 cpu (the boot cpu), causing massive
> >>> performance degradation of workloads. One major user of
> >>> cpusets is libvirt, which means that after a
> >>> suspend/hibernation cycle, all VMs suddenly end up running
> >>> terribly slow!
> >>>
> >>> Also, the kernel moves the tasks from one cpuset to another
> >>> during CPU hotplug in the suspend/resume path, leading to a
> >>> task-management nightmare after resume.
> >>>
> >>> Patch 1 fixes this by keeping cpusets unmodified in the
> >>> suspend/resume path. But to ensure we don't trip over, it
> >>> keeps the sched domains updated during every CPU hotplug in
> >>> the s/r path. This is a long standing issue and we need to
> >>> fix up stable kernels too.
> >>>
> >>> The rest of the patches in the series are mostly
> >>> cleanups/optimizations.
> >>
> >> Hi Peter,
> >>
> >> Would you be taking these patches through -tip for 3.6?
> >
> > They are now in tip:sched/core.
> >
> > Note that I removed the Cc:stable tag - it's not a regression
> > fix and such it is not eligible for immediate -stable backports.
> >
> > ( Once they are upstream and have been problem-free upstream for
> > several weeks then *maybe* we could forward the first commit
> > to -stable, as a super special exception. )
> >
>
>
> OK, I get the point of allowing it to cook in the mainline for
> a while before backporting to -stable and I totally agree with
> that, but why so much of uncertainty about whether the first
> commit should (eventually) even land in -stable or not?
> Distros have been struggling to deal with this bug in
> userspace and have failed, and AFAIK they are waiting for a
> proper kernel fix for this bug. Agreed, this is not a
> regression per se, but isn't this bug critical enough to
> qualify for -stable?
No, as a general rule only regression fixes are included in
-stable. The workflow is this: in the v3.4 -stable kernel we
included fixes that were introduced in the v3.4 merge window,
i.e. bugs that were introduced after v3.3 was released.
Not 'fixes' in general.
Fixes for "has been broken forever" problems (like this one) go
upstream and get released in the next stable kernel that gets
released - v3.6 in this case.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations
2012-06-20 14:47 ` Ingo Molnar
@ 2012-06-20 16:06 ` Srivatsa S. Bhat
0 siblings, 0 replies; 21+ messages in thread
From: Srivatsa S. Bhat @ 2012-06-20 16:06 UTC (permalink / raw)
To: Ingo Molnar
Cc: Peter Zijlstra, pjt, paul, akpm, rjw, nacc, rientjes, paulmck,
tglx, seto.hidetoshi, tj, mschmidt, berrange, nikunj, vatsa,
liuj97, linux-kernel, linux-pm
On 06/20/2012 08:17 PM, Ingo Molnar wrote:
>
> * Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>
>> On 06/20/2012 05:09 PM, Ingo Molnar wrote:
>>
>>> * Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> wrote:
>>>
>>>> On 05/24/2012 07:46 PM, Srivatsa S. Bhat wrote:
>>>>
>>>>> Currently the kernel doesn't handle cpusets properly during
>>>>> suspend/resume. After a resume, all non-root cpusets end up
>>>>> having only 1 cpu (the boot cpu), causing massive
>>>>> performance degradation of workloads. One major user of
>>>>> cpusets is libvirt, which means that after a
>>>>> suspend/hibernation cycle, all VMs suddenly end up running
>>>>> terribly slow!
>>>>>
>>>>> Also, the kernel moves the tasks from one cpuset to another
>>>>> during CPU hotplug in the suspend/resume path, leading to a
>>>>> task-management nightmare after resume.
>>>>>
>>>>> Patch 1 fixes this by keeping cpusets unmodified in the
>>>>> suspend/resume path. But to ensure we don't trip over, it
>>>>> keeps the sched domains updated during every CPU hotplug in
>>>>> the s/r path. This is a long standing issue and we need to
>>>>> fix up stable kernels too.
>>>>>
>>>>> The rest of the patches in the series are mostly
>>>>> cleanups/optimizations.
>>>>
>>>> Hi Peter,
>>>>
>>>> Would you be taking these patches through -tip for 3.6?
>>>
>>> They are now in tip:sched/core.
>>>
>>> Note that I removed the Cc:stable tag - it's not a regression
>>> fix and such it is not eligible for immediate -stable backports.
>>>
>>> ( Once they are upstream and have been problem-free upstream for
>>> several weeks then *maybe* we could forward the first commit
>>> to -stable, as a super special exception. )
>>>
>>
>>
>> OK, I get the point of allowing it to cook in the mainline for
>> a while before backporting to -stable and I totally agree with
>> that, but why so much of uncertainty about whether the first
>> commit should (eventually) even land in -stable or not?
>> Distros have been struggling to deal with this bug in
>> userspace and have failed, and AFAIK they are waiting for a
>> proper kernel fix for this bug. Agreed, this is not a
>> regression per se, but isn't this bug critical enough to
>> qualify for -stable?
>
> No, as a general rule only regression fixes are included in
> -stable. The workflow is this: in the v3.4 -stable kernel we
> included fixes that were introduced in the v3.4 merge window,
> i.e. bugs that were introduced after v3.3 was released.
>
> Not 'fixes' in general.
>
> Fixes for "has been broken forever" problems (like this one) go
> upstream and get released in the next stable kernel that gets
> released - v3.6 in this case.
>
Ah, ok.. Thanks for the explanation!
Regards,
Srivatsa S. Bhat
^ permalink raw reply [flat|nested] 21+ messages in thread
* [tip:sched/core] CPU hotplug, cpusets, suspend: Don' t modify cpusets during suspend/resume
2012-05-24 14:16 ` [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume Srivatsa S. Bhat
2012-06-20 10:44 ` [tip:sched/core] CPU hotplug, cpusets, suspend: Don' t " tip-bot for Srivatsa S. Bhat
@ 2012-07-24 14:14 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-07-24 14:14 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: d35be8bab9b0ce44bed4b9453f86ebf64062721e
Gitweb: http://git.kernel.org/tip/d35be8bab9b0ce44bed4b9453f86ebf64062721e
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:46:26 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 24 Jul 2012 13:53:14 +0200
CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume
In the event of CPU hotplug, the kernel modifies the cpusets' cpus_allowed
masks as and when necessary to ensure that the tasks belonging to the cpusets
have some place (online CPUs) to run on. And regular CPU hotplug is
destructive in the sense that the kernel doesn't remember the original cpuset
configurations set by the user, across hotplug operations.
However, suspend/resume (which uses CPU hotplug) is a special case in which
the kernel has the responsibility to restore the system (during resume), to
exactly the same state it was in before suspend.
In order to achieve that, do the following:
1. Don't modify cpusets during suspend/resume. At all.
In particular, don't move the tasks from one cpuset to another, and
don't modify any cpuset's cpus_allowed mask. So, simply ignore cpusets
during the CPU hotplug operations that are carried out in the
suspend/resume path.
2. However, cpusets and sched domains are related. We just want to avoid
altering cpusets alone. So, to keep the sched domains updated, build
a single sched domain (containing all active cpus) during each of the
CPU hotplug operations carried out in s/r path, effectively ignoring
the cpusets' cpus_allowed masks.
(Since userspace is frozen while doing all this, it will go unnoticed.)
3. During the last CPU online operation during resume, build the sched
domains by looking up the (unaltered) cpusets' cpus_allowed masks.
That will bring back the system to the same original state as it was in
before suspend.
Ultimately, this will not only solve the cpuset problem related to suspend
resume (ie., restores the cpusets to exactly what it was before suspend, by
not touching it at all) but also speeds up suspend/resume because we avoid
running cpuset update code for every CPU being offlined/onlined.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141611.3692.20155.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/cpuset.c | 3 +++
kernel/sched/core.c | 40 ++++++++++++++++++++++++++++++++++++----
2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 8c8bd65..746d1ee 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2054,6 +2054,9 @@ static void scan_for_empty_cpusets(struct cpuset *root)
* (of no affect) on systems that are actively using CPU hotplug
* but making no active use of cpusets.
*
+ * The only exception to this is suspend/resume, where we don't
+ * modify cpusets at all.
+ *
* This routine ensures that top_cpuset.cpus_allowed tracks
* cpu_active_mask on each CPU hotplug (cpuhp) event.
*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 468bdd4..4c1d80c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7097,34 +7097,66 @@ match2:
mutex_unlock(&sched_domains_mutex);
}
+static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */
+
/*
* Update cpusets according to cpu_active mask. If cpusets are
* disabled, cpuset_update_active_cpus() becomes a simple wrapper
* around partition_sched_domains().
+ *
+ * If we come here as part of a suspend/resume, don't touch cpusets because we
+ * want to restore it back to its original state upon resume anyway.
*/
static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
+ case CPU_ONLINE_FROZEN:
+ case CPU_DOWN_FAILED_FROZEN:
+
+ /*
+ * num_cpus_frozen tracks how many CPUs are involved in suspend
+ * resume sequence. As long as this is not the last online
+ * operation in the resume sequence, just build a single sched
+ * domain, ignoring cpusets.
+ */
+ num_cpus_frozen--;
+ if (likely(num_cpus_frozen)) {
+ partition_sched_domains(1, NULL, NULL);
+ break;
+ }
+
+ /*
+ * This is the last CPU online operation. So fall through and
+ * restore the original sched domains by considering the
+ * cpuset configurations.
+ */
+
case CPU_ONLINE:
case CPU_DOWN_FAILED:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
void *hcpu)
{
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
case CPU_DOWN_PREPARE:
cpuset_update_active_cpus();
- return NOTIFY_OK;
+ break;
+ case CPU_DOWN_PREPARE_FROZEN:
+ num_cpus_frozen++;
+ partition_sched_domains(1, NULL, NULL);
+ break;
default:
return NOTIFY_DONE;
}
+ return NOTIFY_OK;
}
void __init sched_init_smp(void)
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:sched/core] cpusets, hotplug: Implement cpuset tree traversal in a helper function
2012-05-24 14:16 ` [PATCH v6 2/4] cpusets, hotplug: Implement cpuset tree traversal in a helper function Srivatsa S. Bhat
2012-06-20 10:45 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
@ 2012-07-24 14:15 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-07-24 14:15 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: 80d1fa6463d934969b7aebf04107fc133463f0f6
Gitweb: http://git.kernel.org/tip/80d1fa6463d934969b7aebf04107fc133463f0f6
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:46:41 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 24 Jul 2012 13:53:18 +0200
cpusets, hotplug: Implement cpuset tree traversal in a helper function
At present, the functions that deal with cpusets during CPU/Mem hotplug
are quite messy, since a lot of the functionality is mixed up without clear
separation. And this takes a toll on optimization as well. For example,
the function cpuset_update_active_cpus() is called on both CPU offline and CPU
online events; and it invokes scan_for_empty_cpusets(), which makes sense
only for CPU offline events. And hence, the current code ends up unnecessarily
traversing the cpuset tree during CPU online also.
As a first step towards cleaning up those functions, encapsulate the cpuset
tree traversal in a helper function, so as to facilitate upcoming changes.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141635.3692.893.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/cpuset.c | 36 +++++++++++++++++++++++++++---------
1 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 746d1ee..ba96349 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1990,6 +1990,32 @@ static void remove_tasks_in_empty_cpuset(struct cpuset *cs)
}
/*
+ * Helper function to traverse cpusets.
+ * It can be used to walk the cpuset tree from top to bottom, completing
+ * one layer before dropping down to the next (thus always processing a
+ * node before any of its children).
+ */
+static struct cpuset *cpuset_next(struct list_head *queue)
+{
+ struct cpuset *cp;
+ struct cpuset *child; /* scans child cpusets of cp */
+ struct cgroup *cont;
+
+ if (list_empty(queue))
+ return NULL;
+
+ cp = list_first_entry(queue, struct cpuset, stack_list);
+ list_del(queue->next);
+ list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
+ child = cgroup_cs(cont);
+ list_add_tail(&child->stack_list, queue);
+ }
+
+ return cp;
+}
+
+
+/*
* Walk the specified cpuset subtree and look for empty cpusets.
* The tasks of such cpuset must be moved to a parent cpuset.
*
@@ -2008,19 +2034,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
{
LIST_HEAD(queue);
struct cpuset *cp; /* scans cpusets being updated */
- struct cpuset *child; /* scans child cpusets of cp */
- struct cgroup *cont;
static nodemask_t oldmems; /* protected by cgroup_mutex */
list_add_tail((struct list_head *)&root->stack_list, &queue);
- while (!list_empty(&queue)) {
- cp = list_first_entry(&queue, struct cpuset, stack_list);
- list_del(queue.next);
- list_for_each_entry(cont, &cp->css.cgroup->children, sibling) {
- child = cgroup_cs(cont);
- list_add_tail(&child->stack_list, &queue);
- }
+ while ((cp = cpuset_next(&queue)) != NULL) {
/* Continue past cpusets with all cpus, mems online */
if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:sched/core] cpusets, hotplug: Restructure functions that are invoked during hotplug
2012-05-24 14:16 ` [PATCH v6 3/4] cpusets, hotplug: Restructure functions that are invoked during hotplug Srivatsa S. Bhat
2012-06-20 10:46 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
@ 2012-07-24 14:16 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-07-24 14:16 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: 7ddf96b02fe8dd441f452deef879040def5f7b34
Gitweb: http://git.kernel.org/tip/7ddf96b02fe8dd441f452deef879040def5f7b34
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:46:55 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 24 Jul 2012 13:53:22 +0200
cpusets, hotplug: Restructure functions that are invoked during hotplug
Separate out the cpuset related handling for CPU/Memory online/offline.
This also helps us exploit the most obvious and basic level of optimization
that any notification mechanism (CPU/Mem online/offline) has to offer us:
"We *know* why we have been invoked. So stop pretending that we are lost,
and do only the necessary amount of processing!".
And while at it, rename scan_for_empty_cpusets() to
scan_cpusets_upon_hotplug(), which is more appropriate considering how
it is restructured.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141650.3692.48637.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
include/linux/cpuset.h | 4 +-
kernel/cpuset.c | 88 +++++++++++++++++++++++++++++++++---------------
kernel/sched/core.c | 4 +-
3 files changed, 65 insertions(+), 31 deletions(-)
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 668f66b..838320f 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -20,7 +20,7 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */
extern int cpuset_init(void);
extern void cpuset_init_smp(void);
-extern void cpuset_update_active_cpus(void);
+extern void cpuset_update_active_cpus(bool cpu_online);
extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
@@ -124,7 +124,7 @@ static inline void set_mems_allowed(nodemask_t nodemask)
static inline int cpuset_init(void) { return 0; }
static inline void cpuset_init_smp(void) {}
-static inline void cpuset_update_active_cpus(void)
+static inline void cpuset_update_active_cpus(bool cpu_online)
{
partition_sched_domains(1, NULL, NULL);
}
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ba96349..ba0a4d7 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -147,6 +147,12 @@ typedef enum {
CS_SPREAD_SLAB,
} cpuset_flagbits_t;
+/* the type of hotplug event */
+enum hotplug_event {
+ CPUSET_CPU_OFFLINE,
+ CPUSET_MEM_OFFLINE,
+};
+
/* convenient tests for these bits */
static inline int is_cpu_exclusive(const struct cpuset *cs)
{
@@ -2016,8 +2022,10 @@ static struct cpuset *cpuset_next(struct list_head *queue)
/*
- * Walk the specified cpuset subtree and look for empty cpusets.
- * The tasks of such cpuset must be moved to a parent cpuset.
+ * Walk the specified cpuset subtree upon a hotplug operation (CPU/Memory
+ * online/offline) and update the cpusets accordingly.
+ * For regular CPU/Mem hotplug, look for empty cpusets; the tasks of such
+ * cpuset must be moved to a parent cpuset.
*
* Called with cgroup_mutex held. We take callback_mutex to modify
* cpus_allowed and mems_allowed.
@@ -2030,38 +2038,58 @@ static struct cpuset *cpuset_next(struct list_head *queue)
* that has tasks along with an empty 'mems'. But if we did see such
* a cpuset, we'd handle it just like we do if its 'cpus' was empty.
*/
-static void scan_for_empty_cpusets(struct cpuset *root)
+static void
+scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
{
LIST_HEAD(queue);
- struct cpuset *cp; /* scans cpusets being updated */
+ struct cpuset *cp; /* scans cpusets being updated */
static nodemask_t oldmems; /* protected by cgroup_mutex */
list_add_tail((struct list_head *)&root->stack_list, &queue);
- while ((cp = cpuset_next(&queue)) != NULL) {
+ switch (event) {
+ case CPUSET_CPU_OFFLINE:
+ while ((cp = cpuset_next(&queue)) != NULL) {
+
+ /* Continue past cpusets with all cpus online */
+ if (cpumask_subset(cp->cpus_allowed, cpu_active_mask))
+ continue;
+
+ /* Remove offline cpus from this cpuset. */
+ mutex_lock(&callback_mutex);
+ cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
+ cpu_active_mask);
+ mutex_unlock(&callback_mutex);
+
+ /* Move tasks from the empty cpuset to a parent */
+ if (cpumask_empty(cp->cpus_allowed))
+ remove_tasks_in_empty_cpuset(cp);
+ else
+ update_tasks_cpumask(cp, NULL);
+ }
+ break;
- /* Continue past cpusets with all cpus, mems online */
- if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) &&
- nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
- continue;
+ case CPUSET_MEM_OFFLINE:
+ while ((cp = cpuset_next(&queue)) != NULL) {
- oldmems = cp->mems_allowed;
+ /* Continue past cpusets with all mems online */
+ if (nodes_subset(cp->mems_allowed,
+ node_states[N_HIGH_MEMORY]))
+ continue;
- /* Remove offline cpus and mems from this cpuset. */
- mutex_lock(&callback_mutex);
- cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
- cpu_active_mask);
- nodes_and(cp->mems_allowed, cp->mems_allowed,
+ oldmems = cp->mems_allowed;
+
+ /* Remove offline mems from this cpuset. */
+ mutex_lock(&callback_mutex);
+ nodes_and(cp->mems_allowed, cp->mems_allowed,
node_states[N_HIGH_MEMORY]);
- mutex_unlock(&callback_mutex);
+ mutex_unlock(&callback_mutex);
- /* Move tasks from the empty cpuset to a parent */
- if (cpumask_empty(cp->cpus_allowed) ||
- nodes_empty(cp->mems_allowed))
- remove_tasks_in_empty_cpuset(cp);
- else {
- update_tasks_cpumask(cp, NULL);
- update_tasks_nodemask(cp, &oldmems, NULL);
+ /* Move tasks from the empty cpuset to a parent */
+ if (nodes_empty(cp->mems_allowed))
+ remove_tasks_in_empty_cpuset(cp);
+ else
+ update_tasks_nodemask(cp, &oldmems, NULL);
}
}
}
@@ -2080,8 +2108,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
*
* Called within get_online_cpus(). Needs to call cgroup_lock()
* before calling generate_sched_domains().
+ *
+ * @cpu_online: Indicates whether this is a CPU online event (true) or
+ * a CPU offline event (false).
*/
-void cpuset_update_active_cpus(void)
+void cpuset_update_active_cpus(bool cpu_online)
{
struct sched_domain_attr *attr;
cpumask_var_t *doms;
@@ -2091,7 +2122,10 @@ void cpuset_update_active_cpus(void)
mutex_lock(&callback_mutex);
cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
mutex_unlock(&callback_mutex);
- scan_for_empty_cpusets(&top_cpuset);
+
+ if (!cpu_online)
+ scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_CPU_OFFLINE);
+
ndoms = generate_sched_domains(&doms, &attr);
cgroup_unlock();
@@ -2122,9 +2156,9 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
case MEM_OFFLINE:
/*
* needn't update top_cpuset.mems_allowed explicitly because
- * scan_for_empty_cpusets() will update it.
+ * scan_cpusets_upon_hotplug() will update it.
*/
- scan_for_empty_cpusets(&top_cpuset);
+ scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_MEM_OFFLINE);
break;
default:
break;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 4c1d80c..4b4a63d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7134,7 +7134,7 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
case CPU_ONLINE:
case CPU_DOWN_FAILED:
- cpuset_update_active_cpus();
+ cpuset_update_active_cpus(true);
break;
default:
return NOTIFY_DONE;
@@ -7147,7 +7147,7 @@ static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
{
switch (action) {
case CPU_DOWN_PREPARE:
- cpuset_update_active_cpus();
+ cpuset_update_active_cpus(false);
break;
case CPU_DOWN_PREPARE_FROZEN:
num_cpus_frozen++;
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [tip:sched/core] cpusets: Remove/update outdated comments
2012-05-24 14:17 ` [PATCH v6 4/4] cpusets: Remove/update outdated comments Srivatsa S. Bhat
2012-06-20 10:47 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
@ 2012-07-24 14:17 ` tip-bot for Srivatsa S. Bhat
1 sibling, 0 replies; 21+ messages in thread
From: tip-bot for Srivatsa S. Bhat @ 2012-07-24 14:17 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, torvalds, a.p.zijlstra, srivatsa.bhat,
akpm, tglx
Commit-ID: a1cd2b13f754b2c56fb87b8c4912c015f8f57c0c
Gitweb: http://git.kernel.org/tip/a1cd2b13f754b2c56fb87b8c4912c015f8f57c0c
Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
AuthorDate: Thu, 24 May 2012 19:47:03 +0530
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 24 Jul 2012 13:53:28 +0200
cpusets: Remove/update outdated comments
cpuset_track_online_cpus() is no longer present. So remove the
outdated comment and replace it with reference to cpuset_update_active_cpus()
which is its equivalent.
Also, we don't lack memory hot-unplug anymore. And David Rientjes pointed
out how it is dealt with. So update that comment as well.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20120524141700.3692.98192.stgit@srivatsabhat.in.ibm.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
kernel/cpuset.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ba0a4d7..f33c715 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2034,9 +2034,8 @@ static struct cpuset *cpuset_next(struct list_head *queue)
* before dropping down to the next. It always processes a node before
* any of its children.
*
- * For now, since we lack memory hot unplug, we'll never see a cpuset
- * that has tasks along with an empty 'mems'. But if we did see such
- * a cpuset, we'd handle it just like we do if its 'cpus' was empty.
+ * In the case of memory hot-unplug, it will remove nodes from N_HIGH_MEMORY
+ * if all present pages from a node are offlined.
*/
static void
scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
@@ -2137,7 +2136,7 @@ void cpuset_update_active_cpus(bool cpu_online)
/*
* Keep top_cpuset.mems_allowed tracking node_states[N_HIGH_MEMORY].
* Call this routine anytime after node_states[N_HIGH_MEMORY] changes.
- * See also the previous routine cpuset_track_online_cpus().
+ * See cpuset_update_active_cpus() for CPU hotplug handling.
*/
static int cpuset_track_online_nodes(struct notifier_block *self,
unsigned long action, void *arg)
^ permalink raw reply related [flat|nested] 21+ messages in thread
end of thread, other threads:[~2012-07-24 14:17 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-24 14:16 [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 1/4] CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume Srivatsa S. Bhat
2012-06-20 10:44 ` [tip:sched/core] CPU hotplug, cpusets, suspend: Don' t " tip-bot for Srivatsa S. Bhat
2012-07-24 14:14 ` tip-bot for Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 2/4] cpusets, hotplug: Implement cpuset tree traversal in a helper function Srivatsa S. Bhat
2012-06-20 10:45 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
2012-07-24 14:15 ` tip-bot for Srivatsa S. Bhat
2012-05-24 14:16 ` [PATCH v6 3/4] cpusets, hotplug: Restructure functions that are invoked during hotplug Srivatsa S. Bhat
2012-06-20 10:46 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
2012-07-24 14:16 ` tip-bot for Srivatsa S. Bhat
2012-05-24 14:17 ` [PATCH v6 4/4] cpusets: Remove/update outdated comments Srivatsa S. Bhat
2012-06-20 10:47 ` [tip:sched/core] " tip-bot for Srivatsa S. Bhat
2012-07-24 14:17 ` tip-bot for Srivatsa S. Bhat
2012-05-25 9:38 ` [PATCH v6 0/4] CPU hotplug, cpusets, suspend/resume: Fixes, cleanups and optimizations Peter Zijlstra
2012-05-25 11:22 ` Srivatsa S. Bhat
2012-06-20 9:36 ` Srivatsa S. Bhat
2012-06-20 11:39 ` Ingo Molnar
2012-06-20 14:17 ` Srivatsa S. Bhat
2012-06-20 14:26 ` Srivatsa S. Bhat
2012-06-20 14:47 ` Ingo Molnar
2012-06-20 16:06 ` Srivatsa S. Bhat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).