* [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix
@ 2026-01-18 19:22 Shivank Garg
2026-01-18 19:22 ` [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label Shivank Garg
` (5 more replies)
0 siblings, 6 replies; 32+ messages in thread
From: Shivank Garg @ 2026-01-18 19:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel,
shivankg
This series contains several cleanups for mm/khugepaged.c to improve code
readability and type safety, and one functional fix to ensure
khugepaged_scan_mm_slot() correctly accounts for small VMAs towards
scan limit.
To apply this series on mm-new, please drop:
- 20251215084615.5283-3-shivankg@amd.com:
[PATCH V4 0/2] mm/khugepaged: fix dirty page handling for MADV_COLLAPSE
- 20251224111351.41042-4-shivankg@amd.com:
[PATCH V2 0/5] mm/khugepaged: cleanups and scan limit fix
- Apply https://lore.kernel.org/all/20260118190939.8986-2-shivankg@amd.com
[PATCH V5 0/2] mm/khugepaged: fix dirty page handling for MADV_COLLAPSE
Thanks,
v3:
- Fold mm-khugepaged-count-small-vmas-towards-scan-limit-fix: add comment (Lance)
- Remove extern and use two tabs indent (David)
v2:
- https://lore.kernel.org/all/20251224111351.41042-4-shivankg@amd.com
- Added a fix for small VMAs not being counted in the scan limit (Wei)
- Updated 'progress' to 'unsigned int' to match types
- Update return types of internal functions to use enum scan_result (Zi)
- Add void wrapper collapse_pte_mapped_thp() for external callers to avoid
exposing internal enum (David)
v1:
https://lore.kernel.org/linux-mm/20251216111139.95438-2-shivankg@amd.com
Shivank Garg (5):
mm/khugepaged: remove unnecessary goto 'skip' label
mm/khugepaged: count small VMAs towards scan limit
mm/khugepaged: change collapse_pte_mapped_thp() to return void
mm/khugepaged: use enum scan_result for result variables and return
types
mm/khugepaged: make khugepaged_collapse_control static
include/linux/khugepaged.h | 9 +--
mm/khugepaged.c | 149 +++++++++++++++++++------------------
2 files changed, 79 insertions(+), 79 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
@ 2026-01-18 19:22 ` Shivank Garg
2026-01-22 7:04 ` Dev Jain
2026-01-22 11:56 ` Nico Pache
2026-01-18 19:22 ` [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit Shivank Garg
` (4 subsequent siblings)
5 siblings, 2 replies; 32+ messages in thread
From: Shivank Garg @ 2026-01-18 19:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel,
shivankg
Replace goto skip with actual logic for better code readability.
No functional change.
Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
Reviewed-by: Lance Yang <lance.yang@linux.dev>
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
mm/khugepaged.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 16582bdcb6ff..984294a16861 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -2442,14 +2442,15 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
break;
}
if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_KHUGEPAGED, PMD_ORDER)) {
-skip:
progress++;
continue;
}
hstart = round_up(vma->vm_start, HPAGE_PMD_SIZE);
hend = round_down(vma->vm_end, HPAGE_PMD_SIZE);
- if (khugepaged_scan.address > hend)
- goto skip;
+ if (khugepaged_scan.address > hend) {
+ progress++;
+ continue;
+ }
if (khugepaged_scan.address < hstart)
khugepaged_scan.address = hstart;
VM_BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK);
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
2026-01-18 19:22 ` [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label Shivank Garg
@ 2026-01-18 19:22 ` Shivank Garg
2026-01-22 7:32 ` Dev Jain
2026-01-18 19:22 ` [PATCH V3 3/5] mm/khugepaged: change collapse_pte_mapped_thp() to return void Shivank Garg
` (3 subsequent siblings)
5 siblings, 1 reply; 32+ messages in thread
From: Shivank Garg @ 2026-01-18 19:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel,
shivankg, Wei Yang
The khugepaged_scan_mm_slot() uses a 'progress' counter to limit the
amount of work performed and consists of three components:
1. Transitioning to a new mm (+1).
2. Skipping an unsuitable VMA (+1).
3. Scanning a PMD-sized range (+HPAGE_PMD_NR).
Consider a 1MB VMA sitting between two 2MB alignment boundaries:
vma1 vma2 vma3
+----------+------+----------+
|2M |1M |2M |
+----------+------+----------+
^ ^
start end
^
hstart,hend
In this case, for vma2:
hstart = round_up(start, HPAGE_PMD_SIZE) -> Next 2MB alignment
hend = round_down(end, HPAGE_PMD_SIZE) -> Prev 2MB alignment
Currently, since `hend <= hstart`, VMAs that are too small or unaligned
to contain a hugepage are skipped without incrementing 'progress'.
A process containing a large number of such small VMAs will unfairly
consume more CPU cycles before yielding compared to a process with
fewer, larger, or aligned VMAs.
Fix this by incrementing progress when the `hend <= hstart` condition
is met.
Additionally, change 'progress' type to `unsigned int` to match both
the 'pages' type and the function return value.
Suggested-by: Wei Yang <richard.weiyang@gmail.com>
Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
Reviewed-by: Lance Yang <lance.yang@linux.dev>
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
Incorporate comment feedback from Lance:
https://lore.kernel.org/linux-mm/6b408736-978a-4d40-adfc-97819951c3a6@linux.dev
mm/khugepaged.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 984294a16861..93ce39915f4a 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -2403,7 +2403,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
struct mm_slot *slot;
struct mm_struct *mm;
struct vm_area_struct *vma;
- int progress = 0;
+ unsigned int progress = 0;
VM_BUG_ON(!pages);
lockdep_assert_held(&khugepaged_mm_lock);
@@ -2447,7 +2447,8 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
}
hstart = round_up(vma->vm_start, HPAGE_PMD_SIZE);
hend = round_down(vma->vm_end, HPAGE_PMD_SIZE);
- if (khugepaged_scan.address > hend) {
+ if (khugepaged_scan.address > hend || hend <= hstart) {
+ /* VMA already scanned or too small/unaligned for hugepage. */
progress++;
continue;
}
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V3 3/5] mm/khugepaged: change collapse_pte_mapped_thp() to return void
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
2026-01-18 19:22 ` [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label Shivank Garg
2026-01-18 19:22 ` [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit Shivank Garg
@ 2026-01-18 19:22 ` Shivank Garg
2026-01-22 12:17 ` Nico Pache
2026-01-18 19:22 ` [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types Shivank Garg
` (2 subsequent siblings)
5 siblings, 1 reply; 32+ messages in thread
From: Shivank Garg @ 2026-01-18 19:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel,
shivankg
The only external caller of collapse_pte_mapped_thp() is uprobe, which
ignores the return value. Change the external API to return void to
simplify the interface.
Introduce try_collapse_pte_mapped_thp() for internal use that preserves
the return value. This prepares for future patch that will convert
the return type to use enum scan_result.
Suggested-by: David Hildenbrand (Red Hat) <david@kernel.org>
Acked-by: Lance Yang <lance.yang@linux.dev>
Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
include/linux/khugepaged.h | 9 ++++-----
mm/khugepaged.c | 40 ++++++++++++++++++++++----------------
2 files changed, 27 insertions(+), 22 deletions(-)
diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
index eb1946a70cff..d7a9053ff4fe 100644
--- a/include/linux/khugepaged.h
+++ b/include/linux/khugepaged.h
@@ -17,8 +17,8 @@ extern void khugepaged_enter_vma(struct vm_area_struct *vma,
vm_flags_t vm_flags);
extern void khugepaged_min_free_kbytes_update(void);
extern bool current_is_khugepaged(void);
-extern int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd);
+void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+ bool install_pmd);
static inline void khugepaged_fork(struct mm_struct *mm, struct mm_struct *oldmm)
{
@@ -42,10 +42,9 @@ static inline void khugepaged_enter_vma(struct vm_area_struct *vma,
vm_flags_t vm_flags)
{
}
-static inline int collapse_pte_mapped_thp(struct mm_struct *mm,
- unsigned long addr, bool install_pmd)
+static inline void collapse_pte_mapped_thp(struct mm_struct *mm,
+ unsigned long addr, bool install_pmd)
{
- return 0;
}
static inline void khugepaged_min_free_kbytes_update(void)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 93ce39915f4a..17f3f0043368 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1477,20 +1477,8 @@ static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
return SCAN_SUCCEED;
}
-/**
- * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at
- * address haddr.
- *
- * @mm: process address space where collapse happens
- * @addr: THP collapse address
- * @install_pmd: If a huge PMD should be installed
- *
- * This function checks whether all the PTEs in the PMD are pointing to the
- * right THP. If so, retract the page table so the THP can refault in with
- * as pmd-mapped. Possibly install a huge PMD mapping the THP.
- */
-int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd)
+static int try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+ bool install_pmd)
{
int nr_mapped_ptes = 0, result = SCAN_FAIL;
unsigned int nr_batch_ptes;
@@ -1711,6 +1699,24 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
return result;
}
+/**
+ * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at
+ * address haddr.
+ *
+ * @mm: process address space where collapse happens
+ * @addr: THP collapse address
+ * @install_pmd: If a huge PMD should be installed
+ *
+ * This function checks whether all the PTEs in the PMD are pointing to the
+ * right THP. If so, retract the page table so the THP can refault in with
+ * as pmd-mapped. Possibly install a huge PMD mapping the THP.
+ */
+void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+ bool install_pmd)
+{
+ try_collapse_pte_mapped_thp(mm, addr, install_pmd);
+}
+
/* Can we retract page tables for this file-backed VMA? */
static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)
{
@@ -2227,7 +2233,7 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
/*
* Remove pte page tables, so we can re-fault the page as huge.
- * If MADV_COLLAPSE, adjust result to call collapse_pte_mapped_thp().
+ * If MADV_COLLAPSE, adjust result to call try_collapse_pte_mapped_thp().
*/
retract_page_tables(mapping, start);
if (cc && !cc->is_khugepaged)
@@ -2480,7 +2486,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
mmap_read_lock(mm);
if (hpage_collapse_test_exit_or_disable(mm))
goto breakouterloop;
- *result = collapse_pte_mapped_thp(mm,
+ *result = try_collapse_pte_mapped_thp(mm,
khugepaged_scan.address, false);
if (*result == SCAN_PMD_MAPPED)
*result = SCAN_SUCCEED;
@@ -2845,7 +2851,7 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
case SCAN_PTE_MAPPED_HUGEPAGE:
BUG_ON(mmap_locked);
mmap_read_lock(mm);
- result = collapse_pte_mapped_thp(mm, addr, true);
+ result = try_collapse_pte_mapped_thp(mm, addr, true);
mmap_read_unlock(mm);
goto handle_result;
/* Whitelisted set of results where continuing OK */
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
` (2 preceding siblings ...)
2026-01-18 19:22 ` [PATCH V3 3/5] mm/khugepaged: change collapse_pte_mapped_thp() to return void Shivank Garg
@ 2026-01-18 19:22 ` Shivank Garg
2026-01-19 10:24 ` David Hildenbrand (Red Hat)
` (2 more replies)
2026-01-18 19:23 ` [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static Shivank Garg
2026-01-18 20:34 ` [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Andrew Morton
5 siblings, 3 replies; 32+ messages in thread
From: Shivank Garg @ 2026-01-18 19:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel,
shivankg
Convert result variables and return types from int to enum scan_result
throughout khugepaged code. This improves type safety and code clarity
by making the intent explicit.
No functional change.
Reviewed-by: Zi Yan <ziy@nvidia.com>
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
mm/khugepaged.c | 99 +++++++++++++++++++++++--------------------------
1 file changed, 46 insertions(+), 53 deletions(-)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 17f3f0043368..1667abae6d8d 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -537,17 +537,16 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte,
}
}
-static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
- unsigned long start_addr,
- pte_t *pte,
- struct collapse_control *cc,
- struct list_head *compound_pagelist)
+static enum scan_result __collapse_huge_page_isolate(struct vm_area_struct *vma,
+ unsigned long start_addr, pte_t *pte, struct collapse_control *cc,
+ struct list_head *compound_pagelist)
{
struct page *page = NULL;
struct folio *folio = NULL;
unsigned long addr = start_addr;
pte_t *_pte;
- int none_or_zero = 0, shared = 0, result = SCAN_FAIL, referenced = 0;
+ int none_or_zero = 0, shared = 0, referenced = 0;
+ enum scan_result result = SCAN_FAIL;
for (_pte = pte; _pte < pte + HPAGE_PMD_NR;
_pte++, addr += PAGE_SIZE) {
@@ -780,13 +779,13 @@ static void __collapse_huge_page_copy_failed(pte_t *pte,
* @ptl: lock on raw pages' PTEs
* @compound_pagelist: list that stores compound pages
*/
-static int __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
+static enum scan_result __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
pmd_t *pmd, pmd_t orig_pmd, struct vm_area_struct *vma,
unsigned long address, spinlock_t *ptl,
struct list_head *compound_pagelist)
{
unsigned int i;
- int result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
/*
* Copying pages' contents is subject to memory poison at any iteration.
@@ -898,10 +897,8 @@ static int hpage_collapse_find_target_node(struct collapse_control *cc)
* Returns enum scan_result value.
*/
-static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
- bool expect_anon,
- struct vm_area_struct **vmap,
- struct collapse_control *cc)
+static enum scan_result hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
+ bool expect_anon, struct vm_area_struct **vmap, struct collapse_control *cc)
{
struct vm_area_struct *vma;
enum tva_type type = cc->is_khugepaged ? TVA_KHUGEPAGED :
@@ -930,7 +927,7 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
return SCAN_SUCCEED;
}
-static inline int check_pmd_state(pmd_t *pmd)
+static inline enum scan_result check_pmd_state(pmd_t *pmd)
{
pmd_t pmde = pmdp_get_lockless(pmd);
@@ -953,9 +950,8 @@ static inline int check_pmd_state(pmd_t *pmd)
return SCAN_SUCCEED;
}
-static int find_pmd_or_thp_or_none(struct mm_struct *mm,
- unsigned long address,
- pmd_t **pmd)
+static enum scan_result find_pmd_or_thp_or_none(struct mm_struct *mm,
+ unsigned long address, pmd_t **pmd)
{
*pmd = mm_find_pmd(mm, address);
if (!*pmd)
@@ -964,12 +960,11 @@ static int find_pmd_or_thp_or_none(struct mm_struct *mm,
return check_pmd_state(*pmd);
}
-static int check_pmd_still_valid(struct mm_struct *mm,
- unsigned long address,
- pmd_t *pmd)
+static enum scan_result check_pmd_still_valid(struct mm_struct *mm,
+ unsigned long address, pmd_t *pmd)
{
pmd_t *new_pmd;
- int result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
+ enum scan_result result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
if (result != SCAN_SUCCEED)
return result;
@@ -985,15 +980,14 @@ static int check_pmd_still_valid(struct mm_struct *mm,
* Called and returns without pte mapped or spinlocks held.
* Returns result: if not SCAN_SUCCEED, mmap_lock has been released.
*/
-static int __collapse_huge_page_swapin(struct mm_struct *mm,
- struct vm_area_struct *vma,
- unsigned long start_addr, pmd_t *pmd,
- int referenced)
+static enum scan_result __collapse_huge_page_swapin(struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long start_addr, pmd_t *pmd,
+ int referenced)
{
int swapped_in = 0;
vm_fault_t ret = 0;
unsigned long addr, end = start_addr + (HPAGE_PMD_NR * PAGE_SIZE);
- int result;
+ enum scan_result result;
pte_t *pte = NULL;
spinlock_t *ptl;
@@ -1062,8 +1056,8 @@ static int __collapse_huge_page_swapin(struct mm_struct *mm,
return result;
}
-static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
- struct collapse_control *cc)
+static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
+ struct collapse_control *cc)
{
gfp_t gfp = (cc->is_khugepaged ? alloc_hugepage_khugepaged_gfpmask() :
GFP_TRANSHUGE);
@@ -1090,9 +1084,8 @@ static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
return SCAN_SUCCEED;
}
-static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
- int referenced, int unmapped,
- struct collapse_control *cc)
+static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long address,
+ int referenced, int unmapped, struct collapse_control *cc)
{
LIST_HEAD(compound_pagelist);
pmd_t *pmd, _pmd;
@@ -1100,7 +1093,7 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
pgtable_t pgtable;
struct folio *folio;
spinlock_t *pmd_ptl, *pte_ptl;
- int result = SCAN_FAIL;
+ enum scan_result result = SCAN_FAIL;
struct vm_area_struct *vma;
struct mmu_notifier_range range;
@@ -1246,15 +1239,14 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
return result;
}
-static int hpage_collapse_scan_pmd(struct mm_struct *mm,
- struct vm_area_struct *vma,
- unsigned long start_addr, bool *mmap_locked,
- struct collapse_control *cc)
+static enum scan_result hpage_collapse_scan_pmd(struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long start_addr, bool *mmap_locked,
+ struct collapse_control *cc)
{
pmd_t *pmd;
pte_t *pte, *_pte;
- int result = SCAN_FAIL, referenced = 0;
- int none_or_zero = 0, shared = 0;
+ int none_or_zero = 0, shared = 0, referenced = 0;
+ enum scan_result result = SCAN_FAIL;
struct page *page = NULL;
struct folio *folio = NULL;
unsigned long addr;
@@ -1441,8 +1433,8 @@ static void collect_mm_slot(struct mm_slot *slot)
}
/* folio must be locked, and mmap_lock must be held */
-static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
- pmd_t *pmdp, struct folio *folio, struct page *page)
+static enum scan_result set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
+ pmd_t *pmdp, struct folio *folio, struct page *page)
{
struct mm_struct *mm = vma->vm_mm;
struct vm_fault vmf = {
@@ -1477,10 +1469,11 @@ static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
return SCAN_SUCCEED;
}
-static int try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
bool install_pmd)
{
- int nr_mapped_ptes = 0, result = SCAN_FAIL;
+ enum scan_result result = SCAN_FAIL;
+ int nr_mapped_ptes = 0;
unsigned int nr_batch_ptes;
struct mmu_notifier_range range;
bool notified = false;
@@ -1862,9 +1855,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
* + unlock old pages
* + unlock and free huge page;
*/
-static int collapse_file(struct mm_struct *mm, unsigned long addr,
- struct file *file, pgoff_t start,
- struct collapse_control *cc)
+static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
+ struct file *file, pgoff_t start, struct collapse_control *cc)
{
struct address_space *mapping = file->f_mapping;
struct page *dst;
@@ -1872,7 +1864,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
pgoff_t index = 0, end = start + HPAGE_PMD_NR;
LIST_HEAD(pagelist);
XA_STATE_ORDER(xas, &mapping->i_pages, start, HPAGE_PMD_ORDER);
- int nr_none = 0, result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
+ int nr_none = 0;
bool is_shmem = shmem_file(file);
VM_BUG_ON(!IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && !is_shmem);
@@ -2293,16 +2286,15 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
return result;
}
-static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
- struct file *file, pgoff_t start,
- struct collapse_control *cc)
+static enum scan_result hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
+ struct file *file, pgoff_t start, struct collapse_control *cc)
{
struct folio *folio = NULL;
struct address_space *mapping = file->f_mapping;
XA_STATE(xas, &mapping->i_pages, start);
int present, swap;
int node = NUMA_NO_NODE;
- int result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
present = 0;
swap = 0;
@@ -2400,7 +2392,7 @@ static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
return result;
}
-static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
+static unsigned int khugepaged_scan_mm_slot(unsigned int pages, enum scan_result *result,
struct collapse_control *cc)
__releases(&khugepaged_mm_lock)
__acquires(&khugepaged_mm_lock)
@@ -2562,7 +2554,7 @@ static void khugepaged_do_scan(struct collapse_control *cc)
unsigned int progress = 0, pass_through_head = 0;
unsigned int pages = READ_ONCE(khugepaged_pages_to_scan);
bool wait = true;
- int result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
lru_add_drain_all();
@@ -2775,7 +2767,8 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
struct collapse_control *cc;
struct mm_struct *mm = vma->vm_mm;
unsigned long hstart, hend, addr;
- int thps = 0, last_fail = SCAN_FAIL;
+ enum scan_result last_fail = SCAN_FAIL;
+ int thps = 0;
bool mmap_locked = true;
BUG_ON(vma->vm_start > start);
@@ -2796,7 +2789,7 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
hend = end & HPAGE_PMD_MASK;
for (addr = hstart; addr < hend; addr += HPAGE_PMD_SIZE) {
- int result = SCAN_FAIL;
+ enum scan_result result = SCAN_FAIL;
bool triggered_wb = false;
retry:
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
` (3 preceding siblings ...)
2026-01-18 19:22 ` [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types Shivank Garg
@ 2026-01-18 19:23 ` Shivank Garg
2026-01-22 9:28 ` Dev Jain
2026-01-18 20:34 ` [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Andrew Morton
5 siblings, 1 reply; 32+ messages in thread
From: Shivank Garg @ 2026-01-18 19:23 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel,
shivankg, Wei Yang, Anshuman Khandual
The global variable 'khugepaged_collapse_control' is not used outside of
mm/khugepaged.c. Make it static to limit its scope.
Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
mm/khugepaged.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 1667abae6d8d..fba6aea5bea6 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
remove_wait_queue(&khugepaged_wait, &wait);
}
-struct collapse_control khugepaged_collapse_control = {
+static struct collapse_control khugepaged_collapse_control = {
.is_khugepaged = true,
};
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
` (4 preceding siblings ...)
2026-01-18 19:23 ` [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static Shivank Garg
@ 2026-01-18 20:34 ` Andrew Morton
2026-01-19 0:17 ` Zi Yan
2026-01-19 5:50 ` Garg, Shivank
5 siblings, 2 replies; 32+ messages in thread
From: Andrew Morton @ 2026-01-18 20:34 UTC (permalink / raw)
To: Shivank Garg
Cc: David Hildenbrand, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, linux-mm, linux-kernel
On Sun, 18 Jan 2026 19:22:51 +0000 Shivank Garg <shivankg@amd.com> wrote:
> This series contains several cleanups for mm/khugepaged.c to improve code
> readability and type safety, and one functional fix to ensure
> khugepaged_scan_mm_slot() correctly accounts for small VMAs towards
> scan limit.
>
That's a lot of changes to a well-reviewed 24 day old patchset.
>
> v3:
> - Fold mm-khugepaged-count-small-vmas-towards-scan-limit-fix: add comment (Lance)
> - Remove extern and use two tabs indent (David)
Are you sure? The v2->v3 diff is large. A lot of (unchangelogged)
alterations from `int' to `enum scan_result'.
It all looks pretty simple/straightforward to me but again, can
reviewers please check this over fairly soonly, thanks.
--- a/include/linux/khugepaged.h~b
+++ a/include/linux/khugepaged.h
@@ -17,8 +17,8 @@ extern void khugepaged_enter_vma(struct
vm_flags_t vm_flags);
extern void khugepaged_min_free_kbytes_update(void);
extern bool current_is_khugepaged(void);
-extern void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd);
+void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+ bool install_pmd);
static inline void khugepaged_fork(struct mm_struct *mm, struct mm_struct *oldmm)
{
@@ -43,7 +43,7 @@ static inline void khugepaged_enter_vma(
{
}
static inline void collapse_pte_mapped_thp(struct mm_struct *mm,
- unsigned long addr, bool install_pmd)
+ unsigned long addr, bool install_pmd)
{
}
--- a/mm/khugepaged.c~b
+++ a/mm/khugepaged.c
@@ -537,17 +537,16 @@ static void release_pte_pages(pte_t *pte
}
}
-static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
- unsigned long start_addr,
- pte_t *pte,
- struct collapse_control *cc,
- struct list_head *compound_pagelist)
+static enum scan_result __collapse_huge_page_isolate(struct vm_area_struct *vma,
+ unsigned long start_addr, pte_t *pte, struct collapse_control *cc,
+ struct list_head *compound_pagelist)
{
struct page *page = NULL;
struct folio *folio = NULL;
unsigned long addr = start_addr;
pte_t *_pte;
- int none_or_zero = 0, shared = 0, result = SCAN_FAIL, referenced = 0;
+ int none_or_zero = 0, shared = 0, referenced = 0;
+ enum scan_result result = SCAN_FAIL;
for (_pte = pte; _pte < pte + HPAGE_PMD_NR;
_pte++, addr += PAGE_SIZE) {
@@ -780,13 +779,13 @@ static void __collapse_huge_page_copy_fa
* @ptl: lock on raw pages' PTEs
* @compound_pagelist: list that stores compound pages
*/
-static int __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
+static enum scan_result __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
pmd_t *pmd, pmd_t orig_pmd, struct vm_area_struct *vma,
unsigned long address, spinlock_t *ptl,
struct list_head *compound_pagelist)
{
unsigned int i;
- int result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
/*
* Copying pages' contents is subject to memory poison at any iteration.
@@ -898,10 +897,8 @@ static int hpage_collapse_find_target_no
* Returns enum scan_result value.
*/
-static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
- bool expect_anon,
- struct vm_area_struct **vmap,
- struct collapse_control *cc)
+static enum scan_result hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
+ bool expect_anon, struct vm_area_struct **vmap, struct collapse_control *cc)
{
struct vm_area_struct *vma;
enum tva_type type = cc->is_khugepaged ? TVA_KHUGEPAGED :
@@ -930,7 +927,7 @@ static int hugepage_vma_revalidate(struc
return SCAN_SUCCEED;
}
-static inline int check_pmd_state(pmd_t *pmd)
+static inline enum scan_result check_pmd_state(pmd_t *pmd)
{
pmd_t pmde = pmdp_get_lockless(pmd);
@@ -953,9 +950,8 @@ static inline int check_pmd_state(pmd_t
return SCAN_SUCCEED;
}
-static int find_pmd_or_thp_or_none(struct mm_struct *mm,
- unsigned long address,
- pmd_t **pmd)
+static enum scan_result find_pmd_or_thp_or_none(struct mm_struct *mm,
+ unsigned long address, pmd_t **pmd)
{
*pmd = mm_find_pmd(mm, address);
if (!*pmd)
@@ -964,12 +960,11 @@ static int find_pmd_or_thp_or_none(struc
return check_pmd_state(*pmd);
}
-static int check_pmd_still_valid(struct mm_struct *mm,
- unsigned long address,
- pmd_t *pmd)
+static enum scan_result check_pmd_still_valid(struct mm_struct *mm,
+ unsigned long address, pmd_t *pmd)
{
pmd_t *new_pmd;
- int result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
+ enum scan_result result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
if (result != SCAN_SUCCEED)
return result;
@@ -985,15 +980,14 @@ static int check_pmd_still_valid(struct
* Called and returns without pte mapped or spinlocks held.
* Returns result: if not SCAN_SUCCEED, mmap_lock has been released.
*/
-static int __collapse_huge_page_swapin(struct mm_struct *mm,
- struct vm_area_struct *vma,
- unsigned long start_addr, pmd_t *pmd,
- int referenced)
+static enum scan_result __collapse_huge_page_swapin(struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long start_addr, pmd_t *pmd,
+ int referenced)
{
int swapped_in = 0;
vm_fault_t ret = 0;
unsigned long addr, end = start_addr + (HPAGE_PMD_NR * PAGE_SIZE);
- int result;
+ enum scan_result result;
pte_t *pte = NULL;
spinlock_t *ptl;
@@ -1062,8 +1056,8 @@ out:
return result;
}
-static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
- struct collapse_control *cc)
+static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
+ struct collapse_control *cc)
{
gfp_t gfp = (cc->is_khugepaged ? alloc_hugepage_khugepaged_gfpmask() :
GFP_TRANSHUGE);
@@ -1090,9 +1084,8 @@ static int alloc_charge_folio(struct fol
return SCAN_SUCCEED;
}
-static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
- int referenced, int unmapped,
- struct collapse_control *cc)
+static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long address,
+ int referenced, int unmapped, struct collapse_control *cc)
{
LIST_HEAD(compound_pagelist);
pmd_t *pmd, _pmd;
@@ -1100,7 +1093,7 @@ static int collapse_huge_page(struct mm_
pgtable_t pgtable;
struct folio *folio;
spinlock_t *pmd_ptl, *pte_ptl;
- int result = SCAN_FAIL;
+ enum scan_result result = SCAN_FAIL;
struct vm_area_struct *vma;
struct mmu_notifier_range range;
@@ -1246,15 +1239,14 @@ out_nolock:
return result;
}
-static int hpage_collapse_scan_pmd(struct mm_struct *mm,
- struct vm_area_struct *vma,
- unsigned long start_addr, bool *mmap_locked,
- struct collapse_control *cc)
+static enum scan_result hpage_collapse_scan_pmd(struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long start_addr, bool *mmap_locked,
+ struct collapse_control *cc)
{
pmd_t *pmd;
pte_t *pte, *_pte;
- int result = SCAN_FAIL, referenced = 0;
- int none_or_zero = 0, shared = 0;
+ int none_or_zero = 0, shared = 0, referenced = 0;
+ enum scan_result result = SCAN_FAIL;
struct page *page = NULL;
struct folio *folio = NULL;
unsigned long addr;
@@ -1441,8 +1433,8 @@ static void collect_mm_slot(struct mm_sl
}
/* folio must be locked, and mmap_lock must be held */
-static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
- pmd_t *pmdp, struct folio *folio, struct page *page)
+static enum scan_result set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
+ pmd_t *pmdp, struct folio *folio, struct page *page)
{
struct mm_struct *mm = vma->vm_mm;
struct vm_fault vmf = {
@@ -1477,10 +1469,11 @@ static int set_huge_pmd(struct vm_area_s
return SCAN_SUCCEED;
}
-static int try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd)
+static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+ bool install_pmd)
{
- int nr_mapped_ptes = 0, result = SCAN_FAIL;
+ enum scan_result result = SCAN_FAIL;
+ int nr_mapped_ptes = 0;
unsigned int nr_batch_ptes;
struct mmu_notifier_range range;
bool notified = false;
@@ -1712,7 +1705,7 @@ drop_folio:
* as pmd-mapped. Possibly install a huge PMD mapping the THP.
*/
void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd)
+ bool install_pmd)
{
try_collapse_pte_mapped_thp(mm, addr, install_pmd);
}
@@ -1862,9 +1855,8 @@ drop_pml:
* + unlock old pages
* + unlock and free huge page;
*/
-static int collapse_file(struct mm_struct *mm, unsigned long addr,
- struct file *file, pgoff_t start,
- struct collapse_control *cc)
+static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
+ struct file *file, pgoff_t start, struct collapse_control *cc)
{
struct address_space *mapping = file->f_mapping;
struct page *dst;
@@ -1872,7 +1864,8 @@ static int collapse_file(struct mm_struc
pgoff_t index = 0, end = start + HPAGE_PMD_NR;
LIST_HEAD(pagelist);
XA_STATE_ORDER(xas, &mapping->i_pages, start, HPAGE_PMD_ORDER);
- int nr_none = 0, result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
+ int nr_none = 0;
bool is_shmem = shmem_file(file);
VM_BUG_ON(!IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && !is_shmem);
@@ -2293,16 +2286,15 @@ out:
return result;
}
-static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
- struct file *file, pgoff_t start,
- struct collapse_control *cc)
+static enum scan_result hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
+ struct file *file, pgoff_t start, struct collapse_control *cc)
{
struct folio *folio = NULL;
struct address_space *mapping = file->f_mapping;
XA_STATE(xas, &mapping->i_pages, start);
int present, swap;
int node = NUMA_NO_NODE;
- int result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
present = 0;
swap = 0;
@@ -2400,7 +2392,7 @@ static int hpage_collapse_scan_file(stru
return result;
}
-static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
+static unsigned int khugepaged_scan_mm_slot(unsigned int pages, enum scan_result *result,
struct collapse_control *cc)
__releases(&khugepaged_mm_lock)
__acquires(&khugepaged_mm_lock)
@@ -2562,7 +2554,7 @@ static void khugepaged_do_scan(struct co
unsigned int progress = 0, pass_through_head = 0;
unsigned int pages = READ_ONCE(khugepaged_pages_to_scan);
bool wait = true;
- int result = SCAN_SUCCEED;
+ enum scan_result result = SCAN_SUCCEED;
lru_add_drain_all();
@@ -2775,7 +2767,8 @@ int madvise_collapse(struct vm_area_stru
struct collapse_control *cc;
struct mm_struct *mm = vma->vm_mm;
unsigned long hstart, hend, addr;
- int thps = 0, last_fail = SCAN_FAIL;
+ enum scan_result last_fail = SCAN_FAIL;
+ int thps = 0;
bool mmap_locked = true;
BUG_ON(vma->vm_start > start);
@@ -2796,7 +2789,7 @@ int madvise_collapse(struct vm_area_stru
hend = end & HPAGE_PMD_MASK;
for (addr = hstart; addr < hend; addr += HPAGE_PMD_SIZE) {
- int result = SCAN_FAIL;
+ enum scan_result result = SCAN_FAIL;
bool triggered_wb = false;
retry:
_
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix
2026-01-18 20:34 ` [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Andrew Morton
@ 2026-01-19 0:17 ` Zi Yan
2026-01-19 5:50 ` Garg, Shivank
1 sibling, 0 replies; 32+ messages in thread
From: Zi Yan @ 2026-01-19 0:17 UTC (permalink / raw)
To: Andrew Morton
Cc: Shivank Garg, David Hildenbrand, Lorenzo Stoakes, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, linux-mm, linux-kernel
On 18 Jan 2026, at 15:34, Andrew Morton wrote:
> On Sun, 18 Jan 2026 19:22:51 +0000 Shivank Garg <shivankg@amd.com> wrote:
>
>> This series contains several cleanups for mm/khugepaged.c to improve code
>> readability and type safety, and one functional fix to ensure
>> khugepaged_scan_mm_slot() correctly accounts for small VMAs towards
>> scan limit.
>>
>
> That's a lot of changes to a well-reviewed 24 day old patchset.
>
>>
>> v3:
>> - Fold mm-khugepaged-count-small-vmas-towards-scan-limit-fix: add comment (Lance)
>> - Remove extern and use two tabs indent (David)
>
> Are you sure? The v2->v3 diff is large. A lot of (unchangelogged)
> alterations from `int' to `enum scan_result'.
V2 has this change[1].
[1] https://lore.kernel.org/all/20251224111351.41042-12-shivankg@amd.com/
>
> It all looks pretty simple/straightforward to me but again, can
> reviewers please check this over fairly soonly, thanks.
I have reviewed it when it was out last year.
--
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix
2026-01-18 20:34 ` [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Andrew Morton
2026-01-19 0:17 ` Zi Yan
@ 2026-01-19 5:50 ` Garg, Shivank
1 sibling, 0 replies; 32+ messages in thread
From: Garg, Shivank @ 2026-01-19 5:50 UTC (permalink / raw)
To: Andrew Morton
Cc: David Hildenbrand, Lorenzo Stoakes, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, linux-mm, linux-kernel
On 1/19/2026 2:04 AM, Andrew Morton wrote:
> On Sun, 18 Jan 2026 19:22:51 +0000 Shivank Garg <shivankg@amd.com> wrote:
>
>> This series contains several cleanups for mm/khugepaged.c to improve code
>> readability and type safety, and one functional fix to ensure
>> khugepaged_scan_mm_slot() correctly accounts for small VMAs towards
>> scan limit.
>>
>
> That's a lot of changes to a well-reviewed 24 day old patchset.
>
Sincere apologies for the last minute churn.
>>
>> v3:
>> - Fold mm-khugepaged-count-small-vmas-towards-scan-limit-fix: add comment (Lance)
>> - Remove extern and use two tabs indent (David)
>
> Are you sure? The v2->v3 diff is large. A lot of (unchangelogged)
> alterations from `int' to `enum scan_result'.
>
> It all looks pretty simple/straightforward to me but again, can
> reviewers please check this over fairly soonly, thanks.
>
The diff appears large because it somehow did not capture V2 Patch 4/5.
The correct V3 vs V2 diff changes:
diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
index 37b992b22bba..d7a9053ff4fe 100644
--- a/include/linux/khugepaged.h
+++ b/include/linux/khugepaged.h
@@ -17,8 +17,8 @@ extern void khugepaged_enter_vma(struct vm_area_struct *vma,
vm_flags_t vm_flags);
extern void khugepaged_min_free_kbytes_update(void);
extern bool current_is_khugepaged(void);
-extern void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd);
+void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
+ bool install_pmd);
static inline void khugepaged_fork(struct mm_struct *mm, struct mm_struct *oldmm)
{
@@ -43,7 +43,7 @@ static inline void khugepaged_enter_vma(struct vm_area_struct *vma,
{
}
static inline void collapse_pte_mapped_thp(struct mm_struct *mm,
- unsigned long addr, bool install_pmd)
+ unsigned long addr, bool install_pmd)
{
}
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 9f790ec34400..fba6aea5bea6 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -538,10 +538,8 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte,
}
static enum scan_result __collapse_huge_page_isolate(struct vm_area_struct *vma,
- unsigned long start_addr,
- pte_t *pte,
- struct collapse_control *cc,
- struct list_head *compound_pagelist)
+ unsigned long start_addr, pte_t *pte, struct collapse_control *cc,
+ struct list_head *compound_pagelist)
{
struct page *page = NULL;
struct folio *folio = NULL;
@@ -900,8 +898,7 @@ static int hpage_collapse_find_target_node(struct collapse_control *cc)
*/
static enum scan_result hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
- bool expect_anon, struct vm_area_struct **vmap,
- struct collapse_control *cc)
+ bool expect_anon, struct vm_area_struct **vmap, struct collapse_control *cc)
{
struct vm_area_struct *vma;
enum tva_type type = cc->is_khugepaged ? TVA_KHUGEPAGED :
@@ -954,8 +951,7 @@ static inline enum scan_result check_pmd_state(pmd_t *pmd)
}
static enum scan_result find_pmd_or_thp_or_none(struct mm_struct *mm,
- unsigned long address,
- pmd_t **pmd)
+ unsigned long address, pmd_t **pmd)
{
*pmd = mm_find_pmd(mm, address);
if (!*pmd)
@@ -965,8 +961,7 @@ static enum scan_result find_pmd_or_thp_or_none(struct mm_struct *mm,
}
static enum scan_result check_pmd_still_valid(struct mm_struct *mm,
- unsigned long address,
- pmd_t *pmd)
+ unsigned long address, pmd_t *pmd)
{
pmd_t *new_pmd;
enum scan_result result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
@@ -986,9 +981,8 @@ static enum scan_result check_pmd_still_valid(struct mm_struct *mm,
* Returns result: if not SCAN_SUCCEED, mmap_lock has been released.
*/
static enum scan_result __collapse_huge_page_swapin(struct mm_struct *mm,
- struct vm_area_struct *vma,
- unsigned long start_addr, pmd_t *pmd,
- int referenced)
+ struct vm_area_struct *vma, unsigned long start_addr, pmd_t *pmd,
+ int referenced)
{
int swapped_in = 0;
vm_fault_t ret = 0;
@@ -1063,7 +1057,7 @@ static enum scan_result __collapse_huge_page_swapin(struct mm_struct *mm,
}
static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
- struct collapse_control *cc)
+ struct collapse_control *cc)
{
gfp_t gfp = (cc->is_khugepaged ? alloc_hugepage_khugepaged_gfpmask() :
GFP_TRANSHUGE);
@@ -1091,8 +1085,7 @@ static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_stru
}
static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long address,
- int referenced, int unmapped,
- struct collapse_control *cc)
+ int referenced, int unmapped, struct collapse_control *cc)
{
LIST_HEAD(compound_pagelist);
pmd_t *pmd, _pmd;
@@ -1247,9 +1240,8 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
}
static enum scan_result hpage_collapse_scan_pmd(struct mm_struct *mm,
- struct vm_area_struct *vma,
- unsigned long start_addr, bool *mmap_locked,
- struct collapse_control *cc)
+ struct vm_area_struct *vma, unsigned long start_addr, bool *mmap_locked,
+ struct collapse_control *cc)
{
pmd_t *pmd;
pte_t *pte, *_pte;
@@ -1442,7 +1434,7 @@ static void collect_mm_slot(struct mm_slot *slot)
/* folio must be locked, and mmap_lock must be held */
static enum scan_result set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
- pmd_t *pmdp, struct folio *folio, struct page *page)
+ pmd_t *pmdp, struct folio *folio, struct page *page)
{
struct mm_struct *mm = vma->vm_mm;
struct vm_fault vmf = {
@@ -1478,7 +1470,7 @@ static enum scan_result set_huge_pmd(struct vm_area_struct *vma, unsigned long a
}
static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd)
+ bool install_pmd)
{
enum scan_result result = SCAN_FAIL;
int nr_mapped_ptes = 0;
@@ -1713,7 +1705,7 @@ static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsign
* as pmd-mapped. Possibly install a huge PMD mapping the THP.
*/
void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
- bool install_pmd)
+ bool install_pmd)
{
try_collapse_pte_mapped_thp(mm, addr, install_pmd);
}
@@ -1864,8 +1856,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
* + unlock and free huge page;
*/
static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
- struct file *file, pgoff_t start,
- struct collapse_control *cc)
+ struct file *file, pgoff_t start, struct collapse_control *cc)
{
struct address_space *mapping = file->f_mapping;
struct page *dst;
@@ -2296,8 +2287,7 @@ static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
}
static enum scan_result hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
- struct file *file, pgoff_t start,
- struct collapse_control *cc)
+ struct file *file, pgoff_t start, struct collapse_control *cc)
{
struct folio *folio = NULL;
struct address_space *mapping = file->f_mapping;
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types
2026-01-18 19:22 ` [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types Shivank Garg
@ 2026-01-19 10:24 ` David Hildenbrand (Red Hat)
2026-01-22 9:19 ` Dev Jain
2026-01-22 12:14 ` Nico Pache
2 siblings, 0 replies; 32+ messages in thread
From: David Hildenbrand (Red Hat) @ 2026-01-19 10:24 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, linux-mm, linux-kernel
On 1/18/26 20:22, Shivank Garg wrote:
> Convert result variables and return types from int to enum scan_result
> throughout khugepaged code. This improves type safety and code clarity
> by making the intent explicit.
>
> No functional change.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
> ---
Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
--
Cheers
David
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label
2026-01-18 19:22 ` [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label Shivank Garg
@ 2026-01-22 7:04 ` Dev Jain
2026-01-22 11:56 ` Nico Pache
1 sibling, 0 replies; 32+ messages in thread
From: Dev Jain @ 2026-01-22 7:04 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel
On 19/01/26 12:52 am, Shivank Garg wrote:
> Replace goto skip with actual logic for better code readability.
>
> No functional change.
>
> Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
LGTM
Reviewed-by: Dev Jain <dev.jain@arm.com>
> ---
> mm/khugepaged.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 16582bdcb6ff..984294a16861 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -2442,14 +2442,15 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> break;
> }
> if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_KHUGEPAGED, PMD_ORDER)) {
> -skip:
> progress++;
> continue;
> }
> hstart = round_up(vma->vm_start, HPAGE_PMD_SIZE);
> hend = round_down(vma->vm_end, HPAGE_PMD_SIZE);
> - if (khugepaged_scan.address > hend)
> - goto skip;
> + if (khugepaged_scan.address > hend) {
> + progress++;
> + continue;
> + }
> if (khugepaged_scan.address < hstart)
> khugepaged_scan.address = hstart;
> VM_BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK);
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-18 19:22 ` [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit Shivank Garg
@ 2026-01-22 7:32 ` Dev Jain
2026-01-22 8:44 ` Lance Yang
0 siblings, 1 reply; 32+ messages in thread
From: Dev Jain @ 2026-01-22 7:32 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang
On 19/01/26 12:52 am, Shivank Garg wrote:
> The khugepaged_scan_mm_slot() uses a 'progress' counter to limit the
> amount of work performed and consists of three components:
> 1. Transitioning to a new mm (+1).
> 2. Skipping an unsuitable VMA (+1).
> 3. Scanning a PMD-sized range (+HPAGE_PMD_NR).
>
> Consider a 1MB VMA sitting between two 2MB alignment boundaries:
>
> vma1 vma2 vma3
> +----------+------+----------+
> |2M |1M |2M |
> +----------+------+----------+
> ^ ^
> start end
> ^
> hstart,hend
Won't such a VMA be skipped by thp_vma_allowable_order()? That internally
checks, apart from eligibility by sysfs, that the extent of the VMA can
map a hugepage.
>
> In this case, for vma2:
> hstart = round_up(start, HPAGE_PMD_SIZE) -> Next 2MB alignment
> hend = round_down(end, HPAGE_PMD_SIZE) -> Prev 2MB alignment
>
> Currently, since `hend <= hstart`, VMAs that are too small or unaligned
> to contain a hugepage are skipped without incrementing 'progress'.
> A process containing a large number of such small VMAs will unfairly
> consume more CPU cycles before yielding compared to a process with
> fewer, larger, or aligned VMAs.
>
> Fix this by incrementing progress when the `hend <= hstart` condition
> is met.
>
> Additionally, change 'progress' type to `unsigned int` to match both
> the 'pages' type and the function return value.
>
> Suggested-by: Wei Yang <richard.weiyang@gmail.com>
> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
> ---
>
> Incorporate comment feedback from Lance:
> https://lore.kernel.org/linux-mm/6b408736-978a-4d40-adfc-97819951c3a6@linux.dev
>
> mm/khugepaged.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 984294a16861..93ce39915f4a 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -2403,7 +2403,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> struct mm_slot *slot;
> struct mm_struct *mm;
> struct vm_area_struct *vma;
> - int progress = 0;
> + unsigned int progress = 0;
>
> VM_BUG_ON(!pages);
> lockdep_assert_held(&khugepaged_mm_lock);
> @@ -2447,7 +2447,8 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> }
> hstart = round_up(vma->vm_start, HPAGE_PMD_SIZE);
> hend = round_down(vma->vm_end, HPAGE_PMD_SIZE);
> - if (khugepaged_scan.address > hend) {
> + if (khugepaged_scan.address > hend || hend <= hstart) {
> + /* VMA already scanned or too small/unaligned for hugepage. */
> progress++;
> continue;
> }
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-22 7:32 ` Dev Jain
@ 2026-01-22 8:44 ` Lance Yang
2026-01-22 12:26 ` Garg, Shivank
0 siblings, 1 reply; 32+ messages in thread
From: Lance Yang @ 2026-01-22 8:44 UTC (permalink / raw)
To: Dev Jain, Shivank Garg
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache,
David Hildenbrand, Ryan Roberts, Barry Song, linux-mm,
linux-kernel, Wei Yang, Lorenzo Stoakes, Andrew Morton
On 2026/1/22 15:32, Dev Jain wrote:
>
> On 19/01/26 12:52 am, Shivank Garg wrote:
>> The khugepaged_scan_mm_slot() uses a 'progress' counter to limit the
>> amount of work performed and consists of three components:
>> 1. Transitioning to a new mm (+1).
>> 2. Skipping an unsuitable VMA (+1).
>> 3. Scanning a PMD-sized range (+HPAGE_PMD_NR).
>>
>> Consider a 1MB VMA sitting between two 2MB alignment boundaries:
>>
>> vma1 vma2 vma3
>> +----------+------+----------+
>> |2M |1M |2M |
>> +----------+------+----------+
>> ^ ^
>> start end
>> ^
>> hstart,hend
>
> Won't such a VMA be skipped by thp_vma_allowable_order()? That internally
> checks, apart from eligibility by sysfs, that the extent of the VMA can
> map a hugepage.
Ah, you're right!
I was worrying about a case that doesn't actually happen.
Thanks,
Lance
>
>>
>> In this case, for vma2:
>> hstart = round_up(start, HPAGE_PMD_SIZE) -> Next 2MB alignment
>> hend = round_down(end, HPAGE_PMD_SIZE) -> Prev 2MB alignment
>>
>> Currently, since `hend <= hstart`, VMAs that are too small or unaligned
>> to contain a hugepage are skipped without incrementing 'progress'.
>> A process containing a large number of such small VMAs will unfairly
>> consume more CPU cycles before yielding compared to a process with
>> fewer, larger, or aligned VMAs.
>>
>> Fix this by incrementing progress when the `hend <= hstart` condition
>> is met.
>>
>> Additionally, change 'progress' type to `unsigned int` to match both
>> the 'pages' type and the function return value.
>>
>> Suggested-by: Wei Yang <richard.weiyang@gmail.com>
>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
>> Reviewed-by: Lance Yang <lance.yang@linux.dev>
>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>> ---
>>
>> Incorporate comment feedback from Lance:
>> https://lore.kernel.org/linux-mm/6b408736-978a-4d40-adfc-97819951c3a6@linux.dev
>>
>> mm/khugepaged.c | 5 +++--
>> 1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>> index 984294a16861..93ce39915f4a 100644
>> --- a/mm/khugepaged.c
>> +++ b/mm/khugepaged.c
>> @@ -2403,7 +2403,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
>> struct mm_slot *slot;
>> struct mm_struct *mm;
>> struct vm_area_struct *vma;
>> - int progress = 0;
>> + unsigned int progress = 0;
>>
>> VM_BUG_ON(!pages);
>> lockdep_assert_held(&khugepaged_mm_lock);
>> @@ -2447,7 +2447,8 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
>> }
>> hstart = round_up(vma->vm_start, HPAGE_PMD_SIZE);
>> hend = round_down(vma->vm_end, HPAGE_PMD_SIZE);
>> - if (khugepaged_scan.address > hend) {
>> + if (khugepaged_scan.address > hend || hend <= hstart) {
>> + /* VMA already scanned or too small/unaligned for hugepage. */
>> progress++;
>> continue;
>> }
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types
2026-01-18 19:22 ` [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types Shivank Garg
2026-01-19 10:24 ` David Hildenbrand (Red Hat)
@ 2026-01-22 9:19 ` Dev Jain
2026-01-22 12:14 ` Nico Pache
2 siblings, 0 replies; 32+ messages in thread
From: Dev Jain @ 2026-01-22 9:19 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel
On 19/01/26 12:52 am, Shivank Garg wrote:
> Convert result variables and return types from int to enum scan_result
> throughout khugepaged code. This improves type safety and code clarity
> by making the intent explicit.
>
> No functional change.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
Reviewed-by: Dev Jain <dev.jain@arm.com>
> ---
> mm/khugepaged.c | 99 +++++++++++++++++++++++--------------------------
> 1 file changed, 46 insertions(+), 53 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 17f3f0043368..1667abae6d8d 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -537,17 +537,16 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte,
> }
> }
>
> -static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
> - unsigned long start_addr,
> - pte_t *pte,
> - struct collapse_control *cc,
> - struct list_head *compound_pagelist)
> +static enum scan_result __collapse_huge_page_isolate(struct vm_area_struct *vma,
> + unsigned long start_addr, pte_t *pte, struct collapse_control *cc,
> + struct list_head *compound_pagelist)
> {
> struct page *page = NULL;
> struct folio *folio = NULL;
> unsigned long addr = start_addr;
> pte_t *_pte;
> - int none_or_zero = 0, shared = 0, result = SCAN_FAIL, referenced = 0;
> + int none_or_zero = 0, shared = 0, referenced = 0;
> + enum scan_result result = SCAN_FAIL;
>
> for (_pte = pte; _pte < pte + HPAGE_PMD_NR;
> _pte++, addr += PAGE_SIZE) {
> @@ -780,13 +779,13 @@ static void __collapse_huge_page_copy_failed(pte_t *pte,
> * @ptl: lock on raw pages' PTEs
> * @compound_pagelist: list that stores compound pages
> */
> -static int __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
> +static enum scan_result __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
> pmd_t *pmd, pmd_t orig_pmd, struct vm_area_struct *vma,
> unsigned long address, spinlock_t *ptl,
> struct list_head *compound_pagelist)
> {
> unsigned int i;
> - int result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
>
> /*
> * Copying pages' contents is subject to memory poison at any iteration.
> @@ -898,10 +897,8 @@ static int hpage_collapse_find_target_node(struct collapse_control *cc)
> * Returns enum scan_result value.
> */
>
> -static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
> - bool expect_anon,
> - struct vm_area_struct **vmap,
> - struct collapse_control *cc)
> +static enum scan_result hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
> + bool expect_anon, struct vm_area_struct **vmap, struct collapse_control *cc)
> {
> struct vm_area_struct *vma;
> enum tva_type type = cc->is_khugepaged ? TVA_KHUGEPAGED :
> @@ -930,7 +927,7 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
> return SCAN_SUCCEED;
> }
>
> -static inline int check_pmd_state(pmd_t *pmd)
> +static inline enum scan_result check_pmd_state(pmd_t *pmd)
> {
> pmd_t pmde = pmdp_get_lockless(pmd);
>
> @@ -953,9 +950,8 @@ static inline int check_pmd_state(pmd_t *pmd)
> return SCAN_SUCCEED;
> }
>
> -static int find_pmd_or_thp_or_none(struct mm_struct *mm,
> - unsigned long address,
> - pmd_t **pmd)
> +static enum scan_result find_pmd_or_thp_or_none(struct mm_struct *mm,
> + unsigned long address, pmd_t **pmd)
> {
> *pmd = mm_find_pmd(mm, address);
> if (!*pmd)
> @@ -964,12 +960,11 @@ static int find_pmd_or_thp_or_none(struct mm_struct *mm,
> return check_pmd_state(*pmd);
> }
>
> -static int check_pmd_still_valid(struct mm_struct *mm,
> - unsigned long address,
> - pmd_t *pmd)
> +static enum scan_result check_pmd_still_valid(struct mm_struct *mm,
> + unsigned long address, pmd_t *pmd)
> {
> pmd_t *new_pmd;
> - int result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
> + enum scan_result result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
>
> if (result != SCAN_SUCCEED)
> return result;
> @@ -985,15 +980,14 @@ static int check_pmd_still_valid(struct mm_struct *mm,
> * Called and returns without pte mapped or spinlocks held.
> * Returns result: if not SCAN_SUCCEED, mmap_lock has been released.
> */
> -static int __collapse_huge_page_swapin(struct mm_struct *mm,
> - struct vm_area_struct *vma,
> - unsigned long start_addr, pmd_t *pmd,
> - int referenced)
> +static enum scan_result __collapse_huge_page_swapin(struct mm_struct *mm,
> + struct vm_area_struct *vma, unsigned long start_addr, pmd_t *pmd,
> + int referenced)
> {
> int swapped_in = 0;
> vm_fault_t ret = 0;
> unsigned long addr, end = start_addr + (HPAGE_PMD_NR * PAGE_SIZE);
> - int result;
> + enum scan_result result;
> pte_t *pte = NULL;
> spinlock_t *ptl;
>
> @@ -1062,8 +1056,8 @@ static int __collapse_huge_page_swapin(struct mm_struct *mm,
> return result;
> }
>
> -static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
> - struct collapse_control *cc)
> +static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
> + struct collapse_control *cc)
> {
> gfp_t gfp = (cc->is_khugepaged ? alloc_hugepage_khugepaged_gfpmask() :
> GFP_TRANSHUGE);
> @@ -1090,9 +1084,8 @@ static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
> return SCAN_SUCCEED;
> }
>
> -static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
> - int referenced, int unmapped,
> - struct collapse_control *cc)
> +static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long address,
> + int referenced, int unmapped, struct collapse_control *cc)
> {
> LIST_HEAD(compound_pagelist);
> pmd_t *pmd, _pmd;
> @@ -1100,7 +1093,7 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
> pgtable_t pgtable;
> struct folio *folio;
> spinlock_t *pmd_ptl, *pte_ptl;
> - int result = SCAN_FAIL;
> + enum scan_result result = SCAN_FAIL;
> struct vm_area_struct *vma;
> struct mmu_notifier_range range;
>
> @@ -1246,15 +1239,14 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
> return result;
> }
>
> -static int hpage_collapse_scan_pmd(struct mm_struct *mm,
> - struct vm_area_struct *vma,
> - unsigned long start_addr, bool *mmap_locked,
> - struct collapse_control *cc)
> +static enum scan_result hpage_collapse_scan_pmd(struct mm_struct *mm,
> + struct vm_area_struct *vma, unsigned long start_addr, bool *mmap_locked,
> + struct collapse_control *cc)
> {
> pmd_t *pmd;
> pte_t *pte, *_pte;
> - int result = SCAN_FAIL, referenced = 0;
> - int none_or_zero = 0, shared = 0;
> + int none_or_zero = 0, shared = 0, referenced = 0;
> + enum scan_result result = SCAN_FAIL;
> struct page *page = NULL;
> struct folio *folio = NULL;
> unsigned long addr;
> @@ -1441,8 +1433,8 @@ static void collect_mm_slot(struct mm_slot *slot)
> }
>
> /* folio must be locked, and mmap_lock must be held */
> -static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> - pmd_t *pmdp, struct folio *folio, struct page *page)
> +static enum scan_result set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> + pmd_t *pmdp, struct folio *folio, struct page *page)
> {
> struct mm_struct *mm = vma->vm_mm;
> struct vm_fault vmf = {
> @@ -1477,10 +1469,11 @@ static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> return SCAN_SUCCEED;
> }
>
> -static int try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> +static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> bool install_pmd)
> {
> - int nr_mapped_ptes = 0, result = SCAN_FAIL;
> + enum scan_result result = SCAN_FAIL;
> + int nr_mapped_ptes = 0;
> unsigned int nr_batch_ptes;
> struct mmu_notifier_range range;
> bool notified = false;
> @@ -1862,9 +1855,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> * + unlock old pages
> * + unlock and free huge page;
> */
> -static int collapse_file(struct mm_struct *mm, unsigned long addr,
> - struct file *file, pgoff_t start,
> - struct collapse_control *cc)
> +static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
> + struct file *file, pgoff_t start, struct collapse_control *cc)
> {
> struct address_space *mapping = file->f_mapping;
> struct page *dst;
> @@ -1872,7 +1864,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> pgoff_t index = 0, end = start + HPAGE_PMD_NR;
> LIST_HEAD(pagelist);
> XA_STATE_ORDER(xas, &mapping->i_pages, start, HPAGE_PMD_ORDER);
> - int nr_none = 0, result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
> + int nr_none = 0;
> bool is_shmem = shmem_file(file);
>
> VM_BUG_ON(!IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && !is_shmem);
> @@ -2293,16 +2286,15 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> return result;
> }
>
> -static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
> - struct file *file, pgoff_t start,
> - struct collapse_control *cc)
> +static enum scan_result hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
> + struct file *file, pgoff_t start, struct collapse_control *cc)
> {
> struct folio *folio = NULL;
> struct address_space *mapping = file->f_mapping;
> XA_STATE(xas, &mapping->i_pages, start);
> int present, swap;
> int node = NUMA_NO_NODE;
> - int result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
>
> present = 0;
> swap = 0;
> @@ -2400,7 +2392,7 @@ static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
> return result;
> }
>
> -static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> +static unsigned int khugepaged_scan_mm_slot(unsigned int pages, enum scan_result *result,
> struct collapse_control *cc)
> __releases(&khugepaged_mm_lock)
> __acquires(&khugepaged_mm_lock)
> @@ -2562,7 +2554,7 @@ static void khugepaged_do_scan(struct collapse_control *cc)
> unsigned int progress = 0, pass_through_head = 0;
> unsigned int pages = READ_ONCE(khugepaged_pages_to_scan);
> bool wait = true;
> - int result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
>
> lru_add_drain_all();
>
> @@ -2775,7 +2767,8 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
> struct collapse_control *cc;
> struct mm_struct *mm = vma->vm_mm;
> unsigned long hstart, hend, addr;
> - int thps = 0, last_fail = SCAN_FAIL;
> + enum scan_result last_fail = SCAN_FAIL;
> + int thps = 0;
> bool mmap_locked = true;
>
> BUG_ON(vma->vm_start > start);
> @@ -2796,7 +2789,7 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
> hend = end & HPAGE_PMD_MASK;
>
> for (addr = hstart; addr < hend; addr += HPAGE_PMD_SIZE) {
> - int result = SCAN_FAIL;
> + enum scan_result result = SCAN_FAIL;
> bool triggered_wb = false;
>
> retry:
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-18 19:23 ` [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static Shivank Garg
@ 2026-01-22 9:28 ` Dev Jain
2026-01-23 7:48 ` Dev Jain
0 siblings, 1 reply; 32+ messages in thread
From: Dev Jain @ 2026-01-22 9:28 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On 19/01/26 12:53 am, Shivank Garg wrote:
> The global variable 'khugepaged_collapse_control' is not used outside of
> mm/khugepaged.c. Make it static to limit its scope.
>
> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
> ---
> mm/khugepaged.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 1667abae6d8d..fba6aea5bea6 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
> remove_wait_queue(&khugepaged_wait, &wait);
> }
>
> -struct collapse_control khugepaged_collapse_control = {
> +static struct collapse_control khugepaged_collapse_control = {
> .is_khugepaged = true,
> };
>
Will it not be better to just remove this variable? In madvise_collapse,
we defined cc as a local variable and set .is_khugepaged = false. The
same can be done in int khugepaged() - define a local variable and set
.is_khugepaged = true.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label
2026-01-18 19:22 ` [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label Shivank Garg
2026-01-22 7:04 ` Dev Jain
@ 2026-01-22 11:56 ` Nico Pache
1 sibling, 0 replies; 32+ messages in thread
From: Nico Pache @ 2026-01-22 11:56 UTC (permalink / raw)
To: Shivank Garg
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Zi Yan,
Baolin Wang, Liam R . Howlett, Ryan Roberts, Dev Jain,
Barry Song, Lance Yang, linux-mm, linux-kernel
On Sun, Jan 18, 2026 at 12:26 PM Shivank Garg <shivankg@amd.com> wrote:
>
> Replace goto skip with actual logic for better code readability.
>
> No functional change.
>
> Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
Recently I did a round of testing for khugepaged with regards to my
mTHP changes. This series was part of that testing. Thanks for the
cleanups!
Tested-by: Nico Pache <npache@redhat.com>
Reviewed-by: Nico Pache <npache@redhat.com>
> ---
> mm/khugepaged.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 16582bdcb6ff..984294a16861 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -2442,14 +2442,15 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> break;
> }
> if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_KHUGEPAGED, PMD_ORDER)) {
> -skip:
> progress++;
> continue;
> }
> hstart = round_up(vma->vm_start, HPAGE_PMD_SIZE);
> hend = round_down(vma->vm_end, HPAGE_PMD_SIZE);
> - if (khugepaged_scan.address > hend)
> - goto skip;
> + if (khugepaged_scan.address > hend) {
> + progress++;
> + continue;
> + }
> if (khugepaged_scan.address < hstart)
> khugepaged_scan.address = hstart;
> VM_BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK);
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types
2026-01-18 19:22 ` [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types Shivank Garg
2026-01-19 10:24 ` David Hildenbrand (Red Hat)
2026-01-22 9:19 ` Dev Jain
@ 2026-01-22 12:14 ` Nico Pache
2 siblings, 0 replies; 32+ messages in thread
From: Nico Pache @ 2026-01-22 12:14 UTC (permalink / raw)
To: Shivank Garg
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Zi Yan,
Baolin Wang, Liam R . Howlett, Ryan Roberts, Dev Jain,
Barry Song, Lance Yang, linux-mm, linux-kernel
On Sun, Jan 18, 2026 at 12:31 PM Shivank Garg <shivankg@amd.com> wrote:
>
> Convert result variables and return types from int to enum scan_result
> throughout khugepaged code. This improves type safety and code clarity
> by making the intent explicit.
>
> No functional change.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
LGTM!
Tested-by: Nico Pache <npache@redhat.com>
Reviewed-by: Nico Pache <npache@redhat.com>
> ---
> mm/khugepaged.c | 99 +++++++++++++++++++++++--------------------------
> 1 file changed, 46 insertions(+), 53 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 17f3f0043368..1667abae6d8d 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -537,17 +537,16 @@ static void release_pte_pages(pte_t *pte, pte_t *_pte,
> }
> }
>
> -static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
> - unsigned long start_addr,
> - pte_t *pte,
> - struct collapse_control *cc,
> - struct list_head *compound_pagelist)
> +static enum scan_result __collapse_huge_page_isolate(struct vm_area_struct *vma,
> + unsigned long start_addr, pte_t *pte, struct collapse_control *cc,
> + struct list_head *compound_pagelist)
> {
> struct page *page = NULL;
> struct folio *folio = NULL;
> unsigned long addr = start_addr;
> pte_t *_pte;
> - int none_or_zero = 0, shared = 0, result = SCAN_FAIL, referenced = 0;
> + int none_or_zero = 0, shared = 0, referenced = 0;
> + enum scan_result result = SCAN_FAIL;
>
> for (_pte = pte; _pte < pte + HPAGE_PMD_NR;
> _pte++, addr += PAGE_SIZE) {
> @@ -780,13 +779,13 @@ static void __collapse_huge_page_copy_failed(pte_t *pte,
> * @ptl: lock on raw pages' PTEs
> * @compound_pagelist: list that stores compound pages
> */
> -static int __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
> +static enum scan_result __collapse_huge_page_copy(pte_t *pte, struct folio *folio,
> pmd_t *pmd, pmd_t orig_pmd, struct vm_area_struct *vma,
> unsigned long address, spinlock_t *ptl,
> struct list_head *compound_pagelist)
> {
> unsigned int i;
> - int result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
>
> /*
> * Copying pages' contents is subject to memory poison at any iteration.
> @@ -898,10 +897,8 @@ static int hpage_collapse_find_target_node(struct collapse_control *cc)
> * Returns enum scan_result value.
> */
>
> -static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
> - bool expect_anon,
> - struct vm_area_struct **vmap,
> - struct collapse_control *cc)
> +static enum scan_result hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
> + bool expect_anon, struct vm_area_struct **vmap, struct collapse_control *cc)
> {
> struct vm_area_struct *vma;
> enum tva_type type = cc->is_khugepaged ? TVA_KHUGEPAGED :
> @@ -930,7 +927,7 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address,
> return SCAN_SUCCEED;
> }
>
> -static inline int check_pmd_state(pmd_t *pmd)
> +static inline enum scan_result check_pmd_state(pmd_t *pmd)
> {
> pmd_t pmde = pmdp_get_lockless(pmd);
>
> @@ -953,9 +950,8 @@ static inline int check_pmd_state(pmd_t *pmd)
> return SCAN_SUCCEED;
> }
>
> -static int find_pmd_or_thp_or_none(struct mm_struct *mm,
> - unsigned long address,
> - pmd_t **pmd)
> +static enum scan_result find_pmd_or_thp_or_none(struct mm_struct *mm,
> + unsigned long address, pmd_t **pmd)
> {
> *pmd = mm_find_pmd(mm, address);
> if (!*pmd)
> @@ -964,12 +960,11 @@ static int find_pmd_or_thp_or_none(struct mm_struct *mm,
> return check_pmd_state(*pmd);
> }
>
> -static int check_pmd_still_valid(struct mm_struct *mm,
> - unsigned long address,
> - pmd_t *pmd)
> +static enum scan_result check_pmd_still_valid(struct mm_struct *mm,
> + unsigned long address, pmd_t *pmd)
> {
> pmd_t *new_pmd;
> - int result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
> + enum scan_result result = find_pmd_or_thp_or_none(mm, address, &new_pmd);
>
> if (result != SCAN_SUCCEED)
> return result;
> @@ -985,15 +980,14 @@ static int check_pmd_still_valid(struct mm_struct *mm,
> * Called and returns without pte mapped or spinlocks held.
> * Returns result: if not SCAN_SUCCEED, mmap_lock has been released.
> */
> -static int __collapse_huge_page_swapin(struct mm_struct *mm,
> - struct vm_area_struct *vma,
> - unsigned long start_addr, pmd_t *pmd,
> - int referenced)
> +static enum scan_result __collapse_huge_page_swapin(struct mm_struct *mm,
> + struct vm_area_struct *vma, unsigned long start_addr, pmd_t *pmd,
> + int referenced)
> {
> int swapped_in = 0;
> vm_fault_t ret = 0;
> unsigned long addr, end = start_addr + (HPAGE_PMD_NR * PAGE_SIZE);
> - int result;
> + enum scan_result result;
> pte_t *pte = NULL;
> spinlock_t *ptl;
>
> @@ -1062,8 +1056,8 @@ static int __collapse_huge_page_swapin(struct mm_struct *mm,
> return result;
> }
>
> -static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
> - struct collapse_control *cc)
> +static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
> + struct collapse_control *cc)
> {
> gfp_t gfp = (cc->is_khugepaged ? alloc_hugepage_khugepaged_gfpmask() :
> GFP_TRANSHUGE);
> @@ -1090,9 +1084,8 @@ static int alloc_charge_folio(struct folio **foliop, struct mm_struct *mm,
> return SCAN_SUCCEED;
> }
>
> -static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
> - int referenced, int unmapped,
> - struct collapse_control *cc)
> +static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long address,
> + int referenced, int unmapped, struct collapse_control *cc)
> {
> LIST_HEAD(compound_pagelist);
> pmd_t *pmd, _pmd;
> @@ -1100,7 +1093,7 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
> pgtable_t pgtable;
> struct folio *folio;
> spinlock_t *pmd_ptl, *pte_ptl;
> - int result = SCAN_FAIL;
> + enum scan_result result = SCAN_FAIL;
> struct vm_area_struct *vma;
> struct mmu_notifier_range range;
>
> @@ -1246,15 +1239,14 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
> return result;
> }
>
> -static int hpage_collapse_scan_pmd(struct mm_struct *mm,
> - struct vm_area_struct *vma,
> - unsigned long start_addr, bool *mmap_locked,
> - struct collapse_control *cc)
> +static enum scan_result hpage_collapse_scan_pmd(struct mm_struct *mm,
> + struct vm_area_struct *vma, unsigned long start_addr, bool *mmap_locked,
> + struct collapse_control *cc)
> {
> pmd_t *pmd;
> pte_t *pte, *_pte;
> - int result = SCAN_FAIL, referenced = 0;
> - int none_or_zero = 0, shared = 0;
> + int none_or_zero = 0, shared = 0, referenced = 0;
> + enum scan_result result = SCAN_FAIL;
> struct page *page = NULL;
> struct folio *folio = NULL;
> unsigned long addr;
> @@ -1441,8 +1433,8 @@ static void collect_mm_slot(struct mm_slot *slot)
> }
>
> /* folio must be locked, and mmap_lock must be held */
> -static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> - pmd_t *pmdp, struct folio *folio, struct page *page)
> +static enum scan_result set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> + pmd_t *pmdp, struct folio *folio, struct page *page)
> {
> struct mm_struct *mm = vma->vm_mm;
> struct vm_fault vmf = {
> @@ -1477,10 +1469,11 @@ static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> return SCAN_SUCCEED;
> }
>
> -static int try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> +static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> bool install_pmd)
> {
> - int nr_mapped_ptes = 0, result = SCAN_FAIL;
> + enum scan_result result = SCAN_FAIL;
> + int nr_mapped_ptes = 0;
> unsigned int nr_batch_ptes;
> struct mmu_notifier_range range;
> bool notified = false;
> @@ -1862,9 +1855,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> * + unlock old pages
> * + unlock and free huge page;
> */
> -static int collapse_file(struct mm_struct *mm, unsigned long addr,
> - struct file *file, pgoff_t start,
> - struct collapse_control *cc)
> +static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
> + struct file *file, pgoff_t start, struct collapse_control *cc)
> {
> struct address_space *mapping = file->f_mapping;
> struct page *dst;
> @@ -1872,7 +1864,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> pgoff_t index = 0, end = start + HPAGE_PMD_NR;
> LIST_HEAD(pagelist);
> XA_STATE_ORDER(xas, &mapping->i_pages, start, HPAGE_PMD_ORDER);
> - int nr_none = 0, result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
> + int nr_none = 0;
> bool is_shmem = shmem_file(file);
>
> VM_BUG_ON(!IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) && !is_shmem);
> @@ -2293,16 +2286,15 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
> return result;
> }
>
> -static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
> - struct file *file, pgoff_t start,
> - struct collapse_control *cc)
> +static enum scan_result hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
> + struct file *file, pgoff_t start, struct collapse_control *cc)
> {
> struct folio *folio = NULL;
> struct address_space *mapping = file->f_mapping;
> XA_STATE(xas, &mapping->i_pages, start);
> int present, swap;
> int node = NUMA_NO_NODE;
> - int result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
>
> present = 0;
> swap = 0;
> @@ -2400,7 +2392,7 @@ static int hpage_collapse_scan_file(struct mm_struct *mm, unsigned long addr,
> return result;
> }
>
> -static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> +static unsigned int khugepaged_scan_mm_slot(unsigned int pages, enum scan_result *result,
> struct collapse_control *cc)
> __releases(&khugepaged_mm_lock)
> __acquires(&khugepaged_mm_lock)
> @@ -2562,7 +2554,7 @@ static void khugepaged_do_scan(struct collapse_control *cc)
> unsigned int progress = 0, pass_through_head = 0;
> unsigned int pages = READ_ONCE(khugepaged_pages_to_scan);
> bool wait = true;
> - int result = SCAN_SUCCEED;
> + enum scan_result result = SCAN_SUCCEED;
>
> lru_add_drain_all();
>
> @@ -2775,7 +2767,8 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
> struct collapse_control *cc;
> struct mm_struct *mm = vma->vm_mm;
> unsigned long hstart, hend, addr;
> - int thps = 0, last_fail = SCAN_FAIL;
> + enum scan_result last_fail = SCAN_FAIL;
> + int thps = 0;
> bool mmap_locked = true;
>
> BUG_ON(vma->vm_start > start);
> @@ -2796,7 +2789,7 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
> hend = end & HPAGE_PMD_MASK;
>
> for (addr = hstart; addr < hend; addr += HPAGE_PMD_SIZE) {
> - int result = SCAN_FAIL;
> + enum scan_result result = SCAN_FAIL;
> bool triggered_wb = false;
>
> retry:
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 3/5] mm/khugepaged: change collapse_pte_mapped_thp() to return void
2026-01-18 19:22 ` [PATCH V3 3/5] mm/khugepaged: change collapse_pte_mapped_thp() to return void Shivank Garg
@ 2026-01-22 12:17 ` Nico Pache
0 siblings, 0 replies; 32+ messages in thread
From: Nico Pache @ 2026-01-22 12:17 UTC (permalink / raw)
To: Shivank Garg
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Zi Yan,
Baolin Wang, Liam R . Howlett, Ryan Roberts, Dev Jain,
Barry Song, Lance Yang, linux-mm, linux-kernel
On Sun, Jan 18, 2026 at 12:28 PM Shivank Garg <shivankg@amd.com> wrote:
>
> The only external caller of collapse_pte_mapped_thp() is uprobe, which
> ignores the return value. Change the external API to return void to
> simplify the interface.
>
> Introduce try_collapse_pte_mapped_thp() for internal use that preserves
> the return value. This prepares for future patch that will convert
> the return type to use enum scan_result.
>
> Suggested-by: David Hildenbrand (Red Hat) <david@kernel.org>
> Acked-by: Lance Yang <lance.yang@linux.dev>
> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
LGTM!
Tested-by: Nico Pache <npache@redhat.com>
Reviewed-by: Nico Pache <npache@redhat.com>
> ---
>
> include/linux/khugepaged.h | 9 ++++-----
> mm/khugepaged.c | 40 ++++++++++++++++++++++----------------
> 2 files changed, 27 insertions(+), 22 deletions(-)
>
> diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
> index eb1946a70cff..d7a9053ff4fe 100644
> --- a/include/linux/khugepaged.h
> +++ b/include/linux/khugepaged.h
> @@ -17,8 +17,8 @@ extern void khugepaged_enter_vma(struct vm_area_struct *vma,
> vm_flags_t vm_flags);
> extern void khugepaged_min_free_kbytes_update(void);
> extern bool current_is_khugepaged(void);
> -extern int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> - bool install_pmd);
> +void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> + bool install_pmd);
>
> static inline void khugepaged_fork(struct mm_struct *mm, struct mm_struct *oldmm)
> {
> @@ -42,10 +42,9 @@ static inline void khugepaged_enter_vma(struct vm_area_struct *vma,
> vm_flags_t vm_flags)
> {
> }
> -static inline int collapse_pte_mapped_thp(struct mm_struct *mm,
> - unsigned long addr, bool install_pmd)
> +static inline void collapse_pte_mapped_thp(struct mm_struct *mm,
> + unsigned long addr, bool install_pmd)
> {
> - return 0;
> }
>
> static inline void khugepaged_min_free_kbytes_update(void)
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 93ce39915f4a..17f3f0043368 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -1477,20 +1477,8 @@ static int set_huge_pmd(struct vm_area_struct *vma, unsigned long addr,
> return SCAN_SUCCEED;
> }
>
> -/**
> - * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at
> - * address haddr.
> - *
> - * @mm: process address space where collapse happens
> - * @addr: THP collapse address
> - * @install_pmd: If a huge PMD should be installed
> - *
> - * This function checks whether all the PTEs in the PMD are pointing to the
> - * right THP. If so, retract the page table so the THP can refault in with
> - * as pmd-mapped. Possibly install a huge PMD mapping the THP.
> - */
> -int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> - bool install_pmd)
> +static int try_collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> + bool install_pmd)
> {
> int nr_mapped_ptes = 0, result = SCAN_FAIL;
> unsigned int nr_batch_ptes;
> @@ -1711,6 +1699,24 @@ int collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> return result;
> }
>
> +/**
> + * collapse_pte_mapped_thp - Try to collapse a pte-mapped THP for mm at
> + * address haddr.
> + *
> + * @mm: process address space where collapse happens
> + * @addr: THP collapse address
> + * @install_pmd: If a huge PMD should be installed
> + *
> + * This function checks whether all the PTEs in the PMD are pointing to the
> + * right THP. If so, retract the page table so the THP can refault in with
> + * as pmd-mapped. Possibly install a huge PMD mapping the THP.
> + */
> +void collapse_pte_mapped_thp(struct mm_struct *mm, unsigned long addr,
> + bool install_pmd)
> +{
> + try_collapse_pte_mapped_thp(mm, addr, install_pmd);
> +}
> +
> /* Can we retract page tables for this file-backed VMA? */
> static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)
> {
> @@ -2227,7 +2233,7 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
>
> /*
> * Remove pte page tables, so we can re-fault the page as huge.
> - * If MADV_COLLAPSE, adjust result to call collapse_pte_mapped_thp().
> + * If MADV_COLLAPSE, adjust result to call try_collapse_pte_mapped_thp().
> */
> retract_page_tables(mapping, start);
> if (cc && !cc->is_khugepaged)
> @@ -2480,7 +2486,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
> mmap_read_lock(mm);
> if (hpage_collapse_test_exit_or_disable(mm))
> goto breakouterloop;
> - *result = collapse_pte_mapped_thp(mm,
> + *result = try_collapse_pte_mapped_thp(mm,
> khugepaged_scan.address, false);
> if (*result == SCAN_PMD_MAPPED)
> *result = SCAN_SUCCEED;
> @@ -2845,7 +2851,7 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start,
> case SCAN_PTE_MAPPED_HUGEPAGE:
> BUG_ON(mmap_locked);
> mmap_read_lock(mm);
> - result = collapse_pte_mapped_thp(mm, addr, true);
> + result = try_collapse_pte_mapped_thp(mm, addr, true);
> mmap_read_unlock(mm);
> goto handle_result;
> /* Whitelisted set of results where continuing OK */
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-22 8:44 ` Lance Yang
@ 2026-01-22 12:26 ` Garg, Shivank
2026-01-23 10:42 ` Garg, Shivank
0 siblings, 1 reply; 32+ messages in thread
From: Garg, Shivank @ 2026-01-22 12:26 UTC (permalink / raw)
To: Lance Yang, Dev Jain
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache,
David Hildenbrand, Ryan Roberts, Barry Song, linux-mm,
linux-kernel, Wei Yang, Lorenzo Stoakes, Andrew Morton
On 1/22/2026 2:14 PM, Lance Yang wrote:
>
>
> On 2026/1/22 15:32, Dev Jain wrote:
>>
>> On 19/01/26 12:52 am, Shivank Garg wrote:
>>> The khugepaged_scan_mm_slot() uses a 'progress' counter to limit the
>>> amount of work performed and consists of three components:
>>> 1. Transitioning to a new mm (+1).
>>> 2. Skipping an unsuitable VMA (+1).
>>> 3. Scanning a PMD-sized range (+HPAGE_PMD_NR).
>>>
>>> Consider a 1MB VMA sitting between two 2MB alignment boundaries:
>>>
>>> vma1 vma2 vma3
>>> +----------+------+----------+
>>> |2M |1M |2M |
>>> +----------+------+----------+
>>> ^ ^
>>> start end
>>> ^
>>> hstart,hend
>>
>> Won't such a VMA be skipped by thp_vma_allowable_order()? That internally
>> checks, apart from eligibility by sysfs, that the extent of the VMA can
>> map a hugepage.
>
> Ah, you're right!
>
> I was worrying about a case that doesn't actually happen.
>
You're right, thp_vma_allowable_order() is taking care of this, making
hend <= hstart check redundant.
Thank you for catching this.
I'll drop this change and send revision keeping only the unsigned int type
change for 'progress'.
Thanks,
Shivank
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-22 9:28 ` Dev Jain
@ 2026-01-23 7:48 ` Dev Jain
2026-01-23 9:33 ` Garg, Shivank
0 siblings, 1 reply; 32+ messages in thread
From: Dev Jain @ 2026-01-23 7:48 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On 22/01/26 2:58 pm, Dev Jain wrote:
> On 19/01/26 12:53 am, Shivank Garg wrote:
>> The global variable 'khugepaged_collapse_control' is not used outside of
>> mm/khugepaged.c. Make it static to limit its scope.
>>
>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
>> Reviewed-by: Zi Yan <ziy@nvidia.com>
>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>> ---
>> mm/khugepaged.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>> index 1667abae6d8d..fba6aea5bea6 100644
>> --- a/mm/khugepaged.c
>> +++ b/mm/khugepaged.c
>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
>> remove_wait_queue(&khugepaged_wait, &wait);
>> }
>>
>> -struct collapse_control khugepaged_collapse_control = {
>> +static struct collapse_control khugepaged_collapse_control = {
>> .is_khugepaged = true,
>> };
>>
> Will it not be better to just remove this variable? In madvise_collapse,
> we defined cc as a local variable and set .is_khugepaged = false. The
> same can be done in int khugepaged() - define a local variable and set
> .is_khugepaged = true.
Since this patch has been stabilized already by 4 R-bs, it may be a headache
to now remove this, we can do my suggestion later.
Reviewed-by: Dev Jain <dev.jain@arm.com>
>
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-23 7:48 ` Dev Jain
@ 2026-01-23 9:33 ` Garg, Shivank
2026-01-24 1:21 ` Andrew Morton
2026-01-24 9:01 ` Lorenzo Stoakes
0 siblings, 2 replies; 32+ messages in thread
From: Garg, Shivank @ 2026-01-23 9:33 UTC (permalink / raw)
To: Dev Jain, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On 1/23/2026 1:18 PM, Dev Jain wrote:
>
> On 22/01/26 2:58 pm, Dev Jain wrote:
>> On 19/01/26 12:53 am, Shivank Garg wrote:
>>> The global variable 'khugepaged_collapse_control' is not used outside of
>>> mm/khugepaged.c. Make it static to limit its scope.
>>>
>>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
>>> Reviewed-by: Zi Yan <ziy@nvidia.com>
>>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
>>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>>> ---
>>> mm/khugepaged.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>> index 1667abae6d8d..fba6aea5bea6 100644
>>> --- a/mm/khugepaged.c
>>> +++ b/mm/khugepaged.c
>>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
>>> remove_wait_queue(&khugepaged_wait, &wait);
>>> }
>>>
>>> -struct collapse_control khugepaged_collapse_control = {
>>> +static struct collapse_control khugepaged_collapse_control = {
>>> .is_khugepaged = true,
>>> };
>>>
>> Will it not be better to just remove this variable? In madvise_collapse,
>> we defined cc as a local variable and set .is_khugepaged = false. The
>> same can be done in int khugepaged() - define a local variable and set
>> .is_khugepaged = true.
>
> Since this patch has been stabilized already by 4 R-bs, it may be a headache
> to now remove this, we can do my suggestion later.
>
> Reviewed-by: Dev Jain <dev.jain@arm.com>
>
>>
>>
Thank you Dev for the feedback and review.
I've attached the patch implementing your suggestion and sending this as a separate
follow-up to avoid disrupting the current series.
I’m happy to queue it for next cycle or if it’s acceptable now, please take it.
Thanks for the suggestion!
Regards,
Shivank
---
From: Shivank Garg <shivankg@amd.com>
Date: Thu, 22 Jan 2026 12:36:28 +0000
Subject: [PATCH] mm/khugepaged: convert khugepaged_collapse_control to local
variable in khugepaged()
Make khugepaged_collapse_control a local variable in khugepaged() instead
of static global, consistent with how madvise_collapse() handles its
collapse_control. Static storage is unnecessary here as node_load and
alloc_nmask are reset per-VMA during scanning.
No functional change.
Suggested-by: Dev Jain <dev.jain@arm.com>
Signed-off-by: Shivank Garg <shivankg@amd.com>
---
mm/khugepaged.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 9f790ec34400..c18d2ce639b1 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
remove_wait_queue(&khugepaged_wait, &wait);
}
-static struct collapse_control khugepaged_collapse_control = {
- .is_khugepaged = true,
-};
-
static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
{
int i;
@@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
static int khugepaged(void *none)
{
+ struct collapse_control cc = {
+ .is_khugepaged = true,
+ };
struct mm_slot *slot;
set_freezable();
set_user_nice(current, MAX_NICE);
while (!kthread_should_stop()) {
- khugepaged_do_scan(&khugepaged_collapse_control);
+ khugepaged_do_scan(&cc);
khugepaged_wait_work();
}
--
2.43.0
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-22 12:26 ` Garg, Shivank
@ 2026-01-23 10:42 ` Garg, Shivank
2026-01-23 15:37 ` Andrew Morton
0 siblings, 1 reply; 32+ messages in thread
From: Garg, Shivank @ 2026-01-23 10:42 UTC (permalink / raw)
To: Andrew Morton
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache,
David Hildenbrand, Ryan Roberts, Barry Song, linux-mm,
linux-kernel, Wei Yang, Lorenzo Stoakes
On 1/22/2026 5:56 PM, Garg, Shivank wrote:
>
>
> On 1/22/2026 2:14 PM, Lance Yang wrote:
>>
>>
>> On 2026/1/22 15:32, Dev Jain wrote:
>>>
>>> On 19/01/26 12:52 am, Shivank Garg wrote:
>>>> The khugepaged_scan_mm_slot() uses a 'progress' counter to limit the
>>>> amount of work performed and consists of three components:
>>>> 1. Transitioning to a new mm (+1).
>>>> 2. Skipping an unsuitable VMA (+1).
>>>> 3. Scanning a PMD-sized range (+HPAGE_PMD_NR).
>>>>
>>>> Consider a 1MB VMA sitting between two 2MB alignment boundaries:
>>>>
>>>> vma1 vma2 vma3
>>>> +----------+------+----------+
>>>> |2M |1M |2M |
>>>> +----------+------+----------+
>>>> ^ ^
>>>> start end
>>>> ^
>>>> hstart,hend
>>>
>>> Won't such a VMA be skipped by thp_vma_allowable_order()? That internally
>>> checks, apart from eligibility by sysfs, that the extent of the VMA can
>>> map a hugepage.
>>
>> Ah, you're right!
>>
>> I was worrying about a case that doesn't actually happen.
>>
> You're right, thp_vma_allowable_order() is taking care of this, making
> hend <= hstart check redundant.
>
> Thank you for catching this.
>
> I'll drop this change and send revision keeping only the unsigned int type
> change for 'progress'.
>
Hi Andrew,
Please drop this patch.
As Dev and Lance noted that the hend <= hstart handling check is redundant.
The 'progress' variable to unsigned int is not critical either.
Other patches from series remain unchanged.
Sorry for the noise, and thanks.
Regards,
Shivank
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-23 10:42 ` Garg, Shivank
@ 2026-01-23 15:37 ` Andrew Morton
2026-01-23 20:07 ` Garg, Shivank
0 siblings, 1 reply; 32+ messages in thread
From: Andrew Morton @ 2026-01-23 15:37 UTC (permalink / raw)
To: Garg, Shivank
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache,
David Hildenbrand, Ryan Roberts, Barry Song, linux-mm,
linux-kernel, Wei Yang, Lorenzo Stoakes
On Fri, 23 Jan 2026 16:12:07 +0530 "Garg, Shivank" <shivankg@amd.com> wrote:
> >> I was worrying about a case that doesn't actually happen.
> >>
> > You're right, thp_vma_allowable_order() is taking care of this, making
> > hend <= hstart check redundant.
> >
> > Thank you for catching this.
> >
> > I'll drop this change and send revision keeping only the unsigned int type
> > change for 'progress'.
> >
>
> Hi Andrew,
>
> Please drop this patch.
thud.
> As Dev and Lance noted that the hend <= hstart handling check is redundant.
>
> The 'progress' variable to unsigned int is not critical either.
OK.
Were you thinking of adopting Dev's suggestion?
https://lkml.kernel.org/r/6486c6dd-2702-4a4d-9662-09639532ce6f@arm.com.
If so, let's defer until the next cycle, please. Now is the time to be
focusing on stabilization, test, finishing up review, etc.
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit
2026-01-23 15:37 ` Andrew Morton
@ 2026-01-23 20:07 ` Garg, Shivank
0 siblings, 0 replies; 32+ messages in thread
From: Garg, Shivank @ 2026-01-23 20:07 UTC (permalink / raw)
To: Andrew Morton
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache,
David Hildenbrand, Ryan Roberts, Barry Song, linux-mm,
linux-kernel, Wei Yang, Lorenzo Stoakes
On 1/23/2026 9:07 PM, Andrew Morton wrote:
> On Fri, 23 Jan 2026 16:12:07 +0530 "Garg, Shivank" <shivankg@amd.com> wrote:
>
>>>> I was worrying about a case that doesn't actually happen.
>>>>
>>> You're right, thp_vma_allowable_order() is taking care of this, making
>>> hend <= hstart check redundant.
>>>
>>> Thank you for catching this.
>>>
>>> I'll drop this change and send revision keeping only the unsigned int type
>>> change for 'progress'.
>>>
>>
>> Hi Andrew,
>>
>> Please drop this patch.
>
> thud.
>
>> As Dev and Lance noted that the hend <= hstart handling check is redundant.
>>
>> The 'progress' variable to unsigned int is not critical either.
>
> OK.
>
> Were you thinking of adopting Dev's suggestion?
> https://lkml.kernel.org/r/6486c6dd-2702-4a4d-9662-09639532ce6f@arm.com.
>
> If so, let's defer until the next cycle, please. Now is the time to be
> focusing on stabilization, test, finishing up review, etc.
>
Thanks Andrew, understood. I'll defer Dev's suggestion to next cycle.
Thanks for the guidance. :)
Best Regards,
Shivank
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-23 9:33 ` Garg, Shivank
@ 2026-01-24 1:21 ` Andrew Morton
2026-01-24 3:02 ` Andrew Morton
2026-01-24 9:01 ` Lorenzo Stoakes
1 sibling, 1 reply; 32+ messages in thread
From: Andrew Morton @ 2026-01-24 1:21 UTC (permalink / raw)
To: Garg, Shivank
Cc: Dev Jain, David Hildenbrand, Lorenzo Stoakes, Zi Yan,
Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On Fri, 23 Jan 2026 15:03:58 +0530 "Garg, Shivank" <shivankg@amd.com> wrote:
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
> remove_wait_queue(&khugepaged_wait, &wait);
> }
>
> -static struct collapse_control khugepaged_collapse_control = {
> - .is_khugepaged = true,
> -};
> -
> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
> {
> int i;
> @@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
>
> static int khugepaged(void *none)
> {
> + struct collapse_control cc = {
> + .is_khugepaged = true,
> + };
> struct mm_slot *slot;
>
> set_freezable();
> set_user_nice(current, MAX_NICE);
>
> while (!kthread_should_stop()) {
> - khugepaged_do_scan(&khugepaged_collapse_control);
> + khugepaged_do_scan(&cc);
> khugepaged_wait_work();
> }
>
lol, OK, I droppped $Subject and did this:
From: "Garg, Shivank" <shivankg@amd.com>
Subject: mm/khugepaged: make khugepaged_collapse_control a local
Date: Fri, 23 Jan 2026 15:03:58 +0530
Make this collapse_control instance local to the only function which uses
it.
Link: https://lkml.kernel.org/r/ba4502f7-0c35-460e-a42c-d32dea9ab9eb@amd.com
Signed-off-by: Shivank Garg <shivankg@amd.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Barry Song <baohua@kernel.org>
Cc: David Hildenbrand (Red Hat) <david@kernel.org>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Wei Yang <richard.weiyang@gmail.com>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
mm/khugepaged.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
--- a/mm/khugepaged.c~mm-khugepaged-make-khugepaged_collapse_control-a-local
+++ a/mm/khugepaged.c
@@ -827,10 +827,6 @@ static void khugepaged_alloc_sleep(void)
remove_wait_queue(&khugepaged_wait, &wait);
}
-struct collapse_control khugepaged_collapse_control = {
- .is_khugepaged = true,
-};
-
static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
{
int i;
@@ -2618,13 +2614,16 @@ static void khugepaged_wait_work(void)
static int khugepaged(void *none)
{
+ struct collapse_control cc = {
+ .is_khugepaged = true,
+ };
struct mm_slot *slot;
set_freezable();
set_user_nice(current, MAX_NICE);
while (!kthread_should_stop()) {
- khugepaged_do_scan(&khugepaged_collapse_control);
+ khugepaged_do_scan(&cc);
khugepaged_wait_work();
}
_
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-24 1:21 ` Andrew Morton
@ 2026-01-24 3:02 ` Andrew Morton
2026-01-24 9:02 ` Lorenzo Stoakes
0 siblings, 1 reply; 32+ messages in thread
From: Andrew Morton @ 2026-01-24 3:02 UTC (permalink / raw)
To: Garg, Shivank, Dev Jain, David Hildenbrand, Lorenzo Stoakes,
Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On Fri, 23 Jan 2026 17:21:42 -0800 Andrew Morton <akpm@linux-foundation.org> wrote:
>
> lol, OK, I droppped $Subject and did this:
>
> --- a/mm/khugepaged.c~mm-khugepaged-make-khugepaged_collapse_control-a-local
> +++ a/mm/khugepaged.c
> @@ -827,10 +827,6 @@ static void khugepaged_alloc_sleep(void)
> remove_wait_queue(&khugepaged_wait, &wait);
> }
>
> -struct collapse_control khugepaged_collapse_control = {
> - .is_khugepaged = true,
> -};
> -
> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
> {
> int i;
> @@ -2618,13 +2614,16 @@ static void khugepaged_wait_work(void)
>
> static int khugepaged(void *none)
> {
> + struct collapse_control cc = {
> + .is_khugepaged = true,
> + };
nope, that thing's really big!
mm/khugepaged.c: In function 'khugepaged':
mm/khugepaged.c:2637:1: error: the frame size of 4696 bytes is larger than 2048
We could kzalloc() it but I think I'll just restore the make-it-static
patch. Someone please add to the todo list?
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-23 9:33 ` Garg, Shivank
2026-01-24 1:21 ` Andrew Morton
@ 2026-01-24 9:01 ` Lorenzo Stoakes
2026-01-24 10:54 ` Dev Jain
1 sibling, 1 reply; 32+ messages in thread
From: Lorenzo Stoakes @ 2026-01-24 9:01 UTC (permalink / raw)
To: Garg, Shivank
Cc: Dev Jain, Andrew Morton, David Hildenbrand, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Barry Song,
Lance Yang, linux-mm, linux-kernel, Wei Yang, Anshuman Khandual
NAK to this change....
On Fri, Jan 23, 2026 at 03:03:58PM +0530, Garg, Shivank wrote:
>
>
> On 1/23/2026 1:18 PM, Dev Jain wrote:
> >
> > On 22/01/26 2:58 pm, Dev Jain wrote:
> >> On 19/01/26 12:53 am, Shivank Garg wrote:
> >>> The global variable 'khugepaged_collapse_control' is not used outside of
> >>> mm/khugepaged.c. Make it static to limit its scope.
> >>>
> >>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
> >>> Reviewed-by: Zi Yan <ziy@nvidia.com>
> >>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
> >>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
> >>> Signed-off-by: Shivank Garg <shivankg@amd.com>
> >>> ---
> >>> mm/khugepaged.c | 2 +-
> >>> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>>
> >>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> >>> index 1667abae6d8d..fba6aea5bea6 100644
> >>> --- a/mm/khugepaged.c
> >>> +++ b/mm/khugepaged.c
> >>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
> >>> remove_wait_queue(&khugepaged_wait, &wait);
> >>> }
> >>>
> >>> -struct collapse_control khugepaged_collapse_control = {
> >>> +static struct collapse_control khugepaged_collapse_control = {
> >>> .is_khugepaged = true,
> >>> };
> >>>
> >> Will it not be better to just remove this variable? In madvise_collapse,
> >> we defined cc as a local variable and set .is_khugepaged = false. The
> >> same can be done in int khugepaged() - define a local variable and set
> >> .is_khugepaged = true.
> >
> > Since this patch has been stabilized already by 4 R-bs, it may be a headache
> > to now remove this, we can do my suggestion later.
> >
> > Reviewed-by: Dev Jain <dev.jain@arm.com>
> >
> >>
> >>
>
> Thank you Dev for the feedback and review.
>
> I've attached the patch implementing your suggestion and sending this as a separate
> follow-up to avoid disrupting the current series.
>
> I’m happy to queue it for next cycle or if it’s acceptable now, please take it.
>
> Thanks for the suggestion!
>
> Regards,
> Shivank
>
> ---
> From: Shivank Garg <shivankg@amd.com>
> Date: Thu, 22 Jan 2026 12:36:28 +0000
> Subject: [PATCH] mm/khugepaged: convert khugepaged_collapse_control to local
> variable in khugepaged()
>
> Make khugepaged_collapse_control a local variable in khugepaged() instead
> of static global, consistent with how madvise_collapse() handles its
> collapse_control. Static storage is unnecessary here as node_load and
> alloc_nmask are reset per-VMA during scanning.
>
> No functional change.
>
> Suggested-by: Dev Jain <dev.jain@arm.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
> ---
> mm/khugepaged.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 9f790ec34400..c18d2ce639b1 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
> remove_wait_queue(&khugepaged_wait, &wait);
> }
>
> -static struct collapse_control khugepaged_collapse_control = {
> - .is_khugepaged = true,
> -};
> -
> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
> {
> int i;
> @@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
>
> static int khugepaged(void *none)
> {
> + struct collapse_control cc = {
> + .is_khugepaged = true,
> + };
> struct mm_slot *slot;
>
> set_freezable();
> set_user_nice(current, MAX_NICE);
>
> while (!kthread_should_stop()) {
> - khugepaged_do_scan(&khugepaged_collapse_control);
> + khugepaged_do_scan(&cc);
> khugepaged_wait_work();
> }
>
> --
> 2.43.0
>
>
>
>
Andrew's already commented but this is terribly mistaken.
The argument against it (why did nobody check...) is that this struct is HUGE
and there's really no benefit to doing this.
Nico's series makes this struct even bigger (...!)
Dev - PLEASE use pahole or sizeof(...) or something before suggesting moving
things like this on to the stack, in future e.g.:
$ pahole collapse_control
struct collapse_control {
bool is_khugepaged; /* 0 1 */
/* XXX 3 bytes hole, try to pack */
u32 node_load[1024]; /* 4 4096 */
/* XXX 4 bytes hole, try to pack */
/* --- cacheline 64 boundary (4096 bytes) was 8 bytes ago --- */
nodemask_t alloc_nmask; /* 4104 128 */
/* size: 4232, cachelines: 67, members: 3 */
/* sum members: 4225, holes: 2, sum holes: 7 */
/* last cacheline: 8 bytes */
};
Making this static was fine. Leave it as-is.
Thanks, Lorenzo
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-24 3:02 ` Andrew Morton
@ 2026-01-24 9:02 ` Lorenzo Stoakes
0 siblings, 0 replies; 32+ messages in thread
From: Lorenzo Stoakes @ 2026-01-24 9:02 UTC (permalink / raw)
To: Andrew Morton
Cc: Garg, Shivank, Dev Jain, David Hildenbrand, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Barry Song,
Lance Yang, linux-mm, linux-kernel, Wei Yang, Anshuman Khandual
On Fri, Jan 23, 2026 at 07:02:13PM -0800, Andrew Morton wrote:
> On Fri, 23 Jan 2026 17:21:42 -0800 Andrew Morton <akpm@linux-foundation.org> wrote:
>
> >
> > lol, OK, I droppped $Subject and did this:
> >
> > --- a/mm/khugepaged.c~mm-khugepaged-make-khugepaged_collapse_control-a-local
> > +++ a/mm/khugepaged.c
> > @@ -827,10 +827,6 @@ static void khugepaged_alloc_sleep(void)
> > remove_wait_queue(&khugepaged_wait, &wait);
> > }
> >
> > -struct collapse_control khugepaged_collapse_control = {
> > - .is_khugepaged = true,
> > -};
> > -
> > static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
> > {
> > int i;
> > @@ -2618,13 +2614,16 @@ static void khugepaged_wait_work(void)
> >
> > static int khugepaged(void *none)
> > {
> > + struct collapse_control cc = {
> > + .is_khugepaged = true,
> > + };
>
> nope, that thing's really big!
>
> mm/khugepaged.c: In function 'khugepaged':
> mm/khugepaged.c:2637:1: error: the frame size of 4696 bytes is larger than 2048
Yup, thanks Andrew, this change is completely crazy.
>
> We could kzalloc() it but I think I'll just restore the make-it-static
> patch. Someone please add to the todo list?
And no to kzalloc(), let's just keep this static for now. It works fine as it is!
Thanks, Lorenzo
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-24 9:01 ` Lorenzo Stoakes
@ 2026-01-24 10:54 ` Dev Jain
2026-01-24 11:40 ` Lorenzo Stoakes
0 siblings, 1 reply; 32+ messages in thread
From: Dev Jain @ 2026-01-24 10:54 UTC (permalink / raw)
To: Lorenzo Stoakes, Garg, Shivank
Cc: Andrew Morton, David Hildenbrand, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Barry Song,
Lance Yang, linux-mm, linux-kernel, Wei Yang, Anshuman Khandual
On 24/01/26 2:31 pm, Lorenzo Stoakes wrote:
> NAK to this change....
>
> On Fri, Jan 23, 2026 at 03:03:58PM +0530, Garg, Shivank wrote:
>>
>> On 1/23/2026 1:18 PM, Dev Jain wrote:
>>> On 22/01/26 2:58 pm, Dev Jain wrote:
>>>> On 19/01/26 12:53 am, Shivank Garg wrote:
>>>>> The global variable 'khugepaged_collapse_control' is not used outside of
>>>>> mm/khugepaged.c. Make it static to limit its scope.
>>>>>
>>>>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
>>>>> Reviewed-by: Zi Yan <ziy@nvidia.com>
>>>>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
>>>>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
>>>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>>>>> ---
>>>>> mm/khugepaged.c | 2 +-
>>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>>>> index 1667abae6d8d..fba6aea5bea6 100644
>>>>> --- a/mm/khugepaged.c
>>>>> +++ b/mm/khugepaged.c
>>>>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
>>>>> remove_wait_queue(&khugepaged_wait, &wait);
>>>>> }
>>>>>
>>>>> -struct collapse_control khugepaged_collapse_control = {
>>>>> +static struct collapse_control khugepaged_collapse_control = {
>>>>> .is_khugepaged = true,
>>>>> };
>>>>>
>>>> Will it not be better to just remove this variable? In madvise_collapse,
>>>> we defined cc as a local variable and set .is_khugepaged = false. The
>>>> same can be done in int khugepaged() - define a local variable and set
>>>> .is_khugepaged = true.
>>> Since this patch has been stabilized already by 4 R-bs, it may be a headache
>>> to now remove this, we can do my suggestion later.
>>>
>>> Reviewed-by: Dev Jain <dev.jain@arm.com>
>>>
>>>>
>> Thank you Dev for the feedback and review.
>>
>> I've attached the patch implementing your suggestion and sending this as a separate
>> follow-up to avoid disrupting the current series.
>>
>> I’m happy to queue it for next cycle or if it’s acceptable now, please take it.
>>
>> Thanks for the suggestion!
>>
>> Regards,
>> Shivank
>>
>> ---
>> From: Shivank Garg <shivankg@amd.com>
>> Date: Thu, 22 Jan 2026 12:36:28 +0000
>> Subject: [PATCH] mm/khugepaged: convert khugepaged_collapse_control to local
>> variable in khugepaged()
>>
>> Make khugepaged_collapse_control a local variable in khugepaged() instead
>> of static global, consistent with how madvise_collapse() handles its
>> collapse_control. Static storage is unnecessary here as node_load and
>> alloc_nmask are reset per-VMA during scanning.
>>
>> No functional change.
>>
>> Suggested-by: Dev Jain <dev.jain@arm.com>
>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>> ---
>> mm/khugepaged.c | 9 ++++-----
>> 1 file changed, 4 insertions(+), 5 deletions(-)
>>
>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>> index 9f790ec34400..c18d2ce639b1 100644
>> --- a/mm/khugepaged.c
>> +++ b/mm/khugepaged.c
>> @@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
>> remove_wait_queue(&khugepaged_wait, &wait);
>> }
>>
>> -static struct collapse_control khugepaged_collapse_control = {
>> - .is_khugepaged = true,
>> -};
>> -
>> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
>> {
>> int i;
>> @@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
>>
>> static int khugepaged(void *none)
>> {
>> + struct collapse_control cc = {
>> + .is_khugepaged = true,
>> + };
>> struct mm_slot *slot;
>>
>> set_freezable();
>> set_user_nice(current, MAX_NICE);
>>
>> while (!kthread_should_stop()) {
>> - khugepaged_do_scan(&khugepaged_collapse_control);
>> + khugepaged_do_scan(&cc);
>> khugepaged_wait_work();
>> }
>>
>> --
>> 2.43.0
>>
>>
>>
>>
> Andrew's already commented but this is terribly mistaken.
>
> The argument against it (why did nobody check...) is that this struct is HUGE
> and there's really no benefit to doing this.
>
> Nico's series makes this struct even bigger (...!)
>
> Dev - PLEASE use pahole or sizeof(...) or something before suggesting moving
> things like this on to the stack, in future e.g.:
>
> $ pahole collapse_control
> struct collapse_control {
> bool is_khugepaged; /* 0 1 */
>
> /* XXX 3 bytes hole, try to pack */
>
> u32 node_load[1024]; /* 4 4096 */
>
> /* XXX 4 bytes hole, try to pack */
>
> /* --- cacheline 64 boundary (4096 bytes) was 8 bytes ago --- */
> nodemask_t alloc_nmask; /* 4104 128 */
>
> /* size: 4232, cachelines: 67, members: 3 */
> /* sum members: 4225, holes: 2, sum holes: 7 */
> /* last cacheline: 8 bytes */
> };
>
> Making this static was fine. Leave it as-is.
I wasn't suggesting that! When I said
"In madvise_collapse, we defined cc as a local variable and set .is_khugepaged = false. The
same can be done in int khugepaged() - define a local variable and set .is_khugepaged = true."
madvise_collapse does kmalloc() to allocate this large struct. I was suggesting to do the
same for khugepaged, to enforce consistency.
>
> Thanks, Lorenzo
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-24 10:54 ` Dev Jain
@ 2026-01-24 11:40 ` Lorenzo Stoakes
2026-01-24 11:56 ` Dev Jain
2026-01-24 18:37 ` Garg, Shivank
0 siblings, 2 replies; 32+ messages in thread
From: Lorenzo Stoakes @ 2026-01-24 11:40 UTC (permalink / raw)
To: Dev Jain
Cc: Garg, Shivank, Andrew Morton, David Hildenbrand, Zi Yan,
Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On Sat, Jan 24, 2026 at 04:24:24PM +0530, Dev Jain wrote:
>
> On 24/01/26 2:31 pm, Lorenzo Stoakes wrote:
> > NAK to this change....
> >
> > On Fri, Jan 23, 2026 at 03:03:58PM +0530, Garg, Shivank wrote:
> >>
> >> On 1/23/2026 1:18 PM, Dev Jain wrote:
> >>> On 22/01/26 2:58 pm, Dev Jain wrote:
> >>>> On 19/01/26 12:53 am, Shivank Garg wrote:
> >>>>> The global variable 'khugepaged_collapse_control' is not used outside of
> >>>>> mm/khugepaged.c. Make it static to limit its scope.
> >>>>>
> >>>>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
> >>>>> Reviewed-by: Zi Yan <ziy@nvidia.com>
> >>>>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
> >>>>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
> >>>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
> >>>>> ---
> >>>>> mm/khugepaged.c | 2 +-
> >>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
> >>>>>
> >>>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> >>>>> index 1667abae6d8d..fba6aea5bea6 100644
> >>>>> --- a/mm/khugepaged.c
> >>>>> +++ b/mm/khugepaged.c
> >>>>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
> >>>>> remove_wait_queue(&khugepaged_wait, &wait);
> >>>>> }
> >>>>>
> >>>>> -struct collapse_control khugepaged_collapse_control = {
> >>>>> +static struct collapse_control khugepaged_collapse_control = {
> >>>>> .is_khugepaged = true,
> >>>>> };
> >>>>>
> >>>> Will it not be better to just remove this variable? In madvise_collapse,
> >>>> we defined cc as a local variable and set .is_khugepaged = false. The
> >>>> same can be done in int khugepaged() - define a local variable and set
> >>>> .is_khugepaged = true.
> >>> Since this patch has been stabilized already by 4 R-bs, it may be a headache
> >>> to now remove this, we can do my suggestion later.
> >>>
> >>> Reviewed-by: Dev Jain <dev.jain@arm.com>
> >>>
> >>>>
> >> Thank you Dev for the feedback and review.
> >>
> >> I've attached the patch implementing your suggestion and sending this as a separate
> >> follow-up to avoid disrupting the current series.
> >>
> >> I’m happy to queue it for next cycle or if it’s acceptable now, please take it.
> >>
> >> Thanks for the suggestion!
> >>
> >> Regards,
> >> Shivank
> >>
> >> ---
> >> From: Shivank Garg <shivankg@amd.com>
> >> Date: Thu, 22 Jan 2026 12:36:28 +0000
> >> Subject: [PATCH] mm/khugepaged: convert khugepaged_collapse_control to local
> >> variable in khugepaged()
> >>
> >> Make khugepaged_collapse_control a local variable in khugepaged() instead
> >> of static global, consistent with how madvise_collapse() handles its
> >> collapse_control. Static storage is unnecessary here as node_load and
> >> alloc_nmask are reset per-VMA during scanning.
> >>
> >> No functional change.
> >>
> >> Suggested-by: Dev Jain <dev.jain@arm.com>
> >> Signed-off-by: Shivank Garg <shivankg@amd.com>
> >> ---
> >> mm/khugepaged.c | 9 ++++-----
> >> 1 file changed, 4 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> >> index 9f790ec34400..c18d2ce639b1 100644
> >> --- a/mm/khugepaged.c
> >> +++ b/mm/khugepaged.c
> >> @@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
> >> remove_wait_queue(&khugepaged_wait, &wait);
> >> }
> >>
> >> -static struct collapse_control khugepaged_collapse_control = {
> >> - .is_khugepaged = true,
> >> -};
> >> -
> >> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
> >> {
> >> int i;
> >> @@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
> >>
> >> static int khugepaged(void *none)
> >> {
> >> + struct collapse_control cc = {
> >> + .is_khugepaged = true,
> >> + };
> >> struct mm_slot *slot;
> >>
> >> set_freezable();
> >> set_user_nice(current, MAX_NICE);
> >>
> >> while (!kthread_should_stop()) {
> >> - khugepaged_do_scan(&khugepaged_collapse_control);
> >> + khugepaged_do_scan(&cc);
> >> khugepaged_wait_work();
> >> }
> >>
> >> --
> >> 2.43.0
> >>
> >>
> >>
> >>
> > Andrew's already commented but this is terribly mistaken.
> >
> > The argument against it (why did nobody check...) is that this struct is HUGE
> > and there's really no benefit to doing this.
> >
> > Nico's series makes this struct even bigger (...!)
> >
> > Dev - PLEASE use pahole or sizeof(...) or something before suggesting moving
> > things like this on to the stack, in future e.g.:
> >
> > $ pahole collapse_control
> > struct collapse_control {
> > bool is_khugepaged; /* 0 1 */
> >
> > /* XXX 3 bytes hole, try to pack */
> >
> > u32 node_load[1024]; /* 4 4096 */
> >
> > /* XXX 4 bytes hole, try to pack */
> >
> > /* --- cacheline 64 boundary (4096 bytes) was 8 bytes ago --- */
> > nodemask_t alloc_nmask; /* 4104 128 */
> >
> > /* size: 4232, cachelines: 67, members: 3 */
> > /* sum members: 4225, holes: 2, sum holes: 7 */
> > /* last cacheline: 8 bytes */
> > };
> >
> > Making this static was fine. Leave it as-is.
>
> I wasn't suggesting that! When I said
>
> "In madvise_collapse, we defined cc as a local variable and set .is_khugepaged = false. The
> same can be done in int khugepaged() - define a local variable and set .is_khugepaged = true."
Yeah I would suggest more precision in your language in future :) 'as a local
variable' and set . not -> is_khugepaged true... I can see why Shivank
interpreted it at as a stack variable.
>
> madvise_collapse does kmalloc() to allocate this large struct. I was suggesting to do the
> same for khugepaged, to enforce consistency.
As I said in reply to Andrew, NAK to the kmalloc idea too.
This consistency argument is nonsense, madvise_collapse() does that because
_there can be multiple instances_ of the cc around for different processes, you
literally _have_ to kmalloc there.
For khugepaged this isn't the case. We're good as we are.
Thanks, Lorenzo
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-24 11:40 ` Lorenzo Stoakes
@ 2026-01-24 11:56 ` Dev Jain
2026-01-24 18:37 ` Garg, Shivank
1 sibling, 0 replies; 32+ messages in thread
From: Dev Jain @ 2026-01-24 11:56 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: Garg, Shivank, Andrew Morton, David Hildenbrand, Zi Yan,
Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Barry Song, Lance Yang, linux-mm, linux-kernel, Wei Yang,
Anshuman Khandual
On 24/01/26 5:10 pm, Lorenzo Stoakes wrote:
> On Sat, Jan 24, 2026 at 04:24:24PM +0530, Dev Jain wrote:
>> On 24/01/26 2:31 pm, Lorenzo Stoakes wrote:
>>> NAK to this change....
>>>
>>> On Fri, Jan 23, 2026 at 03:03:58PM +0530, Garg, Shivank wrote:
>>>> On 1/23/2026 1:18 PM, Dev Jain wrote:
>>>>> On 22/01/26 2:58 pm, Dev Jain wrote:
>>>>>> On 19/01/26 12:53 am, Shivank Garg wrote:
>>>>>>> The global variable 'khugepaged_collapse_control' is not used outside of
>>>>>>> mm/khugepaged.c. Make it static to limit its scope.
>>>>>>>
>>>>>>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
>>>>>>> Reviewed-by: Zi Yan <ziy@nvidia.com>
>>>>>>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
>>>>>>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
>>>>>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>>>>>>> ---
>>>>>>> mm/khugepaged.c | 2 +-
>>>>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>>>
>>>>>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>>>>>> index 1667abae6d8d..fba6aea5bea6 100644
>>>>>>> --- a/mm/khugepaged.c
>>>>>>> +++ b/mm/khugepaged.c
>>>>>>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
>>>>>>> remove_wait_queue(&khugepaged_wait, &wait);
>>>>>>> }
>>>>>>>
>>>>>>> -struct collapse_control khugepaged_collapse_control = {
>>>>>>> +static struct collapse_control khugepaged_collapse_control = {
>>>>>>> .is_khugepaged = true,
>>>>>>> };
>>>>>>>
>>>>>> Will it not be better to just remove this variable? In madvise_collapse,
>>>>>> we defined cc as a local variable and set .is_khugepaged = false. The
>>>>>> same can be done in int khugepaged() - define a local variable and set
>>>>>> .is_khugepaged = true.
>>>>> Since this patch has been stabilized already by 4 R-bs, it may be a headache
>>>>> to now remove this, we can do my suggestion later.
>>>>>
>>>>> Reviewed-by: Dev Jain <dev.jain@arm.com>
>>>>>
>>>> Thank you Dev for the feedback and review.
>>>>
>>>> I've attached the patch implementing your suggestion and sending this as a separate
>>>> follow-up to avoid disrupting the current series.
>>>>
>>>> I’m happy to queue it for next cycle or if it’s acceptable now, please take it.
>>>>
>>>> Thanks for the suggestion!
>>>>
>>>> Regards,
>>>> Shivank
>>>>
>>>> ---
>>>> From: Shivank Garg <shivankg@amd.com>
>>>> Date: Thu, 22 Jan 2026 12:36:28 +0000
>>>> Subject: [PATCH] mm/khugepaged: convert khugepaged_collapse_control to local
>>>> variable in khugepaged()
>>>>
>>>> Make khugepaged_collapse_control a local variable in khugepaged() instead
>>>> of static global, consistent with how madvise_collapse() handles its
>>>> collapse_control. Static storage is unnecessary here as node_load and
>>>> alloc_nmask are reset per-VMA during scanning.
>>>>
>>>> No functional change.
>>>>
>>>> Suggested-by: Dev Jain <dev.jain@arm.com>
>>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>>>> ---
>>>> mm/khugepaged.c | 9 ++++-----
>>>> 1 file changed, 4 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>>> index 9f790ec34400..c18d2ce639b1 100644
>>>> --- a/mm/khugepaged.c
>>>> +++ b/mm/khugepaged.c
>>>> @@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
>>>> remove_wait_queue(&khugepaged_wait, &wait);
>>>> }
>>>>
>>>> -static struct collapse_control khugepaged_collapse_control = {
>>>> - .is_khugepaged = true,
>>>> -};
>>>> -
>>>> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
>>>> {
>>>> int i;
>>>> @@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
>>>>
>>>> static int khugepaged(void *none)
>>>> {
>>>> + struct collapse_control cc = {
>>>> + .is_khugepaged = true,
>>>> + };
>>>> struct mm_slot *slot;
>>>>
>>>> set_freezable();
>>>> set_user_nice(current, MAX_NICE);
>>>>
>>>> while (!kthread_should_stop()) {
>>>> - khugepaged_do_scan(&khugepaged_collapse_control);
>>>> + khugepaged_do_scan(&cc);
>>>> khugepaged_wait_work();
>>>> }
>>>>
>>>> --
>>>> 2.43.0
>>>>
>>>>
>>>>
>>>>
>>> Andrew's already commented but this is terribly mistaken.
>>>
>>> The argument against it (why did nobody check...) is that this struct is HUGE
>>> and there's really no benefit to doing this.
>>>
>>> Nico's series makes this struct even bigger (...!)
>>>
>>> Dev - PLEASE use pahole or sizeof(...) or something before suggesting moving
>>> things like this on to the stack, in future e.g.:
>>>
>>> $ pahole collapse_control
>>> struct collapse_control {
>>> bool is_khugepaged; /* 0 1 */
>>>
>>> /* XXX 3 bytes hole, try to pack */
>>>
>>> u32 node_load[1024]; /* 4 4096 */
>>>
>>> /* XXX 4 bytes hole, try to pack */
>>>
>>> /* --- cacheline 64 boundary (4096 bytes) was 8 bytes ago --- */
>>> nodemask_t alloc_nmask; /* 4104 128 */
>>>
>>> /* size: 4232, cachelines: 67, members: 3 */
>>> /* sum members: 4225, holes: 2, sum holes: 7 */
>>> /* last cacheline: 8 bytes */
>>> };
>>>
>>> Making this static was fine. Leave it as-is.
>> I wasn't suggesting that! When I said
>>
>> "In madvise_collapse, we defined cc as a local variable and set .is_khugepaged = false. The
>> same can be done in int khugepaged() - define a local variable and set .is_khugepaged = true."
> Yeah I would suggest more precision in your language in future :) 'as a local
> variable' and set . not -> is_khugepaged true... I can see why Shivank
> interpreted it at as a stack variable.
>
>> madvise_collapse does kmalloc() to allocate this large struct. I was suggesting to do the
>> same for khugepaged, to enforce consistency.
> As I said in reply to Andrew, NAK to the kmalloc idea too.
>
> This consistency argument is nonsense, madvise_collapse() does that because
> _there can be multiple instances_ of the cc around for different processes, you
> literally _have_ to kmalloc there.
Ah yes nice observation : ) Thanks.
>
> For khugepaged this isn't the case. We're good as we are.
>
> Thanks, Lorenzo
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static
2026-01-24 11:40 ` Lorenzo Stoakes
2026-01-24 11:56 ` Dev Jain
@ 2026-01-24 18:37 ` Garg, Shivank
1 sibling, 0 replies; 32+ messages in thread
From: Garg, Shivank @ 2026-01-24 18:37 UTC (permalink / raw)
To: Lorenzo Stoakes, Dev Jain
Cc: Andrew Morton, David Hildenbrand, Zi Yan, Baolin Wang,
Liam R . Howlett, Nico Pache, Ryan Roberts, Barry Song,
Lance Yang, linux-mm, linux-kernel, Wei Yang, Anshuman Khandual
On 1/24/2026 5:10 PM, Lorenzo Stoakes wrote:
> On Sat, Jan 24, 2026 at 04:24:24PM +0530, Dev Jain wrote:
>>
>> On 24/01/26 2:31 pm, Lorenzo Stoakes wrote:
>>> NAK to this change....
>>>
>>> On Fri, Jan 23, 2026 at 03:03:58PM +0530, Garg, Shivank wrote:
>>>>
>>>> On 1/23/2026 1:18 PM, Dev Jain wrote:
>>>>> On 22/01/26 2:58 pm, Dev Jain wrote:
>>>>>> On 19/01/26 12:53 am, Shivank Garg wrote:
>>>>>>> The global variable 'khugepaged_collapse_control' is not used outside of
>>>>>>> mm/khugepaged.c. Make it static to limit its scope.
>>>>>>>
>>>>>>> Reviewed-by: Wei Yang <richard.weiyang@gmail.com>
>>>>>>> Reviewed-by: Zi Yan <ziy@nvidia.com>
>>>>>>> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
>>>>>>> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
>>>>>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>>>>>>> ---
>>>>>>> mm/khugepaged.c | 2 +-
>>>>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>>>
>>>>>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>>>>>> index 1667abae6d8d..fba6aea5bea6 100644
>>>>>>> --- a/mm/khugepaged.c
>>>>>>> +++ b/mm/khugepaged.c
>>>>>>> @@ -827,7 +827,7 @@ static void khugepaged_alloc_sleep(void)
>>>>>>> remove_wait_queue(&khugepaged_wait, &wait);
>>>>>>> }
>>>>>>>
>>>>>>> -struct collapse_control khugepaged_collapse_control = {
>>>>>>> +static struct collapse_control khugepaged_collapse_control = {
>>>>>>> .is_khugepaged = true,
>>>>>>> };
>>>>>>>
>>>>>> Will it not be better to just remove this variable? In madvise_collapse,
>>>>>> we defined cc as a local variable and set .is_khugepaged = false. The
>>>>>> same can be done in int khugepaged() - define a local variable and set
>>>>>> .is_khugepaged = true.
>>>>> Since this patch has been stabilized already by 4 R-bs, it may be a headache
>>>>> to now remove this, we can do my suggestion later.
>>>>>
>>>>> Reviewed-by: Dev Jain <dev.jain@arm.com>
>>>>>
>>>>>>
>>>> Thank you Dev for the feedback and review.
>>>>
>>>> I've attached the patch implementing your suggestion and sending this as a separate
>>>> follow-up to avoid disrupting the current series.
>>>>
>>>> I’m happy to queue it for next cycle or if it’s acceptable now, please take it.
>>>>
>>>> Thanks for the suggestion!
>>>>
>>>> Regards,
>>>> Shivank
>>>>
>>>> ---
>>>> From: Shivank Garg <shivankg@amd.com>
>>>> Date: Thu, 22 Jan 2026 12:36:28 +0000
>>>> Subject: [PATCH] mm/khugepaged: convert khugepaged_collapse_control to local
>>>> variable in khugepaged()
>>>>
>>>> Make khugepaged_collapse_control a local variable in khugepaged() instead
>>>> of static global, consistent with how madvise_collapse() handles its
>>>> collapse_control. Static storage is unnecessary here as node_load and
>>>> alloc_nmask are reset per-VMA during scanning.
>>>>
>>>> No functional change.
>>>>
>>>> Suggested-by: Dev Jain <dev.jain@arm.com>
>>>> Signed-off-by: Shivank Garg <shivankg@amd.com>
>>>> ---
>>>> mm/khugepaged.c | 9 ++++-----
>>>> 1 file changed, 4 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>>> index 9f790ec34400..c18d2ce639b1 100644
>>>> --- a/mm/khugepaged.c
>>>> +++ b/mm/khugepaged.c
>>>> @@ -829,10 +829,6 @@ static void khugepaged_alloc_sleep(void)
>>>> remove_wait_queue(&khugepaged_wait, &wait);
>>>> }
>>>>
>>>> -static struct collapse_control khugepaged_collapse_control = {
>>>> - .is_khugepaged = true,
>>>> -};
>>>> -
>>>> static bool hpage_collapse_scan_abort(int nid, struct collapse_control *cc)
>>>> {
>>>> int i;
>>>> @@ -2629,13 +2625,16 @@ static void khugepaged_wait_work(void)
>>>>
>>>> static int khugepaged(void *none)
>>>> {
>>>> + struct collapse_control cc = {
>>>> + .is_khugepaged = true,
>>>> + };
>>>> struct mm_slot *slot;
>>>>
>>>> set_freezable();
>>>> set_user_nice(current, MAX_NICE);
>>>>
>>>> while (!kthread_should_stop()) {
>>>> - khugepaged_do_scan(&khugepaged_collapse_control);
>>>> + khugepaged_do_scan(&cc);
>>>> khugepaged_wait_work();
>>>> }
>>>>
>>>> --
>>>> 2.43.0
>>>>
>>>>
>>>>
>>>>
>>> Andrew's already commented but this is terribly mistaken.
>>>
>>> The argument against it (why did nobody check...) is that this struct is HUGE
>>> and there's really no benefit to doing this.
>>>
>>> Nico's series makes this struct even bigger (...!)
>>>
>>> Dev - PLEASE use pahole or sizeof(...) or something before suggesting moving
>>> things like this on to the stack, in future e.g.:
>>>
>>> $ pahole collapse_control
>>> struct collapse_control {
>>> bool is_khugepaged; /* 0 1 */
>>>
>>> /* XXX 3 bytes hole, try to pack */
>>>
>>> u32 node_load[1024]; /* 4 4096 */
>>>
>>> /* XXX 4 bytes hole, try to pack */
>>>
>>> /* --- cacheline 64 boundary (4096 bytes) was 8 bytes ago --- */
>>> nodemask_t alloc_nmask; /* 4104 128 */
>>>
>>> /* size: 4232, cachelines: 67, members: 3 */
>>> /* sum members: 4225, holes: 2, sum holes: 7 */
>>> /* last cacheline: 8 bytes */
>>> };
>>>
>>> Making this static was fine. Leave it as-is.
>>
>> I wasn't suggesting that! When I said
>>
>> "In madvise_collapse, we defined cc as a local variable and set .is_khugepaged = false. The
>> same can be done in int khugepaged() - define a local variable and set .is_khugepaged = true."
>
> Yeah I would suggest more precision in your language in future :) 'as a local
> variable' and set . not -> is_khugepaged true... I can see why Shivank
> interpreted it at as a stack variable.
>
>>
>> madvise_collapse does kmalloc() to allocate this large struct. I was suggesting to do the
>> same for khugepaged, to enforce consistency.
>
> As I said in reply to Andrew, NAK to the kmalloc idea too.
>
> This consistency argument is nonsense, madvise_collapse() does that because
> _there can be multiple instances_ of the cc around for different processes, you
> literally _have_ to kmalloc there.
>
> For khugepaged this isn't the case. We're good as we are.
>
Thank you Lorenzo for explanation on frame-size/pahole and single-instance vs multi-instance pattern.
This was a valuable discussion and I learned a lot from it :)
Best Regards,
Shivank
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2026-01-24 18:37 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-18 19:22 [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Shivank Garg
2026-01-18 19:22 ` [PATCH V3 1/5] mm/khugepaged: remove unnecessary goto 'skip' label Shivank Garg
2026-01-22 7:04 ` Dev Jain
2026-01-22 11:56 ` Nico Pache
2026-01-18 19:22 ` [PATCH V3 2/5] mm/khugepaged: count small VMAs towards scan limit Shivank Garg
2026-01-22 7:32 ` Dev Jain
2026-01-22 8:44 ` Lance Yang
2026-01-22 12:26 ` Garg, Shivank
2026-01-23 10:42 ` Garg, Shivank
2026-01-23 15:37 ` Andrew Morton
2026-01-23 20:07 ` Garg, Shivank
2026-01-18 19:22 ` [PATCH V3 3/5] mm/khugepaged: change collapse_pte_mapped_thp() to return void Shivank Garg
2026-01-22 12:17 ` Nico Pache
2026-01-18 19:22 ` [PATCH V3 4/5] mm/khugepaged: use enum scan_result for result variables and return types Shivank Garg
2026-01-19 10:24 ` David Hildenbrand (Red Hat)
2026-01-22 9:19 ` Dev Jain
2026-01-22 12:14 ` Nico Pache
2026-01-18 19:23 ` [PATCH V3 5/5] mm/khugepaged: make khugepaged_collapse_control static Shivank Garg
2026-01-22 9:28 ` Dev Jain
2026-01-23 7:48 ` Dev Jain
2026-01-23 9:33 ` Garg, Shivank
2026-01-24 1:21 ` Andrew Morton
2026-01-24 3:02 ` Andrew Morton
2026-01-24 9:02 ` Lorenzo Stoakes
2026-01-24 9:01 ` Lorenzo Stoakes
2026-01-24 10:54 ` Dev Jain
2026-01-24 11:40 ` Lorenzo Stoakes
2026-01-24 11:56 ` Dev Jain
2026-01-24 18:37 ` Garg, Shivank
2026-01-18 20:34 ` [PATCH V3 0/5] mm/khugepaged: cleanups and scan limit fix Andrew Morton
2026-01-19 0:17 ` Zi Yan
2026-01-19 5:50 ` Garg, Shivank
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox