diff --git a/mm/damon.c b/mm/damon.c
index 124f12d4be40..e7f07c9e3333 100644
--- a/mm/damon.c
+++ b/mm/damon.c
@@ -63,14 +63,18 @@ static LIST_HEAD(damon_tasks_list);
  * 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 'aggr_interval' and then flushes it to the result buffer if
- * an 'aggr_interval' surpassed.
+ * an 'aggr_interval' surpassed.  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.
  */
 static unsigned long sample_interval = 5 * 1000;
 static unsigned long aggr_interval = 100 * 1000;
+static unsigned long regions_update_interval = 1000 * 1000;
 
 static struct timespec64 last_aggregate_time;
+static struct timespec64 last_regions_update_time;
 
 static unsigned long min_nr_regions = 10;
 static unsigned long max_nr_regions = 1000;
@@ -740,6 +744,87 @@ static void kdamond_split_regions(void)
 		damon_split_regions_of(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(void)
+{
+	return damon_check_reset_time_interval(&last_regions_update_time,
+			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_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(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(void)
+{
+	struct region three_regions[3];
+	struct damon_task *t;
+
+	damon_for_each_task(t) {
+		if (damon_three_regions_of(t, three_regions))
+			continue;
+		damon_apply_three_regions(t, three_regions);
+	}
+}
+
 /*
  * Check whether current monitoring should be stopped
  *
@@ -803,6 +888,9 @@ static int kdamond_fn(void *data)
 			kdamond_split_regions();
 		}
 
+		if (kdamond_need_update_regions())
+			kdamond_update_regions();
+
 		usleep_range(sample_interval, sample_interval + 1);
 	}
 	damon_flush_rbuffer();
@@ -909,6 +997,7 @@ static long damon_set_pids(unsigned long *pids, ssize_t nr_pids)
  *
  * 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
  * path_to_rfile	path to the monitor result files
@@ -919,7 +1008,7 @@ static long damon_set_pids(unsigned long *pids, ssize_t nr_pids)
  * Returns 0 on success, negative error code otherwise.
  */
 static long damon_set_attrs(unsigned long sample_int,
-		unsigned long aggr_int,
+		unsigned long aggr_int, unsigned long regions_update_int,
 		unsigned long min_nr_reg, unsigned long max_nr_reg,
 		char *path_to_rfile)
 {
@@ -941,6 +1030,7 @@ static long damon_set_attrs(unsigned long sample_int,
 
 	sample_interval = sample_int;
 	aggr_interval = aggr_int;
+	regions_update_interval = regions_update_int;
 	min_nr_regions = min_nr_reg;
 	max_nr_regions = max_nr_reg;
 	strncpy(rfile_path, path_to_rfile, LEN_RES_FILE_PATH);
@@ -953,6 +1043,7 @@ static int __init damon_init(void)
 
 	prandom_seed_state(&rndseed, 42);
 	ktime_get_coarse_ts64(&last_aggregate_time);
+	last_regions_update_time = last_aggregate_time;
 	return 0;
 }
 
