diff options
author | Mel Gorman <mgorman@suse.de> | 2014-06-04 19:10:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 19:54:09 -0400 |
commit | dc4b0caff24d9b2918e9f27bc65499ee63187eba (patch) | |
tree | ae94a40e2da00a8b32c81c4451d42447b65d6e03 /mm | |
parent | e58469bafd0524e848c3733bc3918d854595e20f (diff) |
mm: page_alloc: reduce number of times page_to_pfn is called
In the free path we calculate page_to_pfn multiple times. Reduce that.
Signed-off-by: Mel Gorman <mgorman@suse.de>
Acked-by: Rik van Riel <riel@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Jan Kara <jack@suse.cz>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Hugh Dickins <hughd@google.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.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.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6e937809c87a..6cadc8678e28 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -560,6 +560,7 @@ static inline int page_is_buddy(struct page *page, struct page *buddy, | |||
560 | */ | 560 | */ |
561 | 561 | ||
562 | static inline void __free_one_page(struct page *page, | 562 | static inline void __free_one_page(struct page *page, |
563 | unsigned long pfn, | ||
563 | struct zone *zone, unsigned int order, | 564 | struct zone *zone, unsigned int order, |
564 | int migratetype) | 565 | int migratetype) |
565 | { | 566 | { |
@@ -576,7 +577,7 @@ static inline void __free_one_page(struct page *page, | |||
576 | 577 | ||
577 | VM_BUG_ON(migratetype == -1); | 578 | VM_BUG_ON(migratetype == -1); |
578 | 579 | ||
579 | page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); | 580 | page_idx = pfn & ((1 << MAX_ORDER) - 1); |
580 | 581 | ||
581 | VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page); | 582 | VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page); |
582 | VM_BUG_ON_PAGE(bad_range(zone, page), page); | 583 | VM_BUG_ON_PAGE(bad_range(zone, page), page); |
@@ -711,7 +712,7 @@ static void free_pcppages_bulk(struct zone *zone, int count, | |||
711 | list_del(&page->lru); | 712 | list_del(&page->lru); |
712 | mt = get_freepage_migratetype(page); | 713 | mt = get_freepage_migratetype(page); |
713 | /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */ | 714 | /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */ |
714 | __free_one_page(page, zone, 0, mt); | 715 | __free_one_page(page, page_to_pfn(page), zone, 0, mt); |
715 | trace_mm_page_pcpu_drain(page, 0, mt); | 716 | trace_mm_page_pcpu_drain(page, 0, mt); |
716 | if (likely(!is_migrate_isolate_page(page))) { | 717 | if (likely(!is_migrate_isolate_page(page))) { |
717 | __mod_zone_page_state(zone, NR_FREE_PAGES, 1); | 718 | __mod_zone_page_state(zone, NR_FREE_PAGES, 1); |
@@ -723,13 +724,15 @@ static void free_pcppages_bulk(struct zone *zone, int count, | |||
723 | spin_unlock(&zone->lock); | 724 | spin_unlock(&zone->lock); |
724 | } | 725 | } |
725 | 726 | ||
726 | static void free_one_page(struct zone *zone, struct page *page, int order, | 727 | static void free_one_page(struct zone *zone, |
728 | struct page *page, unsigned long pfn, | ||
729 | int order, | ||
727 | int migratetype) | 730 | int migratetype) |
728 | { | 731 | { |
729 | spin_lock(&zone->lock); | 732 | spin_lock(&zone->lock); |
730 | zone->pages_scanned = 0; | 733 | zone->pages_scanned = 0; |
731 | 734 | ||
732 | __free_one_page(page, zone, order, migratetype); | 735 | __free_one_page(page, pfn, zone, order, migratetype); |
733 | if (unlikely(!is_migrate_isolate(migratetype))) | 736 | if (unlikely(!is_migrate_isolate(migratetype))) |
734 | __mod_zone_freepage_state(zone, 1 << order, migratetype); | 737 | __mod_zone_freepage_state(zone, 1 << order, migratetype); |
735 | spin_unlock(&zone->lock); | 738 | spin_unlock(&zone->lock); |
@@ -766,15 +769,16 @@ static void __free_pages_ok(struct page *page, unsigned int order) | |||
766 | { | 769 | { |
767 | unsigned long flags; | 770 | unsigned long flags; |
768 | int migratetype; | 771 | int migratetype; |
772 | unsigned long pfn = page_to_pfn(page); | ||
769 | 773 | ||
770 | if (!free_pages_prepare(page, order)) | 774 | if (!free_pages_prepare(page, order)) |
771 | return; | 775 | return; |
772 | 776 | ||
773 | local_irq_save(flags); | 777 | local_irq_save(flags); |
774 | __count_vm_events(PGFREE, 1 << order); | 778 | __count_vm_events(PGFREE, 1 << order); |
775 | migratetype = get_pageblock_migratetype(page); | 779 | migratetype = get_pfnblock_migratetype(page, pfn); |
776 | set_freepage_migratetype(page, migratetype); | 780 | set_freepage_migratetype(page, migratetype); |
777 | free_one_page(page_zone(page), page, order, migratetype); | 781 | free_one_page(page_zone(page), page, pfn, order, migratetype); |
778 | local_irq_restore(flags); | 782 | local_irq_restore(flags); |
779 | } | 783 | } |
780 | 784 | ||
@@ -1380,12 +1384,13 @@ void free_hot_cold_page(struct page *page, int cold) | |||
1380 | struct zone *zone = page_zone(page); | 1384 | struct zone *zone = page_zone(page); |
1381 | struct per_cpu_pages *pcp; | 1385 | struct per_cpu_pages *pcp; |
1382 | unsigned long flags; | 1386 | unsigned long flags; |
1387 | unsigned long pfn = page_to_pfn(page); | ||
1383 | int migratetype; | 1388 | int migratetype; |
1384 | 1389 | ||
1385 | if (!free_pages_prepare(page, 0)) | 1390 | if (!free_pages_prepare(page, 0)) |
1386 | return; | 1391 | return; |
1387 | 1392 | ||
1388 | migratetype = get_pageblock_migratetype(page); | 1393 | migratetype = get_pfnblock_migratetype(page, pfn); |
1389 | set_freepage_migratetype(page, migratetype); | 1394 | set_freepage_migratetype(page, migratetype); |
1390 | local_irq_save(flags); | 1395 | local_irq_save(flags); |
1391 | __count_vm_event(PGFREE); | 1396 | __count_vm_event(PGFREE); |
@@ -1399,7 +1404,7 @@ void free_hot_cold_page(struct page *page, int cold) | |||
1399 | */ | 1404 | */ |
1400 | if (migratetype >= MIGRATE_PCPTYPES) { | 1405 | if (migratetype >= MIGRATE_PCPTYPES) { |
1401 | if (unlikely(is_migrate_isolate(migratetype))) { | 1406 | if (unlikely(is_migrate_isolate(migratetype))) { |
1402 | free_one_page(zone, page, 0, migratetype); | 1407 | free_one_page(zone, page, pfn, 0, migratetype); |
1403 | goto out; | 1408 | goto out; |
1404 | } | 1409 | } |
1405 | migratetype = MIGRATE_MOVABLE; | 1410 | migratetype = MIGRATE_MOVABLE; |
@@ -6028,17 +6033,16 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) | |||
6028 | * @end_bitidx: The last bit of interest | 6033 | * @end_bitidx: The last bit of interest |
6029 | * returns pageblock_bits flags | 6034 | * returns pageblock_bits flags |
6030 | */ | 6035 | */ |
6031 | unsigned long get_pageblock_flags_mask(struct page *page, | 6036 | unsigned long get_pfnblock_flags_mask(struct page *page, unsigned long pfn, |
6032 | unsigned long end_bitidx, | 6037 | unsigned long end_bitidx, |
6033 | unsigned long mask) | 6038 | unsigned long mask) |
6034 | { | 6039 | { |
6035 | struct zone *zone; | 6040 | struct zone *zone; |
6036 | unsigned long *bitmap; | 6041 | unsigned long *bitmap; |
6037 | unsigned long pfn, bitidx, word_bitidx; | 6042 | unsigned long bitidx, word_bitidx; |
6038 | unsigned long word; | 6043 | unsigned long word; |
6039 | 6044 | ||
6040 | zone = page_zone(page); | 6045 | zone = page_zone(page); |
6041 | pfn = page_to_pfn(page); | ||
6042 | bitmap = get_pageblock_bitmap(zone, pfn); | 6046 | bitmap = get_pageblock_bitmap(zone, pfn); |
6043 | bitidx = pfn_to_bitidx(zone, pfn); | 6047 | bitidx = pfn_to_bitidx(zone, pfn); |
6044 | word_bitidx = bitidx / BITS_PER_LONG; | 6048 | word_bitidx = bitidx / BITS_PER_LONG; |
@@ -6050,25 +6054,25 @@ unsigned long get_pageblock_flags_mask(struct page *page, | |||
6050 | } | 6054 | } |
6051 | 6055 | ||
6052 | /** | 6056 | /** |
6053 | * set_pageblock_flags_mask - Set the requested group of flags for a pageblock_nr_pages block of pages | 6057 | * set_pfnblock_flags_mask - Set the requested group of flags for a pageblock_nr_pages block of pages |
6054 | * @page: The page within the block of interest | 6058 | * @page: The page within the block of interest |
6055 | * @start_bitidx: The first bit of interest | 6059 | * @start_bitidx: The first bit of interest |
6056 | * @end_bitidx: The last bit of interest | 6060 | * @end_bitidx: The last bit of interest |
6057 | * @flags: The flags to set | 6061 | * @flags: The flags to set |
6058 | */ | 6062 | */ |
6059 | void set_pageblock_flags_mask(struct page *page, unsigned long flags, | 6063 | void set_pfnblock_flags_mask(struct page *page, unsigned long flags, |
6064 | unsigned long pfn, | ||
6060 | unsigned long end_bitidx, | 6065 | unsigned long end_bitidx, |
6061 | unsigned long mask) | 6066 | unsigned long mask) |
6062 | { | 6067 | { |
6063 | struct zone *zone; | 6068 | struct zone *zone; |
6064 | unsigned long *bitmap; | 6069 | unsigned long *bitmap; |
6065 | unsigned long pfn, bitidx, word_bitidx; | 6070 | unsigned long bitidx, word_bitidx; |
6066 | unsigned long old_word, word; | 6071 | unsigned long old_word, word; |
6067 | 6072 | ||
6068 | BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 4); | 6073 | BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 4); |
6069 | 6074 | ||
6070 | zone = page_zone(page); | 6075 | zone = page_zone(page); |
6071 | pfn = page_to_pfn(page); | ||
6072 | bitmap = get_pageblock_bitmap(zone, pfn); | 6076 | bitmap = get_pageblock_bitmap(zone, pfn); |
6073 | bitidx = pfn_to_bitidx(zone, pfn); | 6077 | bitidx = pfn_to_bitidx(zone, pfn); |
6074 | word_bitidx = bitidx / BITS_PER_LONG; | 6078 | word_bitidx = bitidx / BITS_PER_LONG; |