diff options
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r-- | kernel/cpuset.c | 93 |
1 files changed, 62 insertions, 31 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 7e75a41bd508..3cf2183b472d 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -537,8 +537,7 @@ update_domain_attr_tree(struct sched_domain_attr *dattr, struct cpuset *c) | |||
537 | * element of the partition (one sched domain) to be passed to | 537 | * element of the partition (one sched domain) to be passed to |
538 | * partition_sched_domains(). | 538 | * partition_sched_domains(). |
539 | */ | 539 | */ |
540 | /* FIXME: see the FIXME in partition_sched_domains() */ | 540 | static int generate_sched_domains(cpumask_var_t **domains, |
541 | static int generate_sched_domains(struct cpumask **domains, | ||
542 | struct sched_domain_attr **attributes) | 541 | struct sched_domain_attr **attributes) |
543 | { | 542 | { |
544 | LIST_HEAD(q); /* queue of cpusets to be scanned */ | 543 | LIST_HEAD(q); /* queue of cpusets to be scanned */ |
@@ -546,7 +545,7 @@ static int generate_sched_domains(struct cpumask **domains, | |||
546 | struct cpuset **csa; /* array of all cpuset ptrs */ | 545 | struct cpuset **csa; /* array of all cpuset ptrs */ |
547 | int csn; /* how many cpuset ptrs in csa so far */ | 546 | int csn; /* how many cpuset ptrs in csa so far */ |
548 | int i, j, k; /* indices for partition finding loops */ | 547 | int i, j, k; /* indices for partition finding loops */ |
549 | struct cpumask *doms; /* resulting partition; i.e. sched domains */ | 548 | cpumask_var_t *doms; /* resulting partition; i.e. sched domains */ |
550 | struct sched_domain_attr *dattr; /* attributes for custom domains */ | 549 | struct sched_domain_attr *dattr; /* attributes for custom domains */ |
551 | int ndoms = 0; /* number of sched domains in result */ | 550 | int ndoms = 0; /* number of sched domains in result */ |
552 | int nslot; /* next empty doms[] struct cpumask slot */ | 551 | int nslot; /* next empty doms[] struct cpumask slot */ |
@@ -557,7 +556,8 @@ static int generate_sched_domains(struct cpumask **domains, | |||
557 | 556 | ||
558 | /* Special case for the 99% of systems with one, full, sched domain */ | 557 | /* Special case for the 99% of systems with one, full, sched domain */ |
559 | if (is_sched_load_balance(&top_cpuset)) { | 558 | if (is_sched_load_balance(&top_cpuset)) { |
560 | doms = kmalloc(cpumask_size(), GFP_KERNEL); | 559 | ndoms = 1; |
560 | doms = alloc_sched_domains(ndoms); | ||
561 | if (!doms) | 561 | if (!doms) |
562 | goto done; | 562 | goto done; |
563 | 563 | ||
@@ -566,9 +566,8 @@ static int generate_sched_domains(struct cpumask **domains, | |||
566 | *dattr = SD_ATTR_INIT; | 566 | *dattr = SD_ATTR_INIT; |
567 | update_domain_attr_tree(dattr, &top_cpuset); | 567 | update_domain_attr_tree(dattr, &top_cpuset); |
568 | } | 568 | } |
569 | cpumask_copy(doms, top_cpuset.cpus_allowed); | 569 | cpumask_copy(doms[0], top_cpuset.cpus_allowed); |
570 | 570 | ||
571 | ndoms = 1; | ||
572 | goto done; | 571 | goto done; |
573 | } | 572 | } |
574 | 573 | ||
@@ -636,7 +635,7 @@ restart: | |||
636 | * Now we know how many domains to create. | 635 | * Now we know how many domains to create. |
637 | * Convert <csn, csa> to <ndoms, doms> and populate cpu masks. | 636 | * Convert <csn, csa> to <ndoms, doms> and populate cpu masks. |
638 | */ | 637 | */ |
639 | doms = kmalloc(ndoms * cpumask_size(), GFP_KERNEL); | 638 | doms = alloc_sched_domains(ndoms); |
640 | if (!doms) | 639 | if (!doms) |
641 | goto done; | 640 | goto done; |
642 | 641 | ||
@@ -656,7 +655,7 @@ restart: | |||
656 | continue; | 655 | continue; |
657 | } | 656 | } |
658 | 657 | ||
659 | dp = doms + nslot; | 658 | dp = doms[nslot]; |
660 | 659 | ||
661 | if (nslot == ndoms) { | 660 | if (nslot == ndoms) { |
662 | static int warnings = 10; | 661 | static int warnings = 10; |
@@ -718,7 +717,7 @@ done: | |||
718 | static void do_rebuild_sched_domains(struct work_struct *unused) | 717 | static void do_rebuild_sched_domains(struct work_struct *unused) |
719 | { | 718 | { |
720 | struct sched_domain_attr *attr; | 719 | struct sched_domain_attr *attr; |
721 | struct cpumask *doms; | 720 | cpumask_var_t *doms; |
722 | int ndoms; | 721 | int ndoms; |
723 | 722 | ||
724 | get_online_cpus(); | 723 | get_online_cpus(); |
@@ -1324,9 +1323,10 @@ static int fmeter_getrate(struct fmeter *fmp) | |||
1324 | static cpumask_var_t cpus_attach; | 1323 | static cpumask_var_t cpus_attach; |
1325 | 1324 | ||
1326 | /* Called by cgroups to determine if a cpuset is usable; cgroup_mutex held */ | 1325 | /* Called by cgroups to determine if a cpuset is usable; cgroup_mutex held */ |
1327 | static int cpuset_can_attach(struct cgroup_subsys *ss, | 1326 | static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont, |
1328 | struct cgroup *cont, struct task_struct *tsk) | 1327 | struct task_struct *tsk, bool threadgroup) |
1329 | { | 1328 | { |
1329 | int ret; | ||
1330 | struct cpuset *cs = cgroup_cs(cont); | 1330 | struct cpuset *cs = cgroup_cs(cont); |
1331 | 1331 | ||
1332 | if (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) | 1332 | if (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)) |
@@ -1343,18 +1343,51 @@ static int cpuset_can_attach(struct cgroup_subsys *ss, | |||
1343 | if (tsk->flags & PF_THREAD_BOUND) | 1343 | if (tsk->flags & PF_THREAD_BOUND) |
1344 | return -EINVAL; | 1344 | return -EINVAL; |
1345 | 1345 | ||
1346 | return security_task_setscheduler(tsk, 0, NULL); | 1346 | ret = security_task_setscheduler(tsk, 0, NULL); |
1347 | if (ret) | ||
1348 | return ret; | ||
1349 | if (threadgroup) { | ||
1350 | struct task_struct *c; | ||
1351 | |||
1352 | rcu_read_lock(); | ||
1353 | list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) { | ||
1354 | ret = security_task_setscheduler(c, 0, NULL); | ||
1355 | if (ret) { | ||
1356 | rcu_read_unlock(); | ||
1357 | return ret; | ||
1358 | } | ||
1359 | } | ||
1360 | rcu_read_unlock(); | ||
1361 | } | ||
1362 | return 0; | ||
1347 | } | 1363 | } |
1348 | 1364 | ||
1349 | static void cpuset_attach(struct cgroup_subsys *ss, | 1365 | static void cpuset_attach_task(struct task_struct *tsk, nodemask_t *to, |
1350 | struct cgroup *cont, struct cgroup *oldcont, | 1366 | struct cpuset *cs) |
1351 | struct task_struct *tsk) | 1367 | { |
1368 | int err; | ||
1369 | /* | ||
1370 | * can_attach beforehand should guarantee that this doesn't fail. | ||
1371 | * TODO: have a better way to handle failure here | ||
1372 | */ | ||
1373 | err = set_cpus_allowed_ptr(tsk, cpus_attach); | ||
1374 | WARN_ON_ONCE(err); | ||
1375 | |||
1376 | task_lock(tsk); | ||
1377 | cpuset_change_task_nodemask(tsk, to); | ||
1378 | task_unlock(tsk); | ||
1379 | cpuset_update_task_spread_flag(cs, tsk); | ||
1380 | |||
1381 | } | ||
1382 | |||
1383 | static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont, | ||
1384 | struct cgroup *oldcont, struct task_struct *tsk, | ||
1385 | bool threadgroup) | ||
1352 | { | 1386 | { |
1353 | nodemask_t from, to; | 1387 | nodemask_t from, to; |
1354 | struct mm_struct *mm; | 1388 | struct mm_struct *mm; |
1355 | struct cpuset *cs = cgroup_cs(cont); | 1389 | struct cpuset *cs = cgroup_cs(cont); |
1356 | struct cpuset *oldcs = cgroup_cs(oldcont); | 1390 | struct cpuset *oldcs = cgroup_cs(oldcont); |
1357 | int err; | ||
1358 | 1391 | ||
1359 | if (cs == &top_cpuset) { | 1392 | if (cs == &top_cpuset) { |
1360 | cpumask_copy(cpus_attach, cpu_possible_mask); | 1393 | cpumask_copy(cpus_attach, cpu_possible_mask); |
@@ -1363,15 +1396,19 @@ static void cpuset_attach(struct cgroup_subsys *ss, | |||
1363 | guarantee_online_cpus(cs, cpus_attach); | 1396 | guarantee_online_cpus(cs, cpus_attach); |
1364 | guarantee_online_mems(cs, &to); | 1397 | guarantee_online_mems(cs, &to); |
1365 | } | 1398 | } |
1366 | err = set_cpus_allowed_ptr(tsk, cpus_attach); | ||
1367 | if (err) | ||
1368 | return; | ||
1369 | 1399 | ||
1370 | task_lock(tsk); | 1400 | /* do per-task migration stuff possibly for each in the threadgroup */ |
1371 | cpuset_change_task_nodemask(tsk, &to); | 1401 | cpuset_attach_task(tsk, &to, cs); |
1372 | task_unlock(tsk); | 1402 | if (threadgroup) { |
1373 | cpuset_update_task_spread_flag(cs, tsk); | 1403 | struct task_struct *c; |
1404 | rcu_read_lock(); | ||
1405 | list_for_each_entry_rcu(c, &tsk->thread_group, thread_group) { | ||
1406 | cpuset_attach_task(c, &to, cs); | ||
1407 | } | ||
1408 | rcu_read_unlock(); | ||
1409 | } | ||
1374 | 1410 | ||
1411 | /* change mm; only needs to be done once even if threadgroup */ | ||
1375 | from = oldcs->mems_allowed; | 1412 | from = oldcs->mems_allowed; |
1376 | to = cs->mems_allowed; | 1413 | to = cs->mems_allowed; |
1377 | mm = get_task_mm(tsk); | 1414 | mm = get_task_mm(tsk); |
@@ -2014,7 +2051,7 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, | |||
2014 | unsigned long phase, void *unused_cpu) | 2051 | unsigned long phase, void *unused_cpu) |
2015 | { | 2052 | { |
2016 | struct sched_domain_attr *attr; | 2053 | struct sched_domain_attr *attr; |
2017 | struct cpumask *doms; | 2054 | cpumask_var_t *doms; |
2018 | int ndoms; | 2055 | int ndoms; |
2019 | 2056 | ||
2020 | switch (phase) { | 2057 | switch (phase) { |
@@ -2499,15 +2536,9 @@ const struct file_operations proc_cpuset_operations = { | |||
2499 | }; | 2536 | }; |
2500 | #endif /* CONFIG_PROC_PID_CPUSET */ | 2537 | #endif /* CONFIG_PROC_PID_CPUSET */ |
2501 | 2538 | ||
2502 | /* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */ | 2539 | /* Display task mems_allowed in /proc/<pid>/status file. */ |
2503 | void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task) | 2540 | void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task) |
2504 | { | 2541 | { |
2505 | seq_printf(m, "Cpus_allowed:\t"); | ||
2506 | seq_cpumask(m, &task->cpus_allowed); | ||
2507 | seq_printf(m, "\n"); | ||
2508 | seq_printf(m, "Cpus_allowed_list:\t"); | ||
2509 | seq_cpumask_list(m, &task->cpus_allowed); | ||
2510 | seq_printf(m, "\n"); | ||
2511 | seq_printf(m, "Mems_allowed:\t"); | 2542 | seq_printf(m, "Mems_allowed:\t"); |
2512 | seq_nodemask(m, &task->mems_allowed); | 2543 | seq_nodemask(m, &task->mems_allowed); |
2513 | seq_printf(m, "\n"); | 2544 | seq_printf(m, "\n"); |