Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kernel/sysctl.c: threads-max observe limits

Users can change the maximum number of threads by writing to
/proc/sys/kernel/threads-max.

With the patch the value entered is checked against the same limits that
apply when fork_init is called.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Heinrich Schuchardt and committed by
Linus Torvalds
16db3d3f ac1b398d

+34 -6
+3
include/linux/sysctl.h
··· 212 212 213 213 #endif /* CONFIG_SYSCTL */ 214 214 215 + int sysctl_max_threads(struct ctl_table *table, int write, 216 + void __user *buffer, size_t *lenp, loff_t *ppos); 217 + 215 218 #endif /* _LINUX_SYSCTL_H */
+29 -2
kernel/fork.c
··· 74 74 #include <linux/uprobes.h> 75 75 #include <linux/aio.h> 76 76 #include <linux/compiler.h> 77 + #include <linux/sysctl.h> 77 78 78 79 #include <asm/pgtable.h> 79 80 #include <asm/pgalloc.h> ··· 267 266 /* 268 267 * set_max_threads 269 268 */ 270 - static void set_max_threads(void) 269 + static void set_max_threads(unsigned int max_threads_suggested) 271 270 { 272 271 u64 threads; 273 272 ··· 280 279 else 281 280 threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, 282 281 (u64) THREAD_SIZE * 8UL); 282 + 283 + if (threads > max_threads_suggested) 284 + threads = max_threads_suggested; 283 285 284 286 max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); 285 287 } ··· 302 298 /* do the arch specific task caches init */ 303 299 arch_task_cache_init(); 304 300 305 - set_max_threads(); 301 + set_max_threads(MAX_THREADS); 306 302 307 303 init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2; 308 304 init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2; ··· 2022 2018 task_lock(task); 2023 2019 task->files = copy; 2024 2020 task_unlock(task); 2021 + return 0; 2022 + } 2023 + 2024 + int sysctl_max_threads(struct ctl_table *table, int write, 2025 + void __user *buffer, size_t *lenp, loff_t *ppos) 2026 + { 2027 + struct ctl_table t; 2028 + int ret; 2029 + int threads = max_threads; 2030 + int min = MIN_THREADS; 2031 + int max = MAX_THREADS; 2032 + 2033 + t = *table; 2034 + t.data = &threads; 2035 + t.extra1 = &min; 2036 + t.extra2 = &max; 2037 + 2038 + ret = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); 2039 + if (ret || !write) 2040 + return ret; 2041 + 2042 + set_max_threads(threads); 2043 + 2025 2044 return 0; 2026 2045 }
+2 -4
kernel/sysctl.c
··· 93 93 #include <linux/nmi.h> 94 94 #endif 95 95 96 - 97 96 #if defined(CONFIG_SYSCTL) 98 97 99 98 /* External variables not in a header file. */ 100 - extern int max_threads; 101 99 extern int suid_dumpable; 102 100 #ifdef CONFIG_COREDUMP 103 101 extern int core_uses_pid; ··· 708 710 #endif 709 711 { 710 712 .procname = "threads-max", 711 - .data = &max_threads, 713 + .data = NULL, 712 714 .maxlen = sizeof(int), 713 715 .mode = 0644, 714 - .proc_handler = proc_dointvec, 716 + .proc_handler = sysctl_max_threads, 715 717 }, 716 718 { 717 719 .procname = "random",