[PATCH 6.18 277/309] mm/damon/stat: monitor all System RAM resources

Greg Kroah-Hartman
2026-03-31T17:09:59Z

From: SeongJae Park <sj@kernel.org>

commit 84481e705ab07ed46e56587fe846af194acacafe upstream.

DAMON_STAT usage document (Documentation/admin-guide/mm/damon/stat.rst)
says it monitors the system's entire physical memory. But, it is
monitoring only the biggest System RAM resource of the system. When there
are multiple System RAM resources, this results in monitoring only an
unexpectedly small fraction of the physical memory. For example, suppose
the system has a 500 GiB System RAM, 10 MiB non-System RAM, and 500 GiB
System RAM resources in order on the physical address space. DAMON_STAT
will monitor only the first 500 GiB System RAM. This situation is
particularly common on NUMA systems.

Select a physical address range that covers all System RAM areas of the
system, to fix this issue and make it work as documented.

[sj@kernel.org: return error if monitoring target region is invalid]
Link: https://lkml.kernel.org/r/20260317053631.87907-1-sj@kernel.org
Link: https://lkml.kernel.org/r/20260316235118.873-1-sj@kernel.org
Fixes: 369c415e6073 ("mm/damon: introduce DAMON_STAT module")
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: <stable@vger.kernel.org> [6.17+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: SeongJae Park <sj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/damon/stat.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)

--- a/mm/damon/stat.c
+++ b/mm/damon/stat.c
@@ -145,12 +145,44 @@ static int damon_stat_damon_call_fn(void
return 0;
}

+struct damon_stat_system_ram_range_walk_arg {
+ bool walked;
+ struct resource res;
+};
+
+static int damon_stat_system_ram_walk_fn(struct resource *res, void *arg)
+{
+ struct damon_stat_system_ram_range_walk_arg *a = arg;
+
+ if (!a->walked) {
+ a->walked = true;
+ a->res.start = res->start;
+ }
+ a->res.end = res->end;
+ return 0;
+}
+
+static int damon_stat_set_monitoring_region(struct damon_target *t,
+ unsigned long addr_unit)
+{
+ struct damon_addr_range addr_range;
+ struct damon_stat_system_ram_range_walk_arg arg = {};
+
+ walk_system_ram_res(0, ULONG_MAX, &arg, damon_stat_system_ram_walk_fn);
+ if (!arg.walked)
+ return -EINVAL;
+ addr_range.start = arg.res.start;
+ addr_range.end = arg.res.end + 1;
+ if (addr_range.end <= addr_range.start)
+ return -EINVAL;
+ return damon_set_regions(t, &addr_range, 1, DAMON_MIN_REGION);
+}
+
static struct damon_ctx *damon_stat_build_ctx(void)
{
struct damon_ctx *ctx;
struct damon_attrs attrs;
struct damon_target *target;
- unsigned long start = 0, end = 0;

ctx = damon_new_ctx();
if (!ctx)
@@ -188,7 +220,7 @@ static struct damon_ctx *damon_stat_buil
if (!target)
goto free_out;
damon_add_target(ctx, target);
- if (damon_set_region_biggest_system_ram_default(target, &start, &end))
+ if (damon_stat_set_monitoring_region(target, ctx->addr_unit))
goto free_out;
return ctx;