aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpuset.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-01-07 11:51:07 -0500
committerTejun Heo <tj@kernel.org>2013-01-07 11:51:07 -0500
commit452477fa68c6d8ef80adebd05194c1c157ad9a53 (patch)
tree28682f4307a4e4bc2180d18ccb71a262700699df /kernel/cpuset.c
parent8d03394877ecdf87e1d694664c460747b8e05aa1 (diff)
cpuset: pin down cpus and mems while a task is being attached
cpuset is scheduled to be decoupled from cgroup_lock which will make configuration updates race with task migration. Any config update will be allowed to happen between ->can_attach() and ->attach(). If such config update removes either all cpus or mems, by the time ->attach() is called, the condition verified by ->can_attach(), that the cpuset is capable of hosting the tasks, is no longer true. This patch adds cpuset->attach_in_progress which is incremented from ->can_attach() and decremented when the attach operation finishes either successfully or not. validate_change() treats cpusets w/ non-zero ->attach_in_progress like cpusets w/ tasks and refuses to remove all cpus or mems from it. This currently doesn't make any functional difference as everything is protected by cgroup_mutex but enables decoupling the locking. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r--kernel/cpuset.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index a7bb547786d7..4334576f5d6a 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -91,6 +91,12 @@ struct cpuset {
91 91
92 struct fmeter fmeter; /* memory_pressure filter */ 92 struct fmeter fmeter; /* memory_pressure filter */
93 93
94 /*
95 * Tasks are being attached to this cpuset. Used to prevent
96 * zeroing cpus/mems_allowed between ->can_attach() and ->attach().
97 */
98 int attach_in_progress;
99
94 /* partition number for rebuild_sched_domains() */ 100 /* partition number for rebuild_sched_domains() */
95 int pn; 101 int pn;
96 102
@@ -468,9 +474,12 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
468 goto out; 474 goto out;
469 } 475 }
470 476
471 /* Cpusets with tasks can't have empty cpus_allowed or mems_allowed */ 477 /*
478 * Cpusets with tasks - existing or newly being attached - can't
479 * have empty cpus_allowed or mems_allowed.
480 */
472 ret = -ENOSPC; 481 ret = -ENOSPC;
473 if (cgroup_task_count(cur->css.cgroup) && 482 if ((cgroup_task_count(cur->css.cgroup) || cur->attach_in_progress) &&
474 (cpumask_empty(trial->cpus_allowed) || 483 (cpumask_empty(trial->cpus_allowed) ||
475 nodes_empty(trial->mems_allowed))) 484 nodes_empty(trial->mems_allowed)))
476 goto out; 485 goto out;
@@ -1386,9 +1395,21 @@ static int cpuset_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
1386 return ret; 1395 return ret;
1387 } 1396 }
1388 1397
1398 /*
1399 * Mark attach is in progress. This makes validate_change() fail
1400 * changes which zero cpus/mems_allowed.
1401 */
1402 cs->attach_in_progress++;
1403
1389 return 0; 1404 return 0;
1390} 1405}
1391 1406
1407static void cpuset_cancel_attach(struct cgroup *cgrp,
1408 struct cgroup_taskset *tset)
1409{
1410 cgroup_cs(cgrp)->attach_in_progress--;
1411}
1412
1392/* 1413/*
1393 * Protected by cgroup_mutex. cpus_attach is used only by cpuset_attach() 1414 * Protected by cgroup_mutex. cpus_attach is used only by cpuset_attach()
1394 * but we can't allocate it dynamically there. Define it global and 1415 * but we can't allocate it dynamically there. Define it global and
@@ -1441,6 +1462,8 @@ static void cpuset_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
1441 &cpuset_attach_nodemask_to); 1462 &cpuset_attach_nodemask_to);
1442 mmput(mm); 1463 mmput(mm);
1443 } 1464 }
1465
1466 cs->attach_in_progress--;
1444} 1467}
1445 1468
1446/* The various types of files and directories in a cpuset file system */ 1469/* The various types of files and directories in a cpuset file system */
@@ -1908,6 +1931,7 @@ struct cgroup_subsys cpuset_subsys = {
1908 .css_offline = cpuset_css_offline, 1931 .css_offline = cpuset_css_offline,
1909 .css_free = cpuset_css_free, 1932 .css_free = cpuset_css_free,
1910 .can_attach = cpuset_can_attach, 1933 .can_attach = cpuset_can_attach,
1934 .cancel_attach = cpuset_cancel_attach,
1911 .attach = cpuset_attach, 1935 .attach = cpuset_attach,
1912 .subsys_id = cpuset_subsys_id, 1936 .subsys_id = cpuset_subsys_id,
1913 .base_cftypes = files, 1937 .base_cftypes = files,