summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorVlastimil Babka <vbabka@suse.cz>2017-02-22 18:41:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 19:41:27 -0500
commit76741e776a37973a3e398d504069b3e55c5cc866 (patch)
tree2cbf1aeea702a4695911a242eacafe105ca63579 /mm/page_alloc.c
parentaa187507ef8bb3178a3312d851e8485bd81913c9 (diff)
mm, page_alloc: don't convert pfn to idx when merging
In __free_one_page() we do the buddy merging arithmetics on "page/buddy index", which is just the lower MAX_ORDER bits of pfn. The operations we do that affect the higher bits are bitwise AND and subtraction (in that order), where the final result will be the same with the higher bits left unmasked, as long as these bits are equal for both buddies - which must be true by the definition of a buddy. We can therefore use pfn's directly instead of "index" and skip the zeroing of >MAX_ORDER bits. This can help a bit by itself, although compiler might be smart enough already. It also helps the next patch to avoid page_to_pfn() for memory hole checks. Link: http://lkml.kernel.org/r/20161216120009.20064-1-vbabka@suse.cz Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Mel Gorman <mgorman@techsingularity.net> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Michal Hocko <mhocko@kernel.org> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c31
1 files changed, 14 insertions, 17 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3c790ae4cb52..49d40261f8c4 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -787,9 +787,8 @@ static inline void __free_one_page(struct page *page,
787 struct zone *zone, unsigned int order, 787 struct zone *zone, unsigned int order,
788 int migratetype) 788 int migratetype)
789{ 789{
790 unsigned long page_idx; 790 unsigned long combined_pfn;
791 unsigned long combined_idx; 791 unsigned long uninitialized_var(buddy_pfn);
792 unsigned long uninitialized_var(buddy_idx);
793 struct page *buddy; 792 struct page *buddy;
794 unsigned int max_order; 793 unsigned int max_order;
795 794
@@ -802,15 +801,13 @@ static inline void __free_one_page(struct page *page,
802 if (likely(!is_migrate_isolate(migratetype))) 801 if (likely(!is_migrate_isolate(migratetype)))
803 __mod_zone_freepage_state(zone, 1 << order, migratetype); 802 __mod_zone_freepage_state(zone, 1 << order, migratetype);
804 803
805 page_idx = pfn & ((1 << MAX_ORDER) - 1); 804 VM_BUG_ON_PAGE(pfn & ((1 << order) - 1), page);
806
807 VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page);
808 VM_BUG_ON_PAGE(bad_range(zone, page), page); 805 VM_BUG_ON_PAGE(bad_range(zone, page), page);
809 806
810continue_merging: 807continue_merging:
811 while (order < max_order - 1) { 808 while (order < max_order - 1) {
812 buddy_idx = __find_buddy_index(page_idx, order); 809 buddy_pfn = __find_buddy_pfn(pfn, order);
813 buddy = page + (buddy_idx - page_idx); 810 buddy = page + (buddy_pfn - pfn);
814 if (!page_is_buddy(page, buddy, order)) 811 if (!page_is_buddy(page, buddy, order))
815 goto done_merging; 812 goto done_merging;
816 /* 813 /*
@@ -824,9 +821,9 @@ continue_merging:
824 zone->free_area[order].nr_free--; 821 zone->free_area[order].nr_free--;
825 rmv_page_order(buddy); 822 rmv_page_order(buddy);
826 } 823 }
827 combined_idx = buddy_idx & page_idx; 824 combined_pfn = buddy_pfn & pfn;
828 page = page + (combined_idx - page_idx); 825 page = page + (combined_pfn - pfn);
829 page_idx = combined_idx; 826 pfn = combined_pfn;
830 order++; 827 order++;
831 } 828 }
832 if (max_order < MAX_ORDER) { 829 if (max_order < MAX_ORDER) {
@@ -841,8 +838,8 @@ continue_merging:
841 if (unlikely(has_isolate_pageblock(zone))) { 838 if (unlikely(has_isolate_pageblock(zone))) {
842 int buddy_mt; 839 int buddy_mt;
843 840
844 buddy_idx = __find_buddy_index(page_idx, order); 841 buddy_pfn = __find_buddy_pfn(pfn, order);
845 buddy = page + (buddy_idx - page_idx); 842 buddy = page + (buddy_pfn - pfn);
846 buddy_mt = get_pageblock_migratetype(buddy); 843 buddy_mt = get_pageblock_migratetype(buddy);
847 844
848 if (migratetype != buddy_mt 845 if (migratetype != buddy_mt
@@ -867,10 +864,10 @@ done_merging:
867 */ 864 */
868 if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) { 865 if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) {
869 struct page *higher_page, *higher_buddy; 866 struct page *higher_page, *higher_buddy;
870 combined_idx = buddy_idx & page_idx; 867 combined_pfn = buddy_pfn & pfn;
871 higher_page = page + (combined_idx - page_idx); 868 higher_page = page + (combined_pfn - pfn);
872 buddy_idx = __find_buddy_index(combined_idx, order + 1); 869 buddy_pfn = __find_buddy_pfn(combined_pfn, order + 1);
873 higher_buddy = higher_page + (buddy_idx - combined_idx); 870 higher_buddy = higher_page + (buddy_pfn - combined_pfn);
874 if (page_is_buddy(higher_page, higher_buddy, order + 1)) { 871 if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
875 list_add_tail(&page->lru, 872 list_add_tail(&page->lru,
876 &zone->free_area[order].free_list[migratetype]); 873 &zone->free_area[order].free_list[migratetype]);