@@ -178,11 +178,15 @@ struct cpuset {
178
178
*
179
179
* 0 - member (not a partition root)
180
180
* 1 - partition root
181
+ * 2 - partition root without load balancing (isolated)
181
182
* -1 - invalid partition root
183
+ * -2 - invalid isolated partition root
182
184
*/
183
185
#define PRS_MEMBER 0
184
186
#define PRS_ROOT 1
187
+ #define PRS_ISOLATED 2
185
188
#define PRS_INVALID_ROOT -1
189
+ #define PRS_INVALID_ISOLATED -2
186
190
187
191
static inline bool is_prs_invalid (int prs_state )
188
192
{
@@ -282,7 +286,8 @@ static inline int is_partition_invalid(const struct cpuset *cs)
282
286
*/
283
287
static inline void make_partition_invalid (struct cpuset * cs )
284
288
{
285
- cs -> partition_root_state = PRS_INVALID_ROOT ;
289
+ if (is_partition_valid (cs ))
290
+ cs -> partition_root_state = - cs -> partition_root_state ;
286
291
}
287
292
288
293
/*
@@ -1380,17 +1385,19 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
1380
1385
1381
1386
if (cmd == partcmd_update ) {
1382
1387
/*
1383
- * Check for possible transition between PRS_ROOT
1384
- * and PRS_INVALID_ROOT .
1388
+ * Check for possible transition between valid and invalid
1389
+ * partition root .
1385
1390
*/
1386
1391
switch (cs -> partition_root_state ) {
1387
1392
case PRS_ROOT :
1393
+ case PRS_ISOLATED :
1388
1394
if (part_error )
1389
- new_prs = PRS_INVALID_ROOT ;
1395
+ new_prs = - old_prs ;
1390
1396
break ;
1391
1397
case PRS_INVALID_ROOT :
1398
+ case PRS_INVALID_ISOLATED :
1392
1399
if (!part_error )
1393
- new_prs = PRS_ROOT ;
1400
+ new_prs = - old_prs ;
1394
1401
break ;
1395
1402
}
1396
1403
}
@@ -1400,7 +1407,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
1400
1407
1401
1408
/*
1402
1409
* Transitioning between invalid to valid or vice versa may require
1403
- * changing CS_CPU_EXCLUSIVE.
1410
+ * changing CS_CPU_EXCLUSIVE and CS_SCHED_LOAD_BALANCE .
1404
1411
*/
1405
1412
if (old_prs != new_prs ) {
1406
1413
if (is_prs_invalid (old_prs ) && !is_cpu_exclusive (cs ) &&
@@ -1443,8 +1450,17 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
1443
1450
if (adding || deleting )
1444
1451
update_tasks_cpumask (parent );
1445
1452
1453
+ /*
1454
+ * Set or clear CS_SCHED_LOAD_BALANCE when partcmd_update, if necessary.
1455
+ * rebuild_sched_domains_locked() may be called.
1456
+ */
1457
+ if (old_prs != new_prs ) {
1458
+ if (old_prs == PRS_ISOLATED )
1459
+ update_flag (CS_SCHED_LOAD_BALANCE , cs , 1 );
1460
+ else if (new_prs == PRS_ISOLATED )
1461
+ update_flag (CS_SCHED_LOAD_BALANCE , cs , 0 );
1462
+ }
1446
1463
notify_partition_change (cs , old_prs );
1447
-
1448
1464
return 0 ;
1449
1465
}
1450
1466
@@ -1519,6 +1535,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
1519
1535
if ((cp != cs ) && old_prs ) {
1520
1536
switch (parent -> partition_root_state ) {
1521
1537
case PRS_ROOT :
1538
+ case PRS_ISOLATED :
1522
1539
update_parent = true;
1523
1540
break ;
1524
1541
@@ -1528,7 +1545,8 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp,
1528
1545
* invalid, child partition roots become
1529
1546
* invalid too.
1530
1547
*/
1531
- new_prs = PRS_INVALID_ROOT ;
1548
+ if (is_partition_valid (cp ))
1549
+ new_prs = - cp -> partition_root_state ;
1532
1550
break ;
1533
1551
}
1534
1552
}
@@ -2110,6 +2128,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
2110
2128
static int update_prstate (struct cpuset * cs , int new_prs )
2111
2129
{
2112
2130
int err = 0 , old_prs = cs -> partition_root_state ;
2131
+ bool sched_domain_rebuilt = false;
2113
2132
struct cpuset * parent = parent_cs (cs );
2114
2133
struct tmpmasks tmpmask ;
2115
2134
@@ -2120,8 +2139,10 @@ static int update_prstate(struct cpuset *cs, int new_prs)
2120
2139
* For a previously invalid partition root, leave it at being
2121
2140
* invalid if new_prs is not "member".
2122
2141
*/
2123
- if (new_prs && is_prs_invalid (old_prs ))
2142
+ if (new_prs && is_prs_invalid (old_prs )) {
2143
+ cs -> partition_root_state = - new_prs ;
2124
2144
return 0 ;
2145
+ }
2125
2146
2126
2147
if (alloc_cpumasks (NULL , & tmpmask ))
2127
2148
return - ENOMEM ;
@@ -2147,6 +2168,22 @@ static int update_prstate(struct cpuset *cs, int new_prs)
2147
2168
update_flag (CS_CPU_EXCLUSIVE , cs , 0 );
2148
2169
goto out ;
2149
2170
}
2171
+
2172
+ if (new_prs == PRS_ISOLATED ) {
2173
+ /*
2174
+ * Disable the load balance flag should not return an
2175
+ * error unless the system is running out of memory.
2176
+ */
2177
+ update_flag (CS_SCHED_LOAD_BALANCE , cs , 0 );
2178
+ sched_domain_rebuilt = true;
2179
+ }
2180
+ } else if (old_prs && new_prs ) {
2181
+ /*
2182
+ * A change in load balance state only, no change in cpumasks.
2183
+ */
2184
+ update_flag (CS_SCHED_LOAD_BALANCE , cs , (new_prs != PRS_ISOLATED ));
2185
+ sched_domain_rebuilt = true;
2186
+ goto out ; /* Sched domain is rebuilt in update_flag() */
2150
2187
} else {
2151
2188
/*
2152
2189
* Switching back to member is always allowed even if it
@@ -2168,20 +2205,27 @@ static int update_prstate(struct cpuset *cs, int new_prs)
2168
2205
2169
2206
/* Turning off CS_CPU_EXCLUSIVE will not return error */
2170
2207
update_flag (CS_CPU_EXCLUSIVE , cs , 0 );
2208
+
2209
+ if (!is_sched_load_balance (cs )) {
2210
+ /* Make sure load balance is on */
2211
+ update_flag (CS_SCHED_LOAD_BALANCE , cs , 1 );
2212
+ sched_domain_rebuilt = true;
2213
+ }
2171
2214
}
2172
2215
2173
2216
update_tasks_cpumask (parent );
2174
2217
2175
2218
if (parent -> child_ecpus_count )
2176
2219
update_sibling_cpumasks (parent , cs , & tmpmask );
2177
2220
2178
- rebuild_sched_domains_locked ();
2221
+ if (!sched_domain_rebuilt )
2222
+ rebuild_sched_domains_locked ();
2179
2223
out :
2180
2224
/*
2181
2225
* Make partition invalid if an error happen
2182
2226
*/
2183
2227
if (err )
2184
- new_prs = PRS_INVALID_ROOT ;
2228
+ new_prs = - new_prs ;
2185
2229
spin_lock_irq (& callback_lock );
2186
2230
cs -> partition_root_state = new_prs ;
2187
2231
spin_unlock_irq (& callback_lock );
@@ -2691,12 +2735,18 @@ static int sched_partition_show(struct seq_file *seq, void *v)
2691
2735
case PRS_ROOT :
2692
2736
seq_puts (seq , "root\n" );
2693
2737
break ;
2738
+ case PRS_ISOLATED :
2739
+ seq_puts (seq , "isolated\n" );
2740
+ break ;
2694
2741
case PRS_MEMBER :
2695
2742
seq_puts (seq , "member\n" );
2696
2743
break ;
2697
2744
case PRS_INVALID_ROOT :
2698
2745
seq_puts (seq , "root invalid\n" );
2699
2746
break ;
2747
+ case PRS_INVALID_ISOLATED :
2748
+ seq_puts (seq , "isolated invalid\n" );
2749
+ break ;
2700
2750
}
2701
2751
return 0 ;
2702
2752
}
@@ -2717,6 +2767,8 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf,
2717
2767
val = PRS_ROOT ;
2718
2768
else if (!strcmp (buf , "member" ))
2719
2769
val = PRS_MEMBER ;
2770
+ else if (!strcmp (buf , "isolated" ))
2771
+ val = PRS_ISOLATED ;
2720
2772
else
2721
2773
return - EINVAL ;
2722
2774
0 commit comments