aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpuset.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cpuset.c')
-rw-r--r--kernel/cpuset.c93
1 files changed, 60 insertions, 33 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 1e32e6b380af..f66527bfd216 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -415,6 +415,24 @@ static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
415 is_mem_exclusive(p) <= is_mem_exclusive(q); 415 is_mem_exclusive(p) <= is_mem_exclusive(q);
416} 416}
417 417
418/**
419 * alloc_trial_cpuset - allocate a trial cpuset
420 * @cs: the cpuset that the trial cpuset duplicates
421 */
422static struct cpuset *alloc_trial_cpuset(const struct cpuset *cs)
423{
424 return kmemdup(cs, sizeof(*cs), GFP_KERNEL);
425}
426
427/**
428 * free_trial_cpuset - free the trial cpuset
429 * @trial: the trial cpuset to be freed
430 */
431static void free_trial_cpuset(struct cpuset *trial)
432{
433 kfree(trial);
434}
435
418/* 436/*
419 * validate_change() - Used to validate that any proposed cpuset change 437 * validate_change() - Used to validate that any proposed cpuset change
420 * follows the structural rules for cpusets. 438 * follows the structural rules for cpusets.
@@ -880,10 +898,10 @@ static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap)
880 * @cs: the cpuset to consider 898 * @cs: the cpuset to consider
881 * @buf: buffer of cpu numbers written to this cpuset 899 * @buf: buffer of cpu numbers written to this cpuset
882 */ 900 */
883static int update_cpumask(struct cpuset *cs, const char *buf) 901static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
902 const char *buf)
884{ 903{
885 struct ptr_heap heap; 904 struct ptr_heap heap;
886 struct cpuset trialcs;
887 int retval; 905 int retval;
888 int is_load_balanced; 906 int is_load_balanced;
889 907
@@ -891,8 +909,6 @@ static int update_cpumask(struct cpuset *cs, const char *buf)
891 if (cs == &top_cpuset) 909 if (cs == &top_cpuset)
892 return -EACCES; 910 return -EACCES;
893 911
894 trialcs = *cs;
895
896 /* 912 /*
897 * An empty cpus_allowed is ok only if the cpuset has no tasks. 913 * An empty cpus_allowed is ok only if the cpuset has no tasks.
898 * Since cpulist_parse() fails on an empty mask, we special case 914 * Since cpulist_parse() fails on an empty mask, we special case
@@ -900,31 +916,31 @@ static int update_cpumask(struct cpuset *cs, const char *buf)
900 * with tasks have cpus. 916 * with tasks have cpus.
901 */ 917 */
902 if (!*buf) { 918 if (!*buf) {
903 cpus_clear(trialcs.cpus_allowed); 919 cpus_clear(trialcs->cpus_allowed);
904 } else { 920 } else {
905 retval = cpulist_parse(buf, &trialcs.cpus_allowed); 921 retval = cpulist_parse(buf, &trialcs->cpus_allowed);
906 if (retval < 0) 922 if (retval < 0)
907 return retval; 923 return retval;
908 924
909 if (!cpus_subset(trialcs.cpus_allowed, cpu_online_map)) 925 if (!cpus_subset(trialcs->cpus_allowed, cpu_online_map))
910 return -EINVAL; 926 return -EINVAL;
911 } 927 }
912 retval = validate_change(cs, &trialcs); 928 retval = validate_change(cs, trialcs);
913 if (retval < 0) 929 if (retval < 0)
914 return retval; 930 return retval;
915 931
916 /* Nothing to do if the cpus didn't change */ 932 /* Nothing to do if the cpus didn't change */
917 if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed)) 933 if (cpus_equal(cs->cpus_allowed, trialcs->cpus_allowed))
918 return 0; 934 return 0;
919 935
920 retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); 936 retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL);
921 if (retval) 937 if (retval)
922 return retval; 938 return retval;
923 939
924 is_load_balanced = is_sched_load_balance(&trialcs); 940 is_load_balanced = is_sched_load_balance(trialcs);
925 941
926 mutex_lock(&callback_mutex); 942 mutex_lock(&callback_mutex);
927 cs->cpus_allowed = trialcs.cpus_allowed; 943 cs->cpus_allowed = trialcs->cpus_allowed;
928 mutex_unlock(&callback_mutex); 944 mutex_unlock(&callback_mutex);
929 945
930 /* 946 /*
@@ -1099,9 +1115,9 @@ done:
1099 * lock each such tasks mm->mmap_sem, scan its vma's and rebind 1115 * lock each such tasks mm->mmap_sem, scan its vma's and rebind
1100 * their mempolicies to the cpusets new mems_allowed. 1116 * their mempolicies to the cpusets new mems_allowed.
1101 */ 1117 */
1102static int update_nodemask(struct cpuset *cs, const char *buf) 1118static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
1119 const char *buf)
1103{ 1120{
1104 struct cpuset trialcs;
1105 nodemask_t oldmem; 1121 nodemask_t oldmem;
1106 int retval; 1122 int retval;
1107 1123
@@ -1112,8 +1128,6 @@ static int update_nodemask(struct cpuset *cs, const char *buf)
1112 if (cs == &top_cpuset) 1128 if (cs == &top_cpuset)
1113 return -EACCES; 1129 return -EACCES;
1114 1130
1115 trialcs = *cs;
1116
1117 /* 1131 /*
1118 * An empty mems_allowed is ok iff there are no tasks in the cpuset. 1132 * An empty mems_allowed is ok iff there are no tasks in the cpuset.
1119 * Since nodelist_parse() fails on an empty mask, we special case 1133 * Since nodelist_parse() fails on an empty mask, we special case
@@ -1121,27 +1135,27 @@ static int update_nodemask(struct cpuset *cs, const char *buf)
1121 * with tasks have memory. 1135 * with tasks have memory.
1122 */ 1136 */
1123 if (!*buf) { 1137 if (!*buf) {
1124 nodes_clear(trialcs.mems_allowed); 1138 nodes_clear(trialcs->mems_allowed);
1125 } else { 1139 } else {
1126 retval = nodelist_parse(buf, trialcs.mems_allowed); 1140 retval = nodelist_parse(buf, trialcs->mems_allowed);
1127 if (retval < 0) 1141 if (retval < 0)
1128 goto done; 1142 goto done;
1129 1143
1130 if (!nodes_subset(trialcs.mems_allowed, 1144 if (!nodes_subset(trialcs->mems_allowed,
1131 node_states[N_HIGH_MEMORY])) 1145 node_states[N_HIGH_MEMORY]))
1132 return -EINVAL; 1146 return -EINVAL;
1133 } 1147 }
1134 oldmem = cs->mems_allowed; 1148 oldmem = cs->mems_allowed;
1135 if (nodes_equal(oldmem, trialcs.mems_allowed)) { 1149 if (nodes_equal(oldmem, trialcs->mems_allowed)) {
1136 retval = 0; /* Too easy - nothing to do */ 1150 retval = 0; /* Too easy - nothing to do */
1137 goto done; 1151 goto done;
1138 } 1152 }
1139 retval = validate_change(cs, &trialcs); 1153 retval = validate_change(cs, trialcs);
1140 if (retval < 0) 1154 if (retval < 0)
1141 goto done; 1155 goto done;
1142 1156
1143 mutex_lock(&callback_mutex); 1157 mutex_lock(&callback_mutex);
1144 cs->mems_allowed = trialcs.mems_allowed; 1158 cs->mems_allowed = trialcs->mems_allowed;
1145 cs->mems_generation = cpuset_mems_generation++; 1159 cs->mems_generation = cpuset_mems_generation++;
1146 mutex_unlock(&callback_mutex); 1160 mutex_unlock(&callback_mutex);
1147 1161
@@ -1181,31 +1195,36 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val)
1181static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, 1195static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
1182 int turning_on) 1196 int turning_on)
1183{ 1197{
1184 struct cpuset trialcs; 1198 struct cpuset *trialcs;
1185 int err; 1199 int err;
1186 int balance_flag_changed; 1200 int balance_flag_changed;
1187 1201
1188 trialcs = *cs; 1202 trialcs = alloc_trial_cpuset(cs);
1203 if (!trialcs)
1204 return -ENOMEM;
1205
1189 if (turning_on) 1206 if (turning_on)
1190 set_bit(bit, &trialcs.flags); 1207 set_bit(bit, &trialcs->flags);
1191 else 1208 else
1192 clear_bit(bit, &trialcs.flags); 1209 clear_bit(bit, &trialcs->flags);
1193 1210
1194 err = validate_change(cs, &trialcs); 1211 err = validate_change(cs, trialcs);
1195 if (err < 0) 1212 if (err < 0)
1196 return err; 1213 goto out;
1197 1214
1198 balance_flag_changed = (is_sched_load_balance(cs) != 1215 balance_flag_changed = (is_sched_load_balance(cs) !=
1199 is_sched_load_balance(&trialcs)); 1216 is_sched_load_balance(trialcs));
1200 1217
1201 mutex_lock(&callback_mutex); 1218 mutex_lock(&callback_mutex);
1202 cs->flags = trialcs.flags; 1219 cs->flags = trialcs->flags;
1203 mutex_unlock(&callback_mutex); 1220 mutex_unlock(&callback_mutex);
1204 1221
1205 if (!cpus_empty(trialcs.cpus_allowed) && balance_flag_changed) 1222 if (!cpus_empty(trialcs->cpus_allowed) && balance_flag_changed)
1206 async_rebuild_sched_domains(); 1223 async_rebuild_sched_domains();
1207 1224
1208 return 0; 1225out:
1226 free_trial_cpuset(trialcs);
1227 return err;
1209} 1228}
1210 1229
1211/* 1230/*
@@ -1453,21 +1472,29 @@ static int cpuset_write_resmask(struct cgroup *cgrp, struct cftype *cft,
1453 const char *buf) 1472 const char *buf)
1454{ 1473{
1455 int retval = 0; 1474 int retval = 0;
1475 struct cpuset *cs = cgroup_cs(cgrp);
1476 struct cpuset *trialcs;
1456 1477
1457 if (!cgroup_lock_live_group(cgrp)) 1478 if (!cgroup_lock_live_group(cgrp))
1458 return -ENODEV; 1479 return -ENODEV;
1459 1480
1481 trialcs = alloc_trial_cpuset(cs);
1482 if (!trialcs)
1483 return -ENOMEM;
1484
1460 switch (cft->private) { 1485 switch (cft->private) {
1461 case FILE_CPULIST: 1486 case FILE_CPULIST:
1462 retval = update_cpumask(cgroup_cs(cgrp), buf); 1487 retval = update_cpumask(cs, trialcs, buf);
1463 break; 1488 break;
1464 case FILE_MEMLIST: 1489 case FILE_MEMLIST:
1465 retval = update_nodemask(cgroup_cs(cgrp), buf); 1490 retval = update_nodemask(cs, trialcs, buf);
1466 break; 1491 break;
1467 default: 1492 default:
1468 retval = -EINVAL; 1493 retval = -EINVAL;
1469 break; 1494 break;
1470 } 1495 }
1496
1497 free_trial_cpuset(trialcs);
1471 cgroup_unlock(); 1498 cgroup_unlock();
1472 return retval; 1499 return retval;
1473} 1500}