* [RFC PATCH 01/27] mm/damon/api: introduce struct damon_report
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:34 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 02/27] mm/damon/core: implement data attribute report queue SJ Park
` (26 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, damon, linux-kernel, linux-mm
Define a struct for data attribute report. The struct provides public
fields for the type and the memory address range. The type field
represents the type of the report itself. The address range is for the
memory of the reporting data. Data attribute producers can format their
report using those fields.
It also has a private field representing when the report is submitted.
Signed-off-by: SJ Park <sj@kernel.org>
---
include/linux/damon.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 06bd92981af21..5c32ddebf4625 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -751,6 +751,29 @@ struct damon_intervals_goal {
unsigned long max_sample_us;
};
+/**
+ * enum damon_report_type - Type of &struct damon_report.
+ */
+enum damon_report_type {
+ NR_DAMON_REPORT_TYPES,
+};
+
+/**
+ * struct damon_report - Data attribute report information.
+ *
+ * @type: Type of the report.
+ * @addr_range: The address range of the memory to report for.
+ *
+ * Note that the @start_addr and @end_adr represents an end-open range.
+ */
+struct damon_report {
+ enum damon_report_type type;
+ struct damon_addr_range addr_range;
+/* private: */
+ /* when this report is generated */
+ unsigned long jiffies;
+};
+
/**
* enum damon_prep_action - DAMON probing preparation action.
*
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 01/27] mm/damon/api: introduce struct damon_report
2026-11-15 20:28 ` [RFC PATCH 01/27] mm/damon/api: introduce struct damon_report SJ Park
@ 2026-11-15 20:34 ` sashiko-bot
2026-11-15 21:09 ` SJ Park
0 siblings, 1 reply; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:34 UTC (permalink / raw)
To: SJ Park; +Cc: damon, linux-mm
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Low] mm/damon: nonexistent fields in struct damon_report kernel-doc
comment
--
commit 919e8293a0141a206eb1e31c857deac8b6249a6d
Author: SJ Park <sj@kernel.org>
mm/damon/api: introduce struct damon_report
This commit defines enum damon_report_type and struct damon_report to
represent data attribute reports.
> diff --git a/include/linux/damon.h b/include/linux/damon.h
> index 06bd92981af21..5c32ddebf4625 100644
> --- a/include/linux/damon.h
> +++ b/include/linux/damon.h
> @@ -751,6 +751,29 @@ struct damon_intervals_goal {
> unsigned long max_sample_us;
> };
>
> +/**
> + * enum damon_report_type - Type of &struct damon_report.
> + */
> +enum damon_report_type {
> + NR_DAMON_REPORT_TYPES,
> +};
> +
> +/**
> + * struct damon_report - Data attribute report information.
> + *
> + * @type: Type of the report.
> + * @addr_range: The address range of the memory to report for.
> + *
> + * Note that the @start_addr and @end_adr represents an end-open range.
> + */
> +struct damon_report {
> + enum damon_report_type type;
> + struct damon_addr_range addr_range;
[Severity: Low]
The kernel-doc comment refers to @start_addr and @end_adr (with a typo in
"end_adr"), but struct damon_report embeds @addr_range (a struct
damon_addr_range with @start and @end fields) rather than defining those
fields directly.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=1
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [RFC PATCH 01/27] mm/damon/api: introduce struct damon_report
2026-11-15 20:34 ` sashiko-bot
@ 2026-11-15 21:09 ` SJ Park
0 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 21:09 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, damon, linux-mm
On Sun, 15 Nov 2026 20:34:31 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue to consider:
> - [Low] mm/damon: nonexistent fields in struct damon_report kernel-doc
> comment
> --
>
> commit 919e8293a0141a206eb1e31c857deac8b6249a6d
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/api: introduce struct damon_report
>
> This commit defines enum damon_report_type and struct damon_report to
> represent data attribute reports.
>
> > diff --git a/include/linux/damon.h b/include/linux/damon.h
> > index 06bd92981af21..5c32ddebf4625 100644
> > --- a/include/linux/damon.h
> > +++ b/include/linux/damon.h
> > @@ -751,6 +751,29 @@ struct damon_intervals_goal {
> > unsigned long max_sample_us;
> > };
> >
> > +/**
> > + * enum damon_report_type - Type of &struct damon_report.
> > + */
> > +enum damon_report_type {
> > + NR_DAMON_REPORT_TYPES,
> > +};
> > +
> > +/**
> > + * struct damon_report - Data attribute report information.
> > + *
> > + * @type: Type of the report.
> > + * @addr_range: The address range of the memory to report for.
> > + *
> > + * Note that the @start_addr and @end_adr represents an end-open range.
> > + */
> > +struct damon_report {
> > + enum damon_report_type type;
> > + struct damon_addr_range addr_range;
>
> [Severity: Low]
> The kernel-doc comment refers to @start_addr and @end_adr (with a typo in
> "end_adr"), but struct damon_report embeds @addr_range (a struct
> damon_addr_range with @start and @end fields) rather than defining those
> fields directly.
Good finding, thank you. I will drop the last line of the comment.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=1
>
Thanks,
SJ
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 02/27] mm/damon/core: implement data attribute report queue
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
2026-11-15 20:28 ` [RFC PATCH 01/27] mm/damon/api: introduce struct damon_report SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:41 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 03/27] mm/damon/core: introduce damon_submit_report() SJ Park
` (25 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement DAMON core internal data structure for queuing received
data attribute reports. Initialize the queue for up to 1,000 reports,
inside the DAMON init routine. Also update damon_initialized() to
return false for the setup failure of the queue.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 0a056949604f9..3f87a7eec442e 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2334,6 +2334,25 @@ int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control)
return 0;
}
+/*
+ * struct damon_report_queue - &struct damon_report queue.
+ *
+ * @lock: Represent if this queue is being used by someone.
+ * @head: Head of the queue.
+ * @tail: Tail of the queue.
+ * @size: Size of the queue.
+ * @reports: Array of &struct damon_report.
+ */
+struct damon_report_queue {
+ atomic_t lock;
+ unsigned int tail;
+ unsigned int size;
+ unsigned int nr_reports;
+ struct damon_report *reports;
+};
+
+struct damon_report_queue damon_report_queue;
+
/*
* Reset the aggregated monitoring results ('nr_accesses' of each region).
*/
@@ -4308,7 +4327,7 @@ void damon_update_region_access_rate(struct damon_region *r, bool accessed)
*/
bool damon_initialized(void)
{
- return damon_region_cache != NULL;
+ return damon_region_cache && damon_report_queue.reports;
}
static int __init damon_init(void)
@@ -4319,6 +4338,14 @@ static int __init damon_init(void)
return -ENOMEM;
}
+ damon_report_queue.size = 1000;
+ damon_report_queue.reports = kmalloc_objs(*damon_report_queue.reports,
+ 1000, GFP_KERNEL);
+ if (!damon_report_queue.reports) {
+ pr_err("report queue alloc fail\n");
+ return -ENOMEM;
+ }
+
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 02/27] mm/damon/core: implement data attribute report queue
2026-11-15 20:28 ` [RFC PATCH 02/27] mm/damon/core: implement data attribute report queue SJ Park
@ 2026-11-15 20:41 ` sashiko-bot
2026-11-15 21:17 ` SJ Park
0 siblings, 1 reply; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:41 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] mm/damon: damon_init() leaks damon_region_cache on queue
alloc failure
- [Low] mm/damon: missing static qualifier on damon_report_queue in
core.c
- [Low] mm/damon: struct damon_report_queue comment documents head not
nr_reports
--
commit 10a61bc9bab6e48534e4a8552380aecaccbee97a
Author: SJ Park <sj@kernel.org>
mm/damon/core: implement data attribute report queue
This commit adds an internal damon_report_queue structure, allocates its
buffer for up to 1,000 reports in damon_init(), and checks that buffer in
damon_initialized().
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 0a056949604f9..3f87a7eec442e 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2334,6 +2334,25 @@ int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control)
> return 0;
> }
>
> +/*
> + * struct damon_report_queue - &struct damon_report queue.
> + *
> + * @lock: Represent if this queue is being used by someone.
> + * @head: Head of the queue.
> + * @tail: Tail of the queue.
> + * @size: Size of the queue.
> + * @reports: Array of &struct damon_report.
> + */
> +struct damon_report_queue {
> + atomic_t lock;
> + unsigned int tail;
> + unsigned int size;
> + unsigned int nr_reports;
> + struct damon_report *reports;
> +};
[Severity: Low]
The comment above struct damon_report_queue documents @head, whereas the
struct defines nr_reports instead.
> +
> +struct damon_report_queue damon_report_queue;
[Severity: Low]
Should damon_report_queue be marked static? struct damon_report_queue is
private to mm/damon/core.c, so leaving damon_report_queue non-static
exports it into the global namespace and triggers sparse and W=1 missing
variable declaration warnings.
> +
> /*
> * Reset the aggregated monitoring results ('nr_accesses' of each region).
> */
> @@ -4308,7 +4327,7 @@ void damon_update_region_access_rate(struct damon_region *r, bool accessed)
> */
> bool damon_initialized(void)
> {
> - return damon_region_cache != NULL;
> + return damon_region_cache && damon_report_queue.reports;
> }
>
> static int __init damon_init(void)
> @@ -4319,6 +4338,14 @@ static int __init damon_init(void)
> return -ENOMEM;
> }
>
> + damon_report_queue.size = 1000;
> + damon_report_queue.reports = kmalloc_objs(*damon_report_queue.reports,
> + 1000, GFP_KERNEL);
> + if (!damon_report_queue.reports) {
> + pr_err("report queue alloc fail\n");
> + return -ENOMEM;
> + }
[Severity: Medium]
Does this error path leak damon_region_cache when kmalloc_objs() fails?
Destroying damon_region_cache and resetting it (along with
damon_report_queue.size) before returning -ENOMEM would avoid leaking the
slab cache and leaving partially initialized state.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=2
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [RFC PATCH 02/27] mm/damon/core: implement data attribute report queue
2026-11-15 20:41 ` sashiko-bot
@ 2026-11-15 21:17 ` SJ Park
0 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 21:17 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, Andrew Morton, damon, linux-mm
On Sun, 15 Nov 2026 20:41:23 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential
> issues to consider:
> - [Medium] mm/damon: damon_init() leaks damon_region_cache on queue
> alloc failure
> - [Low] mm/damon: missing static qualifier on damon_report_queue in
> core.c
> - [Low] mm/damon: struct damon_report_queue comment documents head not
> nr_reports
> --
>
> commit 10a61bc9bab6e48534e4a8552380aecaccbee97a
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/core: implement data attribute report queue
>
> This commit adds an internal damon_report_queue structure, allocates its
> buffer for up to 1,000 reports in damon_init(), and checks that buffer in
> damon_initialized().
>
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index 0a056949604f9..3f87a7eec442e 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -2334,6 +2334,25 @@ int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control)
> > return 0;
> > }
> >
> > +/*
> > + * struct damon_report_queue - &struct damon_report queue.
> > + *
> > + * @lock: Represent if this queue is being used by someone.
> > + * @head: Head of the queue.
> > + * @tail: Tail of the queue.
> > + * @size: Size of the queue.
> > + * @reports: Array of &struct damon_report.
> > + */
> > +struct damon_report_queue {
> > + atomic_t lock;
> > + unsigned int tail;
> > + unsigned int size;
> > + unsigned int nr_reports;
> > + struct damon_report *reports;
> > +};
>
> [Severity: Low]
> The comment above struct damon_report_queue documents @head, whereas the
> struct defines nr_reports instead.
Nice catch. I will remove the comment for @head and add a comment for
@nr_reports.
>
> > +
> > +struct damon_report_queue damon_report_queue;
>
> [Severity: Low]
> Should damon_report_queue be marked static? struct damon_report_queue is
> private to mm/damon/core.c, so leaving damon_report_queue non-static
> exports it into the global namespace and triggers sparse and W=1 missing
> variable declaration warnings.
Good suggestion, I will mark it as static.
>
> > +
> > /*
> > * Reset the aggregated monitoring results ('nr_accesses' of each region).
> > */
> > @@ -4308,7 +4327,7 @@ void damon_update_region_access_rate(struct damon_region *r, bool accessed)
> > */
> > bool damon_initialized(void)
> > {
> > - return damon_region_cache != NULL;
> > + return damon_region_cache && damon_report_queue.reports;
> > }
> >
> > static int __init damon_init(void)
> > @@ -4319,6 +4338,14 @@ static int __init damon_init(void)
> > return -ENOMEM;
> > }
> >
> > + damon_report_queue.size = 1000;
> > + damon_report_queue.reports = kmalloc_objs(*damon_report_queue.reports,
> > + 1000, GFP_KERNEL);
> > + if (!damon_report_queue.reports) {
> > + pr_err("report queue alloc fail\n");
> > + return -ENOMEM;
> > + }
>
> [Severity: Medium]
> Does this error path leak damon_region_cache when kmalloc_objs() fails?
> Destroying damon_region_cache and resetting it (along with
> damon_report_queue.size) before returning -ENOMEM would avoid leaking the
> slab cache and leaving partially initialized state.
Good suggestion. I will do destroy damon_region_cache.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=2
>
Thanks,
SJ
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 03/27] mm/damon/core: introduce damon_submit_report()
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
2026-11-15 20:28 ` [RFC PATCH 01/27] mm/damon/api: introduce struct damon_report SJ Park
2026-11-15 20:28 ` [RFC PATCH 02/27] mm/damon/core: implement data attribute report queue SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:42 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 04/27] mm/damon/sysfs: add admin/reports/ directory SJ Park
` (24 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement and expose a new DAMON API function for submitting a data
attribute report. Any kernel component in any context including NMI
context can use it to report their finding of data attribute information
for a given memory.
The function copies the content of the report into the DAMON-internal
report queue. The copy is done in a ring buffer-like manner, without
being blocked for consumption. As a result, the queue keeps the latest
reports up to its capacity.
Use simple CAS-based try-locking. If any parallel submission is
detected, simply forgive the submission.
Signed-off-by: SJ Park <sj@kernel.org>
---
include/linux/damon.h | 2 ++
mm/damon/core.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 5c32ddebf4625..ca0135c6f6700 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -1189,6 +1189,8 @@ int damon_kdamond_pid(struct damon_ctx *ctx);
int damon_call(struct damon_ctx *ctx, struct damon_call_control *control);
int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control);
+int damon_submit_report(struct damon_report *report);
+
int damon_set_region_system_rams_default(struct damon_target *t,
unsigned long *start, unsigned long *end,
unsigned long addr_unit,
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 3f87a7eec442e..06b85d00e38d9 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2353,6 +2353,36 @@ struct damon_report_queue {
struct damon_report_queue damon_report_queue;
+/**
+ * damon_submit_report() - Enqueue a given report to DAMON internal buffer.
+ * @report: The report to enqueue.
+ *
+ * This function can be called from any context including the NMI context.
+ */
+int damon_submit_report(struct damon_report *report)
+{
+ struct damon_report_queue *queue;
+ int lock_old_val;
+ unsigned int tail;
+
+ queue = &damon_report_queue;
+ report->jiffies = jiffies;
+ lock_old_val = atomic_cmpxchg(&queue->lock, 0, 1);
+ if (lock_old_val)
+ return -EBUSY;
+
+ tail = queue->tail;
+ if (tail == queue->size)
+ tail = 0;
+ queue->reports[tail] = *report;
+ queue->tail++;
+ if (queue->nr_reports < queue->size)
+ queue->nr_reports++;
+ /* cmpxchg is known to be faster than xchg */
+ atomic_cmpxchg(&queue->lock, 1, 0);
+ return 0;
+}
+
/*
* Reset the aggregated monitoring results ('nr_accesses' of each region).
*/
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 03/27] mm/damon/core: introduce damon_submit_report()
2026-11-15 20:28 ` [RFC PATCH 03/27] mm/damon/core: introduce damon_submit_report() SJ Park
@ 2026-11-15 20:42 ` sashiko-bot
2026-11-15 21:23 ` SJ Park
0 siblings, 1 reply; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:42 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] mm/damon/core: out-of-bounds write in damon_submit_report() on
queue wrap
- [Low] mm/damon/core: missing Return section in damon_submit_report()
kernel-doc
--
commit bcb278386fb51304d0c224892db9744bf9e27c8f
Author: SJ Park <sj@kernel.org>
mm/damon/core: introduce damon_submit_report()
This commit adds damon_submit_report() to enqueue a data attribute report
into the DAMON internal report queue using CAS-based try-locking.
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 3f87a7eec442e..06b85d00e38d9 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2353,6 +2353,36 @@ struct damon_report_queue {
>
> struct damon_report_queue damon_report_queue;
>
> +/**
> + * damon_submit_report() - Enqueue a given report to DAMON internal buffer.
> + * @report: The report to enqueue.
> + *
> + * This function can be called from any context including the NMI context.
> + */
> +int damon_submit_report(struct damon_report *report)
[Severity: Low]
This isn't a bug, but the kernel-doc comment for damon_submit_report() is
missing a Return: section describing the 0 and -EBUSY return values, which
triggers a kernel-doc warning under W=2 builds.
> +{
> + struct damon_report_queue *queue;
> + int lock_old_val;
> + unsigned int tail;
> +
> + queue = &damon_report_queue;
> + report->jiffies = jiffies;
> + lock_old_val = atomic_cmpxchg(&queue->lock, 0, 1);
> + if (lock_old_val)
> + return -EBUSY;
> +
> + tail = queue->tail;
> + if (tail == queue->size)
> + tail = 0;
> + queue->reports[tail] = *report;
> + queue->tail++;
[Severity: High]
Does this write out of bounds of queue->reports[] after the queue wraps?
When queue->tail reaches queue->size, only the local variable tail is
reset to 0 while queue->tail++ increments queue->tail to queue->size + 1.
Every subsequent submission then bypasses the tail == queue->size check
and writes past the end of the queue->reports heap array, corrupting
adjacent slab memory. Updating queue->tail = tail + 1 would wrap the
index properly.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=3
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [RFC PATCH 03/27] mm/damon/core: introduce damon_submit_report()
2026-11-15 20:42 ` sashiko-bot
@ 2026-11-15 21:23 ` SJ Park
0 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 21:23 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, Andrew Morton, damon, linux-mm
On Sun, 15 Nov 2026 20:42:40 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential
> issues to consider:
> - [High] mm/damon/core: out-of-bounds write in damon_submit_report() on
> queue wrap
> - [Low] mm/damon/core: missing Return section in damon_submit_report()
> kernel-doc
> --
>
> commit bcb278386fb51304d0c224892db9744bf9e27c8f
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/core: introduce damon_submit_report()
>
> This commit adds damon_submit_report() to enqueue a data attribute report
> into the DAMON internal report queue using CAS-based try-locking.
>
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index 3f87a7eec442e..06b85d00e38d9 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -2353,6 +2353,36 @@ struct damon_report_queue {
> >
> > struct damon_report_queue damon_report_queue;
> >
> > +/**
> > + * damon_submit_report() - Enqueue a given report to DAMON internal buffer.
> > + * @report: The report to enqueue.
> > + *
> > + * This function can be called from any context including the NMI context.
> > + */
> > +int damon_submit_report(struct damon_report *report)
>
> [Severity: Low]
> This isn't a bug, but the kernel-doc comment for damon_submit_report() is
> missing a Return: section describing the 0 and -EBUSY return values, which
> triggers a kernel-doc warning under W=2 builds.
Nice catch, I will add Return: comment.
>
> > +{
> > + struct damon_report_queue *queue;
> > + int lock_old_val;
> > + unsigned int tail;
> > +
> > + queue = &damon_report_queue;
> > + report->jiffies = jiffies;
> > + lock_old_val = atomic_cmpxchg(&queue->lock, 0, 1);
> > + if (lock_old_val)
> > + return -EBUSY;
> > +
> > + tail = queue->tail;
> > + if (tail == queue->size)
> > + tail = 0;
> > + queue->reports[tail] = *report;
> > + queue->tail++;
>
> [Severity: High]
> Does this write out of bounds of queue->reports[] after the queue wraps?
>
> When queue->tail reaches queue->size, only the local variable tail is
> reset to 0 while queue->tail++ increments queue->tail to queue->size + 1.
> Every subsequent submission then bypasses the tail == queue->size check
> and writes past the end of the queue->reports heap array, corrupting
> adjacent slab memory. Updating queue->tail = tail + 1 would wrap the
> index properly.
Good catch. I will remove tail local variable and just use queue->tail.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=3
>
Thanks,
SJ
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 04/27] mm/damon/sysfs: add admin/reports/ directory
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (2 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 03/27] mm/damon/core: introduce damon_submit_report() SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 05/27] mm/damon/sysfs: add reports/producers/ directory SJ Park
` (23 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Add a new sysfs directory, reports/, as a place holder for sysfs files
that will be used for controlling the data attribute report system. Put
the directory under the admin/ directory, next to kdamonds/ directory.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 63 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 59 insertions(+), 4 deletions(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 779c98205a94b..76850a4b5b5a7 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -2979,6 +2979,38 @@ static const struct kobj_type damon_sysfs_kdamonds_ktype = {
.default_groups = damon_sysfs_kdamonds_groups,
};
+/* reports dir */
+
+struct damon_sysfs_reports {
+ struct kobject kobj;
+};
+
+static struct damon_sysfs_reports *damon_sysfs_reports_alloc(void)
+{
+ return kzalloc_obj(struct damon_sysfs_reports);
+}
+
+static int damon_sysfs_reports_add_dirs(struct damon_sysfs_reports *reports)
+{
+ return 0;
+}
+
+static void damon_sysfs_reports_release(struct kobject *kobj)
+{
+ kfree(container_of(kobj, struct damon_sysfs_reports, kobj));
+}
+
+static struct attribute *damon_sysfs_reports_attrs[] = {
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_reports);
+
+static const struct kobj_type damon_sysfs_reports_ktype = {
+ .release = damon_sysfs_reports_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_reports_groups,
+};
+
/*
* damon user interface directory
*/
@@ -2986,6 +3018,7 @@ static const struct kobj_type damon_sysfs_kdamonds_ktype = {
struct damon_sysfs_ui_dir {
struct kobject kobj;
struct damon_sysfs_kdamonds *kdamonds;
+ struct damon_sysfs_reports *reports;
};
static struct damon_sysfs_ui_dir *damon_sysfs_ui_dir_alloc(void)
@@ -2996,6 +3029,7 @@ static struct damon_sysfs_ui_dir *damon_sysfs_ui_dir_alloc(void)
static int damon_sysfs_ui_dir_add_dirs(struct damon_sysfs_ui_dir *ui_dir)
{
struct damon_sysfs_kdamonds *kdamonds;
+ struct damon_sysfs_reports *reports;
int err;
kdamonds = damon_sysfs_kdamonds_alloc();
@@ -3005,11 +3039,32 @@ static int damon_sysfs_ui_dir_add_dirs(struct damon_sysfs_ui_dir *ui_dir)
err = kobject_init_and_add(&kdamonds->kobj,
&damon_sysfs_kdamonds_ktype, &ui_dir->kobj,
"kdamonds");
- if (err) {
- kobject_put(&kdamonds->kobj);
- return err;
- }
+ if (err)
+ goto put_kdamonds_out;
ui_dir->kdamonds = kdamonds;
+
+ reports = damon_sysfs_reports_alloc();
+ if (!reports) {
+ err = -ENOMEM;
+ goto put_kdamonds_out;
+ }
+ ui_dir->reports = reports;
+
+ err = kobject_init_and_add(&reports->kobj, &damon_sysfs_reports_ktype,
+ &ui_dir->kobj, "reports");
+ if (err)
+ goto put_reports_out;
+ err = damon_sysfs_reports_add_dirs(reports);
+ if (err)
+ goto put_reports_out;
+ return err;
+
+put_reports_out:
+ kobject_put(&reports->kobj);
+ ui_dir->reports = NULL;
+put_kdamonds_out:
+ kobject_put(&kdamonds->kobj);
+ ui_dir->kdamonds = NULL;
return err;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 05/27] mm/damon/sysfs: add reports/producers/ directory
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (3 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 04/27] mm/damon/sysfs: add admin/reports/ directory SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 06/27] mm/damon/sysfs: add producers/nr_producers file SJ Park
` (22 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Add a new sysfs directory, producers/, under reports/ directory. It is
a placeholder for files that will be used for controlling DAMON report
producers.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 76850a4b5b5a7..75701ed662222 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -2979,10 +2979,38 @@ static const struct kobj_type damon_sysfs_kdamonds_ktype = {
.default_groups = damon_sysfs_kdamonds_groups,
};
+/* producers dir */
+
+struct damon_sysfs_producers {
+ struct kobject kobj;
+};
+
+static struct damon_sysfs_producers *damon_sysfs_producers_alloc(void)
+{
+ return kzalloc_obj(struct damon_sysfs_producers);
+}
+
+static void damon_sysfs_producers_release(struct kobject *kobj)
+{
+ kfree(container_of(kobj, struct damon_sysfs_producers, kobj));
+}
+
+static struct attribute *damon_sysfs_producers_attrs[] = {
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_producers);
+
+static const struct kobj_type damon_sysfs_producers_ktype = {
+ .release = damon_sysfs_producers_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_producers_groups,
+};
+
/* reports dir */
struct damon_sysfs_reports {
struct kobject kobj;
+ struct damon_sysfs_producers *producers;
};
static struct damon_sysfs_reports *damon_sysfs_reports_alloc(void)
@@ -2992,7 +3020,25 @@ static struct damon_sysfs_reports *damon_sysfs_reports_alloc(void)
static int damon_sysfs_reports_add_dirs(struct damon_sysfs_reports *reports)
{
- return 0;
+ struct damon_sysfs_producers *producers;
+ int err;
+
+ producers = damon_sysfs_producers_alloc();
+ if (!producers)
+ return -ENOMEM;
+ reports->producers = producers;
+
+ err = kobject_init_and_add(&producers->kobj,
+ &damon_sysfs_producers_ktype, &reports->kobj,
+ "producers");
+ if (err)
+ goto put_producers_out;
+ return err;
+
+put_producers_out:
+ kobject_put(&producers->kobj);
+ reports->producers = NULL;
+ return err;
}
static void damon_sysfs_reports_release(struct kobject *kobj)
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 06/27] mm/damon/sysfs: add producers/nr_producers file
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (4 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 05/27] mm/damon/sysfs: add reports/producers/ directory SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 07/27] mm/damon/sysfs: implement report producer directory SJ Park
` (21 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement a new sysfs file, nr_producers, under the producers/
directory. The file will be used for generating directories for each
report producer, in a manner that is similar to the nr_kdamonds file.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 75701ed662222..d3a7cb170975a 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -2983,6 +2983,7 @@ static const struct kobj_type damon_sysfs_kdamonds_ktype = {
struct damon_sysfs_producers {
struct kobject kobj;
+ int nr;
};
static struct damon_sysfs_producers *damon_sysfs_producers_alloc(void)
@@ -2990,12 +2991,62 @@ static struct damon_sysfs_producers *damon_sysfs_producers_alloc(void)
return kzalloc_obj(struct damon_sysfs_producers);
}
+static void damon_sysfs_producers_rm_dirs(
+ struct damon_sysfs_producers *producers)
+{
+ producers->nr = 0;
+}
+
+static int damon_sysfs_producers_add_dirs(
+ struct damon_sysfs_producers *producers, int nr_producers)
+{
+ damon_sysfs_producers_rm_dirs(producers);
+ producers->nr = nr_producers;
+ return 0;
+}
+
+static ssize_t nr_producers_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_producers *producers = container_of(kobj,
+ struct damon_sysfs_producers, kobj);
+
+ return sysfs_emit(buf, "%d\n", producers->nr);
+}
+
+static ssize_t nr_producers_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_producers *producers;
+ int nr, err = kstrtoint(buf, 0, &nr);
+
+ if (err)
+ return err;
+ if (nr < 0)
+ return -EINVAL;
+
+ producers = container_of(kobj, struct damon_sysfs_producers, kobj);
+
+ if (!mutex_trylock(&damon_sysfs_lock))
+ return -EBUSY;
+ err = damon_sysfs_producers_add_dirs(producers, nr);
+ mutex_unlock(&damon_sysfs_lock);
+ if (err)
+ return err;
+
+ return count;
+}
+
static void damon_sysfs_producers_release(struct kobject *kobj)
{
kfree(container_of(kobj, struct damon_sysfs_producers, kobj));
}
+static struct kobj_attribute damon_sysfs_producers_nr_attr =
+__ATTR_RW_MODE(nr_producers, 0600);
+
static struct attribute *damon_sysfs_producers_attrs[] = {
+ &damon_sysfs_producers_nr_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_producers);
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 07/27] mm/damon/sysfs: implement report producer directory
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (5 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 06/27] mm/damon/sysfs: add producers/nr_producers file SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 08/27] mm/damon/sysfs: implement report producer type and state files SJ Park
` (20 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement a sysfs directory for each report producer. Create and remove
the directories for reports/producers/nr_producers file writes. It is a
placeholder for sysfs files that will be used for controlling each
report producer.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index d3a7cb170975a..7c6bc30c12125 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -2979,10 +2979,40 @@ static const struct kobj_type damon_sysfs_kdamonds_ktype = {
.default_groups = damon_sysfs_kdamonds_groups,
};
+/* producer dir */
+
+struct damon_sysfs_producer {
+ struct kobject kobj;
+};
+
+static struct damon_sysfs_producer *damon_sysfs_producer_alloc(void)
+{
+ return kzalloc_obj(struct damon_sysfs_producer);
+}
+
+static void damon_sysfs_producer_release(struct kobject *kobj)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+ kfree(producer);
+}
+
+static struct attribute *damon_sysfs_producer_attrs[] = {
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_producer);
+
+static const struct kobj_type damon_sysfs_producer_ktype = {
+ .release = damon_sysfs_producer_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_producer_groups,
+};
+
/* producers dir */
struct damon_sysfs_producers {
struct kobject kobj;
+ struct damon_sysfs_producer **producers_arr;
int nr;
};
@@ -2994,14 +3024,53 @@ static struct damon_sysfs_producers *damon_sysfs_producers_alloc(void)
static void damon_sysfs_producers_rm_dirs(
struct damon_sysfs_producers *producers)
{
+ struct damon_sysfs_producer **producers_arr = producers->producers_arr;
+ int i;
+
+ for (i = 0; i < producers->nr; i++) {
+ kobject_del(&producers_arr[i]->kobj);
+ kobject_put(&producers_arr[i]->kobj);
+ }
producers->nr = 0;
+ kfree(producers_arr);
+ producers->producers_arr = NULL;
}
static int damon_sysfs_producers_add_dirs(
struct damon_sysfs_producers *producers, int nr_producers)
{
+ struct damon_sysfs_producer **producers_arr, *producer;
+ int err, i;
+
damon_sysfs_producers_rm_dirs(producers);
- producers->nr = nr_producers;
+ if (!nr_producers)
+ return 0;
+
+ producers_arr = kmalloc_objs(*producers_arr, nr_producers,
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!producers_arr)
+ return -ENOMEM;
+ producers->producers_arr = producers_arr;
+
+ for (i = 0; i < nr_producers; i++) {
+ producer = damon_sysfs_producer_alloc();
+ if (!producer) {
+ damon_sysfs_producers_rm_dirs(producers);
+ return -ENOMEM;
+ }
+
+ err = kobject_init_and_add(&producer->kobj,
+ &damon_sysfs_producer_ktype, &producers->kobj,
+ "%d", i);
+ if (err) {
+ kobject_put(&producer->kobj);
+ damon_sysfs_producers_rm_dirs(producers);
+ return err;
+ }
+
+ producers_arr[i] = producer;
+ producers->nr++;
+ }
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 08/27] mm/damon/sysfs: implement report producer type and state files
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (6 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 07/27] mm/damon/sysfs: implement report producer directory SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 09/27] Docs/mm/damon/design: update for report system SJ Park
` (19 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement report_type and producer_state files under the report producer
directory. The type file receives the type of the reports that the
producer will generate and submit to DAMON. The producer_state file
enables and disables the producer.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 7c6bc30c12125..7cdbe2fedf7d8 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -2983,6 +2983,8 @@ static const struct kobj_type damon_sysfs_kdamonds_ktype = {
struct damon_sysfs_producer {
struct kobject kobj;
+ enum damon_report_type report_type;
+ bool enabled;
};
static struct damon_sysfs_producer *damon_sysfs_producer_alloc(void)
@@ -2990,6 +2992,77 @@ static struct damon_sysfs_producer *damon_sysfs_producer_alloc(void)
return kzalloc_obj(struct damon_sysfs_producer);
}
+struct damon_sysfs_report_type_name {
+ enum damon_report_type type;
+ char *name;
+};
+
+static const struct damon_sysfs_report_type_name
+damon_sysfs_report_type_names[] = {
+};
+
+static ssize_t report_type_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(damon_sysfs_report_type_names); i++) {
+ const struct damon_sysfs_report_type_name *type_name;
+
+ type_name = &damon_sysfs_report_type_names[i];
+ if (type_name->type == producer->report_type)
+ return sysfs_emit(buf, "%s\n", type_name->name);
+ }
+ return -EINVAL;
+}
+
+static ssize_t report_type_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+ ssize_t ret = -EINVAL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(damon_sysfs_report_type_names); i++) {
+ const struct damon_sysfs_report_type_name *type_name;
+
+ type_name = &damon_sysfs_report_type_names[i];
+ if (sysfs_streq(buf, type_name->name)) {
+ producer->report_type = type_name->type;
+ ret = count;
+ break;
+ }
+ }
+ return ret;
+}
+
+static ssize_t producer_state_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+
+ return sysfs_emit(buf, "%s\n", producer->enabled ? "on" : "off");
+}
+
+static ssize_t producer_state_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+
+ if (sysfs_streq(buf, "on"))
+ producer->enabled = true;
+ else if (sysfs_streq(buf, "off"))
+ producer->enabled = false;
+ else
+ return -EINVAL;
+ return count;
+}
+
static void damon_sysfs_producer_release(struct kobject *kobj)
{
struct damon_sysfs_producer *producer = container_of(kobj,
@@ -2997,7 +3070,14 @@ static void damon_sysfs_producer_release(struct kobject *kobj)
kfree(producer);
}
+static struct kobj_attribute damon_sysfs_producer_report_type_attr =
+ __ATTR_RW_MODE(report_type, 0600);
+static struct kobj_attribute damon_sysfs_producer_producer_state_type_attr =
+ __ATTR_RW_MODE(producer_state, 0600);
+
static struct attribute *damon_sysfs_producer_attrs[] = {
+ &damon_sysfs_producer_report_type_attr.attr,
+ &damon_sysfs_producer_producer_state_type_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_producer);
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 09/27] Docs/mm/damon/design: update for report system
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (7 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 08/27] mm/damon/sysfs: implement report producer type and state files SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 10/27] Docs/admin-guide/mm/damon/usage: update for report producer sysfs SJ Park
` (18 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Jonathan Corbet, Randy Dunlap, Shuah Khan, damon,
linux-doc, linux-kernel, linux-mm
Update DAMON design for the data attribute report system.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/mm/damon/design.rst | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index b676be6971589..e0eb53d7694f7 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -356,6 +356,32 @@ monitoring.
Refer to the :ref:`admin guide <damon_usage_sysfs_probes>` to know how users
can use the mode.
+.. _damon_design_attr_reporting:
+
+Data Attributes Reporting
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+DAMON-external entities such as other kernel components and users may have
+special data attribute information. DAMON provides a system that let them
+report such information to DAMON.
+
+DAMON provides the kernel API for submitting a report of data attribute
+information to DAMON. A report describes what type of the report is,
+representing the reporting data attribute type. A report also describes the
+address range of the memory that the report is made for. Depending on the
+report type, the report can have additional information. The report is saved
+in DAMON's internal queue. The queue is automatically managed by DAMON with
+its best effort.
+
+DAMON provides the user :ref:`ABI <damon_usage_sysfs_reports_producers>` for
+configuring report producers. Each producer is configured for a specific
+report type. Users can dynamically enable and disable those. When enabled, it
+can generate and submit reports of the given type. The generations and
+submissions could be done automatically by the kernel or manually by the user,
+depending on the type of the report.
+
+For now, no report type is supported.
+
Dynamic Target Space Updates Handling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 10/27] Docs/admin-guide/mm/damon/usage: update for report producer sysfs
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (8 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 09/27] Docs/mm/damon/design: update for report system SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 11/27] Docs/ABI/damon: update for report producer sysfs files SJ Park
` (17 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Jonathan Corbet, Randy Dunlap, Shuah Khan, damon,
linux-doc, linux-kernel, linux-mm
Update DAMON usage document for the newly added report producer control
sysfs files.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/admin-guide/mm/damon/usage.rst | 35 ++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index 6093b1c8fbfd9..644250c7bd681 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -115,6 +115,10 @@ comma (",").
│ │ │ │ │ │ ...
│ │ │ │ ...
│ │ ...
+ │ reports/
+ │ │ producers/nr_producers
+ │ │ │ 0/report_type,producer_state
+ │ │ │ ...
.. _sysfs_root:
@@ -729,6 +733,37 @@ Please note that it's highly recommended to use user space tools like `damo
<https://github.com/damonitor/damo>`_ rather than manually reading and writing
the files as above. Above is only for an example.
+.. _damon_usage_sysfs_reports_producers:
+
+reports/producers/
+------------------
+
+Under the `admin/` directory, ``reports/producers/`` directory exists. This
+directory is for configuring :ref:`DAMON report producers
+<damon_design_attr_reporting>`. The file below exists in the directory.
+
+``nr_producers`` file is for generating report producers setup files. Writing
+an integer ``N`` to the file creates the number of directories named ``0`` to
+``N-1``. Each number-named directory is for configuring each report producer
+and called "producer directory".
+
+reports/producers/<N>/
+----------------------
+
+Files below exist in each producer directory.
+
+``report_type`` file is for setting the type of the report to produce. Users
+can set the type by writing the type name to the file. Reading the file shows
+the last successfully written input. Refer to the :ref:`design document
+<damon_design_attr_reporting>` for the list of supported report types.
+
+``producer_state`` file is for reading and updating the state. Reading it
+shows ``on`` or ``off`` if the producer is enabled or disabled, respectively.
+Users can write below keywords for the producer to the file.
+
+- ``on``: Enable the producer.
+- ``off``: Disable the producer.
+
.. _tracepoint:
Tracepoints for Monitoring Results
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 11/27] Docs/ABI/damon: update for report producer sysfs files
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (9 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 10/27] Docs/admin-guide/mm/damon/usage: update for report producer sysfs SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 12/27] mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE SJ Park
` (16 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, damon, linux-kernel, linux-mm
Update DAMON ABI document for the newly added data attribute report
producer control sysfs files.
Signed-off-by: SJ Park <sj@kernel.org>
---
.../ABI/testing/sysfs-kernel-mm-damon | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index 4acb2015c2f4f..c9f718f126c70 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -695,3 +695,23 @@ Date: May 2026
Contact: SJ Park <sj@kernel.org>
Description: Reading this file returns the number of data-attribute
monitoring probe-hit positive samples of the region.
+
+What: /sys/kernel/mm/damon/admin/reports/producers/nr_producers
+Date: Nov 2026
+Contact: SJ Park <sj@kernel.org>
+Description: Writing a number 'N' to this file creates the number of
+ directories for controlling each DAMON report producers
+ named '0' to 'N-1' under the 'producers/' directory.
+
+What: /sys/kernel/mm/damon/admin/reports/producers/<P>/report_type
+Date: Nov 2026
+Contact: SJ Park <sj@kernel.org>
+Description: Writing to and reading from this file sets and gets the type of
+ the reports the producer will generate and submit.
+
+What: /sys/kernel/mm/damon/admin/reports/producers/<P>/producer_state
+Date: Nov 2026
+Contact: SJ Park <sj@kernel.org>
+Description: A file for requesting actions including enablement and
+ disablement of the producer. Refer to
+ Documentation/admin-guide/mm/damon/usage.rst for more details.
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 12/27] mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (10 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 11/27] Docs/ABI/damon: update for report producer sysfs files SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:36 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 13/27] mm/damon/core: introduce damon_report_exist() SJ Park
` (15 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Extend DAMON probe filter for the existence of data attribute reports
for the probing memory. Define a new filter type, REPORT_MADE, for the
purpose. Add a union argument for specifying the type of the reports
for the filter. Update the new argument for the new type when new
filter parameters of the type are committed.
Signed-off-by: SJ Park <sj@kernel.org>
---
include/linux/damon.h | 3 +++
mm/damon/core.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index ca0135c6f6700..cce7d344c585b 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -804,6 +804,7 @@ struct damon_prep {
* @DAMON_FILTER_TYPE_PGIDLE_SET: Pgidle is set.
* @DAMON_FILTER_TYPE_HUGEPAGE_SIZE: Page is part of a hugepage.
* @DAMON_FILTER_TYPE_ACTIVE: LRU-active pages.
+ * @DAMON_FILTER_TYPE_REPORT_MADE: Report is submitted.
*/
enum damon_filter_type {
DAMON_FILTER_TYPE_ANON,
@@ -812,6 +813,7 @@ enum damon_filter_type {
DAMON_FILTER_TYPE_PGIDLE_SET,
DAMON_FILTER_TYPE_HUGEPAGE_SIZE,
DAMON_FILTER_TYPE_ACTIVE,
+ DAMON_FILTER_TYPE_REPORT_MADE,
};
/**
@@ -834,6 +836,7 @@ struct damon_filter {
unsigned long range_min;
unsigned long range_max;
};
+ enum damon_report_type report_type;
};
/* private: */
/* Siblings list. */
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 06b85d00e38d9..c02c7fbc1d864 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1834,6 +1834,9 @@ static int damon_commit_filter(struct damon_filter *dst,
dst->range_min = src->range_min;
dst->range_max = src->range_max;
break;
+ case DAMON_FILTER_TYPE_REPORT_MADE:
+ dst->report_type = src->report_type;
+ break;
default:
break;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 12/27] mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE
2026-11-15 20:28 ` [RFC PATCH 12/27] mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE SJ Park
@ 2026-11-15 20:36 ` sashiko-bot
2026-11-15 21:27 ` SJ Park
0 siblings, 1 reply; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:36 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] mm/damon: missing report_type copy in damon_commit_filters()
- [Low] mm/damon: missing kernel-doc for report_type in struct
damon_filter
--
commit 4743cf0114c7407b0d8b853557595a3a4674cb82
Author: SJ Park <sj@kernel.org>
mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE
This commit introduces the DAMON_FILTER_TYPE_REPORT_MADE probe filter
type, adds report_type to struct damon_filter, and copies it in
damon_commit_filter().
> diff --git a/include/linux/damon.h b/include/linux/damon.h
> index ca0135c6f6700..cce7d344c585b 100644
> --- a/include/linux/damon.h
> +++ b/include/linux/damon.h
[ ... ]
> @@ -834,6 +836,7 @@ struct damon_filter {
> unsigned long range_min;
> unsigned long range_max;
> };
> + enum damon_report_type report_type;
> };
[Severity: Low]
Should @report_type be documented in the kernel-doc comment for struct
damon_filter to avoid a kernel-doc warning?
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 06b85d00e38d9..c02c7fbc1d864 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -1834,6 +1834,9 @@ static int damon_commit_filter(struct damon_filter *dst,
> dst->range_min = src->range_min;
> dst->range_max = src->range_max;
> break;
> + case DAMON_FILTER_TYPE_REPORT_MADE:
> + dst->report_type = src->report_type;
> + break;
[Severity: Medium]
Does damon_commit_filters() also need to copy report_type when allocating
a new filter?
damon_commit_filter() is only called when overwriting an existing filter
in dst. When src has more filters than dst, damon_commit_filters()
allocates new_filter via damon_new_filter() (which uses kmalloc_obj()
without initializing the union) and runs a separate switch on
src_filter->type:
mm/damon/core.c:damon_commit_filters() {
...
new_filter = damon_new_filter(
src_filter->type, src_filter->matching,
src_filter->allow);
if (!new_filter)
return -ENOMEM;
switch (src_filter->type) {
case DAMON_FILTER_TYPE_MEMCG:
new_filter->memcg_id = src_filter->memcg_id;
break;
case DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
...
break;
default:
break;
}
...
}
Because DAMON_FILTER_TYPE_REPORT_MADE is not handled there, committing a
newly added report_made filter leaves new_filter->report_type
uninitialized.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=12
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [RFC PATCH 12/27] mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE
2026-11-15 20:36 ` sashiko-bot
@ 2026-11-15 21:27 ` SJ Park
0 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 21:27 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, Andrew Morton, damon, linux-mm
On Sun, 15 Nov 2026 20:36:01 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential
> issues to consider:
> - [Medium] mm/damon: missing report_type copy in damon_commit_filters()
> - [Low] mm/damon: missing kernel-doc for report_type in struct
> damon_filter
> --
>
> commit 4743cf0114c7407b0d8b853557595a3a4674cb82
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE
>
> This commit introduces the DAMON_FILTER_TYPE_REPORT_MADE probe filter
> type, adds report_type to struct damon_filter, and copies it in
> damon_commit_filter().
>
> > diff --git a/include/linux/damon.h b/include/linux/damon.h
> > index ca0135c6f6700..cce7d344c585b 100644
> > --- a/include/linux/damon.h
> > +++ b/include/linux/damon.h
>
> [ ... ]
>
> > @@ -834,6 +836,7 @@ struct damon_filter {
> > unsigned long range_min;
> > unsigned long range_max;
> > };
> > + enum damon_report_type report_type;
> > };
>
> [Severity: Low]
> Should @report_type be documented in the kernel-doc comment for struct
> damon_filter to avoid a kernel-doc warning?
Nice catch. I will add the kernel-doc comment.
>
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index 06b85d00e38d9..c02c7fbc1d864 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -1834,6 +1834,9 @@ static int damon_commit_filter(struct damon_filter *dst,
> > dst->range_min = src->range_min;
> > dst->range_max = src->range_max;
> > break;
> > + case DAMON_FILTER_TYPE_REPORT_MADE:
> > + dst->report_type = src->report_type;
> > + break;
>
> [Severity: Medium]
> Does damon_commit_filters() also need to copy report_type when allocating
> a new filter?
>
> damon_commit_filter() is only called when overwriting an existing filter
> in dst. When src has more filters than dst, damon_commit_filters()
> allocates new_filter via damon_new_filter() (which uses kmalloc_obj()
> without initializing the union) and runs a separate switch on
> src_filter->type:
>
> mm/damon/core.c:damon_commit_filters() {
> ...
> new_filter = damon_new_filter(
> src_filter->type, src_filter->matching,
> src_filter->allow);
> if (!new_filter)
> return -ENOMEM;
> switch (src_filter->type) {
> case DAMON_FILTER_TYPE_MEMCG:
> new_filter->memcg_id = src_filter->memcg_id;
> break;
> case DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
> ...
> break;
> default:
> break;
> }
> ...
> }
>
> Because DAMON_FILTER_TYPE_REPORT_MADE is not handled there, committing a
> newly added report_made filter leaves new_filter->report_type
> uninitialized.
Good catch. I will add that.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=12
>
Thanks,
SJ
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 13/27] mm/damon/core: introduce damon_report_exist()
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (11 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 12/27] mm/damon/core: introduce DAMON_FILTER_TYPE_REPORT_MADE SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:37 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 14/27] mm/damon/paddr: support REPORT_MADE type probe filter SJ Park
` (14 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement and expose a new DAMON API function for searching data
attribute reports from the report queue. The purpose is to let
operation sets use it for supporting the REPORT_MADE type probe filters.
The caller can specify the type, associated memory address range, and
the creation time range of reports to search.
The function uses CAS-based try-locking for the mutual-exclusive
synchronization. If any parallel access to the queue is detected, it
forgives searching.
Signed-off-by: SJ Park <sj@kernel.org>
---
include/linux/damon.h | 3 +++
mm/damon/core.c | 46 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index cce7d344c585b..0e43b669dfc49 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -1193,6 +1193,9 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control);
int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control);
int damon_submit_report(struct damon_report *report);
+bool damon_report_exist(enum damon_report_type report_type,
+ struct damon_addr_range *addr_range,
+ unsigned long jiffies_old);
int damon_set_region_system_rams_default(struct damon_target *t,
unsigned long *start, unsigned long *end,
diff --git a/mm/damon/core.c b/mm/damon/core.c
index c02c7fbc1d864..c60a6504d0a15 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2386,6 +2386,52 @@ int damon_submit_report(struct damon_report *report)
return 0;
}
+/**
+ * damon_report_exist() - Find if a report of a given condition exists.
+ *
+ * @report_type: Type of the report.
+ * @addr_range: Address range of the report.
+ * @jiffies_old: Oldest jiffies to find the report for.
+ *
+ * Returns true if the report is found, false otherwise.
+ */
+bool damon_report_exist(enum damon_report_type report_type,
+ struct damon_addr_range *addr_range, unsigned long jiffies_old)
+{
+ struct damon_report_queue *queue;
+ int lock_old_val;
+ unsigned int idx, nr_read;
+ struct damon_report *report;
+ bool found = false;
+
+ queue = &damon_report_queue;
+ lock_old_val = atomic_cmpxchg(&queue->lock, 0, 1);
+
+ if (lock_old_val)
+ return false;
+ idx = queue->tail;
+ for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
+ report = &queue->reports[idx];
+ if (idx)
+ idx--;
+ else
+ idx = queue->size - 1;
+
+ if (time_before(report->jiffies, jiffies_old))
+ break;
+ if (report->type != report_type)
+ continue;
+ if (addr_range->end <= report->addr_range.start ||
+ report->addr_range.end <= addr_range->start)
+ continue;
+ found = true;
+ break;
+ }
+
+ atomic_cmpxchg(&queue->lock, 1, 0);
+ return found;
+}
+
/*
* Reset the aggregated monitoring results ('nr_accesses' of each region).
*/
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 13/27] mm/damon/core: introduce damon_report_exist()
2026-11-15 20:28 ` [RFC PATCH 13/27] mm/damon/core: introduce damon_report_exist() SJ Park
@ 2026-11-15 20:37 ` sashiko-bot
2026-11-15 21:35 ` SJ Park
0 siblings, 1 reply; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:37 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [High] mm/damon/core: out-of-bounds and uninitialized read in
damon_report_exist()
--
commit be7b07b7677627ddaaa72484649217b5172610a1
Author: SJ Park <sj@kernel.org>
mm/damon/core: introduce damon_report_exist()
This commit adds damon_report_exist() to search damon_report_queue for a
report matching a given type, address range, and minimum age in jiffies.
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index c02c7fbc1d864..c60a6504d0a15 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2386,6 +2386,52 @@ int damon_submit_report(struct damon_report *report)
> return 0;
> }
>
> +/**
> + * damon_report_exist() - Find if a report of a given condition exists.
> + *
> + * @report_type: Type of the report.
> + * @addr_range: Address range of the report.
> + * @jiffies_old: Oldest jiffies to find the report for.
> + *
> + * Returns true if the report is found, false otherwise.
> + */
> +bool damon_report_exist(enum damon_report_type report_type,
> + struct damon_addr_range *addr_range, unsigned long jiffies_old)
> +{
> + struct damon_report_queue *queue;
> + int lock_old_val;
> + unsigned int idx, nr_read;
> + struct damon_report *report;
> + bool found = false;
> +
> + queue = &damon_report_queue;
> + lock_old_val = atomic_cmpxchg(&queue->lock, 0, 1);
> +
> + if (lock_old_val)
> + return false;
> + idx = queue->tail;
> + for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
> + report = &queue->reports[idx];
> + if (idx)
> + idx--;
> + else
> + idx = queue->size - 1;
[Severity: High]
Can indexing queue->reports[idx] before decrementing and wrapping idx read
uninitialized or out-of-bounds memory?
In damon_submit_report(), queue->tail is post-incremented after writing
queue->reports[tail]:
mm/damon/core.c:damon_submit_report() {
...
tail = queue->tail;
if (tail == queue->size)
tail = 0;
queue->reports[tail] = *report;
queue->tail++;
...
}
Because queue->tail points one slot past the newest report, the first
iteration of damon_report_exist() reads the unwritten slot at
queue->reports[queue->tail] (which is allocated with kmalloc_objs() in
damon_init() without zeroing) and never visits queue->reports[0]. Once
queue->size (1000) reports have been submitted, queue->tail reaches 1000
and the first iteration reads queue->reports[1000], one element past the
end of the array. Also, when damon_submit_report() wraps local tail to 0,
queue->tail itself is not wrapped and increments past queue->size on
subsequent submissions.
Should idx be decremented (wrapping from 0 to queue->size - 1) before
indexing queue->reports[idx], with damon_submit_report() updating
queue->tail = tail + 1?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=13
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [RFC PATCH 13/27] mm/damon/core: introduce damon_report_exist()
2026-11-15 20:37 ` sashiko-bot
@ 2026-11-15 21:35 ` SJ Park
0 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 21:35 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, Andrew Morton, damon, linux-mm
On Sun, 15 Nov 2026 20:37:19 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue to consider:
> - [High] mm/damon/core: out-of-bounds and uninitialized read in
> damon_report_exist()
> --
>
> commit be7b07b7677627ddaaa72484649217b5172610a1
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/core: introduce damon_report_exist()
>
> This commit adds damon_report_exist() to search damon_report_queue for a
> report matching a given type, address range, and minimum age in jiffies.
>
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index c02c7fbc1d864..c60a6504d0a15 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -2386,6 +2386,52 @@ int damon_submit_report(struct damon_report *report)
> > return 0;
> > }
> >
> > +/**
> > + * damon_report_exist() - Find if a report of a given condition exists.
> > + *
> > + * @report_type: Type of the report.
> > + * @addr_range: Address range of the report.
> > + * @jiffies_old: Oldest jiffies to find the report for.
> > + *
> > + * Returns true if the report is found, false otherwise.
> > + */
> > +bool damon_report_exist(enum damon_report_type report_type,
> > + struct damon_addr_range *addr_range, unsigned long jiffies_old)
> > +{
> > + struct damon_report_queue *queue;
> > + int lock_old_val;
> > + unsigned int idx, nr_read;
> > + struct damon_report *report;
> > + bool found = false;
> > +
> > + queue = &damon_report_queue;
> > + lock_old_val = atomic_cmpxchg(&queue->lock, 0, 1);
> > +
> > + if (lock_old_val)
> > + return false;
> > + idx = queue->tail;
> > + for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
> > + report = &queue->reports[idx];
> > + if (idx)
> > + idx--;
> > + else
> > + idx = queue->size - 1;
>
> [Severity: High]
> Can indexing queue->reports[idx] before decrementing and wrapping idx read
> uninitialized or out-of-bounds memory?
>
> In damon_submit_report(), queue->tail is post-incremented after writing
> queue->reports[tail]:
>
> mm/damon/core.c:damon_submit_report() {
> ...
> tail = queue->tail;
> if (tail == queue->size)
> tail = 0;
> queue->reports[tail] = *report;
> queue->tail++;
> ...
> }
>
> Because queue->tail points one slot past the newest report, the first
> iteration of damon_report_exist() reads the unwritten slot at
> queue->reports[queue->tail] (which is allocated with kmalloc_objs() in
> damon_init() without zeroing) and never visits queue->reports[0]. Once
> queue->size (1000) reports have been submitted, queue->tail reaches 1000
> and the first iteration reads queue->reports[1000], one element past the
> end of the array. Also, when damon_submit_report() wraps local tail to 0,
> queue->tail itself is not wrapped and increments past queue->size on
> subsequent submissions.
>
> Should idx be decremented (wrapping from 0 to queue->size - 1) before
> indexing queue->reports[idx], with damon_submit_report() updating
> queue->tail = tail + 1?
Good catch. I will move queue->reports[idx] after the idx decrement.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=13
>
Thanks,
SJ
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 14/27] mm/damon/paddr: support REPORT_MADE type probe filter
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (12 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 13/27] mm/damon/core: introduce damon_report_exist() SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:41 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 15/27] mm/damon/sysfs: add filter_report_type file under probe filter directory SJ Park
` (13 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Add a support of DAMON_FILTER_TYPE_REPORT_MADE type probe filter to the
physical address space operation set. Use the DAMON core API function,
damon_report_exist() for the core report search functionality. Set the
time range as the last sampling interval. Pass damon_ctx to the filter
matching function for getting the sampling interval.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/paddr.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 5b773012a8764..04e95047f8cea 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -140,9 +140,10 @@ static void damon_pa_prep_probes(struct damon_ctx *ctx, bool set_samples)
}
static bool damon_pa_filter_match(struct damon_filter *filter,
- struct folio *folio)
+ struct folio *folio, phys_addr_t pa, struct damon_ctx *ctx)
{
bool matched = false;
+ struct damon_addr_range addr_range;
switch (filter->type) {
case DAMON_FILTER_TYPE_PGIDLE_UNSET:
@@ -157,19 +158,27 @@ static bool damon_pa_filter_match(struct damon_filter *filter,
else
matched = damon_folio_young(folio) == false;
break;
+ case DAMON_FILTER_TYPE_REPORT_MADE:
+ addr_range.start = pa;
+ addr_range.end = pa + 1;
+ matched = damon_report_exist(filter->report_type, &addr_range,
+ jiffies -
+ usecs_to_jiffies(ctx->attrs.sample_interval));
+ break;
default:
return damon_ops_filter_match(filter, folio);
}
return matched == filter->matching;
}
-static bool damon_pa_filter_pass(struct folio *folio, struct damon_probe *p)
+static bool damon_pa_filter_pass(struct folio *folio, struct damon_probe *p,
+ phys_addr_t pa, struct damon_ctx *ctx)
{
struct damon_filter *f;
bool pass = true;
damon_for_each_filter(f, p) {
- if (damon_pa_filter_match(f, folio)) {
+ if (damon_pa_filter_match(f, folio, pa, ctx)) {
pass = f->allow;
break;
}
@@ -199,7 +208,7 @@ static unsigned int damon_pa_apply_probes(struct damon_ctx *ctx,
ctx->addr_unit);
folio = damon_get_folio(PHYS_PFN(pa));
damon_for_each_probe(p, ctx) {
- if (damon_pa_filter_pass(folio, p))
+ if (damon_pa_filter_pass(folio, p, pa, ctx))
r->probe_hits[i]++;
i++;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 14/27] mm/damon/paddr: support REPORT_MADE type probe filter
2026-11-15 20:28 ` [RFC PATCH 14/27] mm/damon/paddr: support REPORT_MADE type probe filter SJ Park
@ 2026-11-15 20:41 ` sashiko-bot
2026-11-15 21:40 ` SJ Park
0 siblings, 1 reply; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:41 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] mm/damon: out-of-bounds and uninitialized read in
damon_report_exist()
- [Medium] mm/damon: phys_addr_t truncation and unit mismatch in
damon_pa_filter_match()
- [Medium] mm/damon: uninitialized filter->report_type in
damon_pa_filter_match()
--
commit db7c0b8660ac4e99fdce33921b7535218eaa4dc6
Author: SJ Park <sj@kernel.org>
mm/damon/paddr: support REPORT_MADE type probe filter
This commit adds support for the DAMON_FILTER_TYPE_REPORT_MADE probe
filter in the physical address space operation set by querying
damon_report_exist() over the last sampling interval.
> diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
> index 5b773012a8764..04e95047f8cea 100644
> --- a/mm/damon/paddr.c
> +++ b/mm/damon/paddr.c
> @@ -140,9 +140,10 @@ static void damon_pa_prep_probes(struct damon_ctx *ctx, bool set_samples)
> }
>
> static bool damon_pa_filter_match(struct damon_filter *filter,
> - struct folio *folio)
> + struct folio *folio, phys_addr_t pa, struct damon_ctx *ctx)
> {
> bool matched = false;
> + struct damon_addr_range addr_range;
>
> switch (filter->type) {
> case DAMON_FILTER_TYPE_PGIDLE_UNSET:
> @@ -157,19 +158,27 @@ static bool damon_pa_filter_match(struct damon_filter *filter,
> else
> matched = damon_folio_young(folio) == false;
> break;
> + case DAMON_FILTER_TYPE_REPORT_MADE:
> + addr_range.start = pa;
> + addr_range.end = pa + 1;
[Severity: Medium]
Can assigning pa and pa + 1 into addr_range truncate 64-bit physical
addresses and miss reports when ctx->addr_unit > 1?
struct damon_addr_range defines start and end as unsigned long, so on
32-bit PAE/LPAE systems where phys_addr_t is 64-bit, physical addresses
at or above 4 GiB lose their upper 32 bits (and pa + 1 wraps to 0 when
the low 32 bits are 0xffffffff). In addition, when ctx->addr_unit > 1,
pa is aligned to ctx->addr_unit, so setting addr_range.end = pa + 1 only
checks the first byte of the sampled unit instead of [pa, pa +
ctx->addr_unit).
> + matched = damon_report_exist(filter->report_type, &addr_range,
> + jiffies -
> + usecs_to_jiffies(ctx->attrs.sample_interval));
> + break;
[Severity: High]
Does calling damon_report_exist() read uninitialized or out-of-bounds
elements from damon_report_queue.reports?
In damon_submit_report(), the report is written at queue->reports[tail]
and queue->tail is then incremented, so queue->tail points to the next
slot to be written and is never wrapped when it reaches queue->size:
mm/damon/core.c:damon_submit_report() {
...
tail = queue->tail;
if (tail == queue->size)
tail = 0;
queue->reports[tail] = *report;
queue->tail++;
...
}
mm/damon/core.c:damon_report_exist() {
...
idx = queue->tail;
for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
report = &queue->reports[idx];
if (idx)
idx--;
else
idx = queue->size - 1;
...
}
Because damon_report_exist() indexes queue->reports[idx] at queue->tail
before decrementing idx, it reads uninitialized heap memory on the first
iteration while 1 <= nr_reports < queue->size (and never inspects index
0), and reads out of bounds at queue->reports[queue->size] and beyond once
queue->size reports have been submitted.
[Severity: Medium]
Can filter->report_type be uninitialized here when a new
DAMON_FILTER_TYPE_REPORT_MADE filter is added via damon_commit_ctx()?
damon_new_filter() allocates struct damon_filter with kmalloc_obj()
without zeroing the union, and when damon_commit_filters() creates a new
filter it only copies union members for DAMON_FILTER_TYPE_MEMCG and
DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
mm/damon/core.c:damon_commit_filters() {
...
new_filter = damon_new_filter(src_filter->type,
src_filter->matching, src_filter->allow);
if (!new_filter)
return -ENOMEM;
switch (src_filter->type) {
case DAMON_FILTER_TYPE_MEMCG:
new_filter->memcg_id = src_filter->memcg_id;
break;
case DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
if (src_filter->range_max < src_filter->range_min) {
damon_destroy_filter(new_filter);
return -EINVAL;
}
new_filter->range_min = src_filter->range_min;
new_filter->range_max = src_filter->range_max;
break;
default:
break;
}
...
}
As a result, new_filter->report_type retains uninitialized slab bytes
when damon_pa_filter_match() passes it to damon_report_exist().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=14
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [RFC PATCH 14/27] mm/damon/paddr: support REPORT_MADE type probe filter
2026-11-15 20:41 ` sashiko-bot
@ 2026-11-15 21:40 ` SJ Park
0 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 21:40 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, Andrew Morton, damon, linux-mm
On Sun, 15 Nov 2026 20:41:34 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential
> issues to consider:
> - [High] mm/damon: out-of-bounds and uninitialized read in
> damon_report_exist()
> - [Medium] mm/damon: phys_addr_t truncation and unit mismatch in
> damon_pa_filter_match()
> - [Medium] mm/damon: uninitialized filter->report_type in
> damon_pa_filter_match()
> --
>
> commit db7c0b8660ac4e99fdce33921b7535218eaa4dc6
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/paddr: support REPORT_MADE type probe filter
>
> This commit adds support for the DAMON_FILTER_TYPE_REPORT_MADE probe
> filter in the physical address space operation set by querying
> damon_report_exist() over the last sampling interval.
>
> > diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
> > index 5b773012a8764..04e95047f8cea 100644
> > --- a/mm/damon/paddr.c
> > +++ b/mm/damon/paddr.c
> > @@ -140,9 +140,10 @@ static void damon_pa_prep_probes(struct damon_ctx *ctx, bool set_samples)
> > }
> >
> > static bool damon_pa_filter_match(struct damon_filter *filter,
> > - struct folio *folio)
> > + struct folio *folio, phys_addr_t pa, struct damon_ctx *ctx)
> > {
> > bool matched = false;
> > + struct damon_addr_range addr_range;
> >
> > switch (filter->type) {
> > case DAMON_FILTER_TYPE_PGIDLE_UNSET:
> > @@ -157,19 +158,27 @@ static bool damon_pa_filter_match(struct damon_filter *filter,
> > else
> > matched = damon_folio_young(folio) == false;
> > break;
> > + case DAMON_FILTER_TYPE_REPORT_MADE:
> > + addr_range.start = pa;
> > + addr_range.end = pa + 1;
>
> [Severity: Medium]
> Can assigning pa and pa + 1 into addr_range truncate 64-bit physical
> addresses and miss reports when ctx->addr_unit > 1?
>
> struct damon_addr_range defines start and end as unsigned long, so on
> 32-bit PAE/LPAE systems where phys_addr_t is 64-bit, physical addresses
> at or above 4 GiB lose their upper 32 bits (and pa + 1 wraps to 0 when
> the low 32 bits are 0xffffffff).
Missing a report for this edge case is fine. It only degrades DAMON's
monitoring results, which is anyway best effort.
> In addition, when ctx->addr_unit > 1,
> pa is aligned to ctx->addr_unit, so setting addr_range.end = pa + 1 only
> checks the first byte of the sampled unit instead of [pa, pa +
> ctx->addr_unit).
That's fine. Technically speaking, the sampling is only for the sampling byte.
>
> > + matched = damon_report_exist(filter->report_type, &addr_range,
> > + jiffies -
> > + usecs_to_jiffies(ctx->attrs.sample_interval));
> > + break;
>
> [Severity: High]
> Does calling damon_report_exist() read uninitialized or out-of-bounds
> elements from damon_report_queue.reports?
>
> In damon_submit_report(), the report is written at queue->reports[tail]
> and queue->tail is then incremented, so queue->tail points to the next
> slot to be written and is never wrapped when it reaches queue->size:
>
> mm/damon/core.c:damon_submit_report() {
> ...
> tail = queue->tail;
> if (tail == queue->size)
> tail = 0;
> queue->reports[tail] = *report;
> queue->tail++;
> ...
> }
>
> mm/damon/core.c:damon_report_exist() {
> ...
> idx = queue->tail;
> for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
> report = &queue->reports[idx];
> if (idx)
> idx--;
> else
> idx = queue->size - 1;
> ...
> }
>
> Because damon_report_exist() indexes queue->reports[idx] at queue->tail
> before decrementing idx, it reads uninitialized heap memory on the first
> iteration while 1 <= nr_reports < queue->size (and never inspects index
> 0), and reads out of bounds at queue->reports[queue->size] and beyond once
> queue->size reports have been submitted.
Yes, I will fix it in the earlier patch.
>
> [Severity: Medium]
> Can filter->report_type be uninitialized here when a new
> DAMON_FILTER_TYPE_REPORT_MADE filter is added via damon_commit_ctx()?
>
> damon_new_filter() allocates struct damon_filter with kmalloc_obj()
> without zeroing the union, and when damon_commit_filters() creates a new
> filter it only copies union members for DAMON_FILTER_TYPE_MEMCG and
> DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
>
> mm/damon/core.c:damon_commit_filters() {
> ...
> new_filter = damon_new_filter(src_filter->type,
> src_filter->matching, src_filter->allow);
> if (!new_filter)
> return -ENOMEM;
> switch (src_filter->type) {
> case DAMON_FILTER_TYPE_MEMCG:
> new_filter->memcg_id = src_filter->memcg_id;
> break;
> case DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
> if (src_filter->range_max < src_filter->range_min) {
> damon_destroy_filter(new_filter);
> return -EINVAL;
> }
> new_filter->range_min = src_filter->range_min;
> new_filter->range_max = src_filter->range_max;
> break;
> default:
> break;
> }
> ...
> }
>
> As a result, new_filter->report_type retains uninitialized slab bytes
> when damon_pa_filter_match() passes it to damon_report_exist().
Yes, I will fix it in the earlier patch.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=14
>
Thanks,
SJ
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 15/27] mm/damon/sysfs: add filter_report_type file under probe filter directory
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (13 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 14/27] mm/damon/paddr: support REPORT_MADE type probe filter SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 16/27] mm/damon/sysfs: support REPORT_MADE type probe filter setup SJ Park
` (12 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Add a sysfs file, filter_report_type, under probe filter directory. It
receives damon_report_type from the user. Reuse
damon_sysfs_report_type_name struct for user keyword matching. Move the
definition instead of forward declaration, as the code change is small
enough at this stage.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 61 +++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 52 insertions(+), 9 deletions(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 7cdbe2fedf7d8..ca971cf1dcf6d 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -977,6 +977,7 @@ struct damon_sysfs_filter {
char *path;
unsigned long range_min;
unsigned long range_max;
+ enum damon_report_type report_type;
};
static struct damon_sysfs_filter *damon_sysfs_filter_alloc(void)
@@ -1175,6 +1176,53 @@ static ssize_t max_store(struct kobject *kobj,
return err ? err : count;
}
+struct damon_sysfs_report_type_name {
+ enum damon_report_type type;
+ char *name;
+};
+
+static const struct damon_sysfs_report_type_name
+damon_sysfs_report_type_names[] = {
+};
+
+static ssize_t filter_report_type_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_filter *filter = container_of(kobj,
+ struct damon_sysfs_filter, kobj);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(damon_sysfs_report_type_names); i++) {
+ const struct damon_sysfs_report_type_name *type_name;
+
+ type_name = &damon_sysfs_report_type_names[i];
+ if (type_name->type == filter->report_type)
+ return sysfs_emit(buf, "%s\n", type_name->name);
+ }
+ return -EINVAL;
+}
+
+static ssize_t filter_report_type_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_filter *filter = container_of(kobj,
+ struct damon_sysfs_filter, kobj);
+ ssize_t ret = -EINVAL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(damon_sysfs_report_type_names); i++) {
+ const struct damon_sysfs_report_type_name *type_name;
+
+ type_name = &damon_sysfs_report_type_names[i];
+ if (sysfs_streq(buf, type_name->name)) {
+ filter->report_type = type_name->type;
+ ret = count;
+ break;
+ }
+ }
+ return ret;
+}
+
static void damon_sysfs_filter_release(struct kobject *kobj)
{
struct damon_sysfs_filter *filter = container_of(kobj,
@@ -1202,6 +1250,9 @@ static struct kobj_attribute damon_sysfs_filter_min_attr =
static struct kobj_attribute damon_sysfs_filter_max_attr =
__ATTR_RW_MODE(max, 0600);
+static struct kobj_attribute damon_sysfs_filter_filter_report_type_attr =
+ __ATTR_RW_MODE(filter_report_type, 0600);
+
static struct attribute *damon_sysfs_filter_attrs[] = {
&damon_sysfs_filter_type_attr.attr,
&damon_sysfs_filter_matching_attr.attr,
@@ -1209,6 +1260,7 @@ static struct attribute *damon_sysfs_filter_attrs[] = {
&damon_sysfs_filter_path_attr.attr,
&damon_sysfs_filter_min_attr.attr,
&damon_sysfs_filter_max_attr.attr,
+ &damon_sysfs_filter_filter_report_type_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_filter);
@@ -2992,15 +3044,6 @@ static struct damon_sysfs_producer *damon_sysfs_producer_alloc(void)
return kzalloc_obj(struct damon_sysfs_producer);
}
-struct damon_sysfs_report_type_name {
- enum damon_report_type type;
- char *name;
-};
-
-static const struct damon_sysfs_report_type_name
-damon_sysfs_report_type_names[] = {
-};
-
static ssize_t report_type_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 16/27] mm/damon/sysfs: support REPORT_MADE type probe filter setup
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (14 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 15/27] mm/damon/sysfs: add filter_report_type file under probe filter directory SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:41 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 17/27] Docs/mm/damon/design: update for report_made probe filter type SJ Park
` (11 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Accept user keyword "report_made" to probe filter type file. Set the
damon_filter->type as REPORT_MADE for the input. Setup
damon_filter->report_type with the filter_report_type user input.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index ca971cf1dcf6d..1c171af4590a8 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -1016,6 +1016,10 @@ damon_sysfs_filter_type_names[] = {
.type = DAMON_FILTER_TYPE_ACTIVE,
.name = "active",
},
+ {
+ .type = DAMON_FILTER_TYPE_REPORT_MADE,
+ .name = "report_made",
+ },
};
static ssize_t type_show(struct kobject *kobj,
@@ -2336,6 +2340,8 @@ static int damon_sysfs_set_filters(struct damon_probe *probe,
} else if (filter->type == DAMON_FILTER_TYPE_HUGEPAGE_SIZE) {
filter->range_min = sys_filter->range_min;
filter->range_max = sys_filter->range_max;
+ } else if (filter->type == DAMON_FILTER_TYPE_REPORT_MADE) {
+ filter->report_type = sys_filter->report_type;
}
damon_add_filter(probe, filter);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 16/27] mm/damon/sysfs: support REPORT_MADE type probe filter setup
2026-11-15 20:28 ` [RFC PATCH 16/27] mm/damon/sysfs: support REPORT_MADE type probe filter setup SJ Park
@ 2026-11-15 20:41 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:41 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] mm/damon: out-of-bounds and uninitialized access in
damon_report_exist()
- [Medium] mm/damon: uninitialized report_type in damon_commit_filters()
--
commit 6058e18a855d5b73c171dc4b94eb6031f06fdc63
Author: SJ Park <sj@kernel.org>
mm/damon/sysfs: support REPORT_MADE type probe filter setup
This commit adds "report_made" to the DAMON sysfs probe filter type list
and copies the filter's report_type when setting up probe filters.
> diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
> index ca971cf1dcf6d..1c171af4590a8 100644
> --- a/mm/damon/sysfs.c
> +++ b/mm/damon/sysfs.c
> @@ -1016,6 +1016,10 @@ damon_sysfs_filter_type_names[] = {
> .type = DAMON_FILTER_TYPE_ACTIVE,
> .name = "active",
> },
> + {
> + .type = DAMON_FILTER_TYPE_REPORT_MADE,
> + .name = "report_made",
> + },
> };
>
> static ssize_t type_show(struct kobject *kobj,
[Severity: High]
Can enabling DAMON_FILTER_TYPE_REPORT_MADE filters cause uninitialized and
out-of-bounds accesses on queue->reports[]?
In damon_submit_report(), each report is stored at queue->reports[tail] and
then queue->tail is incremented, so queue->tail points to the next slot to
write rather than the most recent entry:
mm/damon/core.c:damon_submit_report() {
...
tail = queue->tail;
if (tail == queue->size)
tail = 0;
queue->reports[tail] = *report;
queue->tail++;
...
}
When damon_pa_filter_match() calls damon_report_exist() for a report_made
filter, the loop reads queue->reports[idx] starting at idx = queue->tail
before decrementing idx:
mm/damon/core.c:damon_report_exist() {
...
idx = queue->tail;
for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
report = &queue->reports[idx];
if (idx)
idx--;
else
idx = queue->size - 1;
...
}
While queue->nr_reports < queue->size, the first iteration reads the
unwritten slot at queue->reports[queue->tail] and the loop stops before
checking queue->reports[0]. Once queue->tail reaches queue->size,
damon_report_exist() reads out of bounds at queue->reports[queue->size],
and the next damon_submit_report() wraps only the local tail variable
before incrementing queue->tail past queue->size, causing subsequent
submissions and lookups to write and read out of bounds on the heap.
> @@ -2336,6 +2340,8 @@ static int damon_sysfs_set_filters(struct damon_probe *probe,
> } else if (filter->type == DAMON_FILTER_TYPE_HUGEPAGE_SIZE) {
> filter->range_min = sys_filter->range_min;
> filter->range_max = sys_filter->range_max;
> + } else if (filter->type == DAMON_FILTER_TYPE_REPORT_MADE) {
> + filter->report_type = sys_filter->report_type;
> }
> damon_add_filter(probe, filter);
> }
[Severity: Medium]
Does committing a new DAMON_FILTER_TYPE_REPORT_MADE filter to a running
context leave new_filter->report_type uninitialized?
When damon_sysfs_commit_input() commits the context built here via
damon_commit_ctx() -> __damon_commit_ctx() -> damon_commit_probes() ->
damon_commit_filters(), newly added filters are allocated with
damon_new_filter(), which does not initialize the union in struct
damon_filter, and the switch in damon_commit_filters() does not handle
DAMON_FILTER_TYPE_REPORT_MADE:
mm/damon/core.c:damon_commit_filters() {
...
new_filter = damon_new_filter(src_filter->type,
src_filter->matching, src_filter->allow);
if (!new_filter)
return -ENOMEM;
switch (src_filter->type) {
case DAMON_FILTER_TYPE_MEMCG:
new_filter->memcg_id = src_filter->memcg_id;
break;
case DAMON_FILTER_TYPE_HUGEPAGE_SIZE:
...
default:
break;
}
...
}
As a result, damon_pa_filter_match() passes uninitialized slab memory in
new_filter->report_type to damon_report_exist().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=16
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 17/27] Docs/mm/damon/design: update for report_made probe filter type
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (15 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 16/27] mm/damon/sysfs: support REPORT_MADE type probe filter setup SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 18/27] Docs/admin-guide/mm/damon/usage: update for REPORT_MADE probe filter SJ Park
` (10 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Jonathan Corbet, Randy Dunlap, Shuah Khan, damon,
linux-doc, linux-kernel, linux-mm
Update DAMON design document for the newly added data attribute report
existence type probe filter.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/mm/damon/design.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index e0eb53d7694f7..68cd80e2788cd 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -303,6 +303,8 @@ filter types. Currently below filter types are supported.
- ``hugepage_size``: Matches if the page for the memory is a part of a hugepage
of a given size range.
- ``active``: Same to that for DAMOS filters.
+- ``report_made``: Matches if a :ref:`report <damon_design_attr_reporting>` for
+ the memory is made in last sampling interval.
If such probes are registered, DAMON executes the probes for each region's
sampling memory when it does the access :ref:`sampling
@@ -382,6 +384,10 @@ depending on the type of the report.
For now, no report type is supported.
+The data attribute probe supports the reports. The probes can be configured to
+hit for a given memory region if a specific type of valid reports that are
+associated with the probing memory exist in the reports queue.
+
Dynamic Target Space Updates Handling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 18/27] Docs/admin-guide/mm/damon/usage: update for REPORT_MADE probe filter
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (16 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 17/27] Docs/mm/damon/design: update for report_made probe filter type SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 19/27] Docs/ABI/damon: " SJ Park
` (9 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Jonathan Corbet, Randy Dunlap, Shuah Khan, damon,
linux-doc, linux-kernel, linux-mm
Update DAMON usage document for the newly added REPORT_MADE type probe
filter support.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/admin-guide/mm/damon/usage.rst | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index 644250c7bd681..ce4e9e4c13276 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -78,7 +78,7 @@ comma (",").
│ │ │ │ │ │ │ │ │ 0/prep_action
│ │ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ │ │ filters/nr_filters
- │ │ │ │ │ │ │ │ │ 0/type,matching,allow,path,min,max
+ │ │ │ │ │ │ │ │ │ 0/type,matching,allow,path,min,max,filter_report_type
│ │ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ │ ...
│ │ │ │ │ :ref:`targets <sysfs_targets>`/nr_targets
@@ -317,6 +317,10 @@ filter <sysfs_filters>`. When the filter ``type`` is ``hugepage_size``,
``min`` and ``max`` files act as files of the same names for :ref:`DAMOS
filter <sysfs_filters>`.
+When the filter ``type`` is ``report_made``, the :ref:`report
+<damon_design_attr_reporting>` type for the filtering should also be specified
+by writing the type name to ``filter_report_type`` file.
+
.. _sysfs_targets:
contexts/<N>/targets/
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 19/27] Docs/ABI/damon: update for REPORT_MADE probe filter
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (17 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 18/27] Docs/admin-guide/mm/damon/usage: update for REPORT_MADE probe filter SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 20/27] mm/damon/api: introduce user_report report type SJ Park
` (8 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, damon, linux-kernel, linux-mm
Update DAMON ABI document for the newly added REPORT_MADE type probe
filter support.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/ABI/testing/sysfs-kernel-mm-damon | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index c9f718f126c70..e558dd4212f2c 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -233,6 +233,13 @@ Description: Writing 'Y' or 'N' to this file sets whether to allow or reject
hitting the probe for the memory that satisfies the 'type' and
the 'matching' of the directory.
+What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/monitoring_attrs/probes/<P>/filters/<F>/filter_report_type
+Date: Nov 2026
+Contact: SJ Park <sj@kernel.org>
+Description: If 'report_made' is written to the 'type' file, writing to and
+ reading from this file sets and gets the 'report_type' of the
+ reports that this filter is working for.
+
What: /sys/kernel/mm/damon/admin/kdamonds/<K>/contexts/<C>/targets/nr_targets
Date: Mar 2022
Contact: SJ Park <sj@kernel.org>
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 20/27] mm/damon/api: introduce user_report report type
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (18 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 19/27] Docs/ABI/damon: " SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 21/27] mm/damon/sysfs: add user_report support for report type input SJ Park
` (7 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, damon, linux-kernel, linux-mm
Users could know some data attribute information and willing to provide
that to DAMON. Introduce a new damon_report_type,
DAMON_REPORT_TYPE_USER_REPORT, for such user-provided reports.
Signed-off-by: SJ Park <sj@kernel.org>
---
include/linux/damon.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 0e43b669dfc49..329d8202b41db 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -753,9 +753,11 @@ struct damon_intervals_goal {
/**
* enum damon_report_type - Type of &struct damon_report.
+ *
+ * @DAMON_REPORT_TYPE_USER_REPORT: User-generated report.
*/
enum damon_report_type {
- NR_DAMON_REPORT_TYPES,
+ DAMON_REPORT_TYPE_USER_REPORT,
};
/**
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 21/27] mm/damon/sysfs: add user_report support for report type input
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (19 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 20/27] mm/damon/api: introduce user_report report type SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 22/27] mm/damon/sysfs: implement report producer addr_{start,end} files SJ Park
` (6 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Extend the mapping list for data attribute report types and user
keywords, for the USER_REPORT report type. Use "user_report" as the
matching user keyword.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 1c171af4590a8..b4d898ec0c9f7 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -1187,6 +1187,10 @@ struct damon_sysfs_report_type_name {
static const struct damon_sysfs_report_type_name
damon_sysfs_report_type_names[] = {
+ {
+ .type = DAMON_REPORT_TYPE_USER_REPORT,
+ .name = "user_report",
+ },
};
static ssize_t filter_report_type_show(struct kobject *kobj,
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 22/27] mm/damon/sysfs: implement report producer addr_{start,end} files
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (20 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 21/27] mm/damon/sysfs: add user_report support for report type input SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 23/27] mm/damon/sysfs: implement submit command for report producer SJ Park
` (5 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Implement addr_start and addr_end sysfs files under report producer
directory. Those set and get the address range of the user_report type
data attribute reports.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index b4d898ec0c9f7..5f9bb1955dfd5 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -3047,6 +3047,7 @@ struct damon_sysfs_producer {
struct kobject kobj;
enum damon_report_type report_type;
bool enabled;
+ struct damon_addr_range addr_range;
};
static struct damon_sysfs_producer *damon_sysfs_producer_alloc(void)
@@ -3116,6 +3117,44 @@ static ssize_t producer_state_store(struct kobject *kobj,
return count;
}
+static ssize_t addr_start_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+
+ return sysfs_emit(buf, "%lu\n", producer->addr_range.start);
+}
+
+static ssize_t addr_start_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+ int err = kstrtoul(buf, 0, &producer->addr_range.start);
+
+ return err ? err : count;
+}
+
+static ssize_t addr_end_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+
+ return sysfs_emit(buf, "%lu\n", producer->addr_range.end);
+}
+
+static ssize_t addr_end_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_producer *producer = container_of(kobj,
+ struct damon_sysfs_producer, kobj);
+ int err = kstrtoul(buf, 0, &producer->addr_range.end);
+
+ return err ? err : count;
+}
+
static void damon_sysfs_producer_release(struct kobject *kobj)
{
struct damon_sysfs_producer *producer = container_of(kobj,
@@ -3127,10 +3166,16 @@ static struct kobj_attribute damon_sysfs_producer_report_type_attr =
__ATTR_RW_MODE(report_type, 0600);
static struct kobj_attribute damon_sysfs_producer_producer_state_type_attr =
__ATTR_RW_MODE(producer_state, 0600);
+static struct kobj_attribute damon_sysfs_producer_addr_start_type_attr =
+ __ATTR_RW_MODE(addr_start, 0600);
+static struct kobj_attribute damon_sysfs_producer_addr_end_type_attr =
+ __ATTR_RW_MODE(addr_end, 0600);
static struct attribute *damon_sysfs_producer_attrs[] = {
&damon_sysfs_producer_report_type_attr.attr,
&damon_sysfs_producer_producer_state_type_attr.attr,
+ &damon_sysfs_producer_addr_start_type_attr.attr,
+ &damon_sysfs_producer_addr_end_type_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_producer);
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 23/27] mm/damon/sysfs: implement submit command for report producer
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (21 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 22/27] mm/damon/sysfs: implement report producer addr_{start,end} files SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:43 ` sashiko-bot
2026-11-15 20:28 ` [RFC PATCH 24/27] selftests/damon/sysfs.sh: add basic tests for admin/reports/ SJ Park
` (4 subsequent siblings)
27 siblings, 1 reply; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
Let users manually submit a report of a data attribute for a given
address range of memory. Let producer_state receive "submit" input for
that. For the input, generate the report based on user inputs that are
written to the appropriate sysfs files and submit to DAMON using the
core API, damon_submit_report().
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 5f9bb1955dfd5..0049aac6ab974 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -3107,13 +3107,26 @@ static ssize_t producer_state_store(struct kobject *kobj,
{
struct damon_sysfs_producer *producer = container_of(kobj,
struct damon_sysfs_producer, kobj);
+ struct damon_report report;
+ int err;
- if (sysfs_streq(buf, "on"))
+ if (sysfs_streq(buf, "on")) {
producer->enabled = true;
- else if (sysfs_streq(buf, "off"))
+ } else if (sysfs_streq(buf, "off")) {
producer->enabled = false;
- else
+ } else if (sysfs_streq(buf, "submit")) {
+ if (!producer->enabled)
+ return -EINVAL;
+ if (producer->report_type != DAMON_REPORT_TYPE_USER_REPORT)
+ return -EINVAL;
+ report.type = DAMON_REPORT_TYPE_USER_REPORT;
+ report.addr_range = producer->addr_range;
+ err = damon_submit_report(&report);
+ if (err)
+ return err;
+ } else {
return -EINVAL;
+ }
return count;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 23/27] mm/damon/sysfs: implement submit command for report producer
2026-11-15 20:28 ` [RFC PATCH 23/27] mm/damon/sysfs: implement submit command for report producer SJ Park
@ 2026-11-15 20:43 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-11-15 20:43 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, damon, linux-mm
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [High] mm/damon: OOB write in damon_submit_report() and read in
damon_report_exist()
--
commit 2f4ed587e778c0d51407454ba3a19b21c1bc10c0
Author: SJ Park <sj@kernel.org>
mm/damon/sysfs: implement submit command for report producer
This commit adds a "submit" command to producer_state_store() so userspace
can submit manual reports via damon_submit_report().
> diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
> index 5f9bb1955dfd5..0049aac6ab974 100644
> --- a/mm/damon/sysfs.c
> +++ b/mm/damon/sysfs.c
> @@ -3107,13 +3107,26 @@ static ssize_t producer_state_store(struct kobject *kobj,
> {
> struct damon_sysfs_producer *producer = container_of(kobj,
> struct damon_sysfs_producer, kobj);
> + struct damon_report report;
> + int err;
>
> - if (sysfs_streq(buf, "on"))
> + if (sysfs_streq(buf, "on")) {
> producer->enabled = true;
> - else if (sysfs_streq(buf, "off"))
> + } else if (sysfs_streq(buf, "off")) {
> producer->enabled = false;
> - else
> + } else if (sysfs_streq(buf, "submit")) {
> + if (!producer->enabled)
> + return -EINVAL;
> + if (producer->report_type != DAMON_REPORT_TYPE_USER_REPORT)
> + return -EINVAL;
> + report.type = DAMON_REPORT_TYPE_USER_REPORT;
> + report.addr_range = producer->addr_range;
> + err = damon_submit_report(&report);
[Severity: High]
Can repeated "submit" writes overflow damon_report_queue.reports[] in
damon_submit_report() and read out of bounds in damon_report_exist()?
mm/damon/core.c:damon_submit_report() {
...
tail = queue->tail;
if (tail == queue->size)
tail = 0;
queue->reports[tail] = *report;
queue->tail++;
...
}
When queue->tail reaches queue->size (1000), damon_submit_report() wraps
only the local variable tail to 0 and still increments queue->tail to
1001 instead of setting queue->tail = tail + 1. On the next submission,
tail is 1001, the equality check against queue->size is false, and
queue->reports[tail] writes past the end of the 1000-element heap array.
In addition, damon_report_exist() starts its backward scan at
idx = queue->tail (the next free slot) and dereferences
queue->reports[idx] before decrementing idx:
mm/damon/core.c:damon_report_exist() {
...
idx = queue->tail;
for (nr_read = 0; nr_read < queue->nr_reports; nr_read++) {
report = &queue->reports[idx];
if (idx)
idx--;
else
idx = queue->size - 1;
...
}
Before the ring wraps, the first iteration reads uninitialized memory at
queue->reports[queue->tail] while the loop stops before reaching
queue->reports[0], missing a single submitted report entirely; once
1000 reports have been submitted (queue->tail == queue->size), the first
iteration reads out of bounds at queue->reports[1000].
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115202849.99134-1-sj@kernel.org?part=23
^ permalink raw reply [flat|nested] 43+ messages in thread
* [RFC PATCH 24/27] selftests/damon/sysfs.sh: add basic tests for admin/reports/
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (22 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 23/27] mm/damon/sysfs: implement submit command for report producer SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 25/27] Docs/mm/damon/design: update for user report support SJ Park
` (3 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Shuah Khan, damon, linux-kernel, linux-kselftest,
linux-mm
Update sysfs.sh DAMON selftest to cover basic file operations for the
sysfs files under the admin/reports/ directory.
Signed-off-by: SJ Park <sj@kernel.org>
---
tools/testing/selftests/damon/sysfs.sh | 52 ++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/tools/testing/selftests/damon/sysfs.sh b/tools/testing/selftests/damon/sysfs.sh
index 1cc7ab2d7e22f..577953ee4e631 100755
--- a/tools/testing/selftests/damon/sysfs.sh
+++ b/tools/testing/selftests/damon/sysfs.sh
@@ -510,6 +510,57 @@ test_kdamonds()
ensure_dir "$kdamonds_dir/1" "not_exist"
}
+test_producer()
+{
+ producer_dir=$1
+ ensure_file "$producer_dir/report_type" "exist" "600"
+ ensure_write_succ "$producer_dir/report_type" "user_report" \
+ "valid input"
+ ensure_write_fail "$producer_dir/report_type" "foo" "invlid input"
+
+ ensure_file "$producer_dir/producer_state" "exist" "600"
+ ensure_write_succ "$producer_dir/producer_state" "on" "valid input"
+ ensure_write_succ "$producer_dir/producer_state" "submit" "valid input"
+ ensure_write_succ "$producer_dir/producer_state" "off" "valid input"
+ ensure_write_fail "$producer_dir/producer_state" "foo" "invalid input"
+
+ ensure_file "$producer_dir/addr_start" "exist" "600"
+ ensure_write_succ "$producer_dir/addr_start" 123 "valid input"
+ ensure_write_fail "$producer_dir/addr_start" foo "uinvalid input"
+ ensure_write_fail "$producer_dir/addr_start" "1.23" "uinvalid input"
+
+ ensure_file "$producer_dir/addr_end" "exist" "600"
+ ensure_write_succ "$producer_dir/addr_end" 123 "valid input"
+ ensure_write_fail "$producer_dir/addr_end" foo "uinvalid input"
+ ensure_write_fail "$producer_dir/addr_end" "1.23" "uinvalid input"
+}
+
+test_producers()
+{
+ producers_dir=$1
+ ensure_dir "$producers_dir" "exist"
+
+ ensure_file "$producers_dir/nr_producers" "exist" "600"
+
+ ensure_write_succ "$producers_dir/nr_producers" "1" "valid input"
+ test_producer "$producers_dir/0"
+
+ ensure_write_succ "$producers_dir/nr_producers" "2" "valid input"
+ test_producer "$producers_dir/0"
+ test_producer "$producers_dir/1"
+
+ ensure_write_succ "$producers_dir/nr_producers" "0" "valid input"
+ ensure_dir "$producers_dir/0" "not_exist"
+ ensure_dir "$producers_dir/1" "not_exist"
+}
+
+test_reports()
+{
+ reports_dir=$1
+ ensure_dir "$reports_dir" "exist"
+ test_producers "$reports_dir/producers"
+}
+
test_damon_sysfs()
{
damon_sysfs=$1
@@ -520,6 +571,7 @@ test_damon_sysfs()
fi
test_kdamonds "$damon_sysfs/kdamonds"
+ test_reports "$damon_sysfs/reports"
}
check_dependencies
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 25/27] Docs/mm/damon/design: update for user report support
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (23 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 24/27] selftests/damon/sysfs.sh: add basic tests for admin/reports/ SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 26/27] Docs/admin-guide/mm/damon/usage: update for user_report " SJ Park
` (2 subsequent siblings)
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Jonathan Corbet, Randy Dunlap, Shuah Khan, damon,
linux-doc, linux-kernel, linux-mm
Update DAMON design document for the newly aded user_report type data
attribute reports.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/mm/damon/design.rst | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/Documentation/mm/damon/design.rst b/Documentation/mm/damon/design.rst
index 68cd80e2788cd..3f6779cd6ed48 100644
--- a/Documentation/mm/damon/design.rst
+++ b/Documentation/mm/damon/design.rst
@@ -382,12 +382,25 @@ can generate and submit reports of the given type. The generations and
submissions could be done automatically by the kernel or manually by the user,
depending on the type of the report.
-For now, no report type is supported.
+Below report types are supported.
+
+- ``user_report``: User-provided report. To use this, the user should set the
+ address range of the memory to report for. This type of report is not
+ automatically generated and submitted to DAMON. The user should manually
+ generate and submit each report using the interface.
The data attribute probe supports the reports. The probes can be configured to
hit for a given memory region if a specific type of valid reports that are
associated with the probing memory exist in the reports queue.
+For example, users can run DAMON in the classical page table accessed bits
+based access monitoring. In addition to that, users could find hot data that
+might not be able to found by DAMON. DAMON might not able to find that due to
+limitations in page table accessed bits or its overhead control mechanism.
+Users may be able to find that using their access to workload source code,
+experiment results or other tools. Users can complement monitoring results by
+feeding the information as user reports.
+
Dynamic Target Space Updates Handling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 26/27] Docs/admin-guide/mm/damon/usage: update for user_report report support
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (24 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 25/27] Docs/mm/damon/design: update for user report support SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:28 ` [RFC PATCH 27/27] Docs/ABI/damon: " SJ Park
2026-11-15 20:55 ` [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, Jonathan Corbet, Randy Dunlap, Shuah Khan, damon,
linux-doc, linux-kernel, linux-mm
Update DAMON usage document for the newly added user_report type data
attribute report support.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/admin-guide/mm/damon/usage.rst | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
index ce4e9e4c13276..4024dd4e92979 100644
--- a/Documentation/admin-guide/mm/damon/usage.rst
+++ b/Documentation/admin-guide/mm/damon/usage.rst
@@ -117,7 +117,7 @@ comma (",").
│ │ ...
│ reports/
│ │ producers/nr_producers
- │ │ │ 0/report_type,producer_state
+ │ │ │ 0/report_type,producer_state,addr_start,addr_end
│ │ │ ...
.. _sysfs_root:
@@ -767,6 +767,15 @@ Users can write below keywords for the producer to the file.
- ``on``: Enable the producer.
- ``off``: Disable the producer.
+- ``submit``: Generate and submit a new ``user_report`` type report, if
+ ``report_type`` is ``user_report``, and the producer is enabled.
+
+``addr_start`` and ``addr_end`` files are used only for ``user_report`` report
+type. Those set the address range of memory to manually report . Users can
+set the start and end address of the address range by writing the addresses to
+the files. Note that it is open-end range (``[addr_start,addr_end)``) and
+therefore the end address is exclusive. Reading the files shows the last
+successfully written input.
.. _tracepoint:
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* [RFC PATCH 27/27] Docs/ABI/damon: update for user_report report support
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (25 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 26/27] Docs/admin-guide/mm/damon/usage: update for user_report " SJ Park
@ 2026-11-15 20:28 ` SJ Park
2026-11-15 20:55 ` [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:28 UTC (permalink / raw)
Cc: SJ Park, damon, linux-kernel, linux-mm
Update DAMON ABI document for the newly added user_report type data
attribute report support.
Signed-off-by: SJ Park <sj@kernel.org>
---
Documentation/ABI/testing/sysfs-kernel-mm-damon | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-damon b/Documentation/ABI/testing/sysfs-kernel-mm-damon
index e558dd4212f2c..41a4ce49fbd35 100644
--- a/Documentation/ABI/testing/sysfs-kernel-mm-damon
+++ b/Documentation/ABI/testing/sysfs-kernel-mm-damon
@@ -722,3 +722,19 @@ Contact: SJ Park <sj@kernel.org>
Description: A file for requesting actions including enablement and
disablement of the producer. Refer to
Documentation/admin-guide/mm/damon/usage.rst for more details.
+
+What: /sys/kernel/mm/damon/admin/reports/producers/<P>/addr_start
+Date: Nov 2026
+Contact: SJ Park <sj@kernel.org>
+Description: Writing an integer to and reading from this file sets and gets
+ the start address of the report to manually generate and
+ submit, depending on the type of the report producer. Note
+ that the start address is inclusive.
+
+What: /sys/kernel/mm/damon/admin/reports/producers/<P>/addr_end
+Date: Nov 2026
+Contact: SJ Park <sj@kernel.org>
+Description: Writing an integer to and reading from this file sets and gets
+ the end address of the report to manually generate and submit,
+ depending on the type of the report producer. Note that the
+ end address is exclusive.
--
2.47.3
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [RFC PATCH 00/27] mm/damon: let users report their data attribute findings
2026-11-15 20:28 [RFC PATCH 00/27] mm/damon: let users report their data attribute findings SJ Park
` (26 preceding siblings ...)
2026-11-15 20:28 ` [RFC PATCH 27/27] Docs/ABI/damon: " SJ Park
@ 2026-11-15 20:55 ` SJ Park
27 siblings, 0 replies; 43+ messages in thread
From: SJ Park @ 2026-11-15 20:55 UTC (permalink / raw)
To: SJ Park
Cc: Andrew Morton, Jonathan Corbet, Randy Dunlap, Shuah Khan,
Shuah Khan, damon, linux-doc, linux-kernel, linux-kselftest,
linux-mm
On Sun, 15 Nov 2026 12:28:18 -0800 SJ Park <sj@kernel.org> wrote:
> TL;DR
> =====
>
> Build a system for letting DAMON-external entities report their data
> attribute findings to DAMON. Let users report their data attribute
> findings to DAMON using the report system.
>
[...]
> Ongoing and Future Works
> ========================
>
> This is a part of the "beyond page table accessed-bit DAMON extension"
> project milestone 2. This patch series provides the initial and
> essential part of the data attribute report system.
I forgot adding a link for the project. Please refer to this thread [1] for
more details, plans and status of the project.
[1] https://lore.kernel.org/20260525225208.1179-1-sj@kernel.org
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 43+ messages in thread