linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mm/damon/core: support multiple damon_call_control requests
@ 2025-12-02  2:14 Enze Li
  2025-12-02  2:31 ` Enze Li
  2025-12-02  5:29 ` SeongJae Park
  0 siblings, 2 replies; 4+ messages in thread
From: Enze Li @ 2025-12-02  2:14 UTC (permalink / raw)
  To: sj, akpm; +Cc: damon, linux-mm, enze.li, Enze Li

The current implementation only supports repeated calls to a single
damon_call_control request per context.  This limitation introduces
inefficiencies for scenarios that require registering multiple deferred
operations.

This patch modifies the implementation of kdamond_call() to support
repeated calls to multiple damon_call_control requests.  To demonstrate
the effect of this change, I made minor modifications to
samples/damon/prcl.c by adding a new request alongside the original
damon_call_control request and performed comparative tests.

Before applying the patch, I observed,

[  381.661821] damon_sample_prcl: start
[  381.668199] damon_sample_prcl: repeat_call_v2
[  381.668208] damon_sample_prcl: repeat_call
[  381.668211] damon_sample_prcl: wss: 0
[  381.675194] damon_sample_prcl: repeat_call
[  381.675202] damon_sample_prcl: wss: 0

after applying the patch, I saw,

[   61.750723] damon_sample_prcl: start
[   61.757104] damon_sample_prcl: repeat_call_v2
[   61.757106] damon_sample_prcl: repeat_call
[   61.757107] damon_sample_prcl: wss: 0
[   61.763067] damon_sample_prcl: repeat_call_v2
[   61.763069] damon_sample_prcl: repeat_call
[   61.763070] damon_sample_prcl: wss: 0

Signed-off-by: Enze Li <lienze@kylinos.cn>
---
 mm/damon/core.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index 109b050c795a..66b5bae44f22 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2526,13 +2526,19 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel)
 			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);
+	while (true) {
+		control = list_first_entry_or_null(&repeat_controls,
+				struct damon_call_control, list);
+		if (!control)
+			break;
+		/* Unlink from the repeate_controls list. */
+		list_del(&control->list);
+		if (cancel)
+			continue;
+		mutex_lock(&ctx->call_controls_lock);
+		list_add(&control->list, &ctx->call_controls);
+		mutex_unlock(&ctx->call_controls_lock);
+	}
 }
 
 /* Returns negative error code if it's not activated but should return */

base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
-- 
2.52.0



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

* Re: [PATCH] mm/damon/core: support multiple damon_call_control requests
  2025-12-02  2:14 [PATCH] mm/damon/core: support multiple damon_call_control requests Enze Li
@ 2025-12-02  2:31 ` Enze Li
  2025-12-02  5:29 ` SeongJae Park
  1 sibling, 0 replies; 4+ messages in thread
From: Enze Li @ 2025-12-02  2:31 UTC (permalink / raw)
  To: sj; +Cc: akpm, damon, linux-mm, enze.li, lienze


FTR, this is my testing patch for samples/damon/prcl.c based on tag v6.18.

8<------------------------------------------------------
diff --git a/samples/damon/prcl.c b/samples/damon/prcl.c
index b7c50f2656ce..94fd6184fb14 100644
--- a/samples/damon/prcl.c
+++ b/samples/damon/prcl.c
@@ -39,6 +39,7 @@ static int damon_sample_prcl_repeat_call_fn(void *data)
        struct damon_ctx *c = data;
        struct damon_target *t;
 
+       pr_info("repeat_call\n");
        damon_for_each_target(t, c) {
                struct damon_region *r;
                unsigned long wss = 0;
@@ -52,11 +53,22 @@ static int damon_sample_prcl_repeat_call_fn(void *data)
        return 0;
 }
 
+static int damon_sample_prcl_repeat_call_v2_fn(void *data)
+{
+       pr_info("repeat_call_v2\n");
+       return 0;
+}
+
 static struct damon_call_control repeat_call_control = {
        .fn = damon_sample_prcl_repeat_call_fn,
        .repeat = true,
 };
 
