diff options
author | Mel Gorman <mel@csn.ul.ie> | 2010-05-24 17:32:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 11:06:59 -0400 |
commit | 56de7263fcf3eb10c8dcdf8d59a9cec831795f3f (patch) | |
tree | 164637c0b678e20adfdcec4129563d9234faf405 /mm/vmstat.c | |
parent | ed4a6d7f0676db50b5023cc01f6cda82a2f2a307 (diff) |
mm: compaction: direct compact when a high-order allocation fails
Ordinarily when a high-order allocation fails, direct reclaim is entered
to free pages to satisfy the allocation. With this patch, it is
determined if an allocation failed due to external fragmentation instead
of low memory and if so, the calling process will compact until a suitable
page is freed. Compaction by moving pages in memory is considerably
cheaper than paging out to disk and works where there are locked pages or
no swap. If compaction fails to free a page of a suitable size, then
reclaim will still occur.
Direct compaction returns as soon as possible. As each block is
compacted, it is checked if a suitable page has been freed and if so, it
returns.
[akpm@linux-foundation.org: Fix build errors]
[aarcange@redhat.com: fix count_vm_event preempt in memory compaction direct reclaim]
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Acked-by: Rik van Riel <riel@redhat.com>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r-- | mm/vmstat.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index c6aacf51b554..7759941d4e77 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -429,7 +429,7 @@ static void fill_contig_page_info(struct zone *zone, | |||
429 | * The value can be used to determine if page reclaim or compaction | 429 | * The value can be used to determine if page reclaim or compaction |
430 | * should be used | 430 | * should be used |
431 | */ | 431 | */ |
432 | int fragmentation_index(unsigned int order, struct contig_page_info *info) | 432 | static int __fragmentation_index(unsigned int order, struct contig_page_info *info) |
433 | { | 433 | { |
434 | unsigned long requested = 1UL << order; | 434 | unsigned long requested = 1UL << order; |
435 | 435 | ||
@@ -448,6 +448,15 @@ int fragmentation_index(unsigned int order, struct contig_page_info *info) | |||
448 | */ | 448 | */ |
449 | return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total); | 449 | return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total); |
450 | } | 450 | } |
451 | |||
452 | /* Same as __fragmentation index but allocs contig_page_info on stack */ | ||
453 | int fragmentation_index(struct zone *zone, unsigned int order) | ||
454 | { | ||
455 | struct contig_page_info info; | ||
456 | |||
457 | fill_contig_page_info(zone, order, &info); | ||
458 | return __fragmentation_index(order, &info); | ||
459 | } | ||
451 | #endif | 460 | #endif |
452 | 461 | ||
453 | #if defined(CONFIG_PROC_FS) || defined(CONFIG_COMPACTION) | 462 | #if defined(CONFIG_PROC_FS) || defined(CONFIG_COMPACTION) |
@@ -771,6 +780,9 @@ static const char * const vmstat_text[] = { | |||
771 | "compact_blocks_moved", | 780 | "compact_blocks_moved", |
772 | "compact_pages_moved", | 781 | "compact_pages_moved", |
773 | "compact_pagemigrate_failed", | 782 | "compact_pagemigrate_failed", |
783 | "compact_stall", | ||
784 | "compact_fail", | ||
785 | "compact_success", | ||
774 | #endif | 786 | #endif |
775 | 787 | ||
776 | #ifdef CONFIG_HUGETLB_PAGE | 788 | #ifdef CONFIG_HUGETLB_PAGE |
@@ -1136,7 +1148,7 @@ static void extfrag_show_print(struct seq_file *m, | |||
1136 | zone->name); | 1148 | zone->name); |
1137 | for (order = 0; order < MAX_ORDER; ++order) { | 1149 | for (order = 0; order < MAX_ORDER; ++order) { |
1138 | fill_contig_page_info(zone, order, &info); | 1150 | fill_contig_page_info(zone, order, &info); |
1139 | index = fragmentation_index(order, &info); | 1151 | index = __fragmentation_index(order, &info); |
1140 | seq_printf(m, "%d.%03d ", index / 1000, index % 1000); | 1152 | seq_printf(m, "%d.%03d ", index / 1000, index % 1000); |
1141 | } | 1153 | } |
1142 | 1154 | ||