From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82DD160A2633 for ; Thu, 29 Oct 2026 20:34:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=ZpCMEIOe; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=h5YlBqSR DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Unsubscribe-Post: List-Owner; bh=8NeWgKC8rFJYZ7CY//H5MJ8mlDLPVUlB7WRXqG52bhs=; b=ZpCMEIOe0IOwHy you+nJmfjgbYLr8+Cjt0sTieTzoaFDCZwMafBwJTW4N4IkH8RLEFKz3l1WXJuJ44lJdYiLJFiUWvO 9aeb4qTgsd7Rp3lkta/aSPggyCH1AVLtGwSBjM/EiqFn8R+6HIUIPeAIy7ZMV6bFJbejfKpUAziI+ iDUxvnEdiyVBuSqfHM4dzzuUhTyhaR2QkznHgDPs/C2d9ytHY7Uew/MsYJVJ37tuan9RbZwayGfa2 G3Hbn9FeubgOy4e6VWssxav/7nfZfLGzEKzHVJW4NDkDVSUQgSl1ghkmqs79+CyqH8ApCAVmMej73 8JWh6Fitw4ttfTyr2X/w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.100.1 #2 (Red Hat Linux)) id 1xMWph-0000000AKQW-13Mh; Thu, 29 Oct 2026 20:34:45 +0000 Received: from sea.source.kernel.org ([172.234.252.31]) by bombadil.infradead.org with esmtps (Exim 4.100.1 #2 (Red Hat Linux)) id 1xMWpg-0000000AKQ8-0V6I for kexec@lists.infradead.org; Thu, 29 Oct 2026 20:34:44 +0000 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by sea.source.kernel.org (Postfix) with ESMTP id CC6004190F; Thu, 29 Oct 2026 20:34:43 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8A1371F01825; Thu, 29 Oct 2026 20:34:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793306083; bh=8NeWgKC8rFJYZ7CY//H5MJ8mlDLPVUlB7WRXqG52bhs=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=h5YlBqSRsRQCrhmhb7220/BdTpbl1XOfJ22+z1dVZFlRKfbL+drAxRpvK5BSKbiqk z4Yx0Re+/RHynvRBIbM1ppOnJLhfWmgi513P3ua5Wr9IbSLQ8emJZl3Yi/oNEiOcR3 hej0anVMIrPJH6EUcTvHJWuxdJ+OMBQE2DpDrm0QmaVdek3+JEirmytsKmT42UjcWp Cto2aIPZHz2WPdzD6lBNoM479P0R+mPiBjCn083hWSKlAH1IBn8toFkmcHR4qEDSMq 3x7FIDUx5x9Hf7AdMTO6otEaq/aNaHmVondhDFgT3OpBGeXkzBP5HUf1Z1lrXn1/5Z r2urf3Jip4tiA== From: "David Hildenbrand (Arm)" Date: Thu, 29 Oct 2026 21:33:00 +0100 Subject: [PATCH v2 05/47] mm/truncate: look again if a folio left the mapping X-Archived-By: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261029-fixes_core-v2-5-a64ce7f83abb@kernel.org> References: <20261029-fixes_core-v2-0-a64ce7f83abb@kernel.org> In-Reply-To: <20261029-fixes_core-v2-0-a64ce7f83abb@kernel.org> To: Andrew Morton , Johannes Weiner , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Kairui Song , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Baoquan He , Baolin Wang , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Kees Cook , Peter Zijlstra , Jann Horn , Pedro Falcato , Hugh Dickins , Pasha Tatashin , Pratyush Yadav , "Matthew Wilcox (Oracle)" , Jan Kara , Zi Yan , Lance Yang , Rik van Riel , Harry Yoo , Alistair Popple , Nico Pache , Ryan Roberts , Dev Jain , Usama Arif , Kiryl Shutsemau , Matthew Brost , John Hubbard , Peter Xu , Will Deacon , "Aneesh Kumar K.V" , Nick Piggin , Oscar Salvador , Minchan Kim , Muchun Song , Xu Xin , Chengming Zhou , Chris Li , Kemeng Shi , Nhat Pham , Youngjun Park , Gregory Price , Joshua Hahn , Rakie Kim , Ying Huang , Jason Gunthorpe Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, kexec@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-cxl@vger.kernel.org, stable@vger.kernel.org, Josef Bacik , "David Hildenbrand (Arm)" X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3335; i=david@kernel.org; h=from:subject:message-id; bh=8zVtiTIPHUHGhLtYGmDF+TjVfOwqhbOhyrdIJGBJe/g=; b=owGbwMvMwCF2/OVpCdfQ3ZWMp9WSGLIer22p+/bitVtd6s75Z3g2zq/IlNg9X5CvRELkVamsm V7AxoMfOkpZGMQ4GGTFFFmCgu8bvHy5rrbajY8ZZg4rE8gQBi5OAZjI36uMDHfMu/aWOrHVagjM 981Tuuth9qL13rEDrMmT/086Jvnv+ytGhh02l8sV7tQmRFyczcXj1TZlj9uXvw4ej0XnNipX1fN acwIA X-Developer-Key: i=david@kernel.org; a=openpgp; fpr=1BD9CAAD735C4C3A460DFCCA4DDE10F700FF835A X-BeenThere: kexec@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "kexec" X-Spam-Status: No, score=-18.9 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=4.0.1 X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on aws-us-west-2-korg-listserv-alma10-1 invalidate_inode_pages2_range() skips a folio which no longer belongs to the mapping by the time it has got the folio lock, on the assumption that somebody else has removed it from the page cache. But the folio may have been replaced, and then there is a new folio with the same data at that index. For most cases, like folio migration, that is impossible. However, collapse_file() only checks the refcount of the old folios, under the i_pages lock, and relies on their folio locks from there on. That works for users which repeat the lookup when they find folio->mapping changed. The following scenario is, however, possible: CPU0 pwrite(O_DIRECT) CPU1 collapse_file() kiocb_invalidate_pages() read the folio (old data), lock it refcount check the write completes copy to new_folio kiocb_invalidate_post_direct_write() find_get_entries() -> old folio xas_store(new_folio) folio->mapping = NULL folio_unlock(folio) folio_lock() folio->mapping != mapping -> continue In that scenario, the collapsed folio with the data from before the write stays in the page cache after the write has returned. This used to be impossible, as khugepaged only collapsed files that nobody had open for writing. Restart the lookup at that index, like shmem_undo_range() does. The same problem seems to exist in truncate_inode_pages_range() as well when truncate_inode_folio() fails, so handle it there as well, but slightly differently: simply check once more through find_get_entries(). Fixes: 1b6444331beb ("mm/khugepaged: enable clean pagecache folio collapse for writable files") Cc: stable@vger.kernel.org Reported-by: Josef Bacik Reviewed-by: Rik van Riel Signed-off-by: David Hildenbrand (Arm) --- mm/truncate.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mm/truncate.c b/mm/truncate.c index 733d2713a875..9e9bf029635c 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -475,8 +475,11 @@ void truncate_inode_pages_range(struct address_space *mapping, } } + if (start >= end) + return; + index = start; - while (index < end) { + while (true) { cond_resched(); if (!find_get_entries(mapping, &index, end - 1, &fbatch, indices)) { @@ -499,6 +502,7 @@ void truncate_inode_pages_range(struct address_space *mapping, folio_lock(folio); VM_BUG_ON_FOLIO(!folio_contains(folio, indices[i]), folio); folio_wait_writeback(folio); + /* Do not handle errors, we'll do another lookup */ truncate_inode_folio(mapping, folio); folio_unlock(folio); } @@ -760,7 +764,12 @@ int invalidate_inode_pages2_range(struct address_space *mapping, folio_lock(folio); if (unlikely(folio->mapping != mapping)) { folio_unlock(folio); - continue; + /* + * Folio might have been replaced: look up + * again. + */ + index = indices[i]; + break; } VM_BUG_ON_FOLIO(!folio_contains(folio, indices[i]), folio); folio_wait_writeback(folio); -- 2.43.0