aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2009-06-19 13:30:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 19:08:22 -0400
commitc277331d5fbaae5772ed19862feefa91f4e477d3 (patch)
treefcd980b58d9487421e9b0c45b7c082fa1302debb /mm
parent9063c61fd5cbd6f42e95929aa0e02380c9e15656 (diff)
mm: page_alloc: clear PG_locked before checking flags on free
da456f1 "page allocator: do not disable interrupts in free_page_mlock()" moved the PG_mlocked clearing after the flag sanity checking which makes mlocked pages always trigger 'bad page'. Fix this by clearing the bit up front. Reported--and-debugged-by: Peter Chubb <peter.chubb@nicta.com.au> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Mel Gorman <mel@csn.ul.ie> Tested-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6f0753fe694c..30d5093a099d 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -488,7 +488,6 @@ static inline void __free_one_page(struct page *page,
488 */ 488 */
489static inline void free_page_mlock(struct page *page) 489static inline void free_page_mlock(struct page *page)
490{ 490{
491 __ClearPageMlocked(page);
492 __dec_zone_page_state(page, NR_MLOCK); 491 __dec_zone_page_state(page, NR_MLOCK);
493 __count_vm_event(UNEVICTABLE_MLOCKFREED); 492 __count_vm_event(UNEVICTABLE_MLOCKFREED);
494} 493}
@@ -558,7 +557,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
558 unsigned long flags; 557 unsigned long flags;
559 int i; 558 int i;
560 int bad = 0; 559 int bad = 0;
561 int clearMlocked = PageMlocked(page); 560 int wasMlocked = TestClearPageMlocked(page);
562 561
563 kmemcheck_free_shadow(page, order); 562 kmemcheck_free_shadow(page, order);
564 563
@@ -576,7 +575,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
576 kernel_map_pages(page, 1 << order, 0); 575 kernel_map_pages(page, 1 << order, 0);
577 576
578 local_irq_save(flags); 577 local_irq_save(flags);
579 if (unlikely(clearMlocked)) 578 if (unlikely(wasMlocked))
580 free_page_mlock(page); 579 free_page_mlock(page);
581 __count_vm_events(PGFREE, 1 << order); 580 __count_vm_events(PGFREE, 1 << order);
582 free_one_page(page_zone(page), page, order, 581 free_one_page(page_zone(page), page, order,
@@ -1022,7 +1021,7 @@ static void free_hot_cold_page(struct page *page, int cold)
1022 struct zone *zone = page_zone(page); 1021 struct zone *zone = page_zone(page);
1023 struct per_cpu_pages *pcp; 1022 struct per_cpu_pages *pcp;
1024 unsigned long flags; 1023 unsigned long flags;
1025 int clearMlocked = PageMlocked(page); 1024 int wasMlocked = TestClearPageMlocked(page);
1026 1025
1027 kmemcheck_free_shadow(page, 0); 1026 kmemcheck_free_shadow(page, 0);
1028 1027
@@ -1041,7 +1040,7 @@ static void free_hot_cold_page(struct page *page, int cold)
1041 pcp = &zone_pcp(zone, get_cpu())->pcp; 1040 pcp = &zone_pcp(zone, get_cpu())->pcp;
1042 set_page_private(page, get_pageblock_migratetype(page)); 1041 set_page_private(page, get_pageblock_migratetype(page));
1043 local_irq_save(flags); 1042 local_irq_save(flags);
1044 if (unlikely(clearMlocked)) 1043 if (unlikely(wasMlocked))
1045 free_page_mlock(page); 1044 free_page_mlock(page);
1046 __count_vm_event(PGFREE); 1045 __count_vm_event(PGFREE);
1047 1046