Commit 56d93842 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Replace MAX_MAP_COUNT with /proc/sys/vm/max_map_count

From: David Mosberger <davidm@napali.hpl.hp.com>

Below is a warmed up version of a patch originally done by Werner Almesberger
(see http://tinyurl.com/25zra) to replace the MAX_MAP_COUNT limit with a
sysctl variable.  I thought this had gone into the tree a long time ago but
alas it has not and as luck would have it, the hard limit bit someone today
once again with a large app on a large machine.

Here is a small test app:
parent bc5c1743
...@@ -22,6 +22,7 @@ Currently, these files are in /proc/sys/vm: ...@@ -22,6 +22,7 @@ Currently, these files are in /proc/sys/vm:
- dirty_background_ratio - dirty_background_ratio
- dirty_expire_centisecs - dirty_expire_centisecs
- dirty_writeback_centisecs - dirty_writeback_centisecs
- max_map_count
- min_free_kbytes - min_free_kbytes
============================================================== ==============================================================
...@@ -77,6 +78,21 @@ for swap because we only cluster swap data in 32-page groups. ...@@ -77,6 +78,21 @@ for swap because we only cluster swap data in 32-page groups.
============================================================== ==============================================================
max_map_count:
This file contains the maximum number of memory map areas a process
may have. Memory map areas are used as a side-effect of calling
malloc, directly by mmap and mprotect, and also when loading shared
libraries.
While most applications need less than a thousand maps, certain
programs, particularly malloc debuggers, may consume lots of them,
e.g., up to one or two maps per allocation.
The default value is 65536.
==============================================================
min_free_kbytes: min_free_kbytes:
This is used to force the Linux VM to keep a minimum number This is used to force the Linux VM to keep a minimum number
......
...@@ -179,7 +179,9 @@ asmlinkage void schedule(void); ...@@ -179,7 +179,9 @@ asmlinkage void schedule(void);
struct namespace; struct namespace;
/* Maximum number of active map areas.. This is a random (large) number */ /* Maximum number of active map areas.. This is a random (large) number */
#define MAX_MAP_COUNT (65536) #define DEFAULT_MAX_MAP_COUNT 65536
extern int sysctl_max_map_count;
#include <linux/aio.h> #include <linux/aio.h>
......
...@@ -158,6 +158,7 @@ enum ...@@ -158,6 +158,7 @@ enum
VM_SWAPPINESS=19, /* Tendency to steal mapped memory */ VM_SWAPPINESS=19, /* Tendency to steal mapped memory */
VM_LOWER_ZONE_PROTECTION=20,/* Amount of protection of lower zones */ VM_LOWER_ZONE_PROTECTION=20,/* Amount of protection of lower zones */
VM_MIN_FREE_KBYTES=21, /* Minimum free kilobytes to maintain */ VM_MIN_FREE_KBYTES=21, /* Minimum free kilobytes to maintain */
VM_MAX_MAP_COUNT=22, /* int: Maximum number of mmaps/address-space */
}; };
......
...@@ -736,6 +736,14 @@ static ctl_table vm_table[] = { ...@@ -736,6 +736,14 @@ static ctl_table vm_table[] = {
.strategy = &sysctl_intvec, .strategy = &sysctl_intvec,
.extra1 = &zero, .extra1 = &zero,
}, },
{
.ctl_name = VM_MAX_MAP_COUNT,
.procname = "max_map_count",
.data = &sysctl_max_map_count,
.maxlen = sizeof(sysctl_max_map_count),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{ .ctl_name = 0 } { .ctl_name = 0 }
}; };
......
...@@ -54,10 +54,12 @@ pgprot_t protection_map[16] = { ...@@ -54,10 +54,12 @@ pgprot_t protection_map[16] = {
int sysctl_overcommit_memory = 0; /* default is heuristic overcommit */ int sysctl_overcommit_memory = 0; /* default is heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_overcommit_ratio = 50; /* default is 50% */
int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
atomic_t vm_committed_space = ATOMIC_INIT(0); atomic_t vm_committed_space = ATOMIC_INIT(0);
EXPORT_SYMBOL(sysctl_overcommit_memory); EXPORT_SYMBOL(sysctl_overcommit_memory);
EXPORT_SYMBOL(sysctl_overcommit_ratio); EXPORT_SYMBOL(sysctl_overcommit_ratio);
EXPORT_SYMBOL(sysctl_max_map_count);
EXPORT_SYMBOL(vm_committed_space); EXPORT_SYMBOL(vm_committed_space);
/* /*
...@@ -516,7 +518,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, ...@@ -516,7 +518,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
return -EINVAL; return -EINVAL;
/* Too many mappings? */ /* Too many mappings? */
if (mm->map_count > MAX_MAP_COUNT) if (mm->map_count > sysctl_max_map_count)
return -ENOMEM; return -ENOMEM;
/* Obtain the address to map to. we verify (or select) it and ensure /* Obtain the address to map to. we verify (or select) it and ensure
...@@ -1203,7 +1205,7 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, ...@@ -1203,7 +1205,7 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
struct vm_area_struct *new; struct vm_area_struct *new;
struct address_space *mapping = NULL; struct address_space *mapping = NULL;
if (mm->map_count >= MAX_MAP_COUNT) if (mm->map_count >= sysctl_max_map_count)
return -ENOMEM; return -ENOMEM;
new = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); new = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
...@@ -1381,7 +1383,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) ...@@ -1381,7 +1383,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
> current->rlim[RLIMIT_AS].rlim_cur) > current->rlim[RLIMIT_AS].rlim_cur)
return -ENOMEM; return -ENOMEM;
if (mm->map_count > MAX_MAP_COUNT) if (mm->map_count > sysctl_max_map_count)
return -ENOMEM; return -ENOMEM;
if (security_vm_enough_memory(len >> PAGE_SHIFT)) if (security_vm_enough_memory(len >> PAGE_SHIFT))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment