public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
* [PATCH 0/3] mm/damon/core: make passed_sample_intervals comparisons overflow-safe
@ 2026-03-07 19:49 SeongJae Park
  2026-03-07 19:49 ` [PATCH 1/3] mm/damon/core: remove damos_set_next_apply_sis() duplicates SeongJae Park
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: SeongJae Park @ 2026-03-07 19:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: SeongJae Park, damon, linux-kernel, linux-mm

DAMON accounts time using its own jiffies-like time counter, namely
damon_ctx->passed_sample_intervals.  The counter is incremented on each
iteration of kdamond_fn() main loop, which sleeps at least one sample
interval.  Hence the name is like that.

DAMON has time-periodic operations including monitoring results
aggregation and DAMOS action application.  DAMON sets the next time to
do each of such operations in the passed_sample_intervals unit.  And it
does the operation when the counter becomes the same to or larger than
the pre-set values, and update the next time for the operation.  Note
that the operation is done not only when the values exactly match but
also when the time is passed, because the values can be updated for
online-committed DAMON parameters.

The counter is 'unsigned long' type, and the comparison is done using
normal comparison operators.  It is not safe from overflows.  This can
cause rare and limited but odd situations.

Let's suppose there is an operation that should be executed every 20
sampling intervals, and the passed_sample_intervals value for next
execution of the operation is ULONG_MAX - 3.  Once the
passed_sample_intervals reaches ULONG_MAX - 3, the operation will be
executed, and the next time value for doing the operation becomes 17
(ULONG_MAX - 3 + 20), since overflow happens.  In the next iteration of
the kdamond_fn() main loop, passed_sample_intervals is larger than the
next operation time value, so the operation will be executed again.  It
will continue executing the operation for each iteration, until the
passed_sample_intervals also overflows.

Note that this will not be common and problematic in the real world.
The sampling interval, which takes for each passed_sample_intervals
increment, is 5 ms by default.  And it is usually [auto-]tuned for
hundreds of milliseconds.  That means it takes about 248 days or 4,971
days to have the overflow on 32 bit machines when the sampling interval
is 5 ms and 100 ms, respectively (1<<32 * sampling_interval_in_seconds /
3600 / 24).  On 64 bit machines, the numbers become 2924712086.77536 and
58494241735.5072 years.  So the real user impact is negligible.  But
still this is better to be fixed as long as the fix is simple and
efficient.

Fix this by simply replacing the overflow-unsafe native comparison
operators with the existing overflow-safe time comparison helpers.

The first patch only cleans up the next DAMOS action application time
setup for consistency and reduced code.  The second and the third
patches update DAMOS action application time setup and rest,
respectively.

SeongJae Park (3):
  mm/damon/core: remove damos_set_next_apply_sis() duplicates
  mm/damon/core: use time_before() for next_apply_sis
  mm/damon/core: use time_after_eq() in kdamond_fn()

 mm/damon/core.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)


base-commit: 4ef41fd88e37fcdc1751edd9bc57403dba2742a3
-- 
2.47.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] mm/damon/core: remove damos_set_next_apply_sis() duplicates
  2026-03-07 19:49 [PATCH 0/3] mm/damon/core: make passed_sample_intervals comparisons overflow-safe SeongJae Park
@ 2026-03-07 19:49 ` SeongJae Park
  2026-03-07 19:49 ` [PATCH 2/3] mm/damon/core: use time_before() for next_apply_sis SeongJae Park
  2026-03-07 19:49 ` [PATCH 3/3] mm/damon/core: use time_after_eq() in kdamond_fn() SeongJae Park
  2 siblings, 0 replies; 4+ messages in thread
From: SeongJae Park @ 2026-03-07 19:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: SeongJae Park, damon, linux-kernel, linux-mm

There is a function for damos->next_apply_sis setup.  But some places
are open-coding it.  Consistently use the helper.

Signed-off-by: SeongJae Park <sj@kernel.org>
---
 mm/damon/core.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index e8c44541754f7..c4c30824465ee 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2450,8 +2450,6 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
 	struct damon_target *t;
 	struct damon_region *r;
 	struct damos *s;
-	unsigned long sample_interval = c->attrs.sample_interval ?
-		c->attrs.sample_interval : 1;
 	bool has_schemes_to_apply = false;
 
 	damon_for_each_scheme(s, c) {
@@ -2482,9 +2480,7 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
 		if (c->passed_sample_intervals < s->next_apply_sis)
 			continue;
 		damos_walk_complete(c, s);
-		s->next_apply_sis = c->passed_sample_intervals +
-			(s->apply_interval_us ? s->apply_interval_us :
-			 c->attrs.aggr_interval) / sample_interval;
+		damos_set_next_apply_sis(s, c);
 		s->last_applied = NULL;
 		damos_trace_stat(c, s);
 	}
