Re: [PATCH 5/5] mm: consider per-zone inactive ratio to deactivate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Mel,

On Wed, Jul 20, 2016 at 04:21:51PM +0100, Mel Gorman wrote:
> From: Minchan Kim <minchan@xxxxxxxxxx>
> 
> Minchan Kim reported that with per-zone lru state it was possible to
> identify that a normal zone with 8^M anonymous pages could trigger
> OOM with non-atomic order-0 allocations as all pages in the zone
> were in the active list.
> 
>    gfp_mask=0x26004c0(GFP_KERNEL|__GFP_REPEAT|__GFP_NOTRACK), order=0
>    Call Trace:
>     [<c51a76e2>] __alloc_pages_nodemask+0xe52/0xe60
>     [<c51f31dc>] ? new_slab+0x39c/0x3b0
>     [<c51f31dc>] new_slab+0x39c/0x3b0
>     [<c51f4eca>] ___slab_alloc.constprop.87+0x6da/0x840
>     [<c563e6fc>] ? __alloc_skb+0x3c/0x260
>     [<c50b8e93>] ? enqueue_task_fair+0x73/0xbf0
>     [<c5219ee0>] ? poll_select_copy_remaining+0x140/0x140
>     [<c5201645>] __slab_alloc.isra.81.constprop.86+0x40/0x6d
>     [<c563e6fc>] ? __alloc_skb+0x3c/0x260
>     [<c51f525c>] kmem_cache_alloc+0x22c/0x260
>     [<c563e6fc>] ? __alloc_skb+0x3c/0x260
>     [<c563e6fc>] __alloc_skb+0x3c/0x260
>     [<c563eece>] alloc_skb_with_frags+0x4e/0x1a0
>     [<c5638d6a>] sock_alloc_send_pskb+0x16a/0x1b0
>     [<c570b581>] ? wait_for_unix_gc+0x31/0x90
>     [<c57084dd>] unix_stream_sendmsg+0x28d/0x340
>     [<c5634dad>] sock_sendmsg+0x2d/0x40
>     [<c5634e2c>] sock_write_iter+0x6c/0xc0
>     [<c5204a90>] __vfs_write+0xc0/0x120
>     [<c52053ab>] vfs_write+0x9b/0x1a0
>     [<c51cc4a9>] ? __might_fault+0x49/0xa0
>     [<c52062c4>] SyS_write+0x44/0x90
>     [<c50036c6>] do_fast_syscall_32+0xa6/0x1e0
> 
>    Mem-Info:
>    active_anon:101103 inactive_anon:102219 isolated_anon:0
>     active_file:503 inactive_file:544 isolated_file:0
>     unevictable:0 dirty:0 writeback:34 unstable:0
>     slab_reclaimable:6298 slab_unreclaimable:74669
>     mapped:863 shmem:0 pagetables:100998 bounce:0
>     free:23573 free_pcp:1861 free_cma:0
>    Node 0 active_anon:404412kB inactive_anon:409040kB active_file:2012kB inactive_file:2176kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:3452kB dirty:0kB writeback:136kB shmem:0kB writeback_tmp:0kB unstable:0kB pages_scanned:1320845 all_unreclaimable? yes
>    DMA free:3296kB min:68kB low:84kB high:100kB active_anon:5540kB inactive_anon:0kB active_file:0kB inactive_file:0kB present:15992kB managed:15916kB mlocked:0kB slab_reclaimable:248kB slab_unreclaimable:2628kB kernel_stack:792kB pagetables:2316kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
>    lowmem_reserve[]: 0 809 1965 1965
>    Normal free:3600kB min:3604kB low:4504kB high:5404kB active_anon:86304kB inactive_anon:0kB active_file:160kB inactive_file:376kB present:897016kB managed:858524kB mlocked:0kB slab_reclaimable:24944kB slab_unreclaimable:296048kB kernel_stack:163832kB pagetables:35892kB bounce:0kB free_pcp:3076kB local_pcp:656kB free_cma:0kB
>    lowmem_reserve[]: 0 0 9247 9247
>    HighMem free:86156kB min:512kB low:1796kB high:3080kB active_anon:312852kB inactive_anon:410024kB active_file:1924kB inactive_file:2012kB present:1183736kB managed:1183736kB mlocked:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:365784kB bounce:0kB free_pcp:3868kB local_pcp:720kB free_cma:0kB
>    lowmem_reserve[]: 0 0 0 0
>    DMA: 8*4kB (UM) 8*8kB (UM) 4*16kB (M) 2*32kB (UM) 2*64kB (UM) 1*128kB (M) 3*256kB (UME) 2*512kB (UE) 1*1024kB (E) 0*2048kB 0*4096kB = 3296kB
>    Normal: 240*4kB (UME) 160*8kB (UME) 23*16kB (ME) 3*32kB (UE) 3*64kB (UME) 2*128kB (ME) 1*256kB (U) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3408kB
>    HighMem: 10942*4kB (UM) 3102*8kB (UM) 866*16kB (UM) 76*32kB (UM) 11*64kB (UM) 4*128kB (UM) 1*256kB (M) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 86344kB
>    Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
>    54409 total pagecache pages
>    53215 pages in swap cache
>    Swap cache stats: add 300982, delete 247765, find 157978/226539
>    Free swap  = 3803244kB
>    Total swap = 4192252kB
>    524186 pages RAM
>    295934 pages HighMem/MovableOnly
>    9642 pages reserved
>    0 pages cma reserved
> 
> The problem is due to the active deactivation logic in inactive_list_is_low.
> 
> 	Node 0 active_anon:404412kB inactive_anon:409040kB
> 
> IOW, (inactive_anon of node * inactive_ratio > active_anon of node) due to
> highmem anonymous stat so VM never deactivates normal zone's anonymous pages.
> 
> This patch is a modified version of Minchan's original solution but based
> upon it. The problem with Minchan's patch is that it didn't take memcg
> into account and any low zone with an imbalanced list could force a rotation.

