Received: by 10.223.185.116 with SMTP id b49csp307013wrg; Fri, 2 Mar 2018 19:53:18 -0800 (PST) X-Google-Smtp-Source: AG47ELvfRuF7MDzN/4D295lbUeIaJQELnjeV5ojZMCbxnzJ4UcQetApT5Pgf2s392kabVxbjhPCh X-Received: by 10.98.138.66 with SMTP id y63mr7777329pfd.12.1520049197965; Fri, 02 Mar 2018 19:53:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520049197; cv=none; d=google.com; s=arc-20160816; b=hhlFjS3G51ql3ZR4Hqo9bTVpY+oBSVlDCDZVEIlK/y9P2PGCfW2awp2JoD6PLHDsjZ 7LSNTxkWtKv7gjsNgxFO3bSX5RyrsSQJDQ6gqg19gPpCeY4FDjeiT3ws/38Qx7SG3kqA buxXD1GvIVjvfuSsDJsJwnz2KJXV9zgSmfG/WHgpBi7E98TCNROR8HtWi2qisurBEKzT 095tWvgC+GkiT9P/IFLXzGxH+6blshkxLw1L3I4iq1cNDmR+Sy/dGYunvPk31cl2Xif1 oSy/AynmZ5XTIX/0oB656fnoyb/M9yPVnxIQoh0sIi8tWYSnnB3VeMkmGvzQExQbgiwe gsDA== 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:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=xB6pRsgRc49+EjPMij0auvk8rq69Pbju5U5h5a8R76k=; b=ViPGDRMZKoAduptS6Ar1yQamqghNxD/HadkW37AGwyaEhTw8JnXtlIuNwnv3Kyk+X0 w2NduXvt4ufCaCo8qDFqC/+gsAUm16Kz4lYwaylTdhaB0BeR/ome9yfoc3zSEfkJmAzR cFknBlbSZ42rjl/Niia5J58LkDHg7QX/MdaoDJ5hbUJ8Rnin6NNFOtIix0DjYfqU5L+/ sPEjs085TMeRdUXVhdVtPpp1uwa7sQK8joMaeX137bv0ggarLef2GTvZrvwnUd3q7pMr hoP6xwoE5v9VIDLPb3xNb5JZH9azXHfX8bauChUiMdXLTobKUF5K7cAqeSMPzw/W7Uxt b6yg== 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=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t14-v6si2716580plm.224.2018.03.02.19.53.03; Fri, 02 Mar 2018 19:53:17 -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=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935282AbeCCAMw (ORCPT + 99 others); Fri, 2 Mar 2018 19:12:52 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:60916 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S935239AbeCCAMt (ORCPT ); Fri, 2 Mar 2018 19:12:49 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C11588182D27; Sat, 3 Mar 2018 00:12:48 +0000 (UTC) Received: from slurm.brq.redhat.com (unknown [10.40.205.119]) by smtp.corp.redhat.com (Postfix) with ESMTP id 20C1F2156601; Sat, 3 Mar 2018 00:12:47 +0000 (UTC) From: Daniel Vacek To: linux-kernel@vger.kernel.org, linux-mm@kvack.org Cc: Andrew Morton , Michal Hocko , Vlastimil Babka , Mel Gorman , Pavel Tatashin , Paul Burton , Daniel Vacek , stable@vger.kernel.org Subject: [PATCH v3 2/2] mm/page_alloc: fix memmap_init_zone pageblock alignment Date: Sat, 3 Mar 2018 01:12:26 +0100 Message-Id: <0485727b2e82da7efbce5f6ba42524b429d0391a.1520011945.git.neelx@redhat.com> In-Reply-To: References: <1519908465-12328-1-git-send-email-neelx@redhat.com> In-Reply-To: References: X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 03 Mar 2018 00:12:48 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 03 Mar 2018 00:12:48 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'neelx@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit b92df1de5d28 ("mm: page_alloc: skip over regions of invalid pfns where possible") introduced a bug where move_freepages() triggers a VM_BUG_ON() on uninitialized page structure due to pageblock alignment. To fix this, simply align the skipped pfns in memmap_init_zone() the same way as in move_freepages_block(). From one of the RHEL reports: crash> log | grep -e BUG -e RIP -e Call.Trace -e move_freepages_block -e rmqueue -e freelist -A1 kernel BUG at mm/page_alloc.c:1389! invalid opcode: 0000 [#1] SMP -- RIP: 0010:[] [] move_freepages+0x15e/0x160 RSP: 0018:ffff88054d727688 EFLAGS: 00010087 -- Call Trace: [] move_freepages_block+0x73/0x80 [] __rmqueue+0x263/0x460 [] get_page_from_freelist+0x7e1/0x9e0 [] __alloc_pages_nodemask+0x176/0x420 -- RIP [] move_freepages+0x15e/0x160 RSP crash> page_init_bug -v | grep RAM 1000 - 9bfff System RAM (620.00 KiB) 100000 - 430bffff System RAM ( 1.05 GiB = 1071.75 MiB = 1097472.00 KiB) 4b0c8000 - 4bf9cfff System RAM ( 14.83 MiB = 15188.00 KiB) 4bfac000 - 646b1fff System RAM (391.02 MiB = 400408.00 KiB) 7b788000 - 7b7fffff System RAM (480.00 KiB) 100000000 - 67fffffff System RAM ( 22.00 GiB) crash> page_init_bug | head -6 7b788000 - 7b7fffff System RAM (480.00 KiB) 1fffff00000000 0 1 DMA32 4096 1048575 505736 505344 505855 0 0 0 DMA 1 4095 1fffff00000400 0 1 DMA32 4096 1048575 BUG, zones differ! Note that this range follows two not populated sections 68000000-77ffffff in this zone. 7b788000-7b7fffff is the first one after a gap. This makes memmap_init_zone() skip all the pfns up to the beginning of this range. But this range is not pageblock (2M) aligned. In fact no range has to be. crash> kmem -p 77fff000 78000000 7b5ff000 7b600000 7b787000 7b788000 PAGE PHYSICAL MAPPING INDEX CNT FLAGS ffffea0001e00000 78000000 0 0 0 0 ffffea0001ed7fc0 7b5ff000 0 0 0 0 ffffea0001ed8000 7b600000 0 0 0 0 <<<< ffffea0001ede1c0 7b787000 0 0 0 0 ffffea0001ede200 7b788000 0 0 1 1fffff00000000 Top part of page flags should contain nodeid and zonenr, which is not the case for page ffffea0001ed8000 here (<<<<). crash> log | grep -o fffea0001ed[^\ ]* | sort -u fffea0001ed8000 fffea0001eded20 fffea0001edffc0 crash> bt -r | grep -o fffea0001ed[^\ ]* | sort -u fffea0001ed8000 fffea0001eded00 fffea0001eded20 fffea0001edffc0 Initialization of the whole beginning of the section is skipped up to the start of the range due to the commit b92df1de5d28. Now any code calling move_freepages_block() (like reusing the page from a freelist as in this example) with a page from the beginning of the range will get the page rounded down to start_page ffffea0001ed8000 and passed to move_freepages() which crashes on assertion getting wrong zonenr. > VM_BUG_ON(page_zone(start_page) != page_zone(end_page)); Note, page_zone() derives the zone from page flags here. From similar machine before commit b92df1de5d28: crash> kmem -p 77fff000 78000000 7b5ff000 7b600000 7b7fe000 7b7ff000 PAGE PHYSICAL MAPPING INDEX CNT FLAGS fffff73941e00000 78000000 0 0 1 1fffff00000000 fffff73941ed7fc0 7b5ff000 0 0 1 1fffff00000000 fffff73941ed8000 7b600000 0 0 1 1fffff00000000 fffff73941edff80 7b7fe000 0 0 1 1fffff00000000 fffff73941edffc0 7b7ff000 ffff8e67e04d3ae0 ad84 1 1fffff00020068 uptodate,lru,active,mappedtodisk All the pages since the beginning of the section are initialized. move_freepages()' not gonna blow up. The same machine with this fix applied: crash> kmem -p 77fff000 78000000 7b5ff000 7b600000 7b7fe000 7b7ff000 PAGE PHYSICAL MAPPING INDEX CNT FLAGS ffffea0001e00000 78000000 0 0 0 0 ffffea0001e00000 7b5ff000 0 0 0 0 ffffea0001ed8000 7b600000 0 0 1 1fffff00000000 ffffea0001edff80 7b7fe000 0 0 1 1fffff00000000 ffffea0001edffc0 7b7ff000 ffff88017fb13720 8 2 1fffff00020068 uptodate,lru,active,mappedtodisk At least the bare minimum of pages is initialized preventing the crash as well. Fixes: b92df1de5d28 ("mm: page_alloc: skip over regions of invalid pfns where possible") Signed-off-by: Daniel Vacek Cc: stable@vger.kernel.org --- mm/page_alloc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f2c57da5bbe5..eb27ccb50928 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5359,9 +5359,14 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, /* * Skip to the pfn preceding the next valid one (or * end_pfn), such that we hit a valid pfn (or end_pfn) - * on our next iteration of the loop. + * on our next iteration of the loop. Note that it needs + * to be pageblock aligned even when the region itself + * is not. move_freepages_block() can shift ahead of + * the valid region but still depends on correct page + * metadata. */ - pfn = memblock_next_valid_pfn(pfn) - 1; + pfn = (memblock_next_valid_pfn(pfn) & + ~(pageblock_nr_pages-1)) - 1; #endif continue; } -- 2.16.2