diff --git a/mm/damon/core.c b/mm/damon/core.c index 0bed937b1dce..54a7ea98340a 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2649,48 +2649,31 @@ 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; + struct damon_call_control *control, *next; + LIST_HEAD(controls); + + mutex_lock(&ctx->call_controls_lock); + list_splice_tail_init(&ctx->call_controls, &controls); + mutex_unlock(&ctx->call_controls_lock); + + list_for_each_entry_safe(control, next, &controls, list) { + if (!control->repeat || cancel) + list_del(&control->list); - while (true) { - mutex_lock(&ctx->call_controls_lock); - control = list_first_entry_or_null(&ctx->call_controls, - struct damon_call_control, list); - mutex_unlock(&ctx->call_controls_lock); - if (!control) - break; - if (cancel) { - control->canceled = true; - } else { - ret = control->fn(control->data); - control->return_code = ret; - } - mutex_lock(&ctx->call_controls_lock); - list_del(&control->list); - mutex_unlock(&ctx->call_controls_lock); - if (!control->repeat) { - complete(&control->completion); - } else if (control->canceled && control->dealloc_on_cancel) { - kfree(control); - continue; - } else { - list_add(&control->list, &repeat_controls); - } - } - 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); + control->canceled = true; + else + control->return_code = control->fn(control->data); + + if (!control->repeat) + complete(&control->completion); + else if (control->canceled && control->dealloc_on_cancel) + kfree(control); } + + mutex_lock(&ctx->call_controls_lock); + list_splice_tail(&controls, &ctx->call_controls); + mutex_unlock(&ctx->call_controls_lock); } /* Returns negative error code if it's not activated but should return */