Skip to contentSkip to conversation

mm: Use aligned zone start for pfn_to_bitidx calculation

PATCH Superseded Laura Abbott 1 participant 2 messages Dec 6, 2012

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

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
index 92dd060..2e06abd 100644
@@ -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
#1 lore raw
Quoted 29 lines · Laura Abbott

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 +0 -0
index 92dd060..2e06abd 100644

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