linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: SeongJae Park <sj@kernel.org>
Cc: SeongJae Park <sj@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	damon@lists.linux.dev, kernel-team@meta.com,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: [RFC PATCH 02/14] mm/damon/core: introduce repeat mode damon_call()
Date: Sun,  6 Jul 2025 13:00:06 -0700	[thread overview]
Message-ID: <20250706200018.42704-3-sj@kernel.org> (raw)
In-Reply-To: <20250706200018.42704-1-sj@kernel.org>

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@kernel.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


  parent reply	other threads:[~2025-07-06 20:00 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-06 20:00 [RFC PATCH 00/14] mm/damon: remove damon_callback SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 01/14] mm/damon: accept parallel damon_call() requests SeongJae Park
2025-07-06 20:00 ` SeongJae Park [this message]
2025-07-06 21:45   ` [RFC PATCH 02/14] mm/damon/core: introduce repeat mode damon_call() SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 03/14] mm/damon/stat: use damon_call() repeat mode instead of damon_callback SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 04/14] mm/damon/reclaim: " SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 05/14] mm/damon/lru_sort: " SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 06/14] samples/damon/prcl: " SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 07/14] samples/damon/wsse: " SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 08/14] mm/damon/core: do not call ops.cleanup() when destroying targets SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 09/14] mm/damon/core: add cleanup_target() ops callback SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 10/14] mm/damon/vaddr: put pid in cleanup_target() SeongJae Park
2025-07-06 21:48   ` SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 11/14] mm/damon/sysfs: remove damon_sysfs_destroy_targets() SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 12/14] mm/damon/core: destroy targets when kdamond_fn() finish SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 13/14] mm/damon/sysfs: remove damon_sysfs_before_terminate() SeongJae Park
2025-07-06 20:00 ` [RFC PATCH 14/14] mm/damon/core: remove damon_callback SeongJae Park

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250706200018.42704-3-sj@kernel.org \
    --to=sj@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=damon@lists.linux.dev \
    --cc=kernel-team@meta.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).