From: Lian Wang <lianux.mm@gmail.com>
To: damon@lists.linux.dev, linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org, sj@kernel.org,
gutierrez.asier@huawei-partners.com, daichaobing@sangfor.com.cn,
lianux.wang@processmission.com, lianux.mm@gmail.com,
kunwu.chan@gmail.com
Subject: [RESEND RFC PATCH v2 2/5] mm/khugepaged: add damon_collapse_folio_range() for external callers
Date: Thu, 2 Jul 2026 17:52:24 +0800 [thread overview]
Message-ID: <20260702095227.75866-3-lianux.mm@gmail.com> (raw)
In-Reply-To: <20260702095227.75866-1-lianux.mm@gmail.com>
Export a thin wrapper around collapse_huge_page() that allows external
subsystems such as DAMON to trigger THP collapse on a target address
range.
Currently restricted to PMD order (HPAGE_PMD_ORDER), since
collapse_huge_page() does not yet support arbitrary mTHP orders.
The restriction can be relaxed when khugepaged gains mTHP support.
The caller must hold a reference to @mm. Do not hold mmap lock:
collapse_huge_page() acquires mmap_read_lock for validation, releases
it, then acquires mmap_write_lock for the actual collapse. Holding
an outer mmap_read_lock would cause a self-deadlock when the same
thread attempts the inner mmap_write_lock.
Co-developed-by: Kunwu Chan <kunwu.chan@gmail.com>
Signed-off-by: Kunwu Chan <kunwu.chan@gmail.com>
Signed-off-by: Lian Wang <lianux.mm@gmail.com>
Signed-off-by: Lian Wang <lianux.wang@processmission.com>
---
include/linux/khugepaged.h | 9 ++++++++
mm/khugepaged.c | 46 ++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
index d7a9053ff4fe..f7d49cba712f 100644
--- a/include/linux/khugepaged.h
+++ b/include/linux/khugepaged.h
@@ -20,6 +20,9 @@ extern bool current_is_khugepaged(void);
void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
bool install_pmd);
+int damon_collapse_folio_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned int target_order);
+
static inline void khugepaged_fork(struct mm_struct *mm, struct mm_struct *oldmm)
{
if (mm_flags_test(MMF_VM_HUGEPAGE, oldmm))
@@ -47,6 +50,12 @@ static inline void collapse_pte_mapped_thp(struct mm_struct *mm,
{
}
+static inline int damon_collapse_folio_range(struct mm_struct *mm,
+ unsigned long start_addr, unsigned int target_order)
+{
+ return -EINVAL;
+}
+
static inline void khugepaged_min_free_kbytes_update(void)
{
}
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 617bca76db49..7fe9ce1e0533 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -3272,3 +3272,49 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
return thps == ((hend - hstart) >> HPAGE_PMD_SHIFT) ? 0
: madvise_collapse_errno(last_fail);
}
+
+/**
+ * damon_collapse_folio_range() - Collapse base pages in range into a THP
+ * @mm: mm_struct of the target process
+ * @start_addr: start address (must be order-aligned)
+ * @target_order: page order of the collapse result (currently only
+ * HPAGE_PMD_ORDER is supported)
+ *
+ * Thin wrapper around collapse_huge_page() for external callers such as
+ * DAMON. The caller must hold a reference to @mm. Do not hold mmap
+ * lock: collapse_huge_page() acquires mmap_read_lock for validation,
+ * releases it, then acquires mmap_write_lock for the collapse. Holding
+ * an outer mmap_read_lock would self-deadlock.
+ *
+ * Return: 0 on success, -EINVAL on bad arguments, negative error from
+ * madvise_collapse_errno() otherwise.
+ */
+int damon_collapse_folio_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned int target_order)
+{
+ struct collapse_control *cc;
+ enum scan_result result;
+
+ if (target_order != HPAGE_PMD_ORDER) {
+ pr_warn_once("%s: only PMD order (%u) is supported, got %u\n",
+ __func__, HPAGE_PMD_ORDER, target_order);
+ return -EINVAL;
+ }
+ if (start_addr & ((PAGE_SIZE << target_order) - 1))
+ return -EINVAL;
+
+ cc = kmalloc_obj(*cc);
+ if (!cc)
+ return -ENOMEM;
+ cc->is_khugepaged = false;
+ cc->progress = 0;
+
+ lru_add_drain_all();
+
+ result = collapse_huge_page(mm, start_addr, 1, 0, cc, target_order);
+ kfree(cc);
+ if (result == SCAN_SUCCEED || result == SCAN_PMD_MAPPED)
+ return 0;
+ return madvise_collapse_errno(result);
+}
+EXPORT_SYMBOL_GPL(damon_collapse_folio_range);
next prev parent reply other threads:[~2026-07-02 9:52 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 9:52 [RESEND RFC PATCH v2 0/5] mm/damon: add mTHP collapse and split actions Lian Wang
2026-07-02 9:52 ` [RESEND RFC PATCH v2 1/5] mm/damon: add target_order field for DAMOS_COLLAPSE Lian Wang
2026-07-02 10:02 ` sashiko-bot
2026-07-02 9:52 ` Lian Wang [this message]
2026-07-02 10:08 ` [RESEND RFC PATCH v2 2/5] mm/khugepaged: add damon_collapse_folio_range() for external callers sashiko-bot
2026-07-02 9:52 ` [RESEND RFC PATCH v2 3/5] mm/damon/vaddr: implement mTHP-aware DAMOS_COLLAPSE handler Lian Wang
2026-07-02 10:27 ` sashiko-bot
2026-07-02 9:52 ` [RESEND RFC PATCH v2 4/5] mm/damon: introduce DAMOS_SPLIT action Lian Wang
2026-07-02 10:21 ` sashiko-bot
2026-07-02 9:52 ` [RESEND RFC PATCH v2 5/5] mm/damon/vaddr: implement DAMOS_SPLIT handler Lian Wang
2026-07-02 10:30 ` sashiko-bot
2026-07-02 16:39 ` [RESEND RFC PATCH v2 0/5] mm/damon: add mTHP collapse and split actions SJ Park
-- strict thread matches above, loose matches on Subject: below --
2026-07-02 9:46 Lian Wang
2026-07-02 9:46 ` [RESEND RFC PATCH v2 2/5] mm/khugepaged: add damon_collapse_folio_range() for external callers Lian Wang
2026-07-02 10:13 ` sashiko-bot
2026-07-02 11:07 ` Lorenzo Stoakes
2026-07-02 19:43 ` SJ Park
2026-07-02 20:32 ` SJ Park
2026-07-03 2:06 ` wang lian
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=20260702095227.75866-3-lianux.mm@gmail.com \
--to=lianux.mm@gmail.com \
--cc=daichaobing@sangfor.com.cn \
--cc=damon@lists.linux.dev \
--cc=gutierrez.asier@huawei-partners.com \
--cc=kunwu.chan@gmail.com \
--cc=lianux.wang@processmission.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=sj@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.