From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD719480DFC; Tue, 13 Oct 2026 04:34:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791866047; cv=none; b=KaVNeMQHnTcKDShgesqac0GFb2FZgqDiNMTuCJNTMXqyJaFdArIOrNkzBSMjPUnutcJzqNGPDpXg+LdLEj9FoUWhxJIpJwP0OGBcSDkZvzrApgTLt+DWRknl1RnuHu4Y4onKqmju1PNidgHzXxGBszhi/s6VkWE9MrDB1VLyGzs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791866047; c=relaxed/simple; bh=/LsfFf31Wyh9+HCRVsJK+wxS04EyLnW1Hhwk0ars4xo=; h=Date:To:From:Subject:Message-Id; b=Vb7i/622TJoQWBmMlBMjgCf0evxFwhb+wwDmwwe+RTwKBhzbX7+/spoy91n6R3JDJuGZ+JbHtHlyW5uedWlkHWdnMc7hCENiPzWE1MEbmZhFzx5/r8HSSV9W9NnderpUD45J9uMIo/iTgGVRBCFxhEYGcQKopCHZKZKMl1TM8es= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b=aNwNSWqJ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b="aNwNSWqJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82CC21F000FF; Tue, 13 Oct 2026 04:34:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux-foundation.org; s=korg; t=1791866045; bh=tBKZlXi5m2zhmAHVcd9gx5m0TeXnjbXVE59dVEz75Eo=; h=Date:To:From:Subject; b=aNwNSWqJ3opXcXAddaNpoFIDGnRZXSJEXGRZvkIsywiRGr8AgKBXTqO7zPtGOqO4z qL/jerdxAcfBLl+gxrJSLa89LjZ/e4WS1JqQlaSHQ8RE7TEEXUsd8wk4fbjT1KJbw3 v1Dt7HOX2K2tA5KzuQmEEOCH3vFh2Xei0jtdu9gc= Date: Mon, 12 Oct 2026 21:34:05 -0700 To: mm-commits@vger.kernel.org,stable@vger.kernel.org,sj@kernel.org,david@davidgow.net,brendan.higgins@linux.dev,donggeunyoo.kernel@gmail.com,akpm@linux-foundation.org From: Andrew Morton Subject: [merged mm-stable] mm-damon-tests-core-kunit-test-the-size-charged-for-a-filter-trimmed-region.patch removed from -mm tree Message-Id: <20261013043405.82CC21F000FF@smtp.kernel.org> Precedence: bulk X-Mailing-List: mm-commits@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: The quilt patch titled Subject: mm/damon/tests/core-kunit: test the size charged for a filter-trimmed region has been removed from the -mm tree. Its filename was mm-damon-tests-core-kunit-test-the-size-charged-for-a-filter-trimmed-region.patch This patch was dropped because it was merged into the mm-stable branch of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm ------------------------------------------------------ From: Donggeun Yoo Subject: mm/damon/tests/core-kunit: test the size charged for a filter-trimmed region Date: Mon, 21 Sep 2026 08:24:42 -0700 damos_test_filter_out() checks that an address range filter splits a region at the filter boundary, and stops there. Nothing checks what damos_apply_scheme() then charges to the quota and reports as tried. damos_test_apply_scheme_filtered_sz() covers the two ways such a filter trims a region: one that starts before the filter's range, and one that starts inside it. damos_test_apply_scheme_filter_sz_unchanged() and damos_test_apply_scheme_quota_sz() cover the cases whose accounting must not change: a region wholly inside a reject range, one wholly inside an allow range, two filters trimming in a single call, a filter type that never splits, no filter at all, a region the quota trims, and a quota remainder too small for one region. Link: https://lore.kernel.org/20260921152443.80132-3-sj@kernel.org Signed-off-by: Donggeun Yoo Signed-off-by: SJ Park Signed-off-by: Andrew Morton Reviewed-by: SJ Park Cc: Brendan Higgins Cc: David Gow Cc: --- mm/damon/tests/core-kunit.h | 316 ++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) --- a/mm/damon/tests/core-kunit.h~mm-damon-tests-core-kunit-test-the-size-charged-for-a-filter-trimmed-region +++ a/mm/damon/tests/core-kunit.h @@ -1706,6 +1706,319 @@ out: damos_free_filter(f); } +static unsigned long damos_test_apply_scheme_stub(struct damon_ctx *c, + struct damon_target *t, struct damon_region *r, + struct damos *s, unsigned long *sz_filter_passed) +{ + return 0; +} + +static void damos_test_apply_scheme_filtered_sz(struct kunit *test) +{ + struct damos_access_pattern pattern = { + .min_sz_region = 0, + .max_sz_region = ULONG_MAX, + .min_nr_accesses = 0, + .max_nr_accesses = UINT_MAX, + .min_age_region = 0, + .max_age_region = UINT_MAX, + }; + unsigned long min_sz = DAMON_MIN_REGION_SZ; + struct damos_watermarks wmarks = {}; + struct damos_quota quota = {}; + struct damon_ctx *c; + struct damon_target *t; + struct damon_region *r; + struct damos_filter *f; + struct damos *s; + + c = damon_new_ctx(); + if (!c) + kunit_skip(test, "ctx alloc fail"); + c->ops.apply_scheme = damos_test_apply_scheme_stub; + + s = damon_new_scheme(&pattern, DAMOS_STAT, 0, "a, &wmarks, + NUMA_NO_NODE); + if (!s) { + damon_destroy_ctx(c); + kunit_skip(test, "scheme alloc fail"); + } + damon_add_scheme(c, s); + + t = damon_new_target(); + if (!t) { + damon_destroy_ctx(c); + kunit_skip(test, "target alloc fail"); + } + damon_add_target(c, t); + + f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true, false); + if (!f) { + damon_destroy_ctx(c); + kunit_skip(test, "filter alloc fail"); + } + f->addr_range = (struct damon_addr_range){ + .start = 2 * min_sz, + .end = 8 * min_sz + }; + damos_add_filter(s, f); + damos_set_filters_default_reject(s); + + /* reject filter, region starting before the range */ + r = damon_new_region(0, 4 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2); + KUNIT_EXPECT_EQ(test, r->ar.end, 2 * min_sz); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 2 * min_sz); + + if (damon_nr_regions(t) != 2) + goto out; + damon_destroy_region(damon_next_region(r), t); + damon_destroy_region(r, t); + s->stat = (struct damos_stat){}; + + /* allow filter, region starting inside the range */ + f->allow = true; + damos_set_filters_default_reject(s); + r = damon_new_region(2 * min_sz, 10 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2); + KUNIT_EXPECT_EQ(test, r->ar.end, 8 * min_sz); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 6 * min_sz); + +out: + damon_destroy_ctx(c); +} + +static void damos_test_apply_scheme_filter_sz_unchanged(struct kunit *test) +{ + struct damos_access_pattern pattern = { + .min_sz_region = 0, + .max_sz_region = ULONG_MAX, + .min_nr_accesses = 0, + .max_nr_accesses = UINT_MAX, + .min_age_region = 0, + .max_age_region = UINT_MAX, + }; + unsigned long min_sz = DAMON_MIN_REGION_SZ; + struct damos_watermarks wmarks = {}; + struct damos_quota quota = {}; + struct damos_filter *f, *f2; + struct damon_ctx *c; + struct damon_target *t; + struct damon_region *r; + struct damos *s; + + c = damon_new_ctx(); + if (!c) + kunit_skip(test, "ctx alloc fail"); + c->ops.apply_scheme = damos_test_apply_scheme_stub; + + s = damon_new_scheme(&pattern, DAMOS_STAT, 0, "a, &wmarks, + NUMA_NO_NODE); + if (!s) { + damon_destroy_ctx(c); + kunit_skip(test, "scheme alloc fail"); + } + damon_add_scheme(c, s); + + t = damon_new_target(); + if (!t) { + damon_destroy_ctx(c); + kunit_skip(test, "target alloc fail"); + } + damon_add_target(c, t); + + f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true, false); + if (!f) { + damon_destroy_ctx(c); + kunit_skip(test, "filter alloc fail"); + } + f->addr_range = (struct damon_addr_range){ + .start = 2 * min_sz, .end = 8 * min_sz}; + damos_add_filter(s, f); + damos_set_filters_default_reject(s); + + /* wholly inside a reject range: not counted at all */ + r = damon_new_region(4 * min_sz, 6 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, s->stat.nr_tried, 0); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 0); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); + + /* wholly inside an allow range: counted whole, not split */ + f->allow = true; + damos_set_filters_default_reject(s); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 2 * min_sz); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); + + /* two filters, each trimming: the size left after both is counted */ + damon_destroy_region(r, t); + s->stat = (struct damos_stat){}; + f->allow = false; + f->addr_range = (struct damon_addr_range){ + .start = 4 * min_sz, .end = 12 * min_sz}; + f2 = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true, false); + if (!f2) { + damon_destroy_ctx(c); + kunit_skip(test, "filter alloc fail"); + } + f2->addr_range = (struct damon_addr_range){ + .start = 2 * min_sz, .end = 3 * min_sz}; + damos_add_filter(s, f2); + damos_set_filters_default_reject(s); + + r = damon_new_region(0, 8 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 3); + KUNIT_EXPECT_EQ(test, r->ar.end, 2 * min_sz); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 2 * min_sz); + + /* a core filter that never splits: counted whole */ + damos_destroy_filter(f2); + damos_destroy_filter(f); + f = damos_new_filter(DAMOS_FILTER_TYPE_TARGET, true, true); + if (!f) { + damon_destroy_ctx(c); + kunit_skip(test, "filter alloc fail"); + } + f->target_idx = 0; + damos_add_filter(s, f); + damos_set_filters_default_reject(s); + s->stat = (struct damos_stat){}; + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 3); + KUNIT_EXPECT_EQ(test, r->ar.end, 2 * min_sz); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 2 * min_sz); + + damon_destroy_ctx(c); +} + +static void damos_test_apply_scheme_quota_sz(struct kunit *test) +{ + struct damos_access_pattern pattern = { + .min_sz_region = 0, + .max_sz_region = ULONG_MAX, + .min_nr_accesses = 0, + .max_nr_accesses = UINT_MAX, + .min_age_region = 0, + .max_age_region = UINT_MAX, + }; + unsigned long min_sz = DAMON_MIN_REGION_SZ; + struct damos_watermarks wmarks = {}; + struct damos_quota quota = {}; + struct damon_region *r, *next; + struct damon_ctx *c; + struct damon_target *t; + struct damos *s; + + c = damon_new_ctx(); + if (!c) + kunit_skip(test, "ctx alloc fail"); + + s = damon_new_scheme(&pattern, DAMOS_STAT, 0, "a, &wmarks, + NUMA_NO_NODE); + if (!s) { + damon_destroy_ctx(c); + kunit_skip(test, "scheme alloc fail"); + } + damon_add_scheme(c, s); + damos_set_filters_default_reject(s); + + t = damon_new_target(); + if (!t) { + damon_destroy_ctx(c); + kunit_skip(test, "target alloc fail"); + } + damon_add_target(c, t); + + /* no apply_scheme operation: the whole region is counted */ + r = damon_new_region(0, 4 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 4 * min_sz); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); + + /* no filter and no quota: the whole region is counted */ + c->ops.apply_scheme = damos_test_apply_scheme_stub; + s->stat = (struct damos_stat){}; + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 4 * min_sz); + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1); + + /* the quota trims the region: the trimmed size is counted */ + damon_for_each_region_safe(r, next, t) + damon_destroy_region(r, t); + s->stat = (struct damos_stat){}; + s->quota.esz = 2 * min_sz; + s->quota.charged_sz = 0; + + r = damon_new_region(0, 8 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, r->ar.end, 2 * min_sz); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 2 * min_sz); + + /* quota remainder below one region: tried, but nothing counted */ + damon_for_each_region_safe(r, next, t) + damon_destroy_region(r, t); + s->stat = (struct damos_stat){}; + s->quota.esz = 1; + s->quota.charged_sz = 0; + + r = damon_new_region(0, 4 * min_sz); + if (!r) { + damon_destroy_ctx(c); + kunit_skip(test, "region alloc fail"); + } + damon_add_region(r, t); + + damos_apply_scheme(c, t, r, s); + KUNIT_EXPECT_EQ(test, s->stat.nr_tried, 1); + KUNIT_EXPECT_EQ(test, s->stat.sz_tried, 0); + KUNIT_EXPECT_EQ(test, r->ar.end, 4 * min_sz); + + damon_destroy_ctx(c); +} + static void damon_test_feed_loop_next_input(struct kunit *test) { unsigned long last_input = 900000, current_score = 200; @@ -1959,6 +2272,9 @@ static struct kunit_case damon_test_case KUNIT_CASE(damon_test_commit_ctx), KUNIT_CASE(damon_test_valid_probe_params), KUNIT_CASE(damos_test_filter_out), + KUNIT_CASE(damos_test_apply_scheme_filtered_sz), + KUNIT_CASE(damos_test_apply_scheme_filter_sz_unchanged), + KUNIT_CASE(damos_test_apply_scheme_quota_sz), KUNIT_CASE(damon_test_feed_loop_next_input), KUNIT_CASE(damon_test_set_filters_default_reject), KUNIT_CASE(damon_test_apply_min_nr_regions), _ Patches currently in -mm which might be from donggeunyoo.kernel@gmail.com are userfaultfd-clear-the-inherited-uffd-bit-in-move_swap_pte.patch mm-damon-core-prevent-size-quota-overflow-in-the-temporal-goal-tuner.patch mm-damon-tests-core-kunit-test-the-temporal-tuners-size-quota-conversion.patch