[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250706200018.42704-3-sj@kernel.org>
Date: Sun, 6 Jul 2025 13:00:06 -0700
From: SeongJae Park <sj@...nel.org>
To:
Cc: SeongJae Park <sj@...nel.org>,
Andrew Morton <akpm@...ux-foundation.org>,
damon@...ts.linux.dev,
kernel-team@...a.com,
linux-kernel@...r.kernel.org,
linux-mm@...ck.org
Subject: [RFC PATCH 02/14] mm/damon/core: introduce repeat mode damon_call()
damon_call() can be useful for reading or writing DAMON internal data
for one time. A common pattern of DAMON core usage from DAMON modules
is doing such reads and writes repeatedly, for example, to periodically
update the DAMOS stats. To do that with damon_call(), callers should
call damon_call() repeatedly, with their own delay loop. Each caller
doing that is repetitive. Introduce a repeat mode damon_call().
Callers can use the mode by setting a new field in damon_call_control.
If the mode is turned on, damon_call() returns success immediately, and
DAMON repeats invoking the callback function inside the kdamond main
loop.
Signed-off-by: SeongJae Park <sj@...nel.org>
---
include/linux/damon.h | 2 ++
mm/damon/core.c | 23 +++++++++++++++++++----
2 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 9176a1c7d5a8..2d51b575d660 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -659,6 +659,7 @@ struct damon_callback {
*
* @fn: Function to be called back.
* @data: Data that will be passed to @fn.
+ * @repeat: Repeat invocations.
* @return_code: Return code from @fn invocation.
*
* Control damon_call(), which requests specific kdamond to invoke a given
@@ -667,6 +668,7 @@ struct damon_callback {
struct damon_call_control {
int (*fn)(void *data);
void *data;
+ bool repeat;
int return_code;
/* private: internal use only */
/* informs if the kdamond finished handling of the request */
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 01e62bdcdd67..7a4dc76dd023 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1339,8 +1339,9 @@ bool damon_is_running(struct damon_ctx *ctx)
*
* Ask DAMON worker thread (kdamond) of @ctx to call a function with an
* argument data that respectively passed via &damon_call_control->fn and
- * &damon_call_control->data of @control, and wait until the kdamond finishes
- * handling of the request.
+ * &damon_call_control->data of @control. If &damon_call_control->repeat of
+ * @control is set, further wait until the kdamond finishes handling of the
+ * request. Otherwise, return as soon as the request is made.
*
* The kdamond executes the function with the argument in the main loop, just
* after a sampling of the iteration is finished. The function can hence
@@ -1352,7 +1353,8 @@ bool damon_is_running(struct damon_ctx *ctx)
*/
int damon_call(struct damon_ctx *ctx, struct damon_call_control *control)
{
- init_completion(&control->completion);
+ if (!control->repeat)
+ init_completion(&control->completion);
control->canceled = false;
INIT_LIST_HEAD(&control->list);
@@ -1361,6 +1363,8 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control)
mutex_unlock(&ctx->call_controls_lock);
if (!damon_is_running(ctx))
return -EINVAL;
+ if (control->repeat)
+ return 0;
wait_for_completion(&control->completion);
if (control->canceled)
return -ECANCELED;
@@ -2389,6 +2393,7 @@ static void kdamond_usleep(unsigned long usecs)
static void kdamond_call(struct damon_ctx *ctx, bool cancel)
{
struct damon_call_control *control;
+ LIST_HEAD(repeat_controls);
int ret = 0;
while (true) {
@@ -2407,8 +2412,18 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel)
mutex_lock(&ctx->call_controls_lock);
list_del(&control->list);
mutex_unlock(&ctx->call_controls_lock);
- complete(&control->completion);
+ if (!control->repeat)
+ complete(&control->completion);
+ else
+ list_add(&control->list, &repeat_controls);
}
+ control = list_first_entry_or_null(&repeat_controls,
+ struct damon_call_control, list);
+ if (!control || cancel)
+ return;
+ mutex_lock(&ctx->call_controls_lock);
+ list_add_tail(&control->list, &ctx->call_controls);
+ mutex_unlock(&ctx->call_controls_lock);
}
/* Returns negative error code if it's not activated but should return */
--
2.39.5
Powered by blists - more mailing lists