@@ -2858,7 +2854,6 @@ static void kdamond_init_ctx(struct damon_ctx *ctx)
 {
 	unsigned long sample_interval = ctx->attrs.sample_interval ?
 		ctx->attrs.sample_interval : 1;
-	unsigned long apply_interval;
 	struct damos *scheme;
 
 	ctx->passed_sample_intervals = 0;
@@ -2869,9 +2864,7 @@ static void kdamond_init_ctx(struct damon_ctx *ctx)
 		ctx->attrs.intervals_goal.aggrs;
 
 	damon_for_each_scheme(scheme, ctx) {
-		apply_interval = scheme->apply_interval_us ?
-			scheme->apply_interval_us : ctx->attrs.aggr_interval;
-		scheme->next_apply_sis = apply_interval / sample_interval;
+		damos_set_next_apply_sis(scheme, ctx);
 		damos_set_filters_default_reject(scheme);
 	}
 }
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] mm/damon/core: use time_before() for next_apply_sis
  2026-03-07 19:49 [PATCH 0/3] mm/damon/core: make passed_sample_intervals comparisons overflow-safe SeongJae Park
  2026-03-07 19:49 ` [PATCH 1/3] mm/damon/core: remove damos_set_next_apply_sis() duplicates SeongJae Park
@ 2026-03-07 19:49 ` SeongJae Park
  2026-03-07 19:49 ` [PATCH 3/3] mm/damon/core: use time_after_eq() in kdamond_fn() SeongJae Park
  2 siblings, 0 replies; 4+ messages in thread
From: SeongJae Park @ 2026-03-07 19:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: SeongJae Park, damon, linux-kernel, linux-mm

damon_ctx->passed_sample_intervals and damos->next_apply_sis are
unsigned long, and compared via normal comparison operators.  It is
unsafe from overflow.  Use time_before(), which is safe from overflow
when correctly used, instead.

Signed-off-by: SeongJae Park <sj@kernel.org>
---
 mm/damon/core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index c4c30824465ee..4ede733a94cc0 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2095,7 +2095,7 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
 	damon_for_each_scheme(s, c) {
 		struct damos_quota *quota = &s->quota;
 
-		if (c->passed_sample_intervals < s->next_apply_sis)
+		if (time_before(c->passed_sample_intervals, s->next_apply_sis))
 			continue;
 
 		if (!s->wmarks.activated)
@@ -2453,7 +2453,7 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
 	bool has_schemes_to_apply = false;
 
 	damon_for_each_scheme(s, c) {
-		if (c->passed_sample_intervals < s->next_apply_sis)
+		if (time_before(c->passed_sample_intervals, s->next_apply_sis))
 			continue;
 
 		if (!s->wmarks.activated)
@@ -2477,7 +2477,7 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
 	}
 
 	damon_for_each_scheme(s, c) {
-		if (c->passed_sample_intervals < s->next_apply_sis)
+		if (time_before(c->passed_sample_intervals, s->next_apply_sis))
 			continue;
 		damos_walk_complete(c, s);
 		damos_set_next_apply_sis(s, c);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] mm/damon/core: use time_after_eq() in kdamond_fn()
  2026-03-07 19:49 [PATCH 0/3] mm/damon/core: make passed_sample_intervals comparisons overflow-safe SeongJae Park
  2026-03-07 19:49 ` [PATCH 1/3] mm/damon/core: remove damos_set_next_apply_sis() duplicates SeongJae Park
  2026-03-07 19:49 ` [PATCH 2/3] mm/damon/core: use time_before() for next_apply_sis SeongJae Park
@ 2026-03-07 19:49 ` SeongJae Park
  2 siblings, 0 replies; 4+ messages in thread
From: SeongJae Park @ 2026-03-07 19:49 UTC (permalink / raw)
  To: Andrew Morton; +Cc: SeongJae Park, damon, linux-kernel, linux-mm

damon_ctx->passed_sample_intervals and damon_ctx->next_*_sis are
unsigned long.  Those are compared in kdamond_fn() using normal
comparison operators.  It is unsafe from overflow.  Use time_after_eq(),
which is safe from overflows when correctly used, instead.

Signed-off-by: SeongJae Park <sj@kernel.org>
---
 mm/damon/core.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index 4ede733a94cc0..cd2d7a8e3fe92 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2915,7 +2915,8 @@ static int kdamond_fn(void *data)
 		if (ctx->ops.check_accesses)
 			max_nr_accesses = ctx->ops.check_accesses(ctx);
 
-		if (ctx->passed_sample_intervals >= next_aggregation_sis) {
+		if (time_after_eq(ctx->passed_sample_intervals,
+					next_aggregation_sis)) {
 			kdamond_merge_regions(ctx,
 					max_nr_accesses / 10,
 					sz_limit);
@@ -2935,10 +2936,12 @@ static int kdamond_fn(void *data)
 
 		sample_interval = ctx->attrs.sample_interval ?
 			ctx->attrs.sample_interval : 1;
-		if (ctx->passed_sample_intervals >= next_aggregation_sis) {
+		if (time_after_eq(ctx->passed_sample_intervals,
+					next_aggregation_sis)) {
 			if (ctx->attrs.intervals_goal.aggrs &&
-					ctx->passed_sample_intervals >=
-					ctx->next_intervals_tune_sis) {
+					time_after_eq(
+						ctx->passed_sample_intervals,
+						ctx->next_intervals_tune_sis)) {
 				/*
 				 * ctx->next_aggregation_sis might be updated
 				 * from kdamond_call().  In the case,
@@ -2972,7 +2975,8 @@ static int kdamond_fn(void *data)
 			kdamond_split_regions(ctx);
 		}
 
-		if (ctx->passed_sample_intervals >= next_ops_update_sis) {
+		if (time_after_eq(ctx->passed_sample_intervals,
+					next_ops_update_sis)) {
 			ctx->next_ops_update_sis = next_ops_update_sis +
 				ctx->attrs.ops_update_interval /
 				sample_interval;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-03-07 19:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-07 19:49 [PATCH 0/3] mm/damon/core: make passed_sample_intervals comparisons overflow-safe SeongJae Park
2026-03-07 19:49 ` [PATCH 1/3] mm/damon/core: remove damos_set_next_apply_sis() duplicates SeongJae Park
2026-03-07 19:49 ` [PATCH 2/3] mm/damon/core: use time_before() for next_apply_sis SeongJae Park
2026-03-07 19:49 ` [PATCH 3/3] mm/damon/core: use time_after_eq() in kdamond_fn() SeongJae Park

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox