Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'cgroup-for-7.0-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup

Pull cgroup fixes from Tejun Heo:

- Fix circular locking dependency in cpuset partition code by
deferring housekeeping_update() calls to a workqueue instead
of calling them directly under cpus_read_lock

- Fix null-ptr-deref in rebuild_sched_domains_cpuslocked() when
generate_sched_domains() returns NULL due to kmalloc failure

- Fix incorrect cpuset behavior for effective_xcpus in
partition_xcpus_del() and cpuset_update_tasks_cpumask()
in update_cpumasks_hier()

- Fix race between task migration and cgroup iteration

* tag 'cgroup-for-7.0-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
cgroup/cpuset: fix null-ptr-deref in rebuild_sched_domains_cpuslocked
cgroup/cpuset: Call housekeeping_update() without holding cpus_read_lock
cgroup/cpuset: Defer housekeeping_update() calls from CPU hotplug to workqueue
cgroup/cpuset: Move housekeeping_update()/rebuild_sched_domains() together
kselftest/cgroup: Simplify test_cpuset_prs.sh by removing "S+" command
cgroup/cpuset: Set isolated_cpus_updating only if isolated_cpus is changed
cgroup/cpuset: Clarify exclusion rules for cpuset internal variables
cgroup/cpuset: Fix incorrect use of cpuset_update_tasks_cpumask() in update_cpumasks_hier()
cgroup/cpuset: Fix incorrect change to effective_xcpus in partition_xcpus_del()
cgroup: fix race between task migration and iteration

