diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 99 | 
1 files changed, 40 insertions, 59 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 905db9d7962f..22320ea27489 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1743,38 +1743,16 @@ void __init page_alloc_init_late(void)  }  #ifdef CONFIG_CMA -static void __init adjust_present_page_count(struct page *page, long count) -{ -	struct zone *zone = page_zone(page); - -	/* We don't need to hold a lock since it is boot-up process */ -	zone->present_pages += count; -} -  /* Free whole pageblock and set its migration type to MIGRATE_CMA. */  void __init init_cma_reserved_pageblock(struct page *page)  {  	unsigned i = pageblock_nr_pages; -	unsigned long pfn = page_to_pfn(page);  	struct page *p = page; -	int nid = page_to_nid(page); - -	/* -	 * ZONE_MOVABLE will steal present pages from other zones by -	 * changing page links so page_zone() is changed. Before that, -	 * we need to adjust previous zone's page count first. -	 */ -	adjust_present_page_count(page, -pageblock_nr_pages);  	do {  		__ClearPageReserved(p);  		set_page_count(p, 0); - -		/* Steal pages from other zones */ -		set_page_links(p, ZONE_MOVABLE, nid, pfn); -	} while (++p, ++pfn, --i); - -	adjust_present_page_count(page, pageblock_nr_pages); +	} while (++p, --i);  	set_pageblock_migratetype(page, MIGRATE_CMA); @@ -2889,7 +2867,7 @@ int __isolate_free_page(struct page *page, unsigned int order)  		 * exists.  		 */  		watermark = min_wmark_pages(zone) + (1UL << order); -		if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) +		if (!zone_watermark_ok(zone, 0, watermark, 0, ALLOC_CMA))  			return 0;  		__mod_zone_freepage_state(zone, -(1UL << order), mt); @@ -3165,6 +3143,12 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,  	} +#ifdef CONFIG_CMA +	/* If allocation can't use CMA areas don't use free CMA pages */ +	if (!(alloc_flags & ALLOC_CMA)) +		free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES); +#endif +  	/*  	 * Check watermarks for an order-0 allocation request. If these  	 * are not met, then a high-order request also cannot go ahead @@ -3191,8 +3175,10 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,  		}  #ifdef CONFIG_CMA -		if (!list_empty(&area->free_list[MIGRATE_CMA])) +		if ((alloc_flags & ALLOC_CMA) && +		    !list_empty(&area->free_list[MIGRATE_CMA])) {  			return true; +		}  #endif  		if (alloc_harder &&  			!list_empty(&area->free_list[MIGRATE_HIGHATOMIC])) @@ -3212,6 +3198,13 @@ static inline bool zone_watermark_fast(struct zone *z, unsigned int order,  		unsigned long mark, int classzone_idx, unsigned int alloc_flags)  {  	long free_pages = zone_page_state(z, NR_FREE_PAGES); +	long cma_pages = 0; + +#ifdef CONFIG_CMA +	/* If allocation can't use CMA areas don't use free CMA pages */ +	if (!(alloc_flags & ALLOC_CMA)) +		cma_pages = zone_page_state(z, NR_FREE_CMA_PAGES); +#endif  	/*  	 * Fast check for order-0 only. If this fails then the reserves @@ -3220,7 +3213,7 @@ static inline bool zone_watermark_fast(struct zone *z, unsigned int order,  	 * the caller is !atomic then it'll uselessly search the free  	 * list. That corner case is then slower but it is harmless.  	 */ -	if (!order && free_pages > mark + z->lowmem_reserve[classzone_idx]) +	if (!order && (free_pages - cma_pages) > mark + z->lowmem_reserve[classzone_idx])  		return true;  	return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, @@ -3856,6 +3849,10 @@ gfp_to_alloc_flags(gfp_t gfp_mask)  	} else if (unlikely(rt_task(current)) && !in_interrupt())  		alloc_flags |= ALLOC_HARDER; +#ifdef CONFIG_CMA +	if (gfpflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE) +		alloc_flags |= ALLOC_CMA; +#endif  	return alloc_flags;  } @@ -4322,6 +4319,9 @@ static inline bool prepare_alloc_pages(gfp_t gfp_mask, unsigned int order,  	if (should_fail_alloc_page(gfp_mask, order))  		return false; +	if (IS_ENABLED(CONFIG_CMA) && ac->migratetype == MIGRATE_MOVABLE) +		*alloc_flags |= ALLOC_CMA; +  	return true;  } @@ -6204,7 +6204,6 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)  {  	enum zone_type j;  	int nid = pgdat->node_id; -	unsigned long node_end_pfn = 0;  	pgdat_resize_init(pgdat);  #ifdef CONFIG_NUMA_BALANCING @@ -6232,13 +6231,9 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)  		struct zone *zone = pgdat->node_zones + j;  		unsigned long size, realsize, freesize, memmap_pages;  		unsigned long zone_start_pfn = zone->zone_start_pfn; -		unsigned long movable_size = 0;  		size = zone->spanned_pages;  		realsize = freesize = zone->present_pages; -		if (zone_end_pfn(zone) > node_end_pfn) -			node_end_pfn = zone_end_pfn(zone); -  		/*  		 * Adjust freesize so that it accounts for how much memory @@ -6287,30 +6282,12 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)  		zone_seqlock_init(zone);  		zone_pcp_init(zone); -		/* -		 * The size of the CMA area is unknown now so we need to -		 * prepare the memory for the usemap at maximum. -		 */ -		if (IS_ENABLED(CONFIG_CMA) && j == ZONE_MOVABLE && -			pgdat->node_spanned_pages) { -			movable_size = node_end_pfn - pgdat->node_start_pfn; -		} - -		if (!size && !movable_size) +		if (!size)  			continue;  		set_pageblock_order(); -		if (movable_size) { -			zone->zone_start_pfn = pgdat->node_start_pfn; -			zone->spanned_pages = movable_size; -			setup_usemap(pgdat, zone, -				pgdat->node_start_pfn, movable_size); -			init_currently_empty_zone(zone, -				pgdat->node_start_pfn, movable_size); -		} else { -			setup_usemap(pgdat, zone, zone_start_pfn, size); -			init_currently_empty_zone(zone, zone_start_pfn, size); -		} +		setup_usemap(pgdat, zone, zone_start_pfn, size); +		init_currently_empty_zone(zone, zone_start_pfn, size);  		memmap_init(size, nid, j, zone_start_pfn);  	}  } @@ -7621,11 +7598,12 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,  	unsigned long pfn, iter, found;  	/* -	 * For avoiding noise data, lru_add_drain_all() should be called -	 * If ZONE_MOVABLE, the zone never contains unmovable pages +	 * TODO we could make this much more efficient by not checking every +	 * page in the range if we know all of them are in MOVABLE_ZONE and +	 * that the movable zone guarantees that pages are migratable but +	 * the later is not the case right now unfortunatelly. E.g. movablecore +	 * can still lead to having bootmem allocations in zone_movable.  	 */ -	if (zone_idx(zone) == ZONE_MOVABLE) -		return false;  	/*  	 * CMA allocations (alloc_contig_range) really need to mark isolate @@ -7646,7 +7624,7 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,  		page = pfn_to_page(check);  		if (PageReserved(page)) -			return true; +			goto unmovable;  		/*  		 * Hugepages are not in LRU lists, but they're movable. @@ -7696,9 +7674,12 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,  		 * page at boot.  		 */  		if (found > count) -			return true; +			goto unmovable;  	}  	return false; +unmovable: +	WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE); +	return true;  }  bool is_pageblock_removable_nolock(struct page *page) @@ -7951,7 +7932,7 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages)  }  #endif -#if defined CONFIG_MEMORY_HOTPLUG || defined CONFIG_CMA +#ifdef CONFIG_MEMORY_HOTPLUG  /*   * The zone indicated has a new number of managed_pages; batch sizes and percpu   * page high values need to be recalulated.  | 
