From: Andrew Morton <akpm@linux-foundation.org>
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
Subject: [merged mm-stable] mm-damon-tests-core-kunit-test-the-size-charged-for-a-filter-trimmed-region.patch removed from -mm tree
Date: Mon, 12 Oct 2026 21:34:05 -0700 [thread overview]
Message-ID: <20261013043405.82CC21F000FF@smtp.kernel.org> (raw)
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 <donggeunyoo.kernel@gmail.com>
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 <donggeunyoo.kernel@gmail.com>
Signed-off-by: SJ Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: SJ Park <sj@kernel.org>
Cc: Brendan Higgins <brendan.higgins@linux.dev>
Cc: David Gow <david@davidgow.net>
Cc: <stable@vger.kernel.org>
---
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
reply other threads:[~2026-10-13 4:34 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261013043405.82CC21F000FF@smtp.kernel.org \
--to=akpm@linux-foundation.org \
--cc=brendan.higgins@linux.dev \
--cc=david@davidgow.net \
--cc=donggeunyoo.kernel@gmail.com \
--cc=mm-commits@vger.kernel.org \
--cc=sj@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.