diff options
author | Rik van Riel <riel@redhat.com> | 2012-03-21 19:33:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 20:54:56 -0400 |
commit | aff622495c9a0b56148192e53bdec539f5e147f2 (patch) | |
tree | 78f6400d8b6bec3279483006a0e9543e47aa833e /include | |
parent | 7be62de99adcab4449d416977b4274985c5fe023 (diff) |
vmscan: only defer compaction for failed order and higher
Currently a failed order-9 (transparent hugepage) compaction can lead to
memory compaction being temporarily disabled for a memory zone. Even if
we only need compaction for an order 2 allocation, eg. for jumbo frames
networking.
The fix is relatively straightforward: keep track of the highest order at
which compaction is succeeding, and only defer compaction for orders at
which compaction is failing.
Signed-off-by: Rik van Riel <riel@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Mel Gorman <mel@csn.ul.ie>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Hillf Danton <dhillf@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/compaction.h | 14 | ||||
-rw-r--r-- | include/linux/mmzone.h | 1 |
2 files changed, 11 insertions, 4 deletions
diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 7a9323aef4a3..51a90b7f2d60 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h | |||
@@ -34,20 +34,26 @@ extern unsigned long compaction_suitable(struct zone *zone, int order); | |||
34 | * allocation success. 1 << compact_defer_limit compactions are skipped up | 34 | * allocation success. 1 << compact_defer_limit compactions are skipped up |
35 | * to a limit of 1 << COMPACT_MAX_DEFER_SHIFT | 35 | * to a limit of 1 << COMPACT_MAX_DEFER_SHIFT |
36 | */ | 36 | */ |
37 | static inline void defer_compaction(struct zone *zone) | 37 | static inline void defer_compaction(struct zone *zone, int order) |
38 | { | 38 | { |
39 | zone->compact_considered = 0; | 39 | zone->compact_considered = 0; |
40 | zone->compact_defer_shift++; | 40 | zone->compact_defer_shift++; |
41 | 41 | ||
42 | if (order < zone->compact_order_failed) | ||
43 | zone->compact_order_failed = order; | ||
44 | |||
42 | if (zone->compact_defer_shift > COMPACT_MAX_DEFER_SHIFT) | 45 | if (zone->compact_defer_shift > COMPACT_MAX_DEFER_SHIFT) |
43 | zone->compact_defer_shift = COMPACT_MAX_DEFER_SHIFT; | 46 | zone->compact_defer_shift = COMPACT_MAX_DEFER_SHIFT; |
44 | } | 47 | } |
45 | 48 | ||
46 | /* Returns true if compaction should be skipped this time */ | 49 | /* Returns true if compaction should be skipped this time */ |
47 | static inline bool compaction_deferred(struct zone *zone) | 50 | static inline bool compaction_deferred(struct zone *zone, int order) |
48 | { | 51 | { |
49 | unsigned long defer_limit = 1UL << zone->compact_defer_shift; | 52 | unsigned long defer_limit = 1UL << zone->compact_defer_shift; |
50 | 53 | ||
54 | if (order < zone->compact_order_failed) | ||
55 | return false; | ||
56 | |||
51 | /* Avoid possible overflow */ | 57 | /* Avoid possible overflow */ |
52 | if (++zone->compact_considered > defer_limit) | 58 | if (++zone->compact_considered > defer_limit) |
53 | zone->compact_considered = defer_limit; | 59 | zone->compact_considered = defer_limit; |
@@ -73,11 +79,11 @@ static inline unsigned long compaction_suitable(struct zone *zone, int order) | |||
73 | return COMPACT_SKIPPED; | 79 | return COMPACT_SKIPPED; |
74 | } | 80 | } |
75 | 81 | ||
76 | static inline void defer_compaction(struct zone *zone) | 82 | static inline void defer_compaction(struct zone *zone, int order) |
77 | { | 83 | { |
78 | } | 84 | } |
79 | 85 | ||
80 | static inline bool compaction_deferred(struct zone *zone) | 86 | static inline bool compaction_deferred(struct zone *zone, int order) |
81 | { | 87 | { |
82 | return 1; | 88 | return 1; |
83 | } | 89 | } |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 650ba2fb3301..dff711509661 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -365,6 +365,7 @@ struct zone { | |||
365 | */ | 365 | */ |
366 | unsigned int compact_considered; | 366 | unsigned int compact_considered; |
367 | unsigned int compact_defer_shift; | 367 | unsigned int compact_defer_shift; |
368 | int compact_order_failed; | ||
368 | #endif | 369 | #endif |
369 | 370 | ||
370 | ZONE_PADDING(_pad1_) | 371 | ZONE_PADDING(_pad1_) |