* [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging
[not found] <2026090839-reoccupy-dizzy-a7bd@gregkh>
@ 2026-09-09 4:34 ` SJ Park
2026-09-09 4:49 ` sashiko-bot
2026-09-09 12:19 ` Greg KH
2026-09-10 0:52 ` SJ Park
1 sibling, 2 replies; 6+ messages in thread
From: SJ Park @ 2026-09-09 4:34 UTC (permalink / raw)
To: stable; +Cc: damon, SJ Park, Andrew Morton
The number of DAMON regions could temporarily exceed the user-defined
maximum number of regions limit for corner cases. For example, users
could lower the limit via runtime parameters update. For such a case,
kdamond_merge_regions() repeats merging regions in the case doubling the
merge threshold. The repeated merge operation could update the age of
regions multiple times. This corrupts the monitoring results. Fix the
issue by asking the merge operation to skip aging for the corner case.
The user impact is degradation of the monitoring quality. The impact
should be mild, since the degradation is only temporal, and it is not
common to happen in realistic setups.
The issue was discovered [1,2] by Sashiko.
Link: https://lore.kernel.org/20260712165432.87609-1-sj@kernel.org
Link: https://lore.kernel.org/20260621203548.10718-1-sj@kernel.org [1]
Link: https://lore.kernel.org/20260709145425.96247-1-sj@kernel.org [2]
Fixes: 310d6c15e910 ("mm/damon/core: merge regions aggressively when max_nr_regions is unmet")
Signed-off-by: SJ Park <sj@kernel.org>
Cc: <stable@vger.kernel.org> # 6.10
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 0250dbe08c730d003ef9f484da56ae09a1ea0c4c)
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 21 +++++++++++++--------
mm/damon/tests/core-kunit.h | 2 +-
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index cff932b3317d0..024a3a185bfe8 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -3115,18 +3115,20 @@ static void damon_verify_merge_regions_of(struct damon_region *r)
* sz_limit size upper limit of each region
*/
static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
- unsigned long sz_limit)
+ unsigned long sz_limit, bool count_age)
{
struct damon_region *r, *prev = NULL, *next;
damon_for_each_region_safe(r, next, t) {
damon_verify_merge_regions_of(r);
- if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
- r->age = 0;
- else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
- r->age = 0;
- else
- r->age++;
+ if (count_age) {
+ if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
+ r->age = 0;
+ else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
+ r->age = 0;
+ else
+ r->age++;
+ }
if (prev && prev->ar.end == r->ar.start &&
abs(prev->nr_accesses - r->nr_accesses) <= thres &&
@@ -3160,15 +3162,18 @@ static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
struct damon_target *t;
unsigned int nr_regions;
unsigned int max_thres;
+ bool count_age = true;
max_thres = c->attrs.aggr_interval /
(c->attrs.sample_interval ? c->attrs.sample_interval : 1);
do {
nr_regions = 0;
damon_for_each_target(t, c) {
- damon_merge_regions_of(t, threshold, sz_limit);
+ damon_merge_regions_of(t, threshold, sz_limit,
+ count_age);
nr_regions += damon_nr_regions(t);
}
+ count_age = false;
threshold = max(1, threshold * 2);
} while (nr_regions > c->attrs.max_nr_regions &&
threshold / 2 < max_thres);
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index fcf7c7fadb5fe..59bba0552d88c 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -256,7 +256,7 @@ static void damon_test_merge_regions_of(struct kunit *test)
damon_add_region(r, t);
}
- damon_merge_regions_of(t, 9, 9999);
+ damon_merge_regions_of(t, 9, 9999, true);
/* 0-112, 114-130, 130-156, 156-170, 170-230, 230-10170 */
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 6u);
for (i = 0; i < 6; i++) {
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging
2026-09-09 4:34 ` [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging SJ Park
@ 2026-09-09 4:49 ` sashiko-bot
2026-09-09 12:19 ` Greg KH
1 sibling, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-09-09 4:49 UTC (permalink / raw)
To: SJ Park; +Cc: damon
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Unsigned integer wrap-around of `threshold` causes an infinite loop in `kdamond_merge_regions`.
--
commit 1ad6fba11a691c8367f432e647523c0214515b3e
Author: SJ Park <sj@kernel.org>
mm/damon/core: skip aging from repeated aggressive merging
This commit addresses an issue where the number of DAMON regions can
temporarily exceed the maximum limit. It updates kdamond_merge_regions
to skip aging during repeated aggressive merging to avoid corrupting
monitoring results.
Link: https://lore.kernel.org/20260712165432.87609-1-sj@kernel.org
Link: https://lore.kernel.org/20260621203548.10718-1-sj@kernel.org [1]
Link: https://lore.kernel.org/20260709145425.96247-1-sj@kernel.org [2]
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index cff932b3317d0..024a3a185bfe8 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
[ ... ]
> @@ -3160,15 +3162,18 @@ static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
> struct damon_target *t;
> unsigned int nr_regions;
> unsigned int max_thres;
> + bool count_age = true;
>
> max_thres = c->attrs.aggr_interval /
> (c->attrs.sample_interval ? c->attrs.sample_interval : 1);
> do {
> nr_regions = 0;
> damon_for_each_target(t, c) {
> - damon_merge_regions_of(t, threshold, sz_limit);
> + damon_merge_regions_of(t, threshold, sz_limit,
> + count_age);
> nr_regions += damon_nr_regions(t);
> }
> + count_age = false;
> threshold = max(1, threshold * 2);
> } while (nr_regions > c->attrs.max_nr_regions &&
> threshold / 2 < max_thres);
^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: High]
This is a pre-existing issue, but could this loop become infinite?
If a user with access to DAMON sysfs sets aggr_interval and sample_interval
such that their ratio, stored in max_thres, is greater than 1073741824, can
the 32-bit unsigned int threshold wrap around?
Inside the do-while loop, threshold continuously doubles. When it reaches
2147483648, doubling it would wrap it around to 0.
Consequently, threshold / 2 would never exceed 1073741824, making the exit
condition infinitely true.
If regions cannot be merged below max_nr_regions due to sz_limit, would
this result in a kernel hang on the kdamond thread?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260909043419.207354-1-sj@kernel.org?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging
2026-09-09 4:34 ` [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging SJ Park
2026-09-09 4:49 ` sashiko-bot
@ 2026-09-09 12:19 ` Greg KH
2026-09-10 1:02 ` SJ Park
1 sibling, 1 reply; 6+ messages in thread
From: Greg KH @ 2026-09-09 12:19 UTC (permalink / raw)
To: SJ Park; +Cc: stable, damon, Andrew Morton
On Tue, Sep 08, 2026 at 09:34:19PM -0700, SJ Park wrote:
> The number of DAMON regions could temporarily exceed the user-defined
> maximum number of regions limit for corner cases. For example, users
> could lower the limit via runtime parameters update. For such a case,
> kdamond_merge_regions() repeats merging regions in the case doubling the
> merge threshold. The repeated merge operation could update the age of
> regions multiple times. This corrupts the monitoring results. Fix the
> issue by asking the merge operation to skip aging for the corner case.
>
> The user impact is degradation of the monitoring quality. The impact
> should be mild, since the degradation is only temporal, and it is not
> common to happen in realistic setups.
>
> The issue was discovered [1,2] by Sashiko.
>
> Link: https://lore.kernel.org/20260712165432.87609-1-sj@kernel.org
> Link: https://lore.kernel.org/20260621203548.10718-1-sj@kernel.org [1]
> Link: https://lore.kernel.org/20260709145425.96247-1-sj@kernel.org [2]
> Fixes: 310d6c15e910 ("mm/damon/core: merge regions aggressively when max_nr_regions is unmet")
> Signed-off-by: SJ Park <sj@kernel.org>
> Cc: <stable@vger.kernel.org> # 6.10
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> (cherry picked from commit 0250dbe08c730d003ef9f484da56ae09a1ea0c4c)
> Signed-off-by: SJ Park <sj@kernel.org>
> ---
> mm/damon/core.c | 21 +++++++++++++--------
> mm/damon/tests/core-kunit.h | 2 +-
> 2 files changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index cff932b3317d0..024a3a185bfe8 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -3115,18 +3115,20 @@ static void damon_verify_merge_regions_of(struct damon_region *r)
> * sz_limit size upper limit of each region
> */
> static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
> - unsigned long sz_limit)
> + unsigned long sz_limit, bool count_age)
> {
> struct damon_region *r, *prev = NULL, *next;
>
> damon_for_each_region_safe(r, next, t) {
> damon_verify_merge_regions_of(r);
> - if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
> - r->age = 0;
> - else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
> - r->age = 0;
> - else
> - r->age++;
> + if (count_age) {
> + if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
> + r->age = 0;
> + else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
> + r->age = 0;
> + else
> + r->age++;
> + }
>
> if (prev && prev->ar.end == r->ar.start &&
> abs(prev->nr_accesses - r->nr_accesses) <= thres &&
> @@ -3160,15 +3162,18 @@ static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
> struct damon_target *t;
> unsigned int nr_regions;
> unsigned int max_thres;
> + bool count_age = true;
>
> max_thres = c->attrs.aggr_interval /
> (c->attrs.sample_interval ? c->attrs.sample_interval : 1);
> do {
> nr_regions = 0;
> damon_for_each_target(t, c) {
> - damon_merge_regions_of(t, threshold, sz_limit);
> + damon_merge_regions_of(t, threshold, sz_limit,
> + count_age);
> nr_regions += damon_nr_regions(t);
> }
> + count_age = false;
> threshold = max(1, threshold * 2);
> } while (nr_regions > c->attrs.max_nr_regions &&
> threshold / 2 < max_thres);
> diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
> index fcf7c7fadb5fe..59bba0552d88c 100644
> --- a/mm/damon/tests/core-kunit.h
> +++ b/mm/damon/tests/core-kunit.h
> @@ -256,7 +256,7 @@ static void damon_test_merge_regions_of(struct kunit *test)
> damon_add_region(r, t);
> }
>
> - damon_merge_regions_of(t, 9, 9999);
> + damon_merge_regions_of(t, 9, 9999, true);
> /* 0-112, 114-130, 130-156, 156-170, 170-230, 230-10170 */
> KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 6u);
> for (i = 0; i < 6; i++) {
> --
> 2.47.3
>
>
Does not apply to the latest 7.2.y queue :(
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging
[not found] <2026090839-reoccupy-dizzy-a7bd@gregkh>
2026-09-09 4:34 ` [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging SJ Park
@ 2026-09-10 0:52 ` SJ Park
1 sibling, 0 replies; 6+ messages in thread
From: SJ Park @ 2026-09-10 0:52 UTC (permalink / raw)
To: stable; +Cc: damon, SJ Park, Andrew Morton
The number of DAMON regions could temporarily exceed the user-defined
maximum number of regions limit for corner cases. For example, users
could lower the limit via runtime parameters update. For such a case,
kdamond_merge_regions() repeats merging regions in the case doubling the
merge threshold. The repeated merge operation could update the age of
regions multiple times. This corrupts the monitoring results. Fix the
issue by asking the merge operation to skip aging for the corner case.
The user impact is degradation of the monitoring quality. The impact
should be mild, since the degradation is only temporal, and it is not
common to happen in realistic setups.
The issue was discovered [1,2] by Sashiko.
Link: https://lore.kernel.org/20260712165432.87609-1-sj@kernel.org
Link: https://lore.kernel.org/20260621203548.10718-1-sj@kernel.org [1]
Link: https://lore.kernel.org/20260709145425.96247-1-sj@kernel.org [2]
Fixes: 310d6c15e910 ("mm/damon/core: merge regions aggressively when max_nr_regions is unmet")
Signed-off-by: SJ Park <sj@kernel.org>
Cc: <stable@vger.kernel.org> # 6.10
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 0250dbe08c730d003ef9f484da56ae09a1ea0c4c)
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 21 +++++++++++++--------
mm/damon/tests/core-kunit.h | 2 +-
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index a86812d457c14..372ca1161c57d 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -3118,18 +3118,20 @@ static void damon_verify_merge_regions_of(struct damon_region *r)
* sz_limit size upper limit of each region
*/
static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
- unsigned long sz_limit)
+ unsigned long sz_limit, bool count_age)
{
struct damon_region *r, *prev = NULL, *next;
damon_for_each_region_safe(r, next, t) {
damon_verify_merge_regions_of(r);
- if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
- r->age = 0;
- else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
- r->age = 0;
- else
- r->age++;
+ if (count_age) {
+ if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
+ r->age = 0;
+ else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
+ r->age = 0;
+ else
+ r->age++;
+ }
if (prev && prev->ar.end == r->ar.start &&
abs(prev->nr_accesses - r->nr_accesses) <= thres &&
@@ -3163,15 +3165,18 @@ static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
struct damon_target *t;
unsigned int nr_regions;
unsigned int max_thres;
+ bool count_age = true;
max_thres = c->attrs.aggr_interval /
(c->attrs.sample_interval ? c->attrs.sample_interval : 1);
while (true) {
nr_regions = 0;
damon_for_each_target(t, c) {
- damon_merge_regions_of(t, threshold, sz_limit);
+ damon_merge_regions_of(t, threshold, sz_limit,
+ count_age);
nr_regions += damon_nr_regions(t);
}
+ count_age = false;
if (nr_regions <= c->attrs.max_nr_regions ||
max_thres <= threshold)
break;
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index fbcc882dccc94..e543cfff15909 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -261,7 +261,7 @@ static void damon_test_merge_regions_of(struct kunit *test)
damon_add_region(r, t);
}
- damon_merge_regions_of(t, 9, 9999);
+ damon_merge_regions_of(t, 9, 9999, true);
/* 0-112, 114-130, 130-156, 156-170, 170-230, 230-10170 */
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 6u);
if (damon_nr_regions(t) != 6)
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging
2026-09-09 12:19 ` Greg KH
@ 2026-09-10 1:02 ` SJ Park
2026-09-10 6:15 ` Greg KH
0 siblings, 1 reply; 6+ messages in thread
From: SJ Park @ 2026-09-10 1:02 UTC (permalink / raw)
To: Greg KH; +Cc: SJ Park, stable, damon, Andrew Morton
On Wed, 9 Sep 2026 14:19:27 +0200 Greg KH <greg@kroah.com> wrote:
[...]
> Does not apply to the latest 7.2.y queue :(
Thank you, just rebased the patch to 7.2.5-rc1 and posted as another reply [1].
As number of stable patches for DAMON is increasing, this kind of patch
applying-order based conflict might be even more common in future. Maybe I
could reduce this kind of issues if I could post fixed patches as single patch
series, instead of replying to this kind of individual failure report.
I was initially worried if your workflow is dependent to the guided workflow
(replying ported patch as a reply to each failure report), and hence if this
could make your job more difficult. But I know the stable patch submission
rules are quite flexible. And you may already have good enough automation for
such small change.s So as long as I keep the essential stable patches rule
(use 'cherry-pick -x' option and add target branch name as patch subject tag),
that might not really make your work worse?
If that is fine, I will try that from the next time, unless only single failure
is reported on the day.
[1] https://lore.kernel.org/20260910005213.126528-1-sj@kernel.org
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging
2026-09-10 1:02 ` SJ Park
@ 2026-09-10 6:15 ` Greg KH
0 siblings, 0 replies; 6+ messages in thread
From: Greg KH @ 2026-09-10 6:15 UTC (permalink / raw)
To: SJ Park; +Cc: stable, damon, Andrew Morton
On Wed, Sep 09, 2026 at 06:02:09PM -0700, SJ Park wrote:
> On Wed, 9 Sep 2026 14:19:27 +0200 Greg KH <greg@kroah.com> wrote:
> [...]
> > Does not apply to the latest 7.2.y queue :(
>
> Thank you, just rebased the patch to 7.2.5-rc1 and posted as another reply [1].
>
> As number of stable patches for DAMON is increasing, this kind of patch
> applying-order based conflict might be even more common in future. Maybe I
> could reduce this kind of issues if I could post fixed patches as single patch
> series, instead of replying to this kind of individual failure report.
>
> I was initially worried if your workflow is dependent to the guided workflow
> (replying ported patch as a reply to each failure report), and hence if this
> could make your job more difficult. But I know the stable patch submission
> rules are quite flexible. And you may already have good enough automation for
> such small change.s So as long as I keep the essential stable patches rule
> (use 'cherry-pick -x' option and add target branch name as patch subject tag),
> that might not really make your work worse?
A patch series is great, and much simpler for me to apply, otherwise I
have to just guess and go by the email date/time stamp to order them.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-10 6:17 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <2026090839-reoccupy-dizzy-a7bd@gregkh>
2026-09-09 4:34 ` [PATCH 7.2.y] mm/damon/core: skip aging from repeated aggressive merging SJ Park
2026-09-09 4:49 ` sashiko-bot
2026-09-09 12:19 ` Greg KH
2026-09-10 1:02 ` SJ Park
2026-09-10 6:15 ` Greg KH
2026-09-10 0:52 ` SJ Park
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.