hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S9BY CVE: NA
--------------------------------
Add two interfaces to configure the count of 1G/2M hugepages. `echo <number> > dhugetlb.1G.reserved_page` `echo <number> > dhugetlb.2M.reserved_page`
Signed-off-by: Liu Shixin liushixin2@huawei.com --- include/linux/dynamic_pool.h | 8 +++++ mm/dynamic_pool.c | 57 ++++++++++++++++++++++++++++++++++++ mm/memcontrol.c | 46 +++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+)
diff --git a/include/linux/dynamic_pool.h b/include/linux/dynamic_pool.h index b58820affa60..3a7c1ed9adf6 100644 --- a/include/linux/dynamic_pool.h +++ b/include/linux/dynamic_pool.h @@ -22,6 +22,12 @@ struct pages_pool { unsigned long free_pages; unsigned long used_pages; struct list_head freelist; + + /* Used for hugepage allocation */ + unsigned long nr_huge_pages; + unsigned long free_huge_pages; + unsigned long resv_huge_pages; + unsigned long used_huge_pages; };
struct dynamic_pool_ops; @@ -49,6 +55,8 @@ 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); +int dynamic_pool_reserve_hugepage(struct mem_cgroup *memcg, + unsigned long nr_pages, int type);
#else struct dynamic_pool {}; diff --git a/mm/dynamic_pool.c b/mm/dynamic_pool.c index 6492ae074de7..6f596078685b 100644 --- a/mm/dynamic_pool.c +++ b/mm/dynamic_pool.c @@ -430,6 +430,22 @@ void dynamic_pool_show(struct mem_cgroup *memcg, struct seq_file *m)
seq_printf(m, "nid %d\n", dpool->nid); seq_printf(m, "dhugetlb_total_pages %lu\n", dpool->total_pages); + seq_printf(m, "1G_total_reserved_pages %lu\n", + dpool->pool[PAGES_POOL_1G].nr_huge_pages); + seq_printf(m, "1G_free_reserved_pages %lu\n", + dpool->pool[PAGES_POOL_1G].free_huge_pages); + seq_printf(m, "1G_mmap_reserved_pages %lu\n", + dpool->pool[PAGES_POOL_1G].resv_huge_pages); + seq_printf(m, "1G_used_pages %lu\n", + dpool->pool[PAGES_POOL_1G].used_huge_pages); + seq_printf(m, "2M_total_reserved_pages %lu\n", + dpool->pool[PAGES_POOL_2M].nr_huge_pages); + seq_printf(m, "2M_free_reserved_pages %lu\n", + dpool->pool[PAGES_POOL_2M].free_huge_pages); + seq_printf(m, "2M_mmap_reserved_pages %lu\n", + dpool->pool[PAGES_POOL_2M].resv_huge_pages); + seq_printf(m, "2M_used_pages %lu\n", + dpool->pool[PAGES_POOL_2M].used_huge_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", @@ -442,3 +458,44 @@ void dynamic_pool_show(struct mem_cgroup *memcg, struct seq_file *m) spin_unlock(&dpool->lock); dpool_put(dpool); } + +int dynamic_pool_reserve_hugepage(struct mem_cgroup *memcg, + unsigned long nr_pages, int type) +{ + struct dynamic_pool *dpool; + struct pages_pool *pool; + unsigned long delta; + int ret = -EINVAL; + + if (!dpool_enabled) + return -EINVAL; + + mutex_lock(&dpool_mutex); + + dpool = dpool_get_from_memcg(memcg); + if (!dpool) + goto unlock; + + pool = &dpool->pool[type]; + spin_lock(&dpool->lock); + if (nr_pages > pool->nr_huge_pages) { + delta = min(nr_pages - pool->nr_huge_pages, pool->free_pages); + pool->nr_huge_pages += delta; + pool->free_huge_pages += delta; + pool->free_pages -= delta; + } else { + delta = min(pool->nr_huge_pages - nr_pages, + pool->free_huge_pages - pool->resv_huge_pages); + pool->nr_huge_pages -= delta; + pool->free_huge_pages -= delta; + pool->free_pages += delta; + } + spin_unlock(&dpool->lock); + dpool_put(dpool); + ret = 0; + +unlock: + mutex_unlock(&dpool_mutex); + + return ret; +} diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 86f6ebb2d978..06fc891a1988 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5786,6 +5786,42 @@ static int mem_cgroup_dpool_read(struct seq_file *m, void *v)
return 0; } + +static ssize_t mem_cgroup_dpool_1G_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)); + char *endp; + unsigned long nr_pages; + int ret; + + buf = strstrip(buf); + nr_pages = memparse(buf, &endp); + if (*endp != '\0') + return -EINVAL; + + ret = dynamic_pool_reserve_hugepage(memcg, nr_pages, PAGES_POOL_1G); + + return ret ? : nbytes; +} + +static ssize_t mem_cgroup_dpool_2M_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)); + char *endp; + unsigned long nr_pages; + int ret; + + buf = strstrip(buf); + nr_pages = memparse(buf, &endp); + if (*endp != '\0') + return -EINVAL; + + ret = dynamic_pool_reserve_hugepage(memcg, nr_pages, PAGES_POOL_2M); + + return ret ? : nbytes; +} #endif
static int memory_stat_show(struct seq_file *m, void *v); @@ -6156,6 +6192,16 @@ static struct cftype mem_cgroup_legacy_files[] = { .seq_show = mem_cgroup_dpool_read, .flags = CFTYPE_NO_PREFIX | CFTYPE_WORLD_WRITABLE | CFTYPE_NOT_ON_ROOT, }, + { + .name = "dhugetlb.1G.reserved_pages", + .write = mem_cgroup_dpool_1G_write, + .flags = CFTYPE_NO_PREFIX | CFTYPE_WORLD_WRITABLE | CFTYPE_NOT_ON_ROOT, + }, + { + .name = "dhugetlb.2M.reserved_pages", + .write = mem_cgroup_dpool_2M_write, + .flags = CFTYPE_NO_PREFIX | CFTYPE_WORLD_WRITABLE | CFTYPE_NOT_ON_ROOT, + }, #endif { }, /* terminate */ };