From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E9682C43461 for ; Thu, 3 Sep 2020 18:31:00 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id A9ABE20709 for ; Thu, 3 Sep 2020 18:31:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="UAtSclHY" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A9ABE20709 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=infradead.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 4DDA36B0082; Thu, 3 Sep 2020 14:31:00 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 43B086B0083; Thu, 3 Sep 2020 14:31:00 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 329696B0085; Thu, 3 Sep 2020 14:31:00 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0042.hostedemail.com [216.40.44.42]) by kanga.kvack.org (Postfix) with ESMTP id 157BA6B0082 for ; Thu, 3 Sep 2020 14:31:00 -0400 (EDT) Received: from smtpin20.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id C84883631 for ; Thu, 3 Sep 2020 18:30:59 +0000 (UTC) X-FDA: 77222591838.20.farm97_0212de3270ab Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin20.hostedemail.com (Postfix) with ESMTP id 9B78F180C07AB for ; Thu, 3 Sep 2020 18:30:59 +0000 (UTC) X-HE-Tag: farm97_0212de3270ab X-Filterd-Recvd-Size: 5045 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf30.hostedemail.com (Postfix) with ESMTP for ; Thu, 3 Sep 2020 18:30:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=l6t9zq1hMIJ+MNQlF6rh0O5S6GFLDrx/ZAm/gKoYAVc=; b=UAtSclHYUeqHfSoqchK9B4aXjr ULwi9cS9L5jmXrNxqs9Zo+kp6B76czPXCpw0o5WgaZzjAIQkG+yqtmSg+npDXm1JJMWGdO6XK+Mao uv8kJjlBptoOFKEWIQpvhg0R12f1XH4vTVicQcewLZYp4qd+myyqrGsh7FalO9hfay7UFJLIN/rWr vPQjpf0YoxGMht5asU2wqVtaGHYQ8ZAP4PRWz0S1JwuMaUfPwqJHqk11HNQ5+ldDjfQ8pxUniE1Va pHOgr5N2ElqeF/DJer7E63rNznfBeLSxua1FuILFVPlPeN+msVOWdpHsCr7EPxuNi8o2p5XD9FDFn 0GITlJeA==; Received: from willy by casper.infradead.org with local (Exim 4.92.3 #3 (Red Hat Linux)) id 1kDu0R-0003u8-B7; Thu, 03 Sep 2020 18:30:43 +0000 From: "Matthew Wilcox (Oracle)" To: Andrew Morton Cc: "Matthew Wilcox (Oracle)" , linux-mm@kvack.org, Song Liu , "Kirill A . Shutemov" , Qian Cai Subject: [PATCH 3/3] mm/filemap: Fix storing to a THP shadow entry Date: Thu, 3 Sep 2020 19:30:29 +0100 Message-Id: <20200903183029.14930-4-willy@infradead.org> X-Mailer: git-send-email 2.21.3 In-Reply-To: <20200903183029.14930-1-willy@infradead.org> References: <20200903183029.14930-1-willy@infradead.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 9B78F180C07AB X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam04 Content-Transfer-Encoding: quoted-printable 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: When a THP is removed from the page cache by reclaim, we replace it with a shadow entry that occupies all slots of the XArray previously occupied by the THP. If the user then accesses that page again, we only allocate a single page, but storing it into the shadow entry replaces all entries with that one page. That leads to bugs like page dumped because: VM_BUG_ON_PAGE(page_to_pgoff(page) !=3D offset) ------------[ cut here ]------------ kernel BUG at mm/filemap.c:2529! https://bugzilla.kernel.org/show_bug.cgi?id=3D206569 This is hard to reproduce with mainline, but happens regularly with the THP patchset (as so many more THPs are created). This solution is take from the THP patchset. It splits the shadow entry into order-0 pieces at the time that we bring a new page into cache. Signed-off-by: Matthew Wilcox (Oracle) Fixes: 99cb0dbd47a1 ("mm,thp: add read-only THP support for (non-shmem) F= S") --- mm/filemap.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 1aaea26556cc..1ef6b71d68a6 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -829,13 +829,12 @@ EXPORT_SYMBOL_GPL(replace_page_cache_page); =20 static int __add_to_page_cache_locked(struct page *page, struct address_space *mapping, - pgoff_t offset, gfp_t gfp_mask, + pgoff_t offset, gfp_t gfp, void **shadowp) { XA_STATE(xas, &mapping->i_pages, offset); int huge =3D PageHuge(page); int error; - void *old; =20 VM_BUG_ON_PAGE(!PageLocked(page), page); VM_BUG_ON_PAGE(PageSwapBacked(page), page); @@ -846,25 +845,46 @@ static int __add_to_page_cache_locked(struct page *= page, page->index =3D offset; =20 if (!huge) { - error =3D mem_cgroup_charge(page, current->mm, gfp_mask); + error =3D mem_cgroup_charge(page, current->mm, gfp); if (error) goto error; } =20 + gfp &=3D GFP_RECLAIM_MASK; + do { + unsigned int order =3D xa_get_order(xas.xa, xas.xa_index); + void *entry, *old =3D NULL; + + if (order > thp_order(page)) + xas_split_alloc(&xas, xa_load(xas.xa, xas.xa_index), + order, gfp); xas_lock_irq(&xas); - old =3D xas_load(&xas); - if (old && !xa_is_value(old)) - xas_set_err(&xas, -EEXIST); + xas_for_each_conflict(&xas, entry) { + old =3D entry; + if (!xa_is_value(entry)) { + xas_set_err(&xas, -EEXIST); + goto unlock; + } + } + + if (old) { + if (shadowp) + *shadowp =3D old; + /* entry may have been split before we acquired lock */ + order =3D xa_get_order(xas.xa, xas.xa_index); + if (order > thp_order(page)) { + xas_split(&xas, old, order); + xas_reset(&xas); + } + } + xas_store(&xas, page); if (xas_error(&xas)) goto unlock; =20 - if (xa_is_value(old)) { + if (old) mapping->nrexceptional--; - if (shadowp) - *shadowp =3D old; - } mapping->nrpages++; =20 /* hugetlb pages do not participate in page cache accounting */ @@ -872,7 +892,7 @@ static int __add_to_page_cache_locked(struct page *pa= ge, __inc_lruvec_page_state(page, NR_FILE_PAGES); unlock: xas_unlock_irq(&xas); - } while (xas_nomem(&xas, gfp_mask & GFP_RECLAIM_MASK)); + } while (xas_nomem(&xas, gfp)); =20 if (xas_error(&xas)) { error =3D xas_error(&xas); --=20 2.28.0