From: Liu Shixin <liushixin2@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAFWQH -------------------------------- When swapin in async mode, if the swap entry is belong to a memcg and the memcg is bound with a dpool, then we should try to allocate page from dpool firstly. If the swapin is triggered in page fault, then we don't need to allocate from dpool proactively, since the task is belong to the memcg, the page will allocate from dpool naturally. Signed-off-by: Liu Shixin <liushixin2@huawei.com> --- include/linux/memcontrol.h | 10 ++++++++ mm/memcontrol.c | 48 ++++++++++++++++++++++++++++++++++++++ mm/swap_state.c | 3 +-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 25e6580705ef..254741e81085 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -814,6 +814,9 @@ static inline int mem_cgroup_charge(struct folio *folio, struct mm_struct *mm, int mem_cgroup_hugetlb_try_charge(struct mem_cgroup *memcg, gfp_t gfp, long nr_pages); +struct folio *memcg_vma_alloc_folio(swp_entry_t entry, gfp_t gfp_mask, + struct mempolicy *mpol, pgoff_t ilx); + int mem_cgroup_swapin_charge_folio(struct folio *folio, struct mm_struct *mm, gfp_t gfp, swp_entry_t entry); @@ -1422,6 +1425,13 @@ static inline int mem_cgroup_hugetlb_try_charge(struct mem_cgroup *memcg, return 0; } +static inline struct folio *memcg_vma_alloc_folio(swp_entry_t entry, gfp_t gfp_mask, + struct mempolicy *mpol, pgoff_t ilx) +{ + return (struct folio *)alloc_pages_mpol(gfp_mask, 0, + mpol, ilx, numa_node_id()); +} + static inline int mem_cgroup_swapin_charge_folio(struct folio *folio, struct mm_struct *mm, gfp_t gfp, swp_entry_t entry) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 4ed54affdfa9..f4a948b49624 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -8479,6 +8479,54 @@ int mem_cgroup_hugetlb_try_charge(struct mem_cgroup *memcg, gfp_t gfp, return 0; } +#ifdef CONFIG_DYNAMIC_POOL +static struct mem_cgroup *get_mem_cgroup_from_swap(swp_entry_t entry) +{ + struct mem_cgroup *memcg; + unsigned short id; + + if (mem_cgroup_disabled()) + return NULL; + + id = lookup_swap_cgroup_id(entry); + + rcu_read_lock(); + memcg = mem_cgroup_from_id(id); + if (memcg && !css_tryget_online(&memcg->css)) + memcg = NULL; + rcu_read_unlock(); + + return memcg; +} + +struct folio *memcg_vma_alloc_folio(swp_entry_t entry, gfp_t gfp_mask, + struct mempolicy *mpol, pgoff_t ilx) +{ + if (dpool_enabled) { + struct mem_cgroup *memcg; + struct page *page; + + memcg = get_mem_cgroup_from_swap(entry); + if (memcg) { + page = dynamic_pool_alloc_page(memcg, gfp_mask, 0, 0); + css_put(&memcg->css); + if (page) + return page_rmappable_folio(page); + } + } + + return (struct folio *)alloc_pages_mpol(gfp_mask, 0, + mpol, ilx, numa_node_id()); +} +#else +struct folio *memcg_vma_alloc_folio(swp_entry_t entry, gfp_t gfp_mask, + struct mempolicy *mpol, pgoff_t ilx) +{ + return (struct folio *)alloc_pages_mpol(gfp_mask, 0, + mpol, ilx, numa_node_id()); +} +#endif + /** * mem_cgroup_swapin_charge_folio - Charge a newly allocated folio for swapin. * @folio: folio to charge. diff --git a/mm/swap_state.c b/mm/swap_state.c index 840e0f93bf7d..ae108ae1e21f 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -467,8 +467,7 @@ struct folio *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, * before marking swap_map SWAP_HAS_CACHE, when -EEXIST will * cause any racers to loop around until we add it to cache. */ - folio = (struct folio *)alloc_pages_mpol(gfp_mask, 0, - mpol, ilx, numa_node_id()); + folio = memcg_vma_alloc_folio(entry, gfp_mask, mpol, ilx); if (!folio) goto fail_put_swap; -- 2.43.0