diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 185 | 
1 files changed, 94 insertions, 91 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bcb72c6e2b2..5a8d339d282 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -667,11 +667,13 @@ static void free_pcppages_bulk(struct zone *zone, int count,  			/* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */  			__free_one_page(page, zone, 0, mt);  			trace_mm_page_pcpu_drain(page, 0, mt); -			if (is_migrate_cma(mt)) -				__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, 1); +			if (likely(get_pageblock_migratetype(page) != MIGRATE_ISOLATE)) { +				__mod_zone_page_state(zone, NR_FREE_PAGES, 1); +				if (is_migrate_cma(mt)) +					__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, 1); +			}  		} while (--to_free && --batch_free && !list_empty(list));  	} -	__mod_zone_page_state(zone, NR_FREE_PAGES, count);  	spin_unlock(&zone->lock);  } @@ -1392,21 +1394,22 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)  	zone = page_zone(page);  	order = page_order(page); +	mt = get_pageblock_migratetype(page); -	/* Obey watermarks as if the page was being allocated */ -	watermark = low_wmark_pages(zone) + (1 << order); -	if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) -		return 0; +	if (mt != MIGRATE_ISOLATE) { +		/* Obey watermarks as if the page was being allocated */ +		watermark = low_wmark_pages(zone) + (1 << order); +		if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) +			return 0; + +		__mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); +	}  	/* Remove page from free list */  	list_del(&page->lru);  	zone->free_area[order].nr_free--;  	rmv_page_order(page); -	mt = get_pageblock_migratetype(page); -	if (unlikely(mt != MIGRATE_ISOLATE)) -		__mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); -  	if (alloc_order != order)  		expand(zone, page, alloc_order, order,  			&zone->free_area[order], migratetype); @@ -1422,7 +1425,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)  		}  	} -	return 1UL << order; +	return 1UL << alloc_order;  }  /* @@ -1871,7 +1874,7 @@ zonelist_scan:  	 */  	for_each_zone_zonelist_nodemask(zone, z, zonelist,  						high_zoneidx, nodemask) { -		if (NUMA_BUILD && zlc_active && +		if (IS_ENABLED(CONFIG_NUMA) && zlc_active &&  			!zlc_zone_worth_trying(zonelist, z, allowednodes))  				continue;  		if ((alloc_flags & ALLOC_CPUSET) && @@ -1917,7 +1920,8 @@ zonelist_scan:  				    classzone_idx, alloc_flags))  				goto try_this_zone; -			if (NUMA_BUILD && !did_zlc_setup && nr_online_nodes > 1) { +			if (IS_ENABLED(CONFIG_NUMA) && +					!did_zlc_setup && nr_online_nodes > 1) {  				/*  				 * we do zlc_setup if there are multiple nodes  				 * and before considering the first zone allowed @@ -1936,7 +1940,7 @@ zonelist_scan:  			 * As we may have just activated ZLC, check if the first  			 * eligible zone has failed zone_reclaim recently.  			 */ -			if (NUMA_BUILD && zlc_active && +			if (IS_ENABLED(CONFIG_NUMA) && zlc_active &&  				!zlc_zone_worth_trying(zonelist, z, allowednodes))  				continue; @@ -1962,11 +1966,11 @@ try_this_zone:  		if (page)  			break;  this_zone_full: -		if (NUMA_BUILD) +		if (IS_ENABLED(CONFIG_NUMA))  			zlc_mark_zone_full(zonelist, z);  	} -	if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) { +	if (unlikely(IS_ENABLED(CONFIG_NUMA) && page == NULL && zlc_active)) {  		/* Disable zlc cache for second zonelist scan */  		zlc_active = 0;  		goto zonelist_scan; @@ -2266,7 +2270,7 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order,  		return NULL;  	/* After successful reclaim, reconsider all zones for allocation */ -	if (NUMA_BUILD) +	if (IS_ENABLED(CONFIG_NUMA))  		zlc_clear_zones_full(zonelist);  retry: @@ -2412,12 +2416,14 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,  	 * allowed per node queues are empty and that nodes are  	 * over allocated.  	 */ -	if (NUMA_BUILD && (gfp_mask & GFP_THISNODE) == GFP_THISNODE) +	if (IS_ENABLED(CONFIG_NUMA) && +			(gfp_mask & GFP_THISNODE) == GFP_THISNODE)  		goto nopage;  restart: -	wake_all_kswapd(order, zonelist, high_zoneidx, -					zone_idx(preferred_zone)); +	if (!(gfp_mask & __GFP_NO_KSWAPD)) +		wake_all_kswapd(order, zonelist, high_zoneidx, +						zone_idx(preferred_zone));  	/*  	 * OK, we're below the kswapd watermark and have kicked background @@ -2494,7 +2500,7 @@ rebalance:  	 * system then fail the allocation instead of entering direct reclaim.  	 */  	if ((deferred_compaction || contended_compaction) && -	    (gfp_mask & (__GFP_MOVABLE|__GFP_REPEAT)) == __GFP_MOVABLE) +						(gfp_mask & __GFP_NO_KSWAPD))  		goto nopage;  	/* Try direct reclaim and then allocating */ @@ -2818,7 +2824,7 @@ unsigned int nr_free_pagecache_pages(void)  static inline void show_node(struct zone *zone)  { -	if (NUMA_BUILD) +	if (IS_ENABLED(CONFIG_NUMA))  		printk("Node %d ", zone_to_nid(zone));  } @@ -2876,6 +2882,31 @@ out:  #define K(x) ((x) << (PAGE_SHIFT-10)) +static void show_migration_types(unsigned char type) +{ +	static const char types[MIGRATE_TYPES] = { +		[MIGRATE_UNMOVABLE]	= 'U', +		[MIGRATE_RECLAIMABLE]	= 'E', +		[MIGRATE_MOVABLE]	= 'M', +		[MIGRATE_RESERVE]	= 'R', +#ifdef CONFIG_CMA +		[MIGRATE_CMA]		= 'C', +#endif +		[MIGRATE_ISOLATE]	= 'I', +	}; +	char tmp[MIGRATE_TYPES + 1]; +	char *p = tmp; +	int i; + +	for (i = 0; i < MIGRATE_TYPES; i++) { +		if (type & (1 << i)) +			*p++ = types[i]; +	} + +	*p = '\0'; +	printk("(%s) ", tmp); +} +  /*   * Show free area list (used inside shift_scroll-lock stuff)   * We also calculate the percentage fragmentation. We do this by counting the @@ -3004,6 +3035,7 @@ void show_free_areas(unsigned int filter)  	for_each_populated_zone(zone) {   		unsigned long nr[MAX_ORDER], flags, order, total = 0; +		unsigned char types[MAX_ORDER];  		if (skip_free_areas_node(filter, zone_to_nid(zone)))  			continue; @@ -3012,12 +3044,24 @@ void show_free_areas(unsigned int filter)  		spin_lock_irqsave(&zone->lock, flags);  		for (order = 0; order < MAX_ORDER; order++) { -			nr[order] = zone->free_area[order].nr_free; +			struct free_area *area = &zone->free_area[order]; +			int type; + +			nr[order] = area->nr_free;  			total += nr[order] << order; + +			types[order] = 0; +			for (type = 0; type < MIGRATE_TYPES; type++) { +				if (!list_empty(&area->free_list[type])) +					types[order] |= 1 << type; +			}  		}  		spin_unlock_irqrestore(&zone->lock, flags); -		for (order = 0; order < MAX_ORDER; order++) +		for (order = 0; order < MAX_ORDER; order++) {  			printk("%lu*%lukB ", nr[order], K(1UL) << order); +			if (nr[order]) +				show_migration_types(types[order]); +		}  		printk("= %lukB\n", K(total));  	} @@ -5174,10 +5218,6 @@ static void __setup_per_zone_wmarks(void)  		zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + (tmp >> 2);  		zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1); -		zone->watermark[WMARK_MIN] += cma_wmark_pages(zone); -		zone->watermark[WMARK_LOW] += cma_wmark_pages(zone); -		zone->watermark[WMARK_HIGH] += cma_wmark_pages(zone); -  		setup_zone_migrate_reserve(zone);  		spin_unlock_irqrestore(&zone->lock, flags);  	} @@ -5575,7 +5615,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,   * MIGRATE_MOVABLE block might include unmovable pages. It means you can't   * expect this function should be exact.   */ -bool has_unmovable_pages(struct zone *zone, struct page *page, int count) +bool has_unmovable_pages(struct zone *zone, struct page *page, int count, +			 bool skip_hwpoisoned_pages)  {  	unsigned long pfn, iter, found;  	int mt; @@ -5610,6 +5651,13 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count)  			continue;  		} +		/* +		 * The HWPoisoned page may be not in buddy system, and +		 * page_count() is not 0. +		 */ +		if (skip_hwpoisoned_pages && PageHWPoison(page)) +			continue; +  		if (!PageLRU(page))  			found++;  		/* @@ -5652,7 +5700,7 @@ bool is_pageblock_removable_nolock(struct page *page)  			zone->zone_start_pfn + zone->spanned_pages <= pfn)  		return false; -	return !has_unmovable_pages(zone, page, 0); +	return !has_unmovable_pages(zone, page, 0, true);  }  #ifdef CONFIG_CMA @@ -5710,58 +5758,10 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,  				    0, false, MIGRATE_SYNC);  	} -	putback_lru_pages(&cc->migratepages); +	putback_movable_pages(&cc->migratepages);  	return ret > 0 ? 0 : ret;  } -/* - * Update zone's cma pages counter used for watermark level calculation. - */ -static inline void __update_cma_watermarks(struct zone *zone, int count) -{ -	unsigned long flags; -	spin_lock_irqsave(&zone->lock, flags); -	zone->min_cma_pages += count; -	spin_unlock_irqrestore(&zone->lock, flags); -	setup_per_zone_wmarks(); -} - -/* - * Trigger memory pressure bump to reclaim some pages in order to be able to - * allocate 'count' pages in single page units. Does similar work as - *__alloc_pages_slowpath() function. - */ -static int __reclaim_pages(struct zone *zone, gfp_t gfp_mask, int count) -{ -	enum zone_type high_zoneidx = gfp_zone(gfp_mask); -	struct zonelist *zonelist = node_zonelist(0, gfp_mask); -	int did_some_progress = 0; -	int order = 1; - -	/* -	 * Increase level of watermarks to force kswapd do his job -	 * to stabilise at new watermark level. -	 */ -	__update_cma_watermarks(zone, count); - -	/* Obey watermarks as if the page was being allocated */ -	while (!zone_watermark_ok(zone, 0, low_wmark_pages(zone), 0, 0)) { -		wake_all_kswapd(order, zonelist, high_zoneidx, zone_idx(zone)); - -		did_some_progress = __perform_reclaim(gfp_mask, order, zonelist, -						      NULL); -		if (!did_some_progress) { -			/* Exhausted what can be done so it's blamo time */ -			out_of_memory(zonelist, gfp_mask, order, NULL, false); -		} -	} - -	/* Restore original watermark levels. */ -	__update_cma_watermarks(zone, -count); - -	return count; -} -  /**   * alloc_contig_range() -- tries to allocate given range of pages   * @start:	start PFN to allocate @@ -5785,7 +5785,6 @@ static int __reclaim_pages(struct zone *zone, gfp_t gfp_mask, int count)  int alloc_contig_range(unsigned long start, unsigned long end,  		       unsigned migratetype)  { -	struct zone *zone = page_zone(pfn_to_page(start));  	unsigned long outer_start, outer_end;  	int ret = 0, order; @@ -5823,7 +5822,8 @@ int alloc_contig_range(unsigned long start, unsigned long end,  	 */  	ret = start_isolate_page_range(pfn_max_align_down(start), -				       pfn_max_align_up(end), migratetype); +				       pfn_max_align_up(end), migratetype, +				       false);  	if (ret)  		return ret; @@ -5862,18 +5862,13 @@ int alloc_contig_range(unsigned long start, unsigned long end,  	}  	/* Make sure the range is really isolated. */ -	if (test_pages_isolated(outer_start, end)) { +	if (test_pages_isolated(outer_start, end, false)) {  		pr_warn("alloc_contig_range test_pages_isolated(%lx, %lx) failed\n",  		       outer_start, end);  		ret = -EBUSY;  		goto done;  	} -	/* -	 * Reclaim enough pages to make sure that contiguous allocation -	 * will not starve the system. -	 */ -	__reclaim_pages(zone, GFP_HIGHUSER_MOVABLE, end-start);  	/* Grab isolated pages from freelists. */  	outer_end = isolate_freepages_range(&cc, outer_start, end); @@ -5931,7 +5926,6 @@ void __meminit zone_pcp_update(struct zone *zone)  }  #endif -#ifdef CONFIG_MEMORY_HOTREMOVE  void zone_pcp_reset(struct zone *zone)  {  	unsigned long flags; @@ -5951,6 +5945,7 @@ void zone_pcp_reset(struct zone *zone)  	local_irq_restore(flags);  } +#ifdef CONFIG_MEMORY_HOTREMOVE  /*   * All pages in the range must be isolated before calling this.   */ @@ -5977,6 +5972,16 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)  			continue;  		}  		page = pfn_to_page(pfn); +		/* +		 * The HWPoisoned page may be not in buddy system, and +		 * page_count() is not 0. +		 */ +		if (unlikely(!PageBuddy(page) && PageHWPoison(page))) { +			pfn++; +			SetPageReserved(page); +			continue; +		} +  		BUG_ON(page_count(page));  		BUG_ON(!PageBuddy(page));  		order = page_order(page); @@ -5987,8 +5992,6 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)  		list_del(&page->lru);  		rmv_page_order(page);  		zone->free_area[order].nr_free--; -		__mod_zone_page_state(zone, NR_FREE_PAGES, -				      - (1UL << order));  		for (i = 0; i < (1 << order); i++)  			SetPageReserved((page+i));  		pfn += (1 << order);  |