From: Jason Angelov <[email protected]>

damon_valid_probe_params() makes damon_commit_ctx() reject probe
configurations that could overflow a probe_hits counter, a single
(weight * probe_hits) product, or the sum of those products.

Add a kunit test covering each rejection at its boundary:

- samples per aggregation interval: U8_MAX is allowed, one more could
  overflow a probe_hits counter
- single weight: the largest whose product fits in unsigned int is
  allowed, one larger is rejected
- multiple probes: each product fits, but their sum overflows
- no weight set: the validation is skipped

Signed-off-by: Jason Angelov <[email protected]>
Reviewed-by: SJ Park <[email protected]>
Signed-off-by: SJ Park <[email protected]>
---
 mm/damon/tests/core-kunit.h | 57 +++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index 68591ca99a4f7..af26b3d60957b 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -1341,6 +1341,62 @@ static void damon_test_commit_ctx(struct kunit *test)
        damon_destroy_ctx(dst);
 }
 
+static void damon_test_valid_probe_params(struct kunit *test)
+{
+       struct damon_ctx *ctx;
+       struct damon_probe *probe, *probe2;
+
+       ctx = damon_new_ctx();
+       if (!ctx)
+               kunit_skip(test, "ctx alloc fail");
+       probe = damon_new_probe();
+       if (!probe) {
+               damon_destroy_ctx(ctx);
+               kunit_skip(test, "probe alloc fail");
+       }
+       damon_add_probe(ctx, probe);
+
+       /* Parameters are validated only if any probe weight is set. */
+       ctx->attrs.sample_interval = 1;
+       ctx->attrs.aggr_interval = 1000000;
+       KUNIT_EXPECT_TRUE(test, damon_valid_probe_params(ctx));
+
+       /* Up to U8_MAX samples per aggregation interval are allowed. */
+       probe->weight = 100;
+       ctx->attrs.aggr_interval = 255;
+       KUNIT_EXPECT_TRUE(test, damon_valid_probe_params(ctx));
+
+       /* More samples could overflow the probe_hits counters. */
+       ctx->attrs.aggr_interval = 256;
+       KUNIT_EXPECT_FALSE(test, damon_valid_probe_params(ctx));
+
+       /* The largest weight whose weighted hit count fits in unsigned int. */
+       ctx->attrs.aggr_interval = 255;
+       probe->weight = UINT_MAX / 255;
+       KUNIT_EXPECT_TRUE(test, damon_valid_probe_params(ctx));
+
+       /* Any larger weight could overflow its weighted hit count. */
+       probe->weight = UINT_MAX / 255 + 1;
+       KUNIT_EXPECT_FALSE(test, damon_valid_probe_params(ctx));
+
+       /* With one sample per aggregation, even the largest weight fits. */
+       ctx->attrs.aggr_interval = 1;
+       probe->weight = UINT_MAX;
+       KUNIT_EXPECT_TRUE(test, damon_valid_probe_params(ctx));
+
+       /* The sum of all probes' weighted hit counts could also overflow. */
+       probe2 = damon_new_probe();
+       if (!probe2) {
+               damon_destroy_ctx(ctx);
+               kunit_skip(test, "probe2 alloc fail");
+       }
+       probe2->weight = 1;
+       damon_add_probe(ctx, probe2);
+       KUNIT_EXPECT_FALSE(test, damon_valid_probe_params(ctx));
+
+       damon_destroy_ctx(ctx);
+}
+
 static void damos_test_filter_out(struct kunit *test)
 {
        struct damon_target *t;
@@ -1667,6 +1723,7 @@ static struct kunit_case damon_test_cases[] = {
        KUNIT_CASE(damos_test_commit_migrate_hot),
        KUNIT_CASE(damon_test_commit_target_regions),
        KUNIT_CASE(damon_test_commit_ctx),
+       KUNIT_CASE(damon_test_valid_probe_params),
        KUNIT_CASE(damos_test_filter_out),
        KUNIT_CASE(damon_test_feed_loop_next_input),
        KUNIT_CASE(damon_test_set_filters_default_reject),
-- 
2.47.3

Reply via email to