+static struct damon_call_control repeat_call_control_v2 = {
+       .fn = damon_sample_prcl_repeat_call_v2_fn,
+       .repeat = true,
+};
+
 static int damon_sample_prcl_start(void)
 {
        struct damon_target *target;
@@ -109,6 +121,9 @@ static int damon_sample_prcl_start(void)
        if (err)
                return err;
 
+       repeat_call_control_v2.data = ctx;
+       damon_call(ctx, &repeat_call_control_v2);
+
        repeat_call_control.data = ctx;
        return damon_call(ctx, &repeat_call_control);
 }
>8------------------------------------------------------

Thanks,
Enze

On Tue, Dec 02 2025 at 10:14:07 AM +0800, Enze Li wrote:

> The current implementation only supports repeated calls to a single
> damon_call_control request per context.  This limitation introduces
> inefficiencies for scenarios that require registering multiple deferred
> operations.
>
> This patch modifies the implementation of kdamond_call() to support
> repeated calls to multiple damon_call_control requests.  To demonstrate
> the effect of this change, I made minor modifications to
> samples/damon/prcl.c by adding a new request alongside the original
> damon_call_control request and performed comparative tests.
>
> Before applying the patch, I observed,
>
> [  381.661821] damon_sample_prcl: start
> [  381.668199] damon_sample_prcl: repeat_call_v2
> [  381.668208] damon_sample_prcl: repeat_call
> [  381.668211] damon_sample_prcl: wss: 0
> [  381.675194] damon_sample_prcl: repeat_call
> [  381.675202] damon_sample_prcl: wss: 0
>
> after applying the patch, I saw,
>
> [   61.750723] damon_sample_prcl: start
> [   61.757104] damon_sample_prcl: repeat_call_v2
> [   61.757106] damon_sample_prcl: repeat_call
> [   61.757107] damon_sample_prcl: wss: 0
> [   61.763067] damon_sample_prcl: repeat_call_v2
> [   61.763069] damon_sample_prcl: repeat_call
> [   61.763070] damon_sample_prcl: wss: 0
>
> Signed-off-by: Enze Li <lienze@kylinos.cn>
> ---
>  mm/damon/core.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 109b050c795a..66b5bae44f22 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2526,13 +2526,19 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel)
>  			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);
> +	while (true) {
> +		control = list_first_entry_or_null(&repeat_controls,
> +				struct damon_call_control, list);
> +		if (!control)
> +			break;
> +		/* Unlink from the repeate_controls list. */
> +		list_del(&control->list);
> +		if (cancel)
> +			continue;
> +		mutex_lock(&ctx->call_controls_lock);
> +		list_add(&control->list, &ctx->call_controls);
> +		mutex_unlock(&ctx->call_controls_lock);
> +	}
>  }
>  
>  /* Returns negative error code if it's not activated but should return */
>
> base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449


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

