Commit 6e395bb9 authored by Liu Shixin's avatar Liu Shixin
Browse files

mm/dynamic_pool: compatible with memory hwpoison

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


CVE: NA

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

When handle hwpoison on free pages in dpool, failed will eventually be
reported because they are not in buddy system or can not be dissolved.

But actually, it is safe because there are gatekeeper in allocation path
to make sure it can not be used and there are gatekeeper in demotion and
promotion path to make sure it can not pollute other pages.

Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent cf082a0e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3965,6 +3965,7 @@ enum mf_action_page_type {
	MF_MSG_BUDDY,
	MF_MSG_DAX,
	MF_MSG_UNSPLIT_THP,
	MF_MSG_FREE_DPOOL,
	MF_MSG_UNKNOWN,
};

+1 −0
Original line number Diff line number Diff line
@@ -373,6 +373,7 @@ TRACE_EVENT(aer_event,
	EM ( MF_MSG_BUDDY, "free buddy page" )				\
	EM ( MF_MSG_DAX, "dax page" )					\
	EM ( MF_MSG_UNSPLIT_THP, "unsplit thp" )			\
	EM ( MF_MSG_FREE_DPOOL, "free dynamic pool page" )		\
	EMe ( MF_MSG_UNKNOWN, "unknown page" )

/*
+14 −2
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#include <linux/pagewalk.h>
#include <linux/shmem_fs.h>
#include <linux/sysctl.h>
#include <linux/dynamic_pool.h>
#include "swap.h"
#include "internal.h"
#include "ras/ras_event.h"
@@ -893,6 +894,7 @@ static const char * const action_page_types[] = {
	[MF_MSG_BUDDY]			= "free buddy page",
	[MF_MSG_DAX]			= "dax page",
	[MF_MSG_UNSPLIT_THP]		= "unsplit thp",
	[MF_MSG_FREE_DPOOL]		= "free dynamic pool page",
	[MF_MSG_UNKNOWN]		= "unknown page",
};

@@ -1376,7 +1378,8 @@ static inline bool HWPoisonHandlable(struct page *page, unsigned long flags)
	if ((flags & MF_SOFT_OFFLINE) && __PageMovable(page))
		return true;

	return PageLRU(page) || is_free_buddy_page(page);
	return PageLRU(page) || is_free_buddy_page(page) ||
	       page_in_dynamic_pool(page);
}

static int __get_hwpoison_page(struct page *page, unsigned long flags)
@@ -1432,7 +1435,8 @@ static int get_any_page(struct page *p, unsigned long flags)
				if (pass++ < 3)
					goto try_again;
				ret = -EBUSY;
			} else if (!PageHuge(p) && !is_free_buddy_page(p)) {
			} else if (!PageHuge(p) && !is_free_buddy_page(p) &&
				   !page_in_dynamic_pool(p)) {
				/* We raced with put_page, retry. */
				if (pass++ < 3)
					goto try_again;
@@ -1983,6 +1987,8 @@ int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
		count_increased = true;
	} else if (folio_test_hugetlb_freed(folio)) {
		ret = 0;
	} else if (page_in_dynamic_pool(folio_page(folio, 0))) {
		ret = 0;
	} else if (folio_test_hugetlb_migratable(folio)) {
		ret = folio_try_get(folio);
		if (ret)
@@ -2071,6 +2077,8 @@ static int try_memory_failure_hugetlb(unsigned long pfn, int flags, int *hugetlb
		if (__page_handle_poison(p) >= 0) {
			page_ref_inc(p);
			res = MF_RECOVERED;
		} else if (page_in_dynamic_pool(p)) {
			return action_result(pfn, MF_MSG_FREE_DPOOL, MF_RECOVERED);
		} else {
			res = MF_FAILED;
		}
@@ -2226,6 +2234,8 @@ int memory_failure(unsigned long pfn, int flags)
	 *    Implies some kernel user: cannot stop them from
	 *    R/W the page; let's pray that the page has been
	 *    used and will be freed some time later.
	 * 3) it's a free page in dynamic pool, and therefore in safe hand:
	 *    check_new_page() will be the gate keeper.
	 * In fact it's dangerous to directly bump up page count from 0,
	 * that may make page_ref_freeze()/page_ref_unfreeze() mismatch.
	 */
@@ -2246,6 +2256,8 @@ int memory_failure(unsigned long pfn, int flags)
					res = MF_FAILED;
				}
				res = action_result(pfn, MF_MSG_BUDDY, res);
			} else if (page_in_dynamic_pool(p)) {
				res = action_result(pfn, MF_MSG_FREE_DPOOL, MF_RECOVERED);
			} else {
				res = action_result(pfn, MF_MSG_KERNEL_HIGH_ORDER, MF_IGNORED);
			}