Commit a8a836a3 authored by Liu Shixin's avatar Liu Shixin Committed by Zheng Zengkai
Browse files

mm/dynamic_hugetlb: establish the dynamic hugetlb feature framework

hulk inclusion
category: feature
bugzilla: 46904, https://gitee.com/openeuler/kernel/issues/I4QSHG


CVE: NA

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

Dynamic hugetlb is a self-developed feature based on the hugetlb and memcontrol.
It supports to split huge page dynamically in a memory cgroup. There is a new structure
dhugetlb_pool in every mem_cgroup to manage the pages configured to the mem_cgroup.
For the mem_cgroup configured with dhugetlb_pool, processes in the mem_cgroup will
preferentially use the pages in dhugetlb_pool.

Dynamic hugetlb supports three types of pages, including 1G/2M huge pages and 4K pages.
For the mem_cgroup configured with dhugetlb_pool, processes will be limited to alloc
1G/2M huge pages only from dhugetlb_pool. But there is no such constraint for 4K pages.
If there are insufficient 4K pages in the dhugetlb_pool, pages can also be allocated from
buddy system. So before using dynamic hugetlb, user must know how many huge pages they
need.

Usage:
1. Add 'dynamic_hugetlb=on' in cmdline to enable dynamic hugetlb feature.
2. Prealloc some 1G hugepages through hugetlb.
3. Create a mem_cgroup and configure dhugetlb_pool to mem_cgroup.
4. Configure the count of 1G/2M hugepages, and the remaining pages in dhugetlb_pool will
   be used as basic pages.
5. Bound a process to mem_cgroup. then the memory for it will be allocated from dhugetlb_pool.

This patch add the corresponding structure dhugetlb_pool for dynamic hugetlb feature,
the interface 'dhugetlb.nr_pages' in mem_cgroup to configure dhugetlb_pool and the cmdline
'dynamic_hugetlb=on' to enable dynamic hugetlb feature.

Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 5f53feed
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -251,6 +251,16 @@ config HUGETLB_PAGE_FREE_VMEMMAP_DEFAULT_ON
	  to enable freeing vmemmap pages of HugeTLB by default. It can then
	  be disabled on the command line via hugetlb_free_vmemmap=off.

config DYNAMIC_HUGETLB
	bool "Dynamic HugeTLB"
	depends on X86_64
	depends on HUGETLBFS
	depends on MEMCG && CGROUP_HUGETLB
	help
	  Dynamic hugepage are used in memcg and can be splited into small
	  pages automatically. The tasks in the memcg prefer to alloc dynamic
	  hugepage.

config MEMFD_CREATE
	def_bool TMPFS || HUGETLBFS

+106 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __LINUX_DYNAMIC_HUGETLB_H
#define __LINUX_DYNAMIC_HUGETLB_H

#include <linux/hugetlb.h>
#include <linux/memcontrol.h>

#ifdef CONFIG_DYNAMIC_HUGETLB

extern struct static_key_false dhugetlb_enabled_key;
#define dhugetlb_enabled (static_branch_unlikely(&dhugetlb_enabled_key))

#define NR_PERCPU_POOL		num_possible_cpus()
#define PERCPU_POOL_PAGE_MAX	1024
#define PERCPU_POOL_PAGE_BATCH	(PERCPU_POOL_PAGE_MAX >> 2)

struct split_hugepage {
	struct list_head head_pages;
	unsigned long start_pfn;
};

struct percpu_pages_pool {
	spinlock_t lock;
	unsigned long free_pages;
	long used_pages;
	struct list_head head_page;
};

struct huge_pages_pool {
	/*
	 * This four counts is used for huge page allocation.
	 */
	unsigned long nr_huge_pages;
	unsigned long free_huge_pages;
	unsigned long resv_huge_pages;
	unsigned long used_huge_pages;
	/*
	 * free_normal_pages means how many huge pages can be split to
	 * smaller pages or reserved for huge page allocation.
	 */
	unsigned long free_normal_pages;
	/*
	 * split_normal_pages means how many huge pages have already been
	 * split.
	 */
	unsigned long split_normal_pages;
	struct list_head hugepage_freelists;
	/* Used to record which hugepages have been split */
	struct list_head hugepage_splitlists;
};

