aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2007-10-16 04:25:59 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:00 -0400
commit64c5e135bf5a2a7f0ededb3435a31adbe0202f0c (patch)
treecb4ff93cbcc3c27176723419a313d7c53545d36b /mm
parentac0e5b7a6b93fb291b01fe1e951e3c16bcdd3503 (diff)
don't group high order atomic allocations
Grouping high-order atomic allocations together was intended to allow bursty users of atomic allocations to work such as e1000 in situations where their preallocated buffers were depleted. This did not work in at least one case with a wireless network adapter needing order-1 allocations frequently. To resolve that, the free pages used for min_free_kbytes were moved to separate contiguous blocks with the patch bias-the-location-of-pages-freed-for-min_free_kbytes-in-the-same-max_order_nr_pages-blocks. It is felt that keeping the free pages in the same contiguous blocks should be sufficient for bursty short-lived high-order atomic allocations to succeed, maybe even with the e1000. Even if there is a failure, increasing the value of min_free_kbytes will free pages as contiguous bloks in contrast to the standard buddy allocator which makes no attempt to keep the minimum number of free pages contiguous. This patch backs out grouping high order atomic allocations together to determine if it is really needed or not. If a new report comes in about high-order atomic allocations failing, the feature can be reintroduced to determine if it fixes the problem or not. As a side-effect, this patch reduces by 1 the number of bits required to track the mobility type of pages within a MAX_ORDER_NR_PAGES block. Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Andy Whitcroft <apw@shadowen.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c37
1 files changed, 7 insertions, 30 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8aec4d4601e7..ac8fc51825bb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -174,18 +174,13 @@ static void set_pageblock_migratetype(struct page *page, int migratetype)
174 PB_migrate, PB_migrate_end); 174 PB_migrate, PB_migrate_end);
175} 175}
176 176
177static inline int allocflags_to_migratetype(gfp_t gfp_flags, int order) 177static inline int allocflags_to_migratetype(gfp_t gfp_flags)
178{ 178{
179 WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK); 179 WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
180 180
181 if (unlikely(page_group_by_mobility_disabled)) 181 if (unlikely(page_group_by_mobility_disabled))
182 return MIGRATE_UNMOVABLE; 182 return MIGRATE_UNMOVABLE;
183 183
184 /* Cluster high-order atomic allocations together */
185 if (unlikely(order > 0) &&
186 (!(gfp_flags & __GFP_WAIT) || in_interrupt()))
187 return MIGRATE_HIGHATOMIC;
188
189 /* Cluster based on mobility */ 184 /* Cluster based on mobility */
190 return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) | 185 return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) |
191 ((gfp_flags & __GFP_RECLAIMABLE) != 0); 186 ((gfp_flags & __GFP_RECLAIMABLE) != 0);
@@ -706,11 +701,10 @@ static struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
706 * the free lists for the desirable migrate type are depleted 701 * the free lists for the desirable migrate type are depleted
707 */ 702 */
708static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = { 703static int fallbacks[MIGRATE_TYPES][MIGRATE_TYPES-1] = {
709 [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_HIGHATOMIC, MIGRATE_RESERVE }, 704 [MIGRATE_UNMOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
710 [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_HIGHATOMIC, MIGRATE_RESERVE }, 705 [MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE },
711 [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_HIGHATOMIC, MIGRATE_RESERVE }, 706 [MIGRATE_MOVABLE] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
712 [MIGRATE_HIGHATOMIC] = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_MOVABLE, MIGRATE_RESERVE }, 707 [MIGRATE_RESERVE] = { MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE }, /* Never used */
713 [MIGRATE_RESERVE] = { MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE, MIGRATE_RESERVE }, /* Never used */
714}; 708};
715 709
716/* 710/*
@@ -804,9 +798,7 @@ static struct page *__rmqueue_fallback(struct zone *zone, int order,
804 int current_order; 798 int current_order;
805 struct page *page; 799 struct page *page;
806 int migratetype, i; 800 int migratetype, i;
807 int nonatomic_fallback_atomic = 0;
808 801
809retry:
810 /* Find the largest possible block of pages in the other list */ 802 /* Find the largest possible block of pages in the other list */
811 for (current_order = MAX_ORDER-1; current_order >= order; 803 for (current_order = MAX_ORDER-1; current_order >= order;
812 --current_order) { 804 --current_order) {
@@ -816,14 +808,6 @@ retry:
816 /* MIGRATE_RESERVE handled later if necessary */ 808 /* MIGRATE_RESERVE handled later if necessary */
817 if (migratetype == MIGRATE_RESERVE) 809 if (migratetype == MIGRATE_RESERVE)
818 continue; 810 continue;
819 /*
820 * Make it hard to fallback to blocks used for
821 * high-order atomic allocations
822 */
823 if (migratetype == MIGRATE_HIGHATOMIC &&
824 start_migratetype != MIGRATE_UNMOVABLE &&
825 !nonatomic_fallback_atomic)
826 continue;
827 811
828 area = &(zone->free_area[current_order]); 812 area = &(zone->free_area[current_order]);
829 if (list_empty(&area->free_list[migratetype])) 813 if (list_empty(&area->free_list[migratetype]))
@@ -849,8 +833,7 @@ retry:
849 start_migratetype); 833 start_migratetype);
850 834
851 /* Claim the whole block if over half of it is free */ 835 /* Claim the whole block if over half of it is free */
852 if ((pages << current_order) >= (1 << (MAX_ORDER-2)) && 836 if ((pages << current_order) >= (1 << (MAX_ORDER-2)))
853 migratetype != MIGRATE_HIGHATOMIC)
854 set_pageblock_migratetype(page, 837 set_pageblock_migratetype(page,
855 start_migratetype); 838 start_migratetype);
856 839
@@ -872,12 +855,6 @@ retry:
872 } 855 }
873 } 856 }
874 857
875 /* Allow fallback to high-order atomic blocks if memory is that low */
876 if (!nonatomic_fallback_atomic) {
877 nonatomic_fallback_atomic = 1;
878 goto retry;
879 }
880
881 /* Use MIGRATE_RESERVE rather than fail an allocation */ 858 /* Use MIGRATE_RESERVE rather than fail an allocation */
882 return __rmqueue_smallest(zone, order, MIGRATE_RESERVE); 859 return __rmqueue_smallest(zone, order, MIGRATE_RESERVE);
883} 860}
@@ -1112,7 +1089,7 @@ static struct page *buffered_rmqueue(struct zonelist *zonelist,
1112 struct page *page; 1089 struct page *page;
1113 int cold = !!(gfp_flags & __GFP_COLD); 1090 int cold = !!(gfp_flags & __GFP_COLD);
1114 int cpu; 1091 int cpu;
1115 int migratetype = allocflags_to_migratetype(gfp_flags, order); 1092 int migratetype = allocflags_to_migratetype(gfp_flags);
1116 1093
1117again: 1094again:
1118 cpu = get_cpu(); 1095 cpu = get_cpu();