mm/damon/sysfs-schemes: connect filter directory and filters directory

Implement 'nr_filters' file under 'filters' directory, which will be used
to populate specific number of 'filter' directory under the directory,
similar to other 'nr_*' files in DAMON sysfs interface.

Link: https://lkml.kernel.org/r/20221205230830.144349-8-sj@kernel.org
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
SeongJae Park 2022-12-05 23:08:26 +00:00 committed by Andrew Morton
parent 7ee161f18b
commit 472e2b70ed
1 changed files with 68 additions and 0 deletions

View File

@ -269,6 +269,11 @@ struct damon_sysfs_scheme_filter {
char *memcg_path;
};
static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
{
return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
}
/* Should match with enum damos_filter_type */
static const char * const damon_sysfs_scheme_filter_type_strs[] = {
"anon",
@ -392,6 +397,7 @@ static struct kobj_type damon_sysfs_scheme_filter_ktype = {
struct damon_sysfs_scheme_filters {
struct kobject kobj;
struct damon_sysfs_scheme_filter **filters_arr;
int nr;
};
@ -401,6 +407,57 @@ damon_sysfs_scheme_filters_alloc(void)
return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
}
static void damon_sysfs_scheme_filters_rm_dirs(
struct damon_sysfs_scheme_filters *filters)
{
struct damon_sysfs_scheme_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_scheme_filters_add_dirs(
struct damon_sysfs_scheme_filters *filters, int nr_filters)
{
struct damon_sysfs_scheme_filter **filters_arr, *filter;
int err, i;
damon_sysfs_scheme_filters_rm_dirs(filters);
if (!nr_filters)
return 0;
filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
GFP_KERNEL | __GFP_NOWARN);
if (!filters_arr)
return -ENOMEM;
filters->filters_arr = filters_arr;
for (i = 0; i < nr_filters; i++) {
filter = damon_sysfs_scheme_filter_alloc();
if (!filter) {
damon_sysfs_scheme_filters_rm_dirs(filters);
return -ENOMEM;
}
err = kobject_init_and_add(&filter->kobj,
&damon_sysfs_scheme_filter_ktype,
&filters->kobj, "%d", i);
if (err) {
kobject_put(&filter->kobj);
damon_sysfs_scheme_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)
{
@ -413,6 +470,7 @@ static ssize_t nr_filters_show(struct kobject *kobj,
static ssize_t nr_filters_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
struct damon_sysfs_scheme_filters *filters;
int nr, err = kstrtoint(buf, 0, &nr);
if (err)
@ -420,6 +478,15 @@ static ssize_t nr_filters_store(struct kobject *kobj,
if (nr < 0)
return -EINVAL;
filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
if (!mutex_trylock(&damon_sysfs_lock))
return -EBUSY;
err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
mutex_unlock(&damon_sysfs_lock);
if (err)
return err;
return count;
}
@ -1166,6 +1233,7 @@ static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
damon_sysfs_quotas_rm_dirs(scheme->quotas);
kobject_put(&scheme->quotas->kobj);
kobject_put(&scheme->watermarks->kobj);
damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
kobject_put(&scheme->filters->kobj);
kobject_put(&scheme->stats->kobj);
damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);