From c4ff3ea30640b394df4156d7ddf60ad8ffe765f1 Mon Sep 17 00:00:00 2001 From: SJ Park Date: Sun, 25 Oct 2026 09:48:06 -0700 Subject: [PATCH] mm/damon/core: move static variable rotation to damon_ctx damon_split_some_reigons() uses a static variable, rotation, to remember how many times it was called. It is again used to determine fair selection of regions to split. Since it is a static variable, it can be indeterministic and therefore less fair. The user impact is not critical. No crash, no leak. DAMON's best-effort and indeterministic monitoring accuracy could be slightly more indeterministic when multiple kdamonds are used in parallel. Fix the problem by moving the static variable into the damon_ctx struct. Link: https://lore.kernel.org/20261025164808.152048-4-sj@kernel.org Fixes: 1a582e6e0174 ("mm/damon/core: split a fraction of regions when nr_regions exceeds max/2") Signed-off-by: SJ Park Signed-off-by: Andrew Morton Closes: https://sashiko.dev/#/bug/linux-eebfcdde-2881-48ef-8df1-e2019d2a47f2 Cc: Jiayuan Chen Cc: # 7.3.x --- include/linux/damon.h | 5 +++++ mm/damon/core.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index cb6a50032a1e..380f9cf6ddd8 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -963,6 +963,11 @@ struct damon_ctx { * for more details. */ unsigned long last_nr_regions; + /* + * number of damon_split_some_regions() invocations for this context. + * Read damon_split_some_regions() for more details. + */ + unsigned long region_split_rotation; }; /* Get a random number in [@l, @r) using @ctx's lockless PRNG. */ diff --git a/mm/damon/core.c b/mm/damon/core.c index 09722257ce73..73b571b429cb 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -3753,12 +3753,13 @@ static void damon_split_regions_of(struct damon_ctx *ctx, static void damon_split_some_regions(struct damon_ctx *ctx, unsigned long split_step) { - static unsigned long rotation; struct damon_target *t; struct damon_region *r, *next; - unsigned long offset = rotation++ % split_step; + unsigned long offset; unsigned long idx = 0; + offset = ctx->region_split_rotation++ % split_step; + damon_for_each_target(t, ctx) { damon_for_each_region_safe(r, next, t) { unsigned long sz_region, sz_sub;