diff options
| author | Li Zefan <lizf@cn.fujitsu.com> | 2009-01-07 21:08:43 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 11:31:11 -0500 |
| commit | 645fcc9d2f6946f97a41c8d00edee38f8a6f0060 (patch) | |
| tree | 1d7ad63c9e1bace8f0ccac8814be04af92441ebf /kernel | |
| parent | 2341d1b6598c7146d64a5050b53a72a5a819617f (diff) | |
cpuset: don't allocate trial cpuset on stack
Impact: cleanups, reduce stack usage
This patch prepares for the next patch. When we convert
cpuset.cpus_allowed to cpumask_var_t, (trialcs = *cs) no longer works.
Another result of this patch is reducing stack usage of trialcs.
sizeof(*cs) can be as large as 148 bytes on x86_64, so it's really not
good to have it on stack.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: Mike Travis <travis@sgi.com>
Cc: Paul Menage <menage@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cpuset.c | 93 |
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 | */ | ||
| 422 | static 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 | */ | ||
| 431 | static 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 | */ |
| 883 | static int update_cpumask(struct cpuset *cs, const char *buf) | 901 | static 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 | */ |
| 1102 | static int update_nodemask(struct cpuset *cs, const char *buf) | 1118 | static 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) | |||
| 1181 | static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, | 1195 | static 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; | 1225 | out: |
| 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 | } |
