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 | 39 ++++++++++++++++++++++++++++++++++++ mm/hugetlb.c | 6 ++++++ 3 files changed, 51 insertions(+)
diff --git a/include/linux/dynamic_pool.h b/include/linux/dynamic_pool.h index 45d70c21c35b..d6ef9214c586 100644 --- a/include/linux/dynamic_pool.h +++ b/include/linux/dynamic_pool.h @@ -102,6 +102,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); @@ -143,6 +144,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 fe2c297cdbb2..e6a072a7eafd 100644 --- a/mm/dynamic_pool.c +++ b/mm/dynamic_pool.c @@ -149,6 +149,45 @@ bool __task_in_dynamic_pool(struct task_struct *tsk) return !!dpool; }
+bool page_in_dynamic_pool(struct page *page) +{ + struct dynamic_pool *dpool; + bool ret; + + 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 out; + } + + /* The pfn is not in the range, set dpool to NULL */ + dpool = NULL; + } + +out: + ret = dpool ? !PagePool(page) : false; + dpool_put(dpool); + + return ret; +} + /* === 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.