Received: by 2002:a25:c205:0:0:0:0:0 with SMTP id s5csp2149488ybf; Mon, 2 Mar 2020 03:01:24 -0800 (PST) X-Google-Smtp-Source: APXvYqyxDwq/GmqVz0TIh2BQeJFP6tMIf/2bAijkSR/Ag+zXvkmUzd0HDwGLsMPbB2ymenTny+23 X-Received: by 2002:aca:3354:: with SMTP id z81mr11416673oiz.129.1583146884808; Mon, 02 Mar 2020 03:01:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1583146884; cv=none; d=google.com; s=arc-20160816; b=CYxKA2Ej26LY3AD/PO7T9EpQa3fIGadJcN3MPPnYM9GimzsmlwjJbl/Vt/GTvB8FJ0 Tp7X+VLBa8J6/R7/UsBB05pYRsoE601C5fO6TvA6Hw2mXXx0cnoWB2MEb18sE+Zbt1/G Lbx4dssxfG9XNRlpHQQ+3rN0cb7UYkyeADsi8fMjh3f0o7wTr6+yGo4VZe6Gcb8O6f2B LviaTu3wfC3K+LqPzyoLvBtANYuv0LXtQQWLPb+/6UXPvsjK67PW2Ht/SCXHLckSHs9j YKZcM1FooHnmsW2MLpSllWwW0q/DsWFeMu9CVCyGCSF1gsnFvsa81PEX+2R+ZNscTSOl ODBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=64musmwgjMHcFSxi3xe3DSjMAtPQdxerlv8sUrhGzpI=; b=oJrJB9qorFT/WdSU/YMHcR59YzqG6A7GguI5NnPLldYufeMwDiAHQ3JHW9Il6gkCyZ qQRWyul+rboIV760+kSjXQr7xZwJhqqXG1gcs6I2D9YXoJjAjEuTvdUzq0X0l/TMROG8 WL3Bjfkd6lmo1y9dAG8TSpCCZCMZu4eJaeVpHYSksDjO3Erk8D/Eb+5+IDrt/G/g31nQ rju1yGVMjwN7lCbOUL6ruiuOxm9C9II0FhltTJoLvFpBu6o3dNOcnXu0AoZ3piuKtbas A5NEPHqoG+b/GfP/R/yyDdEXIoQpvljNaHvpWbAG1KM4B+xghzVMYK84fP8Q/hG5DbLE ql6A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v137si4622562oif.170.2020.03.02.03.01.11; Mon, 02 Mar 2020 03:01:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727452AbgCBLBC (ORCPT + 99 others); Mon, 2 Mar 2020 06:01:02 -0500 Received: from out30-45.freemail.mail.aliyun.com ([115.124.30.45]:41417 "EHLO out30-45.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726871AbgCBLBB (ORCPT ); Mon, 2 Mar 2020 06:01:01 -0500 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R191e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04426;MF=alex.shi@linux.alibaba.com;NM=1;PH=DS;RN=14;SR=0;TI=SMTPD_---0TrQzvOy_1583146856; Received: from localhost(mailfrom:alex.shi@linux.alibaba.com fp:SMTPD_---0TrQzvOy_1583146856) by smtp.aliyun-inc.com(127.0.0.1); Mon, 02 Mar 2020 19:00:57 +0800 From: Alex Shi To: cgroups@vger.kernel.org, akpm@linux-foundation.org, mgorman@techsingularity.net, tj@kernel.org, hughd@google.com, khlebnikov@yandex-team.ru, daniel.m.jordan@oracle.com, yang.shi@linux.alibaba.com, willy@infradead.org, hannes@cmpxchg.org, lkp@intel.com Cc: Alex Shi , linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v9 08/20] mm/lru: add page isolation precondition in __isolate_lru_page Date: Mon, 2 Mar 2020 19:00:18 +0800 Message-Id: <1583146830-169516-9-git-send-email-alex.shi@linux.alibaba.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1583146830-169516-1-git-send-email-alex.shi@linux.alibaba.com> References: <1583146830-169516-1-git-send-email-alex.shi@linux.alibaba.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Johannes Weiner has suggested: " So here is a crazy idea that may be worth exploring: Right now, pgdat->lru_lock protects both PageLRU *and* the lruvec's linked list. Can we make PageLRU atomic and use it to stabilize the lru_lock instead, and then use the lru_lock only serialize list operations? ... " Yes, this patch is doing so on __isolate_lru_page which is the core page isolation func in compaction and shrinking path. This patch move clear page lru action before compaction getting lru_lock, makes it as a necessary condition for page isolation. Hence, PageLRU may be cleared druing shrink_inactive_list path for isolation reason. If so, we can skip that page's in reclaim. It's a preparation for later per memcg lru_lock change. Suggested-by: Johannes Weiner Signed-off-by: Alex Shi Cc: Andrew Morton Cc: Matthew Wilcox Cc: Hugh Dickins Cc: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org --- include/linux/swap.h | 2 +- mm/compaction.c | 25 +++++++++++++++++-------- mm/vmscan.c | 48 ++++++++++++++++++++++++++---------------------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index c555e8f161ad..69f0794f1da3 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -351,7 +351,7 @@ extern void lru_cache_add_active_or_unevictable(struct page *page, extern unsigned long zone_reclaimable_pages(struct zone *zone); extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *mask); -extern int __isolate_lru_page(struct page *page, isolate_mode_t mode); +extern int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode); extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, unsigned long nr_pages, gfp_t gfp_mask, diff --git a/mm/compaction.c b/mm/compaction.c index 672d3c78c6ab..1baba328d089 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -948,6 +948,23 @@ static bool too_many_isolated(pg_data_t *pgdat) if (!(cc->gfp_mask & __GFP_FS) && page_mapping(page)) goto isolate_fail; + if (__isolate_lru_page_prepare(page, isolate_mode) != 0) + goto isolate_fail; + + /* + * Be careful not to clear PageLRU until after we're + * sure the page is not being freed elsewhere -- the + * page release code relies on it. + */ + if (unlikely(!get_page_unless_zero(page))) + goto isolate_fail; + + /* Try isolate the page */ + if (!TestClearPageLRU(page)) { + put_page(page); + goto isolate_fail; + } + /* If we already hold the lock, we can skip some rechecking */ if (!locked) { locked = compact_lock_irqsave(&pgdat->lru_lock, @@ -960,10 +977,6 @@ static bool too_many_isolated(pg_data_t *pgdat) goto isolate_abort; } - /* Recheck PageLRU and PageCompound under lock */ - if (!PageLRU(page)) - goto isolate_fail; - /* * Page become compound since the non-locked check, * and it's on LRU. It can only be a THP so the order @@ -977,10 +990,6 @@ static bool too_many_isolated(pg_data_t *pgdat) lruvec = mem_cgroup_page_lruvec(page, pgdat); - /* Try isolate the page */ - if (__isolate_lru_page(page, isolate_mode) != 0) - goto isolate_fail; - VM_BUG_ON_PAGE(PageCompound(page), page); /* Successfully isolated */ diff --git a/mm/vmscan.c b/mm/vmscan.c index 8958454d50fe..bc2ec3fe4f48 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1522,20 +1522,20 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, * * returns 0 on success, -ve errno on failure. */ -int __isolate_lru_page(struct page *page, isolate_mode_t mode) +int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode) { int ret = -EINVAL; - /* Only take pages on the LRU. */ - if (!PageLRU(page)) - return ret; - /* Compaction should not handle unevictable pages but CMA can do so */ if (PageUnevictable(page) && !(mode & ISOLATE_UNEVICTABLE)) return ret; ret = -EBUSY; + /* Only take pages on the LRU. */ + if (!PageLRU(page)) + return ret; + /* * To minimise LRU disruption, the caller can indicate that it only * wants to isolate pages it will be able to operate on without @@ -1576,20 +1576,9 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode) if ((mode & ISOLATE_UNMAPPED) && page_mapped(page)) return ret; - if (likely(get_page_unless_zero(page))) { - /* - * Be careful not to clear PageLRU until after we're - * sure the page is not being freed elsewhere -- the - * page release code relies on it. - */ - ClearPageLRU(page); - ret = 0; - } - - return ret; + return 0; } - /* * Update LRU sizes after isolating pages. The LRU size updates must * be complete before mem_cgroup_update_lru_size due to a santity check. @@ -1653,8 +1642,6 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, page = lru_to_page(src); prefetchw_prev_lru_page(page, src, flags); - VM_BUG_ON_PAGE(!PageLRU(page), page); - nr_pages = compound_nr(page); total_scan += nr_pages; @@ -1675,17 +1662,34 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, * only when the page is being freed somewhere else. */ scan += nr_pages; - switch (__isolate_lru_page(page, mode)) { + switch (__isolate_lru_page_prepare(page, mode)) { case 0: + /* + * Be careful not to clear PageLRU until after we're + * sure the page is not being freed elsewhere -- the + * page release code relies on it. + */ + if (unlikely(!get_page_unless_zero(page))) + goto busy; + + if (!TestClearPageLRU(page)) { + /* + * This page may in other isolation path, + * but we still hold lru_lock. + */ + put_page(page); + goto busy; + } + nr_taken += nr_pages; nr_zone_taken[page_zonenum(page)] += nr_pages; list_move(&page->lru, dst); break; - +busy: case -EBUSY: /* else it is being freed elsewhere */ list_move(&page->lru, src); - continue; + break; default: BUG(); -- 1.8.3.1