mm/damon/core: wait ctx stop in damon_call() before reruning an error

damon_call() failure means the DAMON context started its termination.  The
termination is asynchronously done in kdamond thread.  The caller's error
handling should handle the race, too.  It is complicated and easy to make
mistakes.

Update damon_call() to ensure the context is stopped in the case, by
waiting until the completion is confirmed.

Link: https://lore.kernel.org/20260706140628.87414-10-sj@kernel.org
Signed-off-by: SJ Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
SJ Park 2026-07-06 07:06:24 -07:00 committed by Andrew Morton
parent 3e734a0514
commit d079b6b890

View File

@ -2010,6 +2010,8 @@ int damon_kdamond_pid(struct damon_ctx *ctx)
* @ctx has succeeded. Otherwise, this function could fall into an indefinite
* wait.
*
* When this function is failed, the @ctx is guaranteed to be stopped.
*
* Return: 0 on success, negative error code otherwise.
*/
int damon_call(struct damon_ctx *ctx, struct damon_call_control *control)
@ -2022,7 +2024,7 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control)
mutex_lock(&ctx->call_controls_lock);
if (ctx->call_controls_obsolete) {
mutex_unlock(&ctx->call_controls_lock);
return -ECANCELED;
goto canceled;
}
list_add_tail(&control->list, &ctx->call_controls);
mutex_unlock(&ctx->call_controls_lock);
@ -2030,8 +2032,14 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control)
return 0;
wait_for_completion(&control->completion);
if (control->canceled)
return -ECANCELED;
goto canceled;
return 0;
canceled:
while (damon_is_running(ctx))
schedule_timeout_idle(msecs_to_jiffies(100));
return -ECANCELED;
}
/**