From: Yin Tirui <yintirui@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>, linux-mm@kvack.org
Cc: David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>, Dev Jain <dev.jain@arm.com>,
Zi Yan <ziy@nvidia.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Barry Song <baohua@kernel.org>, Lance Yang <lance.yang@linux.dev>,
Ryan Roberts <ryan.roberts@arm.com>,
Nico Pache <nico.pache@linux.dev>,
Usama Arif <usama.arif@linux.dev>,
"Liam R . Howlett" <liam@infradead.org>,
wangkefeng.wang@huawei.com, chenjun102@huawei.com,
linux-kernel@vger.kernel.org, Yin Tirui <yintirui@gmail.com>
Subject: [PATCH RFC 6/9] mm/huge_memory: add and use split_huge_pmd_anon_rmap()
Date: Sat, 29 Aug 2026 02:33:16 +0800 [thread overview]
Message-ID: <1022e5cfad8bb7e32946da7e881534730757bbbd.1787941780.git.yintirui@gmail.com> (raw)
In-Reply-To: <cover.1787941780.git.yintirui@gmail.com>
The anon-exclusive handling and the PTE-level rmap conversion are written
twice, once for present entries and once for device private ones. Factor
them into one helper.
It returns whether the mapping may still be frozen instead of writing the
caller's freeze back.
No functional change intended.
Signed-off-by: Yin Tirui <yintirui@gmail.com>
---
mm/huge_memory.c | 90 +++++++++++++++++++++++++-----------------------
1 file changed, 47 insertions(+), 43 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 1cd8878edc1d..e0083a9e89b8 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3194,6 +3194,43 @@ static void unmap_huge_pmd_entry(struct vm_area_struct *vma,
folio_put(folio);
}
+/*
+ * Convert the folio's PMD-level anonymous rmap into PTE-level ones.
+ *
+ * Without "freeze", we'll simply split the PMD, propagating the
+ * PageAnonExclusive() flag for each PTE by setting it for
+ * each subpage -- no need to (temporarily) clear.
+ *
+ * With "freeze" we want to replace mapped pages by
+ * migration entries right away. This is only possible if we
+ * managed to clear PageAnonExclusive() -- see
+ * set_pmd_migration_entry().
+ *
+ * In case we cannot clear PageAnonExclusive(), split the PMD
+ * only and let try_to_migrate_one() fail later.
+ *
+ * See folio_try_share_anon_rmap_pmd(): invalidate PMD first.
+ *
+ * Returns: whether the mapping may still be frozen.
+ */
+static bool split_huge_pmd_anon_rmap(struct folio *folio, struct page *page,
+ struct vm_area_struct *vma, unsigned long haddr, bool freeze,
+ bool anon_exclusive)
+{
+ rmap_t rmap_flags = RMAP_NONE;
+
+ if (freeze &&
+ (!anon_exclusive || !folio_try_share_anon_rmap_pmd(folio, page)))
+ return true;
+
+ folio_ref_add(folio, HPAGE_PMD_NR - 1);
+ if (anon_exclusive)
+ rmap_flags |= RMAP_EXCLUSIVE;
+ folio_add_anon_rmap_ptes(folio, page, HPAGE_PMD_NR, vma, haddr,
+ rmap_flags);
+ return false;
+}
+
static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
unsigned long haddr, bool freeze)
{
@@ -3275,23 +3312,12 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
anon_exclusive = PageAnonExclusive(page);
/*
- * Device private THP should be treated the same as regular
- * folios w.r.t anon exclusive handling. See the comments for
- * folio handling and anon_exclusive below.
+ * Device private folios are treated the same as regular folios
+ * w.r.t. anon exclusive handling, see
+ * split_huge_pmd_anon_rmap().
*/
- if (freeze && anon_exclusive &&
- folio_try_share_anon_rmap_pmd(folio, page))
- freeze = false;
- if (!freeze) {
- rmap_t rmap_flags = RMAP_NONE;
-
- folio_ref_add(folio, HPAGE_PMD_NR - 1);
- if (anon_exclusive)
- rmap_flags |= RMAP_EXCLUSIVE;
-
- folio_add_anon_rmap_ptes(folio, page, HPAGE_PMD_NR,
- vma, haddr, rmap_flags);
- }
+ freeze = split_huge_pmd_anon_rmap(folio, page, vma, haddr,
+ freeze, anon_exclusive);
} else {
/*
* Up to this point the pmd is present and huge and userland has
@@ -3315,6 +3341,9 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
* complete for this pmd), then we flush the SMP TLB and finally
* we write the non-huge version of the pmd entry with
* pmd_populate.
+ *
+ * This must also happen before PageAnonExclusive() is read
+ * below, see folio_try_share_anon_rmap_pmd().
*/
old_pmd = pmdp_invalidate(vma, haddr, pmd);
page = pmd_page(old_pmd);
@@ -3329,34 +3358,9 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
VM_WARN_ON_FOLIO(!folio_ref_count(folio), folio);
- /*
- * Without "freeze", we'll simply split the PMD, propagating the
- * PageAnonExclusive() flag for each PTE by setting it for
- * each subpage -- no need to (temporarily) clear.
- *
- * With "freeze" we want to replace mapped pages by
- * migration entries right away. This is only possible if we
- * managed to clear PageAnonExclusive() -- see
- * set_pmd_migration_entry().
- *
- * In case we cannot clear PageAnonExclusive(), split the PMD
- * only and let try_to_migrate_one() fail later.
- *
- * See folio_try_share_anon_rmap_pmd(): invalidate PMD first.
- */
anon_exclusive = PageAnonExclusive(page);
- if (freeze && anon_exclusive &&
- folio_try_share_anon_rmap_pmd(folio, page))
- freeze = false;
- if (!freeze) {
- rmap_t rmap_flags = RMAP_NONE;
-
- folio_ref_add(folio, HPAGE_PMD_NR - 1);
- if (anon_exclusive)
- rmap_flags |= RMAP_EXCLUSIVE;
- folio_add_anon_rmap_ptes(folio, page, HPAGE_PMD_NR,
- vma, haddr, rmap_flags);
- }
+ freeze = split_huge_pmd_anon_rmap(folio, page, vma, haddr,
+ freeze, anon_exclusive);
}
/*
--
2.34.1
next prev parent reply other threads:[~2026-08-28 18:37 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 18:33 [PATCH RFC 0/9] mm/huge_memory: refactor __split_huge_pmd_locked() Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 1/9] mm/huge_memory: read the huge PMD entry once when splitting it Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 2/9] mm/huge_memory: add and use huge_zero_pmd_can_split() Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 3/9] mm/huge_memory: add and use unmap_huge_pmd_entry() Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 4/9] mm/huge_memory: use normal_or_softleaf_folio_pmd() in the PMD split path Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 5/9] mm/huge_memory: dispatch on the folio when splitting a huge PMD Yin Tirui
2026-08-28 18:33 ` Yin Tirui [this message]
2026-08-28 18:33 ` [PATCH RFC 7/9] mm/huge_memory: add struct split_pmd_state Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 8/9] mm/huge_memory: split present and non-present huge PMDs separately Yin Tirui
2026-08-28 18:33 ` [PATCH RFC 9/9] mm/huge_memory: unify the migration and device private PTE loops Yin Tirui
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1022e5cfad8bb7e32946da7e881534730757bbbd.1787941780.git.yintirui@gmail.com \
--to=yintirui@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=chenjun102@huawei.com \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=nico.pache@linux.dev \
--cc=ryan.roberts@arm.com \
--cc=usama.arif@linux.dev \
--cc=wangkefeng.wang@huawei.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox