@@ -1256,6 +1256,7 @@ enum subparts_cmd {
1256
1256
partcmd_enable , /* Enable partition root */
1257
1257
partcmd_disable , /* Disable partition root */
1258
1258
partcmd_update , /* Update parent's subparts_cpus */
1259
+ partcmd_invalidate , /* Make partition invalid */
1259
1260
};
1260
1261
1261
1262
static int update_flag (cpuset_flagbits_t bit , struct cpuset * cs ,
@@ -1286,13 +1287,17 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
1286
1287
* or vice versa. An error code will only be returned if transitioning from
1287
1288
* invalid to valid violates the exclusivity rule.
1288
1289
*
1290
+ * For partcmd_invalidate, the current partition will be made invalid.
1291
+ *
1289
1292
* The partcmd_enable and partcmd_disable commands are used by
1290
1293
* update_prstate(). An error code may be returned and the caller will check
1291
1294
* for error.
1292
1295
*
1293
1296
* The partcmd_update command is used by update_cpumasks_hier() with newmask
1294
- * NULL and update_cpumask() with newmask set. The callers won't check for
1295
- * error and so partition_root_state and prs_error will be updated directly.
1297
+ * NULL and update_cpumask() with newmask set. The partcmd_invalidate is used
1298
+ * by update_cpumask() with NULL newmask. In both cases, the callers won't
1299
+ * check for error and so partition_root_state and prs_error will be updated
1300
+ * directly.
1296
1301
*/
1297
1302
static int update_parent_subparts_cpumask (struct cpuset * cs , int cmd ,
1298
1303
struct cpumask * newmask ,
@@ -1320,7 +1325,8 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
1320
1325
return PERR_CPUSEMPTY ;
1321
1326
1322
1327
/*
1323
- * new_prs will only be changed for the partcmd_update command.
1328
+ * new_prs will only be changed for the partcmd_update and
1329
+ * partcmd_invalidate commands.
1324
1330
*/
1325
1331
adding = deleting = false;
1326
1332
old_prs = new_prs = cs -> partition_root_state ;
@@ -1350,6 +1356,20 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
1350
1356
deleting = !is_prs_invalid (old_prs ) &&
1351
1357
cpumask_and (tmp -> delmask , cs -> cpus_allowed ,
1352
1358
parent -> subparts_cpus );
1359
+ } else if (cmd == partcmd_invalidate ) {
1360
+ if (is_prs_invalid (old_prs ))
1361
+ return 0 ;
1362
+
1363
+ /*
1364
+ * Make the current partition invalid. It is assumed that
1365
+ * invalidation is caused by violating cpu exclusivity rule.
1366
+ */
1367
+ deleting = cpumask_and (tmp -> delmask , cs -> cpus_allowed ,
1368
+ parent -> subparts_cpus );
1369
+ if (old_prs > 0 ) {
1370
+ new_prs = - old_prs ;
1371
+ part_error = PERR_NOTEXCL ;
1372
+ }
1353
1373
} else if (newmask ) {
1354
1374
/*
1355
1375
* partcmd_update with newmask:
@@ -1403,6 +1423,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
1403
1423
parent -> cpus_allowed );
1404
1424
adding = cpumask_andnot (tmp -> addmask , tmp -> addmask ,
1405
1425
parent -> subparts_cpus );
1426
+
1406
1427
if ((is_partition_valid (cs ) && !parent -> nr_subparts_cpus ) ||
1407
1428
(adding &&
1408
1429
cpumask_subset (parent -> effective_cpus , tmp -> addmask ) &&
@@ -1709,6 +1730,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
1709
1730
{
1710
1731
int retval ;
1711
1732
struct tmpmasks tmp ;
1733
+ bool invalidate = false;
1712
1734
1713
1735
/* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */
1714
1736
if (cs == & top_cpuset )
@@ -1736,10 +1758,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
1736
1758
if (cpumask_equal (cs -> cpus_allowed , trialcs -> cpus_allowed ))
1737
1759
return 0 ;
1738
1760
1739
- retval = validate_change (cs , trialcs );
1740
- if (retval < 0 )
1741
- return retval ;
1742
-
1743
1761
#ifdef CONFIG_CPUMASK_OFFSTACK
1744
1762
/*
1745
1763
* Use the cpumasks in trialcs for tmpmasks when they are pointers
@@ -1750,9 +1768,42 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
1750
1768
tmp .new_cpus = trialcs -> cpus_allowed ;
1751
1769
#endif
1752
1770
1771
+ retval = validate_change (cs , trialcs );
1772
+
1773
+ if ((retval == - EINVAL ) && cgroup_subsys_on_dfl (cpuset_cgrp_subsys )) {
1774
+ struct cpuset * cp , * parent ;
1775
+ struct cgroup_subsys_state * css ;
1776
+
1777
+ /*
1778
+ * The -EINVAL error code indicates that partition sibling
1779
+ * CPU exclusivity rule has been violated. We still allow
1780
+ * the cpumask change to proceed while invalidating the
1781
+ * partition. However, any conflicting sibling partitions
1782
+ * have to be marked as invalid too.
1783
+ */
1784
+ invalidate = true;
1785
+ rcu_read_lock ();
1786
+ parent = parent_cs (cs );
1787
+ cpuset_for_each_child (cp , css , parent )
1788
+ if (is_partition_valid (cp ) &&
1789
+ cpumask_intersects (trialcs -> cpus_allowed , cp -> cpus_allowed )) {
1790
+ rcu_read_unlock ();
1791
+ update_parent_subparts_cpumask (cp , partcmd_invalidate , NULL , & tmp );
1792
+ rcu_read_lock ();
1793
+ }
1794
+ rcu_read_unlock ();
1795
+ retval = 0 ;
1796
+ }
1797
+ if (retval < 0 )
1798
+ return retval ;
1799
+
1753
1800
if (cs -> partition_root_state ) {
1754
- update_parent_subparts_cpumask (cs , partcmd_update ,
1755
- trialcs -> cpus_allowed , & tmp );
1801
+ if (invalidate )
1802
+ update_parent_subparts_cpumask (cs , partcmd_invalidate ,
1803
+ NULL , & tmp );
1804
+ else
1805
+ update_parent_subparts_cpumask (cs , partcmd_update ,
1806
+ trialcs -> cpus_allowed , & tmp );
1756
1807
}
1757
1808
1758
1809
compute_effective_cpumask (trialcs -> effective_cpus , trialcs ,
0 commit comments