Commit 7ee161f1 authored by SeongJae Park's avatar SeongJae Park Committed by Andrew Morton
Browse files

mm/damon/sysfs-schemes: implement filter directory

Implement DAMOS filter directory which will be located under the filters
directory.  The directory provides three files, namely type, matching, and
memcg_path.  'type' and 'matching' will be directly connected to the
fields of 'struct damos_filter' having same name.  'memcg_path' will
receive the path of the memory cgroup of the interest and later converted
to memcg id when it's committed.

Link: https://lkml.kernel.org/r/20221205230830.144349-7-sj@kernel.org


Signed-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 ac35264b
Loading
Loading
Loading
Loading
+128 −0
Original line number Diff line number Diff line
@@ -258,6 +258,134 @@ static struct kobj_type damon_sysfs_stats_ktype = {
	.default_groups = damon_sysfs_stats_groups,
};

/*
 * filter directory
 */

struct damon_sysfs_scheme_filter {
	struct kobject kobj;
	enum damos_filter_type type;
	bool matching;
	char *memcg_path;
};

/* Should match with enum damos_filter_type */
static const char * const damon_sysfs_scheme_filter_type_strs[] = {
	"anon",
	"memcg",
};

static ssize_t type_show(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);

	return sysfs_emit(buf, "%s\n",
			damon_sysfs_scheme_filter_type_strs[filter->type]);
}

static ssize_t type_store(struct kobject *kobj,
		struct kobj_attribute *attr, const char *buf, size_t count)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);
	enum damos_filter_type type;
	ssize_t ret = -EINVAL;

	for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
		if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
					type])) {
			filter->type = type;
			ret = count;
			break;
		}
	}
	return ret;
}

static ssize_t matching_show(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);

	return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
}

static ssize_t matching_store(struct kobject *kobj,
		struct kobj_attribute *attr, const char *buf, size_t count)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);
	bool matching;
	int err = kstrtobool(buf, &matching);

	if (err)
		return err;

	filter->matching = matching;
	return count;
}

static ssize_t memcg_path_show(struct kobject *kobj,
		struct kobj_attribute *attr, char *buf)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);

	return sysfs_emit(buf, "%s\n",
			filter->memcg_path ? filter->memcg_path : "");
}

static ssize_t memcg_path_store(struct kobject *kobj,
		struct kobj_attribute *attr, const char *buf, size_t count)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);
	char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);

	if (!path)
		return -ENOMEM;

	strncpy(path, buf, count);
	path[count] = '\0';
	filter->memcg_path = path;
	return count;
}

static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
{
	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
			struct damon_sysfs_scheme_filter, kobj);

	kfree(filter->memcg_path);
	kfree(filter);
}

static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
		__ATTR_RW_MODE(type, 0600);

static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
		__ATTR_RW_MODE(matching, 0600);

static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
		__ATTR_RW_MODE(memcg_path, 0600);

static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
	&damon_sysfs_scheme_filter_type_attr.attr,
	&damon_sysfs_scheme_filter_matching_attr.attr,
	&damon_sysfs_scheme_filter_memcg_path_attr.attr,
	NULL,
};
ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);

static struct kobj_type damon_sysfs_scheme_filter_ktype = {
	.release = damon_sysfs_scheme_filter_release,
	.sysfs_ops = &kobj_sysfs_ops,
	.default_groups = damon_sysfs_scheme_filter_groups,
};

/*
 * filters directory
 */