[RFC PATCH v1.3 08/11] mm/damon/core: reduce range setup in damon_commit_target_regions()

From: SeongJae Park

Date: Thu Jun 25 2026 - 20:19:05 EST


damon_commit_target_regions() calls damon_set_regions() for updating the
destination target's monitoring target region boundaries. It sets the
boundaries same to source target's monitoring regions, even if they are
adjacent. Meanwhile, damon_set_region() sets the destination target
regions exactly the same to the source, only when the target regions are
empty. When there are existing target regions, only a few regions are
expanded or shrunk to fit on only the boundaries for disjoint regions in
the source. Hence the adjacent source ranges mean nothing in common
cases. When there are many regions, such adjacent range setup is only a
waste of time and space. We recently found [1] it is actually causing
memory overhead. Setup the ranges for only distinct ranges.

[1] https://lore.kernel.org/20260603112306.58490-1-akinobu.mita@xxxxxxxxx

Signed-off-by: SeongJae Park <sj@xxxxxxxxxx>
---
mm/damon/core.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index 7e4b9affc5b06..ce5294cb1b4f3 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1349,21 +1349,33 @@ static struct damon_target *damon_nth_target(int n, struct damon_ctx *ctx)
static int damon_commit_target_regions(struct damon_target *dst,
struct damon_target *src, unsigned long src_min_region_sz)
{
- struct damon_region *src_region;
+ struct damon_region *src_region, *prev = NULL;
struct damon_addr_range *ranges;
int i = 0, err;

- damon_for_each_region(src_region, src)
- i++;
+ damon_for_each_region(src_region, src) {
+ if (!prev || prev->ar.end != src_region->ar.start)
+ i++;
+ prev = src_region;
+ }
if (!i)
return 0;

ranges = kmalloc_objs(*ranges, i, GFP_KERNEL | __GFP_NOWARN);
if (!ranges)
return -ENOMEM;
+ prev = NULL;
i = 0;
- damon_for_each_region(src_region, src)
- ranges[i++] = src_region->ar;
+ damon_for_each_region(src_region, src) {
+ if (!prev) {
+ ranges[i].start = src_region->ar.start;
+ } else if (prev->ar.end != src_region->ar.start) {
+ ranges[i++].end = prev->ar.end;
+ ranges[i].start = src_region->ar.start;
+ }
+ prev = src_region;
+ }
+ ranges[i++].end = damon_last_region(src)->ar.end;
err = damon_set_regions(dst, ranges, i, src_min_region_sz);
kfree(ranges);
return err;
--
2.47.3