mm: Use aligned zone start for pfn_to_bitidx calculation
Subsystems (3)
PATCH v2 1/1 mm: Use aligned zone start for pfn_to_bitidx calculation
The current calculation in pfn_to_bitidx assumes that (pfn - zone->zone_start_pfn) >> pageblock_order will return the same bit for all pfn in a pageblock. If zone_start_pfn is not aligned to pageblock_nr_pages, this may not always be correct.
Consider the following with pageblock order = 10, zone start 2MB:
pfn | pfn - zone start | (pfn - zone start) >> page block order
----------------------------------------------------------------
0x26000 | 0x25e00 | 0x97 0x26100 | 0x25f00 | 0x97 0x26200 | 0x26000 | 0x98 0x26300 | 0x26100 | 0x98
This means that calling {get,set}_pageblock_migratetype on a single page will not set the migratetype for the full block. Fix this by rounding down zone_start_pfn when doing the bitidx calculation.
--- mm/page_alloc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
mm/page_alloc.c +1 -1
@@ -5422,7 +5422,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) pfn &= (PAGES_PER_SECTION -1 );return (pfn >> pageblock_order) *NR_PAGEBLOCK_BITS ;#else - pfn = pfn - zone->zone_start_pfn; + pfn = pfn -round_down (zone->start_pfn, pageblock_nr_pages);return (pfn >> pageblock_order) *NR_PAGEBLOCK_BITS ;#endif /* CONFIG_SPARSEMEM */ }
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Quoted 29 lines · Laura Abbott
The current calculation in
pfn_to_bitidxassumes that (pfn -zone->zone_start_pfn) >>pageblock_orderwill return the same bit for all pfn in a pageblock. Ifzone_start_pfnis not aligned topageblock_nr_pages, this may not always be correct.Consider the following with pageblock order = 10, zone start 2MB:
pfn | pfn - zone start | (pfn - zone start) >> page block order
----------------------------------------------------------------0x26000 | 0x25e00 | 0x97 0x26100 | 0x25f00 | 0x97 0x26200 | 0x26000 | 0x98 0x26300 | 0x26100 | 0x98This means that calling {get,set}_pageblock_migratetype on a single page will not set the migratetype for the full block. Fix this by rounding down
zone_start_pfnwhen doing the bitidx calculation.Signed-off-by Laura Abbott <[email protected]>--- mm/page_alloc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)mm/page_alloc.c +0
-0
mm/page_alloc.c static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) · line 5428
Quoted 8 lines
mm/page_alloc.c +1
-1@@ -5422,7 +5422,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) pfn &= (PAGES_PER_SECTION -1 );return (pfn >> pageblock_order) *NR_PAGEBLOCK_BITS ;#else - pfn = pfn - zone->zone_start_pfn; + pfn = pfn -round_down (zone->start_pfn, pageblock_nr_pages);return (pfn >> pageblock_order) *NR_PAGEBLOCK_BITS ;#endif /* CONFIG_SPARSEMEM */ }
Sorry for the spam, please ignore this one. This has a typo. Third times the charm.
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation