]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mm/damon/core: add cleanup_target() ops callback
authorSeongJae Park <sj@kernel.org>
Sat, 12 Jul 2025 19:50:11 +0000 (12:50 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 20 Jul 2025 01:59:56 +0000 (18:59 -0700)
Some DAMON operation sets may need additional cleanup per target.  For
example, [f]vaddr need to put pids of each target.  Each user and core
logic is doing that redundantly.  Add another DAMON ops callback that will
be used for doing such cleanups in operations set layer.

[sj@kernel.org: add kernel-doc comment for damon_operations->cleanup_target]
Link: https://lkml.kernel.org/r/20250715185239.89152-2-sj@kernel.org
[sj@kernel.org: remove damon_ctx->callback kernel-doc comment]
Link: https://lkml.kernel.org/r/20250715185239.89152-3-sj@kernel.org
Link: https://lkml.kernel.org/r/20250712195016.151108-10-sj@kernel.org
Signed-off-by: SeongJae Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/damon.h
mm/damon/core.c
mm/damon/sysfs.c
mm/damon/tests/core-kunit.h
mm/damon/tests/vaddr-kunit.h

index b83987275ff9d2cc94fa70368bc394c26ebbd360..8c765e36623aa7ca872a3e93dfa6e0fe32f27371 100644 (file)
@@ -576,6 +576,7 @@ enum damon_ops_id {
  * @get_scheme_score:          Get the score of a region for a scheme.
  * @apply_scheme:              Apply a DAMON-based operation scheme.
  * @target_valid:              Determine if the target is valid.
+ * @cleanup_target:            Clean up each target before deallocation.
  * @cleanup:                   Clean up the context.
  *
  * DAMON can be extended for various address spaces and usages.  For this,
@@ -608,6 +609,7 @@ enum damon_ops_id {
  * filters (&struct damos_filter) that handled by itself.
  * @target_valid should check whether the target is still valid for the
  * monitoring.
+ * @cleanup_target is called before the target will be deallocated.
  * @cleanup is called from @kdamond just before its termination.
  */
 struct damon_operations {
@@ -623,6 +625,7 @@ struct damon_operations {
                        struct damon_target *t, struct damon_region *r,
                        struct damos *scheme, unsigned long *sz_filter_passed);
        bool (*target_valid)(struct damon_target *t);
+       void (*cleanup_target)(struct damon_target *t);
        void (*cleanup)(struct damon_ctx *context);
 };
 
@@ -771,7 +774,6 @@ struct damon_attrs {
  * Accesses to other fields must be protected by themselves.
  *
  * @ops:       Set of monitoring operations for given use cases.
- * @callback:  Set of callbacks for monitoring events notifications.
  *
  * @adaptive_targets:  Head of monitoring targets (&damon_target) list.
  * @schemes:           Head of schemes (&damos) list.
@@ -933,7 +935,7 @@ struct damon_target *damon_new_target(void);
 void damon_add_target(struct damon_ctx *ctx, struct damon_target *t);
 bool damon_targets_empty(struct damon_ctx *ctx);
 void damon_free_target(struct damon_target *t);
-void damon_destroy_target(struct damon_target *t);
+void damon_destroy_target(struct damon_target *t, struct damon_ctx *ctx);
 unsigned int damon_nr_regions(struct damon_target *t);
 
 struct damon_ctx *damon_new_ctx(void);
index b82a838b5a0e8060e72aeece6a5109fc40a41f3e..678c9b4e038cd69e79f176984a4ebbe68bfe608b 100644 (file)
@@ -502,8 +502,12 @@ void damon_free_target(struct damon_target *t)
        kfree(t);
 }
 
-void damon_destroy_target(struct damon_target *t)
+void damon_destroy_target(struct damon_target *t, struct damon_ctx *ctx)
 {
+
+       if (ctx && ctx->ops.cleanup_target)
+               ctx->ops.cleanup_target(t);
+
        damon_del_target(t);
        damon_free_target(t);
 }
@@ -551,7 +555,7 @@ static void damon_destroy_targets(struct damon_ctx *ctx)
        struct damon_target *t, *next_t;
 
        damon_for_each_target_safe(t, next_t, ctx)
-               damon_destroy_target(t);
+               damon_destroy_target(t, ctx);
 }
 
 void damon_destroy_ctx(struct damon_ctx *ctx)
@@ -1137,7 +1141,7 @@ static int damon_commit_targets(
 
                        if (damon_target_has_pid(dst))
                                put_pid(dst_target->pid);
-                       damon_destroy_target(dst_target);
+                       damon_destroy_target(dst_target, dst);
                        damon_for_each_scheme(s, dst) {
                                if (s->quota.charge_target_from == dst_target) {
                                        s->quota.charge_target_from = NULL;
@@ -1156,7 +1160,7 @@ static int damon_commit_targets(
                err = damon_commit_target(new_target, false,
                                src_target, damon_target_has_pid(src));
                if (err) {
-                       damon_destroy_target(new_target);
+                       damon_destroy_target(new_target, NULL);
                        return err;
                }
                damon_add_target(dst, new_target);
index c0193de6fb9af0fbbece2d0813d319ca61bfe2b1..f2f9f756f5a2bf69f9a4212d3ab0aec7a5cf0988 100644 (file)
@@ -1303,7 +1303,7 @@ static void damon_sysfs_destroy_targets(struct damon_ctx *ctx)
        damon_for_each_target_safe(t, next, ctx) {
                if (has_pid)
                        put_pid(t->pid);
-               damon_destroy_target(t);
+               damon_destroy_target(t, ctx);
        }
 }
 
@@ -1389,7 +1389,7 @@ static void damon_sysfs_before_terminate(struct damon_ctx *ctx)
 
        damon_for_each_target_safe(t, next, ctx) {
                put_pid(t->pid);
-               damon_destroy_target(t);
+               damon_destroy_target(t, ctx);
        }
 }
 
index 298c67557fae44c28ddbfa7fe65a69eb3c8e013c..dfedfff19940e6966180ac9a9280e7a27ab7705f 100644 (file)
@@ -58,7 +58,7 @@ static void damon_test_target(struct kunit *test)
        damon_add_target(c, t);
        KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(c));
 
-       damon_destroy_target(t);
+       damon_destroy_target(t, c);
        KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
 
        damon_destroy_ctx(c);
@@ -310,7 +310,7 @@ static void damon_test_set_regions(struct kunit *test)
                KUNIT_EXPECT_EQ(test, r->ar.start, expects[expect_idx++]);
                KUNIT_EXPECT_EQ(test, r->ar.end, expects[expect_idx++]);
        }
-       damon_destroy_target(t);
+       damon_destroy_target(t, NULL);
 }
 
 static void damon_test_nr_accesses_to_accesses_bp(struct kunit *test)
index 7cd944266a928dbe07d97f1148dce5c3b572ad8c..d2b37ccf2cc0651d28c25aa44096c9486eae6cc9 100644 (file)
@@ -149,7 +149,7 @@ static void damon_do_test_apply_three_regions(struct kunit *test,
                KUNIT_EXPECT_EQ(test, r->ar.end, expected[i * 2 + 1]);
        }
 
-       damon_destroy_target(t);
+       damon_destroy_target(t, NULL);
 }
 
 /*