+266 -189
+1
kernel/cgroup/cgroup.c
··· 2608 2608 2609 2609 mgctx->tset.nr_tasks++; 2610 2610 2611 + css_set_skip_task_iters(cset, task); 2611 2612 list_move_tail(&task->cg_list, &cset->mg_tasks); 2612 2613 if (list_empty(&cset->mg_node)) 2613 2614 list_add_tail(&cset->mg_node,
+149 -73
kernel/cgroup/cpuset.c
··· 62 62 }; 63 63 64 64 /* 65 + * CPUSET Locking Convention 66 + * ------------------------- 67 + * 68 + * Below are the four global/local locks guarding cpuset structures in lock 69 + * acquisition order: 70 + * - cpuset_top_mutex 71 + * - cpu_hotplug_lock (cpus_read_lock/cpus_write_lock) 72 + * - cpuset_mutex 73 + * - callback_lock (raw spinlock) 74 + * 75 + * As cpuset will now indirectly flush a number of different workqueues in 76 + * housekeeping_update() to update housekeeping cpumasks when the set of 77 + * isolated CPUs is going to be changed, it may be vulnerable to deadlock 78 + * if we hold cpus_read_lock while calling into housekeeping_update(). 79 + * 80 + * The first cpuset_top_mutex will be held except when calling into 81 + * cpuset_handle_hotplug() from the CPU hotplug code where cpus_write_lock 82 + * and cpuset_mutex will be held instead. The main purpose of this mutex 83 + * is to prevent regular cpuset control file write actions from interfering 84 + * with the call to housekeeping_update(), though CPU hotplug operation can 85 + * still happen in parallel. This mutex also provides protection for some 86 + * internal variables. 87 + * 88 + * A task must hold all the remaining three locks to modify externally visible 89 + * or used fields of cpusets, though some of the internally used cpuset fields 90 + * and internal variables can be modified without holding callback_lock. If only 91 + * reliable read access of the externally used fields are needed, a task can 92 + * hold either cpuset_mutex or callback_lock which are exposed to other 93 + * external subsystems. 94 + * 95 + * If a task holds cpu_hotplug_lock and cpuset_mutex, it blocks others, 96 + * ensuring that it is the only task able to also acquire callback_lock and 97 + * be able to modify cpusets. It can perform various checks on the cpuset 98 + * structure first, knowing nothing will change. It can also allocate memory 99 + * without holding callback_lock. While it is performing these checks, various 100 + * callback routines can briefly acquire callback_lock to query cpusets. Once 101 + * it is ready to make the changes, it takes callback_lock, blocking everyone 102 + * else. 103 + * 104 + * Calls to the kernel memory allocator cannot be made while holding 105 + * callback_lock which is a spinlock, as the memory allocator may sleep or 106 + * call back into cpuset code and acquire callback_lock. 107 + * 108 + * Now, the task_struct fields mems_allowed and mempolicy may be changed 109 + * by other task, we use alloc_lock in the task_struct fields to protect 110 + * them. 111 + * 112 + * The cpuset_common_seq_show() handlers only hold callback_lock across 113 + * small pieces of code, such as when reading out possibly multi-word 114 + * cpumasks and nodemasks. 115 + */ 116 + 117 + static DEFINE_MUTEX(cpuset_top_mutex); 118 + static DEFINE_MUTEX(cpuset_mutex); 119 + 120 + /* 121 + * File level internal variables below follow one of the following exclusion 122 + * rules. 123 + * 124 + * RWCS: Read/write-able by holding either cpus_write_lock (and optionally 125 + * cpuset_mutex) or both cpus_read_lock and cpuset_mutex. 126 + * 127 + * CSCB: Readable by holding either cpuset_mutex or callback_lock. Writable 128 + * by holding both cpuset_mutex and callback_lock. 129 + * 130 + * T: Read/write-able by holding the cpuset_top_mutex. 131 + */ 132 + 133 + /* 65 134 * For local partitions, update to subpartitions_cpus & isolated_cpus is done 66 135 * in update_parent_effective_cpumask(). For remote partitions, it is done in 67 136 * the remote_partition_*() and remote_cpus_update() helpers. ··· 139 70 * Exclusive CPUs distributed out to local or remote sub-partitions of 140 71 * top_cpuset 141 72 */ 142 - static cpumask_var_t subpartitions_cpus; 73 + static cpumask_var_t subpartitions_cpus; /* RWCS */ 143 74 144 75 /* 145 - * Exclusive CPUs in isolated partitions 76 + * Exclusive CPUs in isolated partitions (shown in cpuset.cpus.isolated) 146 77 */ 147 - static cpumask_var_t isolated_cpus; 78 + static cpumask_var_t isolated_cpus; /* CSCB */ 148 79 149 80 /* 150 - * isolated_cpus updating flag (protected by cpuset_mutex) 151 - * Set if isolated_cpus is going to be updated in the current 152 - * cpuset_mutex crtical section. 81 + * Set if housekeeping cpumasks are to be updated. 153 82 */ 154 - static bool isolated_cpus_updating; 83 + static bool update_housekeeping; /* RWCS */ 84 + 85 + /* 86 + * Copy of isolated_cpus to be passed to housekeeping_update() 87 + */ 88 + static cpumask_var_t isolated_hk_cpus; /* T */ 155 89 156 90 /* 157 91 * A flag to force sched domain rebuild at the end of an operation. ··· 170 98 * Note that update_relax_domain_level() in cpuset-v1.c can still call 171 99 * rebuild_sched_domains_locked() directly without using this flag. 172 100 */ 173 - static bool force_sd_rebuild; 101 + static bool force_sd_rebuild; /* RWCS */ 174 102 175 103 /* 176 104 * Partition root states: ··· 290 218 .partition_root_state = PRS_ROOT, 291 219 }; 292 220 293 - /* 294 - * There are two global locks guarding cpuset structures - cpuset_mutex and 295 - * callback_lock. The cpuset code uses only cpuset_mutex. Other kernel 296 - * subsystems can use cpuset_lock()/cpuset_unlock() to prevent change to cpuset 297 - * structures. Note that cpuset_mutex needs to be a mutex as it is used in 298 - * paths that rely on priority inheritance (e.g. scheduler - on RT) for 299 - * correctness. 300 - * 301 - * A task must hold both locks to modify cpusets. If a task holds 302 - * cpuset_mutex, it blocks others, ensuring that it is the only task able to 303 - * also acquire callback_lock and be able to modify cpusets. It can perform 304 - * various checks on the cpuset structure first, knowing nothing will change. 305 - * It can also allocate memory while just holding cpuset_mutex. While it is 306 - * performing these checks, various callback routines can briefly acquire 307 - * callback_lock to query cpusets. Once it is ready to make the changes, it 308 - * takes callback_lock, blocking everyone else. 309 - * 310 - * Calls to the kernel memory allocator can not be made while holding 311 - * callback_lock, as that would risk double tripping on callback_lock 312 - * from one of the callbacks into the cpuset code from within 313 - * __alloc_pages(). 314 - * 315 - * If a task is only holding callback_lock, then it has read-only 316 - * access to cpusets. 317 - * 318 - * Now, the task_struct fields mems_allowed and mempolicy may be changed 319 - * by other task, we use alloc_lock in the task_struct fields to protect 320 - * them. 321 - * 322 - * The cpuset_common_seq_show() handlers only hold callback_lock across 323 - * small pieces of code, such as when reading out possibly multi-word 324 - * cpumasks and nodemasks. 325 - */ 326 - 327 - static DEFINE_MUTEX(cpuset_mutex); 328 - 329 221 /** 330 222 * cpuset_lock - Acquire the global cpuset mutex 331 223 * ··· 319 283 */ 320 284 void cpuset_full_lock(void) 321 285 { 286 + mutex_lock(&cpuset_top_mutex); 322 287 cpus_read_lock(); 323 288 mutex_lock(&cpuset_mutex); 324 289 } ··· 328 291 { 329 292 mutex_unlock(&cpuset_mutex); 330 293 cpus_read_unlock(); 294 + mutex_unlock(&cpuset_top_mutex); 331 295 } 332 296 333 297 #ifdef CONFIG_LOCKDEP 334 298 bool lockdep_is_cpuset_held(void) 335 299 { 336 - return lockdep_is_held(&cpuset_mutex); 300 + return lockdep_is_held(&cpuset_mutex) || 301 + lockdep_is_held(&cpuset_top_mutex); 337 302 } 338 303 #endif 339 304 ··· 1000 961 * offline CPUs, a warning is emitted and we return directly to 1001 962 * prevent the panic. 1002 963 */ 1003 - for (i = 0; i < ndoms; ++i) { 964 + for (i = 0; doms && i < ndoms; i++) { 1004 965 if (WARN_ON_ONCE(!cpumask_subset(doms[i], cpu_active_mask))) 1005 966 return; 1006 967 } ··· 1200 1161 static void isolated_cpus_update(int old_prs, int new_prs, struct cpumask *xcpus) 1201 1162 { 1202 1163 WARN_ON_ONCE(old_prs == new_prs); 1203 - if (new_prs == PRS_ISOLATED) 1164 + lockdep_assert_held(&callback_lock); 1165 + lockdep_assert_held(&cpuset_mutex); 1166 + if (new_prs == PRS_ISOLATED) { 1167 + if (cpumask_subset(xcpus, isolated_cpus)) 1168 + return; 1204 1169 cpumask_or(isolated_cpus, isolated_cpus, xcpus); 1205 - else 1170 + } else { 1171 + if (!cpumask_intersects(xcpus, isolated_cpus)) 1172 + return; 1206 1173 cpumask_andnot(isolated_cpus, isolated_cpus, xcpus); 1207 - 1208 - isolated_cpus_updating = true; 1174 + } 1175 + update_housekeeping = true; 1209 1176 } 1210 1177 1211 1178 /* ··· 1264 1219 isolated_cpus_update(old_prs, parent->partition_root_state, 1265 1220 xcpus); 1266 1221 1267 - cpumask_and(xcpus, xcpus, cpu_active_mask); 1268 1222 cpumask_or(parent->effective_cpus, parent->effective_cpus, xcpus); 1223 + cpumask_and(parent->effective_cpus, parent->effective_cpus, cpu_active_mask); 1269 1224 } 1270 1225 1271 1226 /* ··· 1329 1284 } 1330 1285 1331 1286 /* 1332 - * update_isolation_cpumasks - Update external isolation related CPU masks 1287 + * update_hk_sched_domains - Update HK cpumasks & rebuild sched domains 1333 1288 * 1334 - * The following external CPU masks will be updated if necessary: 1335 - * - workqueue unbound cpumask 1289 + * Update housekeeping cpumasks and rebuild sched domains if necessary. 1290 + * This should be called at the end of cpuset or hotplug actions. 1336 1291 */ 1337 - static void update_isolation_cpumasks(void) 1292 + static void update_hk_sched_domains(void) 1338 1293 { 1339 - int ret; 1294 + if (update_housekeeping) { 1295 + /* Updating HK cpumasks implies rebuild sched domains */ 1296 + update_housekeeping = false; 1297 + force_sd_rebuild = true; 1298 + cpumask_copy(isolated_hk_cpus, isolated_cpus); 1340 1299 1341 - if (!isolated_cpus_updating) 1342 - return; 1300 + /* 1301 + * housekeeping_update() is now called without holding 1302 + * cpus_read_lock and cpuset_mutex. Only cpuset_top_mutex 1303 + * is still being held for mutual exclusion. 1304 + */ 1305 + mutex_unlock(&cpuset_mutex); 1306 + cpus_read_unlock(); 1307 + WARN_ON_ONCE(housekeeping_update(isolated_hk_cpus)); 1308 + cpus_read_lock(); 1309 + mutex_lock(&cpuset_mutex); 1310 + } 1311 + /* force_sd_rebuild will be cleared in rebuild_sched_domains_locked() */ 1312 + if (force_sd_rebuild) 1313 + rebuild_sched_domains_locked(); 1314 + } 1343 1315 1344 - ret = housekeeping_update(isolated_cpus); 1345 - WARN_ON_ONCE(ret < 0); 1346 - 1347 - isolated_cpus_updating = false; 1316 + /* 1317 + * Work function to invoke update_hk_sched_domains() 1318 + */ 1319 + static void hk_sd_workfn(struct work_struct *work) 1320 + { 1321 + cpuset_full_lock(); 1322 + update_hk_sched_domains(); 1323 + cpuset_full_unlock(); 1348 1324 } 1349 1325 1350 1326 /** ··· 1516 1450 cs->remote_partition = true; 1517 1451 cpumask_copy(cs->effective_xcpus, tmp->new_cpus); 1518 1452 spin_unlock_irq(&callback_lock); 1519 - update_isolation_cpumasks(); 1520 1453 cpuset_force_rebuild(); 1521 1454 cs->prs_err = 0; 1522 1455 ··· 1560 1495 compute_excpus(cs, cs->effective_xcpus); 1561 1496 reset_partition_data(cs); 1562 1497 spin_unlock_irq(&callback_lock); 1563 - update_isolation_cpumasks(); 1564 1498 cpuset_force_rebuild(); 1565 1499 1566 1500 /* ··· 1630 1566 if (xcpus) 1631 1567 cpumask_copy(cs->exclusive_cpus, xcpus); 1632 1568 spin_unlock_irq(&callback_lock); 1633 - update_isolation_cpumasks(); 1634 1569 if (adding || deleting) 1635 1570 cpuset_force_rebuild(); 1636 1571 ··· 1973 1910 partition_xcpus_add(new_prs, parent, tmp->delmask); 1974 1911 1975 1912 spin_unlock_irq(&callback_lock); 1976 - update_isolation_cpumasks(); 1977 1913 1978 1914 if ((old_prs != new_prs) && (cmd == partcmd_update)) 1979 1915 update_partition_exclusive_flag(cs, new_prs); ··· 2217 2155 WARN_ON(!is_in_v2_mode() && 2218 2156 !cpumask_equal(cp->cpus_allowed, cp->effective_cpus)); 2219 2157 2220 - cpuset_update_tasks_cpumask(cp, cp->effective_cpus); 2158 + cpuset_update_tasks_cpumask(cp, tmp->new_cpus); 2221 2159 2222 2160 /* 2223 2161 * On default hierarchy, inherit the CS_SCHED_LOAD_BALANCE ··· 2940 2878 else if (isolcpus_updated) 2941 2879 isolated_cpus_update(old_prs, new_prs, cs->effective_xcpus); 2942 2880 spin_unlock_irq(&callback_lock); 2943 - update_isolation_cpumasks(); 2944 2881 2945 2882 /* Force update if switching back to member & update effective_xcpus */ 2946 2883 update_cpumasks_hier(cs, &tmpmask, !new_prs); ··· 3229 3168 } 3230 3169 3231 3170 free_cpuset(trialcs); 3232 - if (force_sd_rebuild) 3233 - rebuild_sched_domains_locked(); 3234 3171 out_unlock: 3172 + update_hk_sched_domains(); 3235 3173 cpuset_full_unlock(); 3236 3174 if (of_cft(of)->private == FILE_MEMLIST) 3237 3175 schedule_flush_migrate_mm(); ··· 3338 3278 cpuset_full_lock(); 3339 3279 if (is_cpuset_online(cs)) 3340 3280 retval = update_prstate(cs, val); 3281 + update_hk_sched_domains(); 3341 3282 cpuset_full_unlock(); 3342 3283 return retval ?: nbytes; 3343 3284 } ··· 3513 3452 /* Reset valid partition back to member */ 3514 3453 if (is_partition_valid(cs)) 3515 3454 update_prstate(cs, PRS_MEMBER); 3455 + update_hk_sched_domains(); 3516 3456 cpuset_full_unlock(); 3517 3457 } 3518 3458 ··· 3669 3607 BUG_ON(!alloc_cpumask_var(&top_cpuset.exclusive_cpus, GFP_KERNEL)); 3670 3608 BUG_ON(!zalloc_cpumask_var(&subpartitions_cpus, GFP_KERNEL)); 3671 3609 BUG_ON(!zalloc_cpumask_var(&isolated_cpus, GFP_KERNEL)); 3610 + BUG_ON(!zalloc_cpumask_var(&isolated_hk_cpus, GFP_KERNEL)); 3672 3611 3673 3612 cpumask_setall(top_cpuset.cpus_allowed); 3674 3613 nodes_setall(top_cpuset.mems_allowed); ··· 3841 3778 */ 3842 3779 static void cpuset_handle_hotplug(void) 3843 3780 { 3781 + static DECLARE_WORK(hk_sd_work, hk_sd_workfn); 3844 3782 static cpumask_t new_cpus; 3845 3783 static nodemask_t new_mems; 3846 3784 bool cpus_updated, mems_updated; ··· 3923 3859 rcu_read_unlock(); 3924 3860 } 3925 3861 3926 - /* rebuild sched domains if necessary */ 3927 - if (force_sd_rebuild) 3928 - rebuild_sched_domains_cpuslocked(); 3862 + 3863 + /* 3864 + * Queue a work to call housekeeping_update() & rebuild_sched_domains() 3865 + * There will be a slight delay before the HK_TYPE_DOMAIN housekeeping 3866 + * cpumask can correctly reflect what is in isolated_cpus. 3867 + * 3868 + * We rely on WORK_STRUCT_PENDING_BIT to not requeue a work item that 3869 + * is still pending. Before the pending bit is cleared, the work data 3870 + * is copied out and work item dequeued. So it is possible to queue 3871 + * the work again before the hk_sd_workfn() is invoked to process the 3872 + * previously queued work. Since hk_sd_workfn() doesn't use the work 3873 + * item at all, this is not a problem. 3874 + */ 3875 + if (update_housekeeping || force_sd_rebuild) 3876 + queue_work(system_unbound_wq, &hk_sd_work); 3929 3877 3930 3878 free_tmpmasks(ptmp); 3931 3879 }
+1 -3
kernel/sched/isolation.c
··· 123 123 struct cpumask *trial, *old = NULL; 124 124 int err; 125 125 126 - lockdep_assert_cpus_held(); 127 - 128 126 trial = kmalloc(cpumask_size(), GFP_KERNEL); 129 127 if (!trial) 130 128 return -ENOMEM; ··· 134 136 } 135 137 136 138 if (!housekeeping.flags) 137 - static_branch_enable_cpuslocked(&housekeeping_overridden); 139 + static_branch_enable(&housekeeping_overridden); 138 140 139 141 if (housekeeping.flags & HK_FLAG_DOMAIN) 140 142 old = housekeeping_cpumask_dereference(HK_TYPE_DOMAIN);
+1 -3
kernel/time/timer_migration.c
··· 1559 1559 cpumask_var_t cpumask __free(free_cpumask_var) = CPUMASK_VAR_NULL; 1560 1560 int cpu; 1561 1561 1562 - lockdep_assert_cpus_held(); 1563 - 1564 1562 if (!works) 1565 1563 return -ENOMEM; 1566 1564 if (!alloc_cpumask_var(&cpumask, GFP_KERNEL)) ··· 1568 1570 * First set previously isolated CPUs as available (unisolate). 1569 1571 * This cpumask contains only CPUs that switched to available now. 1570 1572 */ 1573 + guard(cpus_read_lock)(); 1571 1574 cpumask_andnot(cpumask, cpu_online_mask, exclude_cpumask); 1572 1575 cpumask_andnot(cpumask, cpumask, tmigr_available_cpumask); 1573 1576 ··· 1625 1626 cpumask_andnot(cpumask, cpu_possible_mask, housekeeping_cpumask(HK_TYPE_DOMAIN)); 1626 1627 1627 1628 /* Protect against RCU torture hotplug testing */ 1628 - guard(cpus_read_lock)(); 1629 1629 return tmigr_isolated_exclude_cpumask(cpumask); 1630 1630 } 1631 1631 late_initcall(tmigr_init_isolation);
+114 -110
tools/testing/selftests/cgroup/test_cpuset_prs.sh
··· 196 196 # P<v> = set cpus.partition (0:member, 1:root, 2:isolated) 197 197 # C<l> = add cpu-list to cpuset.cpus 198 198 # X<l> = add cpu-list to cpuset.cpus.exclusive 199 - # S<p> = use prefix in subtree_control 200 199 # T = put a task into cgroup 201 200 # CX<l> = add cpu-list to both cpuset.cpus and cpuset.cpus.exclusive 202 201 # O<c>=<v> = Write <v> to CPU online file of <c> ··· 208 209 # sched-debug matching which includes offline CPUs and single-CPU partitions 209 210 # while the second one is for matching cpuset.cpus.isolated. 210 211 # 211 - SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1" 212 + SETUP_A123_PARTITIONS="C1-3:P1 C2-3:P1 C3:P1" 212 213 TEST_MATRIX=( 213 214 # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS 214 215 # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ -------- 215 - " C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1" 216 + " C0-1 . . C2-3 . C4-5 . . 0 A2:0-1" 216 217 " C0-1 . . C2-3 P1 . . . 0 " 217 - " C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 " 218 - " C0-1 . . C2-3 P1:S+ C1:P1 . . 0 " 219 - " C0-1:S+ . . C2-3 . . . P1 0 " 220 - " C0-1:P1 . . C2-3 S+ C1 . . 0 " 221 - " C0-1:P1 . . C2-3 S+ C1:P1 . . 0 " 222 - " C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 " 218 + " C0-1 . . C2-3 P1 C0-1:P1 . . 0 " 219 + " C0-1 . . C2-3 P1 C1:P1 . . 0 " 220 + " C0-1 . . C2-3 . . . P1 0 " 221 + " C0-1:P1 . . C2-3 . C1 . . 0 " 222 + " C0-1:P1 . . C2-3 . C1:P1 . . 0 " 223 + " C0-1:P1 . . C2-3 . C1:P1 . P1 0 " 223 224 " C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5" 224 - " C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5" 225 225 " C0-1 . . C2-3:P1 . . . C2 0 " 226 226 " C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5" 227 - "C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1|A2:2-3|XA2:2-3" 228 - "C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3" 229 - "C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:|A2:3|XA2:3 A1:P1|A2:P1" 230 - "C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3|A2:3 A1:P1|A2:P0" 231 - "C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4|A2:2" 232 - "C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:|B1:0-2 A1:P1|A2:P1" 227 + " C0-3:P1 C2-3:P1 . . . . . . 0 A1:0-1|A2:2-3|XA2:2-3" 228 + " C0-3:P1 C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3" 229 + " C2-3:P1 C3:P1 . . C3 . . . 0 A1:|A2:3|XA2:3 A1:P1|A2:P1" 230 + " C2-3:P1 C3:P1 . . C3 P0 . . 0 A1:3|A2:3 A1:P1|A2:P0" 231 + " C2-3:P1 C2:P1 . . C2-4 . . . 0 A1:3-4|A2:2" 232 + " C2-3:P1 C3:P1 . . C3 . . C0-2 0 A1:|B1:0-2 A1:P1|A2:P1" 233 233 "$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1" 234 234 235 235 # CPU offlining cases: 236 - " C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1|B1:3" 237 - "C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1|A2:3" 238 - "C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1|A2:2-3" 239 - "C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0|A2:2-3" 240 - "C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1|A2:2-3" 241 - "C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P1" 242 - "C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P2" 243 - "C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P1" 244 - "C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P2" 245 - "C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:|A2:3 A1:P1|A2:P1" 246 - "C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2|A2: A1:P1|A2:P1" 247 - "C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-1" 248 - "C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2|A2:2 A1:P1|A2:P-1" 236 + " C0-1 . . C2-3 . C4-5 . O2=0 0 A1:0-1|B1:3" 237 + " C0-3:P1 C2-3:P1 . . O2=0 . . . 0 A1:0-1|A2:3" 238 + " C0-3:P1 C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1|A2:2-3" 239 + " C0-3:P1 C2-3:P1 . . O1=0 . . . 0 A1:0|A2:2-3" 240 + " C0-3:P1 C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1|A2:2-3" 241 + " C2-3:P1 C3:P1 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P1" 242 + " C2-3:P1 C3:P2 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P2" 243 + " C2-3:P1 C3:P1 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P1" 244 + " C2-3:P1 C3:P2 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P2" 245 + " C2-3:P1 C3:P1 . . O2=0 . . . 0 A1:|A2:3 A1:P1|A2:P1" 246 + " C2-3:P1 C3:P1 . . O3=0 . . . 0 A1:2|A2: A1:P1|A2:P1" 247 + " C2-3:P1 C3:P1 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-1" 248 + " C2-3:P1 C3:P1 . . . T:O3=0 . . 0 A1:2|A2:2 A1:P1|A2:P-1" 249 + " C2-3:P1 C3:P2 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-2" 250 + " C1-3:P1 C3:P2 . . . T:O3=0 . . 0 A1:1-2|A2:1-2 A1:P1|A2:P-2 3|" 251 + " C1-3:P1 C3:P2 . . . T:O3=0 O3=1 . 0 A1:1-2|A2:3 A1:P1|A2:P2 3" 249 252 "$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:|A2:2|A3:3 A1:P1|A2:P1|A3:P1" 250 253 "$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1|A2:|A3:3 A1:P1|A2:P1|A3:P1" 251 254 "$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1|A2:2|A3: A1:P1|A2:P1|A3:P1" ··· 265 264 # 266 265 # Remote partition and cpuset.cpus.exclusive tests 267 266 # 268 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:2-3" 269 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1|A2:2-3|A3:2-3 A1:P0|A2:P2 2-3" 270 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2|A2:3|A3:3 A1:P0|A2:P2 3" 271 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" 272 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" 273 - " C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-1|A2:1|A3:1|B1:2-3 A1:P0|A3:P0|B1:P2" 274 - " C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5" 275 - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4" 276 - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4" 277 - " C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1|A3:2-3 A2:P2|A3:P2 1-3" 278 - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3|B1:4-5 A3:P2|B1:P2 2-5" 279 - " C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3" 280 - " C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3" 267 + " C0-3 C1-3 C2-3 . X2-3 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:2-3" 268 + " C0-3 C1-3 C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1|A2:2-3|A3:2-3 A1:P0|A2:P2 2-3" 269 + " C0-3 C1-3 C2-3 . X2-3 X3:P2 . . 0 A1:0-2|A2:3|A3:3 A1:P0|A2:P2 3" 270 + " C0-3 C1-3 C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" 271 + " C0-3 C1-3 C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" 272 + " C0-3 C1-3 C2-3 C2-3 . . . P2 0 A1:0-1|A2:1|A3:1|B1:2-3 A1:P0|A3:P0|B1:P2" 273 + " C0-3 C1-3 C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5" 274 + " C0-3 C1-3 C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4" 275 + " C0-3 C1-3 C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3|B1:4 A3:P2|B1:P2 2-4" 276 + " C0-3 C1-3 C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1|A3:2-3 A2:P2|A3:P2 1-3" 277 + " C0-3 C1-3 C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3|B1:4-5 A3:P2|B1:P2 2-5" 278 + " C4:X0-3 X1-3 X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3" 279 + " C4:X0-3 X1-3 X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3" 281 280 282 281 # Nested remote/local partition tests 283 - " C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4-5 \ 282 + " C0-3 C1-3 C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4-5 \ 284 283 A1:P0|A2:P1|A3:P2|B1:P1 2-3" 285 - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4 \ 284 + " C0-3 C1-3 C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:|A3:2-3|B1:4 \ 286 285 A1:P0|A2:P1|A3:P2|B1:P1 2-4|2-3" 287 - " C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1|A2:2-3|A3:2-3|B1:4 \ 286 + " C0-3 C1-3 C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1|A2:2-3|A3:2-3|B1:4 \ 288 287 A1:P0|A2:P1|A3:P0|B1:P1" 289 - " C0-3:S+ C1-3:S+ C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:2|A3:3|B1:4 \ 288 + " C0-3 C1-3 C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:2|A3:3|B1:4 \ 290 289 A1:P0|A2:P1|A3:P2|B1:P1 2-4|3" 291 - " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \ 290 + " C0-4 C1-4 C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \ 292 291 A1:P0|A2:P2|A3:P1 2-4|2-3" 293 - " C0-4:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1|A2:2|A3:3-4 \ 292 + " C0-4 C1-4 C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1|A2:2|A3:3-4 \ 294 293 A1:P0|A2:P2|A3:P1 2" 295 - " C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \ 294 + " C0-4:X2-4 C1-4:X2-4:P2 C2-4:X4:P1 \ 296 295 . . X5 . . 0 A1:0-4|A2:1-4|A3:2-4 \ 297 296 A1:P0|A2:P-2|A3:P-1 ." 298 - " C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \ 297 + " C0-4:X2-4 C1-4:X2-4:P2 C2-4:X4:P1 \ 299 298 . . . X1 . 0 A1:0-1|A2:2-4|A3:2-4 \ 300 299 A1:P0|A2:P2|A3:P-1 2-4" 301 300 302 301 # Remote partition offline tests 303 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1|A2:1|A3:3 A1:P0|A3:P2 2-3" 304 - " C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" 305 - " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2|A2:1-2|A3: A1:P0|A3:P2 3" 306 - " C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2|A2:1-2|A3:1-2 A1:P0|A3:P-2 3|" 302 + " C0-3 C1-3 C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1|A2:1|A3:3 A1:P0|A3:P2 2-3" 303 + " C0-3 C1-3 C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3" 304 + " C0-3 C1-3 C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2|A2:1-2|A3: A1:P0|A3:P2 3" 305 + " C0-3 C1-3 C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2|A2:1-2|A3:1-2 A1:P0|A3:P-2 3|" 307 306 308 307 # An invalidated remote partition cannot self-recover from hotplug 309 - " C0-3:S+ C1-3:S+ C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3|A2:1-3|A3:2 A1:P0|A3:P-2 ." 308 + " C0-3 C1-3 C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3|A2:1-3|A3:2 A1:P0|A3:P-2 ." 310 309 311 310 # cpus.exclusive.effective clearing test 312 - " C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3|A2:1-3|A3:2|XA1:" 311 + " C0-3 C1-3 C2 . X2-3:X . . . 0 A1:0-3|A2:1-3|A3:2|XA1:" 313 312 314 313 # Invalid to valid remote partition transition test 315 - " C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3|A2:1-3|XA2: A2:P-2 ." 316 - " C0-3:S+ C1-3:X3:P2 317 - . . X2-3 P2 . . 0 A1:0-2|A2:3|XA2:3 A2:P2 3" 314 + " C0-3 C1-3 . . . X3:P2 . . 0 A1:0-3|A2:1-3|XA2: A2:P-2 ." 315 + " C0-3 C1-3:X3:P2 . . X2-3 P2 . . 0 A1:0-2|A2:3|XA2:3 A2:P2 3" 318 316 319 317 # Invalid to valid local partition direct transition tests 320 - " C1-3:S+:P2 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3" 321 - " C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2|XA1:1-3|A2:3:XA2:3 A1:P2|A2:P2 1-3" 322 - " C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4|B1:5-6 A1:P2|B1:P0" 323 - " C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3|B1:4-6 A1:P2|B1:P0 0-3" 318 + " C1-3:P2 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3" 319 + " C1-3:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2|XA1:1-3|A2:3:XA2:3 A1:P2|A2:P2 1-3" 320 + " C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4|B1:5-6 A1:P2|B1:P0" 321 + " C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3|B1:4-6 A1:P2|B1:P0 0-3" 324 322 325 323 # Local partition invalidation tests 326 - " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \ 324 + " C0-3:X1-3:P2 C1-3:X2-3:P2 C2-3:X3:P2 \ 327 325 . . . . . 0 A1:1|A2:2|A3:3 A1:P2|A2:P2|A3:P2 1-3" 328 - " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \ 326 + " C0-3:X1-3:P2 C1-3:X2-3:P2 C2-3:X3:P2 \ 329 327 . . X4 . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3" 330 - " C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \ 328 + " C0-3:X1-3:P2 C1-3:X2-3:P2 C2-3:X3:P2 \ 331 329 . . C4:X . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3" 332 330 # Local partition CPU change tests 333 - " C0-5:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P2|A2:P1 0-2" 334 - " C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P2|A2:P1 1-3" 331 + " C0-5:P2 C4-5:P1 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P2|A2:P1 0-2" 332 + " C0-5:P2 C4-5:P1 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P2|A2:P1 1-3" 335 333 336 334 # cpus_allowed/exclusive_cpus update tests 337 - " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \ 335 + " C0-3:X2-3 C1-3:X2-3 C2-3:X2-3 \ 338 336 . X:C4 . P2 . 0 A1:4|A2:4|XA2:|XA3:|A3:4 \ 339 337 A1:P0|A3:P-2 ." 340 - " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \ 338 + " C0-3:X2-3 C1-3:X2-3 C2-3:X2-3 \ 341 339 . X1 . P2 . 0 A1:0-3|A2:1-3|XA1:1|XA2:|XA3:|A3:2-3 \ 342 340 A1:P0|A3:P-2 ." 343 - " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \ 341 + " C0-3:X2-3 C1-3:X2-3 C2-3:X2-3 \ 344 342 . . X3 P2 . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3 \ 345 343 A1:P0|A3:P2 3" 346 - " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \ 344 + " C0-3:X2-3 C1-3:X2-3 C2-3:X2-3:P2 \ 347 345 . . X3 . . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3|XA3:3 \ 348 346 A1:P0|A3:P2 3" 349 - " C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \ 347 + " C0-3:X2-3 C1-3:X2-3 C2-3:X2-3:P2 \ 350 348 . X4 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:4|XA2:|XA3 \ 351 349 A1:P0|A3:P-2" 352 350 ··· 356 356 # 357 357 # Adding CPUs to partition root that are not in parent's 358 358 # cpuset.cpus is allowed, but those extra CPUs are ignored. 359 - "C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:|A2:2-3 A1:P1|A2:P1" 359 + " C2-3:P1 C3:P1 . . . C2-4 . . 0 A1:|A2:2-3 A1:P1|A2:P1" 360 360 361 361 # Taking away all CPUs from parent or itself if there are tasks 362 362 # will make the partition invalid. 363 - "C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3|A2:2-3 A1:P1|A2:P-1" 364 - " C3:P1:S+ C3 . . T P1 . . 0 A1:3|A2:3 A1:P1|A2:P-1" 363 + " C2-3:P1 C3:P1 . . T C2-3 . . 0 A1:2-3|A2:2-3 A1:P1|A2:P-1" 364 + " C3:P1 C3 . . T P1 . . 0 A1:3|A2:3 A1:P1|A2:P-1" 365 365 "$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P-1|A3:P-1" 366 366 "$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1|A2:2|A3:3 A1:P1|A2:P1|A3:P1" 367 367 368 368 # Changing a partition root to member makes child partitions invalid 369 - "C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3|A2:3 A1:P0|A2:P-1" 369 + " C2-3:P1 C3:P1 . . P0 . . . 0 A1:2-3|A2:3 A1:P0|A2:P-1" 370 370 "$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3|A2:2-3|A3:3 A1:P1|A2:P0|A3:P-1" 371 371 372 372 # cpuset.cpus can contains cpus not in parent's cpuset.cpus as long 373 373 # as they overlap. 374 - "C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1" 374 + " C2-3:P1 . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1" 375 375 376 376 # Deletion of CPUs distributed to child cgroup is allowed. 377 - "C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5|A2:4-5" 377 + " C0-1:P1 C1 . C2-3 C4-5 . . . 0 A1:4-5|A2:4-5" 378 378 379 379 # To become a valid partition root, cpuset.cpus must overlap parent's 380 380 # cpuset.cpus. 381 - " C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1|A2:0-1 A1:P1|A2:P-1" 381 + " C0-1:P1 . . C2-3 . C4-5:P1 . . 0 A1:0-1|A2:0-1 A1:P1|A2:P-1" 382 382 383 383 # Enabling partition with child cpusets is allowed 384 - " C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1|A2:1 A1:P1" 384 + " C0-1 C1 . C2-3 P1 . . . 0 A1:0-1|A2:1 A1:P1" 385 385 386 386 # A partition root with non-partition root parent is invalid| but it 387 387 # can be made valid if its parent becomes a partition root too. 388 - " C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1|A2:1 A1:P0|A2:P-2" 389 - " C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0|A2:1 A1:P1|A2:P2 0-1|1" 388 + " C0-1 C1 . C2-3 . P2 . . 0 A1:0-1|A2:1 A1:P0|A2:P-2" 389 + " C0-1 C1:P2 . C2-3 P1 . . . 0 A1:0|A2:1 A1:P1|A2:P2 0-1|1" 390 390 391 391 # A non-exclusive cpuset.cpus change will not invalidate its siblings partition. 392 392 " C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2|B1:3 A1:P1|B1:P0" ··· 398 398 399 399 # Child partition root that try to take all CPUs from parent partition 400 400 # with tasks will remain invalid. 401 - " C1-4:P1:S+ P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1" 402 - " C1-4:P1:S+ P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1" 403 - " C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1" 401 + " C1-4:P1 P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1" 402 + " C1-4:P1 P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1" 403 + " C1-4:P1 P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1" 404 404 405 405 # Clearing of cpuset.cpus with a preset cpuset.cpus.exclusive shouldn't 406 406 # affect cpuset.cpus.exclusive.effective. 407 - " C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4|XA2:3" 407 + " C1-4:X3 C1:X3 . . . C . . 0 A2:1-4|XA2:3" 408 408 409 409 # cpuset.cpus can contain CPUs that overlap a sibling cpuset with cpus.exclusive 410 410 # but creating a local partition out of it is not allowed. Similarly and change 411 411 # in cpuset.cpus of a local partition that overlaps sibling exclusive CPUs will 412 412 # invalidate it. 413 - " CX1-4:S+ CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \ 413 + " CX1-4 CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \ 414 414 A1:P0|A2:P2:B1:P1 2-4" 415 - " CX1-4:S+ CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \ 415 + " CX1-4 CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \ 416 416 A1:P0|A2:P2:B1:P-1 2-4" 417 - " CX1-4:S+ CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \ 417 + " CX1-4 CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \ 418 418 A1:P0|A2:P2:B1:P-1 2-4" 419 419 420 420 # When multiple partitions with conflicting cpuset.cpus are created, the ··· 426 426 " C1-3:X1-3 . . C4-5 . . . C1-2 0 A1:1-3|B1:1-2" 427 427 428 428 # cpuset.cpus can become empty with task in it as it inherits parent's effective CPUs 429 - " C1-3:S+ C2 . . . T:C . . 0 A1:1-3|A2:1-3" 429 + " C1-3 C2 . . . T:C . . 0 A1:1-3|A2:1-3" 430 430 431 431 # old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS 432 432 # ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ -------- 433 433 # Failure cases: 434 434 435 435 # A task cannot be added to a partition with no cpu 436 - "C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1" 436 + " C2-3:P1 C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1" 437 437 438 438 # Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected 439 439 " C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3|B1:4-5" ··· 465 465 # old-p1 old-p2 old-c11 old-c12 old-c21 old-c22 466 466 # new-p1 new-p2 new-c11 new-c12 new-c21 new-c22 ECPUs Pstate ISOLCPUS 467 467 # ------ ------ ------- ------- ------- ------- ----- ------ -------- 468 - " X1-3:S+ X4-6:S+ X1-2 X3 X4-5 X6 \ 468 + " X1-3 X4-6 X1-2 X3 X4-5 X6 \ 469 469 . . P2 P2 P2 P2 c11:1-2|c12:3|c21:4-5|c22:6 \ 470 470 c11:P2|c12:P2|c21:P2|c22:P2 1-6" 471 - " CX1-4:S+ . X1-2:P2 C3 . . \ 471 + " CX1-4 . X1-2:P2 C3 . . \ 472 472 . . . C3-4 . . p1:3-4|c11:1-2|c12:3-4 \ 473 473 p1:P0|c11:P2|c12:P0 1-2" 474 - " CX1-4:S+ . X1-2:P2 . . . \ 474 + " CX1-4 . X1-2:P2 . . . \ 475 475 X2-4 . . . . . p1:1,3-4|c11:2 \ 476 476 p1:P0|c11:P2 2" 477 - " CX1-5:S+ . X1-2:P2 X3-5:P1 . . \ 477 + " CX1-5 . X1-2:P2 X3-5:P1 . . \ 478 478 X2-4 . . . . . p1:1,5|c11:2|c12:3-4 \ 479 479 p1:P0|c11:P2|c12:P1 2" 480 - " CX1-4:S+ . X1-2:P2 X3-4:P1 . . \ 480 + " CX1-4 . X1-2:P2 X3-4:P1 . . \ 481 481 . . X2 . . . p1:1|c11:2|c12:3-4 \ 482 482 p1:P0|c11:P2|c12:P1 2" 483 483 # p1 as member, will get its effective CPUs from its parent rtest 484 - " CX1-4:S+ . X1-2:P2 X3-4:P1 . . \ 484 + " CX1-4 . X1-2:P2 X3-4:P1 . . \ 485 485 . . X1 CX2-4 . . p1:5-7|c11:1|c12:2-4 \ 486 486 p1:P0|c11:P2|c12:P1 1" 487 - " CX1-4:S+ X5-6:P1:S+ . . . . \ 488 - . . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \ 487 + " CX1-4 X5-6:P1 . . . . \ 488 + . . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \ 489 489 p1:P0|p2:P1|c11:P2|c12:P1|c22:P2 \ 490 490 1-2,4-6|1-2,5-6" 491 491 # c12 whose cpuset.cpus CPUs are all granted to c11 will become invalid partition 492 - " C1-5:P1:S+ . C1-4:P1 C2-3 . . \ 492 + " C1-5:P1 . C1-4:P1 C2-3 . . \ 493 493 . . . P1 . . p1:5|c11:1-4|c12:5 \ 494 494 p1:P1|c11:P1|c12:P-1" 495 495 ) ··· 530 530 CGRP=$1 531 531 STATE=$2 532 532 SHOWERR=${3} 533 - CTRL=${CTRL:=$CONTROLLER} 534 533 HASERR=0 535 534 REDIRECT="2> $TMPMSG" 536 535 [[ -z "$STATE" || "$STATE" = '.' ]] && return 0 ··· 539 540 for CMD in $(echo $STATE | sed -e "s/:/ /g") 540 541 do 541 542 TFILE=$CGRP/cgroup.procs 542 - SFILE=$CGRP/cgroup.subtree_control 543 543 PFILE=$CGRP/cpuset.cpus.partition 544 544 CFILE=$CGRP/cpuset.cpus 545 545 XFILE=$CGRP/cpuset.cpus.exclusive 546 - case $CMD in 547 - S*) PREFIX=${CMD#?} 548 - COMM="echo ${PREFIX}${CTRL} > $SFILE" 546 + 547 + # Enable cpuset controller if not enabled yet 548 + [[ -f $CFILE ]] || { 549 + COMM="echo +cpuset > $CGRP/../cgroup.subtree_control" 549 550 eval $COMM $REDIRECT 550 - ;; 551 + } 552 + case $CMD in 551 553 X*) 552 554 CPUS=${CMD#?} 553 555 COMM="echo $CPUS > $XFILE" ··· 764 764 # only CPUs in isolated partitions as well as those that are isolated at 765 765 # boot time. 766 766 # 767 - # $1 - expected isolated cpu list(s) <isolcpus1>{,<isolcpus2>} 767 + # $1 - expected isolated cpu list(s) <isolcpus1>{|<isolcpus2>} 768 768 # <isolcpus1> - expected sched/domains value 769 769 # <isolcpus2> - cpuset.cpus.isolated value = <isolcpus1> if not defined 770 770 # ··· 773 773 EXPECTED_ISOLCPUS=$1 774 774 ISCPUS=${CGROUP2}/cpuset.cpus.isolated 775 775 ISOLCPUS=$(cat $ISCPUS) 776 + HKICPUS=$(cat /sys/devices/system/cpu/isolated) 776 777 LASTISOLCPU= 777 778 SCHED_DOMAINS=/sys/kernel/debug/sched/domains 778 779 if [[ $EXPECTED_ISOLCPUS = . ]] ··· 810 809 [[ "$EXPECTED_ISOLCPUS" != "$ISOLCPUS" ]] && return 1 811 810 ISOLCPUS= 812 811 EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN 812 + 813 + # 814 + # The inverse of HK_TYPE_DOMAIN cpumask in $HKICPUS should match $ISOLCPUS 815 + # 816 + [[ "$ISOLCPUS" != "$HKICPUS" ]] && return 1 813 817 814 818 # 815 819 # Use the sched domain in debugfs to check isolated CPUs, if available ··· 953 947 run_state_test() 954 948 { 955 949 TEST=$1 956 - CONTROLLER=cpuset 957 950 CGROUP_LIST=". A1 A1/A2 A1/A2/A3 B1" 958 951 RESET_LIST="A1/A2/A3 A1/A2 A1 B1" 959 952 I=0 ··· 1008 1003 run_remote_state_test() 1009 1004 { 1010 1005 TEST=$1 1011 - CONTROLLER=cpuset 1012 1006 [[ -d rtest ]] || mkdir rtest 1013 1007 cd rtest 1014 1008 echo +cpuset > cgroup.subtree_control