Commit e6a0deb6 authored by SeongJae Park's avatar SeongJae Park Committed by Andrew Morton
Browse files

mm/damon/core: introduce damon_call_control->dealloc_on_cancel

Patch series "mm/damon/sysfs: fix refresh_ms control overwriting on
multi-kdamonds usages".

Automatic esssential DAMON/DAMOS status update feature of DAMON sysfs
interface (refresh_ms) is broken [1] for multiple DAMON contexts
(kdamonds) use case, since it uses a global single damon_call_control
object for all created DAMON contexts.  The fields of the object,
particularly the list field is over-written for the contexts and it makes
unexpected results including user-space hangup and kernel crashes [2]. 
Fix it by extending damon_call_control for the use case and updating the
usage on DAMON sysfs interface to use per-context dynamically allocated
damon_call_control object.


This patch (of 2):

When damon_call_control->repeat is set, damon_call() is executed
asynchronously, and is eventually canceled when kdamond finishes.  If the
damon_call_control object is dynamically allocated, finding the place to
deallocate the object is difficult.  Introduce a new damon_call_control
field, namely dealloc_on_cancel, to ask the kdamond deallocates those
dynamically allocated objects when those are canceled.

Link: https://lkml.kernel.org/r/20250908201513.60802-3-sj@kernel.org
Link: https://lkml.kernel.org/r/20250908201513.60802-2-sj@kernel.org


Fixes: d809a7c6 ("mm/damon/sysfs: implement refresh_ms file internal work")
Signed-off-by: default avatarSeongJae Park <sj@kernel.org>
Cc: Yunjeong Mun <yunjeong.mun@sk.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 2da6de30
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -636,6 +636,7 @@ struct damon_operations {
 * @data:		Data that will be passed to @fn.
 * @repeat:		Repeat invocations.
 * @return_code:	Return code from @fn invocation.
 * @dealloc_on_cancel:	De-allocate when canceled.
 *
 * Control damon_call(), which requests specific kdamond to invoke a given
 * function.  Refer to damon_call() for more details.
@@ -645,6 +646,7 @@ struct damon_call_control {
	void *data;
	bool repeat;
	int return_code;
	bool dealloc_on_cancel;
/* private: internal use only */
	/* informs if the kdamond finished handling of the request */
	struct completion completion;
+6 −2
Original line number Diff line number Diff line
@@ -2479,11 +2479,15 @@ 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);
		if (!control->repeat)
		if (!control->repeat) {
			complete(&control->completion);
		else
		} else if (control->canceled && control->dealloc_on_cancel) {
			kfree(control);
			continue;
		} else {
			list_add(&control->list, &repeat_controls);
		}
	}
	control = list_first_entry_or_null(&repeat_controls,
			struct damon_call_control, list);
	if (!control || cancel)