From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EB3783988F9 for ; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=JK+DKcK9chNf/6XpK81Z2aIyFLWpjEBh6RdwHg0Lp9I6ioOx27RARyjETkuC7jUUnNhQs6X6ePrmN1f7kYezPjH0+0wP+B5DP3YjnM0ohjoimFHfP1btMCDOf6BRyi7vay0LCB60dJmKKRIB2/Nd/Z7qHMCBGoBz1TIoitoBWbA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=2OHip8UwlIqXDOB8Lnk3JZ3NJ7DAj/dnNPtoVJTO4mk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CKeqxgCKzQessT1kOIw/26pOyoN48e6LyU1lIJMqHF6bhUFsLGFDWnRBv1LJ+Stw2oXqL4iAXLvA/D+WFT16maoqBTTeV7yRH7Fdt//Z8VfFDgtkclcaSwfvhQuSKtFMD0wZvi6IAi28fsuOOQAx2ikyYigwhUj7y/1dD3crNUw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tkTxKnZQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tkTxKnZQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9D297C2BCF7; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252127; bh=2OHip8UwlIqXDOB8Lnk3JZ3NJ7DAj/dnNPtoVJTO4mk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=tkTxKnZQF8ks7KpBRo/MSTUbj6DR4NVRFhBZkahAQi+MrMC6YhGwBqNI9q7Sf0BCP P5GPN9yk+lO8Ia1f50sw/8BQw0HSQ8U4w7gRTvLOe89vquxpSDvwGGYQ4sb7F3T2uv cuOwh/4VDy8lxxdtMgJU3NEcQkqo81qyyLD1xYJMpRK40Y/MEtD0n+VGUY3+a8ATD0 a99L9HU2Cj/ZTSdqc51Z+mJ0ZHLI8E8gEt7vMkTvMQiLDBQ/QajiBngNCtRGjm2Xg/ mjZKnQsM8uEOQGulIvWlwlbN6RKsdZcXoic0yRhqolwdpkf9WZ457tcdIPGMkJVfgL 6fxnGgvmJJXBQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F1D2C5DF86; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:14 +0800 Subject: [PATCH v3 01/18] mm/swap: fix off-by-one in swap cache replace sanity check Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-1-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=1345; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=tJZfyDImR2TdvWcvOQ8ef1+tGYyooD8eF/fUtRm/Q0c=; b=d9mOmsd320+dGuqxQHJsrYoXje+bUDhlcIpN8BhavuVVPbwWGCjmKk9zse0A0fLzPDfLEPK/O 7Yzv7bhliBuD4WqFvIcWLzhYCDddbFGyKNtToThkIKT1wICanBZz9yb X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The DEBUG_VM sanity check in __swap_cache_replace_folio() iterates the old folio's range with "while (ci_off++ < ci_end)", so the loop body runs on the already-incremented offset: the first entry is skipped and one entry past the range is read. For a folio split that entry belongs to the first after-split folio and was just repointed by the replacement loop above, so the check would warn spuriously whenever sub-folio orders differ from the head folio's, as non-uniform swapcache splits now do. Use the same do-while pattern as the replacement loop. Fixes: 8578e0c00dcf ("mm, swap: use the swap table for the swap cache and s= witch API") Acked-by: Zi Yan Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Acked-by: Kiryl Shutsemau (Meta) Reviewed-by: Barry Song Reviewed-by: Yeoreum Yun --- mm/swap_state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/swap_state.c b/mm/swap_state.c index b76eb3d876fd..59a577f685b5 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -389,8 +389,9 @@ void __swap_cache_replace_folio(struct swap_cluster_inf= o *ci, folio_order(old) !=3D folio_order(new)) { ci_off =3D swp_cluster_offset(old->swap); ci_end =3D ci_off + folio_nr_pages(old); - while (ci_off++ < ci_end) + do { WARN_ON_ONCE(swp_tb_to_folio(__swap_table_get(ci, ci_off)) !=3D old); + } while (++ci_off < ci_end); } } =20 --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF7D1399018 for ; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=KSIfOh2DpbCeci1jM3MrKUrX/VefqdpORdDYvxDtMqoAOFuC0tKvVie6xQZj4Gg2gE+oLkDKGYo+qp0VS50hezDMZAKrCy0OKu4t3MZIOb+L4LNO06UWWnBwwWx/8X3iEkZeB6jSFDsUZW9EmQDYPm2NfA9lz87bA7PuuQSlyWc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=ZIOx7u5+j5YnV0RDhkMv9qnsb5igOw0DW4GkSQInsKE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PjGjZD1eqx7zmz3SEFGCTxmyXUwZzzTgM6VPNPj2IBlvHhKA35ULNKVKUxUdxD4GX/y1IN60q1k5C2aRvvWs1VcTcbP5xLKWIEfUBtSLJYTEfzbhk9o70JJBTY7gOoIl32AMtvGo/e+FSZkpR7EdCO3BJDDF30x/fDaYEP8sAx8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E0L9KID7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="E0L9KID7" Received: by smtp.kernel.org (Postfix) with ESMTPS id C22EDC2BCFB; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252127; bh=ZIOx7u5+j5YnV0RDhkMv9qnsb5igOw0DW4GkSQInsKE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=E0L9KID7NlgM1pvWIdQrCWVQasdTTmDK/f+TDRorWQBCr1omRl7XbsFJMXAdkc+fX vx55lxGlOOxd4U3hqCGdjFmCQePcBLStCc0h8oa8C+Zws++JTFzXROYjrRDvoaNUFO zdCrsRMvdcJ21UPrAz531iFroX2dkRh0KMViniPEi+dBGvAEvMfdtzYcCFZ+I5oA8z 7s56ofVSCg+6OZz2MFCo30TRhXLXaEJbYtOTgsZfMBscvp5z8Fdu02cUy5NAPMLkJj 58LnaQoKwSRwjSnwlYlEgSmMxvJXao587jNkBqjoic1PEYaNdz6laY+wgrHaurH7YG OxS++UTmImfXg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5F81C5DF82; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:15 +0800 Subject: [PATCH v3 02/18] mm/huge_memory: fix rejection of swap cache folios with a mapping Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-2-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=3656; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=sKRHOoJ3KjkPT6/oC1u2CVtXhFAq341fQZtAgnnTY3A=; b=3zwvvtcfXVg5C8pq5HfEixAwFpKfWp0hrW/JYJS4MCzZ1dJ2W08HHgEf7dbSN7ZQmgWIXj+2l QpM+O2g0stgC+SMPtNGHt7Gg4qZuyont6+VUtuo3edQXKDC09M/ePV4 X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song A folio in the swap cache cannot be split if it has a mapping (shmem). The split code does a defensive check for this in __folio_freeze_and_split_unmapped, after the folio ref has been frozen and the NR_SHMEM_THPS/NR_FILE_THPS counters have been decremented. It rejects the split and returns -EINVAL without unfreezing the folio or restoring the counters. That error path is buggy: if it is ever taken, it leaves the folio frozen and stuck, skews the counters, and fires the VM_WARN_ON_ONCE_FOLIO for a state that is actually legitimate. Check for this case up front in folio_check_splittable and return -EBUSY before any state is modified, so the split routine always backs out cleanly. Also fix a bracket style issue that checkpatch.pl keeps complaining about. Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions = for folio_split()") Fixes: 714b056c8321 ("mm/huge_memory: convert VM_BUG* to VM_WARN* in __foli= o_split") Reviewed-by: Zi Yan Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Reviewed-by: Barry Song Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index ced400f72d43..a6759a14e057 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3878,6 +3878,9 @@ static int __split_unmapped_folio(struct folio *folio= , int new_order, int folio_check_splittable(struct folio *folio, unsigned int new_order, enum split_type split_type) { + bool is_anon =3D folio_test_anon(folio); + bool is_swapcache =3D folio_test_swapcache(folio); + VM_WARN_ON_FOLIO(!folio_test_locked(folio), folio); /* * Folios that just got truncated cannot get split. Signal to the @@ -3886,11 +3889,11 @@ int folio_check_splittable(struct folio *folio, uns= igned int new_order, * TODO: this will also currently refuse folios without a mapping in the * swapcache (shmem or to-be-anon folios). */ - if (!folio->mapping && !folio_test_anon(folio)) + if (!folio->mapping && !is_anon) return -EBUSY; =20 /* order-1 is not supported for anonymous THP. */ - if (folio_test_anon(folio) && new_order =3D=3D 1) + if (is_anon && new_order =3D=3D 1) return -EINVAL; =20 /* @@ -3901,9 +3904,8 @@ int folio_check_splittable(struct folio *folio, unsig= ned int new_order, * swapcache folio split. Only uniform split to order-0 can be used * here. */ - if ((split_type =3D=3D SPLIT_TYPE_NON_UNIFORM || new_order) && folio_test= _swapcache(folio)) { + if ((split_type =3D=3D SPLIT_TYPE_NON_UNIFORM || new_order) && is_swapcac= he) return -EINVAL; - } =20 if (is_huge_zero_folio(folio)) return -EINVAL; @@ -3911,6 +3913,15 @@ int folio_check_splittable(struct folio *folio, unsi= gned int new_order, if (folio_test_writeback(folio)) return -EBUSY; =20 + /* + * A non-anon swapcache folio that still has a mapping can only be a + * shmem folio under SWAP IO, it's removed from either swap cache or + * shmem mapping afterward. There is little benefit in splitting them + * hence reject it here up front before touching anything. + */ + if (!is_anon && is_swapcache && folio->mapping) + return -EBUSY; + return 0; } =20 @@ -3983,14 +3994,8 @@ static int __folio_freeze_and_split_unmapped(struct = folio *folio, unsigned int n } } =20 - if (folio_test_swapcache(folio)) { - if (mapping) { - VM_WARN_ON_ONCE_FOLIO(mapping, folio); - return -EINVAL; - } - + if (folio_test_swapcache(folio)) ci =3D swap_cluster_get_and_lock(folio); - } =20 /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ if (do_lru) --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36158399354 for ; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=jEizcceK/0gigljxqIoD699Tw06ppnx7/l0d84ySDL0U0k4Y90K64D+ah2kBzWgb8hXndy9pylXHAd3UkO3yQOPwMC8d9IGTQeEQMoDjP9ePeieGvy6s6iQuVh6AbBEIofY4EeRdjYJ1rkDlFBtqM1TQrFnRrdrmO4knkrlII1k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=+Fhq/ThhPdJvanb/xrY423riYXh79oib+Ae4a1g8tWE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SodnDJ0V5MKq8YsvpuLTXgd9hpmvY+qtMqrmAkGyjsQtn8Aq5GzhE7V63KnEFdQe3ADpcTEnS0aiajx66rH9L0uozh6F3NbWosU0hwoQBTpXJoE8xM7/3Rw2pGbLh/VREpgR1NaPSKNVgyNWxPQ5tvgKvgtwhdb0Df7zTxLVJqE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EK3WsBFR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EK3WsBFR" Received: by smtp.kernel.org (Postfix) with ESMTPS id E8A65C2BCFC; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252128; bh=+Fhq/ThhPdJvanb/xrY423riYXh79oib+Ae4a1g8tWE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=EK3WsBFR4L+foI14/kCgTqKldpA+4IgxTJyLvAQC7jCVL4+Y05UpEobNMLN8oPa1n LsZoIdO+mz3y8Vj6IAiGzkInSpB85b8mjheOptcFdgiIzU0Ul0F0NfMdKYjS15h37g Sne4FEB2CVDC2Ze4cIhZCKer4vZMqzvtIGr21ZeGm2L/Bv0EFde5Fto9knH6rOA3aj mON2qL0/p/VFQBk3Z+H7b2rmkbYc6J4v2XBqLopjHoUv8OjDv0P/S6iINMrpuzw3ix dUrYdnpKcMqh4G/hLqiH7HJqPbS7hea5uGSTXi0uk2Bsuxuv+z5RjpqUJaQe9ClkVI /Cl+kpfSBEsEw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE71AC5DF89; Thu, 20 Aug 2026 18:55:27 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:16 +0800 Subject: [PATCH v3 03/18] mm/huge_memory: invert folio_ref_freeze() check to reduce indentation Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-3-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=7863; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=UY6iMKTpGLPfiYtzBDed5IoafUyCePQg/1v3UphPlKE=; b=l0sPmEqPmT8nBCikfRluoTynOrjtdDJng6/asUYQZF2y+2hhTjyJUEQF30etsd6v5pmNYUflh xbvQ8SDlDgrCKDbmn0g/Sie1J2KEftxrbFKTx9x5DtXt0OtYtOo9P1O X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Invert the folio_ref_freeze() success check in __folio_freeze_and_split_unmapped() to return early on failure, which removes one level of indentation from the entire success path. This is a pure refactoring with no functional change. It prepares the function to be split into separate helpers for anonymous and file-backed folios in a later patch. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Reviewed-by: Barry Song Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 181 +++++++++++++++++++++++++++------------------------= ---- 1 file changed, 90 insertions(+), 91 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index a6759a14e057..7fb603ac500f 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3940,9 +3940,11 @@ static int __folio_freeze_and_split_unmapped(struct = folio *folio, unsigned int n pgoff_t end, int *nr_shmem_dropped) { struct folio *end_folio =3D folio_next(folio); + struct swap_cluster_info *ci =3D NULL; struct folio *new_folio, *next; int old_order =3D folio_order(folio); struct list_lru_one *lru; + struct lruvec *lruvec; bool dequeue_deferred; int ret =3D 0; =20 @@ -3963,122 +3965,119 @@ static int __folio_freeze_and_split_unmapped(stru= ct folio *folio, unsigned int n lru =3D list_lru_lock(&deferred_split_lru, folio_nid(folio), &memcg); } - if (folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) { - struct swap_cluster_info *ci =3D NULL; - struct lruvec *lruvec; =20 + if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) { if (dequeue_deferred) { - __list_lru_del(&deferred_split_lru, lru, - &folio->_deferred_list, folio_nid(folio)); - if (folio_test_partially_mapped(folio)) { - folio_clear_partially_mapped(folio); - mod_mthp_stat(old_order, - MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1); - } list_lru_unlock(lru); rcu_read_unlock(); } + return -EAGAIN; + } =20 - if (mapping) { - int nr =3D folio_nr_pages(folio); - - if (folio_test_pmd_mappable(folio) && - new_order < HPAGE_PMD_ORDER) { - if (folio_test_swapbacked(folio)) { - lruvec_stat_mod_folio(folio, - NR_SHMEM_THPS, -nr); - } else { - lruvec_stat_mod_folio(folio, - NR_FILE_THPS, -nr); - } - } + if (dequeue_deferred) { + __list_lru_del(&deferred_split_lru, lru, + &folio->_deferred_list, folio_nid(folio)); + if (folio_test_partially_mapped(folio)) { + folio_clear_partially_mapped(folio); + mod_mthp_stat(old_order, + MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1); } + list_lru_unlock(lru); + rcu_read_unlock(); + } =20 - if (folio_test_swapcache(folio)) - ci =3D swap_cluster_get_and_lock(folio); - - /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ - if (do_lru) - lruvec =3D folio_lruvec_lock(folio); - - ret =3D __split_unmapped_folio(folio, new_order, split_at, xas, - mapping, split_type); + if (mapping) { + int nr =3D folio_nr_pages(folio); =20 - /* - * Unfreeze after-split folios and put them back to the right - * list. @folio should be kept frozon until page cache - * entries are updated with all the other after-split folios - * to prevent others seeing stale page cache entries. - * As a result, new_folio starts from the next folio of - * @folio. - */ - for (new_folio =3D folio_next(folio); new_folio !=3D end_folio; - new_folio =3D next) { - unsigned long nr_pages =3D folio_nr_pages(new_folio); + if (folio_test_pmd_mappable(folio) && + new_order < HPAGE_PMD_ORDER) { + if (folio_test_swapbacked(folio)) { + lruvec_stat_mod_folio(folio, + NR_SHMEM_THPS, -nr); + } else { + lruvec_stat_mod_folio(folio, + NR_FILE_THPS, -nr); + } + } + } =20 - next =3D folio_next(new_folio); + if (folio_test_swapcache(folio)) + ci =3D swap_cluster_get_and_lock(folio); =20 - zone_device_private_split_cb(folio, new_folio); + /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ + if (do_lru) + lruvec =3D folio_lruvec_lock(folio); =20 - folio_ref_unfreeze(new_folio, - folio_cache_ref_count(new_folio) + 1); + ret =3D __split_unmapped_folio(folio, new_order, split_at, xas, + mapping, split_type); =20 - if (do_lru) - lru_add_split_folio(folio, new_folio, lruvec, list); + /* + * Unfreeze after-split folios and put them back to the right + * list. @folio should be kept frozon until page cache + * entries are updated with all the other after-split folios + * to prevent others seeing stale page cache entries. + * As a result, new_folio starts from the next folio of + * @folio. + */ + for (new_folio =3D folio_next(folio); new_folio !=3D end_folio; + new_folio =3D next) { + unsigned long nr_pages =3D folio_nr_pages(new_folio); =20 - /* - * Anonymous folio with swap cache. - * NOTE: shmem in swap cache is not supported yet. - */ - if (ci) { - __swap_cache_replace_folio(ci, folio, new_folio); - continue; - } + next =3D folio_next(new_folio); =20 - /* Anonymous folio without swap cache */ - if (!mapping) - continue; + zone_device_private_split_cb(folio, new_folio); =20 - /* Add the new folio to the page cache. */ - if (new_folio->index < end) { - __xa_store(&mapping->i_pages, new_folio->index, - new_folio, 0); - continue; - } + folio_ref_unfreeze(new_folio, + folio_cache_ref_count(new_folio) + 1); =20 - VM_WARN_ON_ONCE(!nr_shmem_dropped); - /* Drop folio beyond EOF: ->index >=3D end */ - if (shmem_mapping(mapping) && nr_shmem_dropped) - *nr_shmem_dropped +=3D nr_pages; - else if (folio_test_clear_dirty(new_folio)) - folio_account_cleaned( - new_folio, inode_to_wb(mapping->host)); - __filemap_remove_folio(new_folio, NULL); - folio_put_refs(new_folio, nr_pages); - } + if (do_lru) + lru_add_split_folio(folio, new_folio, lruvec, list); =20 - zone_device_private_split_cb(folio, NULL); /* - * Unfreeze @folio only after all page cache entries, which - * used to point to it, have been updated with new folios. - * Otherwise, a parallel folio_try_get() can grab @folio - * and its caller can see stale page cache entries. + * Anonymous folio with swap cache. + * NOTE: shmem in swap cache is not supported yet. */ - folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1); + if (ci) { + __swap_cache_replace_folio(ci, folio, new_folio); + continue; + } =20 - if (do_lru) - lruvec_unlock(lruvec); + /* Anonymous folio without swap cache */ + if (!mapping) + continue; =20 - if (ci) - swap_cluster_unlock(ci); - } else { - if (dequeue_deferred) { - list_lru_unlock(lru); - rcu_read_unlock(); + /* Add the new folio to the page cache. */ + if (new_folio->index < end) { + __xa_store(&mapping->i_pages, new_folio->index, + new_folio, 0); + continue; } - return -EAGAIN; + + VM_WARN_ON_ONCE(!nr_shmem_dropped); + /* Drop folio beyond EOF: ->index >=3D end */ + if (shmem_mapping(mapping) && nr_shmem_dropped) + *nr_shmem_dropped +=3D nr_pages; + else if (folio_test_clear_dirty(new_folio)) + folio_account_cleaned(new_folio, + inode_to_wb(mapping->host)); + __filemap_remove_folio(new_folio, NULL); + folio_put_refs(new_folio, nr_pages); } =20 + zone_device_private_split_cb(folio, NULL); + /* + * Unfreeze @folio only after all page cache entries, which + * used to point to it, have been updated with new folios. + * Otherwise, a parallel folio_try_get() can grab @folio + * and its caller can see stale page cache entries. + */ + folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1); + + if (do_lru) + lruvec_unlock(lruvec); + if (ci) + swap_cluster_unlock(ci); + return ret; } =20 --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AC4F39A048 for ; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=FA6JtfLtoFXlaBpGx+fB3Czo4fzQN4PFVwoir88s+jaCYcB5oO6dnaLu0QsmvjglP78jF+4A6wS22tqkP+1WmVLdQPOW9qkcjIbnIbYJcEnOrZFE9zTYNoNelolMrPBfTBB+rmBIkNswUR1vRJ31Z7x62ofvX/Fe/eEjG3Q3aPQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=FkFUYML3XV8JWw54qlKPTW7rYb5oxaI1kamvWQ5J08k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FKy0yKb73rkcW/PJO2M92ExnpFU/jflZzzThHf/sbCSaIr3seTrsmbmXTpffJvPngN8x15FzMaRJUSUTduLNl8yO8yRpDuw+9zslJf5ZJMagEqytiUXuU3DoM0nWZXbXREivuHyE7HtKTwoFYNAxNcePyjw3xFq3EHoYDbTLm+k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CGJyb5WY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CGJyb5WY" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2558FC2BCB3; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252128; bh=FkFUYML3XV8JWw54qlKPTW7rYb5oxaI1kamvWQ5J08k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=CGJyb5WYKnCtVa35pHxSENz8Ru4Hg9/k692pyNSdfN2ZQy35kn0v6wp5yL7W/IDsG DSS1LfswD8QJhjFBjdRvX/LbT7074PjCfVgei+Xhj7PuDKORfcJNU4XvTqW8FrgK6l LvxcfmyKpfl47r3O69j7GOtIkeVi2Yfu6finAFg1NqzwB98Ub/jVyD+zxcU6BQKdnQ trZwS/On8nap7NRhwZbxSBVuVUpOCs4tv+IRqdBw5LbVVuuXGJgHZJSRZGLaTJvrpd dry7gPIspg4QyDwtP22IdxLswRzO0VNE63LjM5SFz2EoURzpZhH6a+QztVVXgQ+1lG oRftG+fZG3o0Q== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02660C5DF86; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:17 +0800 Subject: [PATCH v3 04/18] mm/huge_memory: split the routine for splitting anon and file folio Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-4-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=8202; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=o2S8TMWLz7STFa+m4GqxK4/Q0Rl6U6CqX2p2Zm1CMpA=; b=xYaGlOBj3wxj41dOviDUwCe9+7Rj1ObGbtXvFQkivEXB2Eo96MWrvqMwPvybdECYC+Y9fhSQ1 9o/34Ox2HyGBY7UrUy5EH8vhB2ihH57x0pG+VXdmZo9wk6ROen9XsRi X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song No functional change intended. Before adding more logic, split __folio_freeze_and_split_unmapped() into an anon and a file variant so each path can evolve independently. The two paths shared little beyond the folio freeze call, the LRU locking, and the unfreeze skeleton, but differed in all other per-folio bookkeeping and routines. While splitting, some cleanups become easy to apply, and helped drop a few now-redundant checks. Also introduce a folio iteration helper to avoid a common pitfall of iterating post-split sub-folios: a sub folio might get freed mid-iteration as pointed out by Zi [1]. Link: https://lore.kernel.org/linux-mm/DKJSFCLP967N.YBR4DNK1NM2N@nvidia.com= / [1] Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Reviewed-by: Yeoreum Yun Reviewed-by: Zi Yan --- mm/huge_memory.c | 119 +++++++++++++++++++++++++++++++++++----------------= ---- 1 file changed, 75 insertions(+), 44 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 7fb603ac500f..c3fd6757c14c 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3933,11 +3933,9 @@ static unsigned int folio_cache_ref_count(const stru= ct folio *folio) return folio_nr_pages(folio); } =20 -static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned= int new_order, - struct page *split_at, struct xa_state *xas, - struct address_space *mapping, bool do_lru, - struct list_head *list, enum split_type split_type, - pgoff_t end, int *nr_shmem_dropped) +static int __folio_freeze_split_unmapped_anon(struct folio *folio, unsigne= d int new_order, + struct page *split_at, bool do_lru, + struct list_head *list, enum split_type split_type) { struct folio *end_folio =3D folio_next(folio); struct swap_cluster_info *ci =3D NULL; @@ -3948,7 +3946,6 @@ static int __folio_freeze_and_split_unmapped(struct f= olio *folio, unsigned int n bool dequeue_deferred; int ret =3D 0; =20 - VM_WARN_ON_ONCE(!mapping && end); /* * If this folio can be on the deferred split queue, lock out * the shrinker before freezing the ref. If the shrinker sees @@ -3956,7 +3953,7 @@ static int __folio_freeze_and_split_unmapped(struct f= olio *folio, unsigned int n * lock and must clean up the LRU state - the same dequeue we * will do below as part of the split. */ - dequeue_deferred =3D folio_test_anon(folio) && old_order > 1; + dequeue_deferred =3D old_order > 1; if (dequeue_deferred) { struct mem_cgroup *memcg; =20 @@ -3986,24 +3983,72 @@ static int __folio_freeze_and_split_unmapped(struct= folio *folio, unsigned int n rcu_read_unlock(); } =20 - if (mapping) { + if (folio_test_swapcache(folio)) + ci =3D swap_cluster_get_and_lock(folio); + + if (do_lru) + lruvec =3D folio_lruvec_lock(folio); + + ret =3D __split_unmapped_folio(folio, new_order, split_at, NULL, + NULL, split_type); + + /* + * Unfreeze the post-split folios and put them back to the right + * place. Keep the head @folio frozen until the end: sub entries + * in swap cache must be updated first, so a concurrent + * swap_cache_get_folio() cannot return the head folio for a sub + * entry (folio_try_get() will fail on the head @folio until unfreeze). + */ + for (new_folio =3D folio_next(folio); new_folio !=3D end_folio; + new_folio =3D next) { + next =3D folio_next(new_folio); + zone_device_private_split_cb(folio, new_folio); + folio_ref_unfreeze(new_folio, + folio_cache_ref_count(new_folio) + 1); + if (do_lru) + lru_add_split_folio(folio, new_folio, lruvec, list); + if (ci) + __swap_cache_replace_folio(ci, folio, new_folio); + } + + zone_device_private_split_cb(folio, NULL); + folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1); + + if (do_lru) + lruvec_unlock(lruvec); + if (ci) + swap_cluster_unlock(ci); + + return ret; +} + +static int __folio_freeze_split_unmapped_file(struct folio *folio, unsigne= d int new_order, + struct page *split_at, struct xa_state *xas, + struct address_space *mapping, bool do_lru, + struct list_head *list, enum split_type split_type, + pgoff_t end, int *nr_shmem_dropped) +{ + struct folio *end_folio =3D folio_next(folio); + struct folio *new_folio, *next; + struct lruvec *lruvec; + int ret; + + if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) + return -EAGAIN; + + if (folio_test_pmd_mappable(folio) && + new_order < HPAGE_PMD_ORDER) { int nr =3D folio_nr_pages(folio); =20 - if (folio_test_pmd_mappable(folio) && - new_order < HPAGE_PMD_ORDER) { - if (folio_test_swapbacked(folio)) { - lruvec_stat_mod_folio(folio, - NR_SHMEM_THPS, -nr); - } else { - lruvec_stat_mod_folio(folio, - NR_FILE_THPS, -nr); - } + if (folio_test_swapbacked(folio)) { + lruvec_stat_mod_folio(folio, + NR_SHMEM_THPS, -nr); + } else { + lruvec_stat_mod_folio(folio, + NR_FILE_THPS, -nr); } } =20 - if (folio_test_swapcache(folio)) - ci =3D swap_cluster_get_and_lock(folio); - /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ if (do_lru) lruvec =3D folio_lruvec_lock(folio); @@ -4013,7 +4058,7 @@ static int __folio_freeze_and_split_unmapped(struct f= olio *folio, unsigned int n =20 /* * Unfreeze after-split folios and put them back to the right - * list. @folio should be kept frozon until page cache + * list. @folio should be kept frozen until page cache * entries are updated with all the other after-split folios * to prevent others seeing stale page cache entries. * As a result, new_folio starts from the next folio of @@ -4023,29 +4068,15 @@ static int __folio_freeze_and_split_unmapped(struct= folio *folio, unsigned int n new_folio =3D next) { unsigned long nr_pages =3D folio_nr_pages(new_folio); =20 + /* compute next before the folio can be freed below */ next =3D folio_next(new_folio); =20 - zone_device_private_split_cb(folio, new_folio); - folio_ref_unfreeze(new_folio, folio_cache_ref_count(new_folio) + 1); =20 if (do_lru) lru_add_split_folio(folio, new_folio, lruvec, list); =20 - /* - * Anonymous folio with swap cache. - * NOTE: shmem in swap cache is not supported yet. - */ - if (ci) { - __swap_cache_replace_folio(ci, folio, new_folio); - continue; - } - - /* Anonymous folio without swap cache */ - if (!mapping) - continue; - /* Add the new folio to the page cache. */ if (new_folio->index < end) { __xa_store(&mapping->i_pages, new_folio->index, @@ -4064,7 +4095,6 @@ static int __folio_freeze_and_split_unmapped(struct f= olio *folio, unsigned int n folio_put_refs(new_folio, nr_pages); } =20 - zone_device_private_split_cb(folio, NULL); /* * Unfreeze @folio only after all page cache entries, which * used to point to it, have been updated with new folios. @@ -4075,8 +4105,6 @@ static int __folio_freeze_and_split_unmapped(struct f= olio *folio, unsigned int n =20 if (do_lru) lruvec_unlock(lruvec); - if (ci) - swap_cluster_unlock(ci); =20 return ret; } @@ -4230,10 +4258,14 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, ret =3D -EAGAIN; goto fail; } + ret =3D __folio_freeze_split_unmapped_file(folio, new_order, split_at, &= xas, mapping, + true, list, split_type, end, + &nr_shmem_dropped); + } else { + ret =3D __folio_freeze_split_unmapped_anon(folio, new_order, split_at, t= rue, + list, split_type); } =20 - ret =3D __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xa= s, mapping, - true, list, split_type, end, &nr_shmem_dropped); fail: if (mapping) xas_unlock(&xas); @@ -4333,9 +4365,8 @@ int folio_split_unmapped(struct folio *folio, unsigne= d int new_order) return -EAGAIN; =20 local_irq_disable(); - ret =3D __folio_freeze_and_split_unmapped(folio, new_order, &folio->page,= NULL, - NULL, false, NULL, SPLIT_TYPE_UNIFORM, - 0, NULL); + ret =3D __folio_freeze_split_unmapped_anon(folio, new_order, &folio->page, + false, NULL, SPLIT_TYPE_UNIFORM); local_irq_enable(); return ret; } --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7ABBC397940 for ; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=hrI9XBrjIi1oc3iSGba13HtO1B7nqCv2uux2oM0ECv6R79XDFVY9Aw8QURPd+Z77O9nBMeRFmia48P7mYA05WwCDUNGZv/7R1b+f3r/MNf2zKPhcgSfPedV0ZFRSeWoQmTPL/LkjAbElUjI5YwNKCck1bTtL0CreFoaIFTg2JCs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=JvobTG9I7QZbRCAH/9qqa05jBi0cwM7PQ2k7NS/kQJk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CBtdnRARENeluqhi6yPOJIuaaTlj8EOjAbJAkrQN2FIJWNm5MTMQauaaf+r9glwkT+OaIEAl6ccLpdDRJpvReEpFOMbdO/xWyDGyfJfwjTxWmHzp0tqjhomKjwlXkGZ93Obkn66pDHe9bHezTuM5RjUHynYcl33zhYHtF2cr9lc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LRHn2lWN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LRHn2lWN" Received: by smtp.kernel.org (Postfix) with ESMTPS id 50412C2BCC7; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252128; bh=JvobTG9I7QZbRCAH/9qqa05jBi0cwM7PQ2k7NS/kQJk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LRHn2lWNvYoewOgPgKxsoDMwG91xtiDZmys2sdye37e7S5ZZvHG5J3D35ZmMXdx4S t30c2bEFzQ+s5iSkt4AtUjsjETIpKfeJHOd0hSH2rFh5YMGsFuZWPPABUi9nIAAYvw X/t6WhVCBNGaYuQsoerOE3YLdP/N9ri4OGTmnvlbk/L9b93hHeXNm1KJcYKchEptrR W12P5ZC2g88GFE2vSAhrCxWJcdJPUWVaR7Gie6hmNm7QNdOJAFKSo+7tMW12aYjQYG UQ7H5idyFH6qAcX27C85cbexAQgQNXGX4/SITx6kbqw64tAHi5/9gvYgcr1u5yNZ9I 5C0DGjbp3zKSQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2CD66C5DF85; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:18 +0800 Subject: [PATCH v3 05/18] mm/huge_memory: rename __split_unmapped_folio() to __split_frozen_folio() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-5-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=3691; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=n6EfNzAc4w/2SwnSy/zj9BR1996opKhXS3Y2Z4MVxpM=; b=PDeSmX4GhPuxR46o2+iAjFz0/oFyjGkew1yVAX4RNe/9A6IFfXMVfEN+GSC/O81uKVt9ETwO3 pzawe+Rwny4DnpunJo84j+vprqwIt1h8eBuAS/PuqSt8AETE38huzdC X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The helper splits a folio whose refcount is frozen: the frozen refcount is the state it relies on, while unmapping is arranged by the caller beforehand. The old name caused confusion and people may try to call the helper on non-frozen folios. Suggested-by: Zi Yan Reviewed-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c3fd6757c14c..427e14d7985a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3755,8 +3755,8 @@ static void __split_folio_to_order(struct folio *foli= o, int old_order, } =20 /** - * __split_unmapped_folio() - splits an unmapped @folio to lower order fol= ios in - * two ways: uniform split or non-uniform split. + * __split_frozen_folio() - splits a frozen @folio to lower order folios + * in two ways: uniform split or non-uniform split. * @folio: the to-be-split folio * @new_order: the smallest order of the after split folios (since buddy * allocator like split generates folios with orders from @fol= io's @@ -3795,7 +3795,7 @@ static void __split_folio_to_order(struct folio *foli= o, int old_order, * Return: 0 - successful, <0 - failed (if -ENOMEM is returned, @folio mig= ht be * split but not to @new_order, the caller needs to check) */ -static int __split_unmapped_folio(struct folio *folio, int new_order, +static int __split_frozen_folio(struct folio *folio, int new_order, struct page *split_at, struct xa_state *xas, struct address_space *mapping, enum split_type split_type) { @@ -3989,8 +3989,8 @@ static int __folio_freeze_split_unmapped_anon(struct = folio *folio, unsigned int if (do_lru) lruvec =3D folio_lruvec_lock(folio); =20 - ret =3D __split_unmapped_folio(folio, new_order, split_at, NULL, - NULL, split_type); + ret =3D __split_frozen_folio(folio, new_order, split_at, NULL, + NULL, split_type); =20 /* * Unfreeze the post-split folios and put them back to the right @@ -4053,8 +4053,8 @@ static int __folio_freeze_split_unmapped_file(struct = folio *folio, unsigned int if (do_lru) lruvec =3D folio_lruvec_lock(folio); =20 - ret =3D __split_unmapped_folio(folio, new_order, split_at, xas, - mapping, split_type); + ret =3D __split_frozen_folio(folio, new_order, split_at, xas, + mapping, split_type); =20 /* * Unfreeze after-split folios and put them back to the right @@ -4118,9 +4118,9 @@ static int __folio_freeze_split_unmapped_file(struct = folio *folio, unsigned int * @list: after-split folios will be put on it if non NULL * @split_type: perform uniform split or not (non-uniform split) * - * It calls __split_unmapped_folio() to perform uniform and non-uniform sp= lit. + * It calls __split_frozen_folio() to perform uniform and non-uniform spli= t. * It is in charge of checking whether the split is supported or not and - * preparing @folio for __split_unmapped_folio(). + * preparing @folio for __split_frozen_folio(). * * After splitting, the after-split folio containing @lock_at remains lock= ed * and others are unlocked: @@ -4223,7 +4223,7 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, i_mmap_lock_read(mapping); =20 /* - *__split_unmapped_folio() may need to trim off pages beyond + * __split_frozen_folio() may need to trim off pages beyond * EOF: but on 32-bit, i_size_read() takes an irq-unsafe * seqlock, which cannot be nested inside the page tree lock. * So note end now: i_size itself may be changed at any moment, --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97E6038F253 for ; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=lmfPp83D8rBKrOntTW2+7tb3JLI5DG40/EMK0auqUfyHvslEL+lN2cZrrHf+sxSlvTD6xNCGoSEDp3ZzyU+lUvJFc5fZh74QDee7XZwWLDCxOlUUesCOOX9juV5h9nG8NbuEZZvj3HDWCkKbjkelfTkonULrG+Iqrq4kzG2hcnE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=XliG3xrzz9pN6Bq3jcef9F6/PirhKUf7omvzTzDPdXE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iJnVqe+9seuE5m9l9qLa2SVHC8HUYio09Cj0aRjMPc6O8jfkjuVUvKZqpkhMVyDHTOG11VTHQEVHRvpI3uvFRYAj3SD5hUrV54D5+02HEQh4nedpqSn0+de9Mdj9chXQnphBvy2b4BqFQCRkg0c7BmuvwTaOE0oY3cEaONcFrOc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Uo+Be2Ps; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Uo+Be2Ps" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6FA64C2BCFB; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252128; bh=XliG3xrzz9pN6Bq3jcef9F6/PirhKUf7omvzTzDPdXE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Uo+Be2PsQ84iKgIMTOVONuKNsAB9EbnXAvTwTVL8xUqeSqgIKa1VuU54BBwGXYMYE WcnUQYbyTS80bn+0va9KDtHUHp07i7P8Ey5142h1A6tbunUQdRKR/PAjGFx649kSvF GQafhgqXLIb4I+6dnhCcSK1yBGcHSMNObdbyjfh5zfISuhEjjhwKRLSTgJps53+dXz yE+uxUhN7Pj5jhykGdGjWLoUk5Aazlk9GoMzqygkhy0U2mv+eF9RpGmKbFLTc3thAW opkoLtIlCTSqz0GUSjCyHZW89ZgHBUT+63FCEROc8CINyCYZyQAqrFSOMGcPKlZHyi cOU5hWPkFaLPQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53714C5DF8C; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:19 +0800 Subject: [PATCH v3 06/18] mm/huge_memory: consolidate irq and locking for folio split Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-6-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=4821; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=kg6VQFGolmACY/RqrJ4EQVqIYb6qG4JCJfoecxkhaQ8=; b=0Gg6pZYKuwo87RQUWCu22J/1MzcNTDa0eVW33D/XV5QjuKjak/B0oiR/Yyrb0uXB6rJzXUXod 2M8kJx7HXGcAFl6LWyj3H0he4N+ALtRRlguXeqlVnLZ58r1ar9ndSUu X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Let each split helper handle its own locking instead of relying on the caller, so both helpers manage their own irq and locking state. This lets __folio_split() drop its local irq handling and fail label, preparing for further cleanup. The file path now uses xas_lock_irq() instead of local_irq_disable() with xas_lock(). The two are equivalent on non-RT, and TRANSPARENT_HUGEPAGE cannot be enabled on RT anyway. This conversion also buys consistency: every other place in mm/ that freezes a folio while it is still reachable through the page cache already takes the lock this way. This was actually the last plain xas_lock() on mapping->i_pages left in mm. If we are going to support RT, spinning on frozen folio refs could be a problem, but it already exists in many places and should be fixed generically. The anon helper keeps a single local_irq_disable() as before, because it has to cover several plain spinlocks at once. The dropped xas_reset() was a no-op as the xa_state is not walked before the xas_load() under the lock. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 52 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 427e14d7985a..69d3a6889f9e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3946,6 +3946,8 @@ static int __folio_freeze_split_unmapped_anon(struct = folio *folio, unsigned int bool dequeue_deferred; int ret =3D 0; =20 + local_irq_disable(); + /* * If this folio can be on the deferred split queue, lock out * the shrinker before freezing the ref. If the shrinker sees @@ -3968,6 +3970,7 @@ static int __folio_freeze_split_unmapped_anon(struct = folio *folio, unsigned int list_lru_unlock(lru); rcu_read_unlock(); } + local_irq_enable(); return -EAGAIN; } =20 @@ -4018,6 +4021,7 @@ static int __folio_freeze_split_unmapped_anon(struct = folio *folio, unsigned int lruvec_unlock(lruvec); if (ci) swap_cluster_unlock(ci); + local_irq_enable(); =20 return ret; } @@ -4033,8 +4037,21 @@ static int __folio_freeze_split_unmapped_file(struct= folio *folio, unsigned int struct lruvec *lruvec; int ret; =20 - if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) - return -EAGAIN; + xas_lock_irq(xas); + + /* + * Check if the folio is present in page cache. + * We assume all tail are present too, if folio is there. + */ + if (xas_load(xas) !=3D folio) { + ret =3D -EAGAIN; + goto fail; + } + + if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) { + ret =3D -EAGAIN; + goto fail; + } =20 if (folio_test_pmd_mappable(folio) && new_order < HPAGE_PMD_ORDER) { @@ -4106,6 +4123,8 @@ static int __folio_freeze_split_unmapped_file(struct = folio *folio, unsigned int if (do_lru) lruvec_unlock(lruvec); =20 +fail: + xas_unlock_irq(xas); return ret; } =20 @@ -4245,19 +4264,7 @@ static int __folio_split(struct folio *folio, unsign= ed int new_order, =20 unmap_folio(folio); =20 - /* block interrupt reentry in xa_lock and spinlock */ - local_irq_disable(); - if (mapping) { - /* - * Check if the folio is present in page cache. - * We assume all tail are present too, if folio is there. - */ - xas_lock(&xas); - xas_reset(&xas); - if (xas_load(&xas) !=3D folio) { - ret =3D -EAGAIN; - goto fail; - } + if (!is_anon) { ret =3D __folio_freeze_split_unmapped_file(folio, new_order, split_at, &= xas, mapping, true, list, split_type, end, &nr_shmem_dropped); @@ -4266,12 +4273,6 @@ static int __folio_split(struct folio *folio, unsign= ed int new_order, list, split_type); } =20 -fail: - if (mapping) - xas_unlock(&xas); - - local_irq_enable(); - if (nr_shmem_dropped) shmem_uncharge(mapping->host, nr_shmem_dropped); =20 @@ -4354,8 +4355,6 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, */ int folio_split_unmapped(struct folio *folio, unsigned int new_order) { - int ret =3D 0; - VM_WARN_ON_ONCE_FOLIO(folio_mapped(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio); @@ -4364,11 +4363,8 @@ int folio_split_unmapped(struct folio *folio, unsign= ed int new_order) if (folio_expected_ref_count(folio) !=3D folio_ref_count(folio) - 1) return -EAGAIN; =20 - local_irq_disable(); - ret =3D __folio_freeze_split_unmapped_anon(folio, new_order, &folio->page, - false, NULL, SPLIT_TYPE_UNIFORM); - local_irq_enable(); - return ret; + return __folio_freeze_split_unmapped_anon(folio, new_order, &folio->page, + false, NULL, SPLIT_TYPE_UNIFORM); } =20 /* --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B22BD39A07C for ; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; cv=none; b=o7Pi9z2vm5qxZtqlL06I+zmG0q41jvFHCh1w5jHbI5heW2pDAwfgRBzilfXFc2oa/WX9B3hIDYN5iUZK72pZZ5ZdzV2gpzu0GdqOFpuMXEU/tZJiPFssoRNpIpC5ybyY1+fpT6//EtiZBOp4RyR1/xt7Y44ZTU1qiX3jZnLj3Ug= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252128; c=relaxed/simple; bh=3CfMcjiNddwe9dRGubBMNv3C8JR+aOzPu0U1+6Cwm3g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Sq6d534h0TSsv1CoRAKKG4mEy3eFhuVnrx1cMWExW8gvWPNQn839pXrlUet6I81JH6VwGh6GFjasZ6adAyPRPv2mx3cUV6juGYUx2rz0oOUi9AC8R+RlN03mqtRTJKQGH2UbLexcz8mGBw9BLb0rtxp/nDx1ooaudoGSOHosTQ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YDd2/6ag; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YDd2/6ag" Received: by smtp.kernel.org (Postfix) with ESMTPS id 914E7C32781; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252128; bh=3CfMcjiNddwe9dRGubBMNv3C8JR+aOzPu0U1+6Cwm3g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=YDd2/6aglrFrnhykio9zu4YpGvhI0fJsC6GGvNiVF14v079/j52yG2dd17UEMV/rz WQn7m4EHRU1r7Ie0OPg/ez1GOXn+h0H52D4FhvVLsoQqiW1solvnS4In8i+H26BI5L T2vbjmdZ5I4AoBAxjFMFTmjSwMl7EXlHpT2WxCVJrKbftCvoXpq4oPjxZbzn7cgh1m Ov4tqivLH7FOt/Vxtv1TruNM+JiFgxmguk22/A7aVYsfqqHPMrotnulk5NNf916cSO wW7AcEwzPNDSuwMRUOsA8faspE6OdeXU1ZdvE/Qqpzp6JVgpvHYKGXmi/OsDWyhvNz i4tO78nQtXXVQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D974C5DF86; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:20 +0800 Subject: [PATCH v3 07/18] mm/huge_memory: move EOF trimming into the file split helper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-7-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=4165; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=iHc7pAaIWrvecdrYUZp632jxrrl7JCpaJ3/M1UaVKXM=; b=SSoVa7oBxRV5XNOTEkWS5QvNz8DmMOLpNiHcpSpatLmWJ2BgTT8vxBo1owQndnsF1GBNZS3PT H4ECfhrdcmICJ5mWGv51TZGUXGuzoZX1tVVARrbzwXTEMIpX34esKVJ X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Instead of receiving @end and @nr_shmem_dropped from the caller, the file split helper now computes the EOF boundary and trims pages beyond it itself, as this is only needed for file split. This drops the redundant parameter passing and sanity check. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 69d3a6889f9e..01c8cf428595 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4029,14 +4029,26 @@ static int __folio_freeze_split_unmapped_anon(struc= t folio *folio, unsigned int static int __folio_freeze_split_unmapped_file(struct folio *folio, unsigne= d int new_order, struct page *split_at, struct xa_state *xas, struct address_space *mapping, bool do_lru, - struct list_head *list, enum split_type split_type, - pgoff_t end, int *nr_shmem_dropped) + struct list_head *list, enum split_type split_type) { struct folio *end_folio =3D folio_next(folio); struct folio *new_folio, *next; + int nr_shmem_dropped =3D 0; struct lruvec *lruvec; + pgoff_t end =3D 0; int ret; =20 + /* + * __split_frozen_folio() may need to trim off pages beyond + * EOF: but on 32-bit, i_size_read() takes an irq-unsafe + * seqlock, which cannot be nested inside the page tree lock. + * So note end now: i_size itself may be changed at any moment, + * but folio lock is good enough to serialize the trimming. + */ + end =3D DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); + if (shmem_mapping(mapping)) + end =3D shmem_fallocend(mapping->host, end); + xas_lock_irq(xas); =20 /* @@ -4101,10 +4113,9 @@ static int __folio_freeze_split_unmapped_file(struct= folio *folio, unsigned int continue; } =20 - VM_WARN_ON_ONCE(!nr_shmem_dropped); /* Drop folio beyond EOF: ->index >=3D end */ - if (shmem_mapping(mapping) && nr_shmem_dropped) - *nr_shmem_dropped +=3D nr_pages; + if (shmem_mapping(mapping)) + nr_shmem_dropped +=3D nr_pages; else if (folio_test_clear_dirty(new_folio)) folio_account_cleaned(new_folio, inode_to_wb(mapping->host)); @@ -4125,6 +4136,8 @@ static int __folio_freeze_split_unmapped_file(struct = folio *folio, unsigned int =20 fail: xas_unlock_irq(xas); + if (nr_shmem_dropped) + shmem_uncharge(mapping->host, nr_shmem_dropped); return ret; } =20 @@ -4161,9 +4174,7 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, struct anon_vma *anon_vma =3D NULL; int old_order =3D folio_order(folio); struct folio *new_folio, *next; - int nr_shmem_dropped =3D 0; enum ttu_flags ttu_flags =3D 0; - pgoff_t end =3D 0; int ret; =20 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio); @@ -4240,17 +4251,6 @@ static int __folio_split(struct folio *folio, unsign= ed int new_order, =20 anon_vma =3D NULL; i_mmap_lock_read(mapping); - - /* - * __split_frozen_folio() may need to trim off pages beyond - * EOF: but on 32-bit, i_size_read() takes an irq-unsafe - * seqlock, which cannot be nested inside the page tree lock. - * So note end now: i_size itself may be changed at any moment, - * but folio lock is good enough to serialize the trimming. - */ - end =3D DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); - if (shmem_mapping(mapping)) - end =3D shmem_fallocend(mapping->host, end); } =20 /* @@ -4266,16 +4266,12 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, =20 if (!is_anon) { ret =3D __folio_freeze_split_unmapped_file(folio, new_order, split_at, &= xas, mapping, - true, list, split_type, end, - &nr_shmem_dropped); + true, list, split_type); } else { ret =3D __folio_freeze_split_unmapped_anon(folio, new_order, split_at, t= rue, list, split_type); } =20 - if (nr_shmem_dropped) - shmem_uncharge(mapping->host, nr_shmem_dropped); - if (!ret && is_anon && !folio_is_device_private(folio)) ttu_flags =3D TTU_USE_SHARED_ZEROPAGE; =20 --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E56B639A7E5 for ; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; cv=none; b=K403gytWuBjjYQpJ5V2xhYaWh3mZVaQ4oLEefHm2P1k0IIURmC6U6ei+6JCCl8YV2tdMkd4mjAXoafLutVQOdVtIjni524XGGVVmm44LY3845NHHbVyGuAI+sIGQHD6cW+imprClt2/0svbZjARGBby2r/NR6PhNigZaHX53NTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; c=relaxed/simple; bh=57wY1JKmm5GvWQDkOulo9aLZpUhYxYqy/jAD/p/XA+Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CME6vP/5zr7nqnfVojUpxV5dFtXKInHblP4z0qZlK6tyW2fxuTVfzCcKyIk721A9Pkh83n7JOXgKTB5VrSlxg33IFlC77zndopFelSJch05K/bdL77IaVWKLBNLwDPegsPptY3jnIRk6BKUWXcuyqocheqk/0jTTz9JHIERkVd0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Cx1vGRL8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Cx1vGRL8" Received: by smtp.kernel.org (Postfix) with ESMTPS id BBAE1C2BCFC; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252128; bh=57wY1JKmm5GvWQDkOulo9aLZpUhYxYqy/jAD/p/XA+Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Cx1vGRL8tqiZln75bx1A6wQ0a58ahsbe7w8B1a1F//uvW41pqpy+cUACDh2U7VSa+ vAJSewArCM+XRKn+68JDn9ivj/n+XDhu8LQXWvbx+ajbyklUwu/x8VjsHGwn5XBUom 0LoCBRkFauwH2h5UY5muEfViUwMvK2JTdB9CLsLdJ13w6uluoMjYNupYp5+SxJ6mJj o+Z2yj1T49AWcvxPRi7LutHb0CwqyqLt5RAO3beszVZMTukq8JhnoW9AT3LZHOM+v7 gxXaRaxlq9OFcrC7+wnjUm05fymGZP5SmW3UJ04in2d1CpOU9aZVKiw5gkJZql/gwY X8ZAB7XaiZ5Uw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A133C5DF85; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:21 +0800 Subject: [PATCH v3 08/18] mm/huge_memory: move unmap and remap into the split helpers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-8-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=5602; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=oK2L5X8TGo6Z9/D2DTTdT9kf2V7+XELqp768EPNH+Os=; b=NW83Br76VciZusNk7gBmN0sIfGfz7EYPOIlFZ/0vBbR8o2Z+dT/rEoXSEgTcUW1EV0alnfXpa R7TPmBJFr/4AKAu8u6ypiQtxg3fwt114rgDRr3thuMdJCJipxsdoW9p X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song To prepare for further cleanup, move the unmap/remap handling from __folio_split() into the split helpers. Only anon folios need to be remapped, so remap_page() is now only called for anon splits and the anon check in remap_page() is redundant and can be removed. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 58 ++++++++++++++++++++++++++++++----------------------= ---- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 01c8cf428595..af9c2edd1fba 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3589,9 +3589,6 @@ static void remap_page(struct folio *folio, unsigned = long nr, int flags) { int i =3D 0; =20 - /* If unmap_folio() uses try_to_migrate() on file, remove this check */ - if (!folio_test_anon(folio)) - return; for (;;) { remove_migration_ptes(folio, folio, TTU_RMAP_LOCKED | flags); i +=3D folio_nr_pages(folio); @@ -3933,19 +3930,23 @@ static unsigned int folio_cache_ref_count(const str= uct folio *folio) return folio_nr_pages(folio); } =20 -static int __folio_freeze_split_unmapped_anon(struct folio *folio, unsigne= d int new_order, - struct page *split_at, bool do_lru, - struct list_head *list, enum split_type split_type) +static int __folio_split_unmap_and_freeze_anon(struct folio *folio, unsign= ed int new_order, + struct page *split_at, bool do_lru, bool unmap, + struct list_head *list, enum split_type split_type) { struct folio *end_folio =3D folio_next(folio); struct swap_cluster_info *ci =3D NULL; struct folio *new_folio, *next; int old_order =3D folio_order(folio); + enum ttu_flags ttu_flags =3D 0; struct list_lru_one *lru; struct lruvec *lruvec; bool dequeue_deferred; int ret =3D 0; =20 + if (unmap) + unmap_folio(folio); + local_irq_disable(); =20 /* @@ -3970,8 +3971,8 @@ static int __folio_freeze_split_unmapped_anon(struct = folio *folio, unsigned int list_lru_unlock(lru); rcu_read_unlock(); } - local_irq_enable(); - return -EAGAIN; + ret =3D -EAGAIN; + goto out_no_split; } =20 if (dequeue_deferred) { @@ -4021,15 +4022,21 @@ static int __folio_freeze_split_unmapped_anon(struc= t folio *folio, unsigned int lruvec_unlock(lruvec); if (ci) swap_cluster_unlock(ci); +out_no_split: local_irq_enable(); + if (unmap) { + if (!ret && !folio_is_device_private(folio)) + ttu_flags =3D TTU_USE_SHARED_ZEROPAGE; + remap_page(folio, 1 << old_order, ttu_flags); + } =20 return ret; } =20 -static int __folio_freeze_split_unmapped_file(struct folio *folio, unsigne= d int new_order, - struct page *split_at, struct xa_state *xas, - struct address_space *mapping, bool do_lru, - struct list_head *list, enum split_type split_type) +static int __folio_split_unmap_and_freeze_file(struct folio *folio, unsign= ed int new_order, + struct page *split_at, struct xa_state *xas, + struct address_space *mapping, bool do_lru, + struct list_head *list, enum split_type split_type) { struct folio *end_folio =3D folio_next(folio); struct folio *new_folio, *next; @@ -4049,6 +4056,8 @@ static int __folio_freeze_split_unmapped_file(struct = folio *folio, unsigned int if (shmem_mapping(mapping)) end =3D shmem_fallocend(mapping->host, end); =20 + unmap_folio(folio); + xas_lock_irq(xas); =20 /* @@ -4133,8 +4142,11 @@ static int __folio_freeze_split_unmapped_file(struct= folio *folio, unsigned int =20 if (do_lru) lruvec_unlock(lruvec); - fail: + /* + * If we want to use try_to_migrate() on file in unmap_folio, + * remember to add remap_page() and adapt it. + */ xas_unlock_irq(xas); if (nr_shmem_dropped) shmem_uncharge(mapping->host, nr_shmem_dropped); @@ -4174,7 +4186,6 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, struct anon_vma *anon_vma =3D NULL; int old_order =3D folio_order(folio); struct folio *new_folio, *next; - enum ttu_flags ttu_flags =3D 0; int ret; =20 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio); @@ -4262,21 +4273,14 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, goto out_unlock; } =20 - unmap_folio(folio); - if (!is_anon) { - ret =3D __folio_freeze_split_unmapped_file(folio, new_order, split_at, &= xas, mapping, - true, list, split_type); + ret =3D __folio_split_unmap_and_freeze_file(folio, new_order, split_at, = &xas, mapping, + true, list, split_type); } else { - ret =3D __folio_freeze_split_unmapped_anon(folio, new_order, split_at, t= rue, - list, split_type); + ret =3D __folio_split_unmap_and_freeze_anon(folio, new_order, split_at, = true, + true, list, split_type); } =20 - if (!ret && is_anon && !folio_is_device_private(folio)) - ttu_flags =3D TTU_USE_SHARED_ZEROPAGE; - - remap_page(folio, 1 << old_order, ttu_flags); - /* * Drop the mapping while the inode is still pinned. @folio stays * locked and present in the page cache until the loop below, so @@ -4359,8 +4363,8 @@ int folio_split_unmapped(struct folio *folio, unsigne= d int new_order) if (folio_expected_ref_count(folio) !=3D folio_ref_count(folio) - 1) return -EAGAIN; =20 - return __folio_freeze_split_unmapped_anon(folio, new_order, &folio->page, - false, NULL, SPLIT_TYPE_UNIFORM); + return __folio_split_unmap_and_freeze_anon(folio, new_order, &folio->page= , false, + false, NULL, SPLIT_TYPE_UNIFORM); } =20 /* --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C60339B4A2 for ; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; cv=none; b=kQdCaL77QqpLDrTFoudtXgHfxeLiDEeoASRJXl5JjXwV1INUWUpjmV3oBzkQFMq1nZV6UITLBL/8UThgn0tIEwgK0ajyk5ahC1qBnqZi6mE8RInfBPvzzWh+bg1Cd86wpcax+17OpuQLgY29YW+UtNXn5yhxRtKt6bw67ewfBRI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; c=relaxed/simple; bh=Y1NhnR+oVzRh0Uwx/iM0sg0BGMub99qDv8ZmzcQY9dM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MAnUxghfnuU+1qpndIXOpRwDeW3S1DkyU9+bLxtGvuaIlpfo6+A03/Y1pA6wCvVKGyNINgK5DlayMENPekuECb4zAgJXuGxmf+xarKaRGWFzkMWQU30PqoWtXaEd62Icr/OV4eOgI3tVmk1I55vLe+g4OseOEQDcE79z1fHiA28= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=trPly8+X; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="trPly8+X" Received: by smtp.kernel.org (Postfix) with ESMTPS id EE40EC2BCFA; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252129; bh=Y1NhnR+oVzRh0Uwx/iM0sg0BGMub99qDv8ZmzcQY9dM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=trPly8+X1EtNPpthD7FDXDoXz3iCZNWsTXgwjFb3BL45TgmiUlc5rIE35iTx3T0Nf 3XCNISiH6dMgn9yKyfdHmuGcpB6u27lm4DhAQJudibo+atIzokZb3T+7OAbBRewh1a wfNcAaTMLB6J8/QkWs8SShHRk3X5nGadhIAPSuPZz+FswkGxIHCxabNN/T5J9uZqVb l0Tt6jirYjD3FYlXMSMJ5tGN/edZh6RmZOjtBkixEKhUYCT+UX4QXBpz2xQT+MvjGB S1SoHsgRNA2gFG7CE0HpbHNMWp4hrwj3+83v46DY9dxk7hIpweEmp/kwgu7EPps3zD Gm+aqODmbqvGw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF16CC5DF89; Thu, 20 Aug 2026 18:55:28 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:22 +0800 Subject: [PATCH v3 09/18] mm/huge_memory: move anon_vma and filemap management into split helpers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-9-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=9165; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=j4/qLBMewzYJxQm3k2J67YZ1aAy2ziPk5hv8fhUeJnw=; b=JsV65MFo7tzk+MTw+yZfxT9Fh3u24aV6Kl9GfjNaSm8j29iCbx6LOukHJwUuBm9uKacgDM1qs KjuPzKLqKIgCOdp/cw3JX+uTawQfJsxL47DKGJKIuk/ozOmsEykUL7l X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Only anon split needs vma info, and only file split needs the filemap handling. Move the related code into separate helpers so they are genuinely more self-contained. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 177 +++++++++++++++++++++++++--------------------------= ---- 1 file changed, 79 insertions(+), 98 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index af9c2edd1fba..1ee312cbd438 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3938,12 +3938,33 @@ static int __folio_split_unmap_and_freeze_anon(stru= ct folio *folio, unsigned int struct swap_cluster_info *ci =3D NULL; struct folio *new_folio, *next; int old_order =3D folio_order(folio); + struct anon_vma *anon_vma =3D NULL; enum ttu_flags ttu_flags =3D 0; struct list_lru_one *lru; struct lruvec *lruvec; bool dequeue_deferred; int ret =3D 0; =20 + /* + * Unmap/remap needs the anon_vma. The caller does not necessarily + * hold an mmap_lock that would prevent the anon_vma from + * disappearing, so we first take a reference and lock it. This is + * similar to folio_lock_anon_vma_read() except the write lock is + * taken to serialize against parallel split or collapse. + */ + if (unmap) { + anon_vma =3D folio_get_anon_vma(folio); + if (!anon_vma) + return -EBUSY; + anon_vma_lock_write(anon_vma); + } + + /* Racy check if we can split the page, before the optional unmap. */ + if (folio_expected_ref_count(folio) !=3D folio_ref_count(folio) - 1) { + ret =3D -EAGAIN; + goto out_unlock; + } + if (unmap) unmap_folio(folio); =20 @@ -4029,21 +4050,58 @@ static int __folio_split_unmap_and_freeze_anon(stru= ct folio *folio, unsigned int ttu_flags =3D TTU_USE_SHARED_ZEROPAGE; remap_page(folio, 1 << old_order, ttu_flags); } +out_unlock: + if (anon_vma) { + anon_vma_unlock_write(anon_vma); + put_anon_vma(anon_vma); + } =20 return ret; } =20 static int __folio_split_unmap_and_freeze_file(struct folio *folio, unsign= ed int new_order, - struct page *split_at, struct xa_state *xas, - struct address_space *mapping, bool do_lru, + struct page *split_at, bool do_lru, struct list_head *list, enum split_type split_type) { + struct address_space *mapping =3D folio->mapping; + XA_STATE(xas, &mapping->i_pages, folio->index); struct folio *end_folio =3D folio_next(folio); struct folio *new_folio, *next; int nr_shmem_dropped =3D 0; + unsigned int min_order; struct lruvec *lruvec; pgoff_t end =3D 0; - int ret; + gfp_t gfp; + int ret =3D 0; + + min_order =3D mapping_min_folio_order(mapping); + if (new_order < min_order) + return -EINVAL; + + gfp =3D current_gfp_context(mapping_gfp_mask(mapping) & GFP_RECLAIM_MASK); + if (!filemap_release_folio(folio, gfp)) + return -EBUSY; + + mapping_set_update(&xas, mapping); + + if (split_type =3D=3D SPLIT_TYPE_UNIFORM) { + int old_order =3D folio_order(folio); + + xas_set_order(&xas, folio->index, new_order); + xas_split_alloc(&xas, folio, old_order, gfp); + if (xas_error(&xas)) { + ret =3D xas_error(&xas); + goto fail_free; + } + } + + i_mmap_lock_read(mapping); + + /* Racy check if we can split the page, before unmap_folio() */ + if (folio_expected_ref_count(folio) !=3D folio_ref_count(folio) - 1) { + ret =3D -EAGAIN; + goto fail_mmap_unlock; + } =20 /* * __split_frozen_folio() may need to trim off pages beyond @@ -4058,13 +4116,13 @@ static int __folio_split_unmap_and_freeze_file(stru= ct folio *folio, unsigned int =20 unmap_folio(folio); =20 - xas_lock_irq(xas); + xas_lock_irq(&xas); =20 /* * Check if the folio is present in page cache. * We assume all tail are present too, if folio is there. */ - if (xas_load(xas) !=3D folio) { + if (xas_load(&xas) !=3D folio) { ret =3D -EAGAIN; goto fail; } @@ -4091,7 +4149,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int if (do_lru) lruvec =3D folio_lruvec_lock(folio); =20 - ret =3D __split_frozen_folio(folio, new_order, split_at, xas, + ret =3D __split_frozen_folio(folio, new_order, split_at, &xas, mapping, split_type); =20 /* @@ -4147,9 +4205,19 @@ static int __folio_split_unmap_and_freeze_file(struc= t folio *folio, unsigned int * If we want to use try_to_migrate() on file in unmap_folio, * remember to add remap_page() and adapt it. */ - xas_unlock_irq(xas); + xas_unlock_irq(&xas); +fail_mmap_unlock: if (nr_shmem_dropped) shmem_uncharge(mapping->host, nr_shmem_dropped); + /* + * Drop the mapping while the inode is still pinned. @folio stays + * locked and present in the page cache, so eviction cannot free + * the inode yet, nothing past this point may touch the inode or + * the mapping. + */ + i_mmap_unlock_read(mapping); +fail_free: + xas_destroy(&xas); return ret; } =20 @@ -4178,12 +4246,9 @@ static int __folio_split(struct folio *folio, unsign= ed int new_order, struct page *split_at, struct page *lock_at, struct list_head *list, enum split_type split_type) { - XA_STATE(xas, &folio->mapping->i_pages, folio->index); struct folio *end_folio =3D folio_next(folio); bool is_anon =3D folio_test_anon(folio); struct mem_cgroup *memcg, *old_memcg; - struct address_space *mapping =3D NULL; - struct anon_vma *anon_vma =3D NULL; int old_order =3D folio_order(folio); struct folio *new_folio, *next; int ret; @@ -4214,84 +4279,12 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, memcg =3D get_mem_cgroup_from_folio(folio); old_memcg =3D set_active_memcg(memcg); =20 - if (is_anon) { - /* - * The caller does not necessarily hold an mmap_lock that would - * prevent the anon_vma disappearing so we first we take a - * reference to it and then lock the anon_vma for write. This - * is similar to folio_lock_anon_vma_read except the write lock - * is taken to serialise against parallel split or collapse - * operations. - */ - anon_vma =3D folio_get_anon_vma(folio); - if (!anon_vma) { - ret =3D -EBUSY; - goto out; - } - anon_vma_lock_write(anon_vma); - mapping =3D NULL; - } else { - unsigned int min_order; - gfp_t gfp; - - mapping =3D folio->mapping; - min_order =3D mapping_min_folio_order(mapping); - if (new_order < min_order) { - ret =3D -EINVAL; - goto out; - } - - gfp =3D current_gfp_context(mapping_gfp_mask(mapping) & - GFP_RECLAIM_MASK); - - if (!filemap_release_folio(folio, gfp)) { - ret =3D -EBUSY; - goto out; - } - - mapping_set_update(&xas, mapping); - - if (split_type =3D=3D SPLIT_TYPE_UNIFORM) { - xas_set_order(&xas, folio->index, new_order); - xas_split_alloc(&xas, folio, old_order, gfp); - if (xas_error(&xas)) { - ret =3D xas_error(&xas); - goto out; - } - } - - anon_vma =3D NULL; - i_mmap_lock_read(mapping); - } - - /* - * Racy check if we can split the page, before unmap_folio() will - * split PMDs - */ - if (folio_expected_ref_count(folio) !=3D folio_ref_count(folio) - 1) { - ret =3D -EAGAIN; - goto out_unlock; - } - - if (!is_anon) { - ret =3D __folio_split_unmap_and_freeze_file(folio, new_order, split_at, = &xas, mapping, - true, list, split_type); - } else { + if (is_anon) ret =3D __folio_split_unmap_and_freeze_anon(folio, new_order, split_at, = true, true, list, split_type); - } - - /* - * Drop the mapping while the inode is still pinned. @folio stays - * locked and present in the page cache until the loop below, so - * eviction cannot free the inode yet; @lock_at is not enough, it may - * be a tail beyond EOF that the split already dropped from the page - * cache. Nothing past this point may touch the inode or the mapping. - */ - if (mapping) { - i_mmap_unlock_read(mapping); - mapping =3D NULL; - } + else + ret =3D __folio_split_unmap_and_freeze_file(folio, new_order, split_at, + true, list, split_type); =20 /* * Unlock all after-split folios except the one containing @@ -4312,19 +4305,10 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, free_folio_and_swap_cache(new_folio); } =20 -out_unlock: - if (anon_vma) { - anon_vma_unlock_write(anon_vma); - put_anon_vma(anon_vma); - } - if (mapping) - i_mmap_unlock_read(mapping); -out: /* restore to caller's old_memcg */ set_active_memcg(old_memcg); mem_cgroup_put(memcg); out_no_memcg: - xas_destroy(&xas); if (is_pmd_order(old_order)) count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED); count_mthp_stat(old_order, !ret ? MTHP_STAT_SPLIT : MTHP_STAT_SPLIT_FAILE= D); @@ -4360,9 +4344,6 @@ int folio_split_unmapped(struct folio *folio, unsigne= d int new_order) VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_anon(folio), folio); =20 - if (folio_expected_ref_count(folio) !=3D folio_ref_count(folio) - 1) - return -EAGAIN; - return __folio_split_unmap_and_freeze_anon(folio, new_order, &folio->page= , false, false, NULL, SPLIT_TYPE_UNIFORM); } --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 42935397E73 for ; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; cv=none; b=dDUJEZA+/tdA524NbbrUlhqLrsWUw3gbRfhvCQL4refo42DReUAbewxJ4OC25ShC/1rM+NzKRLhJc8r1M+NQbkX3B15hfRIEijB7vNLIjwkfudU+hviE5XWTLmk+e97aBzhrViHtFcZ+gVM5Z9LobgbHTyO8D1Bz5BQHWW2AxRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; c=relaxed/simple; bh=ZGYahGpoGxsINHOEPB5yESjNQzFn4mBfE6UUR+TK7y8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=K6C4sydHf+W4NUgmeR4uTUiBvTdHV41KwN3I6cGZaQQq3rIjHBX5790EUx9Jv4hPOxFWQhyvZLVSNFeA72YUKCskMJ/wbzwDUeHuX8ILk9Gh4Z1DU9vbM9pitncWHJ3Re47dhpdS2/8l2pI/7NipT6gooiAuJt8RjiIpGz+Citk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PI9zKvos; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PI9zKvos" Received: by smtp.kernel.org (Postfix) with ESMTPS id 25F65C4AF09; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252129; bh=ZGYahGpoGxsINHOEPB5yESjNQzFn4mBfE6UUR+TK7y8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=PI9zKvoskMF9NrHX23aF668zBezcnpW7iL3COEjFXLmSmcE9GrKWJYN/4VYglgF+G a4SBaA0g2d4MKsoMZDtq3OwM4K71lT6wqvT9LQfBRgw7PGONpwyjXUlAO5ZsCKkky8 9PQv8ofbbd05AgYZqZqsW1GcATD/5MZBOQcdLLi6E+ZmOYsHdn8i9HrBzz09pO/FrW 3CzJiM0AtInGMxFjC3l7WvLFvWxeoe8gpBeYS+AQrC5WSLpksSDyU8npCegGwAwdvK WCfMW9BgwatAKQsgyvln6y6Pk9XU2fPc1BLJE3iciZF/g3GGXE3WjKHKE8+0EGQkAh R84pbu5qBdJ/A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0991BC5DF86; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:23 +0800 Subject: [PATCH v3 10/18] mm/huge_memory: move memcg switch into the file split helper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-10-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=3647; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=eMTqZ8JIOYum5cAAc6MT1lBInID0tKW7zfeYCZgfWVU=; b=zneDwfPqwi5R0lmrW6mAO6on1uogPVfixDYLlJBBggg3F+EzpANQSbBxWQBUQSwVBYf61f9bQ MEJXBQyjKOwDDrFoG9CIGwod6RCEMf2u+8RLgw5g3/JV3aGig26VYWq X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The xarray node allocations in __folio_freeze_split_unmap_file() need to be charged to the folio's memcg, so move the memcg switch from __folio_split() into the helper. The anon split helper and the after-split folio freeing perform no chargeable allocations, so no memcg handling is left in __folio_split(). Rename its out_no_memcg label to out. Acked-by: Zi Yan Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 1ee312cbd438..3029cb1f07f3 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4066,6 +4066,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int struct address_space *mapping =3D folio->mapping; XA_STATE(xas, &mapping->i_pages, folio->index); struct folio *end_folio =3D folio_next(folio); + struct mem_cgroup *memcg, *old_memcg; struct folio *new_folio, *next; int nr_shmem_dropped =3D 0; unsigned int min_order; @@ -4078,9 +4079,18 @@ static int __folio_split_unmap_and_freeze_file(struc= t folio *folio, unsigned int if (new_order < min_order) return -EINVAL; =20 + /* + * Switch to folio's memcg as xarray node allocation can happen and + * needs to charge to it. + */ + memcg =3D get_mem_cgroup_from_folio(folio); + old_memcg =3D set_active_memcg(memcg); + gfp =3D current_gfp_context(mapping_gfp_mask(mapping) & GFP_RECLAIM_MASK); - if (!filemap_release_folio(folio, gfp)) - return -EBUSY; + if (!filemap_release_folio(folio, gfp)) { + ret =3D -EBUSY; + goto fail_free; + } =20 mapping_set_update(&xas, mapping); =20 @@ -4217,6 +4227,9 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int */ i_mmap_unlock_read(mapping); fail_free: + /* Restore the previously active memcg */ + set_active_memcg(old_memcg); + mem_cgroup_put(memcg); xas_destroy(&xas); return ret; } @@ -4248,7 +4261,6 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, { struct folio *end_folio =3D folio_next(folio); bool is_anon =3D folio_test_anon(folio); - struct mem_cgroup *memcg, *old_memcg; int old_order =3D folio_order(folio); struct folio *new_folio, *next; int ret; @@ -4258,27 +4270,20 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, =20 if (folio !=3D page_folio(split_at) || folio !=3D page_folio(lock_at)) { ret =3D -EINVAL; - goto out_no_memcg; + goto out; } =20 if (new_order >=3D old_order) { ret =3D -EINVAL; - goto out_no_memcg; + goto out; } =20 ret =3D folio_check_splittable(folio, new_order, split_type); if (ret) { VM_WARN_ONCE(ret =3D=3D -EINVAL, "Tried to split an unsplittable folio"); - goto out_no_memcg; + goto out; } =20 - /* - * switch to folio's memcg as xarray node allocation can happen and - * needs to charge to it. - */ - memcg =3D get_mem_cgroup_from_folio(folio); - old_memcg =3D set_active_memcg(memcg); - if (is_anon) ret =3D __folio_split_unmap_and_freeze_anon(folio, new_order, split_at, = true, true, list, split_type); @@ -4305,10 +4310,7 @@ static int __folio_split(struct folio *folio, unsign= ed int new_order, free_folio_and_swap_cache(new_folio); } =20 - /* restore to caller's old_memcg */ - set_active_memcg(old_memcg); - mem_cgroup_put(memcg); -out_no_memcg: +out: if (is_pmd_order(old_order)) count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED); count_mthp_stat(old_order, !ret ? MTHP_STAT_SPLIT : MTHP_STAT_SPLIT_FAILE= D); --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C3C039B949 for ; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; cv=none; b=eeTCNX5S2hijecpDcx2CEFWWtOwXqAVtbJEpACZizKZIiGPZInJwaB6D/isoyuQSHcuD8wBT/XpBAL/77nUaUGpsx9XWAbSUV3o+4P0i2ltZEfccYFLXGFydJFAQc+kI4Ug0KRhvZ3VrtP8dlrDBYa1Do/EKOYkFOK0zKCekeZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; c=relaxed/simple; bh=qS4GqYWYyCCl8+fmXxoIq1Kn3P5FdUJnXvOLbgJEa5Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OYuF3oF8Bqb6vGKl804OvFnXPg+naKt5SXEqF7TpX6MMRL+EHwuTdBomXozRRyATVOAOWut6h8SeNmSdB9QNv5r64PT5jf2jITo6v8ZxHCLXP9U/H28doKoZXX2L2nObbinQw3fHqMOhh86tCAUcSSmC03OX2S9APk4R2ezeOQE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sMHXXLtk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sMHXXLtk" Received: by smtp.kernel.org (Postfix) with ESMTPS id 4DC6BC2BCC7; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252129; bh=qS4GqYWYyCCl8+fmXxoIq1Kn3P5FdUJnXvOLbgJEa5Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=sMHXXLtkAHLYLZzD+2nckPPvXWVlnM8Yxr/9pYnZ8pvfH1FcV9iHiYYkpatY3OIOz lAFY0Q5JMWaZbJOlrodHlUpOXWZ9PMzJutfc4S6NnmjjDjBTOCB00H5Lw3Hb7Zxq1h lNGJ/72e2o0w5Y2VWazqBpk1/44EMB89kt7oAoVHcxrwKsZ38omXVU7QJiFPHBtbfT o+Ez41bbGNFw3yCsfuoeTLzFFotDvo3ZlqaGRisfNxkNhA8l6TwPwCroo1IoyfCkHL S7ceJ/Q9hP6ehtIQULIU1kgVHgv4U9bchZnBQdkEraYzULeRjxhLRfLEPpB590pOIW uplKxjSTeZoYQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F6B0C5DF89; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:24 +0800 Subject: [PATCH v3 11/18] mm/huge_memory: allow splitting mappingless swap cache folios Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-11-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=5443; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=+MFrBoVl3UissmIXdeJ6Mf1y1W98vPZg6lWzSIq2S8w=; b=9MxM5xq4PW1atRNEtWMxx91LNUhT+mJy9k4IxQ04fXi5Ho8QFpxpINzrNVJMNsi/kw1TFRQqI z+DYD7MH8KxAq3QbHAHrQfgIDvWuGjgXSQC7XAbzH2H907ywtYOxxhr X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Lift the restriction that kept swap cache folios without a mapping from being split. All the underlying infrastructure is sound against that with a few more tweaks, no reason to block it anymore. Also rename the split helper, which now handles mappingless swap cache folios that are yet to be anon, or may actually belong to shmem. In either case there is not much difference in how they would be split. A non-anon swap cache folio that still has a mapping (e.g. a shmem swap cache folio) remains rejected up front: it would need both its page cache and swap cache entries updated on split, which the split helpers do not do, and there would be little benefit in doing so. Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun Reviewed-by: Zi Yan --- mm/huge_memory.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 3029cb1f07f3..0186238e0d1e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3881,12 +3881,10 @@ int folio_check_splittable(struct folio *folio, uns= igned int new_order, VM_WARN_ON_FOLIO(!folio_test_locked(folio), folio); /* * Folios that just got truncated cannot get split. Signal to the - * caller that there was a race. - * - * TODO: this will also currently refuse folios without a mapping in the - * swapcache (shmem or to-be-anon folios). + * caller that there was a race. A mappingless swap cache folio + * has no page cache entries to update, so it is fine to split. */ - if (!folio->mapping && !is_anon) + if (!folio->mapping && !is_swapcache) return -EBUSY; =20 /* order-1 is not supported for anonymous THP. */ @@ -3930,11 +3928,12 @@ static unsigned int folio_cache_ref_count(const str= uct folio *folio) return folio_nr_pages(folio); } =20 -static int __folio_split_unmap_and_freeze_anon(struct folio *folio, unsign= ed int new_order, - struct page *split_at, bool do_lru, bool unmap, - struct list_head *list, enum split_type split_type) +static int __folio_split_unmap_and_freeze(struct folio *folio, unsigned in= t new_order, + struct page *split_at, bool do_lru, bool anon_unmap, + struct list_head *list, enum split_type split_type) { struct folio *end_folio =3D folio_next(folio); + bool is_anon =3D folio_test_anon(folio); struct swap_cluster_info *ci =3D NULL; struct folio *new_folio, *next; int old_order =3D folio_order(folio); @@ -3952,7 +3951,7 @@ static int __folio_split_unmap_and_freeze_anon(struct= folio *folio, unsigned int * similar to folio_lock_anon_vma_read() except the write lock is * taken to serialize against parallel split or collapse. */ - if (unmap) { + if (anon_unmap) { anon_vma =3D folio_get_anon_vma(folio); if (!anon_vma) return -EBUSY; @@ -3965,7 +3964,7 @@ static int __folio_split_unmap_and_freeze_anon(struct= folio *folio, unsigned int goto out_unlock; } =20 - if (unmap) + if (anon_unmap) unmap_folio(folio); =20 local_irq_disable(); @@ -3976,8 +3975,11 @@ static int __folio_split_unmap_and_freeze_anon(struc= t folio *folio, unsigned int * a 0-ref folio, it assumes it beat folio_put() to the list * lock and must clean up the LRU state - the same dequeue we * will do below as part of the split. + * + * Only anon folios are ever queued on the deferred split list, + * so non-anon folios (mappingless swapcache) never need dequeuing. */ - dequeue_deferred =3D old_order > 1; + dequeue_deferred =3D old_order > 1 && is_anon; if (dequeue_deferred) { struct mem_cgroup *memcg; =20 @@ -4045,7 +4047,7 @@ static int __folio_split_unmap_and_freeze_anon(struct= folio *folio, unsigned int swap_cluster_unlock(ci); out_no_split: local_irq_enable(); - if (unmap) { + if (anon_vma) { if (!ret && !folio_is_device_private(folio)) ttu_flags =3D TTU_USE_SHARED_ZEROPAGE; remap_page(folio, 1 << old_order, ttu_flags); @@ -4259,6 +4261,7 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, struct page *split_at, struct page *lock_at, struct list_head *list, enum split_type split_type) { + bool is_swapcache =3D folio_test_swapcache(folio); struct folio *end_folio =3D folio_next(folio); bool is_anon =3D folio_test_anon(folio); int old_order =3D folio_order(folio); @@ -4285,8 +4288,11 @@ static int __folio_split(struct folio *folio, unsign= ed int new_order, } =20 if (is_anon) - ret =3D __folio_split_unmap_and_freeze_anon(folio, new_order, split_at, = true, - true, list, split_type); + ret =3D __folio_split_unmap_and_freeze(folio, new_order, split_at, true, + true, list, split_type); + else if (is_swapcache) + ret =3D __folio_split_unmap_and_freeze(folio, new_order, split_at, true, + false, list, split_type); else ret =3D __folio_split_unmap_and_freeze_file(folio, new_order, split_at, true, list, split_type); @@ -4346,8 +4352,8 @@ int folio_split_unmapped(struct folio *folio, unsigne= d int new_order) VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio); VM_WARN_ON_ONCE_FOLIO(!folio_test_anon(folio), folio); =20 - return __folio_split_unmap_and_freeze_anon(folio, new_order, &folio->page= , false, - false, NULL, SPLIT_TYPE_UNIFORM); + return __folio_split_unmap_and_freeze(folio, new_order, &folio->page, fal= se, + false, NULL, SPLIT_TYPE_UNIFORM); } =20 /* --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8774E39792C for ; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; cv=none; b=jgp6vhr0F00wLlIPKI3Os5JMZ3LQWytnVQwKwtOD81HNjwKPubfxwdCbUQKPam1wZxYTSyjkWqkwDXD5881MH/n5XgvddKjhj91nBQ3sohd/SBKSu6A5gmjiDJrRD9/B7wQDj07sSh5jHN9c+qKfYHVr8g3ewZFfY+AFKYwEmF4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; c=relaxed/simple; bh=Hzwzth9JfzXU6G/7k5R13jr0cPcr7N3JG9oLieGcwo8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RIZX99OL2dEfxN9TQxIWJRLOoIgmrZ6roI7vq21vXWuwLgrskJgNVQsrj1dapsuCpnV6WmNukzG5Dr1Ic/ggq5SOVR1cO5e5Qnk0lYHRVR0GudD2I+Fa3GteR/0tN41npT+KAYEpkhsmD9XfwkIL265TYSCxcV+0rOAlWQtIj3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=onLYRwOQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="onLYRwOQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 69EDDC2BCFF; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252129; bh=Hzwzth9JfzXU6G/7k5R13jr0cPcr7N3JG9oLieGcwo8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=onLYRwOQP/Q4tD/72aklmaQG2o4led0qUUOy3+WzTp8dH70FDgTPb0i3NcEtWJjnJ 98JKfK2PF8MYxbxfwM49vfZYj9uf1eYS6PpdFLlMz0kSfPgxWjzaSfibyhefBYdS71 XhfUPi+CqVgg0JGevJy4xCnegmfg+XsnBkczPc6yhZWft9uXKa4nEljRGg9xqAsRNa SPorjdiKjiaN4r7JW7gjRzZ3jc7tjVDddIsz6UQdIA8KTtWAhUDG+C+TgeeT8bKJaR ceW3nVZgO3lr5RFHZRS1ctzDBH7o+Y/ci39nrPQx7iulgrK99aNu41sUQQ1a+jxJR1 j/IRuezz+B/Bg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 559B6C5DF85; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:25 +0800 Subject: [PATCH v3 12/18] mm/huge_memory: add kerneldoc for the split helpers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-12-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=3229; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=kkYICD6QbWqRFssjOxU44lo2ZuCNOXywu0Ctt6XQNZg=; b=iTb0ckBN6dHmAPctrV4Br62LLWX6ZAgNv/UeyxZEBzV+MXrW6V5bKZvdnEYS4etaaE7oZcsiQ Tnhy+6ivET2AtWL0LL710cO5ulJmEpy4gR0CElo5+/xpitRNlIxHA6b X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Document __folio_split_unmap_and_freeze() and __folio_split_unmap_and_freeze_file(), and rename the file split helper's definition to match its call site. Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun Reviewed-by: Zi Yan --- mm/huge_memory.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0186238e0d1e..72b364a90062 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3928,6 +3928,25 @@ static unsigned int folio_cache_ref_count(const stru= ct folio *folio) return folio_nr_pages(folio); } =20 +/** + * __folio_split_unmap_and_freeze() - split an anon or swap cache folio + * @folio: folio to split, must be locked + * @new_order: the order of the after-split folios (uniform split), or the + * smallest order of the after-split folios (non-uniform split) + * @split_at: in non-uniform split, the folio containing @split_at is split + * until its order becomes @new_order + * @do_lru: if true, add after-split folios to @list if non NULL, otherwis= e to + * the LRU list + * @anon_unmap: if true, unmap @folio before the split and remap it after + * @list: after-split folios will be put on it if non NULL + * @split_type: perform uniform split or not (non-uniform split) + * + * Helper for splitting an anon or swap cache folio. It unmaps @folio (unl= ess + * @anon_unmap is false), freezes its refcount, and performs the split, up= dates + * the swap cache entries. Split folios are unfrozen and remapped. + * + * Return: 0 on success, otherwise an error number is returned. + */ static int __folio_split_unmap_and_freeze(struct folio *folio, unsigned in= t new_order, struct page *split_at, bool do_lru, bool anon_unmap, struct list_head *list, enum split_type split_type) @@ -4061,6 +4080,25 @@ static int __folio_split_unmap_and_freeze(struct fol= io *folio, unsigned int new_ return ret; } =20 +/** + * __folio_split_unmap_and_freeze_file() - split a file-backed folio + * @folio: folio to split, must be locked and file-backed + * @new_order: the order of the after-split folios (uniform split), or the + * smallest order of the after-split folios (non-uniform split) + * @split_at: in non-uniform split, the folio containing @split_at is split + * until its order becomes @new_order + * @do_lru: if true, add after-split folios to @list if non NULL, otherwis= e to + * the LRU list + * @list: after-split folios will be put on it if non NULL + * @split_type: perform uniform split or not (non-uniform split) + * + * Helper for splitting a file-backed folio. It unmaps @folio, freezes its + * refcount, and perform the split, updates the page cache entries. Split + * folios are unfrozen but not remapped, they are faulted back in on deman= d. + * + * Return: 0 on success, otherwise an error number is returned. (if -ENOMEM + * is returned, @folio might be split but not to @new_order) + */ static int __folio_split_unmap_and_freeze_file(struct folio *folio, unsign= ed int new_order, struct page *split_at, bool do_lru, struct list_head *list, enum split_type split_type) --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A870C39BFE7 for ; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; cv=none; b=Y69L5h18uPzTXnm1eqgjl7KOx2g1HeNmQQ4Lfsfd+5Bk0+yMp7KlVDHclu2GbvU+2p8J6+LYLifufRXAxEmxAoE9oUu4NLM7+EUiC2syA/TSdE1h3IIaelFvuPLDbJZeG5qmPfah3iPd1G1SxT9unklX/mLx6MWTFu6Q+Au3LAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252129; c=relaxed/simple; bh=F/veNG6x4bSM+ZHU80+kOOADneaHOKiDsvyy52Z3utE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VcTAb1Kn5ch/TbdnITrG7dQnoKbW+xrSQTVmXg2fn3sC/Jt7NEoNdEeuVgxPxwbL0Yu3AmlQDClCwaOdPjCt2GGN6lDC+KE32aZ0vgypP+hRPPsMEn6zELbJn6EpW/k+c9KMk7TOUCCZ8cVwstt1cLDLq6uhVKn3r03dDAEeVcM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BO/MEsuR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BO/MEsuR" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8A1F1C2BCFC; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252129; bh=F/veNG6x4bSM+ZHU80+kOOADneaHOKiDsvyy52Z3utE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=BO/MEsuR+mhu/LBzLZD03DI3O3i6aivmWCCW1BF7O2XgfSVBeQpbNL/mGgu7L0qID cwsvv9bR64J0byIxRecIrHChf1XKadwhsxIwAAyQmcaZpH7UCMAA9jEjkYYBUQ0sQG cwiayzhQNHsvKkj9vbT4dVMm6jlaBDqYUQvQPZ2k7cmDHX4HxDZXbXsonCGT47C4+3 rjqq1xVUuFMTMzyf/84rpSxsVeurK1Fmp6mYgORGhBXQqwciscIGarcHl4MH/ozGjZ /8AxujBPgj69K9x3zsKz0cac5jFCBUTpxzLw2btV5V5oWWGLIjDiE7fAMVEQ5o4bAZ +GAO28KIUOrsQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 75984C5DF8C; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:26 +0800 Subject: [PATCH v3 13/18] mm/huge_memory: drop the unused do_lru argument of the file split helper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-13-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=3118; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=s7TgEALmkIL/2xL5mg01PDrva5N+mct9TklI6TyUYnE=; b=V20sD2oW1vdDGjcEea3QpexdnTRqM1+FRJ1Y9d3JudIe18U9Ozqj32oILE/ceGqodrSPBNr20 cnQAa9oupwxD3cgcv/ggE5vKkEip3RSbrFhumT7Zv0LHHDmVZiRySlR X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The only caller of __folio_split_unmap_and_freeze_file() always passes do_lru as true, so the argument and the branches gated on it are dead code. Drop it. Signed-off-by: Kairui Song Acked-by: David Hildenbrand (Arm) Reviewed-by: Yeoreum Yun Reviewed-by: Zi Yan --- mm/huge_memory.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 72b364a90062..84c6e4bbaa88 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4087,8 +4087,6 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ * smallest order of the after-split folios (non-uniform split) * @split_at: in non-uniform split, the folio containing @split_at is split * until its order becomes @new_order - * @do_lru: if true, add after-split folios to @list if non NULL, otherwis= e to - * the LRU list * @list: after-split folios will be put on it if non NULL * @split_type: perform uniform split or not (non-uniform split) * @@ -4100,8 +4098,8 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ * is returned, @folio might be split but not to @new_order) */ static int __folio_split_unmap_and_freeze_file(struct folio *folio, unsign= ed int new_order, - struct page *split_at, bool do_lru, - struct list_head *list, enum split_type split_type) + struct page *split_at, struct list_head *list, + enum split_type split_type) { struct address_space *mapping =3D folio->mapping; XA_STATE(xas, &mapping->i_pages, folio->index); @@ -4196,9 +4194,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int } =20 /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ - if (do_lru) - lruvec =3D folio_lruvec_lock(folio); - + lruvec =3D folio_lruvec_lock(folio); ret =3D __split_frozen_folio(folio, new_order, split_at, &xas, mapping, split_type); =20 @@ -4220,8 +4216,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int folio_ref_unfreeze(new_folio, folio_cache_ref_count(new_folio) + 1); =20 - if (do_lru) - lru_add_split_folio(folio, new_folio, lruvec, list); + lru_add_split_folio(folio, new_folio, lruvec, list); =20 /* Add the new folio to the page cache. */ if (new_folio->index < end) { @@ -4247,9 +4242,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int * and its caller can see stale page cache entries. */ folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1); - - if (do_lru) - lruvec_unlock(lruvec); + lruvec_unlock(lruvec); fail: /* * If we want to use try_to_migrate() on file in unmap_folio, @@ -4333,7 +4326,7 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, false, list, split_type); else ret =3D __folio_split_unmap_and_freeze_file(folio, new_order, split_at, - true, list, split_type); + list, split_type); =20 /* * Unlock all after-split folios except the one containing --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C44139CCF1 for ; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; cv=none; b=EcnoWpW/IUsmqBrOpP5l+q14wCVfkWB+ZXplLStWkpLpCjt7MsBDvMp03T/qKzfk71HL16NEsRYEum3c9y55Tcv0sF7tNl+K/Yzccll4iBpVRo5cliRPDlZI30lCmKP0/nshuNjl7daxIRLT6W5E51D0W5r6vH3mHYxf1iXlmM0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; c=relaxed/simple; bh=ZdMCHVoFYQCILSgXOuBnI4SarXdsYWmXjvhz54wwgc8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DpGDDty5RGdIamNqvcJsEk90oBOXSqNxV5jy9CVaVp68GDQkPAHXMqkGqfuSWnEZ5Y7OZLjQamSgIAYpwql9LkIGcivV45K+33SN0ywTKJeSb2Nfdw6JdsJ9QcQAGyB2is/qraGx4QZFnawTD1WBftMGOS15Ia9XontPIeL6DqA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SZlwNopf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SZlwNopf" Received: by smtp.kernel.org (Postfix) with ESMTPS id C4FF9C2BCB3; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252129; bh=ZdMCHVoFYQCILSgXOuBnI4SarXdsYWmXjvhz54wwgc8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=SZlwNopfxk4IoGogIaPtPK2wSYSJT5Nk1lsQ+oncbSqCgXPAd4L9t0kc1ihIJJFiU UYAMmuK15Ts4vB9Ot3E3jBEN4w4rjtAIS/Mm8SDYlSVXXcCqdFnqJPqq3USdR38z6w 9No3+7LJ+GPd3Lur6B5MpaKSy+5zb8Xfpbkz05UanPVbE5wM6tRfkkeDCiiF3nZB+z sF3oTFmNFLCkSyNl7XDiTk9H0t0zC/YAhKKPZDNBdQ7MaRu4cH6d10LPUW7gvPLF5F IkeqQeH4pBmiohHazwQnkNVNaOiXONm3Hs80dzp16RNdcU0VxuIlDjDTs50nMW+Es7 rWJglXf3BdANw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A02EDC5DF89; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:27 +0800 Subject: [PATCH v3 14/18] mm/huge_memory: clean up after-split folio freeing in __folio_split Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-14-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=2112; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=inPttDVpThP3IDtiWZmKlScFOY7gDvdR6fwZyskm3d8=; b=TTz/tqeNbxw/fhpg7X6kae4SyHT4Bfkz02ieoBqhE+MPrhNF5KdXVm+oJV4VxPohoszYr5X+d 7fpJSE+ijlEB4vYBXYxpkQUfwNZV6TdWvLt/zwSkULqqVG4rTq6UK8y X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Replace free_folio_and_swap_cache() with an explicit folio_free_swap() and folio_put() in the after-split loop. free_folio_and_swap_cache() unlocks the folio, then free_swap_cache() must trylock it again and re-check folio_mapped() before freeing the swap cache entries; if the trylock loses a race, the entries are left behind even though the folio reference is dropped. The sub folios are still locked and unmapped here, so just directly call folio_free_swap() directly under the lock, unlock and drop the reference. This makes the swap cache freeing deterministic and the reference drop explicit. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 84c6e4bbaa88..113a33cddace 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4337,14 +4337,16 @@ static int __folio_split(struct folio *folio, unsig= ned int new_order, if (new_folio =3D=3D page_folio(lock_at)) continue; =20 - folio_unlock(new_folio); /* * Subpages whose mapping has been zapped may be freed * earlier, but freeing them requires taking the - * lru_lock, so we defer put_page() on tail pages until + * lru_lock, so we defer folio_put() on tail pages until * after the split completes. */ - free_folio_and_swap_cache(new_folio); + if (is_swapcache && !folio_mapped(new_folio)) + folio_free_swap(new_folio); + folio_unlock(new_folio); + folio_put(new_folio); } =20 out: @@ -4371,7 +4373,7 @@ static int __folio_split(struct folio *folio, unsigne= d int new_order, * isolated from LRU (if applicable) * * Upon return, the folio is not remapped, split folios are not added to L= RU, - * free_folio_and_swap_cache() is not called, and new folios remain locked. + * folio_free_swap() is not called, and new folios remain locked. * * Return: 0 on success, -EAGAIN if the folio cannot be split (e.g., due to * insufficient reference count or extra pins). --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4409939936E for ; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; cv=none; b=fb2RXmoUrzTMQNmJ+c8KvOjx5lVjn/sABIud+HuY2jzFUEO40I8AyHZcw5N5CmnlytEdajm+8ICRNxzD1/ZSMtDqUsuYZzh3hJfWj/00QX4GCZT4kvp19vw5cl/3yPrs0pH5S5VQituGfZagqDOlN++IMSnjDyeP/25QO+Zk76Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; c=relaxed/simple; bh=ya21pIxQSsux3BlG3ZskOAeG3L0c/ADEJFGxjEU1tt4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pbERCGrRFdrYlb/42R+zPpHjZGLbR4sMKWnMBB3v6TEruNc5NT++13tsPPL0igxshJYgNJY/qUVywdJtPNNItv6k7AGcamssoHVgLLCZlw0ic0HqKWNG1UCPwhzUgyNTy4WE9twuhvZr7OX87hRlXmFKIuUp8gpHGjDM8at7WrE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LKIyxWIm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LKIyxWIm" Received: by smtp.kernel.org (Postfix) with ESMTPS id F38E3C2BCC7; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252130; bh=ya21pIxQSsux3BlG3ZskOAeG3L0c/ADEJFGxjEU1tt4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LKIyxWImlc2IcOOlxch9s/7zFW9lEp5rgR0mu2ye+Cky5ByyonJwK68+lV1wamnyW Z/ueTo+9MZ/4JCX1rQz6TnUIBnZR8o+HQOh9Y7aTc4ROmRTwSNhGSEA1IHMDdlL2WJ BdJqFI2FI6CbWwZPm086VksDdqG1jRQrlUjEHUhpHZYLBnNp3UirIsisZQrklKbVmt Ibe/Akj08kwkVjp6JcjCRD/kaXTYNycm9dnfsBDNtgWtz4tRTrYDwU4kfmSRW8Mh8c l3LUQY5sUz9D/VyglViS5xYZ7n/uxN0hwQYketPlIF4wUDp5zB+qJrdSc6ZKDF1qBn oHL4w3d6t8CsA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE71FC5DF86; Thu, 20 Aug 2026 18:55:29 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:28 +0800 Subject: [PATCH v3 15/18] mm/huge_memory: lift order-0 restriction for swapcache split Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-15-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=4239; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=Ck/sQwhNsEW7aOrpnl5OtjvomBAG/W4r8DcOvIJa0P4=; b=KLUkvjpHuIejSkFjYK0HMSbyzjaxKoIAJ+uo9IzE7hImYJ+OOK35RtL0A1PuF+MuXjplnbn8O wCoG1pOHgkgBZikpmNMeb57klT4fItMH6zmloALB+tQjIjeQVp8zy+z X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The restriction that swapcache folios can only be uniformly split to order 0 dates back to when the swap cache was managed via address_space mapping (swap_address_space). The old split loop only created order-0 sub-folios with a fixed stride, so non-uniform split and non-zero order were rightfully blocked. After the swap cache switched to swap table under a cluster lock, __swap_cache_replace_folio already gained the ability to replace any number of entries for any sub-folio size in one cluster, and the old swap_address_space locking and limit was removed. The restriction became obsolete but persisted through multiple refactorings. Drop it now: swapcache folios can be split to any supported order with either uniform or non-uniform split, except order-1 which is not supported for anon folios. Mappingless swap cache folios could be either anon or shmem, so for now we just simply forbid order-1 for all swapcache. Acked-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 113a33cddace..06f353f937d1 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3797,6 +3797,7 @@ static int __split_frozen_folio(struct folio *folio, = int new_order, struct address_space *mapping, enum split_type split_type) { const bool is_anon =3D folio_test_anon(folio); + const bool is_swapcache =3D folio_test_swapcache(folio); int old_order =3D folio_order(folio); int start_order =3D split_type =3D=3D SPLIT_TYPE_UNIFORM ? new_order : ol= d_order - 1; struct folio *old_folio =3D folio; @@ -3811,8 +3812,8 @@ static int __split_frozen_folio(struct folio *folio, = int new_order, split_order--) { int nr_new_folios =3D 1UL << (old_order - split_order); =20 - /* order-1 anonymous folio is not supported */ - if (is_anon && split_order =3D=3D 1) + /* order-1 anonymous or swapcache folio is not supported */ + if ((is_anon || is_swapcache) && split_order =3D=3D 1) continue; =20 if (mapping) { @@ -3887,19 +3888,13 @@ int folio_check_splittable(struct folio *folio, uns= igned int new_order, if (!folio->mapping && !is_swapcache) return -EBUSY; =20 - /* order-1 is not supported for anonymous THP. */ - if (is_anon && new_order =3D=3D 1) - return -EINVAL; - /* - * swapcache folio could only be split to order 0 - * - * non-uniform split creates after-split folios with orders from - * folio_order(folio) - 1 to new_order, making it not suitable for any - * swapcache folio split. Only uniform split to order-0 can be used - * here. + * Order-1 is unsupported: anon folios need subpage 2 for the + * deferred split list, hybrid shmem & swap cache folios are not + * splittable, and a splittable mappingless swap cache folio could + * be either anon or shmem, which we cannot tell apart. */ - if ((split_type =3D=3D SPLIT_TYPE_NON_UNIFORM || new_order) && is_swapcac= he) + if ((is_anon || is_swapcache) && new_order =3D=3D 1) return -EINVAL; =20 if (is_huge_zero_folio(folio)) @@ -4405,11 +4400,11 @@ int folio_split_unmapped(struct folio *folio, unsig= ned int new_order) * GUP pins, will result in the folio not getting split; instead, the c= aller * will receive an -EAGAIN. * - * 4) @new_order > 1, usually. Splitting to order-1 anonymous folios is not - * supported for non-file-backed folios, because folio->_deferred_list,= which - * is used by partially mapped folios, is stored in subpage 2, but an o= rder-1 - * folio only has subpages 0 and 1. File-backed order-1 folios are supp= orted, - * since they do not use _deferred_list. + * 4) @new_order > 1, usually. Order-1 is not supported for anon or swapca= che + * folios: anon folios need subpage 2 for _deferred_list, which order-1 + * folios lack, and a swapcache folio may become anon once faulted in. + * File-backed order-1 folios are supported, since they do not use + * _deferred_list. * * After splitting, the caller's folio reference will be transferred to @p= age, * resulting in a raised refcount of @page after this call. The other page= s may --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49D4539CCF5 for ; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; cv=none; b=KUSRb7MtglUTSBFMgHOOLE5YY8jGOJZOkBMRLsyx8hqdWcQdxK9kNo7F0f7+nykM+sUgm92HMqWadPvw3qmN89OTwzVE4WYH1zT32knPQxaR/TH2BLwOFhw9WYzlS46AzWWRecvQ99536EHziuttfw4VvOkpz5jI8IbYJU6wnUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; c=relaxed/simple; bh=D+uYtmzqMh1Chmlc5Iro9Bjk9B5bgnOe9YSwa3oEhv0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EnH6Q+Kz9iIXQbPBov/vok8fLd/e2S6r5F4/ATLYGwjwP7YAL3UATEE3povuinnzwjKRZL6Ha9hicFWpuVCusjTLZBovs4A8dtgTJvZuCn40Z5Cx5Zw4/Qe7QENV/M06bRd1fSC2Pt2VPPlTB3cY5IEdMB1ozhRc+AxJI5W51Vc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bfX1Qk9G; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bfX1Qk9G" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1DB38C2BCFA; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252130; bh=D+uYtmzqMh1Chmlc5Iro9Bjk9B5bgnOe9YSwa3oEhv0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=bfX1Qk9GSn5/3hzJsqKe5TXcVumqiTi0WOTOzHH0z7h6YBwO03NbIod7U7xRh3tSm v56cgtj3YmQhgRyIx/5/LrCv5XYYS0nRS4yTzBBhAM0kfbtbvhWAgm/bnta/teokOP w0J1t1Q0Y/B5UrZ3KlJLqQksarvZawVL8UoquUk0pvPHxie7GtK7AlyTVvTAN3ap6k BKQtN1HLJ60enlMz/sovC/ZCGDnQ8YsSx6VdDFkN00R+yh3bU/FtsD19y2dtdbW8/g 7fwyEUtutCBqnDBGVqDJDK7xMAw+ux3i0CModc6J7V8CAdgI33rPyO88lWUOtsgmV3 oDUtp9JOkhwcA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 024DCC5DF85; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:29 +0800 Subject: [PATCH v3 16/18] mm/huge_memory: clarify supported split orders in comment Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-16-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=1942; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=ZOm4Nz3i3imY6j3a4YN28Ig3P8X8i5gtRVzey97AJz8=; b=VqkQiDNbmac/QvX+JvB+ToITPSitcf/coH2/Q8btONl7ekAFpAv0q6SURT2xGF1l7wRaMsQaw piVlB5Tca96AdnZuEGUjx9Nf/H4NFkwBG2eOAsTRk3q+rJ8cN0rBGAx X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The doc comment for __split_huge_page_to_list_to_order() needs an update: only order 1 is rejected for anon and swapcache folios, matching the new_order =3D=3D 1 check in folio_check_splittable(). Also realign the continuation line of the function signature while at it. Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun Reviewed-by: Zi Yan --- mm/huge_memory.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 06f353f937d1..0a971ca48151 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4400,11 +4400,10 @@ int folio_split_unmapped(struct folio *folio, unsig= ned int new_order) * GUP pins, will result in the folio not getting split; instead, the c= aller * will receive an -EAGAIN. * - * 4) @new_order > 1, usually. Order-1 is not supported for anon or swapca= che - * folios: anon folios need subpage 2 for _deferred_list, which order-1 - * folios lack, and a swapcache folio may become anon once faulted in. - * File-backed order-1 folios are supported, since they do not use - * _deferred_list. + * 4) @new_order !=3D 1 for anon or swapcache. Anon folios need subpage 2 = for + * _deferred_list, which order-1 folios lack, and a swapcache folio may + * become anon once faulted in. File-backed order-1 folios are supporte= d, + * since they do not use _deferred_list. * * After splitting, the caller's folio reference will be transferred to @p= age, * resulting in a raised refcount of @page after this call. The other page= s may @@ -4432,7 +4431,7 @@ int folio_split_unmapped(struct folio *folio, unsigne= d int new_order) * with the folio. Splitting to order 0 is compatible with all folios. */ int __split_huge_page_to_list_to_order(struct page *page, struct list_head= *list, - unsigned int new_order) + unsigned int new_order) { struct folio *folio =3D page_folio(page); =20 --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E92B39934B for ; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; cv=none; b=MYq2OVh60IKLRDEfRwXJ1bX0LRAPfaYnjBaxsB13mNDb4Pgksvta0UMeYpojpciZsBD5E74P1sCMzjFtq4AMUyI/CkGPxU5SoLrj5ap29vOhatk2TGSBGbwpAAYWtQjVh3gzBd81Rr9QzXaSxsf/+/lthpNwkQXpWTCWODwlFo0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; c=relaxed/simple; bh=1Vp9iAi7DIBv3YUqfa5ynWvIwCbIw7QgrLewvsEwF+o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=i6+4P+wXI/fZPTuK1BJ8vbp8NPG+msEneq+f1sugl5hLH/5eVv7W4zZ2y4ipzSI48up175kuv9nfHM//8vNvn8w0uqSzs1p+naZ7pnkq+c3R3WuPcUXY8aVV7b8UsvGpoKGAq795TWsW8QDdLAdJ7pJlATftMuop/H+mAVE4Peg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aZpC8W66; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aZpC8W66" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3DB0FC2BCFF; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252130; bh=1Vp9iAi7DIBv3YUqfa5ynWvIwCbIw7QgrLewvsEwF+o=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=aZpC8W66dfNf+SamEGN4vhzqHHK8YgSt2tWjjhzQY8ctF7cG3iTDKQvDB/veT/h0Q 1KIDjigFwhJCKOL0syroAZBU7d/j+4BnWHgcyavwOYC7VDHlvpicWxNfLSAdjs83Fm BjGSfYX4j8P5j/dQw3B6vem4qOCpS0uJZtJi1nXcD0e29HGSQJXQkjPIGyisYWLD0/ cH54Vt2AP9k7946vIADiSgt7MkSqZYbASbJZb7DaI+OzeefcrSo2vE9LZZEg9rYOFp K2neksMCrJBqva5TGl73nm0FwVL88SD6O9YC0APGurE/d3IRxwo+f+7rxOYOq5q5N5 bKN09TjR5amFg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20209C5DF8C; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:30 +0800 Subject: [PATCH v3 17/18] mm/huge_memory: count only swap cache refs in anon folio split Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-17-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=4442; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=TgKhkDQrFrEKVN/TkYCZhsRocqLMR143+q4KiemUWkA=; b=3dJobk7dFRk7m9rm1E1L3nmEN9fHa8TbQflgudEQNEGDJmF5szk2IpfMrxAoOfjSI+ZlLN2sw xs7d+tsMjj2ANRfh3Y/tPn/oaCQ72rNh8px1QsyCt5KumYB04Idu06a X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song Only __folio_freeze_split_unmap() sees anon folios and swap cache folios now. The file split helper only handles page cache folios, which hold exactly folio_nr_pages() references. Rename folio_cache_ref_count() to folio_swapcache_ref_count() and drop the anon check so the helper counts what its name says. The file split helper now uses folio_nr_pages() directly. Reviewed-by: Zi Yan Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun --- mm/huge_memory.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0a971ca48151..3e4c0fac7ba6 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3915,10 +3915,10 @@ int folio_check_splittable(struct folio *folio, uns= igned int new_order, return 0; } =20 -/* Number of folio references from the pagecache or the swapcache. */ -static unsigned int folio_cache_ref_count(const struct folio *folio) +/* Number of folio references from the swapcache. */ +static unsigned int folio_swapcache_ref_count(const struct folio *folio) { - if (folio_test_anon(folio) && !folio_test_swapcache(folio)) + if (!folio_test_swapcache(folio)) return 0; return folio_nr_pages(folio); } @@ -4003,7 +4003,7 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ folio_nid(folio), &memcg); } =20 - if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) { + if (!folio_ref_freeze(folio, folio_swapcache_ref_count(folio) + 1)) { if (dequeue_deferred) { list_lru_unlock(lru); rcu_read_unlock(); @@ -4045,7 +4045,7 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ next =3D folio_next(new_folio); zone_device_private_split_cb(folio, new_folio); folio_ref_unfreeze(new_folio, - folio_cache_ref_count(new_folio) + 1); + folio_swapcache_ref_count(new_folio) + 1); if (do_lru) lru_add_split_folio(folio, new_folio, lruvec, list); if (ci) @@ -4053,7 +4053,7 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ } =20 zone_device_private_split_cb(folio, NULL); - folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1); + folio_ref_unfreeze(folio, folio_swapcache_ref_count(folio) + 1); =20 if (do_lru) lruvec_unlock(lruvec); @@ -4099,6 +4099,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int struct address_space *mapping =3D folio->mapping; XA_STATE(xas, &mapping->i_pages, folio->index); struct folio *end_folio =3D folio_next(folio); + long old_nr_pages =3D folio_nr_pages(folio); struct mem_cgroup *memcg, *old_memcg; struct folio *new_folio, *next; int nr_shmem_dropped =3D 0; @@ -4170,22 +4171,16 @@ static int __folio_split_unmap_and_freeze_file(stru= ct folio *folio, unsigned int goto fail; } =20 - if (!folio_ref_freeze(folio, folio_cache_ref_count(folio) + 1)) { + if (!folio_ref_freeze(folio, old_nr_pages + 1)) { ret =3D -EAGAIN; goto fail; } =20 - if (folio_test_pmd_mappable(folio) && - new_order < HPAGE_PMD_ORDER) { - int nr =3D folio_nr_pages(folio); - - if (folio_test_swapbacked(folio)) { - lruvec_stat_mod_folio(folio, - NR_SHMEM_THPS, -nr); - } else { - lruvec_stat_mod_folio(folio, - NR_FILE_THPS, -nr); - } + if (folio_test_pmd_mappable(folio) && new_order < HPAGE_PMD_ORDER) { + if (folio_test_swapbacked(folio)) + lruvec_stat_mod_folio(folio, NR_SHMEM_THPS, -old_nr_pages); + else + lruvec_stat_mod_folio(folio, NR_FILE_THPS, -old_nr_pages); } =20 /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ @@ -4209,7 +4204,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int next =3D folio_next(new_folio); =20 folio_ref_unfreeze(new_folio, - folio_cache_ref_count(new_folio) + 1); + folio_nr_pages(new_folio) + 1); =20 lru_add_split_folio(folio, new_folio, lruvec, list); =20 @@ -4236,7 +4231,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int * Otherwise, a parallel folio_try_get() can grab @folio * and its caller can see stale page cache entries. */ - folio_ref_unfreeze(folio, folio_cache_ref_count(folio) + 1); + folio_ref_unfreeze(folio, folio_nr_pages(folio) + 1); lruvec_unlock(lruvec); fail: /* --=20 2.55.0 From nobody Mon Sep 28 14:00:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73C7D39CD06 for ; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; cv=none; b=spdhA8KSO3tWJQGvJ+ofVYoMfzArem6GaNCH51qwRS+5e2BZk1ZaLMO5lUT+G/TUxhOncn2RFpqyW9LsJmzzLQ1BW0a3N7YRm6nJ8HeJJx02b+dOSMEkM0vkhdLP1oOsMgPSyMm5LhWfPvY2E2o8aWqr9pnMzG9dgqvIHOkbtBQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787252130; c=relaxed/simple; bh=SWtLgMu8GvUawbF95kE3Xr/LCFZlkb7lXy3FF4qxH2c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qFWYD1I1Rz1VhzrAbrT3b7P90aJRHxCLPpGU1nGGU65Ryb2jcaQms01hzz64swtYrLKgitieQbtOiAn5HANpke+0VOzEHz/Rsj9S/hI3kWfpCM0dsFtMkvgHSHlSprXtC+cukc/4KOgu89PoKPBdCfihUYgKPViAu8/ur4J55Fs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Omn759rG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Omn759rG" Received: by smtp.kernel.org (Postfix) with ESMTPS id 56433C4AF0D; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787252130; bh=SWtLgMu8GvUawbF95kE3Xr/LCFZlkb7lXy3FF4qxH2c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Omn759rGwGCH/Yu002GtXsO3kH5oCUq0cfePxXsf20jOf4JLWB+zBobOrRKDnwZGA rNQcbmOxvyPIwE7WbnKbaCwas1x1wqGoArS4gd99g6eGnmHoEqQ3qHYbDjkWJbgs3B h/jjSkowmD0G3EQ0DPZco4p75raoQpterjcdsyVxgrI+ImJS+OdkhTUB1LCHGQUy0Q mSkAlGERLROwGzpYTjg2Wb0mrKJ9iMnoyXvlZf3YvMuYgl+XMw94cNNfSuc+oeWXYj iKlHfLkcUpy2wzTM6GB/8ThFy5GL7cM29Bmz7gFIFMkzYCYyIPwKXlEltGybfLLdUd kt9bZ50/ghquA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3DFE7C5DF81; Thu, 20 Aug 2026 18:55:30 +0000 (UTC) From: Kairui Song via B4 Relay Date: Fri, 21 Aug 2026 02:55:31 +0800 Subject: [PATCH v3 18/18] mm/huge_memory: drop the redundant mapping argument of __split_frozen_folio Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260821-swap-thp-cleanup-v3-18-9b43f5163238@tencent.com> References: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> In-Reply-To: <20260821-swap-thp-cleanup-v3-0-9b43f5163238@tencent.com> To: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org, Andrew Morton , David Hildenbrand , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R. Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Lance Yang , Usama Arif , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Chris Li , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , Shivam Kalra , Kairui Song , Kairui Song X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787252124; l=2730; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=C/KWMIc1TIGmzytCo1JZzeZN1wb37i566yMOyV+S0h4=; b=pofJaSAoZPdagM0AwrC0JaDfa+6zRFpa+ZSDQm5WY/uffAKQWRp+Grd+4i7g3llomauI/M5sO ei0FFMii7viDibexOhjJv3emPk+9DlA90cruEMHWMOU4KNGEX7o7opn X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song The mapping parameter only served as a non-NULL check to detect whether page cache entries need updating. The xa_state pointer conveys exactly the same information: the anon split helper passes NULL and the file split helper passes &xas, which is non-NULL iff the folio is in the page cache. Use the xas pointer instead and drop the parameter, along with its kerneldoc entry. Signed-off-by: Kairui Song Reviewed-by: Yeoreum Yun Reviewed-by: Zi Yan --- mm/huge_memory.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 3e4c0fac7ba6..cc9f7e0d4194 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3761,7 +3761,6 @@ static void __split_folio_to_order(struct folio *foli= o, int old_order, * @split_at: in buddy allocator like split, the folio containing @split_at * will be split until its order becomes @new_order. * @xas: xa_state pointing to folio->mapping->i_pages and locked by caller - * @mapping: @folio->mapping * @split_type: if the split is uniform or not (buddy allocator like split) * * @@ -3794,7 +3793,7 @@ static void __split_folio_to_order(struct folio *foli= o, int old_order, */ static int __split_frozen_folio(struct folio *folio, int new_order, struct page *split_at, struct xa_state *xas, - struct address_space *mapping, enum split_type split_type) + enum split_type split_type) { const bool is_anon =3D folio_test_anon(folio); const bool is_swapcache =3D folio_test_swapcache(folio); @@ -3816,7 +3815,7 @@ static int __split_frozen_folio(struct folio *folio, = int new_order, if ((is_anon || is_swapcache) && split_order =3D=3D 1) continue; =20 - if (mapping) { + if (xas) { /* * uniform split has xas_split_alloc() called before * irq is disabled to allocate enough memory, whereas @@ -4030,8 +4029,7 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ if (do_lru) lruvec =3D folio_lruvec_lock(folio); =20 - ret =3D __split_frozen_folio(folio, new_order, split_at, NULL, - NULL, split_type); + ret =3D __split_frozen_folio(folio, new_order, split_at, NULL, split_type= ); =20 /* * Unfreeze the post-split folios and put them back to the right @@ -4185,8 +4183,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int =20 /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ lruvec =3D folio_lruvec_lock(folio); - ret =3D __split_frozen_folio(folio, new_order, split_at, &xas, - mapping, split_type); + ret =3D __split_frozen_folio(folio, new_order, split_at, &xas, split_type= ); =20 /* * Unfreeze after-split folios and put them back to the right --=20 2.55.0