enum huge_pages_pool_type {
	HUGE_PAGES_POOL_1G,
	HUGE_PAGES_POOL_2M,
	HUGE_PAGES_POOL_4K,
	HUGE_PAGES_POOL_MAX,
};
/*
 * Dynamic hugetlb pool data structure. Each Dynamic hugetlb pool is
 * associated with one memory cgroup and controls the allocation of memory
 * resources for both processes and files which belongs to the memory cgroup.
 */
struct dhugetlb_pool {
	int nid;
	spinlock_t lock;
	spinlock_t reserved_lock;
	atomic_t refcnt;
	unsigned long normal_pages_disabled;

	struct mem_cgroup *attach_memcg;

	unsigned long total_huge_pages;
	struct huge_pages_pool hpages_pool[HUGE_PAGES_POOL_MAX];
	struct percpu_pages_pool percpu_pool[0];
};

bool dhugetlb_hide_files(struct cftype *cft);
ssize_t write_hugepage_to_hpool(struct kernfs_open_file *of,
				char *buf, size_t nbytes, loff_t off);
int hugetlb_pool_info_show(struct seq_file *m, void *v);
void hugetlb_pool_inherit(struct mem_cgroup *memcg, struct mem_cgroup *parent);
int hugetlb_pool_destroy(struct cgroup *cgrp);
void __init dynamic_hugetlb_init(void);

#else

#define dhugetlb_enabled	0

struct dhugetlb_pool {};

static inline bool dhugetlb_hide_files(struct cftype *cft)
{
	return false;
}
static inline void hugetlb_pool_inherit(struct mem_cgroup *memcg, struct mem_cgroup *parent)
{
}
static inline int hugetlb_pool_destroy(struct cgroup *cgrp)
{
	return 0;
}
static inline void __init dynamic_hugetlb_init(void)
{
}
#endif /* CONFIG_DYNAMIC_HUGETLB */
#endif /* __LINUX_DYNAMIC_HUGETLB_H */
+4 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/writeback.h>
#include <linux/page-flags.h>
#include <linux/kabi.h>
#include <linux/dynamic_hugetlb.h>

struct mem_cgroup;
struct obj_cgroup;
@@ -370,6 +371,9 @@ struct mem_cgroup {
	struct deferred_split deferred_split_queue;
#endif

#ifdef CONFIG_DYNAMIC_HUGETLB
	struct dhugetlb_pool *hpool;
#endif
	KABI_RESERVE(1)
	KABI_RESERVE(2)
	KABI_RESERVE(3)
@@ -1238,7 +1242,6 @@ void split_page_memcg(struct page *head, unsigned int nr);
unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
						gfp_t gfp_mask,
						unsigned long *total_scanned);

/*
 * Test whether @memcg has children, dead or alive.  Note that this
 * function doesn't care whether @memcg has use_hierarchy enabled and
+11 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
#include <linux/fs_parser.h>
#include <linux/sched/cputime.h>
#include <linux/psi.h>
#include <linux/dynamic_hugetlb.h>
#include <net/sock.h>

#define CREATE_TRACE_POINTS
@@ -4009,6 +4010,9 @@ static int cgroup_addrm_files(struct cgroup_subsys_state *css,
			continue;
		if ((cft->flags & CFTYPE_DEBUG) && !cgroup_debug)
			continue;
		/* if dynamic hugetlb is not enabled, hide the interfaces */
		if (dhugetlb_hide_files(cft))
			continue;
		if (is_add) {
			ret = cgroup_add_file(css, cgrp, cft);
			if (ret) {
@@ -5609,6 +5613,13 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
	if (css_has_online_children(&cgrp->self))
		return -EBUSY;

	/*
	 * If dynamic hugetlb is enabled, make sure dhugtlb_pool is free
	 * before removing the corresponding memory cgroup.
	 */
	if (hugetlb_pool_destroy(cgrp))
		return -EBUSY;

	/*
	 * Mark @cgrp and the associated csets dead.  The former prevents
	 * further task migration and child creation by disabling
+1 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ obj-$(CONFIG_ZSWAP) += zswap.o
obj-$(CONFIG_HAS_DMA)	+= dmapool.o
obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
obj-$(CONFIG_HUGETLB_PAGE_FREE_VMEMMAP)	+= hugetlb_vmemmap.o
obj-$(CONFIG_DYNAMIC_HUGETLB) += dynamic_hugetlb.o
obj-$(CONFIG_NUMA) 	+= mempolicy.o
obj-$(CONFIG_SPARSEMEM)	+= sparse.o
obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
Loading