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