aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/mmap.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index 5485f18e6631..43c4955535aa 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -33,6 +33,8 @@
33#include <linux/uprobes.h> 33#include <linux/uprobes.h>
34#include <linux/rbtree_augmented.h> 34#include <linux/rbtree_augmented.h>
35#include <linux/sched/sysctl.h> 35#include <linux/sched/sysctl.h>
36#include <linux/notifier.h>
37#include <linux/memory.h>
36 38
37#include <asm/uaccess.h> 39#include <asm/uaccess.h>
38#include <asm/cacheflush.h> 40#include <asm/cacheflush.h>
@@ -3110,7 +3112,7 @@ void __init mmap_init(void)
3110 * The default value is min(3% of free memory, 128MB) 3112 * The default value is min(3% of free memory, 128MB)
3111 * 128MB is enough to recover with sshd/login, bash, and top/kill. 3113 * 128MB is enough to recover with sshd/login, bash, and top/kill.
3112 */ 3114 */
3113static int __meminit init_user_reserve(void) 3115static int init_user_reserve(void)
3114{ 3116{
3115 unsigned long free_kbytes; 3117 unsigned long free_kbytes;
3116 3118
@@ -3131,7 +3133,7 @@ module_init(init_user_reserve)
3131 * with sshd, bash, and top in OVERCOMMIT_GUESS. Smaller systems will 3133 * with sshd, bash, and top in OVERCOMMIT_GUESS. Smaller systems will
3132 * only reserve 3% of free pages by default. 3134 * only reserve 3% of free pages by default.
3133 */ 3135 */
3134static int __meminit init_admin_reserve(void) 3136static int init_admin_reserve(void)
3135{ 3137{
3136 unsigned long free_kbytes; 3138 unsigned long free_kbytes;
3137 3139
@@ -3141,3 +3143,73 @@ static int __meminit init_admin_reserve(void)
3141 return 0; 3143 return 0;
3142} 3144}
3143module_init(init_admin_reserve) 3145module_init(init_admin_reserve)
3146
3147/*
3148 * Reinititalise user and admin reserves if memory is added or removed.
3149 *
3150 * The default user reserve max is 128MB, and the default max for the
3151 * admin reserve is 8MB. These are usually, but not always, enough to
3152 * enable recovery from a memory hogging process using login/sshd, a shell,
3153 * and tools like top. It may make sense to increase or even disable the
3154 * reserve depending on the existence of swap or variations in the recovery
3155 * tools. So, the admin may have changed them.
3156 *
3157 * If memory is added and the reserves have been eliminated or increased above
3158 * the default max, then we'll trust the admin.
3159 *
3160 * If memory is removed and there isn't enough free memory, then we
3161 * need to reset the reserves.
3162 *
3163 * Otherwise keep the reserve set by the admin.
3164 */
3165static int reserve_mem_notifier(struct notifier_block *nb,
3166 unsigned long action, void *data)
3167{
3168 unsigned long tmp, free_kbytes;
3169
3170 switch (action) {
3171 case MEM_ONLINE:
3172 /* Default max is 128MB. Leave alone if modified by operator. */
3173 tmp = sysctl_user_reserve_kbytes;
3174 if (0 < tmp && tmp < (1UL << 17))
3175 init_user_reserve();
3176
3177 /* Default max is 8MB. Leave alone if modified by operator. */
3178 tmp = sysctl_admin_reserve_kbytes;
3179 if (0 < tmp && tmp < (1UL << 13))
3180 init_admin_reserve();
3181
3182 break;
3183 case MEM_OFFLINE:
3184 free_kbytes = global_page_state(NR_FREE_PAGES) << (PAGE_SHIFT - 10);
3185
3186 if (sysctl_user_reserve_kbytes > free_kbytes) {
3187 init_user_reserve();
3188 pr_info("vm.user_reserve_kbytes reset to %lu\n",
3189 sysctl_user_reserve_kbytes);
3190 }
3191
3192 if (sysctl_admin_reserve_kbytes > free_kbytes) {
3193 init_admin_reserve();
3194 pr_info("vm.admin_reserve_kbytes reset to %lu\n",
3195 sysctl_admin_reserve_kbytes);
3196 }
3197 break;
3198 default:
3199 break;
3200 }
3201 return NOTIFY_OK;
3202}
3203
3204static struct notifier_block reserve_mem_nb = {
3205 .notifier_call = reserve_mem_notifier,
3206};
3207
3208static int __meminit init_reserve_notifier(void)
3209{
3210 if (register_hotmemory_notifier(&reserve_mem_nb))
3211 printk("Failed registering memory add/remove notifier for admin reserve");
3212
3213 return 0;
3214}
3215module_init(init_reserve_notifier)