mm/damon: introduce data access-as-a-data attribute
Subsystems (5)
SJ Park
maintainercover mm/damon: introduce data access-as-a-data attribute
TL;DR: extend DAMON's data attributes monitoring system to support page table accessed bit and PG_idle based access monitoring.
DAMON was initially introduced as a data access monitor. Users found data access pattern becomes more useful when it is combined with other data attributes such as belonging cgroups and backing page types. For such cases, DAMON has extended to support such data attributes monitoring in addition to the original data access monitoring. The DAMON probes system was introduced for this purpose. Users set probes for filtering data attributes of their interest. For use cases where the primary interests are the attributes but the access pattern, probe weights system has been introduced. When it is used, DAMON applies its adaptive regions adjustment based on the monitored data attributes.
However, DAMON stops access monitoring when the probe weights are used. DAMON cannot optimally help users who have interests in both data attributes and access patterns. Data access can also be thought of as another data attribute, though. Extend the probe system to support data access as a data attribute.
Introduce a new probe filter type, pgidle_unset. It shows if the page is not set as idle. Specifically, it shows the page table accessed bit and the PG_idle flag. It can inform if the region is ever accessed. But it cannot say when it is accessed. To answer the second question, introduce a new probe feature, prep actions. Using the features, Users can specify what preparation actions should be made to each region for each probe. DAMON executes the preparation actions for each sampling interval, like it is doing the preparation for access check in the access monitoring mode. To help 'pgidle_unset' probe action use case, 'set_pgidle' preparation action is introduced together. The action does exactly what the access monitoring was doing: clearing the page table accessed bits and setting the PG_idle flags.
Tests
=====
I compared the access pattern monitoring results from the classic way and the probe based way. As expected, the probe based way shows the results similar to that of the classic way. More detailed test methods and results are below.
First, do the access monitoring using the DAMON user-space tool [1] in the classic way. The system is idle. It shows no access as expected.
$ sudo ./damo/damo start
$ sudo ./damo/damo report access
heatmap:
00000000000000000000000000000000000000008999999811111110000000000000000000000000
# min/max temperatures: -640,000,000, -100,000,000, column size: 99.800
MiB
intervals: sample 5 ms aggr 100 ms (max access hz 200)
0 addr 4.000 KiB size 3.898 GiB access 0 hz age 6.400 s
1 addr 3.898 GiB size 787.301 MiB access 0 hz age 1 s
2 addr 4.667 GiB size 773.457 MiB access 0 hz age 5.800 s
3 addr 5.423 GiB size 2.374 GiB access 0 hz age 6.400 s
memory bw estimate: 0 B per second
total size: 7.797 GiB
record DAMON intervals: sample 5 ms, aggr 100 msStart an artificial memory access generator (masim) [2] in another window.
$ ./masim/masim.py run --config_file ./masim/configs/zigzag.cfg
Show the monitoring results. As expected, it captures accesses.
$ sudo ./damo/damo report access
heatmap:
00000000000000000000000000000000000000011111111111111118888888833378988888888888
# min/max temperatures: -1,470,000,000, -12,482,536, column size: 99.800
MiB
intervals: sample 5 ms aggr 100 ms (max access hz 200)
0 addr 4.000 KiB size 1.542 GiB access 0 hz age 14.700 s
1 addr 1.542 GiB size 788.324 MiB access 0 hz age 14.600 s
2 addr 2.311 GiB size 772.844 MiB access 0 hz age 14.200 s
[...]
50 addr 6.839 GiB size 1.742 MiB access 0 hz age 1.300 s
51 addr 6.840 GiB size 8.000 KiB access 100 hz age 0 ns
52 addr 6.840 GiB size 1.496 MiB access 160 hz age 0 ns
[...]
97 addr 7.162 GiB size 1.199 MiB access 40 hz age 400 ms
98 addr 7.163 GiB size 1.199 MiB access 20 hz age 400 ms
99 addr 7.164 GiB size 2.004 MiB access 160 hz age 0 ns
100 addr 7.166 GiB size 646.004 MiB access 0 hz age 400 ms
memory bw estimate: 26.148 GiB per second
total size: 7.797 GiB
record DAMON intervals: sample 5 ms, aggr 100 msAfter the artificial memory access generator (masim) is terminated, restart DAMON with the probe-based access monitoring. As expected, it shows no access since the system is idle again.
$ sudo ./damo/damo stop
$ sudo ./damo/damo start --probe_prep set_pgidle \
--probe_filter allow pgidle_unset --probe_weight 1
$ sudo ./damo/damo report attrs
heatmap:
00000000000000000000000000000000000000008999999711111100000000000000000000000000
# min/max temperatures: -600,000,000, -430,000,000, column size: 99.800
MiB
probe prep: set_pgidle, filter: allow pgidle_unset (weight: 1)
intervals: sample 5 ms aggr 100 ms (max probe hits 20)
# addr size age probe_hits
0 4.000 KiB 3.898 GiB 6 s 0
1 5.285 GiB 2.512 GiB 6 s 0
2 4.659 GiB 641.816 MiB 5.700 s 0
3 3.898 GiB 778.375 MiB 4.300 s 0
memory bw estimate: 0 B per second
total size: 7.797 GiB
record DAMON intervals: sample 5 ms, aggr 100 msStart the artificial memory access generator [2] again.
$ ./masim/masim.py run --config_file ./masim/configs/zigzag.cfg
Show the monitoring results. As expected, it captures accesses similar to the classic monitoring mode.
$ sudo ./damo/damo report attrs
heatmap:
00000000000000000000000000000000000000011111110000000177777777777777878798887777
# min/max temperatures: -1,330,000,000, 84,847,514, column size: 99.800
MiB
probe prep: set_pgidle, filter: allow pgidle_unset (weight: 1)
intervals: sample 5 ms aggr 100 ms (max probe hits 20)
# addr size age probe_hits
0 4.000 KiB 1.508 GiB 13.300 s 0
1 1.508 GiB 794.684 MiB 13.200 s 0
2 2.284 GiB 764.555 MiB 13 s 0
[...]
50 6.711 GiB 4.625 MiB 0 ns 17
51 6.716 GiB 2.504 MiB 0 ns 17
52 6.732 GiB 796.000 KiB 0 ns 17
[...]
90 7.162 GiB 512.000 KiB 2.200 s 2
91 7.061 GiB 700.000 KiB 2.300 s 1
92 6.935 GiB 316.000 KiB 2.300 s 4
memory bw estimate: 0 B per second
total size: 7.797 GiB
record DAMON intervals: sample 5 ms, aggr 100 msPatches Sequence
================
First four patches (patches 1-4) introduce the new probe filter type for knowing if a region is accessed. Patch 1 defines the new type in the core. Patch 2 implements the execution of the new filter in the physical address space DAMON operation set. Patch 3 implements a user interface on DAMON sysfs interface. Patch 4 updates the documentation for the new filter type.
Following 13 patches (patches 5-17) introduce the probe preparation actions feature. Patch 5 defines the data structure for specifying the preparation actions. Patch 6 completes setup of the API parameter for the prep. Patch 7 extends the DAMON operation set callback list to connect the parameter with the underlying operation set. Patch 8 implements the execution of the prep in the physical address space DAMON operation set.
Following five patches (patches 9-13) extends DAMON sysfs interface for the new prep feature. Patch 14 adds simple selftest for basic file operations of the new sysfs files. Final three patches (patches 15-17) respectively update design, usage and ABI documents for the new feature and its interface.
[1] https://github.com/damonitor/damo
[2] https://github.com/sjp38/masim
Changelog
=========
Changes from RFC v2.2
- RFC v2.2: https://lore.kernel.org/[email protected]
- Update test results with latest version of damo and masim.
- Rebase to latest mm-new.
Changes from RFC v2.1
- RFC v2.1: https://lore.kernel.org/[email protected]
- Evaluate ops.prep_probes first for do_prep.
- Rebase to the latest mm-new.
Changes from RFC v2
- RFC v2: https://lore.kernel.org/[email protected]
- Rename prep iterator macro param names to make more sense.
- Document set_samples param of prep_probes().
- Set do_prep after kdamond_wait_activation().
- Use const keyword for sysfs prep action-name structure fields.
- Fix typos in documents.
- Restructure sysfs interface patches for no build warning.
- Rebase to the latest mm-new.
Changes from RFC v1
- RFC v1: https://lore.kernel.org/[email protected]
- Fix wrong sample_addr setup condition.
- Fix build warnings from sysfs part.
- Fix typos.
- Rebase to latest mm-new.
- Add the tests section to the cover letter.
SJ Park (17):
mm/damon/core: introduce DAMON_FILTER_TYPE_PGIDLE_UNSET mm/damon/paddr: support PGIDLE_UNSET probe filter type mm/damon/sysfs: support pgidle_unset probe filter type Docs/mm/damon/design: document pgidle_unset probe filter type mm/damon/core: introduce damon_prep struct mm/damon/core: commit preps
mm/damon/core: introduce damon_operations->prep_probes() mm/damon/paddr: support damon_prep
mm/damon/sysfs: implement preps directory mm/damon/sysfs: implement preps/nr_preps file mm/damon/sysfs: create directories for nr_preps writes mm/damon/sysfs: implement prep_action file mm/damon/sysfs: pass preps to DAMON core selftests/damon/sysfs.sh: test probe prep sysfs files Docs/mm/damon/design: document probe preps Docs/admin-guide/mm/damon/usage: document probe preps sysfs files Docs/ABI/damon: document probe prep sysfs files
.../ABI/testing/sysfs-kernel-mm-damon | 13 + Documentation/admin-guide/mm/damon/usage.rst | 18 +- Documentation/mm/damon/design.rst | 15 +- include/linux/damon.h | 43 ++- mm/damon/core.c | 105 ++++++- mm/damon/paddr.c | 41 +++ mm/damon/sysfs.c | 280 +++++++++++++++++- tools/testing/selftests/damon/sysfs.sh | 27 ++ 8 files changed, 528 insertions(+), 14 deletions(-)
base-commit: 559cf8fac9b5af8d8d8c350fcf338e21aa049a31
Signature · 1 line
2.47.3
SJ Park
maintainerPATCH 1/17 mm/damon/core: introduce DAMON_FILTER_TYPE_PGIDLE_UNSET
Introduce a new DAMON filter type, pgidle_unset. It will match pages that have their PG_Idle flag unset, or the page table accessed bit set. In other words, it says if the page is accessed.
--- include/linux/damon.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
include/linux/damon.h +4 -2
@@ -745,12 +745,14 @@ struct damon_intervals_goal {/** * enum damon_filter_type - Type of &struct damon_filter * -* @DAMON_FILTER_TYPE_ANON: Anonymous pages. -* @DAMON_FILTER_TYPE_MEMCG: Specific memcg's pages. +* @DAMON_FILTER_TYPE_ANON: Anonymous pages. +* @DAMON_FILTER_TYPE_MEMCG: Specific memcg's pages. +* @DAMON_FILTER_TYPE_PGIDLE_UNSET: Pgidle is unset. */ enum damon_filter_type {DAMON_FILTER_TYPE_ANON ,DAMON_FILTER_TYPE_MEMCG , +DAMON_FILTER_TYPE_PGIDLE_UNSET , };/**
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 01/17] mm/damon/core: introduce DAMON_FILTER_TYPE_PGIDLE_UNSET
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
Introduce a new DAMON filter type,
pgidle_unset. It will match pages that have theirPG_Idleflag unset, or the page table accessed bit set. In other words, it says if the page is accessed.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
SJ Park
maintainerPATCH 2/17 mm/damon/paddr: support PGIDLE_UNSET probe filter type
In reply to SJ ParkImplement support of DAMON_FILTER_TYPE_PGIDLE_UNSET in the physical address space DAMON operations set. It reuses damon_folio_young(), which was being used for access monitoring.
--- mm/damon/paddr.c | 6 ++++++ 1 file changed, 6 insertions(+)
mm/damon/paddr.c +6 -0
@@ -132,6 +132,12 @@ static bool damon_pa_filter_match(struct damon_filter *filter, matched = filter->memcg_id ==mem_cgroup_id (memcg);rcu_read_unlock ();break ; +case DAMON_FILTER_TYPE_PGIDLE_UNSET : +if (!folio) + matched = false; +else + matched =damon_folio_young (folio); +break ;default :break ; }
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 02/17] mm/damon/paddr: support PGIDLE_UNSET probe filter type
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
Implement support of
DAMON_FILTER_TYPE_PGIDLE_UNSETin the physical address space DAMON operations set. It reusesdamon_folio_young(), which was being used for access monitoring.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
SJ Park
maintainerPATCH 3/17 mm/damon/sysfs: support pgidle_unset probe filter type
In reply to SJ ParkExtend DAMON sysfs interface to allow users to set DAMON_FILTER_TYPE_PGIDLE_UNSET by writing 'pgidle_unset' to the probe filter type file.
--- mm/damon/sysfs.c | 4 ++++ 1 file changed, 4 insertions(+)
mm/damon/sysfs.c +4 -0
@@ -781,6 +781,10 @@ damon_sysfs_filter_type_names[] = { .type = DAMON_FILTER_TYPE_MEMCG, .name = "memcg", }, + { + .type = DAMON_FILTER_TYPE_PGIDLE_UNSET, + .name = "pgidle_unset", + }, }; static ssize_t type_show(struct kobject *kobj,
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 03/17] mm/damon/sysfs: support pgidle_unset probe filter type
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
Extend DAMON sysfs interface to allow users to set
DAMON_FILTER_TYPE_PGIDLE_UNSETby writing 'pgidle_unset' to the probe filter type file.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
SJ Park
maintainerPATCH 4/17 Docs/mm/damon/design: document pgidle_unset probe filter type
In reply to SJ ParkUpdate DAMON design document for the newly added pgidle_unset probe filter type. Also use a list for the types, as it becomes not very easy to read the whole types in a simple sentence.
--- Documentation/mm/damon/design.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
Documentation/mm/damon/design.rst +6 -2
@@ -293,8 +293,12 @@ registration is made by specifying a probe per attribute. Each of the probe specifies a rule to determine if a given memory region has the related attribute. The rule is constructed with multiple filters. The filters work same to :ref:`DAMOS filters <damon_design_damos_filters>` except the supported -filter types. Currently only ``anon`` and ``memcg`` filter types are supported -for data attributes monitoring. +filter types. Currently below filter types are supported. + +- ``anon``: Same to that for DAMOS filters. +- ``memcg``: Same to that for DAMOS filters. +- ``pgidle_unset``: Matches if the page for the memory is marked as not + access-idle. If such probes are registered, DAMON executes the probes for each region's sampling memory when it does the access :ref:`sampling
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 04/17] Docs/mm/damon/design: document pgidle_unset probe filter type
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
Update DAMON design document for the newly added
pgidle_unsetprobe filter type. Also use a list for the types, as it becomes not very easy to read the whole types in a simple sentence.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
SJ Park
maintainerPATCH 5/17 mm/damon/core: introduce damon_prep struct
In reply to SJ ParkSome DAMON probe filter types require preparatory actions. For example, pgilde_unset probe filter can say if the page was accessed but when. To answer the second question, the PG_Idle flag should be set at a specific time. It can make life much easier if DAMON can do such preparatory actions. Introduce a new data type called damon_prep. It specifies each of the preparation actions for each probe. DAMON will execute the action for each region per sampling interval, like it clears page table accessed bits and unsets PG_Idle flag for access monitoring.
Also introduce DAMON_PREP_SET_PGIDLE as the initial prep action. As the name says, it will do exactly what DAMON was doing as the preparation action for the access monitoring.
--- include/linux/damon.h | 32 ++++++++++++++++++++++++++++++++ mm/damon/core.c | 26 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+)
include/linux/damon.h +32 -0
@@ -742,6 +742,27 @@ struct damon_intervals_goal {unsigned long max_sample_us; }; +/** +* enum damon_prep_action - DAMON probing preparation action. +* +* @DAMON_PREP_SET_PGIDLE: Set the probing memory as idle page. +*/ +enum damon_prep_action { +DAMON_PREP_SET_PGIDLE , +}; + +/** +* struct damon_prep - DAMON probing preparation request. +* +* @action: Action to do to the probing memory for the preparation. +*/ +struct damon_prep { +enum damon_prep_action action; +/* private: */ +/* siblings list. */ +struct list_head list; +}; +/** * enum damon_filter_type - Type of &struct damon_filter *
@@ -783,6 +804,8 @@ struct damon_filter {struct damon_probe {unsigned int weight;/* private: */ +/* Preparation actions to apply to each probing memory. */ +struct list_head preps;/* Filters for assessing if a given region is for this probe. */ struct list_head filters;/* Siblings list. */
@@ -962,6 +985,12 @@ static inline unsigned long damon_sz_region(struct damon_region *r)return r->ar.end - r->ar.start; } +#define damon_for_each_prep (p, probe) \ + list_for_each_entry(p, &(probe)->preps, list) + +#define damon_for_each_prep_safe (p, next, probe) \ + list_for_each_entry_safe(p, next, &(probe)->preps, list) +#define damon_for_each_filter (f, p) \ list_for_each_entry(f, &(p)->filters, list)
@@ -1015,6 +1044,9 @@ static inline unsigned long damon_sz_region(struct damon_region *r)#ifdef CONFIG_DAMON +struct damon_prep *damon_new_prep (enum damon_prep_action action); +void damon_add_prep (struct damon_probe *p,struct damon_prep *prep); +struct damon_filter *damon_new_filter (enum damon_filter_type type,bool matching,bool allow);void damon_add_filter (struct damon_probe *probe,struct damon_filter *f);
mm/damon/core.c +26 -0
@@ -112,6 +112,28 @@ int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)return err; } +struct damon_prep *damon_new_prep (enum damon_prep_action action) +{ +struct damon_prep *prep; + + prep =kmalloc_obj (*prep); +if (!prep) +return NULL ; + prep->action = action; +INIT_LIST_HEAD (&prep->list); +return prep; +} + +void damon_add_prep (struct damon_probe *p,struct damon_prep *prep) +{ +list_add_tail (&prep->list, &p->preps); +} + +static void damon_free_prep (struct damon_prep *p) +{ +kfree (p); +} +struct damon_filter *damon_new_filter (enum damon_filter_type type,bool matching,bool allow) {
@@ -168,6 +190,7 @@ struct damon_probe *damon_new_probe(void)if (!p)return NULL ; p->weight =0 ; +INIT_LIST_HEAD (&p->preps);INIT_LIST_HEAD (&p->filters);INIT_LIST_HEAD (&p->list);return p;
@@ -185,8 +208,11 @@ static void damon_del_probe(struct damon_probe *p)static void damon_free_probe (struct damon_probe *p) { +struct damon_prep *prep, *prep_next;struct damon_filter *f, *next; +damon_for_each_prep_safe (prep, prep_next, p) +damon_free_prep (prep);damon_for_each_filter_safe (f, next, p)damon_free_filter (f);kfree (p);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 05/17] mm/damon/core: introduce damon_prep struct
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] Missing exported cleanup API for `struct damon_prep` leads to broken abstraction on error paths. --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing exported cleanup API for struct damon_prep leads to broken abstraction on error paths. --
commit 046989ba790c1b12be9fe4a07f46c502a62eeb7b
Author: SJ Park <[email protected]>
mm/damon/core: introduce damon_prep struct
This commit introduces the damon_prep data structure to specify preparatory actions for DAMON probes. It also adds DAMON_PREP_SET_PGIDLE as the initial preparation action for access monitoring.
Quoted 4 lines
mm/damon/core.c +0
-0
[ ... ]
Quoted 5 lines
mm/damon/core.c +1
-0@@ -111,6 +111,28 @@ int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)return err; } +struct damon_prep *damon_new_prep (enum damon_prep_action action)
mm/damon/core.c int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id) · line 124
Quoted 10 lines
mm/damon/core.c +10
-0+{ +struct damon_prep *prep; + + prep =kmalloc_obj (*prep); +if (!prep) +return NULL ; + prep->action = action; +INIT_LIST_HEAD (&prep->list); +return prep; +}
[Severity: Low]
Is there a missing exported cleanup API for struct damon_prep?
Since damon_new_prep() is exposed for external modules to allocate a new prep structure, do they need a corresponding exported destructor (like damon_destroy_prep()) to clean it up if an error occurs before it is attached to a probe via damon_add_prep()?
Currently, damon_free_prep() is static, which forces any external caller to manually call kfree() on error paths, potentially breaking the subsystem's abstraction.
Quoted 10 lines
mm/damon/core.c +10
-0+ +void damon_add_prep (struct damon_probe *p,struct damon_prep *prep) +{ +list_add_tail (&prep->list, &p->preps); +} + +static void damon_free_prep (struct damon_prep *p) +{ +kfree (p); +}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
SJ Park
maintainerRe: [PATCH 05/17] mm/damon/core: introduce damon_prep struct
Quoted 39 lines · On Tue, 01 Sep 2026 04:46:01 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing exported cleanup API forstruct damon_prepleads to broken abstraction on error paths. --commit
046989ba790c1b12be9fe4a07f46c502a62eeb7b
Author: SJ Park <[email protected]>
mm/damon/core: introducedamon_prepstructThis commit introduces the
damon_prepdata structure to specify preparatory actions for DAMON probes. It also addsDAMON_PREP_SET_PGIDLEas the initial preparation action for access monitoring.Quoted 4 lines
mm/damon/core.c +0
-0[ ... ]
Quoted 5 lines
mm/damon/core.c +1
-0@@ -111,6 +111,28 @@ int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)return err; } +struct damon_prep *damon_new_prep (enum damon_prep_action action)mm/damon/core.c int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id) · line 124
Quoted 10 lines
mm/damon/core.c +10
-0+{ +struct damon_prep *prep; + + prep =kmalloc_obj (*prep); +if (!prep) +return NULL ; + prep->action = action; +INIT_LIST_HEAD (&prep->list); +return prep; +}[Severity: Low]
Is there a missing exported cleanup API for structdamon_prep?
Quoted 8 lines
Since
damon_new_prep()is exposed for external modules to allocate a new prep structure, do they need a corresponding exported destructor (likedamon_destroy_prep()) to clean it up if an error occurs before it is attached to a probe viadamon_add_prep()?Currently,
damon_free_prep()is static, which forces any external caller to manually callkfree()on error paths, potentially breaking the subsystem's abstraction.
The cleanup API is not necessary. Callers will be able to free up preps with the context at once using damon_destroy_ctx().
Quoted 14 lines
Quoted 11 lines
mm/damon/core.c +10
-0+ +void damon_add_prep (struct damon_probe *p,struct damon_prep *prep) +{ +list_add_tail (&prep->list, &p->preps); +} + +static void damon_free_prep (struct damon_prep *p) +{ +kfree (p); +}Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
Thanks,
SJ
SJ Park
maintainerPATCH 6/17 mm/damon/core: commit preps
In reply to SJ Parkdamon_commit_probes() is ignoring damon_prep. Commit the prep actions, too.
--- mm/damon/core.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
mm/damon/core.c +59 -0
@@ -129,11 +129,34 @@ void damon_add_prep(struct damon_probe *p, struct damon_prep *prep)list_add_tail (&prep->list, &p->preps); } +static void damon_del_prep (struct damon_prep *p) +{ +list_del (&p->list); +} +static void damon_free_prep (struct damon_prep *p) {kfree (p); } +static void damon_destroy_prep (struct damon_prep *p) +{ +damon_del_prep (p); +damon_free_prep (p); +} + +static struct damon_prep *damon_nth_prep (int n,struct damon_probe *p) +{ +struct damon_prep *prep; +int i =0 ; + +damon_for_each_prep (prep, p) { +if (i++ == n) +return prep; + } +return NULL ; +} +struct damon_filter *damon_new_filter (enum damon_filter_type type,bool matching,bool allow) {
@@ -1706,6 +1729,36 @@ static int damon_commit_targets(return err; } +static void damon_commit_prep (struct damon_prep *dst,struct damon_prep *src) +{ + dst->action = src->action; +} + +static int damon_commit_preps (struct damon_probe *dst,struct damon_probe *src) +{ +struct damon_prep *dst_prep, *next, *src_prep, *new_prep; +int i =0 , j =0 ; + +damon_for_each_prep_safe (dst_prep, next, dst) { + src_prep =damon_nth_prep (i++, src); +if (src_prep) +damon_commit_prep (dst_prep, src_prep); +else +damon_destroy_prep (dst_prep); + } + +damon_for_each_prep_safe (src_prep, next, src) { +if (j++ < i) +continue ; + + new_prep =damon_new_prep (src_prep->action); +if (!new_prep) +return -ENOMEM ; +damon_add_prep (dst, new_prep); + } +return 0 ; +} +static void damon_commit_filter (struct damon_filter *dst,struct damon_filter *src) {
@@ -1764,6 +1817,9 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src) src_probe =damon_nth_probe (i++, src);if (src_probe) { dst_probe->weight = src_probe->weight; + err =damon_commit_preps (dst_probe, src_probe); +if (err) +return err; err =damon_commit_filters (dst_probe, src_probe);if (err)return err;
@@ -1781,6 +1837,9 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src)return -ENOMEM ;damon_add_probe (dst, new_probe); new_probe->weight = src_probe->weight; + err =damon_commit_preps (new_probe, src_probe); +if (err) +return err; err =damon_commit_filters (new_probe, src_probe);if (err)return err;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 06/17] mm/damon/core: commit preps
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
damon_commit_probes()is ignoringdamon_prep. Commit the prep actions, too.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
SJ Park
maintainerPATCH 7/17 mm/damon/core: introduce damon_operations->prep_probes()
In reply to SJ Parkdamon_prep needs to be executed by the underlying DAMON operation set. Extend the operation set callback list for the execution of damon_prep actions. If the underlying operation set implements the callback, DAMON core executes it in the monitoring preparation time.
--- include/linux/damon.h | 5 +++++ mm/damon/core.c | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-)
include/linux/damon.h +5 -0
@@ -630,6 +630,7 @@ enum damon_ops_id {* @update: Update operations-related data structures. * @prepare_access_checks: Prepare next access check of target regions. * @check_accesses: Check the accesses to target regions. +* @prep_probes: Prepare applying probes for each region. * @apply_probes: Apply probes for each region. * @get_scheme_score: Get the score of a region for a scheme. * @apply_scheme: Apply a DAMON-based operation scheme.
@@ -657,6 +658,9 @@ enum damon_ops_id {* last preparation and update the number of observed accesses of each region. * It should also return max number of observed accesses that made as a result * of its update. The value will be used for regions adjustment threshold. +* @prep_probes should execute required &struct damon_prep for next &struct +* damon_probe applications to each region. It should also set +* &damon_region->sampling_addr of each region if ``set_samples`` is true. * @apply_probes should apply the data attribute probes to each region and * accordingly update the probe hits counter of the region. It should also * set &damon_region->sampling_addr of each region if ``set_samples`` is true.
@@ -679,6 +683,7 @@ struct damon_operations {void (*update)(struct damon_ctx *context);void (*prepare_access_checks)(struct damon_ctx *context);unsigned int (*check_accesses)(struct damon_ctx *context); +void (*prep_probes)(struct damon_ctx *context,bool set_samples);unsigned int (*apply_probes)(struct damon_ctx *context,bool set_samples,bool return_max_wsum); int (*get_scheme_score)(struct damon_ctx *context,
mm/damon/core.c +19 -1
@@ -157,6 +157,18 @@ static struct damon_prep *damon_nth_prep(int n, struct damon_probe *p)return NULL ; } +static bool damon_has_prep (struct damon_ctx *c) +{ +struct damon_prep *prep; +struct damon_probe *probe; + +damon_for_each_probe (probe, c) { +damon_for_each_prep (prep, probe) +return true; + } +return false; +} +struct damon_filter *damon_new_filter (enum damon_filter_type type,bool matching,bool allow) {
@@ -3906,14 +3918,19 @@ static int kdamond_fn(void *data)unsigned long next_ops_update_sis = ctx->next_ops_update_sis;unsigned long sample_interval = ctx->attrs.sample_interval;bool access_check_disabled =damon_has_probe_weights (ctx); +bool do_prep;unsigned int max_merge_score =0 , max_wsum;bool get_max_wsum;if (kdamond_wait_activation (ctx))break ; + do_prep = ctx->ops.prep_probes &&damon_has_prep (ctx); +if (!access_check_disabled && ctx->ops.prepare_access_checks) ctx->ops.prepare_access_checks (ctx); +if (do_prep) + ctx->ops.prep_probes (ctx, access_check_disabled);kdamond_usleep (sample_interval); ctx->passed_sample_intervals++;
@@ -3928,7 +3945,8 @@ static int kdamond_fn(void *data)else get_max_wsum = false; max_wsum = ctx->ops.apply_probes (ctx, - access_check_disabled, get_max_wsum); + access_check_disabled && !do_prep, + get_max_wsum);if (get_max_wsum) max_merge_score = max_wsum; }
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 07/17] mm/damon/core: introduce damon_operations->prep_probes()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 6 lines
damon_prepneeds to be executed by the underlying DAMON operation set. Extend the operation set callback list for the execution ofdamon_prepactions. If the underlying operation set implements the callback, DAMON core executes it in the monitoring preparation time.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
SJ Park
maintainerPATCH 8/17 mm/damon/paddr: support damon_prep
In reply to SJ ParkImplement damon_operations->prep_probes() callback. Support the only existing prep action, DAMON_PREP_SET_PGIDLE in a way similar to what it was doing for the access check preparation: unset page table accessed bits and set PG_Idle flag. Reuse the function for the access check preparation.
--- mm/damon/paddr.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
mm/damon/paddr.c +35 -0
@@ -105,6 +105,40 @@ static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx)return max_nr_accesses; } +static void damon_pa_prep_probes_region (struct damon_region *r, +struct damon_probe *probe,struct damon_ctx *ctx) +{ +struct damon_prep *p; + +damon_for_each_prep (p, probe) { +switch (p->action) { +case DAMON_PREP_SET_PGIDLE : +damon_pa_mkold (damon_pa_phys_addr (r->sampling_addr, + ctx->addr_unit)); +break ; +default : +break ; + } + } +} + +static void damon_pa_prep_probes (struct damon_ctx *ctx,bool set_samples) +{ +struct damon_target *t; +struct damon_region *r; +struct damon_probe *p; + +damon_for_each_target (t, ctx) { +damon_for_each_region (r, t) { +if (set_samples) + r->sampling_addr =damon_rand (ctx, r->ar.start, + r->ar.end); +damon_for_each_probe (p, ctx) +damon_pa_prep_probes_region (r, p, ctx); + } + } +} +static bool damon_pa_filter_match (struct damon_filter *filter,struct folio *folio) {
@@ -448,6 +482,7 @@ static int __init damon_pa_initcall(void) .update = NULL, .prepare_access_checks = damon_pa_prepare_access_checks, .check_accesses = damon_pa_check_accesses, + .prep_probes = damon_pa_prep_probes, .apply_probes = damon_pa_apply_probes, .target_valid = NULL, .apply_scheme = damon_pa_apply_scheme,
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 08/17] mm/damon/paddr: support damon_prep
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] `damon_pa_prep_probes` applies probe preparation actions without checking probe filters, causing…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] damon_pa_prep_probes applies probe preparation actions without checking probe filters, causing unintended page state modifications and redundant folio lookups. --
commit 05f1236264960a0054ba7741a1b9b7ae78666ee1
Author: SJ Park <[email protected]>
mm/damon/paddr: support damon_prep
This commit implements the prep_probes() callback for damon_operations. It adds support for the DAMON_PREP_SET_PGIDLE preparation action by unsetting page table accessed bits and setting the PG_idle flag via damon_pa_mkold().
Quoted 4 lines
mm/damon/paddr.c +0
-0
[ ... ]
Quoted 4 lines
mm/damon/paddr.c +0
-0@@ -105,6 +105,40 @@ static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx)return max_nr_accesses; }
mm/damon/paddr.c static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx) · line 117
Quoted 10 lines
mm/damon/paddr.c +10
-0+static void damon_pa_prep_probes_region (struct damon_region *r, +struct damon_probe *probe,struct damon_ctx *ctx) +{ +struct damon_prep *p; + +damon_for_each_prep (p, probe) { +switch (p->action) { +case DAMON_PREP_SET_PGIDLE : +damon_pa_mkold (damon_pa_phys_addr (r->sampling_addr, + ctx->addr_unit));
[Severity: Medium]
Will this unconditionally mutate the page state for every prep action, regardless of whether the page passes the probe's filters?
Because damon_pa_prep_probes_region() doesn't check the filters, it appears it will clear the accessed bit and set PG_idle on pages that are explicitly excluded (e.g., when a probe only targets a specific memcg).
Could this disrupt legitimate LRU tracking and reclaim for processes not targeted by the probe?
Quoted 10 lines
mm/damon/paddr.c +10
-0+break ; +default : +break ; + } + } +} + +static void damon_pa_prep_probes (struct damon_ctx *ctx,bool set_samples) +{ +struct damon_target *t;
mm/damon/paddr.c static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx) · line 137
Quoted 10 lines
mm/damon/paddr.c +10
-0+struct damon_region *r; +struct damon_probe *p; + +damon_for_each_target (t, ctx) { +damon_for_each_region (r, t) { +if (set_samples) + r->sampling_addr =damon_rand (ctx, r->ar.start, + r->ar.end); +damon_for_each_probe (p, ctx) +damon_pa_prep_probes_region (r, p, ctx);
[Severity: Medium]
Since damon_pa_prep_probes_region() is called in a nested loop for each probe, could this cause redundant work?
If multiple probes use DAMON_PREP_SET_PGIDLE, this will redundantly invoke damon_pa_mkold() multiple times on the exact same physical address, leading to unnecessary folio lookups and reference cycles per region.
Quoted 3 lines
mm/damon/paddr.c +3
-0+ } + } +}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
SJ Park
maintainerRe: [PATCH 08/17] mm/damon/paddr: support damon_prep
Quoted 39 lines · On Tue, 01 Sep 2026 04:47:02 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium]damon_pa_prep_probesapplies probe preparation actions without checking probe filters, causing unintended page state modifications and redundant folio lookups. --commit
05f1236264960a0054ba7741a1b9b7ae78666ee1
Author: SJ Park <[email protected]>
mm/damon/paddr: supportdamon_prepThis commit implements the
prep_probes()callback fordamon_operations. It adds support for theDAMON_PREP_SET_PGIDLEpreparation action by unsetting page table accessed bits and setting thePG_idleflag viadamon_pa_mkold().Quoted 4 lines
mm/damon/paddr.c +0
-0[ ... ]
Quoted 4 lines
mm/damon/paddr.c +0
-0@@ -105,6 +105,40 @@ static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx)return max_nr_accesses; }mm/damon/paddr.c static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx) · line 117
Quoted 10 lines
mm/damon/paddr.c +10
-0+static void damon_pa_prep_probes_region (struct damon_region *r, +struct damon_probe *probe,struct damon_ctx *ctx) +{ +struct damon_prep *p; + +damon_for_each_prep (p, probe) { +switch (p->action) { +case DAMON_PREP_SET_PGIDLE : +damon_pa_mkold (damon_pa_phys_addr (r->sampling_addr, + ctx->addr_unit));[Severity: Medium]
Will this unconditionally mutate the page state for every prep action, regardless of whether the page passes the probe's filters?
Quoted 6 lines
Because
damon_pa_prep_probes_region()doesn't check the filters, it appears it will clear the accessed bit and setPG_idleon pages that are explicitly excluded (e.g., when a probe only targets a specific memcg).Could this disrupt legitimate LRU tracking and reclaim for processes not targeted by the probe?
No. damon_pa_mkold() will set page as referenced if it was referenced before, to not disrupt LRU tracking and reclaim, same to the classical access monitoring and idle page tracking.
Quoted 26 lines
Quoted 11 lines
mm/damon/paddr.c +10
-0+break ; +default : +break ; + } + } +} + +static void damon_pa_prep_probes (struct damon_ctx *ctx,bool set_samples) +{ +struct damon_target *t;mm/damon/paddr.c static unsigned int damon_pa_check_accesses(struct damon_ctx *ctx) · line 137
Quoted 10 lines
mm/damon/paddr.c +10
-0+struct damon_region *r; +struct damon_probe *p; + +damon_for_each_target (t, ctx) { +damon_for_each_region (r, t) { +if (set_samples) + r->sampling_addr =damon_rand (ctx, r->ar.start, + r->ar.end); +damon_for_each_probe (p, ctx) +damon_pa_prep_probes_region (r, p, ctx);[Severity: Medium]
Sincedamon_pa_prep_probes_region()is called in a nested loop for each probe, could this cause redundant work?
Quoted 3 lines
If multiple probes use
DAMON_PREP_SET_PGIDLE, this will redundantly invokedamon_pa_mkold()multiple times on the exact same physical address, leading to unnecessary folio lookups and reference cycles per region.
No issue. DAMON users would know what they are asking to do.
Quoted 7 lines
Quoted 4 lines
mm/damon/paddr.c +3
-0+ } + } +}Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
Thanks,
SJ
SJ Park
maintainerPATCH 9/17 mm/damon/sysfs: implement preps directory
In reply to SJ ParkImplement a sysfs directory named 'preps' under the probe directory. It will be evolved to be used for specifying probe preps.
--- mm/damon/sysfs.c | 65 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-)
mm/damon/sysfs.c +59 -6
@@ -749,6 +749,35 @@ static const struct kobj_type damon_sysfs_intervals_ktype = { .default_groups = damon_sysfs_intervals_groups, }; +/* +* preps directory +*/ + +struct damon_sysfs_preps { +struct kobject kobj; +}; + +static struct damon_sysfs_preps *damon_sysfs_preps_alloc (void ) +{ + return kzalloc_obj(struct damon_sysfs_preps); +} + +static void damon_sysfs_preps_release (struct kobject *kobj) +{ +kfree (container_of(kobj ,struct damon_sysfs_preps ,kobj )); +} + +static struct attribute *damon_sysfs_preps_attrs[] = { +NULL , +}; +ATTRIBUTE_GROUPS (damon_sysfs_preps); + +static const struct kobj_type damon_sysfs_preps_ktype = { + .release = damon_sysfs_preps_release, + .sysfs_ops = &kobj_sysfs_ops, + .default_groups = damon_sysfs_preps_groups, +}; +/* * filter directory */
@@ -1069,6 +1098,7 @@ static const struct kobj_type damon_sysfs_filters_ktype = {struct damon_sysfs_probe {struct kobject kobj;unsigned int weight; +struct damon_sysfs_preps *preps;struct damon_sysfs_filters *filters; };
@@ -1079,25 +1109,48 @@ static struct damon_sysfs_probe *damon_sysfs_probe_alloc(void)static int damon_sysfs_probe_add_dirs (struct damon_sysfs_probe *probe) { +struct damon_sysfs_preps *preps;struct damon_sysfs_filters *filters;int err; - filters =damon_sysfs_filters_alloc (); -if (!filters) + preps =damon_sysfs_preps_alloc (); +if (!preps)return -ENOMEM ; + probe->preps = preps; + + err =kobject_init_and_add (&preps->kobj, &damon_sysfs_preps_ktype, + &probe->kobj,"preps" ); +if (err) + goto put_preps_out; + + filters =damon_sysfs_filters_alloc (); +if (!filters) { + err = -ENOMEM ; + goto del_preps_out; + } probe->filters = filters; err =kobject_init_and_add (&filters->kobj, &damon_sysfs_filters_ktype, &probe->kobj,"filters" ); -if (err) { -kobject_put (&filters->kobj); - probe->filters =NULL ; - } +if (err) + goto put_filters_out; +return err; + +put_filters_out: +kobject_put (&filters->kobj); + probe->filters =NULL ; +del_preps_out: +kobject_del (&preps->kobj); +put_preps_out: +kobject_put (&preps->kobj); + probe->preps =NULL ;return err; }static void damon_sysfs_probe_rm_dirs (struct damon_sysfs_probe *probe) { +if (probe->preps) +kobject_put (&probe->preps->kobj);if (probe->filters) {damon_sysfs_filters_rm_dirs (probe->filters);kobject_put (&probe->filters->kobj);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 09/17] mm/damon/sysfs: implement preps directory
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Implement a sysfs directory named 'preps' under the probe directory. It will be evolved to be used for specifying probe preps.
Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=9
SJ Park
maintainerPATCH 10/17 mm/damon/sysfs: implement preps/nr_preps file
In reply to SJ ParkImplement nr_preps file under the preps directory. It will be evolved to be used for generating sub directories that will represent each probe preparation action.
--- mm/damon/sysfs.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-)
mm/damon/sysfs.c +52 -1
@@ -755,6 +755,7 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {struct damon_sysfs_preps {struct kobject kobj; +int nr; };static struct damon_sysfs_preps *damon_sysfs_preps_alloc (void )
@@ -762,12 +763,60 @@ static struct damon_sysfs_preps *damon_sysfs_preps_alloc(void) return kzalloc_obj(struct damon_sysfs_preps); } +static void damon_sysfs_preps_rm_dirs (struct damon_sysfs_preps *preps) +{ + preps->nr =0 ; +} + +static int damon_sysfs_preps_add_dirs (struct damon_sysfs_preps *preps, +int nr_preps) +{ + preps->nr = nr_preps; +return 0 ; +} + +static ssize_t nr_preps_show (struct kobject *kobj,struct kobj_attribute *attr, +char *buf) +{ +struct damon_sysfs_preps *preps =container_of (kobj, + struct damon_sysfs_preps, kobj); + +return sysfs_emit (buf,"%d\n" , preps->nr); +} + +static ssize_t nr_preps_store (struct kobject *kobj, +struct kobj_attribute *attr,const char *buf,size_t count) +{ +struct damon_sysfs_preps *preps; +int nr, err =kstrtoint (buf,0 , &nr); + +if (err) +return err; +if (nr <0 ) +return -EINVAL ; + + preps = container_of(kobj, struct damon_sysfs_preps, kobj); + +if (!mutex_trylock (&damon_sysfs_lock)) +return -EBUSY ; + err =damon_sysfs_preps_add_dirs (preps, nr); +mutex_unlock (&damon_sysfs_lock); +if (err) +return err; + +return count; +} +static void damon_sysfs_preps_release (struct kobject *kobj) {kfree (container_of(kobj ,struct damon_sysfs_preps ,kobj )); } +static struct kobj_attribute damon_sysfs_preps_nr_attr = +__ATTR_RW_MODE (nr_preps,0600 ); +static struct attribute *damon_sysfs_preps_attrs[] = { + &damon_sysfs_preps_nr_attr.attr,NULL , };ATTRIBUTE_GROUPS (damon_sysfs_preps);
@@ -1149,8 +1198,10 @@ static int damon_sysfs_probe_add_dirs(struct damon_sysfs_probe *probe)static void damon_sysfs_probe_rm_dirs (struct damon_sysfs_probe *probe) { -if (probe->preps) +if (probe->preps) { +damon_sysfs_preps_rm_dirs (probe->preps);kobject_put (&probe->preps->kobj); + }if (probe->filters) {damon_sysfs_filters_rm_dirs (probe->filters);kobject_put (&probe->filters->kobj);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 10/17] mm/damon/sysfs: implement preps/nr_preps file
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
Implement
nr_prepsfile under the preps directory. It will be evolved to be used for generating sub directories that will represent each probe preparation action.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=10
SJ Park
maintainerPATCH 11/17 mm/damon/sysfs: create directories for nr_preps writes
In reply to SJ ParkImplement nr_preps write action to actually create subdirectories of the number. Each of the directory will be evolved to represent each probe preparation action.
--- mm/damon/sysfs.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-)
mm/damon/sysfs.c +79 -1
@@ -749,12 +749,50 @@ static const struct kobj_type damon_sysfs_intervals_ktype = { .default_groups = damon_sysfs_intervals_groups, }; +/* +* prep directory +*/ + +struct damon_sysfs_prep { +struct kobject kobj; +}; + +static struct damon_sysfs_prep *damon_sysfs_prep_alloc (void ) +{ +struct damon_sysfs_prep *prep; + + prep = kzalloc_obj(struct damon_sysfs_prep); +if (!prep) +return prep; +return prep; +} + +static void damon_sysfs_prep_release (struct kobject *kobj) +{ +struct damon_sysfs_prep *prep =container_of (kobj, + struct damon_sysfs_prep, kobj); + +kfree (prep); +} + +static struct attribute *damon_sysfs_prep_attrs[] = { +NULL , +}; +ATTRIBUTE_GROUPS (damon_sysfs_prep); + +static const struct kobj_type damon_sysfs_prep_ktype = { + .release = damon_sysfs_prep_release, + .sysfs_ops = &kobj_sysfs_ops, + .default_groups = damon_sysfs_prep_groups, +}; +/* * preps directory */ struct damon_sysfs_preps {struct kobject kobj; +struct damon_sysfs_prep **preps_arr;int nr; };
@@ -765,13 +803,53 @@ static struct damon_sysfs_preps *damon_sysfs_preps_alloc(void)static void damon_sysfs_preps_rm_dirs (struct damon_sysfs_preps *preps) { +struct damon_sysfs_prep **preps_arr = preps->preps_arr; +int i; + +for (i =0 ; i < preps->nr; i++) { +kobject_del (&preps_arr[i]->kobj); +kobject_put (&preps_arr[i]->kobj); + } preps->nr =0 ; +kfree (preps_arr); + preps->preps_arr =NULL ; }static int damon_sysfs_preps_add_dirs (struct damon_sysfs_preps *preps,int nr_preps) { - preps->nr = nr_preps; +struct damon_sysfs_prep **preps_arr, *prep; +int err, i; + +damon_sysfs_preps_rm_dirs (preps); +if (!nr_preps) +return 0 ; + + preps_arr =kmalloc_objs (*preps_arr, nr_preps, +GFP_KERNEL | __GFP_NOWARN); +if (!preps_arr) +return -ENOMEM ; + preps->preps_arr = preps_arr; + +for (i =0 ; i < nr_preps; i++) { + prep =damon_sysfs_prep_alloc (); +if (!prep) { +damon_sysfs_preps_rm_dirs (preps); +return -ENOMEM ; + } + + err =kobject_init_and_add (&prep->kobj, + &damon_sysfs_prep_ktype, &preps->kobj,"%d" , + i); +if (err) { +kobject_put (&prep->kobj); +damon_sysfs_preps_rm_dirs (preps); +return err; + } + + preps_arr[i] = prep; + preps->nr++; + }return 0 ; }
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 11/17] mm/damon/sysfs: create directories for nr_preps writes
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 5 lines
Implement
nr_prepswrite action to actually create subdirectories of the number. Each of the directory will be evolved to represent each probe preparation action.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=11
SJ Park
maintainerPATCH 12/17 mm/damon/sysfs: implement prep_action file
In reply to SJ ParkAdd a file named prep_action under the prep directory. It represents the corresponding probe preparation action.
--- mm/damon/sysfs.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
mm/damon/sysfs.c +57 -0
@@ -755,6 +755,7 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {struct damon_sysfs_prep {struct kobject kobj; +enum damon_prep_action action; };static struct damon_sysfs_prep *damon_sysfs_prep_alloc (void )
@@ -764,9 +765,61 @@ static struct damon_sysfs_prep *damon_sysfs_prep_alloc(void) prep = kzalloc_obj(struct damon_sysfs_prep);if (!prep)return prep; + prep->action =DAMON_PREP_SET_PGIDLE ;return prep; } +struct damon_sysfs_prep_action_name { +const enum damon_prep_action action; +const char *name; +}; + +static const struct damon_sysfs_prep_action_name +damon_sysfs_prep_action_names[] = { + { + .action =DAMON_PREP_SET_PGIDLE , + .name ="set_pgidle" , + }, +}; + +static ssize_t prep_action_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf) +{ +struct damon_sysfs_prep *prep =container_of (kobj, + struct damon_sysfs_prep, kobj); +int i; + +for (i =0 ; i <ARRAY_SIZE (damon_sysfs_prep_action_names); i++) { +const struct damon_sysfs_prep_action_name *action_name; + + action_name = &damon_sysfs_prep_action_names[i]; +if (action_name->action == prep->action) +return sysfs_emit (buf,"%s\n" , action_name->name); + } +return -EINVAL ; +} + +static ssize_t prep_action_store (struct kobject *kobj, +struct kobj_attribute *attr,const char *buf,size_t count) +{ +struct damon_sysfs_prep *prep =container_of (kobj, + struct damon_sysfs_prep, kobj); +ssize_t ret = -EINVAL ; +int i; + +for (i =0 ; i <ARRAY_SIZE (damon_sysfs_prep_action_names); i++) { +const struct damon_sysfs_prep_action_name *action_name; + + action_name = &damon_sysfs_prep_action_names[i]; +if (sysfs_streq (buf, action_name->name)) { + prep->action = action_name->action; + ret = count; +break ; + } + } +return ret; +} +static void damon_sysfs_prep_release (struct kobject *kobj) { struct damon_sysfs_prep *prep = container_of(kobj,
@@ -775,7 +828,11 @@ static void damon_sysfs_prep_release(struct kobject *kobj)kfree (prep); } +static struct kobj_attribute damon_sysfs_prep_prep_action_attr = +__ATTR_RW_MODE (prep_action,0600 ); +static struct attribute *damon_sysfs_prep_attrs[] = { + &damon_sysfs_prep_prep_action_attr.attr,NULL , };ATTRIBUTE_GROUPS (damon_sysfs_prep);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 12/17] mm/damon/sysfs: implement prep_action file
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Add a file named
prep_actionunder the prep directory. It represents the corresponding probe preparation action.Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=12
SJ Park
maintainerPATCH 13/17 mm/damon/sysfs: pass preps to DAMON core
In reply to SJ ParkDAMON sysfs interface provides the files for setting DAMON probe preps. But the underlying code is not really passing the user-set values to DAMON core. Pass those.
--- mm/damon/sysfs.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
mm/damon/sysfs.c +25 -0
@@ -2176,6 +2176,23 @@ static int damon_sysfs_set_attrs(struct damon_ctx *ctx,return damon_set_attrs (ctx, &attrs); } +static int damon_sysfs_set_preps (struct damon_probe *probe, +struct damon_sysfs_preps *sys_preps) +{ +int i; + +for (i =0 ; i < sys_preps->nr; i++) { +struct damon_sysfs_prep *sys_prep = sys_preps->preps_arr[i]; +struct damon_prep *prep; + + prep =damon_new_prep (sys_prep->action); +if (!prep) +return -ENOMEM ; +damon_add_prep (probe, prep); + } +return 0 ; +} +static int damon_sysfs_set_filters (struct damon_probe *probe,struct damon_sysfs_filters *sys_filters) {
@@ -2211,7 +2228,15 @@ static int damon_sysfs_set_probe(struct damon_probe *probe, struct damon_sysfs_probe *sys_probe) {struct damon_sysfs_filters *sys_filters; +struct damon_sysfs_preps *sys_preps; +int err; + sys_preps = sys_probe->preps; +if (sys_preps) { + err =damon_sysfs_set_preps (probe, sys_preps); +if (err) +return err; + } sys_filters = sys_probe->filters;if (!sys_filters)return 0 ;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 13/17] mm/damon/sysfs: pass preps to DAMON core
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] Data race on `sys_prep->action` due to lockless read and write --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Data race on sys_prep->action due to lockless read and write
--
commit 09b46cd761363fb28603bd1d27adb637a6c16a7d
Author: SJ Park <[email protected]>
mm/damon/sysfs: pass preps to DAMON core
DAMON sysfs interface provides the files for setting DAMON probe preps. But the underlying code is not really passing the user-set values to DAMON core. Pass those.
Quoted 8 lines
mm/damon/sysfs.c +0
-0@@ -2176,6 +2176,23 @@ static int damon_sysfs_set_attrs(struct damon_ctx *ctx,return damon_set_attrs (ctx, &attrs); }
mm/damon/sysfs.c static int damon_sysfs_set_attrs(struct damon_ctx *ctx, · line 2188
Quoted 10 lines
mm/damon/sysfs.c +10
-0+static int damon_sysfs_set_preps (struct damon_probe *probe, +struct damon_sysfs_preps *sys_preps) +{ +int i; + +for (i =0 ; i < sys_preps->nr; i++) { +struct damon_sysfs_prep *sys_prep = sys_preps->preps_arr[i]; +struct damon_prep *prep; + + prep =damon_new_prep (sys_prep->action);
[Severity: Low]
Could this result in a data race on sys_prep->action?
During DAMON context building, this locklessly reads the action enum while a concurrent root user could be writing to the /sys/.../prep_action attribute.
A concurrent write to prep_action could happen while another process issues a commit command to the state file, which runs damon_sysfs_commit_input asynchronously on the kdamond thread without holding damon_sysfs_lock.
Would it be better to use READ_ONCE() here, along with a corresponding WRITE_ONCE() on the writer side, to adhere to the Linux Kernel Memory Model guidelines and avoid potential KCSAN warnings?
Quoted 7 lines
mm/damon/sysfs.c +7
-0+if (!prep) +return -ENOMEM ; +damon_add_prep (probe, prep); + } +return 0 ; +} +
[ ... ]
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=13
SJ Park
maintainerRe: [PATCH 13/17] mm/damon/sysfs: pass preps to DAMON core
Quoted 38 lines · On Tue, 01 Sep 2026 04:53:14 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Data race onsys_prep->actiondue to lockless read and write
--commit
09b46cd761363fb28603bd1d27adb637a6c16a7d
Author: SJ Park <[email protected]>
mm/damon/sysfs: pass preps to DAMON coreDAMON sysfs interface provides the files for setting DAMON probe preps. But the underlying code is not really passing the user-set values to DAMON core. Pass those.
Quoted 8 lines
mm/damon/sysfs.c +0
-0@@ -2176,6 +2176,23 @@ static int damon_sysfs_set_attrs(struct damon_ctx *ctx,return damon_set_attrs (ctx, &attrs); }mm/damon/sysfs.c static int damon_sysfs_set_attrs(struct damon_ctx *ctx, · line 2188
Quoted 10 lines
mm/damon/sysfs.c +10
-0+static int damon_sysfs_set_preps (struct damon_probe *probe, +struct damon_sysfs_preps *sys_preps) +{ +int i; + +for (i =0 ; i < sys_preps->nr; i++) { +struct damon_sysfs_prep *sys_prep = sys_preps->preps_arr[i]; +struct damon_prep *prep; + + prep =damon_new_prep (sys_prep->action);[Severity: Low]
Could this result in a data race onsys_prep->action?During DAMON context building, this locklessly reads the action enum while a concurrent root user could be writing to the
/sys/.../prep_actionattribute.
Quoted 7 lines
A concurrent write to
prep_actioncould happen while another process issues a commit command to the state file, which runsdamon_sysfs_commit_inputasynchronously on the kdamond thread without holdingdamon_sysfs_lock.Would it be better to use
READ_ONCE()here, along with a correspondingWRITE_ONCE()on the writer side, to adhere to the Linux Kernel Memory Model guidelines and avoid potential KCSAN warnings?
Good catch. A few similar call paths protect stores with damon_sysfs_lock. I will protect prep->action writing with the lock. Because the context build is done while holding the lock, it should avoid the race, like below.
'''
mm/damon/sysfs.c +3 -0
@@ -827,7 +827,10 @@ static ssize_t prep_action_store(struct kobject *kobj, action_name = &damon_sysfs_prep_action_names[i];if (sysfs_streq (buf, action_name->name)) { +if (!mutex_trylock (&damon_sysfs_lock)) +return -EBUSY ; prep->action = action_name->action; +mutex_unlock (&damon_sysfs_lock); ret = count;break ; }
'''
Quoted 13 lines
Quoted 8 lines
mm/damon/sysfs.c +7
-0+if (!prep) +return -ENOMEM ; +damon_add_prep (probe, prep); + } +return 0 ; +} +[ ... ]
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=13
Thanks,
SJ
SJ Park
maintainerPATCH 14/17 selftests/damon/sysfs.sh: test probe prep sysfs files
In reply to SJ ParkAdd basic file operations test for newly introduced DAMON probe prep sysfs directories and files.
--- tools/testing/selftests/damon/sysfs.sh | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
tools/testing/selftests/damon/sysfs.sh +27 -0
@@ -361,6 +361,32 @@ test_intervals() test_intervals_goal "$intervals_dir/intervals_goal" } +test_damon_prep() +{ + damon_prep_dir=$1 + ensure_file "$damon_prep_dir/prep_action" "exist" "600" + ensure_write_succ "$damon_prep_dir/prep_action" "set_pgidle" \ + "valid input" + ensure_write_fail "$damon_prep_dir/prep_action" "foo" "invalid input" +} + +test_damon_preps() +{ + preps_dir=$1 + ensure_dir "$preps_dir" "exist" + ensure_file "$preps_dir/nr_preps" "exist" "600" + ensure_write_succ "$preps_dir/nr_preps" "1" "valid input" + test_damon_prep "$preps_dir/0" + + ensure_write_succ "$preps_dir/nr_preps" "2" "valid input" + test_damon_prep "$preps_dir/0" + test_damon_prep "$preps_dir/1" + + ensure_write_succ "$preps_dir/nr_preps" "0" "valid input" + ensure_dir "$preps_dir/0" "not_exist" + ensure_dir "$preps_dir/1" "not_exist" +} + test_damon_filter() { damon_filter_dir=$1
@@ -392,6 +418,7 @@ test_probe() { probe_dir=$1 ensure_dir "$probe_dir" "exist" + test_damon_preps "$probe_dir/preps" test_damon_filters "$probe_dir/filters" }
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 14/17] selftests/damon/sysfs.sh: test probe prep sysfs files
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Add basic file operations test for newly introduced DAMON probe prep sysfs directories and files.
Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=14
SJ Park
maintainerPATCH 15/17 Docs/mm/damon/design: document probe preps
In reply to SJ ParkUpdate DAMON design document for the newly added DAMON probe preps feature.
--- Documentation/mm/damon/design.rst | 7 +++++++ 1 file changed, 7 insertions(+)
Documentation/mm/damon/design.rst +7 -0
@@ -309,6 +309,13 @@ Users can therefore know how much of a given DAMON region has a specific data attribute by reading the per-region per-probe probe hits counter after each aggregation interval. +Users can optionally register probing preparation actions per probe. If such +actions are registered, DAMON applies the actions to each region's sampling +memory before starting the next sampling interval. Currently only one action, +``set_pgidle`` is supported. The action marks the page for the probing target +memory as access-idle. This can be useful to be used together with +``pgidle_unset`` probe filter. + This is a sampling based mechanism. Hence, it is lightweight but the output may include some measurement errors. The output should be used with good understanding of statistics.
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 15/17] Docs/mm/damon/design: document probe preps
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Update DAMON design document for the newly added DAMON probe preps feature.
Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=15
SJ Park
maintainerPATCH 16/17 Docs/admin-guide/mm/damon/usage: document probe preps sysfs files
In reply to SJ ParkUpdate DAMON usage document for the newly added DAMON probe preps sysfs files.
--- Documentation/admin-guide/mm/damon/usage.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
Documentation/admin-guide/mm/damon/usage.rst +15 -3
@@ -74,6 +74,9 @@ comma (","). │ │ │ │ │ │ nr_regions/min,max │ │ │ │ │ │ :ref:`probes <damon_usage_sysfs_probes>`/nr_probes │ │ │ │ │ │ │ 0/weight + │ │ │ │ │ │ │ │ preps/nr_preps + │ │ │ │ │ │ │ │ │ 0/prep_action + │ │ │ │ │ │ │ │ │ ... │ │ │ │ │ │ │ │ filters/nr_filters │ │ │ │ │ │ │ │ │ 0/type,matching,allow,path │ │ │ │ │ │ │ │ │ ...
@@ -283,9 +286,18 @@ In the beginning, this directory has only one file, ``nr_probes``. Writing a number (``N``) to the file creates the number of child directories named ``0`` to ``N-1``. Each directory represents each monitoring probe. -In each probe directory, one directory, ``filters`` exists. The directory -contains files for installing filters for the probe, that is used to determine -the data attribute for the probe. +In each probe directory, two directories, ``preps`` and ``filters`` exist. The +directories contain files for installing probing preparation actions and +filters for the probe, that are used to determine the data attribute for the +probe. + +In the beginning, ``preps`` directory has only one file, ``nr_preps``. +Writing a number (``N``) to the file creates the number of child directories +named ``0`` to ``N-1``. Each directory represents each preparation action. +Each directory has one file, ``prep_action``. The preparation action can be +selected by writing the name of the action to the ``prep_action`` file. Refer +to the :ref:`design doc <damon_design_data_attrs_monitoring>` for the list of +supported actions. Each probe directory also contains ``weight`` file. Reading from and writing to the file gets and sets the :ref:`attributes-only monitoring
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 16/17] Docs/admin-guide/mm/damon/usage: document probe preps sysfs files
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Update DAMON usage document for the newly added DAMON probe preps sysfs files.
Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=16
SJ Park
maintainerPATCH 17/17 Docs/ABI/damon: document probe prep sysfs files
In reply to SJ ParkUpdate DAMON ABI document for the newly added DAMON probe prep sysfs files.
--- Documentation/ABI/testing/sysfs-kernel-mm-damon | 13 +++++++++++++ 1 file changed, 13 insertions(+)
Documentation/ABI/testing/sysfs-kernel-mm-damon +13 -0
@@ -173,6 +173,19 @@ Contact: SJ Park <[email protected]> Description: Writing to and reading from this file sets and gets the per-probe attribute weight. +What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/preps/nr_preps +Date: Jun 2026 +Contact: SJ Park <[email protected]> +Description: Writing a number 'N' to this file creates the number of + directories for each DAMON probing preparation action named '0' + to 'N-1' under the preps/ directory. + +What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/preps/<R>/prep_action +Date: Jun 2026 +Contact: SJ Park <[email protected]> +Description: Writing to and reading from this file sets and gets the probing + preparation action. + What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/filters/nr_filters Date: May 2026 Contact: SJ Park <[email protected]>
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 17/17] Docs/ABI/damon: document probe prep sysfs files
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Update DAMON ABI document for the newly added DAMON probe prep sysfs files.
Signed-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=17
SJ Park
maintainerQuoted 2 lines · On Mon, 31 Aug 2026 21:33:56 -0700 SJ Park <[email protected]> wrote:
TL;DR: extend DAMON's data attributes monitoring system to support page table accessed bit and
PG_idlebased access monitoring.
Sashiko found [1] a possible race that is introduced by this series. I will fix it in the next revision.
[1] https://lore.kernel.org/[email protected]
Thanks,
SJ
[...]