aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-08 00:38:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-08 00:38:00 -0400
commitb66484cd74706fa8681d051840fe4b18a3da40ff (patch)
treee8215e7c25661d25f84abc4b98140c2062d6d5de /kernel
parentc913fc4146ba7c280e074558d0a461e5c6f07c8a (diff)
parent05fd007e46296afb24d15c7d589d535e5a5b9d5c (diff)
Merge branch 'akpm' (patches from Andrew)
Merge updates from Andrew Morton: - fsnotify updates - ocfs2 updates - all of MM * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (127 commits) console: don't prefer first registered if DT specifies stdout-path cred: simpler, 1D supplementary groups CREDITS: update Pavel's information, add GPG key, remove snail mail address mailmap: add Johan Hovold .gitattributes: set git diff driver for C source code files uprobes: remove function declarations from arch/{mips,s390} spelling.txt: "modeled" is spelt correctly nmi_backtrace: generate one-line reports for idle cpus arch/tile: adopt the new nmi_backtrace framework nmi_backtrace: do a local dump_stack() instead of a self-NMI nmi_backtrace: add more trigger_*_cpu_backtrace() methods min/max: remove sparse warnings when they're nested Documentation/filesystems/proc.txt: add more description for maps/smaps mm, proc: fix region lost in /proc/self/smaps proc: fix timerslack_ns CAP_SYS_NICE check when adjusting self proc: add LSM hook checks to /proc/<tid>/timerslack_ns proc: relax /proc/<tid>/timerslack_ns capability requirements meminfo: break apart a very long seq_printf with #ifdefs seq/proc: modify seq_put_decimal_[u]ll to take a const char *, not char proc: faster /proc/*/status ...
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c8
-rw-r--r--kernel/groups.c67
-rw-r--r--kernel/power/process.c17
-rw-r--r--kernel/printk/printk.c13
-rw-r--r--kernel/sched/idle.c13
-rw-r--r--kernel/uid16.c4
7 files changed, 58 insertions, 66 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 1e1d913914c0..9d68c45ebbe3 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -511,7 +511,7 @@ static void exit_mm(struct task_struct *tsk)
511 mm_update_next_owner(mm); 511 mm_update_next_owner(mm);
512 mmput(mm); 512 mmput(mm);
513 if (test_thread_flag(TIF_MEMDIE)) 513 if (test_thread_flag(TIF_MEMDIE))
514 exit_oom_victim(tsk); 514 exit_oom_victim();
515} 515}
516 516
517static struct task_struct *find_alive_thread(struct task_struct *p) 517static struct task_struct *find_alive_thread(struct task_struct *p)
diff --git a/kernel/fork.c b/kernel/fork.c
index 9a05bd93f8e7..6d42242485cb 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -359,6 +359,12 @@ static inline void free_signal_struct(struct signal_struct *sig)
359{ 359{
360 taskstats_tgid_free(sig); 360 taskstats_tgid_free(sig);
361 sched_autogroup_exit(sig); 361 sched_autogroup_exit(sig);
362 /*
363 * __mmdrop is not safe to call from softirq context on x86 due to
364 * pgd_dtor so postpone it to the async context
365 */
366 if (sig->oom_mm)
367 mmdrop_async(sig->oom_mm);
362 kmem_cache_free(signal_cachep, sig); 368 kmem_cache_free(signal_cachep, sig);
363} 369}
364 370
@@ -848,6 +854,7 @@ static inline void __mmput(struct mm_struct *mm)
848 ksm_exit(mm); 854 ksm_exit(mm);
849 khugepaged_exit(mm); /* must run before exit_mmap */ 855 khugepaged_exit(mm); /* must run before exit_mmap */
850 exit_mmap(mm); 856 exit_mmap(mm);
857 mm_put_huge_zero_page(mm);
851 set_mm_exe_file(mm, NULL); 858 set_mm_exe_file(mm, NULL);
852 if (!list_empty(&mm->mmlist)) { 859 if (!list_empty(&mm->mmlist)) {
853 spin_lock(&mmlist_lock); 860 spin_lock(&mmlist_lock);
@@ -856,6 +863,7 @@ static inline void __mmput(struct mm_struct *mm)
856 } 863 }
857 if (mm->binfmt) 864 if (mm->binfmt)
858 module_put(mm->binfmt->module); 865 module_put(mm->binfmt->module);
866 set_bit(MMF_OOM_SKIP, &mm->flags);
859 mmdrop(mm); 867 mmdrop(mm);
860} 868}
861 869
diff --git a/kernel/groups.c b/kernel/groups.c
index 74d431d25251..2fcadd66a8fd 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -7,55 +7,31 @@
7#include <linux/security.h> 7#include <linux/security.h>
8#include <linux/syscalls.h> 8#include <linux/syscalls.h>
9#include <linux/user_namespace.h> 9#include <linux/user_namespace.h>
10#include <linux/vmalloc.h>
10#include <asm/uaccess.h> 11#include <asm/uaccess.h>
11 12
12struct group_info *groups_alloc(int gidsetsize) 13struct group_info *groups_alloc(int gidsetsize)
13{ 14{
14 struct group_info *group_info; 15 struct group_info *gi;
15 int nblocks; 16 unsigned int len;
16 int i; 17
17 18 len = sizeof(struct group_info) + sizeof(kgid_t) * gidsetsize;
18 nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK; 19 gi = kmalloc(len, GFP_KERNEL_ACCOUNT|__GFP_NOWARN|__GFP_NORETRY);
19 /* Make sure we always allocate at least one indirect block pointer */ 20 if (!gi)
20 nblocks = nblocks ? : 1; 21 gi = __vmalloc(len, GFP_KERNEL_ACCOUNT|__GFP_HIGHMEM, PAGE_KERNEL);
21 group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER); 22 if (!gi)
22 if (!group_info)
23 return NULL; 23 return NULL;
24 group_info->ngroups = gidsetsize;
25 group_info->nblocks = nblocks;
26 atomic_set(&group_info->usage, 1);
27
28 if (gidsetsize <= NGROUPS_SMALL)
29 group_info->blocks[0] = group_info->small_block;
30 else {
31 for (i = 0; i < nblocks; i++) {
32 kgid_t *b;
33 b = (void *)__get_free_page(GFP_USER);
34 if (!b)
35 goto out_undo_partial_alloc;
36 group_info->blocks[i] = b;
37 }
38 }
39 return group_info;
40 24
41out_undo_partial_alloc: 25 atomic_set(&gi->usage, 1);
42 while (--i >= 0) { 26 gi->ngroups = gidsetsize;
43 free_page((unsigned long)group_info->blocks[i]); 27 return gi;
44 }
45 kfree(group_info);
46 return NULL;
47} 28}
48 29
49EXPORT_SYMBOL(groups_alloc); 30EXPORT_SYMBOL(groups_alloc);
50 31
51void groups_free(struct group_info *group_info) 32void groups_free(struct group_info *group_info)
52{ 33{
53 if (group_info->blocks[0] != group_info->small_block) { 34 kvfree(group_info);
54 int i;
55 for (i = 0; i < group_info->nblocks; i++)
56 free_page((unsigned long)group_info->blocks[i]);
57 }
58 kfree(group_info);
59} 35}
60 36
61EXPORT_SYMBOL(groups_free); 37EXPORT_SYMBOL(groups_free);
@@ -70,7 +46,7 @@ static int groups_to_user(gid_t __user *grouplist,
70 46
71 for (i = 0; i < count; i++) { 47 for (i = 0; i < count; i++) {
72 gid_t gid; 48 gid_t gid;
73 gid = from_kgid_munged(user_ns, GROUP_AT(group_info, i)); 49 gid = from_kgid_munged(user_ns, group_info->gid[i]);
74 if (put_user(gid, grouplist+i)) 50 if (put_user(gid, grouplist+i))
75 return -EFAULT; 51 return -EFAULT;
76 } 52 }
@@ -95,7 +71,7 @@ static int groups_from_user(struct group_info *group_info,
95 if (!gid_valid(kgid)) 71 if (!gid_valid(kgid))
96 return -EINVAL; 72 return -EINVAL;
97 73
98 GROUP_AT(group_info, i) = kgid; 74 group_info->gid[i] = kgid;
99 } 75 }
100 return 0; 76 return 0;
101} 77}
@@ -115,15 +91,14 @@ static void groups_sort(struct group_info *group_info)
115 for (base = 0; base < max; base++) { 91 for (base = 0; base < max; base++) {
116 int left = base; 92 int left = base;
117 int right = left + stride; 93 int right = left + stride;
118 kgid_t tmp = GROUP_AT(group_info, right); 94 kgid_t tmp = group_info->gid[right];
119 95
120 while (left >= 0 && gid_gt(GROUP_AT(group_info, left), tmp)) { 96 while (left >= 0 && gid_gt(group_info->gid[left], tmp)) {
121 GROUP_AT(group_info, right) = 97 group_info->gid[right] = group_info->gid[left];
122 GROUP_AT(group_info, left);
123 right = left; 98 right = left;
124 left -= stride; 99 left -= stride;
125 } 100 }
126 GROUP_AT(group_info, right) = tmp; 101 group_info->gid[right] = tmp;
127 } 102 }
128 stride /= 3; 103 stride /= 3;
129 } 104 }
@@ -141,9 +116,9 @@ int groups_search(const struct group_info *group_info, kgid_t grp)
141 right = group_info->ngroups; 116 right = group_info->ngroups;
142 while (left < right) { 117 while (left < right) {
143 unsigned int mid = (left+right)/2; 118 unsigned int mid = (left+right)/2;
144 if (gid_gt(grp, GROUP_AT(group_info, mid))) 119 if (gid_gt(grp, group_info->gid[mid]))
145 left = mid + 1; 120 left = mid + 1;
146 else if (gid_lt(grp, GROUP_AT(group_info, mid))) 121 else if (gid_lt(grp, group_info->gid[mid]))
147 right = mid; 122 right = mid;
148 else 123 else
149 return 1; 124 return 1;
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 8f27d5a8adf6..2fba066e125f 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -144,23 +144,12 @@ int freeze_processes(void)
144 /* 144 /*
145 * Now that the whole userspace is frozen we need to disbale 145 * Now that the whole userspace is frozen we need to disbale
146 * the OOM killer to disallow any further interference with 146 * the OOM killer to disallow any further interference with
147 * killable tasks. 147 * killable tasks. There is no guarantee oom victims will
148 * ever reach a point they go away we have to wait with a timeout.
148 */ 149 */
149 if (!error && !oom_killer_disable()) 150 if (!error && !oom_killer_disable(msecs_to_jiffies(freeze_timeout_msecs)))
150 error = -EBUSY; 151 error = -EBUSY;
151 152
152 /*
153 * There is a hard to fix race between oom_reaper kernel thread
154 * and oom_killer_disable. oom_reaper calls exit_oom_victim
155 * before the victim reaches exit_mm so try to freeze all the tasks
156 * again and catch such a left over task.
157 */
158 if (!error) {
159 pr_info("Double checking all user space processes after OOM killer disable... ");
160 error = try_to_freeze_tasks(true);
161 pr_cont("\n");
162 }
163
164 if (error) 153 if (error)
165 thaw_processes(); 154 thaw_processes();
166 return error; 155 return error;
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index eea6dbc2d8cf..8019cc0d3a73 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -253,6 +253,17 @@ static int preferred_console = -1;
253int console_set_on_cmdline; 253int console_set_on_cmdline;
254EXPORT_SYMBOL(console_set_on_cmdline); 254EXPORT_SYMBOL(console_set_on_cmdline);
255 255
256#ifdef CONFIG_OF
257static bool of_specified_console;
258
259void console_set_by_of(void)
260{
261 of_specified_console = true;
262}
263#else
264# define of_specified_console false
265#endif
266
256/* Flag: console code may call schedule() */ 267/* Flag: console code may call schedule() */
257static int console_may_schedule; 268static int console_may_schedule;
258 269
@@ -2647,7 +2658,7 @@ void register_console(struct console *newcon)
2647 * didn't select a console we take the first one 2658 * didn't select a console we take the first one
2648 * that registers here. 2659 * that registers here.
2649 */ 2660 */
2650 if (preferred_console < 0) { 2661 if (preferred_console < 0 && !of_specified_console) {
2651 if (newcon->index < 0) 2662 if (newcon->index < 0)
2652 newcon->index = 0; 2663 newcon->index = 0;
2653 if (newcon->setup == NULL || 2664 if (newcon->setup == NULL ||
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 9fb873cfc75c..1d8718d5300d 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -16,6 +16,9 @@
16 16
17#include "sched.h" 17#include "sched.h"
18 18
19/* Linker adds these: start and end of __cpuidle functions */
20extern char __cpuidle_text_start[], __cpuidle_text_end[];
21
19/** 22/**
20 * sched_idle_set_state - Record idle state for the current CPU. 23 * sched_idle_set_state - Record idle state for the current CPU.
21 * @idle_state: State to record. 24 * @idle_state: State to record.
@@ -53,7 +56,7 @@ static int __init cpu_idle_nopoll_setup(char *__unused)
53__setup("hlt", cpu_idle_nopoll_setup); 56__setup("hlt", cpu_idle_nopoll_setup);
54#endif 57#endif
55 58
56static inline int cpu_idle_poll(void) 59static noinline int __cpuidle cpu_idle_poll(void)
57{ 60{
58 rcu_idle_enter(); 61 rcu_idle_enter();
59 trace_cpu_idle_rcuidle(0, smp_processor_id()); 62 trace_cpu_idle_rcuidle(0, smp_processor_id());
@@ -84,7 +87,7 @@ void __weak arch_cpu_idle(void)
84 * 87 *
85 * To use when the cpuidle framework cannot be used. 88 * To use when the cpuidle framework cannot be used.
86 */ 89 */
87void default_idle_call(void) 90void __cpuidle default_idle_call(void)
88{ 91{
89 if (current_clr_polling_and_test()) { 92 if (current_clr_polling_and_test()) {
90 local_irq_enable(); 93 local_irq_enable();
@@ -271,6 +274,12 @@ static void cpu_idle_loop(void)
271 } 274 }
272} 275}
273 276
277bool cpu_in_idle(unsigned long pc)
278{
279 return pc >= (unsigned long)__cpuidle_text_start &&
280 pc < (unsigned long)__cpuidle_text_end;
281}
282
274void cpu_startup_entry(enum cpuhp_state state) 283void cpu_startup_entry(enum cpuhp_state state)
275{ 284{
276 /* 285 /*
diff --git a/kernel/uid16.c b/kernel/uid16.c
index d58cc4d8f0d1..cc40793464e3 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -117,7 +117,7 @@ static int groups16_to_user(old_gid_t __user *grouplist,
117 kgid_t kgid; 117 kgid_t kgid;
118 118
119 for (i = 0; i < group_info->ngroups; i++) { 119 for (i = 0; i < group_info->ngroups; i++) {
120 kgid = GROUP_AT(group_info, i); 120 kgid = group_info->gid[i];
121 group = high2lowgid(from_kgid_munged(user_ns, kgid)); 121 group = high2lowgid(from_kgid_munged(user_ns, kgid));
122 if (put_user(group, grouplist+i)) 122 if (put_user(group, grouplist+i))
123 return -EFAULT; 123 return -EFAULT;
@@ -142,7 +142,7 @@ static int groups16_from_user(struct group_info *group_info,
142 if (!gid_valid(kgid)) 142 if (!gid_valid(kgid))
143 return -EINVAL; 143 return -EINVAL;
144 144
145 GROUP_AT(group_info, i) = kgid; 145 group_info->gid[i] = kgid;
146 } 146 }
147 147
148 return 0; 148 return 0;