diff --git a/include/linux/damon.h b/include/linux/damon.h index 6a29dc2ac8db..42234839ce29 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -169,6 +169,7 @@ enum damos_quota_goal_metric { /** * struct damos_quota_goal - DAMOS scheme quota auto-tuning goal. * @metric: Metric to be used for representing the goal. + * @complement: Use the complement of the metric. * @target_value: Target value of @metric to achieve with the tuning. * @current_value: Current value of @metric. * @nid: Node id. @@ -191,6 +192,7 @@ enum damos_quota_goal_metric { */ struct damos_quota_goal { enum damos_quota_goal_metric metric; + bool complement; unsigned long target_value; unsigned long current_value; /* metric-dependent fields */ diff --git a/mm/damon/core.c b/mm/damon/core.c index 5ecbea5d71e1..0d27f08b350e 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -1224,6 +1224,7 @@ static int damos_commit_quota_goal( if (!src->target_value) return -EINVAL; dst->metric = src->metric; + dst->complement = src->complement; dst->target_value = src->target_value; if (dst->metric == DAMOS_QUOTA_USER_INPUT) dst->current_value = src->current_value; @@ -2960,10 +2961,18 @@ static void damos_set_psi_current_val(u64 now_psi_total, struct damos_quota_goal *goal, struct damos *s) { u64 last_psi_total = goal->last_psi_total; + unsigned long val; goal->last_psi_total = now_psi_total; if (last_psi_total != U64_MAX) { - goal->current_value = now_psi_total - last_psi_total; + val = now_psi_total - last_psi_total; + if (goal->complement) { + if (val < s->quota.reset_interval * 1000) + val = s->quota.reset_interval * 1000 - val; + else + val = 0; + } + goal->current_value = val; return; } /* uninitialized last_psi_total; make no effect this round */ @@ -3255,6 +3264,21 @@ static void damos_set_quota_goal_current_value(struct damon_ctx *c, default: break; } + if (!goal->complement) + return; + + /* update current_value to complemented value */ + + /* for user_input, users set complemented value on their own */ + if (goal->metric == DAMOS_QUOTA_USER_INPUT) + return; + /* damos_set_psi_current_val() handles complement flag itself */ + if (goal->metric == DAMOS_QUOTA_SOME_MEM_PSI_US) + return; + if (goal->current_value < 10000) + goal->current_value = 10000 - goal->current_value; + else + goal->current_value = 0; } /* Return the highest score since it makes schemes least aggressive */