mm/damon: improve readability, clarity and test coverage
Subsystems (5)
SJ Park
maintainerv2 cover mm/damon: improve readability, clarity and test coverage
Yet another batch of miscellaneous DAMON minor improvements. Mostly focused on readability and clarity of code and document, and unit/self test coverage. No user-visible behavioral change is intended.
Changes from RFC
- RFC: https://lore.kernel.org/[email protected]
- Fix a typo in the selftest warning message.
- Collect A-b: from Randy.
- Split out damos_adjust_quota() fix to an individual hotfix patch.
- Add a patch for initializing walk_control_obsolete in damon_new_ctx().
- Add a patch for probe_hits_wsum damos filter commit kunit test.
- Trivial patch sequence update.
- Rebase to the latest mm-new.
SJ Park (10):
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: set damon_ctx->walk_control_obsolete in damon_new_ctx() mm/damon/core: document damon_call()/damon_start() race hang issue mm/damon/paddr: remove pa parameter from damon_pa_filter_pass() mm/damon/tests/core-kunit: test eligible_mem_bp commitment mm/damon/tests/core-kunit: add probe_hits_wsum damos filter commit
test
selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak Docs/mm/damon/design: clarify bp is basis point
Documentation/mm/damon/design.rst | 5 ++-- include/linux/damon.h | 2 -- mm/damon/core.c | 19 ++++-------- mm/damon/paddr.c | 5 ++-- mm/damon/tests/core-kunit.h | 30 +++++++++++++++++++ .../selftests/damon/sysfs_memcg_path_leak.sh | 7 +++++ 6 files changed, 48 insertions(+), 20 deletions(-)
base-commit: b7c76a308c2afda7cfc2ce98be3eed466be71337
Signature · 1 line
2.47.3
SJ Park
maintainerRFC PATCH v2 1/10 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
@@ -400,7 +400,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
@@ -422,7 +421,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 v2 01/10] 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 v2 2/10 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
@@ -2927,10 +2927,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 v2 02/10] 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 v2 3/10 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
@@ -2928,11 +2928,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 v2 03/10] 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 v2 4/10 mm/damon/core: set damon_ctx->walk_control_obsolete in damon_new_ctx()
In reply to SJ Parkdamos_walk() should be called for a damon_ctx context that has successfully started at least once. That's because damon_ctx->walk_control_obsolete is initialized when kdamond starts. If the rule is violated, an indefinite wait can happen. There is no existing violation of the rule.
damon_call() had a similar rule, and it turned out keeping the rule is not easy for damon_call()'s case. Hence, commit 8023b5f47e09 ("mm/damon/core: set ctx->call_controls_obsolete in damon_new_ctx()") added the initialization in damon_new_ctx() and removed the rule.
Keeping the rule for damos_walk() is relatively easier. But having slightly different rules for similar functions could be confusing. Sashiko, for example, repeatedly asked questions about this. Do the initialization of walk_control_obsolete in damon_new_ctx() for consistency.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
mm/damon/core.c +1 -4
@@ -939,6 +939,7 @@ struct damon_ctx *damon_new_ctx(void)INIT_LIST_HEAD (&ctx->schemes); ctx->call_controls_obsolete = true; + ctx->walk_control_obsolete = true;prandom_seed_state (&ctx->rnd_state,get_random_u64 ());return ctx;
@@ -2308,10 +2309,6 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control)* passed at least one &damos->apply_interval_us, kdamond marks the request as * completed so that damos_walk() can wakeup and return. * -* Note that this function should be called only after damon_start() with the -* @ctx has succeeded. Otherwise, this function could fall into an indefinite -* wait. -* * Return: 0 on success, negative error code otherwise. */ int damos_walk (struct damon_ctx *ctx,struct damos_walk_control *control)
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH v2 04/10] mm/damon/core: set damon_ctx->walk_control_obsolete in damon_new_ctx()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 17 lines
damos_walk()should be called for adamon_ctxcontext that has successfully started at least once. That's becausedamon_ctx->walk_control_obsoleteis initialized when kdamond starts. If the rule is violated, an indefinite wait can happen. There is no existing violation of the rule.
damon_call()had a similar rule, and it turned out keeping the rule is not easy for damon_call()'s case. Hence, commit8023b5f47e09("mm/damon/core: setctx->call_controls_obsoleteindamon_new_ctx()") added the initialization indamon_new_ctx()and removed the rule.Keeping the rule for
damos_walk()is relatively easier. But having slightly different rules for similar functions could be confusing. Sashiko, for example, repeatedly asked questions about this. Do the initialization ofwalk_control_obsoleteindamon_new_ctx()for consistency.
Quoted 3 lines
[1] https://lore.kernel.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=4
SJ Park
maintainerRFC PATCH v2 5/10 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_obsolete 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
@@ -2258,6 +2258,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 v2 05/10] mm/damon/core: document damon_call()/damon_start() race hang issue
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 10 lines
Let's suppose
damon_start()anddamon_call()are executed in parallel for the same DAMON context. Then,damon_call()could showctx->damon_calls_obsoleteset whilectx->kdamondis unset. Ifdamon_start()setsctx->kdamondbeforedamon_call()starts the cancelling,damon_call()can indefinitely hang. No DAMON API caller does such parallel execution ofdamon_start()anddamon_call(), so the issue doesn't exist. But who knows what will happen in future. Add a clarification comment for caution.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=5
SJ Park
maintainerRFC PATCH v2 6/10 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 v2 06/10] 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 v2 7/10 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
@@ -835,6 +835,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 ; }
@@ -898,6 +901,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 v2 07/10] 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=7
SJ Park
maintainerRFC PATCH v2 8/10 mm/damon/tests/core-kunit: add probe_hits_wsum damos filter commit test
In reply to SJ ParkDAMOS filter commit kunit test lacks test cases for probe_hits_wsum filter type. Add test cases for probe_hits_wsum type DAMOS filter commit.
--- mm/damon/tests/core-kunit.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
mm/damon/tests/core-kunit.h +20 -0
@@ -1166,6 +1166,10 @@ static void damos_test_commit_filter_for(struct kunit *test,KUNIT_EXPECT_EQ (test, dst->sz_range.min, src->sz_range.min);KUNIT_EXPECT_EQ (test, dst->sz_range.max, src->sz_range.max);break ; +case DAMOS_FILTER_TYPE_PROBE_HITS_WSUM : +KUNIT_EXPECT_EQ (test, dst->range_min, src->range_min); +KUNIT_EXPECT_EQ (test, dst->range_max, src->range_max); +break ;default :break ; }
@@ -1239,6 +1243,22 @@ static void damos_test_commit_filter(struct kunit *test) .allow = true, .target_idx =6 , }, false); +damos_test_commit_filter_for (test, &dst, + &(struct damos_filter ){ + .type =DAMOS_FILTER_TYPE_PROBE_HITS_WSUM , + .matching = false, + .allow = true, + .range_min =12 , + .range_max =34 , + }, false); +damos_test_commit_filter_for (test, &dst, + &(struct damos_filter ){ + .type =DAMOS_FILTER_TYPE_PROBE_HITS_WSUM , + .matching = false, + .allow = true, + .range_min =34 , + .range_max =12 , + }, true); }static void damos_test_help_initailize_scheme (struct damos *scheme)
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH v2 08/10] mm/damon/tests/core-kunit: add probe_hits_wsum damos filter commit test
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
DAMOS filter commit kunit test lacks test cases for
probe_hits_wsumfilter type. Add test cases forprobe_hits_wsumtype DAMOS filter commit.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 v2 9/10 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; apparently 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 v2 09/10] selftests/damon/sysfs_memcg_path_leak: fail only for real DAMON leak
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
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.
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
SJ Park
maintainerRFC PATCH v2 10/10 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 v2 10/10] Docs/mm/damon/design: clarify bp is basis point
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 8 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]>Acked-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=10