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

mm/dynamic_hugetlb: free pages to dhugetlb_pool

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


CVE: NA

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

Add function to free page to dhugetlb_pool.

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 32d6d14f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ void __init dynamic_hugetlb_init(void);

struct page *alloc_page_from_dhugetlb_pool(gfp_t gfp, unsigned int order,
					   unsigned int flags);
bool free_page_to_dhugetlb_pool(struct page *page);
void free_page_list_to_dhugetlb_pool(struct list_head *list);
int task_has_mem_in_hpool(struct task_struct *tsk);

#else
@@ -118,6 +120,13 @@ static inline struct page *alloc_page_from_dhugetlb_pool(gfp_t gfp, unsigned int
{
	return NULL;
}
static inline bool free_page_to_dhugetlb_pool(struct page *page)
{
	return false;
}
static inline void free_page_list_to_dhugetlb_pool(struct list_head *list)
{
}
static inline int task_has_mem_in_hpool(struct task_struct *tsk)
{
	return 0;
+68 −0
Original line number Diff line number Diff line
@@ -378,6 +378,18 @@ static int set_hpool_in_dhugetlb_pagelist(unsigned long idx, struct dhugetlb_poo
	return 0;
}

static struct dhugetlb_pool *find_hpool_by_dhugetlb_pagelist(struct page *page)
{
	unsigned long idx = hugepage_index(page_to_pfn(page));
	struct dhugetlb_pool *hpool = NULL;

	read_lock(&dhugetlb_pagelist_rwlock);
	if (idx < dhugetlb_pagelist_t->count)
		hpool = dhugetlb_pagelist_t->hpool[idx];
	read_unlock(&dhugetlb_pagelist_rwlock);
	return hpool;
}

static struct dhugetlb_pool *find_hpool_by_task(struct task_struct *tsk)
{
	struct mem_cgroup *memcg;
@@ -485,6 +497,62 @@ struct page *alloc_page_from_dhugetlb_pool(gfp_t gfp, unsigned int order,
	return page;
}

static void __free_page_to_dhugetlb_pool(struct page *page)
{
	struct percpu_pages_pool *percpu_pool;
	struct dhugetlb_pool *hpool;
	unsigned long flags;

	hpool = find_hpool_by_dhugetlb_pagelist(page);

	if (!get_hpool_unless_zero(hpool)) {
		pr_err("dhugetlb: free error: get hpool failed\n");
		return;
	}

	percpu_pool = &hpool->percpu_pool[smp_processor_id()];
	spin_lock_irqsave(&percpu_pool->lock, flags);

	ClearPagePool(page);
	list_add(&page->lru, &percpu_pool->head_page);
	percpu_pool->free_pages++;
	percpu_pool->used_pages--;
	if (percpu_pool->free_pages > PERCPU_POOL_PAGE_MAX) {
		spin_lock(&hpool->lock);
		reclaim_pages_from_percpu_pool(hpool, percpu_pool, PERCPU_POOL_PAGE_BATCH);
		spin_unlock(&hpool->lock);
	}

	spin_unlock_irqrestore(&percpu_pool->lock, flags);
	put_hpool(hpool);
}

bool free_page_to_dhugetlb_pool(struct page *page)
{
	if (!dhugetlb_enabled || !PagePool(page))
		return false;

	if (free_pages_prepare(page, 0, true))
		__free_page_to_dhugetlb_pool(page);
	return true;
}

void free_page_list_to_dhugetlb_pool(struct list_head *list)
{
	struct page *page, *next;

	if (!dhugetlb_enabled)
		return;

	list_for_each_entry_safe(page, next, list, lru) {
		if (PagePool(page)) {
			list_del(&page->lru);
			if (free_pages_prepare(page, 0, true))
				__free_page_to_dhugetlb_pool(page);
		}
	}
}

static int alloc_hugepage_from_hugetlb(struct dhugetlb_pool *hpool,
				       unsigned long nid, unsigned long nr_pages)
{
+7 −0
Original line number Diff line number Diff line
@@ -3230,6 +3230,10 @@ void free_unref_page(struct page *page)
	unsigned long flags;
	unsigned long pfn = page_to_pfn(page);

	/* Free dynamic hugetlb page */
	if (free_page_to_dhugetlb_pool(page))
		return;

	if (!free_unref_page_prepare(page, pfn))
		return;

@@ -3247,6 +3251,9 @@ void free_unref_page_list(struct list_head *list)
	unsigned long flags, pfn;
	int batch_count = 0;

	/* Free dynamic hugetlb page list */
	free_page_list_to_dhugetlb_pool(list);

	/* Prepare pages for freeing */
	list_for_each_entry_safe(page, next, list, lru) {
		pfn = page_to_pfn(page);