summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJinmeng Zhou <jinmengzhou22@gmail.com>2026-09-03 15:50:48 +0800
committerAndrew Morton <akpm@linux-foundation.org>2026-10-08 22:54:34 -0700
commitc2deb1356d82c9d54bd2fcf1241cc97eb66fd81f (patch)
tree1f0793f15dfc9e900f2d9198499f3b5612798ad1 /include
parente1e86503027a00a843a77a0477899e5423c43a59 (diff)
downloadlinux-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.h3
-rw-r--r--include/linux/memcontrol.h8
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,