Could you explan why we should consider memcg here?

> 
> In this page, a zone-constrained global reclaim will rotate the list if

          patch,

> the inactive/active ratio of all eligible zones needs to be corrected. It
> is possible that higher zone pages will be initially rotated prematurely
> but this is the safer choice to maintain overall LRU age.
> 
> Signed-off-by: Minchan Kim <minchan@xxxxxxxxxx>
> Signed-off-by: Mel Gorman <mgorman@xxxxxxxxxxxxxxxxxxx>
> ---
>  mm/vmscan.c | 37 ++++++++++++++++++++++++++++++++-----
>  1 file changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 8f5959469079..dddf73f4293c 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -1976,7 +1976,8 @@ static void shrink_active_list(unsigned long nr_to_scan,
>   *    1TB     101        10GB
>   *   10TB     320        32GB
>   */
> -static bool inactive_list_is_low(struct lruvec *lruvec, bool file)
> +static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
> +						struct scan_control *sc)
>  {
>  	unsigned long inactive_ratio;
>  	unsigned long inactive;
> @@ -1993,6 +1994,32 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file)
>  	inactive = lruvec_lru_size(lruvec, file * LRU_FILE);
>  	active = lruvec_lru_size(lruvec, file * LRU_FILE + LRU_ACTIVE);
>  
> +	/*
> +	 * For global reclaim on zone-constrained allocations, it is necessary
> +	 * to check if rotations are required for lowmem to be reclaimed. This
> +	 * calculates the inactive/active pages available in eligible zones.
> +	 */
> +	if (global_reclaim(sc)) {
> +		struct pglist_data *pgdat = lruvec_pgdat(lruvec);
> +		int zid;
> +
> +		for (zid = sc->reclaim_idx; zid < MAX_NR_ZONES; zid++) {
> +			struct zone *zone = &pgdat->node_zones[zid];
> +			unsigned long inactive_zone, active_zone;
> +
> +			if (!populated_zone(zone))
> +				continue;
> +
> +			inactive_zone = zone_page_state(zone,
> +					NR_ZONE_LRU_BASE + (file * LRU_FILE));
> +			active_zone = zone_page_state(zone,
> +					NR_ZONE_LRU_BASE + (file * LRU_FILE) + LRU_ACTIVE);
> +
> +			inactive -= min(inactive, inactive_zone);
> +			active -= min(active, active_zone);
> +		}
> +	}
> +
>  	gb = (inactive + active) >> (30 - PAGE_SHIFT);
>  	if (gb)
>  		inactive_ratio = int_sqrt(10 * gb);
> @@ -2006,7 +2033,7 @@ static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
>  				 struct lruvec *lruvec, struct scan_control *sc)
>  {
>  	if (is_active_lru(lru)) {
> -		if (inactive_list_is_low(lruvec, is_file_lru(lru)))
> +		if (inactive_list_is_low(lruvec, is_file_lru(lru), sc))
>  			shrink_active_list(nr_to_scan, lruvec, sc, lru);
>  		return 0;
>  	}
> @@ -2137,7 +2164,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
>  	 * lruvec even if it has plenty of old anonymous pages unless the
>  	 * system is under heavy pressure.
>  	 */
> -	if (!inactive_list_is_low(lruvec, true) &&
> +	if (!inactive_list_is_low(lruvec, true, sc) &&
>  	    lruvec_lru_size(lruvec, LRU_INACTIVE_FILE) >> sc->priority) {
>  		scan_balance = SCAN_FILE;
>  		goto out;
> @@ -2379,7 +2406,7 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
>  	 * Even if we did not try to evict anon pages at all, we want to
>  	 * rebalance the anon lru active/inactive ratio.
>  	 */
> -	if (inactive_list_is_low(lruvec, false))
> +	if (inactive_list_is_low(lruvec, false, sc))
>  		shrink_active_list(SWAP_CLUSTER_MAX, lruvec,
>  				   sc, LRU_ACTIVE_ANON);
>  
> @@ -3032,7 +3059,7 @@ static void age_active_anon(struct pglist_data *pgdat,
>  	do {
>  		struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg);
>  
> -		if (inactive_list_is_low(lruvec, false))
> +		if (inactive_list_is_low(lruvec, false, sc))
>  			shrink_active_list(SWAP_CLUSTER_MAX, lruvec,
>  					   sc, LRU_ACTIVE_ANON);
>  
> -- 
> 2.6.4
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]