From 069385c15e3c22f03746fb1a2a48194a2ef6ab03 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sun, 23 Jul 2006 11:36:08 -0700 Subject: [PATCH] --- yaml --- r: 32799 b: refs/heads/master c: abb5a5cc6bba1516403146c5b79036fe843beb70 h: refs/heads/master i: 32797: eb64114ccaff442d0a0436e9cb86a9781ec6aaa0 32795: 0bbb6b15f5485c8ddab8a40b4dcd437992779f00 32791: b903f6da7965a24e4707b878864904896cbea1e4 32783: e24275c3568c4d4a8828527ce44f4c12c7753d98 32767: 5ae4f0356026b0363efef5eff8fdbdc7fb85add4 v: v3 --- [refs] | 2 +- trunk/kernel/cpuset.c | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 34b952179af9..1acc92614506 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: aa95387774039096c11803c04011f1aa42d85758 +refs/heads/master: abb5a5cc6bba1516403146c5b79036fe843beb70 diff --git a/trunk/kernel/cpuset.c b/trunk/kernel/cpuset.c index c232dc077438..1a649f2bb9bb 100644 --- a/trunk/kernel/cpuset.c +++ b/trunk/kernel/cpuset.c @@ -762,6 +762,8 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) * * Call with manage_mutex held. May nest a call to the * lock_cpu_hotplug()/unlock_cpu_hotplug() pair. + * Must not be called holding callback_mutex, because we must + * not call lock_cpu_hotplug() while holding callback_mutex. */ static void update_cpu_domains(struct cpuset *cur) @@ -781,7 +783,7 @@ static void update_cpu_domains(struct cpuset *cur) if (is_cpu_exclusive(c)) cpus_andnot(pspan, pspan, c->cpus_allowed); } - if (is_removed(cur) || !is_cpu_exclusive(cur)) { + if (!is_cpu_exclusive(cur)) { cpus_or(pspan, pspan, cur->cpus_allowed); if (cpus_equal(pspan, cur->cpus_allowed)) return; @@ -1917,6 +1919,17 @@ static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode) return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR); } +/* + * Locking note on the strange update_flag() call below: + * + * If the cpuset being removed is marked cpu_exclusive, then simulate + * turning cpu_exclusive off, which will call update_cpu_domains(). + * The lock_cpu_hotplug() call in update_cpu_domains() must not be + * made while holding callback_mutex. Elsewhere the kernel nests + * callback_mutex inside lock_cpu_hotplug() calls. So the reverse + * nesting would risk an ABBA deadlock. + */ + static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) { struct cpuset *cs = dentry->d_fsdata; @@ -1936,11 +1949,16 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) mutex_unlock(&manage_mutex); return -EBUSY; } + if (is_cpu_exclusive(cs)) { + int retval = update_flag(CS_CPU_EXCLUSIVE, cs, "0"); + if (retval < 0) { + mutex_unlock(&manage_mutex); + return retval; + } + } parent = cs->parent; mutex_lock(&callback_mutex); set_bit(CS_REMOVED, &cs->flags); - if (is_cpu_exclusive(cs)) - update_cpu_domains(cs); list_del(&cs->sibling); /* delete my sibling from parent->children */ spin_lock(&cs->dentry->d_lock); d = dget(cs->dentry);