@@ -59,17 +59,22 @@ struct damon_task {
/*
* For each 'sample_interval', DAMON checks whether each region is accessed or
* not. It aggregates and keeps the access information (number of accesses to
- * each region) for each 'aggr_interval' time.
+ * each region) for each 'aggr_interval' time. And for each
+ * 'regions_update_interval', damon checks whether the memory mapping of the
+ * target tasks has changed (e.g., by mmap() calls from the applications) and
+ * applies the changes.
*
* All time intervals are in micro-seconds.
*/
struct damon_ctx {
unsigned long sample_interval;
unsigned long aggr_interval;
+ unsigned long regions_update_interval;
unsigned long min_nr_regions;
unsigned long max_nr_regions;
struct timespec64 last_aggregation;
+ struct timespec64 last_regions_update;
struct task_struct *kdamond;
bool kdamond_stop;
@@ -671,6 +676,87 @@ static void kdamond_split_regions(struct damon_ctx *ctx)
damon_split_regions_of(ctx, t);
}
+/*
+ * Check whether it is time to check and apply the dynamic mmap changes
+ *
+ * Returns true if it is.
+ */
+static bool kdamond_need_update_regions(struct damon_ctx *ctx)
+{
+ return damon_check_reset_time_interval(&ctx->last_regions_update,
+ ctx->regions_update_interval);
+}
+
+static bool damon_intersect(struct damon_region *r, struct region *re)
+{
+ return !(r->vm_end <= re->start || re->end <= r->vm_start);
+}
+
+/*
+ * Update damon regions for the three big regions of the given task
+ *
+ * t the given task
+ * bregions the three big regions of the task
+ */
+static void damon_apply_three_regions(struct damon_ctx *ctx,
+ struct damon_task *t, struct region bregions[3])
+{
+ struct damon_region *r, *next;
+ unsigned int i = 0;
+
+ /* Remove regions which isn't in the three big regions now */
+ damon_for_each_region_safe(r, next, t) {
+ for (i = 0; i < 3; i++) {
+ if (damon_intersect(r, &bregions[i]))
+ break;
+ }
+ if (i == 3)
+ damon_destroy_region(r);
+ }
+
+ /* Adjust intersecting regions to fit with the threee big regions */
+ for (i = 0; i < 3; i++) {
+ struct damon_region *first = NULL, *last;
+ struct damon_region *newr;
+ struct region *br;
+
+ br = &bregions[i];
+ /* Get the first and last regions which intersects with br */
+ damon_for_each_region(r, t) {
+ if (damon_intersect(r, br)) {
+ if (!first)
+ first = r;
+ last = r;
+ }
+ if (r->vm_start >= br->end)
+ break;
+ }
+ if (!first) {
+ /* no damon_region intersects with this big region */
+ newr = damon_new_region(ctx, br->start, br->end);
+ damon_add_region(newr, damon_prev_region(r), r);
+ } else {
+ first->vm_start = br->start;
+ last->vm_end = br->end;
+ }
+ }
+}
+
+/*
+ * Update regions for current memory mappings
+ */
+static void kdamond_update_regions(struct damon_ctx *ctx)
+{
+ struct region three_regions[3];
+ struct damon_task *t;
+
+ damon_for_each_task(ctx, t) {
+ if (damon_three_regions_of(t, three_regions))
+ continue;
+ damon_apply_three_regions(ctx, t, three_regions);
+ }
+}
+
/*
* Check whether current monitoring should be stopped
*
@@ -735,6 +821,9 @@ static int kdamond_fn(void *data)
kdamond_split_regions(ctx);
}
+ if (kdamond_need_update_regions(ctx))
+ kdamond_update_regions(ctx);
+
usleep_range(ctx->sample_interval, ctx->sample_interval + 1);
}
damon_for_each_task(ctx, t) {
@@ -820,6 +909,7 @@ static int damon_set_pids(struct damon_ctx *ctx,
*
* sample_int time interval between samplings
* aggr_int time interval between aggregations
+ * regions_update_int time interval between vma update checks
* min_nr_reg minimal number of regions
* max_nr_reg maximum number of regions
*
@@ -828,9 +918,9 @@ static int damon_set_pids(struct damon_ctx *ctx,
*
* Returns 0 on success, negative error code otherwise.
*/
-static int damon_set_attrs(struct damon_ctx *ctx,
- unsigned long sample_int, unsigned long aggr_int,
- unsigned long min_nr_reg, unsigned long max_nr_reg)
+static int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int,
+ unsigned long aggr_int, unsigned long regions_update_int,
+ unsigned long min_nr_reg, unsigned long max_nr_reg)
{
if (min_nr_reg < 3) {
pr_err("min_nr_regions (%lu) should be bigger than 2\n",
@@ -845,6 +935,7 @@ static int damon_set_attrs(struct damon_ctx *ctx,
ctx->sample_interval = sample_int;
ctx->aggr_interval = aggr_int;
+ ctx->regions_update_interval = regions_update_int;
ctx->min_nr_regions = min_nr_reg;
ctx->max_nr_regions = max_nr_reg;
return 0;