@@ -590,6 +590,35 @@ static inline void free_cpuset(struct cpuset *cs)
590
590
kfree (cs );
591
591
}
592
592
593
+ /*
594
+ * validate_change_legacy() - Validate conditions specific to legacy (v1)
595
+ * behavior.
596
+ */
597
+ static int validate_change_legacy (struct cpuset * cur , struct cpuset * trial )
598
+ {
599
+ struct cgroup_subsys_state * css ;
600
+ struct cpuset * c , * par ;
601
+ int ret ;
602
+
603
+ WARN_ON_ONCE (!rcu_read_lock_held ());
604
+
605
+ /* Each of our child cpusets must be a subset of us */
606
+ ret = - EBUSY ;
607
+ cpuset_for_each_child (c , css , cur )
608
+ if (!is_cpuset_subset (c , trial ))
609
+ goto out ;
610
+
611
+ /* On legacy hierarchy, we must be a subset of our parent cpuset. */
612
+ ret = - EACCES ;
613
+ par = parent_cs (cur );
614
+ if (par && !is_cpuset_subset (trial , par ))
615
+ goto out ;
616
+
617
+ ret = 0 ;
618
+ out :
619
+ return ret ;
620
+ }
621
+
593
622
/*
594
623
* validate_change() - Used to validate that any proposed cpuset change
595
624
* follows the structural rules for cpusets.
@@ -614,20 +643,21 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
614
643
{
615
644
struct cgroup_subsys_state * css ;
616
645
struct cpuset * c , * par ;
617
- int ret ;
618
-
619
- /* The checks don't apply to root cpuset */
620
- if (cur == & top_cpuset )
621
- return 0 ;
646
+ int ret = 0 ;
622
647
623
648
rcu_read_lock ();
624
- par = parent_cs (cur );
625
649
626
- /* On legacy hierarchy, we must be a subset of our parent cpuset. */
627
- ret = - EACCES ;
628
- if (!is_in_v2_mode () && !is_cpuset_subset (trial , par ))
650
+ if (!is_in_v2_mode ())
651
+ ret = validate_change_legacy (cur , trial );
652
+ if (ret )
653
+ goto out ;
654
+
655
+ /* Remaining checks don't apply to root cpuset */
656
+ if (cur == & top_cpuset )
629
657
goto out ;
630
658
659
+ par = parent_cs (cur );
660
+
631
661
/*
632
662
* If either I or some sibling (!= me) is exclusive, we can't
633
663
* overlap
@@ -1175,9 +1205,7 @@ enum subparts_cmd {
1175
1205
*
1176
1206
* Because of the implicit cpu exclusive nature of a partition root,
1177
1207
* cpumask changes that violates the cpu exclusivity rule will not be
1178
- * permitted when checked by validate_change(). The validate_change()
1179
- * function will also prevent any changes to the cpu list if it is not
1180
- * a superset of children's cpu lists.
1208
+ * permitted when checked by validate_change().
1181
1209
*/
1182
1210
static int update_parent_subparts_cpumask (struct cpuset * cpuset , int cmd ,
1183
1211
struct cpumask * newmask ,
@@ -1522,19 +1550,29 @@ static void update_sibling_cpumasks(struct cpuset *parent, struct cpuset *cs,
1522
1550
struct cpuset * sibling ;
1523
1551
struct cgroup_subsys_state * pos_css ;
1524
1552
1553
+ percpu_rwsem_assert_held (& cpuset_rwsem );
1554
+
1525
1555
/*
1526
1556
* Check all its siblings and call update_cpumasks_hier()
1527
1557
* if their use_parent_ecpus flag is set in order for them
1528
1558
* to use the right effective_cpus value.
1559
+ *
1560
+ * The update_cpumasks_hier() function may sleep. So we have to
1561
+ * release the RCU read lock before calling it.
1529
1562
*/
1530
1563
rcu_read_lock ();
1531
1564
cpuset_for_each_child (sibling , pos_css , parent ) {
1532
1565
if (sibling == cs )
1533
1566
continue ;
1534
1567
if (!sibling -> use_parent_ecpus )
1535
1568
continue ;
1569
+ if (!css_tryget_online (& sibling -> css ))
1570
+ continue ;
1536
1571
1572
+ rcu_read_unlock ();
1537
1573
update_cpumasks_hier (sibling , tmp );
1574
+ rcu_read_lock ();
1575
+ css_put (& sibling -> css );
1538
1576
}
1539
1577
rcu_read_unlock ();
1540
1578
}
@@ -1607,8 +1645,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
1607
1645
* Make sure that subparts_cpus is a subset of cpus_allowed.
1608
1646
*/
1609
1647
if (cs -> nr_subparts_cpus ) {
1610
- cpumask_andnot (cs -> subparts_cpus , cs -> subparts_cpus ,
1611
- cs -> cpus_allowed );
1648
+ cpumask_and (cs -> subparts_cpus , cs -> subparts_cpus , cs -> cpus_allowed );
1612
1649
cs -> nr_subparts_cpus = cpumask_weight (cs -> subparts_cpus );
1613
1650
}
1614
1651
spin_unlock_irq (& callback_lock );
0 commit comments