[RFC PATCH 2/5] mm/damon/core: cap effective quota size to total monitored memory
From: Ravi Jonnalagadda
Date: Sat May 16 2026 - 17:05:07 EST
The DAMOS quota goal tuner can compute an effective size (esz) larger
than the total monitored memory because it integrates over cumulative
deltas without bounding by the actual workload size. Once esz exceeds
total monitored memory, the per-tick "remaining quota" arithmetic
stops being meaningful: any scheme can apply to the entire monitored
space and "remaining" stays positive indefinitely.
Cap esz to the total size of all currently monitored regions as a
final bound after all other quota calculations. Add
damon_ctx_total_monitored_sz() helper that sums region sizes across
all targets.
The helper runs only inside damos_set_effective_quota(), which is
called at most once per quota reset_interval (default 1s) per scheme,
not per kdamond tick. Walk cost is O(nr_regions) at that frequency
and is dominated by the enclosing tuner work.
This bound is tuner-shape and goal-metric agnostic: it constrains the
quota controller to physically realisable values regardless of which
tuner or goal metric drives it.
Signed-off-by: Ravi Jonnalagadda <ravis.opensrc@xxxxxxxxx>
---
mm/damon/core.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 9975f3d9ebfe9..fd1db234ca304 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2614,6 +2614,19 @@ static void damos_goal_tune_esz_bp_temporal(struct damon_ctx *c,
quota->esz_bp = ULONG_MAX;
}
+/* Sum of all monitored region sizes across all targets in @ctx. */
+static unsigned long damon_ctx_total_monitored_sz(struct damon_ctx *ctx)
+{
+ struct damon_target *t;
+ struct damon_region *r;
+ unsigned long total = 0;
+
+ damon_for_each_target(t, ctx)
+ damon_for_each_region(r, t)
+ total += damon_sz_region(r);
+ return total;
+}
+
/*
* Called only if quota->ms, or quota->sz are set, or quota->goals is not empty
*/
@@ -2621,6 +2634,7 @@ static void damos_set_effective_quota(struct damon_ctx *ctx, struct damos *s)
{
struct damos_quota *quota = &s->quota;
unsigned long throughput;
+ unsigned long total_sz;
unsigned long esz = ULONG_MAX;
if (!quota->ms && list_empty("a->goals)) {
@@ -2649,6 +2663,11 @@ static void damos_set_effective_quota(struct damon_ctx *ctx, struct damos *s)
if (quota->sz && quota->sz < esz)
esz = quota->sz;
+ /* Safety cap: never migrate more than total monitored memory */
+ total_sz = damon_ctx_total_monitored_sz(ctx);
+ if (total_sz && esz > total_sz)
+ esz = total_sz;
+
quota->esz = esz;
}
--
2.43.0