From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: SeongJae Park <sj@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.12.y 2/3] mm/damon: rename DAMON_MIN_REGION to DAMON_MIN_REGION_SZ
Date: Tue, 29 Sep 2026 22:34:00 -0400 [thread overview]
Message-ID: <20260930023401.3420697-2-sashal@kernel.org> (raw)
In-Reply-To: <20260930023401.3420697-1-sashal@kernel.org>
From: SeongJae Park <sj@kernel.org>
[ Upstream commit dfb1b0c9dc0d61e422905640e1e7334b3cf6f384 ]
The macro is for the default minimum size of each DAMON region. There was
a case that a reader was confused if it is the minimum number of total
DAMON regions, which is set on damon_attrs->min_nr_regions. Make the name
more explicit.
Link: https://lkml.kernel.org/r/20260117175256.82826-8-sj@kernel.org
Signed-off-by: SeongJae Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Stable backport preparation for b3723b596b548 ("mm/damon/core: fix
unconditionally skip last region"):
Rename all uses present in 6.12, including the core KUnit override and
tests. Drop changes to address-unit/minimum-size context fields and the
four-argument damon_set_regions() calls, which do not exist in this tree.
Match the target's quota helper preimage by passing the fixed region size
as min_region_sz and incorporating the existing-function changes from
1745ccbd2907 ("mm/damon/core: do non-safe region walk on
kdamond_apply_schemes()"). The region walk must visit newly split tails
when the helper returns true for the already charged prefix. Preserve
the existing target-validity check and leave the last-region fix to the
target commit. No new functions or context fields are introduced.
[ sashal: Reduced backport -- upstream dfb1b0c9dc0d6 touches 7 file(s), this
backport carries 4. Not backported here:
mm/damon/lru_sort.c
mm/damon/reclaim.c
mm/damon/sysfs.c
mm/damon/tests/vaddr-kunit.h
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: b3723b596b54 ("mm/damon/core: fix unconditionally skip last region")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/damon.h | 2 +-
mm/damon/core.c | 64 +++++++++++++++++++------------------
mm/damon/tests/core-kunit.h | 36 ++++++++++-----------
mm/damon/vaddr.c | 22 ++++++-------
4 files changed, 63 insertions(+), 61 deletions(-)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index 4688a10eca89b..a634d47eaa8bc 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -15,7 +15,7 @@
#include <linux/random.h>
/* Minimal region size. Every damon_region is aligned by this. */
-#define DAMON_MIN_REGION PAGE_SIZE
+#define DAMON_MIN_REGION_SZ PAGE_SIZE
/* Max priority score for DAMON-based operation schemes */
#define DAMOS_MAX_SCORE (99)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index b3a28a857d075..53d479da2007e 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -19,8 +19,8 @@
#include <trace/events/damon.h>
#ifdef CONFIG_DAMON_KUNIT_TEST
-#undef DAMON_MIN_REGION
-#define DAMON_MIN_REGION 1
+#undef DAMON_MIN_REGION_SZ
+#define DAMON_MIN_REGION_SZ 1
#endif
static DEFINE_MUTEX(damon_lock);
@@ -218,8 +218,8 @@ int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges,
for (i = 0; i < nr_ranges; i++) {
unsigned long start, end;
- start = ALIGN_DOWN(ranges[i].start, DAMON_MIN_REGION);
- end = ALIGN(ranges[i].end, DAMON_MIN_REGION);
+ start = ALIGN_DOWN(ranges[i].start, DAMON_MIN_REGION_SZ);
+ end = ALIGN(ranges[i].end, DAMON_MIN_REGION_SZ);
if (start >= end)
return -EINVAL;
if (i > 0 && last_end > start)
@@ -258,16 +258,16 @@ int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges,
/* no region intersects with this range */
newr = damon_new_region(
ALIGN_DOWN(range->start,
- DAMON_MIN_REGION),
- ALIGN(range->end, DAMON_MIN_REGION));
+ DAMON_MIN_REGION_SZ),
+ ALIGN(range->end, DAMON_MIN_REGION_SZ));
if (!newr)
return -ENOMEM;
damon_insert_region(newr, damon_prev_region(r), r, t);
} else {
/* resize intersecting regions to fit in this range */
first->ar.start = ALIGN_DOWN(range->start,
- DAMON_MIN_REGION);
- last->ar.end = ALIGN(range->end, DAMON_MIN_REGION);
+ DAMON_MIN_REGION_SZ);
+ last->ar.end = ALIGN(range->end, DAMON_MIN_REGION_SZ);
/* fill possible holes in the range */
err = damon_fill_regions_holes(first, last, t);
@@ -1092,8 +1092,8 @@ static unsigned long damon_region_sz_limit(struct damon_ctx *ctx)
if (ctx->attrs.min_nr_regions)
sz /= ctx->attrs.min_nr_regions;
- if (sz < DAMON_MIN_REGION)
- sz = DAMON_MIN_REGION;
+ if (sz < DAMON_MIN_REGION_SZ)
+ sz = DAMON_MIN_REGION_SZ;
return sz;
}
@@ -1298,8 +1298,9 @@ static bool damos_valid_target(struct damon_ctx *c, struct damon_target *t,
* damos_skip_charged_region() - Check if the given region or starting part of
* it is already charged for the DAMOS quota.
* @t: The target of the region.
- * @rp: The pointer to the region.
+ * @r: The region.
* @s: The scheme to be applied.
+ * @min_region_sz: minimum region size.
*
* If a quota of a scheme has exceeded in a quota charge window, the scheme's
* action would applied to only a part of the target access pattern fulfilling
@@ -1310,16 +1311,18 @@ static bool damos_valid_target(struct damon_ctx *c, struct damon_target *t,
* This function checks if a given region should be skipped or not for the
* reason. If only the starting part of the region has previously charged,
* this function splits the region into two so that the second one covers the
- * area that not charged in the previous charge widnow and saves the second
- * region in *rp and returns false, so that the caller can apply DAMON action
- * to the second one.
+ * area that not charged in the previous charge widnow, and return true. The
+ * caller can see the second one on the next iteration of the region walk.
+ * Note that this means the caller should use damon_for_each_region() instead
+ * of damon_for_each_region_safe(). If damon_for_each_region_safe() is used,
+ * the second region will just be ignored.
*
- * Return: true if the region should be entirely skipped, false otherwise.
+ * Return: true if the region should be skipped, false otherwise.
*/
static bool damos_skip_charged_region(struct damon_target *t,
- struct damon_region **rp, struct damos *s)
+ struct damon_region *r, struct damos *s,
+ unsigned long min_region_sz)
{
- struct damon_region *r = *rp;
struct damos_quota *quota = &s->quota;
unsigned long sz_to_skip;
@@ -1339,15 +1342,14 @@ static bool damos_skip_charged_region(struct damon_target *t,
if (quota->charge_addr_from && r->ar.start <
quota->charge_addr_from) {
sz_to_skip = ALIGN_DOWN(quota->charge_addr_from -
- r->ar.start, DAMON_MIN_REGION);
+ r->ar.start, min_region_sz);
if (!sz_to_skip) {
- if (damon_sz_region(r) <= DAMON_MIN_REGION)
+ if (damon_sz_region(r) <= min_region_sz)
return true;
- sz_to_skip = DAMON_MIN_REGION;
+ sz_to_skip = min_region_sz;
}
damon_split_region_at(t, r, sz_to_skip);
- r = damon_next_region(r);
- *rp = r;
+ return true;
}
quota->charge_target_from = NULL;
quota->charge_addr_from = 0;
@@ -1383,8 +1385,8 @@ static bool __damos_filter_out(struct damon_ctx *ctx, struct damon_target *t,
matched = target_idx == filter->target_idx;
break;
case DAMOS_FILTER_TYPE_ADDR:
- start = ALIGN_DOWN(filter->addr_range.start, DAMON_MIN_REGION);
- end = ALIGN_DOWN(filter->addr_range.end, DAMON_MIN_REGION);
+ start = ALIGN_DOWN(filter->addr_range.start, DAMON_MIN_REGION_SZ);
+ end = ALIGN_DOWN(filter->addr_range.end, DAMON_MIN_REGION_SZ);
/* inside the range */
if (start <= r->ar.start && r->ar.end <= end) {
@@ -1464,7 +1466,7 @@ static void damos_apply_scheme(struct damon_ctx *c, struct damon_target *t,
if (c->ops.apply_scheme) {
if (quota->esz && quota->charged_sz + sz > quota->esz) {
sz = ALIGN_DOWN(quota->esz - quota->charged_sz,
- DAMON_MIN_REGION);
+ DAMON_MIN_REGION_SZ);
if (!sz)
goto update_stat;
damon_split_region_at(t, r, sz);
@@ -1514,7 +1516,7 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
if (quota->esz && quota->charged_sz >= quota->esz)
continue;
- if (damos_skip_charged_region(t, &r, s))
+ if (damos_skip_charged_region(t, r, s, DAMON_MIN_REGION_SZ))
continue;
if (!damos_valid_target(c, t, r, s))
@@ -1660,7 +1662,7 @@ static void damos_set_effective_quota(struct damos_quota *quota)
esz = min(throughput * quota->ms, esz);
else
esz = throughput * quota->ms;
- esz = max(DAMON_MIN_REGION, esz);
+ esz = max(DAMON_MIN_REGION_SZ, esz);
}
if (quota->sz && quota->sz < esz)
@@ -1727,7 +1729,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)
static void kdamond_apply_schemes(struct damon_ctx *c)
{
struct damon_target *t;
- struct damon_region *r, *next_r;
+ struct damon_region *r;
struct damos *s;
unsigned long sample_interval = c->attrs.sample_interval ?
c->attrs.sample_interval : 1;
@@ -1752,7 +1754,7 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
if (c->ops.target_valid && c->ops.target_valid(t) == false)
continue;
- damon_for_each_region_safe(r, next_r, t)
+ damon_for_each_region(r, t)
damon_do_apply_schemes(c, t, r);
}
@@ -1891,13 +1893,13 @@ static void damon_split_regions_of(struct damon_target *t, int nr_subs)
sz_region = damon_sz_region(r);
for (i = 0; i < nr_subs - 1 &&
- sz_region > 2 * DAMON_MIN_REGION; i++) {
+ sz_region > 2 * DAMON_MIN_REGION_SZ; i++) {
/*
* Randomly select size of left sub-region to be at
* least 10 percent and at most 90% of original region
*/
sz_sub = ALIGN_DOWN(damon_rand(1, 10) *
- sz_region / 10, DAMON_MIN_REGION);
+ sz_region / 10, DAMON_MIN_REGION_SZ);
/* Do not allow blank region */
if (sz_sub == 0 || sz_sub >= sz_region)
continue;
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index ff9f73579f7b3..a97a4326a227e 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -530,10 +530,10 @@ static void damos_test_filter_out(struct kunit *test)
f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true);
f->addr_range = (struct damon_addr_range){
- .start = DAMON_MIN_REGION * 2, .end = DAMON_MIN_REGION * 6};
+ .start = DAMON_MIN_REGION_SZ * 2, .end = DAMON_MIN_REGION_SZ * 6};
t = damon_new_target();
- r = damon_new_region(DAMON_MIN_REGION * 3, DAMON_MIN_REGION * 5);
+ r = damon_new_region(DAMON_MIN_REGION_SZ * 3, DAMON_MIN_REGION_SZ * 5);
damon_add_region(r, t);
/* region in the range */
@@ -541,45 +541,45 @@ static void damos_test_filter_out(struct kunit *test)
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
/* region before the range */
- r->ar.start = DAMON_MIN_REGION * 1;
- r->ar.end = DAMON_MIN_REGION * 2;
+ r->ar.start = DAMON_MIN_REGION_SZ * 1;
+ r->ar.end = DAMON_MIN_REGION_SZ * 2;
KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f));
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
/* region after the range */
- r->ar.start = DAMON_MIN_REGION * 6;
- r->ar.end = DAMON_MIN_REGION * 8;
+ r->ar.start = DAMON_MIN_REGION_SZ * 6;
+ r->ar.end = DAMON_MIN_REGION_SZ * 8;
KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f));
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
/* region started before the range */
- r->ar.start = DAMON_MIN_REGION * 1;
- r->ar.end = DAMON_MIN_REGION * 4;
+ r->ar.start = DAMON_MIN_REGION_SZ * 1;
+ r->ar.end = DAMON_MIN_REGION_SZ * 4;
KUNIT_EXPECT_FALSE(test, __damos_filter_out(NULL, t, r, f));
/* filter should have split the region */
- KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION * 1);
- KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION * 2);
+ KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION_SZ * 1);
+ KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION_SZ * 2);
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
if (damon_nr_regions(t) != 2)
goto out;
r2 = damon_next_region(r);
- KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION * 2);
- KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION * 4);
+ KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION_SZ * 2);
+ KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION_SZ * 4);
damon_destroy_region(r2, t);
/* region started in the range */
- r->ar.start = DAMON_MIN_REGION * 2;
- r->ar.end = DAMON_MIN_REGION * 8;
+ r->ar.start = DAMON_MIN_REGION_SZ * 2;
+ r->ar.end = DAMON_MIN_REGION_SZ * 8;
KUNIT_EXPECT_TRUE(test, __damos_filter_out(NULL, t, r, f));
/* filter should have split the region */
- KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION * 2);
- KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION * 6);
+ KUNIT_EXPECT_EQ(test, r->ar.start, DAMON_MIN_REGION_SZ * 2);
+ KUNIT_EXPECT_EQ(test, r->ar.end, DAMON_MIN_REGION_SZ * 6);
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
if (damon_nr_regions(t) != 2)
goto out;
r2 = damon_next_region(r);
- KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION * 6);
- KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION * 8);
+ KUNIT_EXPECT_EQ(test, r2->ar.start, DAMON_MIN_REGION_SZ * 6);
+ KUNIT_EXPECT_EQ(test, r2->ar.end, DAMON_MIN_REGION_SZ * 8);
damon_destroy_region(r2, t);
out:
diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
index 089ee23e07de7..b423ce9da392d 100644
--- a/mm/damon/vaddr.c
+++ b/mm/damon/vaddr.c
@@ -18,8 +18,8 @@
#include "ops-common.h"
#ifdef CONFIG_DAMON_VADDR_KUNIT_TEST
-#undef DAMON_MIN_REGION
-#define DAMON_MIN_REGION 1
+#undef DAMON_MIN_REGION_SZ
+#define DAMON_MIN_REGION_SZ 1
#endif
/*
@@ -74,7 +74,7 @@ static int damon_va_evenly_split_region(struct damon_target *t,
orig_end = r->ar.end;
sz_orig = damon_sz_region(r);
- sz_piece = ALIGN_DOWN(sz_orig / nr_pieces, DAMON_MIN_REGION);
+ sz_piece = ALIGN_DOWN(sz_orig / nr_pieces, DAMON_MIN_REGION_SZ);
if (!sz_piece)
return -EINVAL;
@@ -157,12 +157,12 @@ static int __damon_va_three_regions(struct mm_struct *mm,
swap(first_gap, second_gap);
/* Store the result */
- regions[0].start = ALIGN(start, DAMON_MIN_REGION);
- regions[0].end = ALIGN(first_gap.start, DAMON_MIN_REGION);
- regions[1].start = ALIGN(first_gap.end, DAMON_MIN_REGION);
- regions[1].end = ALIGN(second_gap.start, DAMON_MIN_REGION);
- regions[2].start = ALIGN(second_gap.end, DAMON_MIN_REGION);
- regions[2].end = ALIGN(prev->vm_end, DAMON_MIN_REGION);
+ regions[0].start = ALIGN(start, DAMON_MIN_REGION_SZ);
+ regions[0].end = ALIGN(first_gap.start, DAMON_MIN_REGION_SZ);
+ regions[1].start = ALIGN(first_gap.end, DAMON_MIN_REGION_SZ);
+ regions[1].end = ALIGN(second_gap.start, DAMON_MIN_REGION_SZ);
+ regions[2].start = ALIGN(second_gap.end, DAMON_MIN_REGION_SZ);
+ regions[2].end = ALIGN(prev->vm_end, DAMON_MIN_REGION_SZ);
return 0;
}
@@ -255,8 +255,8 @@ static void __damon_va_init_regions(struct damon_ctx *ctx,
sz += regions[i].end - regions[i].start;
if (ctx->attrs.min_nr_regions)
sz /= ctx->attrs.min_nr_regions;
- if (sz < DAMON_MIN_REGION)
- sz = DAMON_MIN_REGION;
+ if (sz < DAMON_MIN_REGION_SZ)
+ sz = DAMON_MIN_REGION_SZ;
/* Set the initial three regions of the target */
for (i = 0; i < 3; i++) {
--
2.53.0
next prev parent reply other threads:[~2026-09-30 2:34 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 8:27 FAILED: patch "[PATCH] mm/damon/core: fix unconditionally skip last region" failed to apply to 6.12-stable tree gregkh
2026-09-30 2:33 ` [PATCH 6.12.y 1/3] mm/damon/core: fix wasteful CPU calls by skipping non-existent targets Sasha Levin
2026-09-30 2:34 ` Sasha Levin [this message]
2026-09-30 9:24 ` [PATCH 6.12.y 2/3] mm/damon: rename DAMON_MIN_REGION to DAMON_MIN_REGION_SZ SJ Park
2026-09-30 9:31 ` SJ Park
2026-09-30 2:34 ` [PATCH 6.12.y 3/3] mm/damon/core: fix unconditionally skip last region Sasha Levin
2026-09-30 13:15 ` Greg KH
2026-09-30 9:28 ` [PATCH 6.12.y] " SJ Park
2026-09-30 10:03 ` SJ Park
2026-09-30 10:14 ` [PATCH 6.12.y v2] " SJ Park
2026-10-02 14:19 ` Sasha Levin
2026-10-09 12:36 ` [PATCH 6.12.y v3 0/2] mm/damon/core: fix last region handling of damos_skip_charged_regions() SJ Park
2026-10-09 12:36 ` [PATCH 6.12.y v3 1/2] mm/damon/core: do non-safe region walk on kdamond_apply_schemes() SJ Park
2026-10-09 12:36 ` [PATCH 6.12.y v3 2/2] mm/damon/core: fix unconditionally skip last region SJ Park
2026-10-11 16:48 ` [PATCH 6.12.y v3 0/2] mm/damon/core: fix last region handling of damos_skip_charged_regions() Sasha Levin
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=20260930023401.3420697-2-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=akpm@linux-foundation.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox