Commit 11cb2f9f authored by Liu Shixin's avatar Liu Shixin
Browse files

mm/dynamic_pool: create dpool by dhugetlb.nr_pages interface

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8S9BY


CVE: NA

--------------------------------

With new interface "dhugetlb.nr_pages", the user can create a dpool in
memcg.

To enable dpool, "dynamic_hugetlb=on" should be added to kernel parameters.

Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent c4b558d5
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -32,12 +32,21 @@ struct dynamic_pool {
	spinlock_t lock;
	struct pages_pool pool[PAGES_POOL_MAX];

	/* Used for dynamic hugetlb */
	int nid;
	unsigned long total_pages;

	KABI_RESERVE(1)
};

void dynamic_pool_inherit(struct mem_cgroup *memcg);
int dynamic_pool_destroy(struct cgroup *cgrp, bool *clear_css_online);

bool dynamic_pool_hide_files(struct cftype *cft);
int dynamic_pool_add_memory(struct mem_cgroup *memcg, int nid,
			    unsigned long size);
void dynamic_pool_show(struct mem_cgroup *memcg, struct seq_file *m);

#else
struct dynamic_pool {};

@@ -50,5 +59,12 @@ static inline int dynamic_pool_destroy(struct cgroup *cgrp,
{
	return 0;
}

#ifdef CONFIG_CGROUPS
static inline bool dynamic_pool_hide_files(struct cftype *cft)
{
	return false;
}
#endif
#endif /* CONFIG_DYNAMIC_POOL */
#endif /* __LINUX_DYNAMIC_POOL_H */
+2 −0
Original line number Diff line number Diff line
@@ -4330,6 +4330,8 @@ static int cgroup_addrm_files(struct cgroup_subsys_state *css,
			continue;
		if ((cft->flags & CFTYPE_DEBUG) && !cgroup_debug)
			continue;
		if (dynamic_pool_hide_files(cft))
			continue;
		if (is_add) {
			ret = cgroup_add_file(css, cgrp, cft);
			if (ret) {
+91 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@

#include <linux/dynamic_pool.h>

static bool enable_dhugetlb;

/* Indicate the enabled of dynamic pool */
DEFINE_STATIC_KEY_FALSE(dynamic_pool_key);

@@ -160,9 +162,98 @@ int dynamic_pool_destroy(struct cgroup *cgrp, bool *clear_css_online)

static int __init dynamic_pool_init(void)
{
	if (!enable_dhugetlb)
		return 0;

	static_branch_enable(&dynamic_pool_key);
	pr_info("enabled\n");

	return 0;
}
subsys_initcall(dynamic_pool_init);

/* === Dynamic hugetlb interface ====================================== */

static int __init dynamic_hugetlb_setup(char *buf)
{
	return kstrtobool(buf, &enable_dhugetlb);
}
early_param("dynamic_hugetlb", dynamic_hugetlb_setup);

/* If dynamic pool is disabled, hide the interface */
bool dynamic_pool_hide_files(struct cftype *cft)
{
	if (dpool_enabled && enable_dhugetlb)
		return false;

	return !!strstr(cft->name, "dhugetlb");
}

int dynamic_pool_add_memory(struct mem_cgroup *memcg, int nid,
			    unsigned long size)
{
	struct dynamic_pool *dpool;
	int ret = -EINVAL;

	if (!dpool_enabled)
		return -EINVAL;

	mutex_lock(&dpool_mutex);

	if (!(memcg->css.cgroup->self.flags & CSS_ONLINE)) {
		pr_err("add memory failed, memcg is going offline\n");
		goto unlock;
	}

	dpool = memcg->dpool;
	if (!dpool) {
		dpool = dpool_create(memcg);
		if (!dpool)
			goto unlock;

		dpool->nid = nid;
	} else if (dpool->memcg != memcg) {
		pr_err("add memory failed, not parent memcg\n");
		goto unlock;
	} else if (dpool->nid != nid) {
		pr_err("add memory failed, not target nid(%d)\n",
			dpool->nid);
		goto unlock;
	}
	ret = 0;

unlock:
	mutex_unlock(&dpool_mutex);

	return ret;
}

void dynamic_pool_show(struct mem_cgroup *memcg, struct seq_file *m)
{
	struct dynamic_pool *dpool;

	if (!dpool_enabled || !memcg)
		return;

	dpool = dpool_get_from_memcg(memcg);
	if (!dpool) {
		seq_puts(m, "Current hierarchial have not memory pool.\n");
		return;
	}

	spin_lock(&dpool->lock);

	seq_printf(m, "nid %d\n", dpool->nid);
	seq_printf(m, "dhugetlb_total_pages %lu\n", dpool->total_pages);
	seq_printf(m, "1G_free_unreserved_pages %lu\n",
		   dpool->pool[PAGES_POOL_1G].free_pages);
	seq_printf(m, "2M_free_unreserved_pages %lu\n",
		   dpool->pool[PAGES_POOL_2M].free_pages);
	seq_printf(m, "4K_free_pages %lu\n",
		   dpool->pool[PAGES_POOL_4K].free_pages);
	seq_printf(m, "4K_used_pages %lu\n",
		   dpool->pool[PAGES_POOL_4K].used_pages);

	spin_unlock(&dpool->lock);
	dpool_put(dpool);
}
+47 −0
Original line number Diff line number Diff line
@@ -5749,6 +5749,45 @@ static ssize_t memory_ksm_write(struct kernfs_open_file *of, char *buf,
}
#endif /* CONFIG_KSM */

#ifdef CONFIG_DYNAMIC_POOL
static ssize_t mem_cgroup_dpool_write(struct kernfs_open_file *of,
				      char *buf, size_t nbytes, loff_t off)
{
	struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
	unsigned long size;
	int nid;
	char *endp;
	int ret = -EINVAL;

	buf = strstrip(buf);
	nid = memparse(buf, &endp);
	if (*endp != ' ')
		goto out;

	if (nid < 0 || nid >= MAX_NUMNODES || !node_online(nid))
		goto out;

	buf = endp + 1;
	size = memparse(buf, &endp);
	if (*endp != '\0' || size == 0)
		goto out;

	ret = dynamic_pool_add_memory(memcg, nid, size);

out:
	return ret ? : nbytes;
}

static int mem_cgroup_dpool_read(struct seq_file *m, void *v)
{
	struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));

	dynamic_pool_show(memcg, m);

	return 0;
}
#endif

static int memory_stat_show(struct seq_file *m, void *v);

#ifdef CONFIG_MEMCG_V1_RECLAIM
@@ -6109,6 +6148,14 @@ static struct cftype mem_cgroup_legacy_files[] = {
		.write = memcg_swapfile_write,
		.seq_show = memcg_swapfile_read,
	},
#endif
#ifdef CONFIG_DYNAMIC_POOL
	{
		.name = "dhugetlb.nr_pages",
		.write = mem_cgroup_dpool_write,
		.seq_show = mem_cgroup_dpool_read,
		.flags = CFTYPE_NO_PREFIX | CFTYPE_WORLD_WRITABLE | CFTYPE_NOT_ON_ROOT,
	},
#endif
	{ },	/* terminate */
};