From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6D7F760A380F for ; Mon, 26 Oct 2026 09:41:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=KdxdyErG Received: by kanga.kvack.org (Postfix) id 628E36B05C2; Mon, 26 Oct 2026 05:41:36 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 5D98C6B05C3; Mon, 26 Oct 2026 05:41:36 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4059F6B05C4; Mon, 26 Oct 2026 05:41:36 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 09FEC6B05C2 for ; Mon, 26 Oct 2026 05:41:36 -0400 (EDT) Received: from smtpin23.hostedemail.com (lb01a-stub [10.200.18.249]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 7BAFAA5A9B for ; Mon, 26 Oct 2026 09:41:35 +0000 (UTC) X-FDA: 85364284950.23.BCC5351 Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by imf15.hostedemail.com (Postfix) with ESMTP id B1F79A0003 for ; Mon, 26 Oct 2026 09:41:33 +0000 (UTC) Authentication-Results: imf15.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20260515 header.b=KdxdyErG; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf15.hostedemail.com: domain of david@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=david@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1793007693; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=nmBz+/RTdpUCFQ9pqbTORh8JacvbOfiqJsVOZ0p8atk=; b=wbpGhFOdqzNCf12/ikMsBu5Fmhe4ZYDUCMG7AbnFwoWDdmJv7+Ton23VjEc6Id1V60AXUm SROhfoIgDxxvh/ppgdFZ3qAeeQ/CYdWv1iMt2KNjWzAmhuXabGKAayKSe/2uX9/roqfNze +YEuWLAePcTx+t2kOWG5vaX9HzwHHiQ= ARC-Authentication-Results: i=1; imf15.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20260515 header.b=KdxdyErG; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf15.hostedemail.com: domain of david@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=david@kernel.org ARC-Seal: i=1; a=rsa-sha256; d=hostedemail.com; s=arc-20220608; cv=none; t=1793007693; b=NWsq2Us1JD7SET9yVUiQ7lightcZvU6K/+T+M+LiyQZJ9vAPhReRBNgc31pdIK6iG92p4/ yyfsI2U13JHBAbU91ENeNcYMM5UnRklHBWq2SDmadXaNTEg026ExKesvdA9t47uXW2WhCc b9ZBcjoks0WVEFzxcCN4PmFUWrdRoJ8= Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by tor.source.kernel.org (Postfix) with ESMTP id 4B6AC602C4; Mon, 26 Oct 2026 09:41:33 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 37CDC1F01825; Mon, 26 Oct 2026 09:41:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1793007693; bh=nmBz+/RTdpUCFQ9pqbTORh8JacvbOfiqJsVOZ0p8atk=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=KdxdyErGNR8+Kdh1oGHiW9TptryCXWrie4ChSPdDFePi194rJNX0Z21JDPPrgujkG suKJw30KcdrF4UOX1Fbgg0b9rMqIRnCWSfi0xayvlSLTQTG9jGSN8xYyiG5obGUOM9 OgW3GleYE3akeWhXEkDnCg6bkWiJyn3FSQAPgh4Sg44R+mjldmqQcyj6zK1zwg1/oz LDoBkFDpfFE92j4QYymh/OCSS2G4nqbULDeo5a7J4WhOVgeY75eV0J99UBismUwc4y 6EHMCAzHvxhWNgFO9Jc+XEJRms9onjhF6aZt4c7yTw4R8OlrRmI3hal3ytdCQboJP9 14oeQxP+WdjUQ== From: "David Hildenbrand (Arm)" Date: Mon, 26 Oct 2026 10:40:39 +0100 Subject: [PATCH 06/16] mm/shmem: hold off eviction in shmem_writeout() X-Archived-By: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261026-fixes_shmem-v1-6-703206d5fa0c@kernel.org> References: <20261026-fixes_shmem-v1-0-703206d5fa0c@kernel.org> In-Reply-To: <20261026-fixes_shmem-v1-0-703206d5fa0c@kernel.org> To: Andrew Morton , Gregory Price , Zi Yan , Joshua Hahn , Rakie Kim , Ying Huang , Johannes Weiner , Vladimir Davydov , Michal Hocko , Hugh Dickins , Baolin Wang , Lukas Czerner , Carlos Maiolino , Christian Brauner , Jan Kara , Daniel Verkamp , Jeff Xu , Muchun Song , Oscar Salvador , David Stevens , "Matthew Wilcox (Oracle)" , William Kucharski , Chris Li , Kairui Song , Nhat Pham , Miaohe Lin , Naoya Horiguchi Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, "David Hildenbrand (Arm)" , Josef Bacik , stable@vger.kernel.org X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=5301; i=david@kernel.org; h=from:subject:message-id; bh=w2umf3c0pIqcT0tacT6D+QxAKf6c7D/WDtmAa+uURHs=; b=owGbwMvMwCF2/OVpCdfQ3ZWMp9WSGLLuK4hxn7836fdj0TL3T68mXpYP9d8mrH5Yz07gxeaj1 Vodrhr2HaUsDGIcDLJiiixBwfcNXr5cV1vtxscMM4eVCWQIAxenAEzEO5ORYbaY+ZbE/gn+vRO1 ljmHr7hWuMlwm+Kr78u/pAdePSH7Kpjhv8ti8ZZXR55cE4kK2quoYLlSM595U7Rbubzv3+vmFpy WrAA= X-Developer-Key: i=david@kernel.org; a=openpgp; fpr=1BD9CAAD735C4C3A460DFCCA4DDE10F700FF835A X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: B1F79A0003 X-Stat-Signature: d8in3yhtmfh11xzc33xso6uyj8zapys6 X-Spam-Status: No, score=-19.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_PASS, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=4.0.1 X-Rspam-User: X-HE-Tag: 1793007693-436685 X-HE-Meta: U2FsdGVkX1/6oV8M9T8apRmpNIwlpdO/YnApgXbpMawgwQm802GmcTvH+BrdWebX7HYBCWcrxsLdpBI3MIhGI/c8ZnavmlNStnErXavukUzsDdQWT/d/g42P0QjIkfCujQm86Uy4duoP7qSIUokLC3PerFigIBWFhhYDVixkqnE4/KhldvNq/HRkUgTSKk7+y5REvBREt+ieHnNbr/luxseQ0EN/JUu4hkkO/gws5G5D7iap3bkseytBQKPp6t7ENDeCI7IUeIixR122JLt3FZSKt9mG4tZ4gMoP1JPtL0sJugljuGEyVwVxHmOErm3Zaeq83uUI3kfgpgqRVQxgS62B5GrcOQeKBCms71eIDPIOJk3RZEpPDycKN03IA4qstVY5SR5nnv5jvuuJwzYFmqV+Rn997hTM/JBY43fSfpWG1y2ZAL2UmuVthjlRLEktiOxPZpS86yh3vYz269NtPLcvWygEeZUQMhMzAxMIiQ0ff6/92tlDie1ZtlgF0vRmFfIASgSGU7LGEPvLJcGcUGsbHz3lSIv9YXo1/bQ4WDh6msEw4U1FSiNjXTfjpBXh2NQC5x7ZbTthtmVuS0Xn1wAaatCGMUO8670Kuvz+qna0bZpPxgheo0NRfGdKmccrGawndMnb9oTj4omYUkcaTKN78xBXgv6jwXIvUoOe5V2OnnDp7/Qqer95PgSHjXvYT9A+EEFob8YOb19qJCuuiDPCBXS+SDJGqVhx9R5Ta2lgM0NXV10xNX9nUpf+C4Lp18Z65+G/hC7k7I6B85j87dt1kRc3nBPhsaatJaRWIPU/z/hITzl9Iewnp/ga6Jh4W//1JxIxleTmiwiocswvIsNVUCaJNvGfxa3zZuvz7RnsRr1Qyc5o+3sfPcy3EQsx/LVW6sVJhiCQ7+LoKUcqfssqwfp4+cJIfnLpz3gf7c8XcNbRQPCLdc0J29hj3L3mP08yCU63JhKWfxi6wBx d8eIj6K5 BFk9bGmaql/clobjIaDTXH5Z/qhIGnBp5TyXb8sL0+WeYsCjwWQ9Cs4sMKzPMySRvRaJQZsk2RC7OtJD4PORwknwurVvbwnTIVg2pYH4hJiPfL1JsDk+zBTcj1Nj3DdqRd13sQyTcrUlc1fICGrJ6RsAT2DtsGVOD4EtpM4yUXLmyiBC/y6LVZv8YzEHEeZ7EZ50vuNJnl2j01SAuqsaIdAzj8j4ZCtK36a7CKKglXsg0GQj+/ZAgTOY+8Iz1NoLnMyJeSiadaNKgm/BkA+BU4Nb7No/JKw+dQHP3oTWL0cAdDWYBngj7xeJ4ZbxMgLBnomMusTDy+7NPBKrFnC7G3uPsyMRjvaYR8LbkCRJEVEwRygcpJLTjOwNBIdEPdKJwm0pWHI2ygsmsv8qoS/zqXyQdBaZrZdunMjjQuC8Izv3HiVo= Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on aws-us-west-2-korg-listserv-alma10-1 From: Josef Bacik Once shmem_writeout() has moved the folio from the page cache to the swap cache, the folio lock no longer keeps the inode alive: truncation and eviction find a swap entry, free it and do not wait for anybody. That did not matter as long as swap_writeout() was the last thing the function did. But since it puts the folio back when swap_writeout() returns AOP_WRITEPAGE_ACTIVATE, it uses the mapping and the inode afterwards: reclaim last close of an unlinked file shmem_writeout() shmem_delete_from_page_cache() swap_writeout() zswap_store() fails shmem_evict_inode() writeback is disabled shmem_truncate_range() return AOP_WRITEPAGE_ACTIVATE shmem_free_swap() destroy_inode() ... RCU grace period, freed shmem_add_to_page_cache(mapping) xas_lock_irq() <- use after free swap_writeout() behaves that way if zswap is enabled, cannot take the folio and the memcg or one of its ancestors has memory.zswap.writeback set to 0. shmem_unuse() already added infrastructure to deal with that. Reuse info->stop_eviction to protect the inode during writeout. Increment it before removing the folio from the page cache, and decrement it after swap_writeout() and any attempted reinsertion and inode accounting. In shmem_evict_inode(), wait for the counter to reach zero even if swapoff has already removed the inode from the swap list. Add some helpers to make the code easier to digest. Fix generated by an LLM and sent by Josef Bacik in private. Fixes: 6344a6d9ce13 ("mm/shmem: writeout free swap if swap_writeout() reactivates") Cc: stable@vger.kernel.org Signed-off-by: Josef Bacik [ david: code cleanups; improve description ] Signed-off-by: David Hildenbrand (Arm) --- mm/shmem.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 86b9d19f26c7e..c551e33c697fe 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1619,6 +1619,17 @@ static int shmem_setattr(const struct mnt_idmap *idmap, return error; } +static void shmem_disallow_eviction(struct shmem_inode_info *info) +{ + atomic_inc(&info->stop_eviction); +} + +static void shmem_allow_eviction(struct shmem_inode_info *info) +{ + if (atomic_dec_and_test(&info->stop_eviction)) + wake_up_var(&info->stop_eviction); +} + static void shmem_evict_inode(struct inode *inode) { struct shmem_inode_info *info = SHMEM_I(inode); @@ -1631,16 +1642,21 @@ static void shmem_evict_inode(struct inode *inode) mapping_set_exiting(inode->i_mapping); shmem_truncate_range(inode, 0, (loff_t)-1); shmem_unused_huge_del(inode); - while (!list_empty(&info->swaplist)) { - /* Wait while shmem_unuse() is scanning this inode... */ + /* + * Writeout may still use the inode after swapoff has removed it + * from the swaplist, so always wait at least once. + */ + do { wait_var_event(&info->stop_eviction, !atomic_read(&info->stop_eviction)); + if (list_empty(&info->swaplist)) + break; spin_lock(&shmem_swaplist_lock); /* ...but beware of the race if we peeked too early */ if (!atomic_read(&info->stop_eviction)) list_del_init(&info->swaplist); spin_unlock(&shmem_swaplist_lock); - } + } while (!list_empty(&info->swaplist)); } simple_xattrs_free(&sbinfo->xa_cache, &info->xattrs, sbinfo->max_inodes ? &freed : NULL); @@ -1779,15 +1795,14 @@ int shmem_unuse(unsigned int type) * remove placeholder inode from swaplist, nor let it be freed * (igrab() would protect from unlink, but not from unmount). */ - atomic_inc(&info->stop_eviction); + shmem_disallow_eviction(info); spin_unlock(&shmem_swaplist_lock); error = shmem_unuse_inode(&info->vfs_inode, type); cond_resched(); spin_lock(&shmem_swaplist_lock); - if (atomic_dec_and_test(&info->stop_eviction)) - wake_up_var(&info->stop_eviction); + shmem_allow_eviction(info); if (error) break; if (list_empty(&info->swaplist)) @@ -1918,6 +1933,13 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio, spin_unlock(&shmem_swaplist_lock); } + /* + * Once the folio has left the page cache, its lock no longer + * keeps the inode from being evicted and freed: hold eviction + * off, in case the folio has to be put back below. + */ + shmem_disallow_eviction(info); + folio_dup_swap(folio, NULL); shmem_delete_from_page_cache(folio, swp_to_radix_entry(folio->swap)); @@ -1925,6 +1947,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio, error = swap_writeout(ctx, folio); if (error != AOP_WRITEPAGE_ACTIVATE) { /* folio has been unlocked */ + shmem_allow_eviction(info); return error; } @@ -1941,6 +1964,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio, shmem_recalc_inode(inode, 0, -nr_pages); folio_put_swap(folio, NULL); } + shmem_allow_eviction(info); /* * The swap_cache_del_folio() below could be left for -- 2.43.0