aboutsummaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/damon/core.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 91cff7f2997e..68a5fb1c039d 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -877,6 +877,56 @@ static void damos_update_stat(struct damos *s,
s->stat.sz_applied += sz_applied;
}
+static bool __damos_filter_out(struct damon_target *t, struct damon_region *r,
+ struct damos_filter *filter)
+{
+ bool matched = false;
+ unsigned long start, end;
+
+ switch (filter->type) {
+ 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);
+
+ /* inside the range */
+ if (start <= r->ar.start && r->ar.end <= end) {
+ matched = true;
+ break;
+ }
+ /* outside of the range */
+ if (r->ar.end <= start || end <= r->ar.start) {
+ matched = false;
+ break;
+ }
+ /* start before the range and overlap */
+ if (r->ar.start < start) {
+ damon_split_region_at(t, r, start - r->ar.start);
+ matched = false;
+ break;
+ }
+ /* start inside the range */
+ damon_split_region_at(t, r, end - r->ar.start);
+ matched = true;
+ break;
+ default:
+ break;
+ }
+
+ return matched == filter->matching;
+}
+
+static bool damos_filter_out(struct damon_target *t, struct damon_region *r,
+ struct damos *s)
+{
+ struct damos_filter *filter;
+
+ damos_for_each_filter(filter, s) {
+ if (__damos_filter_out(t, r, filter))
+ return true;
+ }
+ return false;
+}
+
static void damos_apply_scheme(struct damon_ctx *c, struct damon_target *t,
struct damon_region *r, struct damos *s)
{
@@ -894,6 +944,8 @@ static void damos_apply_scheme(struct damon_ctx *c, struct damon_target *t,
goto update_stat;
damon_split_region_at(t, r, sz);
}
+ if (damos_filter_out(t, r, s))
+ return;
ktime_get_coarse_ts64(&begin);
if (c->callback.before_damos_apply)
err = c->callback.before_damos_apply(c, t, r, s);