@@ -170,6 +170,7 @@ struct damos {
* @check_accesses: Checks the access of target regions.
* @target_valid: Determine if the target is valid.
* @cleanup: Cleans up the context.
+ * @apply_scheme: Apply a DAMON-based operation scheme.
* @sample_cb: Called for each sampling interval.
* @aggregate_cb: Called for each aggregation interval.
*
@@ -193,6 +194,9 @@ struct damos {
* monitoring.
* @cleanup is called from @kdamond just before its termination. After this
* call, only @kdamond_lock and @kdamond will be touched.
+ * @apply_scheme is called from @kdamond when a region for user provided
+ * DAMON-based operation scheme is found. It should apply the scheme's action
+ * to the region.
*
* @sample_cb and @aggregate_cb are called from @kdamond for each of the
* sampling intervals and aggregation intervals, respectively. Therefore,
@@ -229,6 +233,8 @@ struct damon_ctx {
unsigned int (*check_accesses)(struct damon_ctx *context);
bool (*target_valid)(struct damon_target *target);
void (*cleanup)(struct damon_ctx *context);
+ int (*apply_scheme)(struct damon_ctx *context, struct damon_target *t,
+ struct damon_region *r, struct damos *scheme);
void (*sample_cb)(struct damon_ctx *context);
void (*aggregate_cb)(struct damon_ctx *context);
};
@@ -312,6 +318,8 @@ void kdamond_prepare_vm_access_checks(struct damon_ctx *ctx);
unsigned int kdamond_check_vm_accesses(struct damon_ctx *ctx);
bool kdamond_vm_target_valid(struct damon_target *t);
void kdamond_vm_cleanup(struct damon_ctx *ctx);
+int kdamond_vm_apply_scheme(struct damon_ctx *context, struct damon_target *t,
+ struct damon_region *r, struct damos *scheme);
void damon_set_vaddr_primitives(struct damon_ctx *ctx);
/* Reference callback implementations for physical memory */
@@ -701,68 +701,6 @@ static void kdamond_reset_aggregated(struct damon_ctx *c)
}
}
-#ifndef CONFIG_ADVISE_SYSCALLS
-static int damos_madvise(struct damon_target *target, struct damon_region *r,
- int behavior)
-{
- return -EINVAL;
-}
-#else
-static int damos_madvise(struct damon_target *target, struct damon_region *r,
- int behavior)
-{
- struct task_struct *t;
- struct mm_struct *mm;
- int ret = -ENOMEM;
-
- t = damon_get_task_struct(target);
- if (!t)
- goto out;
- mm = damon_get_mm(target);
- if (!mm)
- goto put_task_out;
-
- ret = do_madvise(t, mm, PAGE_ALIGN(r->ar.start),
- PAGE_ALIGN(r->ar.end - r->ar.start), behavior);
- mmput(mm);
-put_task_out:
- put_task_struct(t);
-out:
- return ret;
-}
-#endif /* CONFIG_ADVISE_SYSCALLS */
-
-static int damos_do_action(struct damon_target *target, struct damon_region *r,
- enum damos_action action)
-{
- int madv_action;
-
- switch (action) {
- case DAMOS_WILLNEED:
- madv_action = MADV_WILLNEED;
- break;
- case DAMOS_COLD:
- madv_action = MADV_COLD;
- break;
- case DAMOS_PAGEOUT:
- madv_action = MADV_PAGEOUT;
- break;
- case DAMOS_HUGEPAGE:
- madv_action = MADV_HUGEPAGE;
- break;
- case DAMOS_NOHUGEPAGE:
- madv_action = MADV_NOHUGEPAGE;
- break;
- case DAMOS_STAT:
- return 0;
- default:
- pr_warn("Wrong action %d\n", action);
- return -EINVAL;
- }
-
- return damos_madvise(target, r, madv_action);
-}
-
static void damon_do_apply_schemes(struct damon_ctx *c,
struct damon_target *t,
struct damon_region *r)
@@ -781,7 +719,8 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
continue;
s->stat_count++;
s->stat_sz += sz;
- damos_do_action(t, r, s->action);
+ if (c->apply_scheme)
+ c->apply_scheme(c, t, r, s);
if (s->action != DAMOS_STAT)
r->age = 0;
}
@@ -5,31 +5,3 @@
/* Get a random number in [l, r) */
#define damon_rand(l, r) (l + prandom_u32() % (r - l))
-
-/*
- * 't->id' should be the pointer to the relevant 'struct pid' having reference
- * count. Caller must put the returned task, unless it is NULL.
- */
-#define damon_get_task_struct(t) \
- (get_pid_task((struct pid *)t->id, PIDTYPE_PID))
-
-/*
- * Get the mm_struct of the given target
- *
- * Caller _must_ put the mm_struct after use, unless it is NULL.
- *
- * Returns the mm_struct of the target on success, NULL on failure
- */
-static inline struct mm_struct *damon_get_mm(struct damon_target *t)
-{
- struct task_struct *task;
- struct mm_struct *mm;
-
- task = damon_get_task_struct(t);
- if (!task)
- return NULL;
-
- mm = get_task_mm(task);
- put_task_struct(task);
- return mm;
-}
@@ -38,8 +38,11 @@
#endif
/*
- * Functions for the initial monitoring target regions construction
+ * 't->id' should be the pointer to the relevant 'struct pid' having reference
+ * count. Caller must put the returned task, unless it is NULL.
*/
+#define damon_get_task_struct(t) \
+ (get_pid_task((struct pid *)t->id, PIDTYPE_PID))
/*
* Get the mm_struct of the given target
@@ -62,6 +65,10 @@ struct mm_struct *damon_get_mm(struct damon_target *t)
return mm;
}
+/*
+ * Functions for the initial monitoring target regions construction
+ */
+
/*
* Size-evenly split a region into 'nr_pieces' small regions
*
@@ -788,6 +795,68 @@ void kdamond_vm_cleanup(struct damon_ctx *ctx)
}
}
+#ifndef CONFIG_ADVISE_SYSCALLS
+static int damos_madvise(struct damon_target *target, struct damon_region *r,
+ int behavior)
+{
+ return -EINVAL;
+}
+#else
+static int damos_madvise(struct damon_target *target, struct damon_region *r,
+ int behavior)
+{
+ struct task_struct *t;
+ struct mm_struct *mm;
+ int ret = -ENOMEM;
+
+ t = damon_get_task_struct(target);
+ if (!t)
+ goto out;
+ mm = damon_get_mm(target);
+ if (!mm)
+ goto put_task_out;
+
+ ret = do_madvise(t, mm, PAGE_ALIGN(r->ar.start),
+ PAGE_ALIGN(r->ar.end - r->ar.start), behavior);
+ mmput(mm);
+put_task_out:
+ put_task_struct(t);
+out:
+ return ret;
+}
+#endif /* CONFIG_ADVISE_SYSCALLS */
+
+int kdamond_vm_apply_scheme(struct damon_ctx *ctx, struct damon_target *t,
+ struct damon_region *r, struct damos *scheme)
+{
+ int madv_action;
+
+ switch (scheme->action) {
+ case DAMOS_WILLNEED:
+ madv_action = MADV_WILLNEED;
+ break;
+ case DAMOS_COLD:
+ madv_action = MADV_COLD;
+ break;
+ case DAMOS_PAGEOUT:
+ madv_action = MADV_PAGEOUT;
+ break;
+ case DAMOS_HUGEPAGE:
+ madv_action = MADV_HUGEPAGE;
+ break;
+ case DAMOS_NOHUGEPAGE:
+ madv_action = MADV_NOHUGEPAGE;
+ break;
+ case DAMOS_STAT:
+ return 0;
+ default:
+ pr_warn("Wrong action %d\n", scheme->action);
+ return -EINVAL;
+ }
+
+ return damos_madvise(t, r, madv_action);
+}
+
void damon_set_vaddr_primitives(struct damon_ctx *ctx)
{
ctx->init_target_regions = kdamond_init_vm_regions;
@@ -796,6 +865,7 @@ void damon_set_vaddr_primitives(struct damon_ctx *ctx)
ctx->check_accesses = kdamond_check_vm_accesses;
ctx->target_valid = kdamond_vm_target_valid;
ctx->cleanup = kdamond_vm_cleanup;
+ ctx->apply_scheme = kdamond_vm_apply_scheme;
}
void damon_set_paddr_primitives(struct damon_ctx *ctx)
@@ -806,6 +876,7 @@ void damon_set_paddr_primitives(struct damon_ctx *ctx)
ctx->check_accesses = kdamond_check_phys_accesses;
ctx->target_valid = NULL;
ctx->cleanup = NULL;
+ ctx->apply_scheme = NULL;
}
#include "primitives-test.h"