* Re: [PATCH] mm/damon/core: support multiple damon_call_control requests
  2025-12-02  2:14 [PATCH] mm/damon/core: support multiple damon_call_control requests Enze Li
  2025-12-02  2:31 ` Enze Li
@ 2025-12-02  5:29 ` SeongJae Park
  2025-12-02  7:55   ` Enze Li
  1 sibling, 1 reply; 4+ messages in thread
From: SeongJae Park @ 2025-12-02  5:29 UTC (permalink / raw)
  To: Enze Li; +Cc: SeongJae Park, akpm, damon, linux-mm, enze.li, stable

Hello Enze,


First of all, thank you for sharing this patch!

On Tue,  2 Dec 2025 10:14:07 +0800 Enze Li <lienze@kylinos.cn> wrote:

> The current implementation only supports repeated calls to a single
> damon_call_control request per context.

I understand "repeated calls to a single damon_call_control" means "single
damon_call_control object having ->repeat set as true".  Let me call it "repeat
mode damon_call_control object".

This is not an intentionally designed limitation but a bug.  damon_call()
allows callers adding multiple repeat mode damon_call_control objects per
context.  Technically, it adds any requested damon_call_control object to the
per-context linked list, regardless of the number of repeat mode objects on the
list.  But, the consumer of the damon_call_control objects list,
kdamond_call(), moves the repeat mode objects from the per-context list to a
temporal list (repeat_controls), and then move only the first repeat mode entry
from the temporal list to the per-context list.

If there were multiple repeat mode objects in the per-context list, what
happens to the remaining repeat mode damon_call_control objects on the temporal
list?  Nothing.  As a result, the memory for the objects are leaked.
Definitely this is a bug.

Luckily there is no such multiple repeat mode damon_call() requests, so no
upstream kernel user is exposed to the memory leak bug in real.  But the bug is
a bug.  We should fix this.

> This limitation introduces
> inefficiencies for scenarios that require registering multiple deferred
> operations.

I'm not very convinced with the above reasoning because 1. it is not a matter
of inefficiency but a clear memory leak bug.  2. there is no damon_call()
callers that want to have multiple deferred operations with high efficiency, at
the moment.  In my opinion, the above sentence is better to be just dropped.

> 
> This patch modifies the implementation of kdamond_call() to support
> repeated calls to multiple damon_call_control requests.

This change is rquired for fixing the bug, though.

> To demonstrate
> the effect of this change, I made minor modifications to
> samples/damon/prcl.c by adding a new request alongside the original
> damon_call_control request and performed comparative tests.
> 
> Before applying the patch, I observed,
> 
> [  381.661821] damon_sample_prcl: start
> [  381.668199] damon_sample_prcl: repeat_call_v2
> [  381.668208] damon_sample_prcl: repeat_call
> [  381.668211] damon_sample_prcl: wss: 0
> [  381.675194] damon_sample_prcl: repeat_call
> [  381.675202] damon_sample_prcl: wss: 0
> 
> after applying the patch, I saw,
> 
> [   61.750723] damon_sample_prcl: start
> [   61.757104] damon_sample_prcl: repeat_call_v2
> [   61.757106] damon_sample_prcl: repeat_call
> [   61.757107] damon_sample_prcl: wss: 0
> [   61.763067] damon_sample_prcl: repeat_call_v2
> [   61.763069] damon_sample_prcl: repeat_call
> [   61.763070] damon_sample_prcl: wss: 0
> 
> Signed-off-by: Enze Li <lienze@kylinos.cn>

Assuming we agree on the fact this is a fix of the bug, I think we should add
below tags.

Fixes: 43df7676e550 ("mm/damon/core: introduce repeat mode damon_call()")
Cc: <stable@vger.kernel.org> # 6.17.x

> ---
>  mm/damon/core.c | 20 +++++++++++++-------
>  1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 109b050c795a..66b5bae44f22 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2526,13 +2526,19 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel)
>  			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);
> +	while (true) {
> +		control = list_first_entry_or_null(&repeat_controls,
> +				struct damon_call_control, list);
> +		if (!control)
> +			break;
> +		/* Unlink from the repeate_controls list. */
> +		list_del(&control->list);
> +		if (cancel)
> +			continue;
> +		mutex_lock(&ctx->call_controls_lock);
> +		list_add(&control->list, &ctx->call_controls);
> +		mutex_unlock(&ctx->call_controls_lock);
> +	}

This looks good enough to fix the bug.

Could you please resend this patch after rewording the commit message as
appripriate for the bug fix, adding points I listed above?

Again, thank you for letting us find this bug.


Thanks,
SJ

[...]


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

* Re: [PATCH] mm/damon/core: support multiple damon_call_control requests
  2025-12-02  5:29 ` SeongJae Park
