Commit 29cbb9a1 authored by SeongJae Park's avatar SeongJae Park Committed by Andrew Morton

mm/damon/sysfs-schemes: implement scheme filters

Implement scheme filters functionality of DAMON sysfs interface by making
the code reads the values of files under the filter directories and pass
that to DAMON using DAMON kernel API.

[sj@kernel.org: fix leaking a filter for wrong cgroup path]
  Link: https://lkml.kernel.org/r/20221219171807.55708-2-sj@kernel.org
[sj@kernel.org: return an error for filter memcg path id lookup failure]
  Link: https://lkml.kernel.org/r/20221219171807.55708-3-sj@kernel.org
Link: https://lkml.kernel.org/r/20221205230830.144349-9-sj@kernel.orgSigned-off-by: default avatarSeongJae Park <sj@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 472e2b70
...@@ -1403,6 +1403,79 @@ struct kobj_type damon_sysfs_schemes_ktype = { ...@@ -1403,6 +1403,79 @@ struct kobj_type damon_sysfs_schemes_ktype = {
.default_groups = damon_sysfs_schemes_groups, .default_groups = damon_sysfs_schemes_groups,
}; };
static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
char *memcg_path_buf, char *path)
{
#ifdef CONFIG_MEMCG
cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
if (sysfs_streq(memcg_path_buf, path))
return true;
#endif /* CONFIG_MEMCG */
return false;
}
static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
{
struct mem_cgroup *memcg;
char *path;
bool found = false;
if (!memcg_path)
return -EINVAL;
path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
if (!path)
return -ENOMEM;
for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
/* skip removed memcg */
if (!mem_cgroup_id(memcg))
continue;
if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
*id = mem_cgroup_id(memcg);
found = true;
break;
}
}
kfree(path);
return found ? 0 : -EINVAL;
}
static int damon_sysfs_set_scheme_filters(struct damos *scheme,
struct damon_sysfs_scheme_filters *sysfs_filters)
{
int i;
struct damos_filter *filter, *next;
damos_for_each_filter_safe(filter, next, scheme)
damos_destroy_filter(filter);
for (i = 0; i < sysfs_filters->nr; i++) {
struct damon_sysfs_scheme_filter *sysfs_filter =
sysfs_filters->filters_arr[i];
struct damos_filter *filter =
damos_new_filter(sysfs_filter->type,
sysfs_filter->matching);
int err;
if (!filter)
return -ENOMEM;
if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
err = damon_sysfs_memcg_path_to_id(
sysfs_filter->memcg_path,
&filter->memcg_id);
if (err) {
damos_destroy_filter(filter);
return err;
}
}
damos_add_filter(scheme, filter);
}
return 0;
}
static struct damos *damon_sysfs_mk_scheme( static struct damos *damon_sysfs_mk_scheme(
struct damon_sysfs_scheme *sysfs_scheme) struct damon_sysfs_scheme *sysfs_scheme)
{ {
...@@ -1411,6 +1484,10 @@ static struct damos *damon_sysfs_mk_scheme( ...@@ -1411,6 +1484,10 @@ static struct damos *damon_sysfs_mk_scheme(
struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
struct damon_sysfs_scheme_filters *sysfs_filters =
sysfs_scheme->filters;
struct damos *scheme;
int err;
struct damos_access_pattern pattern = { struct damos_access_pattern pattern = {
.min_sz_region = access_pattern->sz->min, .min_sz_region = access_pattern->sz->min,
...@@ -1436,8 +1513,17 @@ static struct damos *damon_sysfs_mk_scheme( ...@@ -1436,8 +1513,17 @@ static struct damos *damon_sysfs_mk_scheme(
.low = sysfs_wmarks->low, .low = sysfs_wmarks->low,
}; };
return damon_new_scheme(&pattern, sysfs_scheme->action, &quota, scheme = damon_new_scheme(&pattern, sysfs_scheme->action, &quota,
&wmarks); &wmarks);
if (!scheme)
return NULL;
err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters);
if (err) {
damon_destroy_scheme(scheme);
return NULL;
}
return scheme;
} }
static void damon_sysfs_update_scheme(struct damos *scheme, static void damon_sysfs_update_scheme(struct damos *scheme,
...@@ -1448,6 +1534,7 @@ static void damon_sysfs_update_scheme(struct damos *scheme, ...@@ -1448,6 +1534,7 @@ static void damon_sysfs_update_scheme(struct damos *scheme,
struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
int err;
scheme->pattern.min_sz_region = access_pattern->sz->min; scheme->pattern.min_sz_region = access_pattern->sz->min;
scheme->pattern.max_sz_region = access_pattern->sz->max; scheme->pattern.max_sz_region = access_pattern->sz->max;
...@@ -1470,6 +1557,10 @@ static void damon_sysfs_update_scheme(struct damos *scheme, ...@@ -1470,6 +1557,10 @@ static void damon_sysfs_update_scheme(struct damos *scheme,
scheme->wmarks.high = sysfs_wmarks->high; scheme->wmarks.high = sysfs_wmarks->high;
scheme->wmarks.mid = sysfs_wmarks->mid; scheme->wmarks.mid = sysfs_wmarks->mid;
scheme->wmarks.low = sysfs_wmarks->low; scheme->wmarks.low = sysfs_wmarks->low;
err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters);
if (err)
damon_destroy_scheme(scheme);
} }
int damon_sysfs_set_schemes(struct damon_ctx *ctx, int damon_sysfs_set_schemes(struct damon_ctx *ctx,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment