diff options
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r-- | kernel/cpuset.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index c232dc077438..1a649f2bb9bb 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -762,6 +762,8 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial) | |||
762 | * | 762 | * |
763 | * Call with manage_mutex held. May nest a call to the | 763 | * Call with manage_mutex held. May nest a call to the |
764 | * lock_cpu_hotplug()/unlock_cpu_hotplug() pair. | 764 | * lock_cpu_hotplug()/unlock_cpu_hotplug() pair. |
765 | * Must not be called holding callback_mutex, because we must | ||
766 | * not call lock_cpu_hotplug() while holding callback_mutex. | ||
765 | */ | 767 | */ |
766 | 768 | ||
767 | static void update_cpu_domains(struct cpuset *cur) | 769 | static void update_cpu_domains(struct cpuset *cur) |
@@ -781,7 +783,7 @@ static void update_cpu_domains(struct cpuset *cur) | |||
781 | if (is_cpu_exclusive(c)) | 783 | if (is_cpu_exclusive(c)) |
782 | cpus_andnot(pspan, pspan, c->cpus_allowed); | 784 | cpus_andnot(pspan, pspan, c->cpus_allowed); |
783 | } | 785 | } |
784 | if (is_removed(cur) || !is_cpu_exclusive(cur)) { | 786 | if (!is_cpu_exclusive(cur)) { |
785 | cpus_or(pspan, pspan, cur->cpus_allowed); | 787 | cpus_or(pspan, pspan, cur->cpus_allowed); |
786 | if (cpus_equal(pspan, cur->cpus_allowed)) | 788 | if (cpus_equal(pspan, cur->cpus_allowed)) |
787 | return; | 789 | return; |
@@ -1917,6 +1919,17 @@ static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
1917 | return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR); | 1919 | return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR); |
1918 | } | 1920 | } |
1919 | 1921 | ||
1922 | /* | ||
1923 | * Locking note on the strange update_flag() call below: | ||
1924 | * | ||
1925 | * If the cpuset being removed is marked cpu_exclusive, then simulate | ||
1926 | * turning cpu_exclusive off, which will call update_cpu_domains(). | ||
1927 | * The lock_cpu_hotplug() call in update_cpu_domains() must not be | ||
1928 | * made while holding callback_mutex. Elsewhere the kernel nests | ||
1929 | * callback_mutex inside lock_cpu_hotplug() calls. So the reverse | ||
1930 | * nesting would risk an ABBA deadlock. | ||
1931 | */ | ||
1932 | |||
1920 | static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) | 1933 | static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) |
1921 | { | 1934 | { |
1922 | struct cpuset *cs = dentry->d_fsdata; | 1935 | struct cpuset *cs = dentry->d_fsdata; |
@@ -1936,11 +1949,16 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
1936 | mutex_unlock(&manage_mutex); | 1949 | mutex_unlock(&manage_mutex); |
1937 | return -EBUSY; | 1950 | return -EBUSY; |
1938 | } | 1951 | } |
1952 | if (is_cpu_exclusive(cs)) { | ||
1953 | int retval = update_flag(CS_CPU_EXCLUSIVE, cs, "0"); | ||
1954 | if (retval < 0) { | ||
1955 | mutex_unlock(&manage_mutex); | ||
1956 | return retval; | ||
1957 | } | ||
1958 | } | ||
1939 | parent = cs->parent; | 1959 | parent = cs->parent; |
1940 | mutex_lock(&callback_mutex); | 1960 | mutex_lock(&callback_mutex); |
1941 | set_bit(CS_REMOVED, &cs->flags); | 1961 | set_bit(CS_REMOVED, &cs->flags); |
1942 | if (is_cpu_exclusive(cs)) | ||
1943 | update_cpu_domains(cs); | ||
1944 | list_del(&cs->sibling); /* delete my sibling from parent->children */ | 1962 | list_del(&cs->sibling); /* delete my sibling from parent->children */ |
1945 | spin_lock(&cs->dentry->d_lock); | 1963 | spin_lock(&cs->dentry->d_lock); |
1946 | d = dget(cs->dentry); | 1964 | d = dget(cs->dentry); |