On Fri, Oct 24, 2014 at 09:40:20AM -0400, Johannes Weiner wrote:
> While moving charges from one memcg to another, page stat updates must
> acquire the old memcg's move_lock to prevent double accounting.  That
> situation is denoted by an increased memcg->move_accounting.  However,
> the charge moving code declares this way too early for now, even
> before summing up the RSS and pre-allocating destination charges.
> 
> Shorten this slowpath mode by increasing memcg->move_accounting only
> right before walking the task's address space with the intention of
> actually moving the pages.
> 
> Signed-off-by: Johannes Weiner <[email protected]>

Reviewed-by: Vladimir Davydov <[email protected]>

> ---
>  mm/memcontrol.c | 21 ++++++++-------------
>  1 file changed, 8 insertions(+), 13 deletions(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index c50176429fa3..23cf27cca370 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -5263,8 +5263,6 @@ static void __mem_cgroup_clear_mc(void)
>  
>  static void mem_cgroup_clear_mc(void)
>  {
> -     struct mem_cgroup *from = mc.from;
> -
>       /*
>        * we must clear moving_task before waking up waiters at the end of
>        * task migration.
> @@ -5275,8 +5273,6 @@ static void mem_cgroup_clear_mc(void)
>       mc.from = NULL;
>       mc.to = NULL;
>       spin_unlock(&mc.lock);
> -
> -     atomic_dec(&from->moving_account);
>  }
>  
>  static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
> @@ -5310,15 +5306,6 @@ static int mem_cgroup_can_attach(struct 
> cgroup_subsys_state *css,
>                       VM_BUG_ON(mc.moved_charge);
>                       VM_BUG_ON(mc.moved_swap);
>  
> -                     /*
> -                      * Signal mem_cgroup_begin_page_stat() to take
> -                      * the memcg's move_lock while we're moving
> -                      * its pages to another memcg.  Then wait for
> -                      * already started RCU-only updates to finish.
> -                      */
> -                     atomic_inc(&from->moving_account);
> -                     synchronize_rcu();
> -
>                       spin_lock(&mc.lock);
>                       mc.from = from;
>                       mc.to = memcg;
> @@ -5450,6 +5437,13 @@ static void mem_cgroup_move_charge(struct mm_struct 
> *mm)
>       struct vm_area_struct *vma;
>  
>       lru_add_drain_all();
> +     /*
> +      * Signal mem_cgroup_begin_page_stat() to take the memcg's
> +      * move_lock while we're moving its pages to another memcg.
> +      * Then wait for already started RCU-only updates to finish.
> +      */
> +     atomic_inc(&mc.from->moving_account);
> +     synchronize_rcu();
>  retry:
>       if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
>               /*
> @@ -5482,6 +5476,7 @@ retry:
>                       break;
>       }
>       up_read(&mm->mmap_sem);
> +     atomic_dec(&mc.from->moving_account);
>  }
>  
>  static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
> -- 
> 2.1.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to