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: Liu Shixin liushixin2@huawei.com --- include/linux/mm.h | 1 + include/ras/ras_event.h | 1 + mm/memory-failure.c | 16 ++++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h index c00def598f95..48a6b0865175 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -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, };
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h index cbd3ddd7c33d..e7d9470a27cd 100644 --- a/include/ras/ras_event.h +++ b/include/ras/ras_event.h @@ -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" )
/* diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 4d6e43c88489..0b59cf8c544a 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -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); }