mm/damon: update probe hits for runtime parameter commits
Subsystems (2)
SJ Park
maintainercover mm/damon: update probe hits for runtime parameter commits
DAMON users can update DAMON parameters such as sampling and aggregation intervals at runtime. For such changes, monitoring results that depend on the intervals should be properly updated for better accuracy. For example, the access frequency counter (nr_accesses) is updated. The data attribute monitoring counter (probe_hits) is not being updated, though. Do the updates for new parameters.
Patches Sequence
================
Patch 1 removes obsolete comments and test code for a function that this series will touch. Patches 2-5 rename functions that are being used for nr_accesses update, to be able to be used for probe_hits without confusion. Patch 6 does the probe_hits update. Patch 7 update damon_probe_hits_mvsum() to cover a corner case from the update for better accuracy.
Changelog
=========
Changes from RFC v1.2
- RFC v1.2: https://lore.kernel.org/[email protected]
- Fix rebase failure-caused kunit break in patch 1.
Changes from RFC v1.1
- RFC v1.1: https://lore.kernel.org/[email protected]
- Remove obsolete divide-by-zero test with comments as a separate patch.
- Remove obsolete comment removal part in a rename commit message.
- Rename name-changed function parameters.
Changes from RFC
- RFC: https://lore.kernel.org/[email protected]
- Remove obsolete comment and code on the test.
SJ Park (7):
mm/damon/core: remove comment and test for nr_to_bp() divide-by-zero mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/ mm/damon/core: s/accesses_bp_to_nr_accesses/sample_bp_to_count/ mm/damon/core: s/nr_accesses_to_accesses_bp/sample_count_to_bp/ mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/ mm/damon/core: update probe hits for new parameter commit mm/damon/core: handle unreset probe_hits in probe_hits_mvsum()
include/linux/damon.h | 10 +++--- mm/damon/core.c | 65 +++++++++++++++++++++++-------------- mm/damon/lru_sort.c | 2 +- mm/damon/ops-common.c | 2 +- mm/damon/tests/core-kunit.h | 36 ++++++-------------- 5 files changed, 59 insertions(+), 56 deletions(-)
base-commit: 82154b14568e9b7abebe2fc9240eafd031e01b30
Signature · 1 line
2.47.3
SJ Park
maintainerRFC PATCH 1/7 mm/damon/core: remove comment and test for nr_to_bp() divide-by-zero
The comments on damon_nr_accesses_to_accesses_bp() and its unit test warn it can trigger division-by-zero when the aggregation interval is zero. Commit 35d4a3cf70a8 ("mm/damon/ops-common: handle extreme intervals in damon_hot_score()") modified damon_nr_samples_per_aggr() to always return non-zero. Hence no division-by-zero of the note can happen. Remove the obsolete comment on the function. The test code was written to test the division-by-zero case, which cannot happen anymore. Having it makes no sense. Entirely remove the test code and its comment.
--- mm/damon/core.c | 8 +------- mm/damon/tests/core-kunit.h | 23 ----------------------- 2 files changed, 1 insertion(+), 30 deletions(-)
mm/damon/core.c +1 -7
@@ -883,13 +883,7 @@ static unsigned int damon_accesses_bp_to_nr_accesses(return accesses_bp *damon_max_nr_accesses (attrs) /10000 ; } -/* -* Convert nr_accesses to access ratio in bp (per 10,000). -* -* Callers should ensure attrs.aggr_interval is not zero, like -* damon_update_monitoring_results() does . Otherwise, divide-by-zero would -* happen. -*/ +/* Convert nr_accesses to access ratio in bp (per 10,000) */ static unsigned int damon_nr_accesses_to_accesses_bp (unsigned int nr_accesses,struct damon_attrs *attrs) {
mm/damon/tests/core-kunit.h +0 -23
@@ -575,28 +575,6 @@ static void damon_test_set_regions(struct kunit *test) }, 3); } -static void damon_test_nr_accesses_to_accesses_bp (struct kunit *test) -{ -struct damon_attrs attrs = { - .sample_interval =10 , - .aggr_interval = ((unsigned long )UINT_MAX +1 ) *10 - }; - -/* -* In some cases such as 32bit architectures where UINT_MAX is -* ULONG_MAX, attrs.aggr_interval becomes zero. Calling -* damon_nr_accesses_to_accesses_bp() in the case will cause -* divide-by-zero. Such case is prohibited in normal execution since -* the caution is documented on the comment for the function, and -* damon_update_monitoring_results() does the check. Skip the test in -* the case. -*/ -if (!attrs.aggr_interval) -kunit_skip (test,"aggr_interval is zero." ); - -KUNIT_EXPECT_EQ (test,damon_nr_accesses_to_accesses_bp (123 , &attrs),0 ); -} -static void damon_test_update_monitoring_result (struct kunit *test) {struct damon_attrs old_attrs = {
@@ -1572,7 +1550,6 @@ static struct kunit_case damon_test_cases[] = {KUNIT_CASE (damon_test_split_above_half_progresses),KUNIT_CASE (damon_test_ops_registration),KUNIT_CASE (damon_test_set_regions), -KUNIT_CASE (damon_test_nr_accesses_to_accesses_bp),KUNIT_CASE (damon_test_update_monitoring_result),KUNIT_CASE (damon_test_set_attrs), KUNIT_CASE(damon_test_mvsum),
Signature · 1 line
2.47.3
SJ Park
maintainerRFC PATCH 2/7 mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/
In reply to SJ Parkdamon_max_nr_accesses() actually returns the number of samples DAMON checks for each region per each aggregation interval. Rename it to better describe what it really does and not confusing for more general uses.
--- include/linux/damon.h | 10 ++++++---- mm/damon/core.c | 4 ++-- mm/damon/lru_sort.c | 2 +- mm/damon/ops-common.c | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-)
include/linux/damon.h +6 -4
@@ -1056,15 +1056,17 @@ static inline bool damon_target_has_pid(const struct damon_ctx *ctx)return ctx->ops.id ==DAMON_OPS_VADDR || ctx->ops.id ==DAMON_OPS_FVADDR ; } -static inline unsigned int damon_max_nr_accesses (const struct damon_attrs *attrs) +/* Returns number of samples per aggregation interval */ +static inline unsigned int damon_nr_samples_per_aggr ( +const struct damon_attrs *attrs) {unsigned long sample_interval; -unsigned long max_nr_accesses; +unsigned long nr_samples; sample_interval = attrs->sample_interval ? :1 ; - max_nr_accesses =min (attrs->aggr_interval / sample_interval, + nr_samples =min (attrs->aggr_interval / sample_interval, (unsigned long )UINT_MAX ); -return max_nr_accesses ? :1 ; +return nr_samples ? :1 ; }
mm/damon/core.c +2 -2
@@ -880,14 +880,14 @@ static unsigned int damon_age_for_new_attrs(unsigned int age,static unsigned int damon_accesses_bp_to_nr_accesses (unsigned int accesses_bp,struct damon_attrs *attrs) { -return accesses_bp *damon_max_nr_accesses (attrs) /10000 ; +return accesses_bp *damon_nr_samples_per_aggr (attrs) /10000 ; }/* Convert nr_accesses to access ratio in bp (per 10,000) */ static unsigned int damon_nr_accesses_to_accesses_bp (unsigned int nr_accesses,struct damon_attrs *attrs) { -return mult_frac (nr_accesses,10000 ,damon_max_nr_accesses (attrs)); +return mult_frac (nr_accesses,10000 ,damon_nr_samples_per_aggr (attrs)); } static unsigned int damon_nr_accesses_for_new_attrs(unsigned int nr_accesses,
mm/damon/lru_sort.c +1 -1
@@ -303,7 +303,7 @@ static int damon_lru_sort_apply_parameters(void) goto out; err = -ENOMEM ; - hot_thres =damon_max_nr_accesses (&attrs) * + hot_thres =damon_nr_samples_per_aggr (&attrs) * hot_thres_access_freq /1000 ; hot_scheme =damon_lru_sort_new_hot_scheme (hot_thres);if (!hot_scheme)
mm/damon/ops-common.c +1 -1
@@ -112,7 +112,7 @@ int damon_hot_score(struct damon_ctx *c, struct damon_region *r,int hotness; freq_subscore = r->nr_accesses *DAMON_MAX_SUBSCORE / -damon_max_nr_accesses (&c->attrs); +damon_nr_samples_per_aggr (&c->attrs); age_in_sec = (unsigned long )r->age * c->attrs.aggr_interval /1000000 ;if (age_in_sec)
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH v1.3 2/7] mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Arithmetic overflow in DAMON access frequency calculations for large sample counts. --
--- Patch [2]: [RFC PATCH v1.3 2/7] mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/ --- commit f4e38af8a3753be681be346a7474a71c5bfadd23
Author: SJ Park <[email protected]>
mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/
This commit renames damon_max_nr_accesses() to damon_nr_samples_per_aggr() to better describe that it returns the number of samples DAMON checks for each region per aggregation interval.
Quoted 4 lines
mm/damon/core.c +0
-0
[ ... ]
mm/damon/core.c static unsigned int damon_age_for_new_attrs(unsigned int age, · line 884
Quoted 7 lines
mm/damon/core.c +1
-1@@ -880,14 +880,14 @@ static unsigned int damon_age_for_new_attrs(unsigned int age,static unsigned int damon_accesses_bp_to_nr_accesses (unsigned int accesses_bp,struct damon_attrs *attrs) { -return accesses_bp *damon_max_nr_accesses (attrs) /10000 ; +return accesses_bp *damon_nr_samples_per_aggr (attrs) /10000 ; }
[Severity: High]
This is a pre-existing issue, but does multiplying accesses_bp by damon_nr_samples_per_aggr() overflow 32-bit arithmetic?
If the total samples exceed ~429,496 (e.g., by configuring a large ratio between the aggregation interval and sample interval), this calculation seems to wrap around, leading to a drastically lower access count threshold.
mm/damon/core.c static unsigned int damon_age_for_new_attrs(unsigned int age, · line 891
Quoted 7 lines
mm/damon/core.c +1
-1/* Convert nr_accesses to access ratio in bp (per 10,000) */ static unsigned int damon_nr_accesses_to_accesses_bp (unsigned int nr_accesses,struct damon_attrs *attrs) { -return mult_frac (nr_accesses,10000 ,damon_max_nr_accesses (attrs)); +return mult_frac (nr_accesses,10000 ,damon_nr_samples_per_aggr (attrs)); }
[Severity: High]
This isn't a bug introduced by this patch, but can this use of mult_frac() overflow?
The mult_frac macro internally multiplies the remainder of nr_accesses by 10000, which appears to overflow 32-bit math for large interval configurations.
Quoted 4 lines
mm/damon/lru_sort.c +0
-0
[ ... ]
mm/damon/lru_sort.c static int damon_lru_sort_apply_parameters(void) · line 307
Quoted 7 lines
mm/damon/lru_sort.c +1
-1@@ -303,7 +303,7 @@ static int damon_lru_sort_apply_parameters(void) goto out; err = -ENOMEM ; - hot_thres =damon_max_nr_accesses (&attrs) * + hot_thres =damon_nr_samples_per_aggr (&attrs) * hot_thres_access_freq /1000 ;
[Severity: High]
This is a pre-existing issue, but does this calculation overflow hot_thres?
Multiplication of the samples by hot_thres_access_freq (typically hundreds) looks like it overflows a 32-bit integer when calculating the hot threshold if samples exceed ~8.5 million.
Quoted 4 lines
mm/damon/ops-common.c +0
-0
[ ... ]
mm/damon/ops-common.c int damon_hot_score(struct damon_ctx *c, struct damon_region *r, · line 115
Quoted 6 lines
mm/damon/ops-common.c +1
-1@@ -112,7 +112,7 @@ int damon_hot_score(struct damon_ctx *c, struct damon_region *r,int hotness; freq_subscore = r->nr_accesses *DAMON_MAX_SUBSCORE / -damon_max_nr_accesses (&c->attrs); +damon_nr_samples_per_aggr (&c->attrs);
[Severity: High]
This isn't a bug introduced by this patch, but could this multiplication cause an integer overflow?
The r->nr_accesses variable is multiplied by DAMON_MAX_SUBSCORE, which is
100. If nr_accesses exceeds ~42.9 million, it overflows a 32-bit integer, resulting in a drastically lower or zeroed hotness score. This could lead to miscalculating region hotness and erroneously reclaiming actively used pages.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
SJ Park
maintainerRe: [RFC PATCH v1.3 2/7] mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/
Quoted 35 lines · On Wed, 08 Jul 2026 02:58:18 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Arithmetic overflow in DAMON access frequency calculations for large sample counts. ----- Patch [2]: [RFC PATCH v1.3 2/7]
mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/ --- commitf4e38af8a3753be681be346a7474a71c5bfadd23
Author: SJ Park <[email protected]>
mm/damon/core: s/damon_max_nr_accesses()/damon_nr_samples_per_aggr()/This commit renames
damon_max_nr_accesses()todamon_nr_samples_per_aggr()to better describe that it returns the number of samples DAMON checks for each region per aggregation interval.Quoted 4 lines
mm/damon/core.c +0
-0[ ... ]
mm/damon/core.c static unsigned int damon_age_for_new_attrs(unsigned int age, · line 884
Quoted 7 lines
mm/damon/core.c +1
-1@@ -880,14 +880,14 @@ static unsigned int damon_age_for_new_attrs(unsigned int age,static unsigned int damon_accesses_bp_to_nr_accesses (unsigned int accesses_bp,struct damon_attrs *attrs) { -return accesses_bp *damon_max_nr_accesses (attrs) /10000 ; +return accesses_bp *damon_nr_samples_per_aggr (attrs) /10000 ; }[Severity: High]
This is a pre-existing issue, but does multiplyingaccesses_bpbydamon_nr_samples_per_aggr()overflow 32-bit arithmetic?
Quoted 3 lines
If the total samples exceed ~429,496 (e.g., by configuring a large ratio between the aggregation interval and sample interval), this calculation seems to wrap around, leading to a drastically lower access count threshold.
Known low priority issue.
Quoted 13 lines
mm/damon/core.c static unsigned int damon_age_for_new_attrs(unsigned int age, · line 891
Quoted 8 lines
mm/damon/core.c +1
-1/* Convert nr_accesses to access ratio in bp (per 10,000) */ static unsigned int damon_nr_accesses_to_accesses_bp (unsigned int nr_accesses,struct damon_attrs *attrs) { -return mult_frac (nr_accesses,10000 ,damon_max_nr_accesses (attrs)); +return mult_frac (nr_accesses,10000 ,damon_nr_samples_per_aggr (attrs)); }[Severity: High]
This isn't a bug introduced by this patch, but can this use ofmult_frac()overflow?
Quoted 3 lines
The
mult_fracmacro internally multiplies the remainder ofnr_accessesby 10000, which appears to overflow 32-bit math for large interval configurations.
Known low priority issue.
Quoted 19 lines
Quoted 5 lines
mm/damon/lru_sort.c +0
-0[ ... ]
mm/damon/lru_sort.c static int damon_lru_sort_apply_parameters(void) · line 307
Quoted 7 lines
mm/damon/lru_sort.c +1
-1@@ -303,7 +303,7 @@ static int damon_lru_sort_apply_parameters(void) goto out; err = -ENOMEM ; - hot_thres =damon_max_nr_accesses (&attrs) * + hot_thres =damon_nr_samples_per_aggr (&attrs) * hot_thres_access_freq /1000 ;[Severity: High]
This is a pre-existing issue, but does this calculation overflowhot_thres?
Quoted 3 lines
Multiplication of the samples by
hot_thres_access_freq(typically hundreds) looks like it overflows a 32-bit integer when calculating the hot threshold if samples exceed ~8.5 million.
Known low priority issue.
Quoted 19 lines
Quoted 5 lines
mm/damon/ops-common.c +0
-0[ ... ]
mm/damon/ops-common.c int damon_hot_score(struct damon_ctx *c, struct damon_region *r, · line 115
Quoted 6 lines
mm/damon/ops-common.c +1
-1@@ -112,7 +112,7 @@ int damon_hot_score(struct damon_ctx *c, struct damon_region *r,int hotness; freq_subscore = r->nr_accesses *DAMON_MAX_SUBSCORE / -damon_max_nr_accesses (&c->attrs); +damon_nr_samples_per_aggr (&c->attrs);[Severity: High]
This isn't a bug introduced by this patch, but could this multiplication cause an integer overflow?
Quoted 4 lines
The
r->nr_accessesvariable is multiplied byDAMON_MAX_SUBSCORE, which is
100. Ifnr_accessesexceeds ~42.9 million, it overflows a 32-bit integer, resulting in a drastically lower or zeroed hotness score. This could lead to miscalculating region hotness and erroneously reclaiming actively used pages.
Known low priority issue.
Quoted 3 lines
Signature · 2 lines
-- Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Thanks,
SJ
SJ Park
maintainerRFC PATCH 3/7 mm/damon/core: s/accesses_bp_to_nr_accesses/sample_bp_to_count/
In reply to SJ Parkaccesses_bp_to_nr_accesses() actually converts a positive samples ratio to the count. Rename it to better describe what it really does and not confusing for more general uses.
--- mm/damon/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
mm/damon/core.c +5 -5
@@ -876,11 +876,11 @@ static unsigned int damon_age_for_new_attrs(unsigned int age,return age * old_attrs->aggr_interval / new_attrs->aggr_interval; } -/* convert access ratio in bp (per 10,000) to nr_accesses */ -static unsigned int damon_accesses_bp_to_nr_accesses ( -unsigned int accesses_bp,struct damon_attrs *attrs) +/* convert sample ratio in bp (per 10,000) to count */ +static unsigned int damon_sample_bp_to_count ( +unsigned int bp,struct damon_attrs *attrs) { -return accesses_bp *damon_nr_samples_per_aggr (attrs) /10000 ; +return bp *damon_nr_samples_per_aggr (attrs) /10000 ; }/* Convert nr_accesses to access ratio in bp (per 10,000) */
@@ -893,7 +893,7 @@ static unsigned int damon_nr_accesses_to_accesses_bp(static unsigned int damon_nr_accesses_for_new_attrs (unsigned int nr_accesses,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs) { -return damon_accesses_bp_to_nr_accesses ( +return damon_sample_bp_to_count (damon_nr_accesses_to_accesses_bp ( nr_accesses, old_attrs), new_attrs);
Signature · 1 line
2.47.3
SJ Park
maintainerRFC PATCH 4/7 mm/damon/core: s/nr_accesses_to_accesses_bp/sample_count_to_bp/
In reply to SJ Parkdamon_nr_accesses_to_accesses_bp() actually converts a positive sample count to the ratio. Rename it to better describe what it really does and not confusing for more general uses.
--- mm/damon/core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
mm/damon/core.c +5 -6
@@ -883,19 +883,18 @@ static unsigned int damon_sample_bp_to_count(return bp *damon_nr_samples_per_aggr (attrs) /10000 ; } -/* Convert nr_accesses to access ratio in bp (per 10,000) */ -static unsigned int damon_nr_accesses_to_accesses_bp ( -unsigned int nr_accesses,struct damon_attrs *attrs) +/* convert sample count to ratio in bp (per 10,000) */ +static unsigned int damon_sample_count_to_bp ( +unsigned int count,struct damon_attrs *attrs) { -return mult_frac (nr_accesses,10000 ,damon_nr_samples_per_aggr (attrs)); +return mult_frac (count,10000 ,damon_nr_samples_per_aggr (attrs)); }static unsigned int damon_nr_accesses_for_new_attrs (unsigned int nr_accesses,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs) {return damon_sample_bp_to_count ( -damon_nr_accesses_to_accesses_bp ( - nr_accesses, old_attrs), +damon_sample_count_to_bp (nr_accesses, old_attrs), new_attrs); }
Signature · 1 line
2.47.3
SJ Park
maintainerRFC PATCH 5/7 mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/
In reply to SJ Parkdamon_nr_accesses_for_new_attrs() can be used for not only nr_accesses but also any positive sample count, like probe_hits. Rename to be able to be used for such general uses without confusion.
--- mm/damon/core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
mm/damon/core.c +4 -5
@@ -890,22 +890,21 @@ static unsigned int damon_sample_count_to_bp(return mult_frac (count,10000 ,damon_nr_samples_per_aggr (attrs)); } -static unsigned int damon_nr_accesses_for_new_attrs (unsigned int nr_accesses, +static unsigned int damon_nr_samples_for_new_attrs (unsigned int nr,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs) {return damon_sample_bp_to_count ( -damon_sample_count_to_bp (nr_accesses, old_attrs), - new_attrs); +damon_sample_count_to_bp (nr, old_attrs), new_attrs); }static void damon_update_monitoring_result (struct damon_region *r,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs,bool aggregating) { - r->last_nr_accesses =damon_nr_accesses_for_new_attrs ( + r->last_nr_accesses =damon_nr_samples_for_new_attrs ( r->last_nr_accesses, old_attrs, new_attrs);if (!aggregating) - r->nr_accesses =damon_nr_accesses_for_new_attrs ( + r->nr_accesses =damon_nr_samples_for_new_attrs ( r->nr_accesses, old_attrs, new_attrs);else /*
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH v1.3 5/7] mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] 32-bit integer overflow in sample scaling functions damon_sample_bp_to_count and damon_sample_count_to_bp. --
--- Patch [5]: [RFC PATCH v1.3 5/7] mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/ --- commit 9db3c90e1f930b4b71612a504362560074396989
Author: SJ Park <[email protected]>
mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/
damon_nr_accesses_for_new_attrs() can be used for not only nr_accesses but also any positive sample count, like probe_hits. Rename to be able to be used for such general uses without confusion.
mm/damon/core.c static unsigned int damon_sample_count_to_bp( · line 891
Quoted 7 lines
mm/damon/core.c +0
-0@@ -890,22 +890,21 @@ static unsigned int damon_sample_count_to_bp(return mult_frac (count,10000 ,damon_nr_samples_per_aggr (attrs)); }
[Severity: High]
This isn't a bug introduced by this patch, but can the 32-bit unsigned integer multiplication here and in damon_sample_bp_to_count() overflow?
When a privileged user configures an aggregation to sample interval ratio greater than ~429,496 via sysfs (e.g., 10s aggregation and 10us sampling), the mult_frac() macro performs a 32-bit multiplication of the remainder by 10000. This could overflow when the remainder exceeds 429,496.
Similarly, in damon_sample_bp_to_count():
mm/damon/core.c:damon_sample_bp_to_count() {
...
return bp * damon_nr_samples_per_aggr(attrs) / 10000;
}The expression bp * damon_nr_samples_per_aggr(attrs) is performed as a 32-bit unsigned int multiplication, which could overflow 4.29B.
Could this overflow silently corrupt region access counts, causing DAMON to make incorrect memory management decisions like paging out actively used memory?
Quoted 10 lines
mm/damon/core.c +2
-3-static unsigned int damon_nr_accesses_for_new_attrs (unsigned int nr_accesses, +static unsigned int damon_nr_samples_for_new_attrs (unsigned int nr,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs) {return damon_sample_bp_to_count ( -damon_sample_count_to_bp (nr_accesses, old_attrs), - new_attrs); +damon_sample_count_to_bp (nr, old_attrs), new_attrs); }
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
SJ Park
maintainerRe: [RFC PATCH v1.3 5/7] mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/
Quoted 40 lines · On Wed, 08 Jul 2026 03:01:54 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] 32-bit integer overflow in sample scaling functionsdamon_sample_bp_to_countanddamon_sample_count_to_bp. ----- Patch [5]: [RFC PATCH v1.3 5/7]
mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/ --- commit9db3c90e1f930b4b71612a504362560074396989
Author: SJ Park <[email protected]>
mm/damon/core: s/nr_accesses_for_new_attrs/nr_samples_for_new_attrs/
damon_nr_accesses_for_new_attrs()can be used for not onlynr_accessesbut also any positive sample count, likeprobe_hits. Rename to be able to be used for such general uses without confusion.mm/damon/core.c static unsigned int damon_sample_count_to_bp( · line 891
Quoted 7 lines
mm/damon/core.c +0
-0@@ -890,22 +890,21 @@ static unsigned int damon_sample_count_to_bp(return mult_frac (count,10000 ,damon_nr_samples_per_aggr (attrs)); }[Severity: High]
This isn't a bug introduced by this patch, but can the 32-bit unsigned integer multiplication here and indamon_sample_bp_to_count()overflow?When a privileged user configures an aggregation to sample interval ratio greater than ~429,496 via sysfs (e.g., 10s aggregation and 10us sampling), the
mult_frac()macro performs a 32-bit multiplication of the remainder by 10000. This could overflow when the remainder exceeds 429,496.Similarly, in
damon_sample_bp_to_count():mm/damon/core.c:damon_sample_bp_to_count() { ... return bp * damon_nr_samples_per_aggr(attrs) / 10000; }
Quoted 6 lines
The expression bp *
damon_nr_samples_per_aggr(attrs)is performed as a 32-bit unsigned int multiplication, which could overflow 4.29B.Could this overflow silently corrupt region access counts, causing DAMON to make incorrect memory management decisions like paging out actively used memory?
Knowwn low priority issue.
Quoted 14 lines
Quoted 11 lines
mm/damon/core.c +2
-3-static unsigned int damon_nr_accesses_for_new_attrs (unsigned int nr_accesses, +static unsigned int damon_nr_samples_for_new_attrs (unsigned int nr,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs) {return damon_sample_bp_to_count ( -damon_sample_count_to_bp (nr_accesses, old_attrs), - new_attrs); +damon_sample_count_to_bp (nr, old_attrs), new_attrs); }Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
Thanks,
SJ
SJ Park
maintainerRFC PATCH 6/7 mm/damon/core: update probe hits for new parameter commit
In reply to SJ ParkUsers can update DAMON parameters at runtime. If the samples and/or aggregation intervals are updated in this way, monitoring results depending on the intervals should also be updated for a more accurate snapshot. The age and nr_accesses are properly updated, while probe_hits are not updated in the way. Do the update.
--- mm/damon/core.c | 28 +++++++++++++++++++++++++--- mm/damon/tests/core-kunit.h | 13 ++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-)
mm/damon/core.c +25 -3
@@ -897,10 +897,32 @@ static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, damon_sample_count_to_bp(nr, old_attrs), new_attrs); } +static void damon_update_probe_hits (struct damon_region *r, +struct damon_attrs *old_attrs,struct damon_attrs *new_attrs, +bool aggregating,struct damon_ctx *ctx) +{ +struct damon_probe *p; +int i =0 ; + +damon_for_each_probe (p, ctx) { + r->last_probe_hits[i] =damon_nr_samples_for_new_attrs ( + r->last_probe_hits[i], old_attrs, new_attrs); +if (!aggregating) + r->probe_hits[i] =damon_nr_samples_for_new_attrs ( + r->probe_hits[i], old_attrs, + new_attrs); +else + r->probe_hits[i] =0 ; + i++; + } +} +static void damon_update_monitoring_result (struct damon_region *r,struct damon_attrs *old_attrs,struct damon_attrs *new_attrs, -bool aggregating) +bool aggregating,struct damon_ctx *ctx) { +damon_update_probe_hits (r, old_attrs, new_attrs, aggregating, ctx); + r->last_nr_accesses =damon_nr_samples_for_new_attrs ( r->last_nr_accesses, old_attrs, new_attrs);if (!aggregating)
@@ -940,8 +962,8 @@ static void damon_update_monitoring_results(struct damon_ctx *ctx,damon_for_each_target (t, ctx)damon_for_each_region (r, t) -damon_update_monitoring_result ( - r, old_attrs, new_attrs, aggregating); +damon_update_monitoring_result (r, old_attrs, new_attrs, + aggregating, ctx); }/*
mm/damon/tests/core-kunit.h +10 -3
@@ -581,32 +581,39 @@ static void damon_test_update_monitoring_result(struct kunit *test) .sample_interval = 10, .aggr_interval = 1000,};struct damon_attrs new_attrs;struct damon_region *r =damon_new_region (3 ,7 ); +struct damon_ctx *ctx;if (!r)kunit_skip (test,"region alloc fail" ); + ctx =damon_new_ctx (); +if (!ctx) { +damon_free_region (r); +kunit_skip (test,"ctx alloc fail" ); + } r->nr_accesses =15 ; r->age =20 ; new_attrs = (struct damon_attrs ){ .sample_interval =100 , .aggr_interval =10000 ,}; -damon_update_monitoring_result (r, &old_attrs, &new_attrs, false); +damon_update_monitoring_result (r, &old_attrs, &new_attrs, false, ctx);KUNIT_EXPECT_EQ (test, r->nr_accesses,15 );KUNIT_EXPECT_EQ (test, r->age,2 ); new_attrs = (struct damon_attrs ){ .sample_interval =1 , .aggr_interval =1000 }; -damon_update_monitoring_result (r, &old_attrs, &new_attrs, false); +damon_update_monitoring_result (r, &old_attrs, &new_attrs, false, ctx);KUNIT_EXPECT_EQ (test, r->nr_accesses,150 );KUNIT_EXPECT_EQ (test, r->age,2 ); new_attrs = (struct damon_attrs ){ .sample_interval =1 , .aggr_interval =100 }; -damon_update_monitoring_result (r, &old_attrs, &new_attrs, false); +damon_update_monitoring_result (r, &old_attrs, &new_attrs, false, ctx);KUNIT_EXPECT_EQ (test, r->nr_accesses,150 );KUNIT_EXPECT_EQ (test, r->age,20 );damon_free_region (r); +damon_destroy_ctx (ctx); }static void damon_test_set_attrs (struct kunit *test)
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [RFC PATCH v1.3 6/7] mm/damon/core: update probe hits for new parameter commit
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Unbounded iteration over `ctx->probes` list writing to the statically sized `probe_hits` array can…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unbounded iteration over ctx->probes list writing to the statically sized probe_hits array can lead to buffer overflow.
- [Medium] Scaling probe_hits and last_probe_hits using damon_nr_samples_for_new_attrs() assigns an unsigned int to an unsigned char, causing silent truncation and data corruption when the scaled count exceeds 255. --
--- Patch [6]: [RFC PATCH v1.3 6/7] mm/damon/core: update probe hits for new parameter commit --- commit 5d7c7277de18e07d88cf49d1f16d870a9dfc0f23
Author: SJ Park <[email protected]>
mm/damon/core: update probe hits for new parameter commit
Users can update DAMON parameters at runtime. If the samples and/or aggregation intervals are updated in this way, monitoring results depending on the intervals should also be updated for a more accurate snapshot. The age and nr_accesses are properly updated, while probe_hits are not updated in the way. Do the update.
Quoted 4 lines
mm/damon/core.c +0
-0
[ ... ]
mm/damon/core.c static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, · line 907
Quoted 12 lines
mm/damon/core.c +8
-0@@ -897,10 +897,32 @@ static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, damon_sample_count_to_bp(nr, old_attrs), new_attrs); } +static void damon_update_probe_hits (struct damon_region *r, +struct damon_attrs *old_attrs,struct damon_attrs *new_attrs, +bool aggregating,struct damon_ctx *ctx) +{ +struct damon_probe *p; +int i =0 ; + +damon_for_each_probe (p, ctx) {
[Severity: High]
Does this loop overflow the r->last_probe_hits[] and r->probe_hits[] arrays?
The probe_hits and last_probe_hits members are defined as fixed-size arrays of size DAMON_MAX_PROBES. Since there is no bounds checking on i, if there are more than DAMON_MAX_PROBES in the ctx->probes list, this will write past the end of the arrays and corrupt adjacent fields in struct damon_region.
mm/damon/core.c static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, · line 909
Quoted 2 lines
mm/damon/core.c +2
-0+ r->last_probe_hits[i] =damon_nr_samples_for_new_attrs ( + r->last_probe_hits[i], old_attrs, new_attrs);
[Severity: Medium]
Will this assignment cause silent truncation and data corruption?
The last_probe_hits and probe_hits arrays are declared as unsigned char (8-bit) in struct damon_region, but damon_nr_samples_for_new_attrs() returns an unsigned int (32-bit).
If the scaled count exceeds 255, assigning it directly will truncate the value to a meaningless modulo-256 wrapped value rather than clamping it at a maximum.
Quoted 10 lines
mm/damon/core.c +10
-0+if (!aggregating) + r->probe_hits[i] =damon_nr_samples_for_new_attrs ( + r->probe_hits[i], old_attrs, + new_attrs); +else + r->probe_hits[i] =0 ; + i++; + } +} +
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
SJ Park
maintainerRe: [RFC PATCH v1.3 6/7] mm/damon/core: update probe hits for new parameter commit
Quoted 40 lines · On Wed, 08 Jul 2026 03:05:43 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unbounded iteration overctx->probeslist writing to the statically sizedprobe_hitsarray can lead to buffer overflow.
- [Medium] Scalingprobe_hitsandlast_probe_hitsusingdamon_nr_samples_for_new_attrs()assigns anunsigned intto anunsigned char, causing silent truncation and data corruption when the scaled count exceeds 255. ----- Patch [6]: [RFC PATCH v1.3 6/7]
mm/damon/core: update probe hits for new parameter commit --- commit5d7c7277de18e07d88cf49d1f16d870a9dfc0f23
Author: SJ Park <[email protected]>
mm/damon/core: update probe hits for new parameter commitUsers can update DAMON parameters at runtime. If the samples and/or aggregation intervals are updated in this way, monitoring results depending on the intervals should also be updated for a more accurate snapshot. The age and
nr_accessesare properly updated, whileprobe_hitsare not updated in the way. Do the update.Quoted 4 lines
mm/damon/core.c +0
-0[ ... ]
mm/damon/core.c static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, · line 907
Quoted 12 lines
mm/damon/core.c +8
-0@@ -897,10 +897,32 @@ static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, damon_sample_count_to_bp(nr, old_attrs), new_attrs); } +static void damon_update_probe_hits (struct damon_region *r, +struct damon_attrs *old_attrs,struct damon_attrs *new_attrs, +bool aggregating,struct damon_ctx *ctx) +{ +struct damon_probe *p; +int i =0 ; + +damon_for_each_probe (p, ctx) {[Severity: High]
Does this loop overflow the r->last_probe_hits[] and r->probe_hits[] arrays?
Quoted 4 lines
The
probe_hitsandlast_probe_hitsmembers are defined as fixed-size arrays of sizeDAMON_MAX_PROBES. Since there is no bounds checking on i, if there are more thanDAMON_MAX_PROBESin thectx->probeslist, this will write past the end of the arrays and corrupt adjacent fields in structdamon_region.
That cannot happen since DAMON_SYSFS is not accepting that input. Readnr_probes_store() for more details.
Quoted 7 lines
mm/damon/core.c static unsigned int damon_nr_samples_for_new_attrs(unsigned int nr, · line 909
Quoted 3 lines
mm/damon/core.c +2
-0+ r->last_probe_hits[i] =damon_nr_samples_for_new_attrs ( + r->last_probe_hits[i], old_attrs, new_attrs);[Severity: Medium]
Will this assignment cause silent truncation and data corruption?
Quoted 6 lines
The
last_probe_hitsandprobe_hitsarrays are declared as unsigned char (8-bit) in structdamon_region, butdamon_nr_samples_for_new_attrs()returns an unsigned int (32-bit).If the scaled count exceeds 255, assigning it directly will truncate the value to a meaningless modulo-256 wrapped value rather than clamping it at a maximum.
Known low priority issue.
Quoted 14 lines
Quoted 11 lines
mm/damon/core.c +10
-0+if (!aggregating) + r->probe_hits[i] =damon_nr_samples_for_new_attrs ( + r->probe_hits[i], old_attrs, + new_attrs); +else + r->probe_hits[i] =0 ; + i++; + } +} +Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
Thanks,
SJ
SJ Park
maintainerRFC PATCH 7/7 mm/damon/core: handle unreset probe_hits in probe_hits_mvsum()
In reply to SJ ParkIf damon_update_monitoring_result() is called at the end of the aggregation interval, probe_hits is not reset. That's because the value will be exposed to the user via damon_region_aggregated trace event.
Meanwhile, damon_probe_hits_mvsum() can be called in this state. Due to its logic, it will return a value that is incorrectly high. This could happen if the user requested DAMOS schemes applied regions sysfs files update exactly in the time sequence.
The impact is minor, but better to avoid. Check the timing and simply return the fully aggregated last_probe_hits, like damon_nr_accesses_mvsum() also does. It is not 100% accurate since it is the last interval's aggregation. But better than the value that is completely reset.
--- mm/damon/core.c | 3 +++ 1 file changed, 3 insertions(+)
mm/damon/core.c +3 -0
@@ -290,6 +290,9 @@ unsigned char damon_probe_hits_mvsum(int probe_idx, struct damon_region *r, ctx->passed_sample_intervals; left_window_bp =mult_frac (left_window,10000 , window_len); +if (left_window_bp ==10000 ) +return r->last_probe_hits[probe_idx]; +return damon_mvsum (r->probe_hits[probe_idx], r->last_probe_hits[probe_idx], left_window_bp); }
Signature · 1 line
2.47.3