Commit ae8086ce15fdab2b57599d7a3242a114ba4b8597
1 parent
efeb77b2f1
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
cpuset: introduce cpuset_for_each_child()
Instead of iterating cgroup->children directly, introduce and use cpuset_for_each_child() which wraps cgroup_for_each_child() and performs online check. As it uses the generic iterator, it requires RCU read locking too. As cpuset is currently protected by cgroup_mutex, non-online cpusets aren't visible to all the iterations and this patch currently doesn't make any functional difference. This will be used to de-couple cpuset locking from cgroup core. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Showing 1 changed file with 54 additions and 31 deletions Side-by-side Diff
kernel/cpuset.c
... | ... | @@ -200,6 +200,19 @@ |
200 | 200 | (1 << CS_MEM_EXCLUSIVE)), |
201 | 201 | }; |
202 | 202 | |
203 | +/** | |
204 | + * cpuset_for_each_child - traverse online children of a cpuset | |
205 | + * @child_cs: loop cursor pointing to the current child | |
206 | + * @pos_cgrp: used for iteration | |
207 | + * @parent_cs: target cpuset to walk children of | |
208 | + * | |
209 | + * Walk @child_cs through the online children of @parent_cs. Must be used | |
210 | + * with RCU read locked. | |
211 | + */ | |
212 | +#define cpuset_for_each_child(child_cs, pos_cgrp, parent_cs) \ | |
213 | + cgroup_for_each_child((pos_cgrp), (parent_cs)->css.cgroup) \ | |
214 | + if (is_cpuset_online(((child_cs) = cgroup_cs((pos_cgrp))))) | |
215 | + | |
203 | 216 | /* |
204 | 217 | * There are two global mutexes guarding cpuset structures. The first |
205 | 218 | * is the main control groups cgroup_mutex, accessed via |
206 | 219 | |
207 | 220 | |
208 | 221 | |
209 | 222 | |
210 | 223 | |
211 | 224 | |
212 | 225 | |
213 | 226 | |
214 | 227 | |
215 | 228 | |
216 | 229 | |
... | ... | @@ -419,48 +432,55 @@ |
419 | 432 | { |
420 | 433 | struct cgroup *cont; |
421 | 434 | struct cpuset *c, *par; |
435 | + int ret; | |
422 | 436 | |
437 | + rcu_read_lock(); | |
438 | + | |
423 | 439 | /* Each of our child cpusets must be a subset of us */ |
424 | - list_for_each_entry(cont, &cur->css.cgroup->children, sibling) { | |
425 | - if (!is_cpuset_subset(cgroup_cs(cont), trial)) | |
426 | - return -EBUSY; | |
427 | - } | |
440 | + ret = -EBUSY; | |
441 | + cpuset_for_each_child(c, cont, cur) | |
442 | + if (!is_cpuset_subset(c, trial)) | |
443 | + goto out; | |
428 | 444 | |
429 | 445 | /* Remaining checks don't apply to root cpuset */ |
446 | + ret = 0; | |
430 | 447 | if (cur == &top_cpuset) |
431 | - return 0; | |
448 | + goto out; | |
432 | 449 | |
433 | 450 | par = cur->parent; |
434 | 451 | |
435 | 452 | /* We must be a subset of our parent cpuset */ |
453 | + ret = -EACCES; | |
436 | 454 | if (!is_cpuset_subset(trial, par)) |
437 | - return -EACCES; | |
455 | + goto out; | |
438 | 456 | |
439 | 457 | /* |
440 | 458 | * If either I or some sibling (!= me) is exclusive, we can't |
441 | 459 | * overlap |
442 | 460 | */ |
443 | - list_for_each_entry(cont, &par->css.cgroup->children, sibling) { | |
444 | - c = cgroup_cs(cont); | |
461 | + ret = -EINVAL; | |
462 | + cpuset_for_each_child(c, cont, par) { | |
445 | 463 | if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) && |
446 | 464 | c != cur && |
447 | 465 | cpumask_intersects(trial->cpus_allowed, c->cpus_allowed)) |
448 | - return -EINVAL; | |
466 | + goto out; | |
449 | 467 | if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) && |
450 | 468 | c != cur && |
451 | 469 | nodes_intersects(trial->mems_allowed, c->mems_allowed)) |
452 | - return -EINVAL; | |
470 | + goto out; | |
453 | 471 | } |
454 | 472 | |
455 | 473 | /* Cpusets with tasks can't have empty cpus_allowed or mems_allowed */ |
456 | - if (cgroup_task_count(cur->css.cgroup)) { | |
457 | - if (cpumask_empty(trial->cpus_allowed) || | |
458 | - nodes_empty(trial->mems_allowed)) { | |
459 | - return -ENOSPC; | |
460 | - } | |
461 | - } | |
474 | + ret = -ENOSPC; | |
475 | + if (cgroup_task_count(cur->css.cgroup) && | |
476 | + (cpumask_empty(trial->cpus_allowed) || | |
477 | + nodes_empty(trial->mems_allowed))) | |
478 | + goto out; | |
462 | 479 | |
463 | - return 0; | |
480 | + ret = 0; | |
481 | +out: | |
482 | + rcu_read_unlock(); | |
483 | + return ret; | |
464 | 484 | } |
465 | 485 | |
466 | 486 | #ifdef CONFIG_SMP |
467 | 487 | |
... | ... | @@ -501,10 +521,10 @@ |
501 | 521 | if (is_sched_load_balance(cp)) |
502 | 522 | update_domain_attr(dattr, cp); |
503 | 523 | |
504 | - list_for_each_entry(cont, &cp->css.cgroup->children, sibling) { | |
505 | - child = cgroup_cs(cont); | |
524 | + rcu_read_lock(); | |
525 | + cpuset_for_each_child(child, cont, cp) | |
506 | 526 | list_add_tail(&child->stack_list, &q); |
507 | - } | |
527 | + rcu_read_unlock(); | |
508 | 528 | } |
509 | 529 | } |
510 | 530 | |
511 | 531 | |
... | ... | @@ -623,10 +643,10 @@ |
623 | 643 | continue; |
624 | 644 | } |
625 | 645 | |
626 | - list_for_each_entry(cont, &cp->css.cgroup->children, sibling) { | |
627 | - child = cgroup_cs(cont); | |
646 | + rcu_read_lock(); | |
647 | + cpuset_for_each_child(child, cont, cp) | |
628 | 648 | list_add_tail(&child->stack_list, &q); |
629 | - } | |
649 | + rcu_read_unlock(); | |
630 | 650 | } |
631 | 651 | |
632 | 652 | for (i = 0; i < csn; i++) |
... | ... | @@ -1824,7 +1844,8 @@ |
1824 | 1844 | { |
1825 | 1845 | struct cpuset *cs = cgroup_cs(cgrp); |
1826 | 1846 | struct cpuset *parent = cs->parent; |
1827 | - struct cgroup *tmp_cg; | |
1847 | + struct cpuset *tmp_cs; | |
1848 | + struct cgroup *pos_cg; | |
1828 | 1849 | |
1829 | 1850 | if (!parent) |
1830 | 1851 | return 0; |
1831 | 1852 | |
1832 | 1853 | |
... | ... | @@ -1853,12 +1874,14 @@ |
1853 | 1874 | * changed to grant parent->cpus_allowed-sibling_cpus_exclusive |
1854 | 1875 | * (and likewise for mems) to the new cgroup. |
1855 | 1876 | */ |
1856 | - list_for_each_entry(tmp_cg, &cgrp->parent->children, sibling) { | |
1857 | - struct cpuset *tmp_cs = cgroup_cs(tmp_cg); | |
1858 | - | |
1859 | - if (is_mem_exclusive(tmp_cs) || is_cpu_exclusive(tmp_cs)) | |
1877 | + rcu_read_lock(); | |
1878 | + cpuset_for_each_child(tmp_cs, pos_cg, parent) { | |
1879 | + if (is_mem_exclusive(tmp_cs) || is_cpu_exclusive(tmp_cs)) { | |
1880 | + rcu_read_unlock(); | |
1860 | 1881 | return 0; |
1882 | + } | |
1861 | 1883 | } |
1884 | + rcu_read_unlock(); | |
1862 | 1885 | |
1863 | 1886 | mutex_lock(&callback_mutex); |
1864 | 1887 | cs->mems_allowed = parent->mems_allowed; |
1865 | 1888 | |
... | ... | @@ -2027,10 +2050,10 @@ |
2027 | 2050 | |
2028 | 2051 | cp = list_first_entry(queue, struct cpuset, stack_list); |
2029 | 2052 | list_del(queue->next); |
2030 | - list_for_each_entry(cont, &cp->css.cgroup->children, sibling) { | |
2031 | - child = cgroup_cs(cont); | |
2053 | + rcu_read_lock(); | |
2054 | + cpuset_for_each_child(child, cont, cp) | |
2032 | 2055 | list_add_tail(&child->stack_list, queue); |
2033 | - } | |
2056 | + rcu_read_unlock(); | |
2034 | 2057 | |
2035 | 2058 | return cp; |
2036 | 2059 | } |