diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpu.c | 28 | ||||
-rw-r--r-- | kernel/cpuset.c | 58 | ||||
-rw-r--r-- | kernel/exit.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 2 | ||||
-rw-r--r-- | kernel/sysctl.c | 25 | ||||
-rw-r--r-- | kernel/sysctl_binary.c | 9 |
6 files changed, 108 insertions, 16 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 545777574779..124ad9d6be16 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -326,6 +326,12 @@ out_notify: | |||
326 | int __cpuinit cpu_up(unsigned int cpu) | 326 | int __cpuinit cpu_up(unsigned int cpu) |
327 | { | 327 | { |
328 | int err = 0; | 328 | int err = 0; |
329 | |||
330 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
331 | int nid; | ||
332 | pg_data_t *pgdat; | ||
333 | #endif | ||
334 | |||
329 | if (!cpu_possible(cpu)) { | 335 | if (!cpu_possible(cpu)) { |
330 | printk(KERN_ERR "can't online cpu %d because it is not " | 336 | printk(KERN_ERR "can't online cpu %d because it is not " |
331 | "configured as may-hotadd at boot time\n", cpu); | 337 | "configured as may-hotadd at boot time\n", cpu); |
@@ -336,6 +342,28 @@ int __cpuinit cpu_up(unsigned int cpu) | |||
336 | return -EINVAL; | 342 | return -EINVAL; |
337 | } | 343 | } |
338 | 344 | ||
345 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
346 | nid = cpu_to_node(cpu); | ||
347 | if (!node_online(nid)) { | ||
348 | err = mem_online_node(nid); | ||
349 | if (err) | ||
350 | return err; | ||
351 | } | ||
352 | |||
353 | pgdat = NODE_DATA(nid); | ||
354 | if (!pgdat) { | ||
355 | printk(KERN_ERR | ||
356 | "Can't online cpu %d due to NULL pgdat\n", cpu); | ||
357 | return -ENOMEM; | ||
358 | } | ||
359 | |||
360 | if (pgdat->node_zonelists->_zonerefs->zone == NULL) { | ||
361 | mutex_lock(&zonelists_mutex); | ||
362 | build_all_zonelists(NULL); | ||
363 | mutex_unlock(&zonelists_mutex); | ||
364 | } | ||
365 | #endif | ||
366 | |||
339 | cpu_maps_update_begin(); | 367 | cpu_maps_update_begin(); |
340 | 368 | ||
341 | if (cpu_hotplug_disabled) { | 369 | if (cpu_hotplug_disabled) { |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 9a50c5f6e727..61d6af7fa676 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -946,16 +946,62 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from, | |||
946 | * In order to avoid seeing no nodes if the old and new nodes are disjoint, | 946 | * In order to avoid seeing no nodes if the old and new nodes are disjoint, |
947 | * we structure updates as setting all new allowed nodes, then clearing newly | 947 | * we structure updates as setting all new allowed nodes, then clearing newly |
948 | * disallowed ones. | 948 | * disallowed ones. |
949 | * | ||
950 | * Called with task's alloc_lock held | ||
951 | */ | 949 | */ |
952 | static void cpuset_change_task_nodemask(struct task_struct *tsk, | 950 | static void cpuset_change_task_nodemask(struct task_struct *tsk, |
953 | nodemask_t *newmems) | 951 | nodemask_t *newmems) |
954 | { | 952 | { |
953 | repeat: | ||
954 | /* | ||
955 | * Allow tasks that have access to memory reserves because they have | ||
956 | * been OOM killed to get memory anywhere. | ||
957 | */ | ||
958 | if (unlikely(test_thread_flag(TIF_MEMDIE))) | ||
959 | return; | ||
960 | if (current->flags & PF_EXITING) /* Let dying task have memory */ | ||
961 | return; | ||
962 | |||
963 | task_lock(tsk); | ||
955 | nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); | 964 | nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); |
956 | mpol_rebind_task(tsk, &tsk->mems_allowed); | 965 | mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1); |
957 | mpol_rebind_task(tsk, newmems); | 966 | |
967 | |||
968 | /* | ||
969 | * ensure checking ->mems_allowed_change_disable after setting all new | ||
970 | * allowed nodes. | ||
971 | * | ||
972 | * the read-side task can see an nodemask with new allowed nodes and | ||
973 | * old allowed nodes. and if it allocates page when cpuset clears newly | ||
974 | * disallowed ones continuous, it can see the new allowed bits. | ||
975 | * | ||
976 | * And if setting all new allowed nodes is after the checking, setting | ||
977 | * all new allowed nodes and clearing newly disallowed ones will be done | ||
978 | * continuous, and the read-side task may find no node to alloc page. | ||
979 | */ | ||
980 | smp_mb(); | ||
981 | |||
982 | /* | ||
983 | * Allocation of memory is very fast, we needn't sleep when waiting | ||
984 | * for the read-side. | ||
985 | */ | ||
986 | while (ACCESS_ONCE(tsk->mems_allowed_change_disable)) { | ||
987 | task_unlock(tsk); | ||
988 | if (!task_curr(tsk)) | ||
989 | yield(); | ||
990 | goto repeat; | ||
991 | } | ||
992 | |||
993 | /* | ||
994 | * ensure checking ->mems_allowed_change_disable before clearing all new | ||
995 | * disallowed nodes. | ||
996 | * | ||
997 | * if clearing newly disallowed bits before the checking, the read-side | ||
998 | * task may find no node to alloc page. | ||
999 | */ | ||
1000 | smp_mb(); | ||
1001 | |||
1002 | mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP2); | ||
958 | tsk->mems_allowed = *newmems; | 1003 | tsk->mems_allowed = *newmems; |
1004 | task_unlock(tsk); | ||
959 | } | 1005 | } |
960 | 1006 | ||
961 | /* | 1007 | /* |
@@ -978,9 +1024,7 @@ static void cpuset_change_nodemask(struct task_struct *p, | |||
978 | cs = cgroup_cs(scan->cg); | 1024 | cs = cgroup_cs(scan->cg); |
979 | guarantee_online_mems(cs, newmems); | 1025 | guarantee_online_mems(cs, newmems); |
980 | 1026 | ||
981 | task_lock(p); | ||
982 | cpuset_change_task_nodemask(p, newmems); | 1027 | cpuset_change_task_nodemask(p, newmems); |
983 | task_unlock(p); | ||
984 | 1028 | ||
985 | NODEMASK_FREE(newmems); | 1029 | NODEMASK_FREE(newmems); |
986 | 1030 | ||
@@ -1383,9 +1427,7 @@ static void cpuset_attach_task(struct task_struct *tsk, nodemask_t *to, | |||
1383 | err = set_cpus_allowed_ptr(tsk, cpus_attach); | 1427 | err = set_cpus_allowed_ptr(tsk, cpus_attach); |
1384 | WARN_ON_ONCE(err); | 1428 | WARN_ON_ONCE(err); |
1385 | 1429 | ||
1386 | task_lock(tsk); | ||
1387 | cpuset_change_task_nodemask(tsk, to); | 1430 | cpuset_change_task_nodemask(tsk, to); |
1388 | task_unlock(tsk); | ||
1389 | cpuset_update_task_spread_flag(cs, tsk); | 1431 | cpuset_update_task_spread_flag(cs, tsk); |
1390 | 1432 | ||
1391 | } | 1433 | } |
diff --git a/kernel/exit.c b/kernel/exit.c index eabca5a73a85..019a2843bf95 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -1002,8 +1002,10 @@ NORET_TYPE void do_exit(long code) | |||
1002 | 1002 | ||
1003 | exit_notify(tsk, group_dead); | 1003 | exit_notify(tsk, group_dead); |
1004 | #ifdef CONFIG_NUMA | 1004 | #ifdef CONFIG_NUMA |
1005 | task_lock(tsk); | ||
1005 | mpol_put(tsk->mempolicy); | 1006 | mpol_put(tsk->mempolicy); |
1006 | tsk->mempolicy = NULL; | 1007 | tsk->mempolicy = NULL; |
1008 | task_unlock(tsk); | ||
1007 | #endif | 1009 | #endif |
1008 | #ifdef CONFIG_FUTEX | 1010 | #ifdef CONFIG_FUTEX |
1009 | if (unlikely(current->pi_state_cache)) | 1011 | if (unlikely(current->pi_state_cache)) |
diff --git a/kernel/module.c b/kernel/module.c index a8014bfb5a4e..625985e70e9d 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -180,8 +180,6 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; | |||
180 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 180 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; |
181 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 181 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; |
182 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 182 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; |
183 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | ||
184 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | ||
185 | extern const unsigned long __start___kcrctab[]; | 183 | extern const unsigned long __start___kcrctab[]; |
186 | extern const unsigned long __start___kcrctab_gpl[]; | 184 | extern const unsigned long __start___kcrctab_gpl[]; |
187 | extern const unsigned long __start___kcrctab_gpl_future[]; | 185 | extern const unsigned long __start___kcrctab_gpl_future[]; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4c93486b45d1..84ff5e75c084 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/highuid.h> | 37 | #include <linux/highuid.h> |
38 | #include <linux/writeback.h> | 38 | #include <linux/writeback.h> |
39 | #include <linux/ratelimit.h> | 39 | #include <linux/ratelimit.h> |
40 | #include <linux/compaction.h> | ||
40 | #include <linux/hugetlb.h> | 41 | #include <linux/hugetlb.h> |
41 | #include <linux/initrd.h> | 42 | #include <linux/initrd.h> |
42 | #include <linux/key.h> | 43 | #include <linux/key.h> |
@@ -262,6 +263,11 @@ static int min_sched_shares_ratelimit = 100000; /* 100 usec */ | |||
262 | static int max_sched_shares_ratelimit = NSEC_PER_SEC; /* 1 second */ | 263 | static int max_sched_shares_ratelimit = NSEC_PER_SEC; /* 1 second */ |
263 | #endif | 264 | #endif |
264 | 265 | ||
266 | #ifdef CONFIG_COMPACTION | ||
267 | static int min_extfrag_threshold; | ||
268 | static int max_extfrag_threshold = 1000; | ||
269 | #endif | ||
270 | |||
265 | static struct ctl_table kern_table[] = { | 271 | static struct ctl_table kern_table[] = { |
266 | { | 272 | { |
267 | .procname = "sched_child_runs_first", | 273 | .procname = "sched_child_runs_first", |
@@ -1121,6 +1127,25 @@ static struct ctl_table vm_table[] = { | |||
1121 | .mode = 0644, | 1127 | .mode = 0644, |
1122 | .proc_handler = drop_caches_sysctl_handler, | 1128 | .proc_handler = drop_caches_sysctl_handler, |
1123 | }, | 1129 | }, |
1130 | #ifdef CONFIG_COMPACTION | ||
1131 | { | ||
1132 | .procname = "compact_memory", | ||
1133 | .data = &sysctl_compact_memory, | ||
1134 | .maxlen = sizeof(int), | ||
1135 | .mode = 0200, | ||
1136 | .proc_handler = sysctl_compaction_handler, | ||
1137 | }, | ||
1138 | { | ||
1139 | .procname = "extfrag_threshold", | ||
1140 | .data = &sysctl_extfrag_threshold, | ||
1141 | .maxlen = sizeof(int), | ||
1142 | .mode = 0644, | ||
1143 | .proc_handler = sysctl_extfrag_handler, | ||
1144 | .extra1 = &min_extfrag_threshold, | ||
1145 | .extra2 = &max_extfrag_threshold, | ||
1146 | }, | ||
1147 | |||
1148 | #endif /* CONFIG_COMPACTION */ | ||
1124 | { | 1149 | { |
1125 | .procname = "min_free_kbytes", | 1150 | .procname = "min_free_kbytes", |
1126 | .data = &min_free_kbytes, | 1151 | .data = &min_free_kbytes, |
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index 937d31dc8566..1357c5786064 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/file.h> | 13 | #include <linux/file.h> |
14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/kernel.h> | ||
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | 18 | ||
18 | #ifdef CONFIG_SYSCTL_SYSCALL | 19 | #ifdef CONFIG_SYSCTL_SYSCALL |
@@ -1124,11 +1125,6 @@ out: | |||
1124 | return result; | 1125 | return result; |
1125 | } | 1126 | } |
1126 | 1127 | ||
1127 | static unsigned hex_value(int ch) | ||
1128 | { | ||
1129 | return isdigit(ch) ? ch - '0' : ((ch | 0x20) - 'a') + 10; | ||
1130 | } | ||
1131 | |||
1132 | static ssize_t bin_uuid(struct file *file, | 1128 | static ssize_t bin_uuid(struct file *file, |
1133 | void __user *oldval, size_t oldlen, void __user *newval, size_t newlen) | 1129 | void __user *oldval, size_t oldlen, void __user *newval, size_t newlen) |
1134 | { | 1130 | { |
@@ -1156,7 +1152,8 @@ static ssize_t bin_uuid(struct file *file, | |||
1156 | if (!isxdigit(str[0]) || !isxdigit(str[1])) | 1152 | if (!isxdigit(str[0]) || !isxdigit(str[1])) |
1157 | goto out; | 1153 | goto out; |
1158 | 1154 | ||
1159 | uuid[i] = (hex_value(str[0]) << 4) | hex_value(str[1]); | 1155 | uuid[i] = (hex_to_bin(str[0]) << 4) | |
1156 | hex_to_bin(str[1]); | ||
1160 | str += 2; | 1157 | str += 2; |
1161 | if (*str == '-') | 1158 | if (*str == '-') |
1162 | str++; | 1159 | str++; |