@ 2025-12-02  7:55   ` Enze Li
  0 siblings, 0 replies; 4+ messages in thread
From: Enze Li @ 2025-12-02  7:55 UTC (permalink / raw)
  To: SeongJae Park; +Cc: akpm, damon, linux-mm, enze.li, stable, lienze

Hi SJ,

Thanks for your review and quick reply!

On Mon, Dec 01 2025 at 09:29:55 PM -0800, SeongJae Park wrote:

<...>

> On Tue,  2 Dec 2025 10:14:07 +0800 Enze Li <lienze@kylinos.cn> wrote:
>
>> The current implementation only supports repeated calls to a single
>> damon_call_control request per context.
>
> I understand "repeated calls to a single damon_call_control" means "single
> damon_call_control object having ->repeat set as true".  Let me call it "repeat
> mode damon_call_control object".
>
> This is not an intentionally designed limitation but a bug.  damon_call()
> allows callers adding multiple repeat mode damon_call_control objects per
> context.  Technically, it adds any requested damon_call_control object to the
> per-context linked list, regardless of the number of repeat mode objects on the
> list.  But, the consumer of the damon_call_control objects list,
> kdamond_call(), moves the repeat mode objects from the per-context list to a
> temporal list (repeat_controls), and then move only the first repeat mode entry
> from the temporal list to the per-context list.
>
> If there were multiple repeat mode objects in the per-context list, what
> happens to the remaining repeat mode damon_call_control objects on the temporal
> list?  Nothing.  As a result, the memory for the objects are leaked.
> Definitely this is a bug.

Thank you for the detailed explanation -- it really clarified the design
for me.

>
> Luckily there is no such multiple repeat mode damon_call() requests, so no
> upstream kernel user is exposed to the memory leak bug in real.  But the bug is
> a bug.  We should fix this.
>
>> This limitation introduces
>> inefficiencies for scenarios that require registering multiple deferred
>> operations.
>
> I'm not very convinced with the above reasoning because 1. it is not a matter
> of inefficiency but a clear memory leak bug.  2. there is no damon_call()
> callers that want to have multiple deferred operations with high efficiency, at
> the moment.  In my opinion, the above sentence is better to be just dropped.
>

Agreed.  I will rework the patch description for the next revision.

>> 
>> This patch modifies the implementation of kdamond_call() to support
>> repeated calls to multiple damon_call_control requests.
>
> This change is rquired for fixing the bug, though.
>

<...>

>
> Assuming we agree on the fact this is a fix of the bug, I think we should add
> below tags.
>
> Fixes: 43df7676e550 ("mm/damon/core: introduce repeat mode damon_call()")
> Cc: <stable@vger.kernel.org> # 6.17.x
>
>> ---
>>  mm/damon/core.c | 20 +++++++++++++-------
>>  1 file changed, 13 insertions(+), 7 deletions(-)
>> 
>> diff --git a/mm/damon/core.c b/mm/damon/core.c
>> index 109b050c795a..66b5bae44f22 100644
>> --- a/mm/damon/core.c
>> +++ b/mm/damon/core.c
>> @@ -2526,13 +2526,19 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel)
>>  			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);
>> +	while (true) {
>> +		control = list_first_entry_or_null(&repeat_controls,
>> +				struct damon_call_control, list);
>> +		if (!control)
>> +			break;
>> +		/* Unlink from the repeate_controls list. */
>> +		list_del(&control->list);
>> +		if (cancel)
>> +			continue;
>> +		mutex_lock(&ctx->call_controls_lock);
>> +		list_add(&control->list, &ctx->call_controls);
>> +		mutex_unlock(&ctx->call_controls_lock);
>> +	}
>
> This looks good enough to fix the bug.
>
> Could you please resend this patch after rewording the commit message as
> appripriate for the bug fix, adding points I listed above?

Okay, I'll resend this patch shortly.

Best Regards,
Enze

<...>


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

end of thread, other threads:[~2025-12-02  7:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-02  2:14 [PATCH] mm/damon/core: support multiple damon_call_control requests Enze Li
2025-12-02  2:31 ` Enze Li
2025-12-02  5:29 ` SeongJae Park
2025-12-02  7:55   ` Enze Li

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