From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754416AbcE3JCB (ORCPT ); Mon, 30 May 2016 05:02:01 -0400 Received: from outbound-smtp07.blacknight.com ([46.22.139.12]:47020 "EHLO outbound-smtp07.blacknight.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752042AbcE3JB6 (ORCPT ); Mon, 30 May 2016 05:01:58 -0400 Date: Mon, 30 May 2016 10:01:54 +0100 From: Mel Gorman To: Andrew Morton Cc: Vlastimil Babka , Naoya Horiguchi , Linux-MM , LKML Subject: [PATCH] mm, page_alloc: prevent infinite loop in buffered_rmqueue() Message-ID: <20160530090154.GM2527@techsingularity.net> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Vlastimil Babka In DEBUG_VM kernel, we can hit infinite loop for order == 0 in buffered_rmqueue() when check_new_pcp() returns 1, because the bad page is never removed from the pcp list. Fix this by removing the page before retrying. Also we don't need to check if page is non-NULL, because we simply grab it from the list which was just tested for being non-empty. Fixes: http://www.ozlabs.org/~akpm/mmotm/broken-out/mm-page_alloc-defer-debugging-checks-of-freed-pages-until-a-pcp-drain.patch Reported-by: Naoya Horiguchi Signed-off-by: Vlastimil Babka Signed-off-by: Mel Gorman --- mm/page_alloc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f8f3bfc435ee..bb320cde4d6d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2609,11 +2609,12 @@ struct page *buffered_rmqueue(struct zone *preferred_zone, page = list_last_entry(list, struct page, lru); else page = list_first_entry(list, struct page, lru); - } while (page && check_new_pcp(page)); - __dec_zone_state(zone, NR_ALLOC_BATCH); - list_del(&page->lru); - pcp->count--; + __dec_zone_state(zone, NR_ALLOC_BATCH); + list_del(&page->lru); + pcp->count--; + + } while (check_new_pcp(page)); } else { /* * We most definitely don't want callers attempting to