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>
This commit is contained in:
SeongJae Park 2026-05-18 16:41:00 -07:00 committed by Andrew Morton
parent af7cb41af9
commit 956bf44e45

View File

@ -747,12 +747,46 @@ static const struct kobj_type damon_sysfs_intervals_ktype = {
.default_groups = damon_sysfs_intervals_groups,
};
/*
* 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)