* [RFC PATCH] mm/damon/core: use time_in_range() for damos quota window start
@ 2026-03-28 16:39 SeongJae Park
2026-03-28 17:00 ` (sashiko review) " SeongJae Park
0 siblings, 1 reply; 3+ messages in thread
From: SeongJae Park @ 2026-03-28 16:39 UTC (permalink / raw)
Cc: SeongJae Park, # 5 . 16 . x, Andrew Morton, damon, linux-kernel,
linux-mm
damos_adjust_quota() uses time_after_eq() to show if it is time to start
a new quota charge window, comparing the current jiffies and the
scheduled next charge window start time. If it is, the next charge
window start time is updated and the new charge window starts.
The time check and next window start time update is skipped while the
scheme is deactivated by the watermarks. Let's suppose the deactivation
is kept more than LONG_MAX jiffies (assuming CONFIG_HZ of 250, more than
99 days in 32 bit systems and more than one billion years in 64 bit
systems), resulting in having the jiffies larger than the next charge
window start time + LONG_MAX. Then, the time_after_eq() call can return
false until another LONG_MAX jiffies are passed.
This means the scheme can continue working after being reactivated by
the watermarks. But, soon, the quota will be exceeded and the scheme
will again effectively stop working until the next charge window starts.
Because the current charge window is extended to up to LONG_MAX jiffies,
however, it will look like it stopped unexpectedly and indefinitely,
from the user's perspective.
Fix this by using !time_in_range() instead.
The issue was discovered [1] by sashiko.
[1] https://lore.kernel.org/20260324040722.57944-1-sj@kernel.org
Fixes: ee801b7dd782 ("mm/damon/schemes: activate schemes based on a watermarks mechanism")
Cc: <stable@vger.kernel.org> # 5.16.x
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 3298ee8d8f64..19ae388ff1e0 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2449,7 +2449,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)
}
/* New charge window starts */
- if (time_after_eq(jiffies, quota->charged_from +
+ if (!time_in_range(jiffies, quota->charged_from, quota->charged_from +
msecs_to_jiffies(quota->reset_interval))) {
if (damos_quota_is_set(quota) &&
quota->charged_sz >= quota->esz)
base-commit: f16846f15feb80ea9553b860bd0f70d9072101aa
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: (sashiko review) [RFC PATCH] mm/damon/core: use time_in_range() for damos quota window start
2026-03-28 16:39 [RFC PATCH] mm/damon/core: use time_in_range() for damos quota window start SeongJae Park
@ 2026-03-28 17:00 ` SeongJae Park
2026-03-28 17:03 ` SeongJae Park
0 siblings, 1 reply; 3+ messages in thread
From: SeongJae Park @ 2026-03-28 17:00 UTC (permalink / raw)
To: SeongJae Park; +Cc: # 5 . 16 . x, Andrew Morton, damon, linux-kernel, linux-mm
Forwarding Sashiko review for doing discussions via mails.
# review url: https://sashiko.dev/#/patchset/20260328163930.47096-1-sj@kernel.org
# start of sashiko.dev inline review
commit 2ee07f5a4fcf25b39aeac61c6b88fe3fdfd0c9b6
Author: SeongJae Park <sj@kernel.org>
mm/damon/core: use time_in_range() for damos quota window start
This commit attempts to fix a stall in DAMOS quota charge windows when
a scheme is deactivated for more than LONG_MAX jiffies. It replaces
time_after_eq() with !time_in_range() to properly handle the extended
time wrap-around.
Link: https://lore.kernel.org/20260324040722.57944-1-sj@kernel.org
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index db6c67e52d2b..8e47183473d3 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2452,7 +2452,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)
> }
>
> /* New charge window starts */
> - if (time_after_eq(jiffies, quota->charged_from +
> + if (!time_in_range(jiffies, quota->charged_from, quota->charged_from +
> msecs_to_jiffies(quota->reset_interval))) {
Does this introduce an off-by-one regression that extends every quota charge
window by 1 jiffy?
time_in_range(a, b, c) evaluates the inclusive interval [b, c], which means
it returns true when jiffies exactly equals the end of the interval. The
original code used time_after_eq(), which correctly triggered the new
charge window exactly on that jiffy.
By replacing it with !time_in_range(), the reset evaluates to false on that
exact jiffy and is delayed until the next jiffy. For small reset_interval
configurations or low CONFIG_HZ values, this 1-jiffy delay might alter the
effective quota replenishment rate.
Would using !time_in_range_open() preserve the exact original timing
semantics while still fixing the wrap-around stall issue?
> if (damos_quota_is_set(quota) &&
> quota->charged_sz >= quota->esz)
# end of sashiko.dev inline review
# review url: https://sashiko.dev/#/patchset/20260328163930.47096-1-sj@kernel.org
#
# hkml [1] generated a draft of this mail. It can be regenerated
# using below command:
#
# hkml patch sashiko_dev --for_forwarding \
# 20260328163930.47096-1-sj@kernel.org
#
# [1] https://github.com/sjp38/hackermail
Sent using hkml (https://github.com/sjp38/hackermail)
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: (sashiko review) [RFC PATCH] mm/damon/core: use time_in_range() for damos quota window start
2026-03-28 17:00 ` (sashiko review) " SeongJae Park
@ 2026-03-28 17:03 ` SeongJae Park
0 siblings, 0 replies; 3+ messages in thread
From: SeongJae Park @ 2026-03-28 17:03 UTC (permalink / raw)
To: SeongJae Park; +Cc: # 5 . 16 . x, Andrew Morton, damon, linux-kernel, linux-mm
On Sat, 28 Mar 2026 10:00:08 -0700 SeongJae Park <sj@kernel.org> wrote:
> Forwarding Sashiko review for doing discussions via mails.
>
> # review url: https://sashiko.dev/#/patchset/20260328163930.47096-1-sj@kernel.org
> # start of sashiko.dev inline review
> commit 2ee07f5a4fcf25b39aeac61c6b88fe3fdfd0c9b6
> Author: SeongJae Park <sj@kernel.org>
>
> mm/damon/core: use time_in_range() for damos quota window start
>
> This commit attempts to fix a stall in DAMOS quota charge windows when
> a scheme is deactivated for more than LONG_MAX jiffies. It replaces
> time_after_eq() with !time_in_range() to properly handle the extended
> time wrap-around.
>
> Link: https://lore.kernel.org/20260324040722.57944-1-sj@kernel.org
>
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index db6c67e52d2b..8e47183473d3 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -2452,7 +2452,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)
> > }
> >
> > /* New charge window starts */
> > - if (time_after_eq(jiffies, quota->charged_from +
> > + if (!time_in_range(jiffies, quota->charged_from, quota->charged_from +
> > msecs_to_jiffies(quota->reset_interval))) {
>
> Does this introduce an off-by-one regression that extends every quota charge
> window by 1 jiffy?
>
> time_in_range(a, b, c) evaluates the inclusive interval [b, c], which means
> it returns true when jiffies exactly equals the end of the interval. The
> original code used time_after_eq(), which correctly triggered the new
> charge window exactly on that jiffy.
>
> By replacing it with !time_in_range(), the reset evaluates to false on that
> exact jiffy and is delayed until the next jiffy. For small reset_interval
> configurations or low CONFIG_HZ values, this 1-jiffy delay might alter the
> effective quota replenishment rate.
The effect should be negligible, but good finding.
>
> Would using !time_in_range_open() preserve the exact original timing
> semantics while still fixing the wrap-around stall issue?
Good suggestion, I will do so in the next revision.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-03-28 17:03 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-28 16:39 [RFC PATCH] mm/damon/core: use time_in_range() for damos quota window start SeongJae Park
2026-03-28 17:00 ` (sashiko review) " SeongJae Park
2026-03-28 17:03 ` SeongJae Park
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox