mm/damon: cleanup, clarify, and add/improve test
Subsystems (5)
SJ Park
maintainercover mm/damon: cleanup, clarify, and add/improve test
Yet another batch of DAMON overall cleanup.
SJ Park (9):
mm/damon/api: remove NR_DAMOS_FILTER_TYPES
mm/damon/core: use abs_diff() in damon_feed_loop_next_input() mm/damon/core: use mult_frac() in damon_feed_loop_next_input() mm/damon/core: use damos_quota_is_set() in damos_adjust_quota() mm/damon/core: document damon_call()/damon_start() race hang issue mm/damon/paddr: remove pa parameter from damon_pa_filter_pass() selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak mm/damon/tests/core-kunit: test eligible_mem_bp commitment Docs/mm/damon/design: clarify bp is basis point
Documentation/mm/damon/design.rst | 5 +++-- include/linux/damon.h | 2 -- mm/damon/core.c | 16 ++++++---------- mm/damon/paddr.c | 5 ++--- mm/damon/tests/core-kunit.h | 10 ++++++++++ .../selftests/damon/sysfs_memcg_path_leak.sh | 7 +++++++ 6 files changed, 28 insertions(+), 17 deletions(-)
base-commit: f0cc06ae989195d7280e0e7eff9d963ddc056d27
Signature · 1 line
2.47.3
SJ Park
maintainerRFC PATCH 1/9 mm/damon/api: remove NR_DAMOS_FILTER_TYPES
Nobody uses NR_DAMOS_FILTER_TYPES. Remove it.
--- include/linux/damon.h | 2 -- 1 file changed, 2 deletions(-)
include/linux/damon.h +0 -2
@@ -402,7 +402,6 @@ struct damos_stat {* @DAMOS_FILTER_TYPE_ADDR: Address range. * @DAMOS_FILTER_TYPE_TARGET: Data Access Monitoring target. * @DAMOS_FILTER_TYPE_PROBE_HITS_WSUM: probe_hits weighted sum range. -* @NR_DAMOS_FILTER_TYPES: Number of filter types. * * All types except &DAMOS_FILTER_TYPE_ADDR, &DAMOS_FILTER_TYPE_TARGET and * &DAMOS_FILTER_TYPE_PROBE_HITS_WSUM are handled by the underlying &struct
@@ -424,7 +423,6 @@ enum damos_filter_type {DAMOS_FILTER_TYPE_ADDR ,DAMOS_FILTER_TYPE_TARGET , DAMOS_FILTER_TYPE_PROBE_HITS_WSUM, - NR_DAMOS_FILTER_TYPES, };/**
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 1/9] mm/damon/api: remove NR_DAMOS_FILTER_TYPES
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 3 lines
Nobody uses
NR_DAMOS_FILTER_TYPES. Remove it.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
SJ Park
maintainerRFC PATCH 2/9 mm/damon/core: use abs_diff() in damon_feed_loop_next_input()
In reply to SJ Parkdamon_feed_loop_next_input() is open-coding absolute diff calculation instead of the dedicated helper, abs_diff(), for no good reason. Use the dedicated helper.
--- mm/damon/core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
mm/damon/core.c +1 -4
@@ -2920,10 +2920,7 @@ static unsigned long damon_feed_loop_next_input(unsigned long last_input,if (score >= goal *2 )return min_input; -if (over_achieving) - score_goal_diff = score - goal; -else - score_goal_diff = goal - score; + score_goal_diff =abs_diff (score, goal);if (last_input <ULONG_MAX / score_goal_diff) compensation = last_input * score_goal_diff / goal;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 2/9] mm/damon/core: use abs_diff() in damon_feed_loop_next_input()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
damon_feed_loop_next_input()is open-coding absolute diff calculation instead of the dedicated helper,abs_diff(), for no good reason. Use the dedicated helper.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
SJ Park
maintainerRFC PATCH 3/9 mm/damon/core: use mult_frac() in damon_feed_loop_next_input()
In reply to SJ Parkdamon_feed_loop_next_input() does its best effort overflow protection. score_goal_diff is always smaller than goal (10,000). Hence the calculation can be replaced to use mult_frac() without concerning the overflow. Use mult_frac().
--- mm/damon/core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
mm/damon/core.c +1 -5
@@ -2921,11 +2921,7 @@ static unsigned long damon_feed_loop_next_input(unsigned long last_input,return min_input; score_goal_diff =abs_diff (score, goal); - -if (last_input <ULONG_MAX / score_goal_diff) - compensation = last_input * score_goal_diff / goal; -else - compensation = last_input / goal * score_goal_diff; + compensation =mult_frac (last_input, score_goal_diff, goal);if (over_achieving)return max (last_input - compensation, min_input);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 3/9] mm/damon/core: use mult_frac() in damon_feed_loop_next_input()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 6 lines
damon_feed_loop_next_input()does its best effort overflow protection.score_goal_diffis always smaller than goal (10,000). Hence the calculation can be replaced to usemult_frac()without concerning the overflow. Usemult_frac().Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
SJ Park
maintainerRFC PATCH 4/9 mm/damon/core: use damos_quota_is_set() in damos_adjust_quota()
In reply to SJ Parkdamos_adjust_quota() is manually checking if the user set the DAMOS quota. There is a dedicated helper, damos_quota_is_set(), for the purpose. Use the helper.
--- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/damon/core.c +1 -1
@@ -3344,7 +3344,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)unsigned long cumulated_sz, cached_esz;unsigned int score, max_score =0 ; -if (!quota->ms && !quota->sz &&list_empty ("a->goals)) +if (!damos_quota_is_set (quota))return ;/* First charge window */
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 4/9] mm/damon/core: use damos_quota_is_set() in damos_adjust_quota()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
damos_adjust_quota()is manually checking if the user set the DAMOS quota. There is a dedicated helper,damos_quota_is_set(), for the purpose. Use the helper.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Re: [RFC PATCH 4/9] mm/damon/core: use damos_quota_is_set() in damos_adjust_quota()
In reply to SJ ParkQuoted 14 lines · On Sat, 12 Sep 2026 13:08:05 -0700 SJ Park <[email protected]> wrote:
damos_adjust_quota()is manually checking if the user set the DAMOS quota. There is a dedicated helper,damos_quota_is_set(), for the purpose. Use the helper.Signed-off-by SJ Park <[email protected]>--- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/damon/core.c +0
-0
mm/damon/core.c static void damos_adjust_quota(struct damon_ctx *c, struct damos *s) · line 3347
Quoted 5 lines
mm/damon/core.c +1
-1@@ -3344,7 +3344,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)unsigned long cumulated_sz, cached_esz;unsigned int score, max_score =0 ; -if (!quota->ms && !quota->sz &&list_empty ("a->goals)) +if (!damos_quota_is_set (quota))
Hi SJ,
This is more than a cleanup, because damos_quota_is_set() also checks quota->esz, which the original condition did not.
The path that makes this matter: damos_commit_quota() copies ms and sz from sysfs but not esz. So if a scheme runs with a non-zero ms, then the user sets ms=0 and commits, the running scheme gets ms=0 while esz keeps its old value.
The old check would then return early, leaving esz stale. That stale esz is visible to damos_valid_target() and damos_quota_is_full(), which also use damos_quota_is_set().
With the helper, damos_adjust_quota() proceeds into damos_set_effective_quota(), where the first branch resets esz from sz when ms and goals are unset.
The code change is correct, but worth noting the behavioral change in the commit message.
Thanks,
Kunwu
Quoted 6 lines
mm/damon/core.c +0
-0return ;/* First charge window */ Signature · 1 line
2.47.3
Sent using hkml (https://github.com/sjp38/hackermail)
SJ Park
maintainerRe: [RFC PATCH 4/9] mm/damon/core: use damos_quota_is_set() in damos_adjust_quota()
Quoted 35 lines · On Mon, 14 Sep 2026 23:01:48 +0800 Kunwu Chan <[email protected]> wrote:
Quoted 14 lines · On Sat, 12 Sep 2026 13:08:05 -0700 SJ Park <[email protected]> wrote:
damos_adjust_quota()is manually checking if the user set the DAMOS quota. There is a dedicated helper,damos_quota_is_set(), for the purpose. Use the helper.Signed-off-by SJ Park <[email protected]>--- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/damon/core.c +0
-0mm/damon/core.c static void damos_adjust_quota(struct damon_ctx *c, struct damos *s) · line 3347
Quoted 5 lines
mm/damon/core.c +1
-1@@ -3344,7 +3344,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)unsigned long cumulated_sz, cached_esz;unsigned int score, max_score =0 ; -if (!quota->ms && !quota->sz &&list_empty ("a->goals)) +if (!damos_quota_is_set (quota))Hi SJ,
This is more than a cleanup, becausedamos_quota_is_set()also checksquota->esz, which the original condition did not.The path that makes this matter:
damos_commit_quota()copies ms and sz from sysfs but not esz. So if a scheme runs with a non-zero ms, then the user sets ms=0 and commits, the running scheme gets ms=0 while esz keeps its old value.The old check would then return early, leaving esz stale. That stale esz is visible to
damos_valid_target()anddamos_quota_is_full(), which also usedamos_quota_is_set().
Quoted 6 lines
With the helper,
damos_adjust_quota()proceeds intodamos_set_effective_quota(), where the first branch resets esz from sz when ms and goals are unset.The code change is correct, but worth noting the behavioral change in the commit message.
So, if user sets only time quota, and then commits the quota to zero while the esz is non-zero, esz is never reset to zero. As a result, DAMOS keeps applying the action with the esz forever. Correct?
If so, this may deserve Cc-ing stable@. Kunwu, what do you think?
Thanks,
SJ
[...]
Re: [RFC PATCH 4/9] mm/damon/core: use damos_quota_is_set() in damos_adjust_quota()
Quoted 42 lines · SJ Park
Quoted 39 lines · On Mon, 14 Sep 2026 23:01:48 +0800 Kunwu Chan <[email protected]> wrote:
Quoted 14 lines · On Sat, 12 Sep 2026 13:08:05 -0700 SJ Park <[email protected]> wrote:
damos_adjust_quota()is manually checking if the user set the DAMOS quota. There is a dedicated helper,damos_quota_is_set(), for the purpose. Use the helper.Signed-off-by SJ Park <[email protected]>--- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/damon/core.c +0
-0mm/damon/core.c static void damos_adjust_quota(struct damon_ctx *c, struct damos *s) · line 3347
Quoted 5 lines
mm/damon/core.c +1
-1@@ -3344,7 +3344,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)unsigned long cumulated_sz, cached_esz;unsigned int score, max_score =0 ; -if (!quota->ms && !quota->sz &&list_empty ("a->goals)) +if (!damos_quota_is_set (quota))Hi SJ,
This is more than a cleanup, becausedamos_quota_is_set()also checksquota->esz, which the original condition did not.The path that makes this matter:
damos_commit_quota()copies ms and sz from sysfs but not esz. So if a scheme runs with a non-zero ms, then the user sets ms=0 and commits, the running scheme gets ms=0 while esz keeps its old value.The old check would then return early, leaving esz stale. That stale esz is visible to
damos_valid_target()anddamos_quota_is_full(), which also usedamos_quota_is_set().With the helper,
damos_adjust_quota()proceeds intodamos_set_effective_quota(), where the first branch resets esz from sz when ms and goals are unset.
Quoted 6 lines
Quoted 2 lines
The code change is correct, but worth noting the behavioral change in the commit message.
So, if user sets only time quota, and then commits the quota to zero while the esz is non-zero, esz is never reset to zero. As a result, DAMOS keeps applying the action with the esz forever. Correct?
Yes, the stale esz path is confirmed.
One clarification, though: it does not keep applying the action forever. While charged_sz < stale_esz, damos_adjust_quota() still returns early, but damos_apply_target() continues to apply the scheme and damos_charge_quota() keeps increasing charged_sz.
Once charged_sz >= stale_esz, damos_quota_is_full() returns true, so damon_do_apply_schemes() skips the scheme. Since the early return also prevents the charge-window handling from running, charged_sz is never reset, and the scheme remains permanently inactive.
So clearing the quota can result in the scheme applying up to the stale esz, and then stopping permanently.
Quoted 2 lines
If so, this may deserve Cc-ing stable@. Kunwu, what do you think?
I think this is a functional bug in the existing code, and Cc'ing stable makes sense.
Thanks,
Kunwu
Quoted 6 lines
Thanks,
SJ[...]
SJ Park
maintainerRe: [RFC PATCH 4/9] mm/damon/core: use damos_quota_is_set() in damos_adjust_quota()
Quoted 5 lines · On Tue, 15 Sep 2026 10:19:43 +0800 KunWu Chan <[email protected]> wrote:
Quoted 4 lines · SJ Park
Quoted 1 line · On Mon, 14 Sep 2026 23:01:48 +0800 Kunwu Chan <[email protected]> wrote:
On Sat, 12 Sep 2026 13:08:05 -0700 SJ Park <[email protected]> wrote:
[...]
Quoted 11 lines
Quoted 3 lines
So, if user sets only time quota, and then commits the quota to zero while the esz is non-zero, esz is never reset to zero. As a result, DAMOS keeps applying the action with the esz forever. Correct?
Yes, the stale esz path is confirmed.
One clarification, though: it does not keep applying the action forever. While
charged_sz<stale_esz,damos_adjust_quota()still returns early, butdamos_apply_target()continues to apply the scheme anddamos_charge_quota()keeps increasingcharged_sz.
Quoted 8 lines
Once
charged_sz>=stale_esz,damos_quota_is_full()returns true, sodamon_do_apply_schemes()skips the scheme. Since the early return also prevents the charge-window handling from running,charged_szis never reset, and the scheme remains permanently inactive.So clearing the quota can result in the scheme applying up to the stale esz, and then stopping permanently.
Thank you for detailed clarification, Kunwu!
Quoted 6 lines
Quoted 3 lines
If so, this may deserve Cc-ing stable@. Kunwu, what do you think?
I think this is a functional bug in the existing code, and Cc'ing stable makes sense.
Agreed. I will post this as a hotfix soon.
Thanks,
SJ
[...]
SJ Park
maintainerRFC PATCH 5/9 mm/damon/core: document damon_call()/damon_start() race hang issue
In reply to SJ ParkLet's suppose damon_start() and damon_call() are executed in parallel for the same DAMON context. Then, damon_call() could show ctx->damon_calls_obsolte set while ctx->kdamond is unset. If damon_start() sets ctx->kdamond before damon_call() starts the cancelling, damon_call() can indefinitely hang. No DAMON API caller does such parallel execution of damon_start() and damon_call(), so the issue doesn't exist. But who knows what will happen in future. Add a clarification comment for caution.
--- mm/damon/core.c | 3 +++ 1 file changed, 3 insertions(+)
mm/damon/core.c +3 -0
@@ -2251,6 +2251,9 @@ int damon_kdamond_pid(struct damon_ctx *ctx)* * When this function is failed, the @ctx is guaranteed to be stopped. * +* This function should not be called in parallel to damon_start() for the +* @ctx. In the case, this function could indefinitely hang. +* * Return: 0 on success, negative error code otherwise. */ int damon_call (struct damon_ctx *ctx,struct damon_call_control *control)
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 5/9] mm/damon/core: document damon_call()/damon_start() race hang issue
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Brittle cancellation polling loop in damon_call() can cause indefinite hangs on rapid context restarts.
- [High] Missing initialization of walk_control_obsolete in damon_new_ctx() causes unrecoverable hangs in damos_walk(). --
commit edbd3bc657324e35d324500107e2e30a1ffabc31
Author: SJ Park <[email protected]>
mm/damon/core: document damon_call()/damon_start() race hang issue
This commit documents a potential race condition and indefinite hang between damon_start() and damon_call() if they are executed in parallel for the same DAMON context. It adds a cautionary comment to damon_call() to warn API users about this behavior.
mm/damon/core.c int damon_kdamond_pid(struct damon_ctx *ctx) · line 2223
Quoted 11 lines
mm/damon/core.c +3
-0@@ -2218,6 +2218,9 @@ int damon_kdamond_pid(struct damon_ctx *ctx)* * When this function is failed, the @ctx is guaranteed to be stopped. * +* This function should not be called in parallel to damon_start() for the +* @ctx. In the case, this function could indefinitely hang. +*
[Severity: High]
This is a pre-existing issue, but does the cancellation polling loop in damon_call() cause indefinite hangs on rapid context restarts?
If Thread A is blocked in damon_call(), and Thread B stops the DAMON context (e.g., via module parameters), the monitoring thread cancels the call and exits.
If Thread A is preempted before evaluating the canceled polling loop, and Thread C concurrently restarts the context, Thread A resumes, evaluates damon_is_running(ctx) to true (due to the newly spawned thread), and hangs forever waiting for the new thread to stop:
mm/damon/core.c:damon_call() {
...
canceled:
while (damon_is_running(ctx))
schedule_timeout_idle(msecs_to_jiffies(100));
return -ECANCELED;
}This race can be triggered by root via concurrent sysfs or module parameter writes (e.g., in damon_reclaim).
[Severity: High]
This is a pre-existing issue, but does the missing initialization of walk_control_obsolete in damon_new_ctx() cause unrecoverable hangs in damos_walk()?
damon_new_ctx() explicitly initializes call_controls_obsolete = true to protect damon_call() from hanging if invoked before the context is started. However, it fails to initialize walk_control_obsolete:
mm/damon/core.c:damon_new_ctx() {
...
ctx->call_controls_obsolete = true;
prandom_seed_state(&ctx->rnd_state, get_random_u64());
...
}If damos_walk() is called before damon_start(), it bypasses the safety check and blocks forever on wait_for_completion(), because no thread exists to signal it:
mm/damon/core.c:damos_walk() {
...
mutex_lock(&ctx->walk_control_lock);
if (ctx->walk_control_obsolete) {
mutex_unlock(&ctx->walk_control_lock);
return -ECANCELED;
}
...
}Even though it requires erroneous API usage, the API intends to gracefully reject this via the obsolete flag. The missing initialization breaks this boundary, leading to an unkillable hang.
Quoted 3 lines
mm/damon/core.c +0
-0* Return: 0 on success, negative error code otherwise. */ int damon_call (struct damon_ctx *ctx,struct damon_call_control *control)
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
SJ Park
maintainerRe: [RFC PATCH 5/9] mm/damon/core: document damon_call()/damon_start() race hang issue
Quoted 50 lines · On Sat, 12 Sep 2026 20:19:44 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Brittle cancellation polling loop indamon_call()can cause indefinite hangs on rapid context restarts.
- [High] Missing initialization ofwalk_control_obsoleteindamon_new_ctx()causes unrecoverable hangs indamos_walk(). --commit
edbd3bc657324e35d324500107e2e30a1ffabc31
Author: SJ Park <[email protected]>
mm/damon/core: document damon_call()/damon_start() race hang issueThis commit documents a potential race condition and indefinite hang between
damon_start()anddamon_call()if they are executed in parallel for the same DAMON context. It adds a cautionary comment todamon_call()to warn API users about this behavior.mm/damon/core.c int damon_kdamond_pid(struct damon_ctx *ctx) · line 2223
Quoted 11 lines
mm/damon/core.c +3
-0@@ -2218,6 +2218,9 @@ int damon_kdamond_pid(struct damon_ctx *ctx)* * When this function is failed, the @ctx is guaranteed to be stopped. * +* This function should not be called in parallel to damon_start() for the +* @ctx. In the case, this function could indefinitely hang. +* [Severity: High]
This is a pre-existing issue, but does the cancellation polling loop indamon_call()cause indefinite hangs on rapid context restarts?If Thread A is blocked in
damon_call(), and Thread B stops the DAMON context (e.g., via module parameters), the monitoring thread cancels the call and exits.If Thread A is preempted before evaluating the canceled polling loop, and Thread C concurrently restarts the context, Thread A resumes, evaluates
damon_is_running(ctx)to true (due to the newly spawned thread), and hangs forever waiting for the new thread to stop:mm/damon/core.c:damon_call() { ... canceled: while (damon_is_running(ctx)) schedule_timeout_idle(msecs_to_jiffies(100)); return -ECANCELED; }
Quoted 2 lines
This race can be triggered by root via concurrent sysfs or module parameter writes (e.g., in
damon_reclaim).
DAMON_SYSFS does not reuse same damon_ctx, so there is no such issue.
DAMON_RECLAIM and DAMON_LRU_SORT reuse same damon_ctx, but their damon_call(), damon_start() and damon_stop() calls are done only in init and param write callback, which holds param lock. So such a race cannot happen.
Quoted 31 lines
[Severity: High]
This is a pre-existing issue, but does the missing initialization ofwalk_control_obsoleteindamon_new_ctx()cause unrecoverable hangs indamos_walk()?
damon_new_ctx()explicitly initializescall_controls_obsolete= true to protectdamon_call()from hanging if invoked before the context is started. However, it fails to initializewalk_control_obsolete:mm/damon/core.c:damon_new_ctx() { ... ctx->call_controls_obsolete = true; prandom_seed_state(&ctx->rnd_state, get_random_u64()); ... }If
damos_walk()is called beforedamon_start(), it bypasses the safety check and blocks forever onwait_for_completion(), because no thread exists to signal it:mm/damon/core.c:damos_walk() { ... mutex_lock(&ctx->walk_control_lock); if (ctx->walk_control_obsolete) { mutex_unlock(&ctx->walk_control_lock); return -ECANCELED; } ... }
Quoted 3 lines
Even though it requires erroneous API usage, the API intends to gracefully reject this via the obsolete flag. The missing initialization breaks this boundary, leading to an unkillable hang.
There is no such API usage, so such issue cannot happen. I will consider adding a comment or the initialization for possible future bug. But no blocker of this patch.
Quoted 7 lines
Quoted 4 lines
mm/damon/core.c +0
-0* Return: 0 on success, negative error code otherwise. */ int damon_call (struct damon_ctx *ctx,struct damon_call_control *control)Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
Thanks,
SJ
SJ Park
maintainerRFC PATCH 6/9 mm/damon/paddr: remove pa parameter from damon_pa_filter_pass()
In reply to SJ Parkdamon_pa_filter_pass() receives the 'pa' parameter, but doesn't use it. Remove the parameter from the function signature.
--- mm/damon/paddr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
mm/damon/paddr.c +2 -3
@@ -163,8 +163,7 @@ static bool damon_pa_filter_match(struct damon_filter *filter,return matched == filter->matching; } -static bool damon_pa_filter_pass (phys_addr_t pa,struct folio *folio, -struct damon_probe *p) +static bool damon_pa_filter_pass (struct folio *folio,struct damon_probe *p) {struct damon_filter *f;bool pass = true;
@@ -200,7 +199,7 @@ static unsigned int damon_pa_apply_probes(struct damon_ctx *ctx, ctx->addr_unit); folio =damon_get_folio (PHYS_PFN (pa));damon_for_each_probe (p, ctx) { -if (damon_pa_filter_pass (pa, folio, p)) +if (damon_pa_filter_pass (folio, p)) r->probe_hits[i]++; i++; }
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 6/9] mm/damon/paddr: remove pa parameter from damon_pa_filter_pass()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
damon_pa_filter_pass()receives the 'pa' parameter, but doesn't use it. Remove the parameter from the function signature.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
SJ Park
maintainerRFC PATCH 7/9 selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak
In reply to SJ ParkThe selftest can fail for any leak if it happens while the test is running. Remove the false positive test failures by further checking if the expected leaking function is called out on the report.
--- tools/testing/selftests/damon/sysfs_memcg_path_leak.sh | 7 +++++++ 1 file changed, 7 insertions(+)
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +7 -0
@@ -41,5 +41,12 @@ if [ "$kmemleak_report" = "" ] then exit 0 fi +if ! echo "$kmemleak_report" | grep "memcg_path_store" --quiet +then + echo "[WARN] memleak found; apparenty not from DAMON, though" + echo "$kmemleak_report" + exit 0 +fi + echo "$kmemleak_report" exit 1
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 7/9] selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Use of the non-standard `--quiet` flag in `grep` can cause the test to silently mask real memory…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Use of the non-standard --quiet flag in grep can cause the test to silently mask real memory leaks on systems with strict POSIX grep implementations.
- [Low] Typo in the warning message: 'apparenty' instead of 'apparently'.
--
commit afc83fe4758b4c2e76cc3da97cb99e2a990b6b83
Author: SJ Park <[email protected]>
selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak
The selftest can fail for any leak if it happens while the test is running. Remove the false positive test failures by further checking if the expected leaking function is called out on the report.
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh if [ "$kmemleak_report" = "" ] · line 44
Quoted 9 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +1
-0@@ -41,5 +41,12 @@ if [ "$kmemleak_report" = "" ] then exit 0 fi +if ! echo "$kmemleak_report" | grep "memcg_path_store" --quiet
[Severity: Medium]
Could the --quiet flag cause the test to accidentally mask real memory leaks?
If the test runs in an environment with a strict POSIX grep implementation that does not support the GNU extension --quiet, grep will fail with an unrecognized option error.
Because of the negated condition, a non-zero exit code from grep causes the script to evaluate to true, print a warning, and exit 0. Should the standard POSIX -q flag be used instead to ensure compatibility?
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh if [ "$kmemleak_report" = "" ] · line 46
Quoted 2 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +2
-0+then + echo "[WARN] memleak found; apparenty not from DAMON, though"
[Severity: Low]
This isn't a bug, but there is a typo in the warning message (apparenty instead of apparently).
Quoted 6 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +4
-0+ echo "$kmemleak_report" + exit 0 +fi + echo "$kmemleak_report" exit 1
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
SJ Park
maintainerRe: [RFC PATCH 7/9] selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak
Quoted 27 lines · On Sat, 12 Sep 2026 20:15:18 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Use of the non-standard--quietflag ingrepcan cause the test to silently mask real memory leaks on systems with strict POSIX grep implementations.
- [Low] Typo in the warning message: 'apparenty' instead of 'apparently'.
--commit
afc83fe4758b4c2e76cc3da97cb99e2a990b6b83
Author: SJ Park <[email protected]>selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak
The selftest can fail for any leak if it happens while the test is running. Remove the false positive test failures by further checking if the expected leaking function is called out on the report.
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh if [ "$kmemleak_report" = "" ] · line 44
Quoted 9 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +1
-0@@ -41,5 +41,12 @@ if [ "$kmemleak_report" = "" ] then exit 0 fi +if ! echo "$kmemleak_report" | grep "memcg_path_store" --quiet[Severity: Medium]
Could the --quiet flag cause the test to accidentally mask real memory leaks?
Quoted 7 lines
If the test runs in an environment with a strict POSIX grep implementation that does not support the GNU extension --quiet, grep will fail with an unrecognized option error.
Because of the negated condition, a non-zero exit code from grep causes the script to evaluate to true, print a warning, and exit 0. Should the standard POSIX -q flag be used instead to ensure compatibility?
I believe kselftest runs on systems modern enough to have --quiet option. Let me know if I'm wrong.
Quoted 7 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh if [ "$kmemleak_report" = "" ] · line 46
Quoted 3 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +2
-0+then + echo "[WARN] memleak found; apparenty not from DAMON, though"[Severity: Low]
This isn't a bug, but there is a typo in the warning message (apparenty instead of apparently).
Good eyes, I will fix in the next spin.
Quoted 10 lines
Quoted 7 lines
tools/testing/selftests/damon/sysfs_memcg_path_leak.sh +4
-0+ echo "$kmemleak_report" + exit 0 +fi + echo "$kmemleak_report" exit 1Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
Thanks,
SJ
SJ Park
maintainerRFC PATCH 8/9 mm/damon/tests/core-kunit: test eligible_mem_bp commitment
In reply to SJ ParkThere was a DAMOS quota goal commit bug [1] that doesn't update the nid field for DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP metric goal. Add a kunit test case for confirming nid commitment.
[1] https://lore.kkernel.org/[email protected]
--- mm/damon/tests/core-kunit.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
mm/damon/tests/core-kunit.h +10 -0
@@ -836,6 +836,9 @@ static void damos_test_commit_quota_goal_for(struct kunit *test,KUNIT_EXPECT_EQ (test, dst->nid, src->nid);KUNIT_EXPECT_EQ (test, dst->memcg_id, src->memcg_id);break ; +case DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP : +KUNIT_EXPECT_EQ (test, dst->nid, src->nid); +break ;default :break ; }
@@ -900,6 +903,13 @@ static void damos_test_commit_quota_goal(struct kunit *test) .current_value = 345, .last_psi_total =567 , }); +damos_test_commit_quota_goal_for (test, &dst, + &(struct damos_quota_goal ){ + .metric =DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP , + .target_value =12 , + .current_value =345 , + .nid =6 , + }); } static void damos_test_commit_quota_goals_for(struct kunit *test,
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 8/9] mm/damon/tests/core-kunit: test eligible_mem_bp commitment
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 7 lines
There was a DAMOS quota goal commit bug [1] that doesn't update the nid field for
DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BPmetric goal. Add a kunit test case for confirming nid commitment.[1] https://lore.kkernel.org/[email protected]
Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
SJ Park
maintainerRFC PATCH 9/9 Docs/mm/damon/design: clarify bp is basis point
In reply to SJ ParkDAMON design document uses "bp" for "basis point" in multiple places. Because it is not clearly mentioned, it is difficult to understand what "bp" stands for. Add the clarification.
--- Documentation/mm/damon/design.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Documentation/mm/damon/design.rst +3 -2
@@ -445,7 +445,7 @@ users to set the aimed amount of access events to observe via DAMON within given time interval. The target can be specified by the user as a ratio of DAMON-observed access events to the theoretical maximum amount of the events (``access_bp``) that measured within a given number of aggregations -(``aggrs``). +(``aggrs``). The ratio is in basis point (bp or 1/10,000). The DAMON-observed access events are calculated in byte granularity based on DAMON :ref:`region assumption <damon_design_region_based_sampling>`. For
@@ -717,7 +717,8 @@ mechanism tries to make ``current_value`` of ``target_metric`` be same to in microseconds that measured from last quota reset to next quota reset. DAMOS does the measurement on its own, so only ``target_value`` need to be set by users at the initial time. In other words, DAMOS does self-feedback. -- ``node_mem_used_bp``: Specific NUMA node's used memory ratio in bp (1/10,000). +- ``node_mem_used_bp``: Specific NUMA node's used memory ratio in basis point + (bp or 1/10,000). - ``node_mem_free_bp``: Specific NUMA node's free memory ratio in bp (1/10,000). - ``node_memcg_used_bp``: Specific cgroup's node used memory ratio for a specific NUMA node, in bp (1/10,000).
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH 9/9] Docs/mm/damon/design: clarify bp is basis point
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 7 lines
DAMON design document uses "bp" for "basis point" in multiple places. Because it is not clearly mentioned, it is difficult to understand what "bp" stands for. Add the clarification.
Reported-by Randy Dunlap <[email protected]>Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=9
Re: [RFC PATCH 9/9] Docs/mm/damon/design: clarify bp is basis point
In reply to SJ ParkQuoted 7 lines · SJ Park
DAMON design document uses "bp" for "basis point" in multiple places. Because it is not clearly mentioned, it is difficult to understand what "bp" stands for. Add the clarification.
Reported-by Randy Dunlap <[email protected]>Signed-off-by SJ Park <[email protected]>
Thanks.
Quoted 27 lines
--- Documentation/mm/damon/design.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)Documentation/mm/damon/design.rst +3
-2@@ -445,7 +445,7 @@ users to set the aimed amount of access events to observe via DAMON within given time interval. The target can be specified by the user as a ratio of DAMON-observed access events to the theoretical maximum amount of the events (``access_bp``) that measured within a given number of aggregations -(``aggrs``). +(``aggrs``). The ratio is in basis point (bp or 1/10,000). The DAMON-observed access events are calculated in byte granularity based on DAMON :ref:`region assumption <damon_design_region_based_sampling>`. For@@ -717,7 +717,8 @@ mechanism tries to make ``current_value`` of ``target_metric`` be same to in microseconds that measured from last quota reset to next quota reset. DAMOS does the measurement on its own, so only ``target_value`` need to be set by users at the initial time. In other words, DAMOS does self-feedback. -- ``node_mem_used_bp``: Specific NUMA node's used memory ratio in bp (1/10,000). +- ``node_mem_used_bp``: Specific NUMA node's used memory ratio in basis point + (bp or 1/10,000). - ``node_mem_free_bp``: Specific NUMA node's free memory ratio in bp (1/10,000). - ``node_memcg_used_bp``: Specific cgroup's node used memory ratio for a specific NUMA node, in bp (1/10,000).
Signature · 1 line
~Randy