diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/Kconfig | 28 | ||||
-rw-r--r-- | mm/madvise.c | 8 | ||||
-rw-r--r-- | mm/nommu.c | 4 | ||||
-rw-r--r-- | mm/oom_kill.c | 44 | ||||
-rw-r--r-- | mm/page_alloc.c | 20 | ||||
-rw-r--r-- | mm/vmalloc.c | 1 |
6 files changed, 78 insertions, 27 deletions
diff --git a/mm/Kconfig b/mm/Kconfig index 57971d2ab848..c2b57d81e153 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -225,3 +225,31 @@ config HAVE_MLOCKED_PAGE_BIT | |||
225 | 225 | ||
226 | config MMU_NOTIFIER | 226 | config MMU_NOTIFIER |
227 | bool | 227 | bool |
228 | |||
229 | config NOMMU_INITIAL_TRIM_EXCESS | ||
230 | int "Turn on mmap() excess space trimming before booting" | ||
231 | depends on !MMU | ||
232 | default 1 | ||
233 | help | ||
234 | The NOMMU mmap() frequently needs to allocate large contiguous chunks | ||
235 | of memory on which to store mappings, but it can only ask the system | ||
236 | allocator for chunks in 2^N*PAGE_SIZE amounts - which is frequently | ||
237 | more than it requires. To deal with this, mmap() is able to trim off | ||
238 | the excess and return it to the allocator. | ||
239 | |||
240 | If trimming is enabled, the excess is trimmed off and returned to the | ||
241 | system allocator, which can cause extra fragmentation, particularly | ||
242 | if there are a lot of transient processes. | ||
243 | |||
244 | If trimming is disabled, the excess is kept, but not used, which for | ||
245 | long-term mappings means that the space is wasted. | ||
246 | |||
247 | Trimming can be dynamically controlled through a sysctl option | ||
248 | (/proc/sys/vm/nr_trim_pages) which specifies the minimum number of | ||
249 | excess pages there must be before trimming should occur, or zero if | ||
250 | no trimming is to occur. | ||
251 | |||
252 | This option specifies the initial value of this option. The default | ||
253 | of 1 says that all excess pages should be trimmed. | ||
254 | |||
255 | See Documentation/nommu-mmap.txt for more information. | ||
diff --git a/mm/madvise.c b/mm/madvise.c index b9ce574827c8..36d6ea2b6340 100644 --- a/mm/madvise.c +++ b/mm/madvise.c | |||
@@ -112,6 +112,14 @@ static long madvise_willneed(struct vm_area_struct * vma, | |||
112 | if (!file) | 112 | if (!file) |
113 | return -EBADF; | 113 | return -EBADF; |
114 | 114 | ||
115 | /* | ||
116 | * Page cache readahead assumes page cache pages are order-0 which | ||
117 | * is not the case for hugetlbfs. Do not give a bad return value | ||
118 | * but ignore the advice. | ||
119 | */ | ||
120 | if (vma->vm_flags & VM_HUGETLB) | ||
121 | return 0; | ||
122 | |||
115 | if (file->f_mapping->a_ops->get_xip_mem) { | 123 | if (file->f_mapping->a_ops->get_xip_mem) { |
116 | /* no bad return value, but ignore advice */ | 124 | /* no bad return value, but ignore advice */ |
117 | return 0; | 125 | return 0; |
diff --git a/mm/nommu.c b/mm/nommu.c index 809998aa7b50..b571ef707428 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -66,7 +66,7 @@ struct percpu_counter vm_committed_as; | |||
66 | int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ | 66 | int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ |
67 | int sysctl_overcommit_ratio = 50; /* default is 50% */ | 67 | int sysctl_overcommit_ratio = 50; /* default is 50% */ |
68 | int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; | 68 | int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; |
69 | int sysctl_nr_trim_pages = 1; /* page trimming behaviour */ | 69 | int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS; |
70 | int heap_stack_gap = 0; | 70 | int heap_stack_gap = 0; |
71 | 71 | ||
72 | atomic_long_t mmap_pages_allocated; | 72 | atomic_long_t mmap_pages_allocated; |
@@ -515,8 +515,6 @@ static void add_nommu_region(struct vm_region *region) | |||
515 | 515 | ||
516 | validate_nommu_regions(); | 516 | validate_nommu_regions(); |
517 | 517 | ||
518 | BUG_ON(region->vm_start & ~PAGE_MASK); | ||
519 | |||
520 | parent = NULL; | 518 | parent = NULL; |
521 | p = &nommu_region_tree.rb_node; | 519 | p = &nommu_region_tree.rb_node; |
522 | while (*p) { | 520 | while (*p) { |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 2f3166e308d9..92bcf1db16b2 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -514,34 +514,32 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask) | |||
514 | */ | 514 | */ |
515 | static void __out_of_memory(gfp_t gfp_mask, int order) | 515 | static void __out_of_memory(gfp_t gfp_mask, int order) |
516 | { | 516 | { |
517 | if (sysctl_oom_kill_allocating_task) { | 517 | struct task_struct *p; |
518 | oom_kill_process(current, gfp_mask, order, 0, NULL, | 518 | unsigned long points; |
519 | "Out of memory (oom_kill_allocating_task)"); | ||
520 | |||
521 | } else { | ||
522 | unsigned long points; | ||
523 | struct task_struct *p; | ||
524 | |||
525 | retry: | ||
526 | /* | ||
527 | * Rambo mode: Shoot down a process and hope it solves whatever | ||
528 | * issues we may have. | ||
529 | */ | ||
530 | p = select_bad_process(&points, NULL); | ||
531 | 519 | ||
532 | if (PTR_ERR(p) == -1UL) | 520 | if (sysctl_oom_kill_allocating_task) |
521 | if (!oom_kill_process(current, gfp_mask, order, 0, NULL, | ||
522 | "Out of memory (oom_kill_allocating_task)")) | ||
533 | return; | 523 | return; |
524 | retry: | ||
525 | /* | ||
526 | * Rambo mode: Shoot down a process and hope it solves whatever | ||
527 | * issues we may have. | ||
528 | */ | ||
529 | p = select_bad_process(&points, NULL); | ||
534 | 530 | ||
535 | /* Found nothing?!?! Either we hang forever, or we panic. */ | 531 | if (PTR_ERR(p) == -1UL) |
536 | if (!p) { | 532 | return; |
537 | read_unlock(&tasklist_lock); | ||
538 | panic("Out of memory and no killable processes...\n"); | ||
539 | } | ||
540 | 533 | ||
541 | if (oom_kill_process(p, gfp_mask, order, points, NULL, | 534 | /* Found nothing?!?! Either we hang forever, or we panic. */ |
542 | "Out of memory")) | 535 | if (!p) { |
543 | goto retry; | 536 | read_unlock(&tasklist_lock); |
537 | panic("Out of memory and no killable processes...\n"); | ||
544 | } | 538 | } |
539 | |||
540 | if (oom_kill_process(p, gfp_mask, order, points, NULL, | ||
541 | "Out of memory")) | ||
542 | goto retry; | ||
545 | } | 543 | } |
546 | 544 | ||
547 | /* | 545 | /* |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e2f26991fff1..fe753ecf2aa5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -2681,6 +2681,7 @@ static void __meminit zone_init_free_lists(struct zone *zone) | |||
2681 | 2681 | ||
2682 | static int zone_batchsize(struct zone *zone) | 2682 | static int zone_batchsize(struct zone *zone) |
2683 | { | 2683 | { |
2684 | #ifdef CONFIG_MMU | ||
2684 | int batch; | 2685 | int batch; |
2685 | 2686 | ||
2686 | /* | 2687 | /* |
@@ -2706,9 +2707,26 @@ static int zone_batchsize(struct zone *zone) | |||
2706 | * of pages of one half of the possible page colors | 2707 | * of pages of one half of the possible page colors |
2707 | * and the other with pages of the other colors. | 2708 | * and the other with pages of the other colors. |
2708 | */ | 2709 | */ |
2709 | batch = (1 << (fls(batch + batch/2)-1)) - 1; | 2710 | batch = rounddown_pow_of_two(batch + batch/2) - 1; |
2710 | 2711 | ||
2711 | return batch; | 2712 | return batch; |
2713 | |||
2714 | #else | ||
2715 | /* The deferral and batching of frees should be suppressed under NOMMU | ||
2716 | * conditions. | ||
2717 | * | ||
2718 | * The problem is that NOMMU needs to be able to allocate large chunks | ||
2719 | * of contiguous memory as there's no hardware page translation to | ||
2720 | * assemble apparent contiguous memory from discontiguous pages. | ||
2721 | * | ||
2722 | * Queueing large contiguous runs of pages for batching, however, | ||
2723 | * causes the pages to actually be freed in smaller chunks. As there | ||
2724 | * can be a significant delay between the individual batches being | ||
2725 | * recycled, this leads to the once large chunks of space being | ||
2726 | * fragmented and becoming unavailable for high-order allocations. | ||
2727 | */ | ||
2728 | return 0; | ||
2729 | #endif | ||
2712 | } | 2730 | } |
2713 | 2731 | ||
2714 | static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) | 2732 | static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index fab19876b4d1..083716ea38c9 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -402,6 +402,7 @@ overflow: | |||
402 | printk(KERN_WARNING | 402 | printk(KERN_WARNING |
403 | "vmap allocation for size %lu failed: " | 403 | "vmap allocation for size %lu failed: " |
404 | "use vmalloc=<size> to increase size.\n", size); | 404 | "use vmalloc=<size> to increase size.\n", size); |
405 | kfree(va); | ||
405 | return ERR_PTR(-EBUSY); | 406 | return ERR_PTR(-EBUSY); |
406 | } | 407 | } |
407 | 408 | ||