From patchwork Wed Nov 27 10:28:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kefeng Wang X-Patchwork-Id: 11263795 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CC54013A4 for ; Wed, 27 Nov 2019 10:30:19 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id A1F0D2080F for ; Wed, 27 Nov 2019 10:30:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A1F0D2080F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=huawei.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id D18636B037D; Wed, 27 Nov 2019 05:30:18 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id CA1916B037F; Wed, 27 Nov 2019 05:30:18 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BDE076B0380; Wed, 27 Nov 2019 05:30:18 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0148.hostedemail.com [216.40.44.148]) by kanga.kvack.org (Postfix) with ESMTP id A60FE6B037D for ; Wed, 27 Nov 2019 05:30:18 -0500 (EST) Received: from smtpin03.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with SMTP id 62BDB8249980 for ; Wed, 27 Nov 2019 10:30:18 +0000 (UTC) X-FDA: 76201687716.03.mint72_59ea90b71913e X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,wangkefeng.wang@huawei.com,::wangkefeng.wang@huawei.com:akpm@linux-foundation.org:mhocko@suse.com:vbabka@suse.cz,RULES_HIT:30003:30054:30056:30069:30070,0,RBL:45.249.212.191:@huawei.com:.lbl8.mailshell.net-62.18.2.100 64.95.201.95,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:none,Custom_rules:0:0:0,LFtime:24,LUA_SUMMARY:none X-HE-Tag: mint72_59ea90b71913e X-Filterd-Recvd-Size: 5105 Received: from huawei.com (szxga05-in.huawei.com [45.249.212.191]) by imf36.hostedemail.com (Postfix) with ESMTP for ; Wed, 27 Nov 2019 10:30:17 +0000 (UTC) Received: from DGGEMS408-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id DAB85F4590DDA1697B3A; Wed, 27 Nov 2019 18:30:09 +0800 (CST) Received: from localhost.localdomain.localdomain (10.175.113.25) by DGGEMS408-HUB.china.huawei.com (10.3.19.208) with Microsoft SMTP Server id 14.3.439.0; Wed, 27 Nov 2019 18:30:00 +0800 From: Kefeng Wang To: CC: Kefeng Wang , Andrew Morton , Michal Hocko , Vlastimil Babka Subject: [RFC PATCH] mm, page_alloc: avoid page_to_pfn() in move_freepages() Date: Wed, 27 Nov 2019 18:28:00 +0800 Message-ID: <20191127102800.51526-1-wangkefeng.wang@huawei.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-Originating-IP: [10.175.113.25] X-CFilter-Loop: Reflected X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: The start_pfn and end_pfn are already available in move_freepages_block(), pfn_valid_within() should validate pfn first before touching the page, or we might access an unitialized page with CONFIG_HOLES_IN_ZONE configs. Cc: Andrew Morton Cc: Michal Hocko Cc: Vlastimil Babka Signed-off-by: Kefeng Wang --- Here is an oops in 4.4(arm64 enabled CONFIG_HOLES_IN_ZONE), Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = ffffff8008f7e000 [00000000] *pgd=0000000017ffe003, *pud=0000000017ffe003, *pmd=0000000000000000 Internal error: Oops: 96000007 [#1] SMP CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W O 4.4.185 #1 PC is at move_freepages+0x80/0x10c LR is at move_freepages_block+0xd4/0xf4 pc : [] lr : [] pstate: 80000085 [...] [] move_freepages+0x80/0x10c [] move_freepages_block+0xd4/0xf4 [] __rmqueue+0x2bc/0x44c [] get_page_from_freelist+0x268/0x600 [] __alloc_pages_nodemask+0x184/0x88c [] new_slab+0xd0/0x494 [] ___slab_alloc.constprop.29+0x1c8/0x2e8 [] __slab_alloc.constprop.28+0x54/0x84 [] kmem_cache_alloc+0x64/0x198 [] __build_skb+0x44/0xa4 [] __netdev_alloc_skb+0xe4/0x134 mm/page_alloc.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f391c0c4ed1d..59f2c2b860fe 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2246,19 +2246,21 @@ static inline struct page *__rmqueue_cma_fallback(struct zone *zone, * boundary. If alignment is required, use move_freepages_block() */ static int move_freepages(struct zone *zone, - struct page *start_page, struct page *end_page, + unsigned long start_pfn, unsigned long end_pfn, int migratetype, int *num_movable) { struct page *page; + unsigned long pfn; unsigned int order; int pages_moved = 0; - for (page = start_page; page <= end_page;) { - if (!pfn_valid_within(page_to_pfn(page))) { - page++; + for (pfn = start_pfn; pfn <= end_pfn;) { + if (!pfn_valid_within(pfn)) { + pfn++; continue; } + page = pfn_to_page(pfn); if (!PageBuddy(page)) { /* * We assume that pages that could be isolated for @@ -2268,8 +2270,7 @@ static int move_freepages(struct zone *zone, if (num_movable && (PageLRU(page) || __PageMovable(page))) (*num_movable)++; - - page++; + pfn++; continue; } @@ -2280,6 +2281,7 @@ static int move_freepages(struct zone *zone, order = page_order(page); move_to_free_area(page, &zone->free_area[order], migratetype); page += 1 << order; + pfn += 1 << order; pages_moved += 1 << order; } @@ -2289,25 +2291,22 @@ static int move_freepages(struct zone *zone, int move_freepages_block(struct zone *zone, struct page *page, int migratetype, int *num_movable) { - unsigned long start_pfn, end_pfn; - struct page *start_page, *end_page; + unsigned long start_pfn, end_pfn, pfn; if (num_movable) *num_movable = 0; - start_pfn = page_to_pfn(page); + pfn = start_pfn = page_to_pfn(page); start_pfn = start_pfn & ~(pageblock_nr_pages-1); - start_page = pfn_to_page(start_pfn); - end_page = start_page + pageblock_nr_pages - 1; end_pfn = start_pfn + pageblock_nr_pages - 1; /* Do not cross zone boundaries */ if (!zone_spans_pfn(zone, start_pfn)) - start_page = page; + start_pfn = pfn; if (!zone_spans_pfn(zone, end_pfn)) return 0; - return move_freepages(zone, start_page, end_page, migratetype, + return move_freepages(zone, start_pfn, end_pfn, migratetype, num_movable); }