* [PATCH 2/2] mm/damon/sysfs-schemes: report the number of tried regions
2026-07-27 9:54 [PATCH 1/2] mm/damon/core: cover discrete System RAM areas with per-range regions Jiayuan Chen
@ 2026-07-27 9:54 ` Jiayuan Chen
2026-07-27 14:34 ` SJ Park
2026-07-27 14:26 ` [PATCH 1/2] mm/damon/core: cover discrete System RAM areas with per-range regions SJ Park
1 sibling, 1 reply; 4+ messages in thread
From: Jiayuan Chen @ 2026-07-27 9:54 UTC (permalink / raw)
To: damon
Cc: jiayuan.chen, Jiayuan Chen, SeongJae Park, Andrew Morton,
David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Jonathan Corbet, Shuah Khan, linux-mm, linux-kernel, linux-doc
From: Jiayuan Chen <jiayuan.chen@shopee.com>
The 'tried_regions' directory of each DAMON sysfs scheme exposes the memory
regions that the scheme's action has been tried to be applied to, as
per-region subdirectories. It also has a 'total_bytes' file that reports
the total size of those regions without materializing the per-region
subdirectories, so that users can cheaply retrieve the aggregated result.
The number of the tried regions is another useful aggregated metric. When
the scheme's access pattern is not restrictive, it approximates the number
of the adaptive monitoring regions of the context, which users may want to
watch, e.g., to see how well the monitoring is refined under a given
max_nr_regions, or to feed fleet wide access pattern dashboards.
Retrieving it currently requires materializing all the per-region
subdirectories (via writing 'update_schemes_tried_regions') and counting
them, which is unnecessarily expensive for users that only need the count.
Add a 'nr_regions' file to the 'tried_regions' directory. Like
'total_bytes', it is updated by both 'update_schemes_tried_bytes' and
'update_schemes_tried_regions', so it can be read as a lightweight counter
without materializing the per-region subdirectories.
Suggested-by: SeongJae Park <sj@kernel.org>
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
.../ABI/testing/sysfs-kernel-mm-damon | 10 +++++++
Documentation/admin-guide/mm/damon/usage.rst | 27 ++++++++++---------
mm/damon/sysfs-schemes.c | 23 +++++++++++++---
3 files changed, 45 insertions(+), 15 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index 786be4537da1..a6e8f5036555 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -622,6 +622,16 @@ Description: Writing a number to this file sets the upper limit of
nr_snapshots that deactivates the scheme when the limit is
reached or exceeded.
+What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/nr_regions
+Date: Aug 2026
+Contact: SJ Park <sj@kernel.org>
+Description: Reading this file returns the number of regions that
+ corresponding DAMON-based Operation Scheme's action has tried
+ to be applied. The number is updated together with
+ '.../tried_regions/total_bytes' by writing 'update_schemes_tried_bytes'
+ or 'update_schemes_tried_regions' to the relevant 'state' file, and
+ hence can be read without materializing the per-region directories.
+
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/schemes/<S>/tried_regions/total_bytes
Date: Jul 2023
Contact: SJ Park <sj@kernel.org>
diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index f6048fc04263..9152ce09de9d 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -108,7 +108,7 @@ comma (",").
│ │ │ │ │ │ │ :ref:`dests <damon_sysfs_dests>`/nr_dests
│ │ │ │ │ │ │ │ 0/id,weight
│ │ │ │ │ │ │ :ref:`stats <sysfs_schemes_stats>`/nr_tried,sz_tried,nr_applied,sz_applied,sz_ops_filter_passed,qt_exceeds,nr_snapshots,max_nr_snapshots
- │ │ │ │ │ │ │ :ref:`tried_regions <sysfs_schemes_tried_regions>`/total_bytes
+ │ │ │ │ │ │ │ :ref:`tried_regions <sysfs_schemes_tried_regions>`/nr_regions,total_bytes
│ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age,sz_filter_passed
│ │ │ │ │ │ │ │ │ probes
│ │ │ │ │ │ │ │ │ │ 0/hits
@@ -671,21 +671,24 @@ relevant ``kdamonds/<N>/state`` file. Refer to :ref:`kdamond directory
schemes/<N>/tried_regions/
--------------------------
-This directory initially has one file, ``total_bytes``.
+This directory initially has two files, ``nr_regions`` and ``total_bytes``.
When a special keyword, ``update_schemes_tried_regions``, is written to the
-relevant ``kdamonds/<N>/state`` file, DAMON updates the ``total_bytes`` file so
-that reading it returns the total size of the scheme tried regions, and creates
-directories named integer starting from ``0`` under this directory. Each
-directory contains files exposing detailed information about each of the memory
-region that the corresponding scheme's ``action`` has tried to be applied under
-this directory, during next :ref:`apply interval <damon_design_damos>` of the
-corresponding scheme. The information includes address range, ``nr_accesses``,
-and ``age`` of the region.
+relevant ``kdamonds/<N>/state`` file, DAMON updates the ``nr_regions`` and
+``total_bytes`` files so that reading them returns the number and the total size
+of the scheme tried regions, respectively, and creates directories named
+integer starting from ``0`` under this directory. Each directory contains files
+exposing detailed information about each of the memory region that the
+corresponding scheme's ``action`` has tried to be applied under this directory,
+during next :ref:`apply interval <damon_design_damos>` of the corresponding
+scheme. The information includes address range, ``nr_accesses``, and ``age`` of
+the region.
Writing ``update_schemes_tried_bytes`` to the relevant ``kdamonds/<N>/state``
-file will only update the ``total_bytes`` file, and will not create the
-subdirectories.
+file will only update the ``nr_regions`` and ``total_bytes`` files, and will not
+create the subdirectories. Hence ``nr_regions`` can be used as a lightweight way
+to read the number of the scheme tried regions without materializing the
+per-region subdirectories.
The directories will be removed when another special keyword,
``clear_schemes_tried_regions``, is written to the relevant
diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c
index 54ff196f8e24..b1df9f21c267 100644
--- a/mm/damon/sysfs-schemes.c
+++ b/mm/damon/sysfs-schemes.c
@@ -297,6 +297,7 @@ static const struct kobj_type damon_sysfs_scheme_region_ktype = {
struct damon_sysfs_scheme_regions {
struct kobject kobj;
struct list_head regions_list;
+ int nr_region_dirs;
int nr_regions;
unsigned long total_bytes;
};
@@ -311,11 +312,21 @@ damon_sysfs_scheme_regions_alloc(void)
regions->kobj = (struct kobject){};
INIT_LIST_HEAD(®ions->regions_list);
+ regions->nr_region_dirs = 0;
regions->nr_regions = 0;
regions->total_bytes = 0;
return regions;
}
+static ssize_t nr_regions_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_scheme_regions *regions = container_of(kobj,
+ struct damon_sysfs_scheme_regions, kobj);
+
+ return sysfs_emit(buf, "%d\n", regions->nr_regions);
+}
+
static ssize_t total_bytes_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -335,7 +346,7 @@ static void damon_sysfs_scheme_regions_rm_dirs(
list_del(&r->list);
kobject_del(&r->kobj);
kobject_put(&r->kobj);
- regions->nr_regions--;
+ regions->nr_region_dirs--;
}
}
@@ -344,10 +355,14 @@ static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
}
+static struct kobj_attribute damon_sysfs_scheme_regions_nr_regions_attr =
+ __ATTR_RO_MODE(nr_regions, 0400);
+
static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
__ATTR_RO_MODE(total_bytes, 0400);
static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
+ &damon_sysfs_scheme_regions_nr_regions_attr.attr,
&damon_sysfs_scheme_regions_total_bytes_attr.attr,
NULL,
};
@@ -3133,6 +3148,7 @@ void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes,
return;
sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
+ sysfs_regions->nr_regions++;
sysfs_regions->total_bytes += r->ar.end - r->ar.start;
if (total_bytes_only)
return;
@@ -3144,13 +3160,13 @@ void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes,
if (kobject_init_and_add(®ion->kobj,
&damon_sysfs_scheme_region_ktype,
&sysfs_regions->kobj, "%d",
- sysfs_regions->nr_regions))
+ sysfs_regions->nr_region_dirs))
goto out;
if (damos_sysfs_region_add_dirs(region, ctx, r))
goto del_out;
list_add_tail(®ion->list, &sysfs_regions->regions_list);
- sysfs_regions->nr_regions++;
+ sysfs_regions->nr_region_dirs++;
return;
del_out:
@@ -3170,6 +3186,7 @@ int damon_sysfs_schemes_clear_regions(
sysfs_scheme = sysfs_schemes->schemes_arr[i];
damon_sysfs_scheme_regions_rm_dirs(
sysfs_scheme->tried_regions);
+ sysfs_scheme->tried_regions->nr_regions = 0;
sysfs_scheme->tried_regions->total_bytes = 0;
}
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 1/2] mm/damon/core: cover discrete System RAM areas with per-range regions
2026-07-27 9:54 [PATCH 1/2] mm/damon/core: cover discrete System RAM areas with per-range regions Jiayuan Chen
2026-07-27 9:54 ` [PATCH 2/2] mm/damon/sysfs-schemes: report the number of tried regions Jiayuan Chen
@ 2026-07-27 14:26 ` SJ Park
1 sibling, 0 replies; 4+ messages in thread
From: SJ Park @ 2026-07-27 14:26 UTC (permalink / raw)
To: Jiayuan Chen
Cc: SJ Park, damon, Jiayuan Chen, Andrew Morton, David Hildenbrand,
Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Jonathan Corbet, Shuah Khan,
linux-mm, linux-kernel, linux-doc
Hello Jiayuan,
On Mon, 27 Jul 2026 17:54:22 +0800 Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
> From: Jiayuan Chen <jiayuan.chen@shopee.com>
>
> damon_set_region_system_rams_default(), introduced by commit 70d8797c15d6
> ("mm/damon: introduce damon_set_region_system_rams_default()"), is used by
> DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT to set the default monitoring
> target address range covering all 'System RAM' when the user does not
> specify a range. It walks the 'System RAM' resources but keeps only the
> start of the first resource and the end of the last one, and then sets a
> single monitoring region spanning that whole [first_start, last_end] range.
>
> On systems whose RAM is split into discrete areas that are far apart in the
> physical address space, that single region also covers the holes between
> them. For example:
>
> $ sudo cat /proc/iomem | grep RAM
> 00001000-0009ffff : System RAM
> 00100000-4848c017 : System RAM
> 4848c018-48550c57 : System RAM
> 48550c58-48551017 : System RAM
> 48551018-48615c57 : System RAM
> 48615c58-48616017 : System RAM
> 48616018-486dac57 : System RAM
> 486dac58-4e563017 : System RAM
> 4e563018-4e627c57 : System RAM
> 4e627c58-4ef39017 : System RAM
> 4ef39018-4ef3f057 : System RAM
> 4ef3f058-4efe6017 : System RAM
> 4efe6018-4efec057 : System RAM
> 4efec058-50247fff : System RAM
> 50317000-56720fff : System RAM
> 56722000-59c19fff : System RAM
> 6bbfe000-6bbfefff : System RAM
> 6bc00000-777fffff : System RAM
> 100000000-1007effffff : System RAM
> 67e80000000-77e7fffffff : System RAM
>
> Here the last two areas (about 1TB starting at 4GiB, and about 1.1TB
> starting at ~6.5TB) are separated by a ~5.5TB hole, and the single-region
> setup makes DAMON treat that entire hole as if it were memory.
>
> This is harmful in a few ways. The monitoring target regions are limited
> by max_nr_regions, so regions that fall into the hole waste that budget and
> leave fewer regions for the real RAM, coarsening the adaptive regions and
> degrading the monitoring accuracy.
The hole would look like not accessed. As a result, the whole region will be a
few regions that very cold. That wouldn't waste the budget that much. Do you
have some specific setups that this cannot help?
> In addition, DAMOS actions on the paddr
> operations set walk such a region page by page, so a region that covers the
> hole is walked for its entire (empty) span on every application.
That makes sense.
>
> Set a separate monitoring region for each discrete System RAM area instead,
> coalescing only truly adjacent (no gap in between) resources into one
> range, so holes between the areas are excluded. The reported *start and
> *end still carry the overall first-start and last-end, so the user-visible
> default range reported via the module parameters is unchanged.
I'm concerned if this could result in having too many regions. The gap between
user-visible parameters and internal state is also a concern.
A quick workaround would be adjusting the memory layout in BIOS, using DAMON
sysfs interface instead, or setting the monitor_region_{start,end} to cover
only the single area. Have you considered such workarounds?
Let's complete this high level discussion first.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 4+ messages in thread