hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8S9BY CVE: NA
--------------------------------
Hugetlb may be dissolved from compaction or hwpoison. Do not dissolve pages in dpool.
Signed-off-by: Liu Shixin liushixin2@huawei.com --- include/linux/dynamic_pool.h | 6 ++++++ mm/dynamic_pool.c | 36 ++++++++++++++++++++++++++++++++++++ mm/hugetlb.c | 6 ++++++ 3 files changed, 48 insertions(+)
diff --git a/include/linux/dynamic_pool.h b/include/linux/dynamic_pool.h index 6a4bc25d22a8..88a7c06dcf05 100644 --- a/include/linux/dynamic_pool.h +++ b/include/linux/dynamic_pool.h @@ -99,6 +99,7 @@ static inline bool file_in_dynamic_pool(struct hugetlbfs_inode_info *p) return p && p->dpool; }
+bool page_in_dynamic_pool(struct page *page); int dynamic_pool_can_attach(struct task_struct *tsk, struct mem_cgroup *memcg); struct page *dynamic_pool_alloc_page(gfp_t gfp, unsigned int order, unsigned int alloc_flags); @@ -140,6 +141,11 @@ static inline bool task_in_dynamic_pool(struct task_struct *tsk) return false; }
+static inline bool page_in_dynamic_pool(const struct page *page) +{ + return false; +} + static inline int dynamic_pool_can_attach(struct task_struct *tsk, struct mem_cgroup *memcg) { diff --git a/mm/dynamic_pool.c b/mm/dynamic_pool.c index 1844888e8648..fccb10bfd278 100644 --- a/mm/dynamic_pool.c +++ b/mm/dynamic_pool.c @@ -149,6 +149,42 @@ bool __task_in_dynamic_pool(struct task_struct *tsk) return !!dpool; }
+bool page_in_dynamic_pool(struct page *page) +{ + struct dynamic_pool *dpool; + + if (!dpool_enabled) + return false; + + if (PageDpool(page)) + return true; + + /* + * If the page don't have the flags, it may be in pcp list. + * Check it using the page range. + */ + dpool = dpool_get_from_page(page); + if (enable_dpagelist && dpool) { + unsigned long pfn = page_to_pfn(page); + int range_cnt = dpool->range_cnt; + struct range *range; + int i; + + for (i = 0; i < range_cnt; i++) { + range = &dpool->pfn_ranges[i]; + if (pfn >= range->start && pfn <= range->end) + goto put; + } + + /* The pfn is not in the range, set dpool to NULL */ + dpool = NULL; + } +put: + dpool_put(dpool); + + return !!dpool; +} + /* === demote and promote function ==================================== */
static void dpool_disable_pcp_pool(struct dynamic_pool *dpool, bool drain); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 0c524a0f6de2..ec33252edb8d 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2399,6 +2399,9 @@ int dissolve_free_huge_page(struct page *page) if (!folio_test_hugetlb(folio)) return 0;
+ if (page_from_dynamic_pool(page) || page_in_dynamic_pool(page)) + return -EBUSY; + spin_lock_irq(&hugetlb_lock); if (!folio_test_hugetlb(folio)) { rc = 0; @@ -3101,6 +3104,9 @@ int isolate_or_dissolve_huge_page(struct page *page, struct list_head *list) struct folio *folio = page_folio(page); int ret = -EBUSY;
+ if (page_from_dynamic_pool(page) || page_in_dynamic_pool(page)) + return -EBUSY; + /* * The page might have been dissolved from under our feet, so make sure * to carefully check the state under the lock.