From nobody Tue Sep 29 04:12:16 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 D8A132F1FED for ; Wed, 12 Aug 2026 18:49:13 +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=1786560553; cv=none; b=tIVGG6qdM9KCWcuXDON/gxjvYkKFtpAm7p5LtYOxjRRf5IZVuWkiY7Yv95hin0Zcrf2rvFvRWSo7B5aT/z1CpRTH3vl2Iwhgl+sfskjd0oqkbQKlUBieaiUa6Tk/MgXPHd6d77GSQmTRL0wXHw88QOGuSH4Dh5Kc+oQ3QAdzQdg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560553; c=relaxed/simple; bh=/AfvPG5wDSljrifmPSVv83+zocjSPM7Rk8tuaUgB0kU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OpbDAjeSSfb7Ezn8GHSm7uymnCeqlyN+hhwO9vSmuXNi8uYCNsBW5ouoboOtYwtHvY1nTE/bWZjYITaqmEfQSK5w3x/xNE+I5bk3DbZUqYsunp8S5i8c7K8U1fTr+6i2nQqgld/XxllHKAtggX57DhWvu1/qVgXB3wgl+oUFygs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UDQ6HWSD; 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="UDQ6HWSD" Received: by smtp.kernel.org (Postfix) with ESMTPS id 81465C2BCB3; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560553; bh=/AfvPG5wDSljrifmPSVv83+zocjSPM7Rk8tuaUgB0kU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=UDQ6HWSDKW14O93sYVnoIM1ZyFdfZaT6T7ER+P9zMGJ3gth9IalZNQTNfwbM8pVCg vihJrvDPhWBXnkKqkZ63J1h+5QIV8u2uaB+K6fGzHh/BwpIV6whsrzJ4xxwXAmxU36 o8aiuO0gZA6NWSke56OzqOKKWeIk55wtAIGUNFXBuI1DuBnhrcHuzGf0n8E+0s4b+Y AoQNKt1vcovogMrvhKcJnmb6bVepyHlimN/ZUh436fYny8umyG3yG9i/1vT5J2tKfs jI3Zt53Fh720aqegCDHf8xrly9NxfZXnXqk5Ry2aicIPXJmp1iqe0UpIZFAnBsI9fF 0pSR6054JSvKQ== 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 61325C5B572; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:41 +0800 Subject: [PATCH v2 01/17] 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: <20260813-swap-thp-cleanup-v2-1-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=1345; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=HKVUTdGN+FJkTgGM5Te/fnEGz8LN/83nu6D2nUyiBUc=; b=7ITNUdvPj/gYV3ooz4SLYeqrRp+BFlq3B9+0PvGPYQGmXnsYu3j6JsKN+8l16AyavYqqFLtQ6 2djwBUvEgDuAIk0Z559FssC7mWmr/jv12RAyq/+Qte+tl3Wy1uEtcU6 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 --- 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 5be825911e64..f1405e5b813e 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -388,8 +388,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 Tue Sep 29 04:12:16 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 D8B112FFF8D for ; Wed, 12 Aug 2026 18:49:13 +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=1786560553; cv=none; b=t6kUT6q+0JweK6MurDhciwCBTT3mQ6P0NPBe81xNWaIE1b0bB12E8r163xufa9sYhPQkcfkPZFuARoiDwbVgYlI8w5vnLB+nAMri20xAgMJ/Qc79oEx2q2PB7A8He0flVPRPHeJa5UhnAmHWcKIp0t1Lei56Gjor4KCYTAxADP0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560553; c=relaxed/simple; bh=JRL5pM86B8RFgADsANhqeFbHfvQl3wS3hJzH3CirW5Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YgQ4B8siahqXpIExuwPWUWvw7m2YajkwGcws6LdVvOOoX6ANEriZHCuNPvSAPy+Gz6VrvbNdJtYJtmw89pNt+sEeZdR1v2fS8vn/qF4MN+XfQzD9lcHfj6YtoPVKySpxlkhOq/aQsd+yBxKbXwfSJKnBdnLN9F2Fl8DY+lxch6s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Jx7AR9bR; 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="Jx7AR9bR" Received: by smtp.kernel.org (Postfix) with ESMTPS id 91B38C2BCF4; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560553; bh=JRL5pM86B8RFgADsANhqeFbHfvQl3wS3hJzH3CirW5Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Jx7AR9bRcjmrZfLaQWtd8fe5PEmSdMdcboi+T4J8jkJiSwMgJ6RDofNSmXo2wf5jn gbiVCgKRXHCijIIJjgYmgIy8/pi1Y2ccVlWRmFuhrCj0nxozHhmNPM5gjd5S2X9QCM xJwlqPFUUHYMP6k+INE0kugXhfpC2q4zRsxFzDkoT5qy5dtwQBHVrO9Rl7UnKcmtz4 72LsYj2mELCumyWyc8T5mQVHE05VBPs9xM+6hVbSXS1poN/JP/J2M2Hok5IcWjl9yR semk8viKUdlkFJtSKOuBLZCmLTqo1aD7BOid1HdGvaER4Dqi+A8/5uRioChfnW8H1x aEAVRuO2EMMpw== 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 72E24C5B56A; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:42 +0800 Subject: [PATCH v2 02/17] 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: <20260813-swap-thp-cleanup-v2-2-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=3618; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=e13wjW133ljVhlDYICXRiHfXbLfq+7vviv5uJlt7V3Q=; b=xVp6uYRp7/HG2Xn+3DreYkz2asTtCCNkel+zPY2gP9WehszGGj+6N0a40H7BQSS7YYhkDx00f Oy19B4zWzafATgehWF49nPpx0JRspUnTs8Fgq8+dxxcLk+PlNwdbWAF 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") Signed-off-by: Kairui Song Reviewed-by: Zi Yan --- 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 Tue Sep 29 04:12:16 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 D89962EACF9 for ; Wed, 12 Aug 2026 18:49:13 +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=1786560553; cv=none; b=Xw7vtqDj9gW+m5NDE73b4ADyhf3QsV/cxzNcg+hujireQF2K+xrOkRi+kCoOAwL7x0wtWvq104fItaJgKRuWFm60tQ86BsUNu9ys6ssOq6LXmjootvoTVojLZcZvPcuY8LN8LDNMaBO3Kox5yiLpE+gaAjYeNBqtOCOfWYJmLm0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560553; 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=T2Y1aH2yzbDjCWDWb+9o2bcW9LNuELszu3oeURwsWZuaT9eTWfwlFcYBuJ1urTA4Vf1flwHht5bn5akUwbaC3B/jH34G9QmWQ/tJ2YSUaVopmhzVWrIv2bZDmIJ2ZQoPFqWYyisUZA8OR1UAco8q+YDfooDMsTI3tS5BNPTPCMY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qZhXbbpJ; 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="qZhXbbpJ" Received: by smtp.kernel.org (Postfix) with ESMTPS id A13E8C2BCFB; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560553; bh=+Fhq/ThhPdJvanb/xrY423riYXh79oib+Ae4a1g8tWE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=qZhXbbpJdi+4pk+4BJjwdcmhZfdJrvIGqOOoAaFCoRhHskAweRtS1udSS8cFqG51C 7GJuY0VU2uey82sQqP/gDzXycQjph7V0hZ1Mulr93m0QzEmcE6Yau8JLXNKKXiu2me 2a/zHuauUqYap4dJvo1o6j4UgTwKupdvl7Hcav4zHhFLxHnswkOWILsQA3WARwmFp2 QA8weqUwhlhNGoHWFjbhikvCsTxfzEojI8xk1k5ObbjoMPzJsbl9ChDQcn2ZwoKstD m4Y4wnI/PL9vpj6+I6d40uVTfSCeYaJJfSEMrhT4HDy9lTA5Wq93qkvIoOdWLY9cdW pT9AFOtFlozvg== 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 85CA2C5CFEE; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:43 +0800 Subject: [PATCH v2 03/17] 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: <20260813-swap-thp-cleanup-v2-3-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=7863; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=UY6iMKTpGLPfiYtzBDed5IoafUyCePQg/1v3UphPlKE=; b=k4IG78nRBmlhKeBfg0Wx4nDDWhC9Vtr8PHRcslUHVjITGXD266Y9FUK35fUyhPfN8FIPI72QP 5iC6XdY49TSC5yoOcDQrHPKCMhVO6EHxgosecP0zC0sUd+wvOep2FvC 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 --- 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 Tue Sep 29 04:12:16 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 EF353305695 for ; Wed, 12 Aug 2026 18:49:13 +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=1786560554; cv=none; b=WG7NoDiFgLQh7iS2wi6seWV3pZSNtRdRXQ8XMx9WD/cmqCXs2Tiu7UOB6oPG7ih/jdd6mWMS/mz3Yx26m/IT8evsgNoO+ysluIOqjSzohPFmPSs9HYkw9QX0ZvLZw75reN94cNtNexQ1ag5i1vVxMySBM5QjSLL+hOneCgpJpS4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=MlidP5oYz6rZc2n0ey9JStoocVc51758tOV6HEpbwWM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LCbO7BUP5speHupq67j6bhsWCbicV+5rbFfgG9x0IF3CcCDC9ACnjCNJ8Qbfb12nWDEwmbfh+PlaoV2XBSN+vi1BNyAV3uUY3DnvbKpQB4wwccpfg1hLZGIGk03sVOtQlyyKotVdptxLuDAdI16jzZbnS+HS7Mh02RTVC36O8BQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RFI/CNwI; 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="RFI/CNwI" Received: by smtp.kernel.org (Postfix) with ESMTPS id C4A9DC2BCFA; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560553; bh=MlidP5oYz6rZc2n0ey9JStoocVc51758tOV6HEpbwWM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=RFI/CNwIFnWf8edIDiPMpCmhXortSgm1OvJa13wRhb1k2M9ZMhczZX1zTcmgIXHlk 6A62afeVfk/8X7mVQGe+zfxmQD+t935PNh8W2u6pbQsNorXzQTRzBe9rlsandHP33T RGPZLmW3PqNxLXV6F90M6fnRsJZaoUmc1pqvmJ1CG+LNibxLzc2VgTxwGPUXyd1oKU j9TZmIQbg4TdFXWTC3GL+M8gxhv4a66uOfnZMIlougv+7jx0uAnQvpxfgcDurP7gji lkO6PL7Kzf+Dov2sP+g3EZsWvV3sSIqxRZ6XYyWOwe2nGqA6OvRWq+b7GRHiOhjzr7 q0UflcaGFy4QA== 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 B2A10C5B572; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:44 +0800 Subject: [PATCH v2 04/17] 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: <20260813-swap-thp-cleanup-v2-4-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=8891; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=u/PY3rA59I05qsJFQoxSfswRpt4QGmWJXn/YBJ2ly+E=; b=UyS+Ybcre9RJQTyAqQjSqfHwqYAvv4gnR792SypgViHDof+y9eE9m3XOtx0gAXQS85+nRFqdL xVBFl+WEPXuBoejnyg+lqyZHq8VJeM3/Zg61bzwUwcxyMie4aQ36dAR 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 --- mm/huge_memory.c | 133 +++++++++++++++++++++++++++++++++++----------------= ---- 1 file changed, 85 insertions(+), 48 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 7fb603ac500f..7587eeb09e4a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3634,6 +3634,18 @@ static bool page_range_has_hwpoisoned(struct page *p= age, long nr_pages) return false; } =20 +/** + * for_each_folio_safe - iterate over contiguous folios safe against folio= free + * @start: the first folio to iterate + * @end: sentinel, folio_next() of the last folio to iterate + * @sub_folio: struct folio * to use as the loop cursor + * @next: struct folio * used as temporary storage + */ +#define for_each_folio_safe(start, end, sub_folio, next) \ + for (sub_folio =3D (start), next =3D folio_next(sub_folio); \ + sub_folio !=3D (end); \ + sub_folio =3D next, next =3D folio_next(next)) + /* * It splits @folio into @new_order folios and copies the @folio metadata = to * all the resulting folios. @@ -3933,11 +3945,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 +3958,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 +3965,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 +3995,70 @@ 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_each_folio_safe(folio_next(folio), end_folio, new_folio, next) { + 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,39 +4068,21 @@ static int __folio_freeze_and_split_unmapped(struct= folio *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 * @folio. */ - for (new_folio =3D folio_next(folio); new_folio !=3D end_folio; - new_folio =3D next) { + for_each_folio_safe(folio_next(folio), end_folio, new_folio, next) { unsigned long nr_pages =3D folio_nr_pages(new_folio); =20 - 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); =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 +4101,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 +4111,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 +4264,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 +4371,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 Tue Sep 29 04:12:16 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 14B3D3254BD for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=O/nNYJWX6f4CJiEnnyvhtsx09sISOL/LYbgKh+yUcDbDfWHz44EJvFna6g7B3vLC+FnpTQdr5pSKUK1wflmrx82NvWtdnCNp5IS9NUi6AIvYKb+4RWLQHIkdlT/KMtdVMpdqmpL4W2IOwJpZBmAvxbtMXHO2OqYA0oKbVfd4fzs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=xDAXyFedhHqx+fkH4wboKUAlsd2gNOQbse2PN3z3vw8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=W6fw/+Jd5eBn58hWA4W9Rw2KjisArPug3ju4/GFKZZIH+09d+lkSLV5KLJKePunHGQAN4dFU7BVY0pN/21osq1+HIhnv3gKv/8TzVlWm9x2MmIWPIC8PXWey2G8S+DBk7QQqDSu4XtZUfTe5248eOIqaYCx3GSWWwKCy68ENXMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lhdCkf5U; 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="lhdCkf5U" Received: by smtp.kernel.org (Postfix) with ESMTPS id D66E9C2BCFC; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560553; bh=xDAXyFedhHqx+fkH4wboKUAlsd2gNOQbse2PN3z3vw8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=lhdCkf5UZJIewylJAEdVc9UdgindTSn+4hKUJd/GvF3O9HVTfIoTcsYskFR7O4Kyu FozSCimR+RCfQT9AKS0E5sQhqus6Ya36nS5ZhMy9g68FdqqPFW/QEJo1BQ+IwLyS0B oScGhinhbUCbcrY++s20hGiuI6QbfY5+8dBDUH2QOJEkV9gUyJnRL6WjngO2qSy2c1 BF2OQ0u30mXNp5dlKo0GFDZlnqEq7gPDFRUklV+w77cao7S7k7JlJ6rStlMXhZmw5s epKQ4SsvpivCgXD1bpjz1hw0qhvcktM7stfBQrLSuUPCLJMMWNb92IR7h5idO70SxE M1n4mHcCWPYPw== 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 C25BDC5CFEB; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:45 +0800 Subject: [PATCH v2 05/17] 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: <20260813-swap-thp-cleanup-v2-5-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=3653; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=4JjolaupwqTSBLBL65mRa9wmeq9w6In5IrkOzFf5Yfo=; b=PHakkmQPHqY39DyzfM8bL3N0JcH49hAnhiemotbeD4OEWgIRduaoR19O8xiqfC1GegF8t58WA V373ObQRPxvC2AazrS50uoRBCj2zFpBrAYxFJeJRNzvTQ0Rm2jNeR7S 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 Signed-off-by: Kairui Song Reviewed-by: Zi Yan --- 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 7587eeb09e4a..dfecb93dd64f 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3767,8 +3767,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 @@ -3807,7 +3807,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) { @@ -4001,8 +4001,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 @@ -4063,8 +4063,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 @@ -4124,9 +4124,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: @@ -4229,7 +4229,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 Tue Sep 29 04:12:16 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 3584D3002B9 for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=ZZZxZAazZZPgc+y9Q4f6Wap87wKr+d03fdsO/cIyrQ61KdwOx3wbf/UiZ6cUcK2I4NfgBUW/IizhXwS0lhHW8HDNRNUCe/tZEB7RY47QlMa93IM/lgYZ3uXDfysxW0mc/rw4L9bien4sMZ0laeT5OtA/BY2UPZ/h0T0R4/XaIHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=OnHSKfnQxoycgFQgDUmNgpdMiqrLFZGFqsr5+cGdiJ8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TfsfcaVdu0W7+QfgX2yCLNoMd3v4K2qvTGIxzgQxmu7QSFYPA5c6v5xP4RfrWXMYCHdSqDr3J+YIlzPNuUYl/ZNe/NPwnWLihtoovXkrEgx8KmxNb+r8LXwiQpC6lXdqAtxZ3e+t42yXiNO4mswDGybSQVYbGhe+Z1SRDSFJl9I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cwDHP1bz; 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="cwDHP1bz" Received: by smtp.kernel.org (Postfix) with ESMTPS id E8864C2BCFF; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=OnHSKfnQxoycgFQgDUmNgpdMiqrLFZGFqsr5+cGdiJ8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=cwDHP1bzrl8a8i+K48g3YNVaP+8J/xaB0kG8/+ZgF5QW57aLyF9qpXoDQAdgGh4j4 8dyd4JK6kaCAK677OaaDrzqPhX1jaIEP426Of+fv4tHs8b6xE/LYFckP7Cwh5wZv30 b+tCMZyI6MNkbPAyWdH4bBbN/0i0qcv6kG8nBZ/6FJSTh2S+gLc0xk76tIPDti+4lo TRbVTVoILau7Glj9HIXHd7LT/iyeh2DG9u7Ws9bKfaqxylMtCLxdBJnA6o7SAFb6Cy 9wfaU55p0Tb6YHliLZnwM9d4C5wIc6ECe/morO6yhi4aA0Ngb0KzheVFl+iYUCXC1q dBlWG+T8pGjOw== 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 D32D0C5B56A; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:46 +0800 Subject: [PATCH v2 06/17] 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: <20260813-swap-thp-cleanup-v2-6-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=4783; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=i75VWCkQ8jK7NZAq0hH8d0si3JwG/+ahq4sLsBZtBsY=; b=YuXMwQdPjrVH7JhAsFv1+GMWhTDNt4GrjxOpz/CbWpY988UPpf/8oMJOsueu/u2QCWRxC7cMz rt1jsToN6BEB5bcR3qmcv1GzRJD+8v4jTXXnCXoUwhlStZkGHo/vOgq 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. Signed-off-by: Kairui Song Reviewed-by: Zi Yan --- 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 dfecb93dd64f..2cd53afac63e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3958,6 +3958,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 @@ -3980,6 +3982,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 @@ -4028,6 +4031,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; } @@ -4043,8 +4047,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) { @@ -4112,6 +4129,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 @@ -4251,19 +4270,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); @@ -4272,12 +4279,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 @@ -4360,8 +4361,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); @@ -4370,11 +4369,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 Tue Sep 29 04:12:16 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 2D1C73290B0 for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=J8LtV+ZMbijRASUDnPQquInVI4WMDouzjilrj6eA6GcaxgG/ueszVhbjpKocu23ZCfDTlHyz8i7Jguvl7RU/R+To9OCyDmoh1Ze6+RWAHaUtL9bu4OUx8CvDrC5EOhH71p1tMtHRFB99vjxMTyH1+tHMIZ3Jd1vMbAWDzmleT58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=tz1pq0t1A51RvfmwONATJHgMHYxmESpNAK86660fq0I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tHRJhHqv7TzNqaIgsJJ/1/hdknZJQkXV0m+vj759hkEj1vaGlSCpgaSN5Wnc8Ljgu3W9ucbeXXf/B4jhLezUNmMhMy+Iyn5G5ZU9KDtqImnw9LueCz9a3A3T295YnblDAZ4u7sd6/Zg7VICTbcZINeavtsWFf6SIXDj0cruPyEs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tfXw7+Kr; 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="tfXw7+Kr" Received: by smtp.kernel.org (Postfix) with ESMTPS id 05549C2BCB3; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=tz1pq0t1A51RvfmwONATJHgMHYxmESpNAK86660fq0I=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=tfXw7+Kr9w2j+mHb33UODxwbxLvec/talBZXxND112xG1Nn7auZ0ioEjATtOHoj3s nxXBk1rqlIRpbgWkew0JkccFGGFz3vyBn62S3dIyh68qy4kkyAVTEaGBUFHDTIgAfJ Y/wATlUJ7PpjmqJEP00o20dTtO88UBqH+cWSyn6CnULMjsRrmZUhE6pzpyt/0p10zS 074fK8A0GhcWPG2WLMTwhN5FJEZAWHjPkxt5yeHi+eYzTc+FvmYx9Q7vTyNXMf1dq9 12Dku5xUjX6a2/DaQo+CQJnY91+8Nc0xToyDSJLiKKwq9HJqYeMTY8SnmqjI1+48J5 /FJJA2/TBFo/g== 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 E4A04C5AD5A; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:47 +0800 Subject: [PATCH v2 07/17] 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: <20260813-swap-thp-cleanup-v2-7-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=4165; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=zbz5fZUbRD1Px3Iw/cdSC2QmjwPbOSiKdK5oTzkxXmg=; b=Y9xtbZnrbsxp2ImoeO86xo/a+HOaqWOqCfBhkc9UG5YII1EUfFlTPgbGfRYjXvBDxwHNL5zR/ zkj1MRyflQoBzwx/NR0G8d58RSTAmCPXgnT6WN+WapyDx4F5vTM+4u3 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 --- 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 2cd53afac63e..43093b9a5bca 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4039,14 +4039,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 /* @@ -4107,10 +4119,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)); @@ -4131,6 +4142,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 @@ -4167,9 +4180,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); @@ -4246,17 +4257,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 /* @@ -4272,16 +4272,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 Tue Sep 29 04:12:16 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 4B26E33065D for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=o1/F87RMaK2odkRRvf5TisyKsx0kPsjOCYcF5pq85p8kCTvexvihUwIFGx+WRKazrNOvRCOl3dbgrtnEnGPdy14PGBs7k/Q7WgyITVDvlStaI2TZXedYjrRtRZnVHH7qEijlnmwYXqd05X/cQohyweQMpqDjB63l5a/0W8D30eA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=13c9mdJfe6/pTFRb8RTKL8PVg3Isrl6dA7icVDAFEf0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WhmtKCrRj+ixIqF6nXvfDEE3Dm7vP3d+qziPG4gez4hg6J+ei1J/WQWxDo7lClKhxQn8gUCC8BrEJgXPMgQFS/N8DyfFcsstlg1vmyhlt0I1ENHYClUEv+2vppu/NCcz/pqwVK36zmu3xLHI0AiCPY2Nsi50wVloADCH1Ynrics= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U4e0tfFY; 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="U4e0tfFY" Received: by smtp.kernel.org (Postfix) with ESMTPS id 12637C2BCF7; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=13c9mdJfe6/pTFRb8RTKL8PVg3Isrl6dA7icVDAFEf0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=U4e0tfFYoxdCuOspk2h3yyUZovB1vgdDQgTSW+nZhAujmuLMn++PCHC1w35xme3sA GjkMXrRxgrU+Q/lEnvEHLOYKop32+LZs5sUJvwBrEsLdzw40ks5Um7wTbxbczxuouv OZX6bEQ9ciKG/PU58+l7SNv4k7Svbcgbs+Yl4J99cGl1y7UGwBwGIPjhvj1L1sR6gr 8jWWDzydoFB/UUUJ7fW0Zq5826h4S0KsR68h8xahAM/PpDPuZLDpEYbgts+/UMKMjU kkAN+Qrxl/3wiAkbsuJL3JiwbbyKyOSsACrZt5fhmAnXVRbSpYEyh+fkHdqs1xqCGr qCUBKpxlHV4rQ== 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 F3FA7C5DF61; Wed, 12 Aug 2026 18:49:13 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:48 +0800 Subject: [PATCH v2 08/17] 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: <20260813-swap-thp-cleanup-v2-8-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=5602; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=JtWm25Dng3Mhqkcbs3f3Xwf56RRf8KwYB3EpO59ZokM=; b=INsZYrdAKljYMMdiEFr1eEUKBxnFmja12VRs97CQi/tVlEjpCg2GFaxG0LDMQC+l32JNFp5Tt GQVahCVb+KaAYlEBqvcMDK1kOB45i/Jiz2dtSIGig14Y92NW0hvM+zr 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 --- 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 43093b9a5bca..aa10a13bc255 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); @@ -3945,19 +3942,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 /* @@ -3982,8 +3983,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) { @@ -4031,15 +4032,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; @@ -4059,6 +4066,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 /* @@ -4139,8 +4148,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); @@ -4180,7 +4192,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); @@ -4268,21 +4279,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 @@ -4365,8 +4369,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 Tue Sep 29 04:12:16 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 3F92632B13A for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=CJF2T2rWeGyWA6dMc0J2DUq9DXdhNHfigLdWwWCgiIZ8N/JpQ+S6HxSQXY7euR9ZJiuz9ZvE52fnQjXIJcKo/gW4rERWiPob0ZB4yzzB/BkwmSOjJPEsXh8EjHwFISKdR2j/FrAnl9YYhQKCMQkmz2XKO83vYDvwo+XOowoZI6k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=yTjGUsr5g9OFnQ9yDghu9h7RK/P5ptVFPG2sEI+z3Wc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=S34iAOqCvadFEucVAtZSIYX8raJzDiSFdcxNIy37R+xyNABfPL+/mMohAY7adsly/zSjJuBaOVyUG2S5+C/gfp9e+zyTSvrIs6ZFQsLmUXHxufS4rXBlbPMnIsjKSsY9H2+BvUATfVEZjP3ADnTzGo4NC/5FropdCP2ewacwHs8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=n3h7g2Af; 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="n3h7g2Af" Received: by smtp.kernel.org (Postfix) with ESMTPS id 21FEAC2BCFA; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=yTjGUsr5g9OFnQ9yDghu9h7RK/P5ptVFPG2sEI+z3Wc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=n3h7g2AfQuTxSC4Ia/kxUh00TA9G0YnK4xIXM/qtin9N9l60cduWHdo7RFY7blv8P Xv5/LFLfTMQvmaW6jIvsGsSzJJazqTdDebXvlqvU3wgyIE+jHLP4GAn9YGvvpHW0oq EcIM6ijAMk0fjIojGgF8tBsKzYrjFilQoUJRRUpO3rLAoVXj2lASgH8W11FCNrl0/m 5Q2kSD04z+uMeOTl0NEbOMz+oPovuSxYGVG86iC98NdBisxez+HX8TlId8SqWRTAi4 EO/yehZrTeNoUJW3kv2y3Rt0sutbgIg9IVKVBllUG7Kx025RcLaM19d8PWTfyWJlyZ wfkWVm+DU2DGQ== 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 0E8B7C5B572; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:49 +0800 Subject: [PATCH v2 09/17] 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: <20260813-swap-thp-cleanup-v2-9-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=9165; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=0NuWyqJHUx62udm2N5rM+d4jHQFwYvmMac4Toewk69E=; b=tJ0I1Q33J8AEg43ux4k8RgZxRXS8g10JnOs+kJKgDx6SFAfK3Zc36qSUwGRhajCOOff7oi/0x 0+6N0bw6jAJARacIH/W4jtsAGYntEogbb6PQq6OAAouJalpeAcmDaET 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 --- 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 aa10a13bc255..1a3ca2606c60 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3950,12 +3950,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 @@ -4039,21 +4060,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 @@ -4068,13 +4126,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; } @@ -4101,7 +4159,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 /* @@ -4153,9 +4211,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 @@ -4184,12 +4252,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; @@ -4220,84 +4285,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 @@ -4318,19 +4311,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); @@ -4366,9 +4350,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 Tue Sep 29 04:12:16 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 51E9C330D43 for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=LXFrOij3LXuspQ0AOLUmZlVAm1t9A5plR0TbTT31cNUiwK3THmIjYpLJoOPqxl8zN1WMg/GLjYHke58k88OH5/snwOymIJHnowq/IwamZRH0kUWq8aHCjXpFb3nU+IHzC7l/0paRLMsOQl1sPspXBb6+iRrjdv1K+OstQd8UuoM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=gUgU7p9/XKgxy5w5HwlPQPYR7Sjykv+trHbewH8ttzs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sSHfkPckk/ZO/aYxqfORfbnXFuq99bXN7jXlOQA5A8LxVyqSL9gZ3Ul8ANs5UFCeRds1oBkbdTNxUTXl1WpAShQ9Q1rQITAxyFjbFcxELgAFd10Dg/DCQ+RUukrF117Pyyy93TCDT9E/NkTgsyk6631QpDtdnBTZlYwRzU05E1M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=F2cecEpr; 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="F2cecEpr" Received: by smtp.kernel.org (Postfix) with ESMTPS id 32B71C2BD05; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=gUgU7p9/XKgxy5w5HwlPQPYR7Sjykv+trHbewH8ttzs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=F2cecEpr782HCcD6qVCIWuvQGOIlXiHqGX7ZW1yPnjnJkno/N+Q5WzUonAEhXWY56 PnogP1qLMFj5GNcih+/V/cQwpuAQjDF8ppL6fhBhz6w9aCFNLT5NEOVmQXZc/1TusN IwXoLaaf9fyvoLQavdk4ERVydOhcuwoIUFSAEoBscwRSi+bM3Q+4inwEQQsNLtGYwa yQoC7A9bUDc3Lc81X2yaVbp17ymJaCspBi0nb1hf99vB8RDuuTjrdRV0id+Bl0azQG NmorKlGZ/FT+kyFnutAgAirXuyI5Lo5iCEfxgY+4nyZs0Ojr+S8ckmhK++XhElQVv9 0v4uG/E+mqwKQ== 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 1FF96C5B56A; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:50 +0800 Subject: [PATCH v2 10/17] 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: <20260813-swap-thp-cleanup-v2-10-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560550; l=3647; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=AzBipzrIrYUu4ErVD0k6sxdH5I4rv7p4DfaxH4DeNi0=; b=jes9fwJxP9M4s7VNl5IMSEwvhWGCAngoxTYzw2AMWzpE4sUG2+1FV5Cz21XD+FqLpHDzkFdNb bz7yQ7uAQ/EADuXC8AGATRok3JFPaGDoa5WuCjIQVCUevuKr1mCw9WC 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 --- 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 1a3ca2606c60..29b46f039d1e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4076,6 +4076,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; @@ -4088,9 +4089,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 @@ -4223,6 +4233,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; } @@ -4254,7 +4267,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; @@ -4264,27 +4276,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); @@ -4311,10 +4316,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 Tue Sep 29 04:12:16 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 61ED2331203 for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=FcC1LlGiw0ibDjqQM/UNDHn2LMHw3tLPDBJPMfAPkLEqsZcoe5FRNdWNAqZKERnnv2o5/J7bJ3xfhF7V/DGvJcQkt6MY13y15nEt6JBOQ5Tx1sFOAHsw5db4PaDoZt96od61YYjFg/xY4IBZPxWFJ5cMmL/ORLZbKz7yRyxAevQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=L74y7kL9EMwS3z+yBXbz518h0GbrhqCoFh1CzcoW5W0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=smTh9gWU9lEaTh5PN8xxx4bYyZN1tI4UKlMeFPAh+9mOVkBkuSZ+Q7x/1f4WLDTg/XQ/upTMFqiyrIiSg/2jVsE78t7cYWRKpUMydvr0027j2F5ArzUU/ST4VvDxgXpdl0KWVoOuUsSjnGeALAbHnGUfB1aDMBg6/DUQjqqOtcg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=icfpxg/z; 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="icfpxg/z" Received: by smtp.kernel.org (Postfix) with ESMTPS id 447DFC2BD00; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=L74y7kL9EMwS3z+yBXbz518h0GbrhqCoFh1CzcoW5W0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=icfpxg/zHzxaLIOzErszHAkzeNLs2kFmrTZAm85i2i78P/k7jIsol/uWMMuDwszlH FztzB+5iO+6bCVOpaOo+VJI1F8+IRLQtwF5xepJ79MqQ+M/iwY1eGt8RU1G+BP7Ei/ 8qZncgoNs+8Bl7JghVwQyjzHquuK62Jaa6yCiY2bmbnVFX5kKUuaAJuZx9dJjd02tx 4vEAGlfn4OSE8h/1LgGzUbbK7WAfeFuLAaWVZc0epz5vJrxN4HcOPcwxmdtk5ScLAY y5IJy+iF/vQS4mExa3iy0LJOdEYSod4c9GeHiWzgttKlKROicMHQ7wIdEKasGPNioo 2LiRU9crZ6a5w== 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 30714C5CFEB; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:51 +0800 Subject: [PATCH v2 11/17] 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: <20260813-swap-thp-cleanup-v2-11-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=5578; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=axzIDmGBd7lK34RIiiCkCmxGB/OY8kzRuNR2iFyLEgA=; b=VVfsDpjhS3AuyTbgJ0R3IWwvcbxW474xxgRHBGP/ufz+aIPrjhmq1f0/CY7W8J4qxugU0Nlt8 iPMsmlMN09zDy48pXfrnTWeWKR9e3BjuYT3OB0USmlvBZznCJwl0hmc 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 --- mm/huge_memory.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 29b46f039d1e..67401c58794e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3893,12 +3893,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. */ @@ -3942,11 +3940,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); @@ -3964,7 +3963,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; @@ -3977,7 +3976,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(); @@ -3988,8 +3987,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 @@ -4055,13 +4057,13 @@ static int __folio_split_unmap_and_freeze_anon(stru= ct folio *folio, unsigned int swap_cluster_unlock(ci); out_no_split: local_irq_enable(); - if (unmap) { + if (anon_unmap) { if (!ret && !folio_is_device_private(folio)) ttu_flags =3D TTU_USE_SHARED_ZEROPAGE; remap_page(folio, 1 << old_order, ttu_flags); } out_unlock: - if (anon_vma) { + if (anon_unmap) { anon_vma_unlock_write(anon_vma); put_anon_vma(anon_vma); } @@ -4265,6 +4267,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); @@ -4291,8 +4294,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); @@ -4352,8 +4358,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 Tue Sep 29 04:12:16 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 7442F33260B for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=eRM9O9DWACogAJDkRDnFaTCdiwnY87wtK0+o05p4rg/kWNoTNaxArcGU2gVDjAfEkQ2un/q/MQKYKm8+xaK1Pnwh3OyiGF553fuvrrG58PrvS/bFb9D7EtVukqvK6+xJm6mJOCVuFpM4gXM9d/+ipwNdvEMGYINk4/dOkgAdJ+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=JjjM3fg/aKGNITezeeJDvpfDoSmgq9K7Z/M4kmelVPk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nh2UiR9cjnm0lzKG3Ho9fy0PPe/X9N4ZyCa+t41WN7XETtTUiAATaOyTswvvZUO5wvG4fAlZ+tVUZgJEfc4VqlcrZ8Nl7unePh0Mwk7j9SEP4DaQsvocP+3XnVdDNQMC0WqCE5alKPY/OH1kPeQmkGyTiIkFaAZUwHJa4giRO7M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XX++aMIl; 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="XX++aMIl" Received: by smtp.kernel.org (Postfix) with ESMTPS id 546A7C2BCFC; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=JjjM3fg/aKGNITezeeJDvpfDoSmgq9K7Z/M4kmelVPk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=XX++aMIlyOmBPDiJyfbgHiq6BlW35+DEk4VJ3UVoulkP1DoK1s+C2+4ZuCYcWZtRg qcWm5QJYHy/5pKSy5SYAEItzituZFu5LOBIA6RNUEuwFNTApTYdWbUyX1+m2GfOgj+ LHour2X6givacGgWcB84JVWvIwS7BA5HTUQOcpVkXjXBLwLhDjjC89apEqUv6R27oy Dx5RvVZvjJUPRXgOY6tFZhFdPPckkOk9lanu6NnhlphX2oIbYOTMov3TH10/k94WxU DPYpNoOL6cEBvOvMvjDEv8w1ycTUstFjECbbtcaw3jKQmqzjLwNSWK4ux/UG4fPqhn YRFovH5HQjFSg== 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 40D93C5AD5A; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:52 +0800 Subject: [PATCH v2 12/17] 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: <20260813-swap-thp-cleanup-v2-12-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=3229; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=FhlwSOL3jcwUQT81uAoRstqIjxLtbsRoy84jVVwb1Vc=; b=9jyBJipVjAGpUZjWUk1tYRg5xbw9l3BNI+o4v5c9PQ7PpRl4b2c6SBlstfbKoKiwSvPd2Lxzp +eozp7aNoM3Cn76fqlLlIaMnPq7V2gmCAQso2WQcCGpCWjWaDO8KuPB 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 --- mm/huge_memory.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 67401c58794e..ce02608b37f4 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3940,6 +3940,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) @@ -4071,6 +4090,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 Tue Sep 29 04:12:16 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 7F4C1332623 for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=ZYu3GSp90hauAoYnAf2B/4kpWVedepZqb02/PKxGt7xhK3P+tRU5V5Sygn48aTgJJG9yeglpJz9xRKdz2C9s7y+5+a1vSyboE6y5JunjN3xyyh8PjtfhRjFRRQEb+WhavqnW1SlFXh0oXXF+z6J1c/gBUPjbGCR5jBXJyIj+vt0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=QbSz+YQQTZ6xFRlXg9OLDeF2jL1LpsveeyExaTayi8M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nIdi8TSe+iedtzS4xuzDqf8Bn5NEyiIZ/as7sP78L+0+Db6p0vuxL/qYLl7zI8/DsAayLek1aJHimKULRRLCMaheOrTbQLa4x55R3ey0AzXaCQm0rQJRAIbOqzh/h3f+4kt1nc/iXcnDSw3iYHfWJWVGAmduEOCfBwC3+Ad2u/o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m50VsuX2; 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="m50VsuX2" Received: by smtp.kernel.org (Postfix) with ESMTPS id 63782C2BCB3; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=QbSz+YQQTZ6xFRlXg9OLDeF2jL1LpsveeyExaTayi8M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=m50VsuX2K2+BX0I4HvRVq+4MGTgtmUFgXpq2HjeojGqPviH3bwowMTQL9j/cZp9si 5VIG/SoFHfzERUSTP+TLSwIYMLi7YmUmoRfkUoHEzS3xCVyHa5Ai4m1avYHViZrY41 mEFOIIYpRRsDidBPO4KM+RGrxSWdlQ8Of3oLQUWE/v2Ac+ggRHMXwDdvlbxyQeSDwd IMTpTOsOxlzKJRSCyRPdG7xf8+kWNvTeYZGVA1FkpzcUrlgeB5sMmRvie2jLRhMFAu OFEUe+HfbsPXFNS2UyY/QrxVQg8yNR9LZLL7V83uQ48THuxgxy8O+5jcRTc5F+h4y8 3Mbfw4vbCOObA== 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 50E8FC5B572; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:53 +0800 Subject: [PATCH v2 13/17] 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: <20260813-swap-thp-cleanup-v2-13-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=3118; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=flVoHm9M5zKLwjUGNriGa0pMoxT0o6QzUJyZyEIqxUE=; b=7DHyK/rZjLlMvKwFURyay/2aB1cvnHprN4cS2TRJ0VbuKTx3rnETMs6xNKZNVSwG7/cUwtAo+ nFEEiTDxTajDsVPW9H95QIQFjwo4VnWNJEkdNJQRdrnRAMEo+g1QN38 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 --- 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 ce02608b37f4..72e7d24139e6 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4097,8 +4097,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) * @@ -4110,8 +4108,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); @@ -4206,9 +4204,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 @@ -4226,8 +4222,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) { @@ -4253,9 +4248,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, @@ -4339,7 +4332,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 Tue Sep 29 04:12:16 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 91219332EBB for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=t1fX+JCSwnHOjcxvMEM6L7fATpSR5zFRcohyvMC+t3BKC6QZVUhCpX9lWgORXY2ibjia4EshEFZjp28ClT+pu/QwvVH4GOJdTeg8FFfK7NxcziJxQ83lrkNPAy+Y9Nf6pcKGtklVumSunegriL6p0ztxXnYRkxuldx2GVozfZLY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=VQ4ZoNoJZMPRFqoDbLthhcmmTCF8yiPpVD3DVjYnoC8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Bwd6qTOrirabyu776p4lhki4dUiarsUMuI4OyY+8O51IbB9gr0crSHeFRenzwRp3Zw5NbSUY+WJsFKmjn7L7fwV11vNnFGOf+j47BOB33ND+4TaxT3Jb4fsou12Tf5MjulPyGiD/zKTyJ4+3kOeFluXaVF+8kKykhj5TFo55L4M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uSQ8efAd; 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="uSQ8efAd" Received: by smtp.kernel.org (Postfix) with ESMTPS id 74563C2BCF7; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=VQ4ZoNoJZMPRFqoDbLthhcmmTCF8yiPpVD3DVjYnoC8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=uSQ8efAdnnC/f0HcConXgoUbzfARsq08xJ9hH3toFzn24skonWID0nxG7L+yNla3m ZqypZ2uexkFn0pX/KoWasonRJWWSeoogHe0N+SESBrS3s0aTvhLa7kaGYK7bCGhEq/ mSXR7FWLD4UzT9u3q2cJ2MFYdbs5MdZ4CftcFrHX+Dq7NLMMiB8CGDiC1IcnSh+1kF 0xVsaeh0L4+kRxdYGHvsZ3vqZQOa1lEaH+5POkjGYcW/jnjb5kbov1GtrTWXvbUPuT WyfznjVe5+laSoOB50ajIHc3j4VdM7MMppQoRQYemnF8csURfb9M17J5fBLTdFuRDx FxGajpJ8KlBiQ== 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 61BB4C5B56A; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:54 +0800 Subject: [PATCH v2 14/17] 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: <20260813-swap-thp-cleanup-v2-14-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=2084; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=J6ngCmgcSfN+77YLugUfoK2XwvgDSIEPy49r2taKtgU=; b=nv/FXOxUi/qyiP/D7zcPbetLgXwHnG2qIx3L69T9uE/2GdbdAXy1CbWexYNXJE6N1pJL77bSO RL1eMo/YHX4AVDELhD5AfWNEz84D+MRVpx1jgZy4LuqLstBpFrssr4q 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 --- 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 72e7d24139e6..503e3bd84cad 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4343,14 +4343,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_free_swap(new_folio); + folio_unlock(new_folio); + folio_put(new_folio); } =20 out: @@ -4377,7 +4379,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 Tue Sep 29 04:12:16 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 A0E2B3358AD for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=D0HJzu5gQtG+wDDJehXRhjleWoXFa/vebKGX4fu931vNh+BOoZTSzcgVv64qQ17RdPJr7Sl7MpmY60VjeosQHtFmFTtigzWAv+2+mE6tPoQSzk+W1tXw7/o4DrjrwlggjVqD6rhTz3o4v7wGKDo+n03abPmIdHcFzXbTYURQLtI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=Owm7OReCxREHcvnBXseOC6h5BF9QRvQixpox1aW734k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XV0aRDkfi5jyDRFDdxrUbMtlsgTa0czkCb111a1VEjNWVRBPngyWyI4Lh+6IJM/lZSopmvN2xLz1C/9RtI+bbPucW4WRVjSlNk2QV+uuPYtb0Untbjj22U5EUqC6E4WHwwen3NEMwofO9Iv9JcGXDN8JeXE7rUkZXXa9T38xYR0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T9+ZKlHk; 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="T9+ZKlHk" Received: by smtp.kernel.org (Postfix) with ESMTPS id 84041C2BCF4; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=Owm7OReCxREHcvnBXseOC6h5BF9QRvQixpox1aW734k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=T9+ZKlHkYjQyXsEwBEpwBtV0Om0LkMfS+sCRWSdVQyTJeMkMXexVhNs7gtAwziBNx eNX2rKav3ZHnD9OPFM42kIyZEmru0ZB2VtougF8mz9HgBHNP3uyxnW2SkdCSQW14Rb cXmXT0mrL0RK7phwkhHAvR4ZlC4fC5BG7yke1sPcc5dH719Q17Il5IcSrSCob4OmIF 6SkTyTcUSIchYiXmZVb4oow8rmOLRsMQjVRr83tOJ0TT8igZRVgwwshEEFQZNlUI+M g+6cuquy3Y/20bDJo7qCJM8M1sXfL5clfsF39mxUM7qFT0tK9t9Q1Mw950KXf+Rx1f yt4zUYjGplG0g== 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 711CFC5AD5A; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:55 +0800 Subject: [PATCH v2 15/17] 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: <20260813-swap-thp-cleanup-v2-15-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=4239; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=7dsbDsudI2n6mDwR1IdM39EPBRK/NxojqOiTK462nZU=; b=c4rzUnqjWf2UO0CXc0WhA8Ig+vZoZxuMwxsTI9vQE01fd/QsHjYctk+jycsH4U3c7Yfgh+u01 zMHvm4b5o83AcjwKuTg9ljA5ByH5F6u2MneiiOA9vL348+KgChDbBSA 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 --- 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 503e3bd84cad..317e5b63d44b 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3809,6 +3809,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; @@ -3823,8 +3824,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) { @@ -3899,19 +3900,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)) @@ -4411,11 +4406,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 Tue Sep 29 04:12:16 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 B3DA1336886 for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=jCIZ5ZQPcZDCxhXspVYRDiKMSW0icbhUlxsEd4UpiUb++pHkuG6s9XXCtek1jYuc38kEwXRnG8NuqXqwDS4f+1aBxEjCSJq1/R9/+AJbNPWHYkd50IdyszmLuGi9ojdq8G0U4qahkZ4zI2lKDzWKtKI7el17Dol4Oo9YkfJY/5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=dbNw8olNiA7PcXPkEC0v/OBVaIweQIwkkGj4cgBBAxU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H4JTzCYtc+SzyZOBbMxdEXhQUy9VDbgxsafufIvMpy8xiDqEsdiSeexeF3urEBsPL9+sG44lNjfWMP+podjsz5yaAbWP1tBC+0IEIvPro+KCjujvEcpTB65n2frkuqxONATTEiXDWuCoPmeXNwvLiJ1Cl+C2VTDonVQLFnxRxCk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i6pGYHAM; 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="i6pGYHAM" Received: by smtp.kernel.org (Postfix) with ESMTPS id 961DFC2BCFB; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=dbNw8olNiA7PcXPkEC0v/OBVaIweQIwkkGj4cgBBAxU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=i6pGYHAMayR3Dh+K+OrmMvtsL/NqvZLIDElgb2IwqG+t0bPiBFEjU9dNGceWVWRWM 5oOcRzAZK4R6mi4E7l+6ZcGc/sIk8ugTN/sksI8zQVVsKZk8DTh/RsrXynjlhqnKXw gvm1h2DIabdpDwX38NWDM52tuTsxdzinqZCEdWxOYb6d3eM/h0nAYL653ViMsC68Dn f9gDC8Jj+0BLT9KBDHg2P3lI2xYoU/5DKZDLnCl6untu1lmFhM+sOs/Dl7UgGZ6cV8 HXmR2q1Xf7stlVjVWK7sr9DddKrYbsJ2mxMtPXAqQlQlxFlPXV0nYtvwQluGEVsKGb 8s5Uga6Z9ToVw== 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 81A16C5DF64; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:56 +0800 Subject: [PATCH v2 16/17] 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: <20260813-swap-thp-cleanup-v2-16-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=1942; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=MHV5HzFK6Fi4cPV8SFNP30qZtKhPmUDpBG5x8ElzA/A=; b=ghP6fLeoLxLoroMH0xcm5w5WQj8k6/m3y+SZvLRMFwxVcxjdFYirWizt0zQPbmWw57lhiicW0 5cVPzTHsKKrClDHF0+q3wVSo93k9BPwBjQ61TTQufmua/1apoI5yAB0 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 --- 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 317e5b63d44b..c8ec12f6f471 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -4406,11 +4406,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 @@ -4438,7 +4437,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 Tue Sep 29 04:12:16 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 C38FE33937A for ; Wed, 12 Aug 2026 18:49:14 +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=1786560554; cv=none; b=WXXqAIUfOvu9+MGwI0IwNpqzk8oAnKau6zZzjf5V4vRFBg1+Jo5rl8NBkzoohtQiAFGvWHbcZ/h5azpZOa7lhuH1NdSO9RbqArluGry+5AmjW6Ncj4pP0CBd6sfyFAqvViP77MexfXGWwu7UY2cu5vgF1ZRpUSzyPm9r1i4vS3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786560554; c=relaxed/simple; bh=zXydGbi1mCMmauDvoJJ6ITE1co5O8uk8Ha0dlSt9yNA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qRqWj/ah5ZsQUm/J/5J6t73D2G9v+ZLBTbH2T64Ipahm8VW7Rj0FdbAjeDuiqJCdQzf3qK1kyoFI8NKBGIOdhkg34gW42ohM4L1ipCQAZHyhmnOBARDgaqHqFkhzSYO/sAzBWrEhfUVVLkcautlj+uweiR/Zgp/bT68tkhBg2ck= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KS3dleUx; 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="KS3dleUx" Received: by smtp.kernel.org (Postfix) with ESMTPS id A5D00C2BCB3; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786560554; bh=zXydGbi1mCMmauDvoJJ6ITE1co5O8uk8Ha0dlSt9yNA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=KS3dleUxCCO7k/8smCuVew9P15AM7rITyvaQqZofT+Eik5XwanhphNO6j45HDUqDw hJR3IMrAPjmyf1KK+l/8z1JNLKwQp4Xns4NhNwpIQ49+igMxRlPND6PvepfqvoVUMD 2rTxKrC1NtBWZBkI7D26Vvb90SdegF5xsVk/g+E2HrSFupC5bYRkg//EFvMfSQs64i 36LUHd56cOMPcnfEBmfB2Vu+eQppA3CdG5hyxh2fo7cKQTRQkclAp+XLuSyok3Z+VI l9YbB7TLo2R046Fr6nR5LgjrYkWwSVEpfdy4z+pE4oU9BEzkeOYSzX/TGBLbi+WIyu yHUxcoiUHYUTg== 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 92E89C5CFEB; Wed, 12 Aug 2026 18:49:14 +0000 (UTC) From: Kairui Song via B4 Relay Date: Thu, 13 Aug 2026 02:48:57 +0800 Subject: [PATCH v2 17/17] 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: <20260813-swap-thp-cleanup-v2-17-d2ee48c6aa49@tencent.com> References: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@tencent.com> In-Reply-To: <20260813-swap-thp-cleanup-v2-0-d2ee48c6aa49@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 X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786560551; l=4502; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=MpCncwju9a9pcoRTMcyfhYSBrYb5Nj043YSXcbCJIqU=; b=r9OynKAJ2fflZntTFDHvkIHY6aARm7sGNPxnfwN+ppGCckMlUqRUJOe/OYX8WUtiuZR4r7Us4 CcXkHITqh5JBHq2AI4csVKqWi6BoPtYp917V6byQWQBj7pHWkuVxfbd 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 --- 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 c8ec12f6f471..1c61b7d39cd0 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3927,10 +3927,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); } @@ -4015,7 +4015,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(); @@ -4055,7 +4055,7 @@ static int __folio_split_unmap_and_freeze(struct foli= o *folio, unsigned int new_ for_each_folio_safe(folio_next(folio), end_folio, new_folio, next) { 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) @@ -4063,7 +4063,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); @@ -4109,6 +4109,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; @@ -4180,22 +4181,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 */ @@ -4215,7 +4210,7 @@ static int __folio_split_unmap_and_freeze_file(struct= folio *folio, unsigned int unsigned long nr_pages =3D folio_nr_pages(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 @@ -4242,7 +4237,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