aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
authorSeongJae Park <sj@kernel.org>2026-05-18 16:41:00 -0700
committerAndrew Morton <akpm@linux-foundation.org>2026-05-28 21:31:13 -0700
commit5d8e2ac19ff80aceb776a0bf9f93202e3e797e9d (patch)
tree241ef649492e2e743c6e0919087417cf7bc8fbbb /mm
parent92c4bb97de78d41a614005efd7c53369ca7be160 (diff)
downloadlinux-next-history-5d8e2ac19ff80aceb776a0bf9f93202e3e797e9d.tar.gz
mm/damon/sysfs: implement filter dir
Implement a sysfs directory for letting the users to configure each data probe filter. Link: https://lore.kernel.org/20260518234119.97569-13-sj@kernel.org Signed-off-by: SeongJae Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/damon/sysfs.c125
1 files changed, 124 insertions, 1 deletions
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index dad4985a826db..2dc475ea0f0f7 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -748,11 +748,45 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {
};
/*
+ * filter directory
+ */
+
+struct damon_sysfs_filter {
+ struct kobject kobj;
+};
+
+static struct damon_sysfs_filter *damon_sysfs_filter_alloc(void)
+{
+ return kzalloc_obj(struct damon_sysfs_filter);
+}
+
+static void damon_sysfs_filter_release(struct kobject *kobj)
+{
+ struct damon_sysfs_filter *filter = container_of(kobj,
+ struct damon_sysfs_filter, kobj);
+
+ kfree(filter);
+}
+
+static struct attribute *damon_sysfs_filter_attrs[] = {
+ NULL,
+};
+ATTRIBUTE_GROUPS(damon_sysfs_filter);
+
+static const struct kobj_type damon_sysfs_filter_ktype = {
+ .release = damon_sysfs_filter_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = damon_sysfs_filter_groups,
+};
+
+/*
* filters directory
*/
struct damon_sysfs_filters {
struct kobject kobj;
+ struct damon_sysfs_filter **filters_arr;
+ int nr;
};
static struct damon_sysfs_filters *damon_sysfs_filters_alloc(void)
@@ -760,12 +794,98 @@ static struct damon_sysfs_filters *damon_sysfs_filters_alloc(void)
return kzalloc_obj(struct damon_sysfs_filters);
}
+static void damon_sysfs_filters_rm_dirs(struct damon_sysfs_filters *filters)
+{
+ struct damon_sysfs_filter **filters_arr = filters->filters_arr;
+ int i;
+
+ for (i = 0; i < filters->nr; i++)
+ kobject_put(&filters_arr[i]->kobj);
+ filters->nr = 0;
+ kfree(filters_arr);
+ filters->filters_arr = NULL;
+}
+
+static int damon_sysfs_filters_add_dirs(
+ struct damon_sysfs_filters *filters, int nr_filters)
+{
+ struct damon_sysfs_filter **filters_arr, *filter;
+ int err, i;
+
+ damon_sysfs_filters_rm_dirs(filters);
+ if (!nr_filters)
+ return 0;
+
+ filters_arr = kmalloc_objs(*filters_arr, nr_filters,
+ GFP_KERNEL | __GFP_NOWARN);
+ if (!filters_arr)
+ return -ENOMEM;
+ filters->filters_arr = filters_arr;
+
+ for (i = 0; i < nr_filters; i++) {
+ filter = damon_sysfs_filter_alloc();
+ if (!filter) {
+ damon_sysfs_filters_rm_dirs(filters);
+ return -ENOMEM;
+ }
+
+ err = kobject_init_and_add(&filter->kobj,
+ &damon_sysfs_filter_ktype, &filters->kobj,
+ "%d", i);
+ if (err) {
+ kobject_put(&filter->kobj);
+ damon_sysfs_filters_rm_dirs(filters);
+ return err;
+ }
+
+ filters_arr[i] = filter;
+ filters->nr++;
+ }
+ return 0;
+}
+
+static ssize_t nr_filters_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct damon_sysfs_filters *filters = container_of(kobj,
+ struct damon_sysfs_filters, kobj);
+
+ return sysfs_emit(buf, "%d\n", filters->nr);
+}
+
+static ssize_t nr_filters_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ struct damon_sysfs_filters *filters;
+ int nr, err = kstrtoint(buf, 0, &nr);
+
+ if (err)
+ return err;
+ if (nr < 0)
+ return -EINVAL;
+
+ filters = container_of(kobj, struct damon_sysfs_filters, kobj);
+
+ if (!mutex_trylock(&damon_sysfs_lock))
+ return -EBUSY;
+ err = damon_sysfs_filters_add_dirs(filters, nr);
+ mutex_unlock(&damon_sysfs_lock);
+ if (err)
+ return err;
+
+ return count;
+}
+
static void damon_sysfs_filters_release(struct kobject *kobj)
{
kfree(container_of(kobj, struct damon_sysfs_filters, kobj));
}
+static struct kobj_attribute damon_sysfs_filters_nr_attr =
+ __ATTR_RW_MODE(nr_filters, 0600);
+
static struct attribute *damon_sysfs_filters_attrs[] = {
+ &damon_sysfs_filters_nr_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_filters);
@@ -811,7 +931,10 @@ static int damon_sysfs_probe_add_dirs(struct damon_sysfs_probe *attr)
static void damon_sysfs_probe_rm_dirs(struct damon_sysfs_probe *attr)
{
- kobject_put(&attr->filters->kobj);
+ if (attr->filters) {
+ damon_sysfs_filters_rm_dirs(attr->filters);
+ kobject_put(&attr->filters->kobj);
+ }
}
static void damon_sysfs_probe_release(struct kobject *kobj)