diff --git a/include/linux/damon.h b/include/linux/damon.h index d3a231275c23..f2370a3a4a9a 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -801,6 +801,7 @@ struct damon_attrs { * @ops: Set of monitoring operations for given use cases. * @addr_unit: Scale factor for core to ops address conversion. * @min_region_sz: Minimum region size. + * @pause: Pause kdamond main loop. * @adaptive_targets: Head of monitoring targets (&damon_target) list. * @schemes: Head of schemes (&damos) list. */ @@ -854,6 +855,7 @@ struct damon_ctx { struct damon_operations ops; unsigned long addr_unit; unsigned long min_region_sz; + bool pause; struct list_head adaptive_targets; struct list_head schemes; diff --git a/mm/damon/core.c b/mm/damon/core.c index 7aeaf319a18a..05e4bef367db 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -1370,6 +1370,7 @@ int damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src) if (err) return err; } + dst->pause = src->pause; dst->ops = src->ops; dst->addr_unit = src->addr_unit; dst->min_region_sz = src->min_region_sz; @@ -3237,6 +3238,14 @@ static int kdamond_fn(void *data) kdamond_call(ctx, false); if (ctx->maybe_corrupted) break; + while (ctx->pause) { + damos_walk_cancel(ctx); + kdamond_usleep(ctx->attrs.sample_interval); + /* allow caller unset pause via damon_call() */ + kdamond_call(ctx, false); + if (kdamond_need_stop(ctx) || ctx->maybe_corrupted) + goto done; + } if (!list_empty(&ctx->schemes)) kdamond_apply_schemes(ctx); else