[PATCH 0/2] mm/damon/core: detect internal variation above max_nr_regions/2

From: Jiayuan Chen

Date: Thu May 21 2026 - 00:53:55 EST


kdamond_split_regions() bails out early when nr_regions is already
above max_nr_regions / 2. A large region that picks up new internal
variation after that point never gets split, so we lose visibility
into its hot/cold structure.

We hit this with damon-paddr on hugepage workloads and damon-vaddr
on processes that mmap a large anonymous range.

On our production tree we added a current_nr_regions counter (no
good upstream home for it yet, so it's not in this series). We saw
nr_regions never getting close to max_nr_regions, and the picture of
the access pattern was too coarse.

Example with max_nr_regions == 1500. A target ends up with 799
small hot/cold regions plus one big region (an earlier merge
collapsed a uniformly-accessed range into a single piece):

H:hot
C:cold

r1 r2 r3 r800
HHHHHH|CCCCCC|HHHHHH|...|HHHHHH..........................|

nr_regions = 800 > max_nr_regions / 2 = 750

Now a cold subarea shows up inside r800:

r1 r2 r3 r800
HHHHHH|CCCCCC|HHHHHH|...|HHHHHH........CCCCCC.............|

The small regions can't merge with each other (their access counts
differ), so budget never frees up. r800 can't be split because
nr_regions > max_nr_regions / 2 returns early. The cold subarea
stays invisible.

Patch 1 lets this path still split regions that just changed
(age == 0), up to whatever budget is left under max_nr_regions.
If a split turns out useless, the next merge cycle undoes it.

Patch 2 adds a KUnit test for the case where nr_regions is already
above max_nr_regions / 2.

Jiayuan Chen (2):
mm/damon/core: split age==0 regions when nr_regions exceeds max/2
mm/damon/tests/core-kunit: test split above max_nr_regions/2

mm/damon/core.c | 68 ++++++++++++++++++++++++++++-------
mm/damon/tests/core-kunit.h | 70 +++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+), 12 deletions(-)

--
2.43.0