* [RFC PATCH 1/8] mm/damon/core: safely validate src on damon_commit_ctx()
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 2/8] mm/damon/core: do parameter testing commit on damon_start() SJ Park
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_commit_ctx() does its holistic parameter set validation while
applying the new parameter in the set one by one. If it finds a
parameter is invalid, because some invalid parameters may already be
committed (it is called "commit" but not atomic and irreversable), it
stops the running DAMON context.
The callers of the function therefore have to validate the parameters
before calling it. Because the function already embeds holistic
validation, DAMON_SYSFS reuses it in a safe way. It creates a
test-purpose context that is not running but mimics the running one, and
calls damon_commit_ctx() against the test purpose context. If it
succeeds, the parameters are considered valid, and a real
damon_commit_ctx() call against the running context is made with those.
Other callers such as DAMON_RECLAIM and DAMON_LRU_SORT do not expose
full parameters to users. For efficiency, they validate only the known
set of parameters. The efficiency gain is arguably small and doubtful,
though. Meanwhile the maintenance overhead of the multiple different
validations is clearly high. We actually found and fixed a few bugs in
the class.
Update damon_commit_ctx() to embed DAMON_SYSFS' safe and holistic
validation approach. Callers can simply call damon_commit_ctx() without
worrying if their parameters are invalid.
Note that damon_commit_ctx() can still cause an unexpected stop of the
running context, if internal memory allocation fails. It is arguably
unlikely since those internal allocations are too small to fail, but
theoretically possible. It should also be better addressed, but not
necessarily a blocker of this small and incremental improvement effort.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 61 +++++++++++++++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 14 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 871c6f5257c9e..62c27002219cd 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1664,20 +1664,7 @@ static int damon_commit_probes(struct damon_ctx *dst, struct damon_ctx *src)
return 0;
}
-/**
- * damon_commit_ctx() - Commit parameters of a DAMON context to another.
- * @dst: The commit destination DAMON context.
- * @src: The commit source DAMON context.
- *
- * This function copies user-specified parameters from @src to @dst and update
- * the internal status and results accordingly. Users should use this function
- * for context-level parameters update of running context, instead of manual
- * in-place updates.
- *
- * This function should be called from parameters-update safe context, like
- * damon_call().
- */
-int damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src)
+static int __damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src)
{
int err;
struct damos *scheme;
@@ -1732,6 +1719,52 @@ int damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src)
return 0;
}
+static struct damon_ctx *damon_new_test_ctx(struct damon_ctx *dst)
+{
+ struct damon_ctx *test_ctx;
+ int err;
+
+ test_ctx = damon_new_ctx();
+ if (!test_ctx)
+ return NULL;
+ err = __damon_commit_ctx(test_ctx, dst);
+ if (err) {
+ damon_destroy_ctx(test_ctx);
+ return NULL;
+ }
+ return test_ctx;
+}
+
+/**
+ * damon_commit_ctx() - Commit parameters of a DAMON context to another.
+ * @dst: The commit destination DAMON context.
+ * @src: The commit source DAMON context.
+ *
+ * This function copies user-specified parameters from @src to @dst and update
+ * the internal status and results accordingly. Users should use this function
+ * for context-level parameters update of running context, instead of manual
+ * in-place updates.
+ *
+ * This function should be called from parameters-update safe context, like
+ * damon_call().
+ */
+int damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src)
+{
+ struct damon_ctx *test_ctx;
+ int err;
+
+ test_ctx = damon_new_test_ctx(dst);
+ if (!test_ctx)
+ return -ENOMEM;
+ err = __damon_commit_ctx(test_ctx, dst);
+ if (err)
+ goto out;
+ err = __damon_commit_ctx(dst, src);
+out:
+ damon_destroy_ctx(test_ctx);
+ return err;
+}
+
/**
* damon_nr_running_ctxs() - Return number of currently running contexts.
*/
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 2/8] mm/damon/core: do parameter testing commit on damon_start()
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
2026-07-01 14:48 ` [RFC PATCH 1/8] mm/damon/core: safely validate src on damon_commit_ctx() SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 3/8] mm/damon/sysfs: remove duplicated commit input validity check SJ Park
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_start() and damon_commit_ctx() are two main DAMON core API
functions for setting whole DAMON parameters. While damon_commit_ctx()
does holistic parameters testing, damon_start() just believes the caller
validated the whole thing. Embed the holistic parameter check that is
already in damon_commit_ctx() into damon_start(). After this change,
the callers can safely call damon_start() without validating the
parameters.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 62c27002219cd..6b30cb6007e54 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1865,6 +1865,8 @@ static int __damon_start(struct damon_ctx *ctx)
return err;
}
+static int __damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src);
+
/**
* damon_start() - Starts the monitorings for a given group of contexts.
* @ctxs: an array of the pointers for contexts to start monitoring
@@ -1882,13 +1884,22 @@ static int __damon_start(struct damon_ctx *ctx)
*/
int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive)
{
+ struct damon_ctx *test_ctx;
int i;
int err = 0;
+ test_ctx = damon_new_ctx();
+ if (!test_ctx)
+ return -ENOMEM;
+
for (i = 0; i < nr_ctxs; i++) {
- if (!is_power_of_2(ctxs[i]->min_region_sz))
- return -EINVAL;
+ err = __damon_commit_ctx(test_ctx, ctxs[i]);
+ if (err) {
+ damon_destroy_ctx(test_ctx);
+ return err;
+ }
}
+ damon_destroy_ctx(test_ctx);
mutex_lock(&damon_lock);
if ((exclusive && nr_running_ctxs) ||
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 3/8] mm/damon/sysfs: remove duplicated commit input validity check
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
2026-07-01 14:48 ` [RFC PATCH 1/8] mm/damon/core: safely validate src on damon_commit_ctx() SJ Park
2026-07-01 14:48 ` [RFC PATCH 2/8] mm/damon/core: do parameter testing commit on damon_start() SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 4/8] mm/damon/reclaim: remove duplicated min_region_sz power of 2 check SJ Park
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
DAMON sysfs interface does parameters validation-purpose
damon_commit_ctx() calls for parameters update. Now the same logic is
embedded inside damon_commit_ctx() itself. Hence, the validation in
DAMON sysfs interface is just an unnecessary duplicate. Remove it.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 32 +-------------------------------
1 file changed, 1 insertion(+), 31 deletions(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 6710b6d019bf5..e666dddf1feba 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -2098,26 +2098,6 @@ static int damon_sysfs_apply_inputs(struct damon_ctx *ctx,
static struct damon_ctx *damon_sysfs_build_ctx(
struct damon_sysfs_context *sys_ctx);
-/*
- * Return a new damon_ctx for testing new parameters to commit.
- */
-static struct damon_ctx *damon_sysfs_new_test_ctx(
- struct damon_ctx *running_ctx)
-{
- struct damon_ctx *test_ctx;
- int err;
-
- test_ctx = damon_new_ctx();
- if (!test_ctx)
- return NULL;
- err = damon_commit_ctx(test_ctx, running_ctx);
- if (err) {
- damon_destroy_ctx(test_ctx);
- return NULL;
- }
- return test_ctx;
-}
-
/*
* damon_sysfs_commit_input() - Commit user inputs to a running kdamond.
* @kdamond: The kobject wrapper for the associated kdamond.
@@ -2127,7 +2107,7 @@ static struct damon_ctx *damon_sysfs_new_test_ctx(
static int damon_sysfs_commit_input(void *data)
{
struct damon_sysfs_kdamond *kdamond = data;
- struct damon_ctx *param_ctx, *test_ctx;
+ struct damon_ctx *param_ctx;
int err;
if (!damon_sysfs_kdamond_running(kdamond))
@@ -2139,17 +2119,7 @@ static int damon_sysfs_commit_input(void *data)
param_ctx = damon_sysfs_build_ctx(kdamond->contexts->contexts_arr[0]);
if (IS_ERR(param_ctx))
return PTR_ERR(param_ctx);
- test_ctx = damon_sysfs_new_test_ctx(kdamond->damon_ctx);
- if (!test_ctx) {
- damon_destroy_ctx(param_ctx);
- return -ENOMEM;
- }
- err = damon_commit_ctx(test_ctx, param_ctx);
- if (err)
- goto out;
err = damon_commit_ctx(kdamond->damon_ctx, param_ctx);
-out:
- damon_destroy_ctx(test_ctx);
damon_destroy_ctx(param_ctx);
return err;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 4/8] mm/damon/reclaim: remove duplicated min_region_sz power of 2 check
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
` (2 preceding siblings ...)
2026-07-01 14:48 ` [RFC PATCH 3/8] mm/damon/sysfs: remove duplicated commit input validity check SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 5/8] mm/damon/lru_sort: remove duplicated min_region_sz power_of_2() check SJ Park
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
DAMON_RECLAIM validates the user input for min_region_sz. The same
validation is done inside damon_start() and damon_commit_ctx(). Remove
the duplicate.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/reclaim.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
index 11b70d0a9a6f0..6469b25cc34f9 100644
--- a/mm/damon/reclaim.c
+++ b/mm/damon/reclaim.c
@@ -208,11 +208,6 @@ static int damon_reclaim_apply_parameters(void)
param_ctx->addr_unit = addr_unit;
param_ctx->min_region_sz = max(DAMON_MIN_REGION_SZ / addr_unit, 1);
- if (!is_power_of_2(param_ctx->min_region_sz)) {
- err = -EINVAL;
- goto out;
- }
-
if (!damon_reclaim_mon_attrs.aggr_interval) {
err = -EINVAL;
goto out;
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 5/8] mm/damon/lru_sort: remove duplicated min_region_sz power_of_2() check
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
` (3 preceding siblings ...)
2026-07-01 14:48 ` [RFC PATCH 4/8] mm/damon/reclaim: remove duplicated min_region_sz power of 2 check SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 6/8] mm/damon: document region size validation in damon_set_regions() SJ Park
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
DAMON_LRU_SORT validates the user input for min_region_sz. The same
validation is done inside damon_start() and damon_commit_ctx(). Remove
the unnecessary duplicate.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/lru_sort.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
index 32f41491b726b..2dd0cd0d26273 100644
--- a/mm/damon/lru_sort.c
+++ b/mm/damon/lru_sort.c
@@ -284,11 +284,6 @@ static int damon_lru_sort_apply_parameters(void)
param_ctx->addr_unit = addr_unit;
param_ctx->min_region_sz = max(DAMON_MIN_REGION_SZ / addr_unit, 1);
- if (!is_power_of_2(param_ctx->min_region_sz)) {
- err = -EINVAL;
- goto out;
- }
-
if (!damon_lru_sort_mon_attrs.sample_interval) {
err = -EINVAL;
goto out;
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 6/8] mm/damon: document region size validation in damon_set_regions()
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
` (4 preceding siblings ...)
2026-07-01 14:48 ` [RFC PATCH 5/8] mm/damon/lru_sort: remove duplicated min_region_sz power_of_2() check SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 7/8] mm/damon/core: remove start, end check in damon_set_region_system_rams() SJ Park
2026-07-01 14:48 ` [RFC PATCH 8/8] mm/damon/sysfs: remove region size validation SJ Park
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, damon, linux-kernel, linux-mm
The kernel doc comment of damon_region clearly specifies every region
should have positive size. But it is unclear who should verify it.
damon_set_regions() is the recommended DAMON core function for setting
regions from the callers, and has the verification. Update the comment
to clarify the callers should be ok to pass any values for region
addresses, as long as they use damon_set_regions().
Signed-off-by: SJ Park <sj@kernel.org>
---
include/linux/damon.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 616bdf0954b52..2661231c0ae82 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -49,7 +49,8 @@ struct damon_size_range {
* @list: List head for siblings.
* @age: Age of this region.
*
- * For any use case, @ar should be non-zero positive size.
+ * For any use case, @ar should be non-zero positive size. damon_set_regions()
+ * does the validation.
*
* @nr_accesses is reset to zero for every &damon_attrs->aggr_interval and be
* increased for every &damon_attrs->sample_interval if an access to the region
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 7/8] mm/damon/core: remove start, end check in damon_set_region_system_rams()
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
` (5 preceding siblings ...)
2026-07-01 14:48 ` [RFC PATCH 6/8] mm/damon: document region size validation in damon_set_regions() SJ Park
@ 2026-07-01 14:48 ` SJ Park
2026-07-01 14:48 ` [RFC PATCH 8/8] mm/damon/sysfs: remove region size validation SJ Park
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_set_region_system_rams() validates user inputs to avoid creating a
negative size region. But DAMON core avoids zero size, too. The check
is incomplete. The complete check is done inside damon_set_regions(),
which is eventually called from damon_set_region_system_rams_default().
Drop the incomplete and unnecessary check.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 6b30cb6007e54..3caf1b67a7f98 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -3847,9 +3847,6 @@ int damon_set_region_system_rams_default(struct damon_target *t,
{
struct damon_addr_range addr_range;
- if (*start > *end)
- return -EINVAL;
-
if (!*start && !*end &&
!damon_find_system_rams_range(start, end, addr_unit))
return -EINVAL;
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [RFC PATCH 8/8] mm/damon/sysfs: remove region size validation
2026-07-01 14:48 [RFC PATCH 0/8] mm/damon: validate all parameters in the core SJ Park
` (6 preceding siblings ...)
2026-07-01 14:48 ` [RFC PATCH 7/8] mm/damon/core: remove start, end check in damon_set_region_system_rams() SJ Park
@ 2026-07-01 14:48 ` SJ Park
7 siblings, 0 replies; 9+ messages in thread
From: SJ Park @ 2026-07-01 14:48 UTC (permalink / raw)
Cc: SJ Park, Andrew Morton, damon, linux-kernel, linux-mm
DAMON_SYSFS validates user inputs for monitoring target regions to
disallow negative size regions. DAMON core assumes only positive size
regions, though. The validation is incomplete. Fortunately
damon_set_regions(), which is eventually used by DAMON_SYSFS, does the
complete validation. Remove the incomplete and unnecessary validation.
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/sysfs.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index e666dddf1feba..b65651498e0d1 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -1987,9 +1987,6 @@ static int damon_sysfs_set_regions(struct damon_target *t,
struct damon_sysfs_region *sys_region =
sysfs_regions->regions_arr[i];
- if (sys_region->ar.start > sys_region->ar.end)
- goto out;
-
ranges[i].start = sys_region->ar.start;
ranges[i].end = sys_region->ar.end;
if (i == 0)
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread