bugfix for dpool Wupeng Ma (5): dpool: Fix refcount leak when page not in dpagelist mm/dpool: fix race between fill_pool and page_in_dynamic_pool dpool: fix compile error for CONFIG_MEMORY_RELIABLE mm/dpool: allow longterm pin for dpool mm/dpool: hide dpool related files if not enabled include/linux/dynamic_pool.h | 29 +++++------------------------ include/linux/mm.h | 36 ++++++++++++++++++++++++++++++++++++ mm/dynamic_pool.c | 31 +++++++++++++++++++++++++------ mm/gup.c | 3 ++- 4 files changed, 68 insertions(+), 31 deletions(-) -- 2.43.0
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/9935 -------------------------------- In page_in_dynamic_pool(), the dpool refcount is incremented in dpool_get_from_page(). However, when dpagelist is enabled and the PFN does not belong to dpagelist, the function updates dpool to NULL without releasing the acquired refcount, leading to a refcount leak. Fix this by releasing the refcount before setting dpool to NULL. Fixes: 93b77bfae066 ("mm/dynamic_pool: compatible with HugeTLB dissolve") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- mm/dynamic_pool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/dynamic_pool.c b/mm/dynamic_pool.c index 89ea36b17e479..b9249a1c5d20a 100644 --- a/mm/dynamic_pool.c +++ b/mm/dynamic_pool.c @@ -193,7 +193,8 @@ bool page_in_dynamic_pool(struct page *page) goto out; } - /* The pfn is not in the range, set dpool to NULL */ + /* The pfn is not in the range, release dpool & set dpool to NULL */ + dpool_put(dpool); dpool = NULL; } -- 2.43.0
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/9935 -------------------------------- During dpool init dpool_global_pool is inited before fill_pool which will init pfn_ranges. However in page_in_dynamic_pool, pfn_ranges will be accessed if dpool_global_pool is set, which will lead to NULL pointer dereference. Fixes this issue by moving dpool_global_pool init to the end of dpool_init. Fixes: cf98ffbc116b ("mm/dynamic_pool: fill dpool with pagelist") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- mm/dynamic_pool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/dynamic_pool.c b/mm/dynamic_pool.c index b9249a1c5d20a..cc553982d85f2 100644 --- a/mm/dynamic_pool.c +++ b/mm/dynamic_pool.c @@ -1710,12 +1710,13 @@ int dpool_init(struct dpool_info *arg) goto unlock; } - dpool_global_pool = dpool; - BUG_ON(!dpool->ops->fill_pool); ret = dpool->ops->fill_pool(dpool, arg); if (ret) dpool_put(dpool); + else + /* make dpool_global_pool visible iff dpool init succeed */ + dpool_global_pool = dpool; unlock: mutex_unlock(&dpool_mutex); -- 2.43.0
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/9935 -------------------------------- Fix compile error with MEMORY_RELIABLE & !CONFIG_DYNAMIC_POOL & !CONFIG_HUGETLBFS. Since dynamic_pool_should_alloc is needed by memory reliable, movable the stub defination out of CONFIG_HUGETLBFS to fix this. Fixes: fd855715f24e ("mm/mem_reliable: Fallback to dpool if reliable memory is not enough") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- include/linux/dynamic_pool.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/dynamic_pool.h b/include/linux/dynamic_pool.h index 1d12d76405cf7..88bacd3ddb999 100644 --- a/include/linux/dynamic_pool.h +++ b/include/linux/dynamic_pool.h @@ -197,11 +197,6 @@ static inline int dynamic_pool_hugetlb_acct_memory(struct hstate *h, long delta, return -ENOMEM; } -static inline bool dynamic_pool_should_alloc(gfp_t gfp_mask, unsigned int order) -{ - return false; -} - static inline struct folio *dynamic_pool_alloc_hugepage(struct hugetlbfs_inode_info *p, struct hstate *h, bool reserved) { @@ -214,6 +209,11 @@ static inline void dynamic_pool_free_hugepage(struct folio *folio, } #endif +static inline bool dynamic_pool_should_alloc(gfp_t gfp_mask, unsigned int order) +{ + return false; +} + static inline void dynamic_pool_inherit(struct mem_cgroup *memcg) { } -- 2.43.0
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/9935 -------------------------------- Enable longterm pin for pages/task belongs to dpool. User task and its memory must be unpined during dpool removal, otherwise dpool offlinine will failed. Fixes: cf98ffbc116b ("mm/dynamic_pool: fill dpool with pagelist") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- include/linux/dynamic_pool.h | 19 ------------------- include/linux/mm.h | 36 ++++++++++++++++++++++++++++++++++++ mm/gup.c | 3 ++- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/include/linux/dynamic_pool.h b/include/linux/dynamic_pool.h index 88bacd3ddb999..9f53ad2d80647 100644 --- a/include/linux/dynamic_pool.h +++ b/include/linux/dynamic_pool.h @@ -8,9 +8,6 @@ #ifdef CONFIG_DYNAMIC_POOL -DECLARE_STATIC_KEY_FALSE(dynamic_pool_key); -#define dpool_enabled (static_branch_unlikely(&dynamic_pool_key)) - enum pages_pool_type { PAGES_POOL_1G, PAGES_POOL_2M, @@ -77,7 +74,6 @@ struct dpool_info { struct range pfn_ranges[]; }; -bool __mm_in_dynamic_pool(struct mm_struct *mm); static inline bool mm_in_dynamic_pool(struct mm_struct *mm) { if (!dpool_enabled) @@ -86,14 +82,6 @@ static inline bool mm_in_dynamic_pool(struct mm_struct *mm) return __mm_in_dynamic_pool(mm); } -static inline bool page_from_dynamic_pool(struct page *page) -{ - if (!dpool_enabled) - return false; - - return PagePool(page); -} - static inline bool file_in_dynamic_pool(struct hugetlbfs_inode_info *p) { if (!dpool_enabled) @@ -135,16 +123,9 @@ int dpool_init(struct dpool_info *arg); void dynamic_pool_show_meminfo(struct seq_file *m); #else -#define dpool_enabled 0 - struct dynamic_pool {}; struct dpool_info {}; -static inline bool page_from_dynamic_pool(struct page *page) -{ - return false; -} - static inline bool mm_in_dynamic_pool(struct mm_struct *mm) { return false; diff --git a/include/linux/mm.h b/include/linux/mm.h index 39d926160c8ca..4788ff7421b8f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2063,10 +2063,46 @@ static inline bool is_zero_folio(const struct folio *folio) return is_zero_page(&folio->page); } +#ifdef CONFIG_DYNAMIC_POOL +DECLARE_STATIC_KEY_FALSE(dynamic_pool_key); +#define dpool_enabled (static_branch_unlikely(&dynamic_pool_key)) + +static inline bool page_from_dynamic_pool(struct page *page) +{ + if (!dpool_enabled) + return false; + + return PagePool(page); +} + +bool __mm_in_dynamic_pool(struct mm_struct *mm); +#else +#define dpool_enabled 0 + +static inline bool page_from_dynamic_pool(struct page *page) +{ + return false; +} + +static inline bool __mm_in_dynamic_pool(struct mm_struct *mm) +{ + return false; +} +#endif + /* MIGRATE_CMA and ZONE_MOVABLE do not allow pin folios */ #ifdef CONFIG_MIGRATION static inline bool folio_is_longterm_pinnable(struct folio *folio) { + /* + * Memory migration and offlining will be preventd if pages is + * Pinned. However dpool memory must be unpinned and related + * processes terminated before taking the dpool offline, which + * avoids this interference. + */ + if (page_from_dynamic_pool(&folio->page)) + return true; + #ifdef CONFIG_CMA int mt = folio_migratetype(folio); diff --git a/mm/gup.c b/mm/gup.c index 5d8a4866431b3..a39bd5869b98f 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -2128,7 +2128,8 @@ static long __gup_longterm_locked(struct mm_struct *mm, unsigned int flags; long rc, nr_pinned_pages; - if (!(gup_flags & FOLL_LONGTERM)) + if (!(gup_flags & FOLL_LONGTERM) || + __mm_in_dynamic_pool(mm)) return __get_user_pages_locked(mm, start, nr_pages, pages, locked, gup_flags); -- 2.43.0
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/9935 -------------------------------- Hide dpool related files if dpagelist is not enabled. Fixes: 118813b0a079 ("[Huawei] mm/dpool: add dpool.show to show meminfo") Signed-off-by: Wupeng Ma <mawupeng1@huawei.com> --- mm/dynamic_pool.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/mm/dynamic_pool.c b/mm/dynamic_pool.c index cc553982d85f2..c5a45b1d34841 100644 --- a/mm/dynamic_pool.c +++ b/mm/dynamic_pool.c @@ -1386,13 +1386,30 @@ static struct dynamic_pool_ops hugetlb_dpool_ops = { .restore_pool = dpool_merge_all, }; -/* If dynamic pool is disabled, hide the interface */ +/* + * Determines whether to hide dynamic pool control files based on + * cross-hiding logic. + * + * Cross-hiding behavior: + * - When enable_dpagelist is ON, hide dhugetlb files + * - When enable_dhugetlb is ON, hide dpagelist files + * + * Prevents conflicts when both features could interfere. + */ bool dynamic_pool_hide_files(struct cftype *cft) { - if (dpool_enabled && enable_dhugetlb) + bool is_dhugetlb_file = !!strstr(cft->name, "dhugetlb"); + bool is_dpagelist_file = !!strstr(cft->name, "dpool"); + /* Non-related files are never hidden */ + if (!is_dhugetlb_file && !is_dpagelist_file) return false; - return !!strstr(cft->name, "dhugetlb"); + /* Hide all related files when the dynamic pool feature is disabled */ + if (!dpool_enabled) + return true; + + return (enable_dpagelist && is_dhugetlb_file) || + (enable_dhugetlb && is_dpagelist_file); } int dynamic_pool_add_memory(struct mem_cgroup *memcg, int nid, -- 2.43.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/27448 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/ZS7... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/27448 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/ZS7...
participants (2)
-
patchwork bot -
Wupeng Ma