[RFC PATCH v3 15/28] mm/damon/sysfs-schemes: implement tried_regions/<r>/probes/

From: SeongJae Park

Date: Sat May 16 2026 - 14:39:43 EST


Implement a sysfs directory for showing the per-region probe hit counts.
It is named 'probes/' and located under the DAMOS tried region
directory.

Signed-off-by: SeongJae Park <sj@xxxxxxxxxx>
---
mm/damon/sysfs-schemes.c | 70 +++++++++++++++++++++++++++++++++++++---
1 file changed, 65 insertions(+), 5 deletions(-)

diff --git a/mm/damon/sysfs-schemes.c b/mm/damon/sysfs-schemes.c
index 245d63808411a..8998df5bdc5c8 100644
--- a/mm/damon/sysfs-schemes.c
+++ b/mm/damon/sysfs-schemes.c
@@ -10,6 +10,32 @@

#include "sysfs-common.h"

+/*
+ * probes directory
+ */
+
+struct damos_sysfs_probes {
+ struct kobject kobj;
+};
+
+static struct damos_sysfs_probes *damos_sysfs_probes_alloc(void)
+{
+ return kzalloc_obj(struct damos_sysfs_probes);
+}
+
+static void damos_sysfs_probes_release(struct kobject *kobj)
+{
+ struct damos_sysfs_probes *probes = container_of(kobj,
+ struct damos_sysfs_probes, kobj);
+
+ kfree(probes);
+}
+
+static const struct kobj_type damos_sysfs_probes_ktype = {
+ .release = damos_sysfs_probes_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+};
+
/*
* scheme region directory
*/
@@ -20,6 +46,7 @@ struct damon_sysfs_scheme_region {
unsigned int nr_accesses;
unsigned int age;
unsigned long sz_filter_passed;
+ struct damos_sysfs_probes *probes;
struct list_head list;
};

@@ -34,10 +61,36 @@ static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
sysfs_region->ar = region->ar;
sysfs_region->nr_accesses = region->nr_accesses_bp / 10000;
sysfs_region->age = region->age;
+ sysfs_region->probes = NULL;
INIT_LIST_HEAD(&sysfs_region->list);
return sysfs_region;
}

+static int damos_sysfs_region_add_dirs(
+ struct damon_sysfs_scheme_region *region)
+{
+ struct damos_sysfs_probes *probes = damos_sysfs_probes_alloc();
+ int err;
+
+ if (!probes)
+ return -ENOMEM;
+ err = kobject_init_and_add(&probes->kobj, &damos_sysfs_probes_ktype,
+ &region->kobj, "probes");
+ if (err) {
+ kobject_put(&probes->kobj);
+ return err;
+ }
+
+ region->probes = probes;
+ return 0;
+}
+
+static void damos_sysfs_region_rm_dirs(
+ struct damon_sysfs_scheme_region *region)
+{
+ kobject_put(&region->probes->kobj);
+}
+
static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
@@ -165,6 +218,7 @@ static void damon_sysfs_scheme_regions_rm_dirs(

list_for_each_entry_safe(r, next, &regions->regions_list, list) {
/* release function deletes it from the list */
+ damos_sysfs_region_rm_dirs(r);
kobject_put(&r->kobj);
regions->nr_regions--;
}
@@ -2927,14 +2981,20 @@ void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes,
if (!region)
return;
region->sz_filter_passed = sz_filter_passed;
- list_add_tail(&region->list, &sysfs_regions->regions_list);
- sysfs_regions->nr_regions++;
if (kobject_init_and_add(&region->kobj,
&damon_sysfs_scheme_region_ktype,
&sysfs_regions->kobj, "%d",
- sysfs_regions->nr_regions++)) {
- kobject_put(&region->kobj);
- }
+ sysfs_regions->nr_regions++))
+ goto out;
+ if (damos_sysfs_region_add_dirs(region))
+ goto out;
+
+ list_add_tail(&region->list, &sysfs_regions->regions_list);
+ sysfs_regions->nr_regions++;
+ return;
+
+out:
+ kobject_put(&region->kobj);
}

int damon_sysfs_schemes_clear_regions(
--
2.47.3