Add a KUnit test to verify that damos_walk() rejects
new requests when walk_control_obsolete is set.
Commit 33c3f6c2b48c ("mm/damon/core: fix damos_walk() vs
kdamond_fn() exit race") introduced walk_control_obsolete
to prevent a race condition where new requests could be
registered during kdamond shutdown and never handled.
This test simulates the shutdown condition by setting
walk_control_obsolete and verifies that damos_walk()
returns -ECANCELED immediately.
This validates the invariant introduced by the fix and
helps prevent regressions.
Suggested-by: SeongJae Park <[email protected]>
Signed-off-by: Sailesh Nandanavanam <[email protected]>
---
Changes since v2
(https://lore.kernel.org/[email protected]):
- Dropped the userspace selftest approach entirely. SeongJae tested
v2 100 times on a kernel with the fix reverted and it always
passed, confirming the microsecond-wide race window cannot be
reliably hit from userspace due to syscall overhead.
- Added a KUnit test for damos_walk() + walk_control_obsolete
instead, as suggested by SeongJae. This directly sets the
obsolete flag and verifies damos_walk() returns -ECANCELED
immediately, without timing dependency.
Changes since v1
(https://lore.kernel.org/[email protected]):
- Addressed sashiko bot review comments (execute bit, threading,
dynamic sysfs path, OSError handling) - superseded by the v3
approach above.
mm/damon/tests/core-kunit.h | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index 9e5904c2beeb..599aac056b73 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -1336,6 +1336,33 @@ static void damon_test_is_last_region(struct kunit *test)
damon_free_target(t);
}
+/*
+ * Verify that damos_walk() rejects new requests when
+ * walk_control_obsolete is set.
+ *
+ * This tests the invariant introduced by:
+ * commit 33c3f6c2b48c ("mm/damon/core: fix damos_walk() vs kdamond_fn() exit
race")
+ */
+static void damon_test_walk_control_obsolete(struct kunit *test)
+{
+ struct damon_ctx *ctx;
+ struct damos_walk_control control = {};
+ int ret;
+
+ ctx = damon_new_ctx();
+ if (!ctx)
+ kunit_skip(test, "ctx alloc fail");
+
+ /* Simulate shutdown phase */
+ ctx->walk_control_obsolete = true;
+
+ ret = damos_walk(ctx, &control);
+
+ KUNIT_EXPECT_EQ(test, ret, -ECANCELED);
+
+ damon_destroy_ctx(ctx);
+}
+
static struct kunit_case damon_test_cases[] = {
KUNIT_CASE(damon_test_target),
KUNIT_CASE(damon_test_regions),
@@ -1365,6 +1392,7 @@ static struct kunit_case damon_test_cases[] = {
KUNIT_CASE(damon_test_set_filters_default_reject),
KUNIT_CASE(damon_test_apply_min_nr_regions),
KUNIT_CASE(damon_test_is_last_region),
+ KUNIT_CASE(damon_test_walk_control_obsolete),
{},
};
--
2.34.1