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 Signed-off-by: Shivank Garg --- mm/khugepaged.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 107146f012b1..0b549c3250f9 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,7 @@ 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) { progress++; continue; } -- 2.43.0