@@ -160,6 +160,9 @@ struct cpuset {
160
160
*/
161
161
int use_parent_ecpus ;
162
162
int child_ecpus_count ;
163
+
164
+ /* Handle for cpuset.cpus.partition */
165
+ struct cgroup_file partition_file ;
163
166
};
164
167
165
168
/*
@@ -263,6 +266,16 @@ static inline int is_partition_root(const struct cpuset *cs)
263
266
return cs -> partition_root_state > 0 ;
264
267
}
265
268
269
+ /*
270
+ * Send notification event of whenever partition_root_state changes.
271
+ */
272
+ static inline void notify_partition_change (struct cpuset * cs ,
273
+ int old_prs , int new_prs )
274
+ {
275
+ if (old_prs != new_prs )
276
+ cgroup_file_notify (& cs -> partition_file );
277
+ }
278
+
266
279
static struct cpuset top_cpuset = {
267
280
.flags = ((1 << CS_ONLINE ) | (1 << CS_CPU_EXCLUSIVE ) |
268
281
(1 << CS_MEM_EXCLUSIVE )),
@@ -1148,7 +1161,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
1148
1161
struct cpuset * parent = parent_cs (cpuset );
1149
1162
int adding ; /* Moving cpus from effective_cpus to subparts_cpus */
1150
1163
int deleting ; /* Moving cpus from subparts_cpus to effective_cpus */
1151
- int new_prs ;
1164
+ int old_prs , new_prs ;
1152
1165
bool part_error = false; /* Partition error? */
1153
1166
1154
1167
percpu_rwsem_assert_held (& cpuset_rwsem );
@@ -1184,7 +1197,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
1184
1197
* A cpumask update cannot make parent's effective_cpus become empty.
1185
1198
*/
1186
1199
adding = deleting = false;
1187
- new_prs = cpuset -> partition_root_state ;
1200
+ old_prs = new_prs = cpuset -> partition_root_state ;
1188
1201
if (cmd == partcmd_enable ) {
1189
1202
cpumask_copy (tmp -> addmask , cpuset -> cpus_allowed );
1190
1203
adding = true;
@@ -1274,7 +1287,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
1274
1287
parent -> subparts_cpus );
1275
1288
}
1276
1289
1277
- if (!adding && !deleting && (new_prs == cpuset -> partition_root_state ))
1290
+ if (!adding && !deleting && (new_prs == old_prs ))
1278
1291
return 0 ;
1279
1292
1280
1293
/*
@@ -1302,9 +1315,11 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
1302
1315
1303
1316
parent -> nr_subparts_cpus = cpumask_weight (parent -> subparts_cpus );
1304
1317
1305
- if (cpuset -> partition_root_state != new_prs )
1318
+ if (old_prs != new_prs )
1306
1319
cpuset -> partition_root_state = new_prs ;
1320
+
1307
1321
spin_unlock_irq (& callback_lock );
1322
+ notify_partition_change (cpuset , old_prs , new_prs );
1308
1323
1309
1324
return cmd == partcmd_update ;
1310
1325
}
@@ -1326,7 +1341,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
1326
1341
struct cpuset * cp ;
1327
1342
struct cgroup_subsys_state * pos_css ;
1328
1343
bool need_rebuild_sched_domains = false;
1329
- int new_prs ;
1344
+ int old_prs , new_prs ;
1330
1345
1331
1346
rcu_read_lock ();
1332
1347
cpuset_for_each_descendant_pre (cp , pos_css , cs ) {
@@ -1366,8 +1381,8 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
1366
1381
* update_tasks_cpumask() again for tasks in the parent
1367
1382
* cpuset if the parent's subparts_cpus changes.
1368
1383
*/
1369
- new_prs = cp -> partition_root_state ;
1370
- if ((cp != cs ) && new_prs ) {
1384
+ old_prs = new_prs = cp -> partition_root_state ;
1385
+ if ((cp != cs ) && old_prs ) {
1371
1386
switch (parent -> partition_root_state ) {
1372
1387
case PRS_DISABLED :
1373
1388
/*
@@ -1438,10 +1453,11 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
1438
1453
}
1439
1454
}
1440
1455
1441
- if (new_prs != cp -> partition_root_state )
1456
+ if (new_prs != old_prs )
1442
1457
cp -> partition_root_state = new_prs ;
1443
1458
1444
1459
spin_unlock_irq (& callback_lock );
1460
+ notify_partition_change (cp , old_prs , new_prs );
1445
1461
1446
1462
WARN_ON (!is_in_v2_mode () &&
1447
1463
!cpumask_equal (cp -> cpus_allowed , cp -> effective_cpus ));
@@ -2023,6 +2039,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
2023
2039
spin_lock_irq (& callback_lock );
2024
2040
cs -> partition_root_state = new_prs ;
2025
2041
spin_unlock_irq (& callback_lock );
2042
+ notify_partition_change (cs , old_prs , new_prs );
2026
2043
}
2027
2044
2028
2045
free_cpumasks (NULL , & tmpmask );
@@ -2708,6 +2725,7 @@ static struct cftype dfl_files[] = {
2708
2725
.write = sched_partition_write ,
2709
2726
.private = FILE_PARTITION_ROOT ,
2710
2727
.flags = CFTYPE_NOT_ON_ROOT ,
2728
+ .file_offset = offsetof(struct cpuset , partition_file ),
2711
2729
},
2712
2730
2713
2731
{
@@ -3103,11 +3121,17 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)
3103
3121
*/
3104
3122
if ((parent -> partition_root_state == PRS_ERROR ) ||
3105
3123
cpumask_empty (& new_cpus )) {
3124
+ int old_prs ;
3125
+
3106
3126
update_parent_subparts_cpumask (cs , partcmd_disable ,
3107
3127
NULL , tmp );
3108
- spin_lock_irq (& callback_lock );
3109
- cs -> partition_root_state = PRS_ERROR ;
3110
- spin_unlock_irq (& callback_lock );
3128
+ old_prs = cs -> partition_root_state ;
3129
+ if (old_prs != PRS_ERROR ) {
3130
+ spin_lock_irq (& callback_lock );
3131
+ cs -> partition_root_state = PRS_ERROR ;
3132
+ spin_unlock_irq (& callback_lock );
3133
+ notify_partition_change (cs , old_prs , PRS_ERROR );
3134
+ }
3111
3135
}
3112
3136
cpuset_force_rebuild ();
3113
3137
}
0 commit comments