diff options
| author | Jinmeng Zhou <jinmengzhou22@gmail.com> | 2026-09-03 15:50:48 +0800 |
|---|---|---|
| committer | Andrew Morton <akpm@linux-foundation.org> | 2026-10-08 22:54:34 -0700 |
| commit | c2deb1356d82c9d54bd2fcf1241cc97eb66fd81f (patch) | |
| tree | 1f0793f15dfc9e900f2d9198499f3b5612798ad1 /include | |
| parent | e1e86503027a00a843a77a0477899e5423c43a59 (diff) | |
| download | linux-next-c2deb1356d82c9d54bd2fcf1241cc97eb66fd81f.tar.gz linux-next-c2deb1356d82c9d54bd2fcf1241cc97eb66fd81f.zip | |
mm/hugetlb: charge folios to the target mm's memcg
HugeTLB folios are currently charged to the memcg of the allocating task.
This gives the wrong result when a userfaultfd handler populates a HugeTLB
VMA that belongs to another process. The UFFDIO_COPY ioctl operates on
the userfaultfd context's mm, but get_mem_cgroup_from_current() charges
the folio to the handler's memcg instead.
This can be reproduced by placing the faulting process and its userfaultfd
handler in different memory cgroups. Have the target process register a
HugeTLB mapping with userfaultfd, trigger a missing fault, and let the
handler resolve it with UFFDIO_COPY. The hugepage usage is then reported
in the handler's memory.current instead of the target's.
The generic userfaultfd population path avoids this problem by charging
folios to dst_vma->vm_mm.
Pass the target mm through hugetlb_alloc_folio() and charge the folio by
using get_mem_cgroup_from_mm(). This preserves the existing charge timing
and error handling while making HugeTLB userfaultfd population consistent
with the generic path.
Link: https://lore.kernel.org/20260903075048.3316-1-zhoujinmeng@bytedance.com
Fixes: 8cba9576df60 ("hugetlb: memcg: account hugetlb-backed memory in memory controller")
Signed-off-by: Jinmeng Zhou <zhoujinmeng@bytedance.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Reviewed-by: Hongfu Li <lihongfu@kylinos.cn>
Cc: David Hildenbrand <david@kernel.org>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: <stable@vger.kernel.org>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/hugetlb.h | 3 | ||||
| -rw-r--r-- | include/linux/memcontrol.h | 8 |
2 files changed, 7 insertions, 4 deletions
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 900c95e346b2..80a5a03e9cee 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -694,7 +694,8 @@ enum hugetlb_alloc_flag { #define HUGETLB_ALLOC_USE_GLOBAL_RESERVATIONS BIT(HUGETLB_ALLOC_USE_GLOBAL_RESERVATIONS_BIT) struct folio *hugetlb_alloc_folio(struct hstate *h, - struct mempolicy_interpreted *mpoli, u8 alloc_flags); + struct mempolicy_interpreted *mpoli, struct mm_struct *mm, + u8 alloc_flags); struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma, unsigned long addr, bool cow_from_owner); struct folio *alloc_hugetlb_folio_nodemask(struct hstate *h, int preferred_nid, diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index c79992643556..058ebd73ff16 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -647,7 +647,8 @@ static inline int mem_cgroup_charge(struct folio *folio, struct mm_struct *mm, return __mem_cgroup_charge(folio, mm, gfp); } -int mem_cgroup_charge_hugetlb(struct folio* folio, gfp_t gfp); +int mem_cgroup_charge_hugetlb(struct folio *folio, struct mm_struct *mm, + gfp_t gfp); int mem_cgroup_swapin_charge_folio(struct folio *folio, unsigned short id, struct mm_struct *mm, gfp_t gfp); @@ -1146,9 +1147,10 @@ static inline int mem_cgroup_charge(struct folio *folio, return 0; } -static inline int mem_cgroup_charge_hugetlb(struct folio* folio, gfp_t gfp) +static inline int mem_cgroup_charge_hugetlb(struct folio *folio, + struct mm_struct *mm, gfp_t gfp) { - return 0; + return 0; } static inline int mem_cgroup_swapin_charge_folio(struct folio *folio, |
