* [RFC PATCH v2 01/10] mm/damon: add CONFIG_DAMON_DEBUG_SANITY
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 02/10] mm/damon/core: add damon_new_region() debug_sanity check SeongJae Park
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
Add a new build config that will enable additional DAMON sanity checks.
It is recommended to be enabled on only development and test setups,
since it can impose additional overhead.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/Kconfig | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/mm/damon/Kconfig b/mm/damon/Kconfig
index 8c868f7035fce..34631a44cdecb 100644
--- a/mm/damon/Kconfig
+++ b/mm/damon/Kconfig
@@ -12,6 +12,17 @@ config DAMON
See https://www.kernel.org/doc/html/latest/mm/damon/index.html for
more information.
+config DAMON_DEBUG_SANITY
+ bool "Check sanity of DAMON code"
+ depends on DAMON
+ help
+ This enables additional DAMON debugging-purpose sanity checks in
+ DAMON code. This can be useful for finding bugs, but impose
+ additional overhead. This is therefore recommended to be enabled on
+ only development and test setups.
+
+ If unsure, say N.
+
config DAMON_KUNIT_TEST
bool "Test for damon" if !KUNIT_ALL_TESTS
depends on DAMON && KUNIT=y
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 02/10] mm/damon/core: add damon_new_region() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 01/10] mm/damon: add CONFIG_DAMON_DEBUG_SANITY SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 03/10] mm/damon/core: add damon_del_region() " SeongJae Park
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_new_region() is supposed to be called with only valid address
range arguments. Do the check under DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index f1a97e85824ac..0c1353164ec81 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -109,6 +109,17 @@ int damon_select_ops(struct damon_ctx *ctx, enum damon_ops_id id)
return err;
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_new_region(unsigned long start, unsigned long end)
+{
+ WARN_ONCE(start >= end, "start %lu >= end %lu\n", start, end);
+}
+#else
+static void damon_verify_new_region(unsigned long start, unsigned long end)
+{
+}
+#endif
+
/*
* Construct a damon_region struct
*
@@ -118,6 +129,7 @@ struct damon_region *damon_new_region(unsigned long start, unsigned long end)
{
struct damon_region *region;
+ damon_verify_new_region(start, end);
region = kmem_cache_alloc(damon_region_cache, GFP_KERNEL);
if (!region)
return NULL;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 03/10] mm/damon/core: add damon_del_region() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 01/10] mm/damon: add CONFIG_DAMON_DEBUG_SANITY SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 02/10] mm/damon/core: add damon_new_region() debug_sanity check SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 04/10] mm/damon/core: add damon_nr_regions() " SeongJae Park
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_del_region() should be called for targets that have one or more
regions. Add a sanity check for that under CONFIG_DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 0c1353164ec81..92eac5eb96026 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -152,8 +152,21 @@ void damon_add_region(struct damon_region *r, struct damon_target *t)
t->nr_regions++;
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_del_region(struct damon_target *t)
+{
+ WARN_ONCE(t->nr_regions == 0, "t->nr_regions == 0\n");
+}
+#else
+static void damon_verify_del_region(struct damon_target *t)
+{
+}
+#endif
+
static void damon_del_region(struct damon_region *r, struct damon_target *t)
{
+ damon_verify_del_region(t);
+
list_del(&r->list);
t->nr_regions--;
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 04/10] mm/damon/core: add damon_nr_regions() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (2 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 03/10] mm/damon/core: add damon_del_region() " SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 05/10] mm/damon/core: add damon_merge_two_regions() " SeongJae Park
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_target->nr_regions is introduced to get the number quickly without
having to iterate regions always. Add a sanity check for that under
CONFIG_DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 92eac5eb96026..2b5aed89d449d 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -545,8 +545,27 @@ void damon_destroy_target(struct damon_target *t, struct damon_ctx *ctx)
damon_free_target(t);
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_nr_regions(struct damon_target *t)
+{
+ struct damon_region *r;
+ unsigned int count = 0;
+
+ damon_for_each_region(r, t)
+ count++;
+ WARN_ONCE(count != t->nr_regions, "t->nr_regions (%u) != count (%u)\n",
+ t->nr_regions, count);
+}
+#else
+static void damon_verify_nr_regions(struct damon_target *t)
+{
+}
+#endif
+
unsigned int damon_nr_regions(struct damon_target *t)
{
+ damon_verify_nr_regions(t);
+
return t->nr_regions;
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 05/10] mm/damon/core: add damon_merge_two_regions() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (3 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 04/10] mm/damon/core: add damon_nr_regions() " SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 06/10] mm/damon/core: add damon_merge_regions_of() " SeongJae Park
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
A data corruption could cause damon_merge_two_regions() creating zero
length DAMON regions. Add a sanity check for that under
CONFIG_DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 2b5aed89d449d..8a3738a17cdd9 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2473,6 +2473,21 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
mutex_unlock(&c->walk_control_lock);
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_merge_two_regions(
+ struct damon_region *l, struct damon_region *r)
+{
+ /* damon_merge_two_regions() may created incorrect left region */
+ WARN_ONCE(l->ar.start >= l->ar.end, "l: %lu-%lu, r: %lu-%lu\n",
+ l->ar.start, l->ar.end, r->ar.start, r->ar.end);
+}
+#else
+static void damon_verify_merge_two_regions(
+ struct damon_region *l, struct damon_region *r)
+{
+}
+#endif
+
/*
* Merge two adjacent regions into one region
*/
@@ -2486,6 +2501,7 @@ static void damon_merge_two_regions(struct damon_target *t,
l->nr_accesses_bp = l->nr_accesses * 10000;
l->age = (l->age * sz_l + r->age * sz_r) / (sz_l + sz_r);
l->ar.end = r->ar.end;
+ damon_verify_merge_two_regions(l, r);
damon_destroy_region(r, t);
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 06/10] mm/damon/core: add damon_merge_regions_of() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (4 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 05/10] mm/damon/core: add damon_merge_two_regions() " SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 07/10] mm/damon/core: add damon_split_region_at() " SeongJae Park
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_merge_regions_of() should be called only after aggregation is
finished and therefore each region's nr_accesses and nr_accesses_bp
match. There were bugs that broke the assumption, during development of
online DAMON parameter updates and monitoring results handling changes.
Add a sanity check for that under CONFIG_DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 8a3738a17cdd9..93d1577b1ae07 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2505,6 +2505,20 @@ static void damon_merge_two_regions(struct damon_target *t,
damon_destroy_region(r, t);
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_merge_regions_of(struct damon_region *r)
+{
+ WARN_ONCE(r->nr_accesses != r->nr_accesses_bp / 10000,
+ "nr_accesses (%u) != nr_accesses_bp (%u)\n",
+ r->nr_accesses, r->nr_accesses_bp);
+}
+#else
+static void damon_verify_merge_regions_of(struct damon_region *r)
+{
+}
+#endif
+
+
/*
* Merge adjacent regions having similar access frequencies
*
@@ -2518,6 +2532,7 @@ static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
struct damon_region *r, *prev = NULL, *next;
damon_for_each_region_safe(r, next, t) {
+ damon_verify_merge_regions_of(r);
if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
r->age = 0;
else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 07/10] mm/damon/core: add damon_split_region_at() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (5 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 06/10] mm/damon/core: add damon_merge_regions_of() " SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 08/10] mm/damon/core: add damon_reset_aggregated() " SeongJae Park
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
damon_split_region_at() should be called with the correct address to
split on. Add a sanity check for that under CONFIG_DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 93d1577b1ae07..be2300cf3aeae 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2586,6 +2586,21 @@ static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
threshold / 2 < max_thres);
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_split_region_at(struct damon_region *r,
+ unsigned long sz_r)
+{
+ WARN_ONCE(sz_r == 0 || sz_r >= damon_sz_region(r),
+ "sz_r: %lu r: %lu-%lu (%lu)\n",
+ sz_r, r->ar.start, r->ar.end, damon_sz_region(r));
+}
+#else
+static void damon_verify_split_region_at(struct damon_region *r,
+ unsigned long sz_r)
+{
+}
+#endif
+
/*
* Split a region in two
*
@@ -2597,6 +2612,7 @@ static void damon_split_region_at(struct damon_target *t,
{
struct damon_region *new;
+ damon_verify_split_region_at(r, sz_r);
new = damon_new_region(r->ar.start + sz_r, r->ar.end);
if (!new)
return;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 08/10] mm/damon/core: add damon_reset_aggregated() debug_sanity check
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (6 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 07/10] mm/damon/core: add damon_split_region_at() " SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 09/10] mm/damon/tests/.kunitconifg: enable DAMON_DEBUG_SANITY SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 10/10] selftests/damon/config: " SeongJae Park
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, damon, linux-kernel, linux-mm
At time of damon_reset_aggregated(), aggregation of the interval should
be completed, and hence nr_accesses and nr_accesses_bp should match. I
found a few bugs caused it to be broken in the past, from online
parameters update and complicated nr_accesses handling changes. Add a
sanity check for that under CONFIG_DAMON_DEBUG_SANITY.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index be2300cf3aeae..e8c44541754f7 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -1666,6 +1666,23 @@ static void damon_warn_fix_nr_accesses_corruption(struct damon_region *r)
r->nr_accesses_bp = r->nr_accesses * 10000;
}
+#ifdef CONFIG_DAMON_DEBUG_SANITY
+static void damon_verify_reset_aggregated(struct damon_region *r,
+ struct damon_ctx *c)
+{
+ WARN_ONCE(r->nr_accesses_bp != r->last_nr_accesses * 10000,
+ "nr_accesses_bp %u last_nr_accesses %u sis %lu %lu\n",
+ r->nr_accesses_bp, r->last_nr_accesses,
+ c->passed_sample_intervals, c->next_aggregation_sis);
+}
+#else
+static void damon_verify_reset_aggregated(struct damon_region *r,
+ struct damon_ctx *c)
+{
+}
+#endif
+
+
/*
* Reset the aggregated monitoring results ('nr_accesses' of each region).
*/
@@ -1682,6 +1699,7 @@ static void kdamond_reset_aggregated(struct damon_ctx *c)
damon_warn_fix_nr_accesses_corruption(r);
r->last_nr_accesses = r->nr_accesses;
r->nr_accesses = 0;
+ damon_verify_reset_aggregated(r, c);
}
ti++;
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 09/10] mm/damon/tests/.kunitconifg: enable DAMON_DEBUG_SANITY
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (7 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 08/10] mm/damon/core: add damon_reset_aggregated() " SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
2026-03-01 17:43 ` [RFC PATCH v2 10/10] selftests/damon/config: " SeongJae Park
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Andrew Morton, Brendan Higgins, David Gow, damon,
kunit-dev, linux-kernel, linux-kselftest, linux-mm
CONFIG_DAMON_DEBUG_SANITY is recommended for DAMON development and test
setups. Enable it on the default configurations for DAMON kunit test
run.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/tests/.kunitconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mm/damon/tests/.kunitconfig b/mm/damon/tests/.kunitconfig
index 36a450f57b581..144d27e6ecc5c 100644
--- a/mm/damon/tests/.kunitconfig
+++ b/mm/damon/tests/.kunitconfig
@@ -13,3 +13,6 @@ CONFIG_DAMON_VADDR_KUNIT_TEST=y
CONFIG_SYSFS=y
CONFIG_DAMON_SYSFS=y
CONFIG_DAMON_SYSFS_KUNIT_TEST=y
+
+# enable DAMON_DEBUG_SANITY to catch any bug
+CONFIG_DAMON_DEBUG_SANITY=y
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread* [RFC PATCH v2 10/10] selftests/damon/config: enable DAMON_DEBUG_SANITY
2026-03-01 17:43 [RFC PATCH v2 00/10] mm/damon: add optional debugging-purpose sanity checks SeongJae Park
` (8 preceding siblings ...)
2026-03-01 17:43 ` [RFC PATCH v2 09/10] mm/damon/tests/.kunitconifg: enable DAMON_DEBUG_SANITY SeongJae Park
@ 2026-03-01 17:43 ` SeongJae Park
9 siblings, 0 replies; 11+ messages in thread
From: SeongJae Park @ 2026-03-01 17:43 UTC (permalink / raw)
Cc: SeongJae Park, Shuah Khan, damon, linux-kernel, linux-kselftest,
linux-mm
CONFIG_DAMON_DEBUG_SANITY is recommended for DAMON development and test
setups. Enable it on the build config for DAMON selftests.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
tools/testing/selftests/damon/config | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/damon/config b/tools/testing/selftests/damon/config
index a68a9fead5dca..6304adacb741c 100644
--- a/tools/testing/selftests/damon/config
+++ b/tools/testing/selftests/damon/config
@@ -4,3 +4,4 @@ CONFIG_DAMON_PADDR=y
CONFIG_DAMON_VADDR=y
CONFIG_DAMON_RECLAIM=y
CONFIG_DAMON_LRU_SORT=y
+CONFIG_DAMON_DEBUG_SANITY=y
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread