damon.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "SJ Park" <sj@kernel.org>
Cc: damon@lists.linux.dev
Subject: Re: [PATCH 6.12.y] mm/damon/core: skip aging from repeated aggressive merging
Date: Wed, 09 Sep 2026 04:46:53 +0000	[thread overview]
Message-ID: <20260909044653.F0CCC1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260909043807.210326-1-sj@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] The do-while loop in `kdamond_merge_regions` can infinite-loop if `nr_regions` remains above `max_nr_regions`. It expects the loop to terminate when `threshold / 2 >= max_thres`, but `threshold` is a 32-bit `unsigned int` that overflows when doubled. If `max_thres` (derived from `aggr_interval / sample_interval`) is sufficiently large (e.g., > 1,073,741,824), the condition `threshold / 2 < max_thres` evaluates to true forever, locking up the kernel thread.
- [Medium] The C macro `abs()` is incorrectly used to compute the absolute difference between two `unsigned int` access counts (`r->nr_accesses`, `r->last_nr_accesses`, and `prev->nr_accesses`). For very large differences (exceeding 2 billion), unsigned wrap-around causes the result to evaluate as a negative 32-bit signed integer inside `abs()`, which negates it to a completely inaccurate value, causing DAMON to incorrectly reset region ages or improperly merge disjoint access patterns.
--

commit 2e588ff7cb5f9fc59f1692ecf781e53ba68d8c92
Author: SJ Park <sj@kernel.org>

mm/damon/core: skip aging from repeated aggressive merging

This commit fixes a corner case where kdamond_merge_regions() repeats
merging regions and updates region ages multiple times, which corrupts
monitoring results. It resolves the issue by skipping age counting during
the repeated merge operations.

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
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -1786,15 +1786,17 @@ static void damon_merge_two_regions(struct damon_target *t,
>   * 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) {
> -		if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
> -			r->age = 0;
> -		else
> -			r->age++;
> +		if (count_age) {
> +			if (abs(r->nr_accesses - r->last_nr_accesses) > thres)

[Severity: Medium]
This is a pre-existing issue, but does using the abs() macro here correctly
handle the absolute difference for large unsigned integer access counters?

For very large differences exceeding 2 billion, the unsigned wrap-around
could cause the result to evaluate as a negative 32-bit signed integer
inside abs(), which then negates it to an inaccurate positive value.

Could this cause DAMON to incorrectly reset region ages or improperly
merge disjoint access patterns when the ratio of aggr_interval to 
sample_interval is very large? Would abs_diff() be a safer alternative here?

> +				r->age = 0;
> +			else
> +				r->age++;
> +		}
>  
>  		if (prev && prev->ar.end == r->ar.start &&
>  		    abs(prev->nr_accesses - r->nr_accesses) <= thres &&

[Severity: Medium]
This is a pre-existing issue, but similarly, could this abs() calculation 
result in false positives during the threshold check, forcing aggressive 
merges of disparate regions if the access frequencies are extremely large?

>  		    damon_sz_region(prev) + damon_sz_region(r) <= sz_limit)
>  			damon_merge_two_regions(t, prev, r);
>  		else
>  			prev = r;
>  	}
>  }

[ ... ]

> @@ -1828,15 +1830,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 can this do-while loop lock up the 
kdamond kernel thread indefinitely?

The loop expects to terminate when threshold / 2 >= max_thres. However, 
threshold is a 32-bit unsigned int that overflows when doubled.

If max_thres is derived to be a very large value during the assignment
at the start of kdamond_merge_regions() (e.g., if a user configures a 
large aggregation and sample interval ratio), threshold could repeatedly 
double until it exceeds 0x7FFFFFFF.

When it overflows, max(1, threshold * 2) resets the threshold to 1.
As a result, threshold / 2 would max out at 0x40000000, causing the 
condition threshold / 2 < max_thres to remain permanently true.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260909043807.210326-1-sj@kernel.org?part=1

  reply	other threads:[~2026-09-09  4:46 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <2026090840-slapstick-viability-4dbd@gregkh>
2026-09-09  4:38 ` [PATCH 6.12.y] mm/damon/core: skip aging from repeated aggressive merging SJ Park
2026-09-09  4:46   ` sashiko-bot [this message]
2026-09-11 11:20   ` Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909044653.F0CCC1F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=damon@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=sj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).