mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	mm: add & use zone_end_pfn() and zone_spans_pfn()
Add 2 helpers (zone_end_pfn() and zone_spans_pfn()) to reduce code duplication. This also switches to using them in compaction (where an additional variable needed to be renamed), page_alloc, vmstat, memory_hotplug, and kmemleak. Note that in compaction.c I avoid calling zone_end_pfn() repeatedly because I expect at some point the sycronization issues with start_pfn & spanned_pages will need fixing, either by actually using the seqlock or clever memory barrier usage. Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com> Cc: David Hansen <dave@linux.vnet.ibm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Mel Gorman <mel@csn.ul.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									9127ab4ff9
								
							
						
					
					
						commit
						108bcc96ef
					
				
					 6 changed files with 32 additions and 27 deletions
				
			
		| 
						 | 
					@ -527,6 +527,16 @@ static inline int zone_is_oom_locked(const struct zone *zone)
 | 
				
			||||||
	return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 | 
						return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned zone_end_pfn(const struct zone *zone)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return zone->zone_start_pfn + zone->spanned_pages;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool zone_spans_pfn(const struct zone *zone, unsigned long pfn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return zone->zone_start_pfn <= pfn && pfn < zone_end_pfn(zone);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The "priority" of VM scanning is how much of the queues we will scan in one
 | 
					 * The "priority" of VM scanning is how much of the queues we will scan in one
 | 
				
			||||||
 * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
 | 
					 * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ static inline bool isolation_suitable(struct compact_control *cc,
 | 
				
			||||||
static void __reset_isolation_suitable(struct zone *zone)
 | 
					static void __reset_isolation_suitable(struct zone *zone)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long start_pfn = zone->zone_start_pfn;
 | 
						unsigned long start_pfn = zone->zone_start_pfn;
 | 
				
			||||||
	unsigned long end_pfn = zone->zone_start_pfn + zone->spanned_pages;
 | 
						unsigned long end_pfn = zone_end_pfn(zone);
 | 
				
			||||||
	unsigned long pfn;
 | 
						unsigned long pfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	zone->compact_cached_migrate_pfn = start_pfn;
 | 
						zone->compact_cached_migrate_pfn = start_pfn;
 | 
				
			||||||
| 
						 | 
					@ -647,7 +647,7 @@ static void isolate_freepages(struct zone *zone,
 | 
				
			||||||
				struct compact_control *cc)
 | 
									struct compact_control *cc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct page *page;
 | 
						struct page *page;
 | 
				
			||||||
	unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
 | 
						unsigned long high_pfn, low_pfn, pfn, z_end_pfn, end_pfn;
 | 
				
			||||||
	int nr_freepages = cc->nr_freepages;
 | 
						int nr_freepages = cc->nr_freepages;
 | 
				
			||||||
	struct list_head *freelist = &cc->freepages;
 | 
						struct list_head *freelist = &cc->freepages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -666,7 +666,7 @@ static void isolate_freepages(struct zone *zone,
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	high_pfn = min(low_pfn, pfn);
 | 
						high_pfn = min(low_pfn, pfn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages;
 | 
						z_end_pfn = zone_end_pfn(zone);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Isolate free pages until enough are available to migrate the
 | 
						 * Isolate free pages until enough are available to migrate the
 | 
				
			||||||
| 
						 | 
					@ -709,7 +709,7 @@ static void isolate_freepages(struct zone *zone,
 | 
				
			||||||
		 * only scans within a pageblock
 | 
							 * only scans within a pageblock
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
 | 
							end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
 | 
				
			||||||
		end_pfn = min(end_pfn, zone_end_pfn);
 | 
							end_pfn = min(end_pfn, z_end_pfn);
 | 
				
			||||||
		isolated = isolate_freepages_block(cc, pfn, end_pfn,
 | 
							isolated = isolate_freepages_block(cc, pfn, end_pfn,
 | 
				
			||||||
						   freelist, false);
 | 
											   freelist, false);
 | 
				
			||||||
		nr_freepages += isolated;
 | 
							nr_freepages += isolated;
 | 
				
			||||||
| 
						 | 
					@ -923,7 +923,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	unsigned long start_pfn = zone->zone_start_pfn;
 | 
						unsigned long start_pfn = zone->zone_start_pfn;
 | 
				
			||||||
	unsigned long end_pfn = zone->zone_start_pfn + zone->spanned_pages;
 | 
						unsigned long end_pfn = zone_end_pfn(zone);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = compaction_suitable(zone, cc->order);
 | 
						ret = compaction_suitable(zone, cc->order);
 | 
				
			||||||
	switch (ret) {
 | 
						switch (ret) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1300,9 +1300,8 @@ static void kmemleak_scan(void)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	lock_memory_hotplug();
 | 
						lock_memory_hotplug();
 | 
				
			||||||
	for_each_online_node(i) {
 | 
						for_each_online_node(i) {
 | 
				
			||||||
		pg_data_t *pgdat = NODE_DATA(i);
 | 
							unsigned long start_pfn = node_start_pfn(i);
 | 
				
			||||||
		unsigned long start_pfn = pgdat->node_start_pfn;
 | 
							unsigned long end_pfn = node_end_pfn(i);
 | 
				
			||||||
		unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
 | 
					 | 
				
			||||||
		unsigned long pfn;
 | 
							unsigned long pfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (pfn = start_pfn; pfn < end_pfn; pfn++) {
 | 
							for (pfn = start_pfn; pfn < end_pfn; pfn++) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -299,7 +299,7 @@ static int __meminit move_pfn_range_left(struct zone *z1, struct zone *z2,
 | 
				
			||||||
	pgdat_resize_lock(z1->zone_pgdat, &flags);
 | 
						pgdat_resize_lock(z1->zone_pgdat, &flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* can't move pfns which are higher than @z2 */
 | 
						/* can't move pfns which are higher than @z2 */
 | 
				
			||||||
	if (end_pfn > z2->zone_start_pfn + z2->spanned_pages)
 | 
						if (end_pfn > zone_end_pfn(z2))
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
	/* the move out part mast at the left most of @z2 */
 | 
						/* the move out part mast at the left most of @z2 */
 | 
				
			||||||
	if (start_pfn > z2->zone_start_pfn)
 | 
						if (start_pfn > z2->zone_start_pfn)
 | 
				
			||||||
| 
						 | 
					@ -315,7 +315,7 @@ static int __meminit move_pfn_range_left(struct zone *z1, struct zone *z2,
 | 
				
			||||||
		z1_start_pfn = start_pfn;
 | 
							z1_start_pfn = start_pfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resize_zone(z1, z1_start_pfn, end_pfn);
 | 
						resize_zone(z1, z1_start_pfn, end_pfn);
 | 
				
			||||||
	resize_zone(z2, end_pfn, z2->zone_start_pfn + z2->spanned_pages);
 | 
						resize_zone(z2, end_pfn, zone_end_pfn(z2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pgdat_resize_unlock(z1->zone_pgdat, &flags);
 | 
						pgdat_resize_unlock(z1->zone_pgdat, &flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -347,15 +347,15 @@ static int __meminit move_pfn_range_right(struct zone *z1, struct zone *z2,
 | 
				
			||||||
	if (z1->zone_start_pfn > start_pfn)
 | 
						if (z1->zone_start_pfn > start_pfn)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
	/* the move out part mast at the right most of @z1 */
 | 
						/* the move out part mast at the right most of @z1 */
 | 
				
			||||||
	if (z1->zone_start_pfn + z1->spanned_pages >  end_pfn)
 | 
						if (zone_end_pfn(z1) >  end_pfn)
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
	/* must included/overlap */
 | 
						/* must included/overlap */
 | 
				
			||||||
	if (start_pfn >= z1->zone_start_pfn + z1->spanned_pages)
 | 
						if (start_pfn >= zone_end_pfn(z1))
 | 
				
			||||||
		goto out_fail;
 | 
							goto out_fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* use end_pfn for z2's end_pfn if z2 is empty */
 | 
						/* use end_pfn for z2's end_pfn if z2 is empty */
 | 
				
			||||||
	if (z2->spanned_pages)
 | 
						if (z2->spanned_pages)
 | 
				
			||||||
		z2_end_pfn = z2->zone_start_pfn + z2->spanned_pages;
 | 
							z2_end_pfn = zone_end_pfn(z2);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		z2_end_pfn = end_pfn;
 | 
							z2_end_pfn = end_pfn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,9 +250,7 @@ static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		seq = zone_span_seqbegin(zone);
 | 
							seq = zone_span_seqbegin(zone);
 | 
				
			||||||
		if (pfn >= zone->zone_start_pfn + zone->spanned_pages)
 | 
							if (!zone_spans_pfn(zone, pfn))
 | 
				
			||||||
			ret = 1;
 | 
					 | 
				
			||||||
		else if (pfn < zone->zone_start_pfn)
 | 
					 | 
				
			||||||
			ret = 1;
 | 
								ret = 1;
 | 
				
			||||||
	} while (zone_span_seqretry(zone, seq));
 | 
						} while (zone_span_seqretry(zone, seq));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -990,9 +988,9 @@ int move_freepages_block(struct zone *zone, struct page *page,
 | 
				
			||||||
	end_pfn = start_pfn + pageblock_nr_pages - 1;
 | 
						end_pfn = start_pfn + pageblock_nr_pages - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Do not cross zone boundaries */
 | 
						/* Do not cross zone boundaries */
 | 
				
			||||||
	if (start_pfn < zone->zone_start_pfn)
 | 
						if (!zone_spans_pfn(zone, start_pfn))
 | 
				
			||||||
		start_page = page;
 | 
							start_page = page;
 | 
				
			||||||
	if (end_pfn >= zone->zone_start_pfn + zone->spanned_pages)
 | 
						if (!zone_spans_pfn(zone, end_pfn))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return move_freepages(zone, start_page, end_page, migratetype);
 | 
						return move_freepages(zone, start_page, end_page, migratetype);
 | 
				
			||||||
| 
						 | 
					@ -1286,7 +1284,7 @@ void mark_free_pages(struct zone *zone)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&zone->lock, flags);
 | 
						spin_lock_irqsave(&zone->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	max_zone_pfn = zone->zone_start_pfn + zone->spanned_pages;
 | 
						max_zone_pfn = zone_end_pfn(zone);
 | 
				
			||||||
	for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
 | 
						for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++)
 | 
				
			||||||
		if (pfn_valid(pfn)) {
 | 
							if (pfn_valid(pfn)) {
 | 
				
			||||||
			struct page *page = pfn_to_page(pfn);
 | 
								struct page *page = pfn_to_page(pfn);
 | 
				
			||||||
| 
						 | 
					@ -3798,7 +3796,7 @@ static void setup_zone_migrate_reserve(struct zone *zone)
 | 
				
			||||||
	 * the block.
 | 
						 * the block.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	start_pfn = zone->zone_start_pfn;
 | 
						start_pfn = zone->zone_start_pfn;
 | 
				
			||||||
	end_pfn = start_pfn + zone->spanned_pages;
 | 
						end_pfn = zone_end_pfn(zone);
 | 
				
			||||||
	start_pfn = roundup(start_pfn, pageblock_nr_pages);
 | 
						start_pfn = roundup(start_pfn, pageblock_nr_pages);
 | 
				
			||||||
	reserve = roundup(min_wmark_pages(zone), pageblock_nr_pages) >>
 | 
						reserve = roundup(min_wmark_pages(zone), pageblock_nr_pages) >>
 | 
				
			||||||
							pageblock_order;
 | 
												pageblock_order;
 | 
				
			||||||
| 
						 | 
					@ -3912,7 +3910,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 | 
				
			||||||
		 * pfn out of zone.
 | 
							 * pfn out of zone.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if ((z->zone_start_pfn <= pfn)
 | 
							if ((z->zone_start_pfn <= pfn)
 | 
				
			||||||
		    && (pfn < z->zone_start_pfn + z->spanned_pages)
 | 
							    && (pfn < zone_end_pfn(z))
 | 
				
			||||||
		    && !(pfn & (pageblock_nr_pages - 1)))
 | 
							    && !(pfn & (pageblock_nr_pages - 1)))
 | 
				
			||||||
			set_pageblock_migratetype(page, MIGRATE_MOVABLE);
 | 
								set_pageblock_migratetype(page, MIGRATE_MOVABLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4713,7 +4711,7 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
 | 
				
			||||||
		 * for the buddy allocator to function correctly.
 | 
							 * for the buddy allocator to function correctly.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
 | 
							start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);
 | 
				
			||||||
		end = pgdat->node_start_pfn + pgdat->node_spanned_pages;
 | 
							end = pgdat_end_pfn(pgdat);
 | 
				
			||||||
		end = ALIGN(end, MAX_ORDER_NR_PAGES);
 | 
							end = ALIGN(end, MAX_ORDER_NR_PAGES);
 | 
				
			||||||
		size =  (end - start) * sizeof(struct page);
 | 
							size =  (end - start) * sizeof(struct page);
 | 
				
			||||||
		map = alloc_remap(pgdat->node_id, size);
 | 
							map = alloc_remap(pgdat->node_id, size);
 | 
				
			||||||
| 
						 | 
					@ -5928,8 +5926,7 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
 | 
				
			||||||
	pfn = page_to_pfn(page);
 | 
						pfn = page_to_pfn(page);
 | 
				
			||||||
	bitmap = get_pageblock_bitmap(zone, pfn);
 | 
						bitmap = get_pageblock_bitmap(zone, pfn);
 | 
				
			||||||
	bitidx = pfn_to_bitidx(zone, pfn);
 | 
						bitidx = pfn_to_bitidx(zone, pfn);
 | 
				
			||||||
	VM_BUG_ON(pfn < zone->zone_start_pfn);
 | 
						VM_BUG_ON(!zone_spans_pfn(zone, pfn));
 | 
				
			||||||
	VM_BUG_ON(pfn >= zone->zone_start_pfn + zone->spanned_pages);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
 | 
						for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
 | 
				
			||||||
		if (flags & value)
 | 
							if (flags & value)
 | 
				
			||||||
| 
						 | 
					@ -6027,8 +6024,7 @@ bool is_pageblock_removable_nolock(struct page *page)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	zone = page_zone(page);
 | 
						zone = page_zone(page);
 | 
				
			||||||
	pfn = page_to_pfn(page);
 | 
						pfn = page_to_pfn(page);
 | 
				
			||||||
	if (zone->zone_start_pfn > pfn ||
 | 
						if (!zone_spans_pfn(zone, pfn))
 | 
				
			||||||
			zone->zone_start_pfn + zone->spanned_pages <= pfn)
 | 
					 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return !has_unmovable_pages(zone, page, 0, true);
 | 
						return !has_unmovable_pages(zone, page, 0, true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -891,7 +891,7 @@ static void pagetypeinfo_showblockcount_print(struct seq_file *m,
 | 
				
			||||||
	int mtype;
 | 
						int mtype;
 | 
				
			||||||
	unsigned long pfn;
 | 
						unsigned long pfn;
 | 
				
			||||||
	unsigned long start_pfn = zone->zone_start_pfn;
 | 
						unsigned long start_pfn = zone->zone_start_pfn;
 | 
				
			||||||
	unsigned long end_pfn = start_pfn + zone->spanned_pages;
 | 
						unsigned long end_pfn = zone_end_pfn(zone);
 | 
				
			||||||
	unsigned long count[MIGRATE_TYPES] = { 0, };
 | 
						unsigned long count[MIGRATE_TYPES] = { 0, };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
 | 
						for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue