[PATCH 19/20] mm/mshare: get memcg from current->mm instead of mshare mm

From: Anthony Yznaga
Date: Fri Jan 24 2025 - 19:02:46 EST


Because handle_mm_fault() may operate on a vma from an mshare host mm,
the mm passed to cgroup functions count_memcg_event_mm() and
get_mem_cgroup_from_mm() may be an mshare host mm. These functions find
a memcg by dereferencing mm->owner which is set when an mm is allocated.
Since the task that created an mshare file may exit before the file is
deleted, use current->mm instead to find the memcg to update or charge
to.
This may not be the right solution but is hopefully a good starting
point. If charging should always go to a single memcg associated with
the mshare file, perhaps active_memcg could be used.

Signed-off-by: Anthony Yznaga <anthony.yznaga@xxxxxxxxxx>
---
include/linux/memcontrol.h | 3 +++
mm/memcontrol.c | 3 ++-
mm/mshare.c | 3 +++
3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 6e74b8254d9b..e458ca80e833 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -987,6 +987,9 @@ static inline void count_memcg_events_mm(struct mm_struct *mm,
if (mem_cgroup_disabled())
return;

+ if (test_bit(MMF_MSHARE, &mm->flags))
+ mm = current->mm;
+
rcu_read_lock();
memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
if (likely(memcg))
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 46f8b372d212..ba6267615ee6 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -938,7 +938,8 @@ struct mem_cgroup *get_mem_cgroup_from_mm(struct mm_struct *mm)
mm = current->mm;
if (unlikely(!mm))
return root_mem_cgroup;
- }
+ } else if (test_bit(MMF_MSHARE, &mm->flags))
+ mm = current->mm;

rcu_read_lock();
do {
diff --git a/mm/mshare.c b/mm/mshare.c
index 4c3f6c2410d6..5cc416cfd78c 100644
--- a/mm/mshare.c
+++ b/mm/mshare.c
@@ -381,6 +381,9 @@ msharefs_fill_mm(struct inode *inode)
if (ret)
goto err_free;

+#ifdef CONFIG_MEMCG
+ mm->owner = NULL;
+#endif
return 0;

err_free:
--
2.43.5