Skip to content

Commit

Permalink
mm: memcontrol: catch root bypass in move precharge
Browse files Browse the repository at this point in the history
When mem_cgroup_try_charge() returns -EINTR, it bypassed the charge to
the root memcg.  But move precharging does not catch this and treats
this case as if no charge had happened, thus leaking a charge against
root.  Because of an old optimization, the root memcg's res_counter is
not actually charged right now, but it's still an imbalance and
subsequent patches will charge the root memcg again.

Catch those bypasses to the root memcg and properly cancel them before
giving up the move.

Signed-off-by: Johannes Weiner <[email protected]>
Acked-by: Michal Hocko <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Tejun Heo <[email protected]>
Cc: Vladimir Davydov <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
hnaz authored and torvalds committed Aug 7, 2014
1 parent 9476db9 commit 692e7c4
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -6401,6 +6401,10 @@ static int mem_cgroup_do_precharge(unsigned long count)
mc.precharge += count;
return ret;
}
if (ret == -EINTR) {
__mem_cgroup_cancel_charge(root_mem_cgroup, count);
return ret;
}

/* Try charges one by one with reclaim */
while (count--) {
Expand All @@ -6409,8 +6413,11 @@ static int mem_cgroup_do_precharge(unsigned long count)
/*
* In case of failure, any residual charges against
* mc.to will be dropped by mem_cgroup_clear_mc()
* later on.
* later on. However, cancel any charges that are
* bypassed to root right away or they'll be lost.
*/
if (ret == -EINTR)
__mem_cgroup_cancel_charge(root_mem_cgroup, 1);
if (ret)
return ret;
mc.precharge++;
Expand Down

0 comments on commit 692e7c4

Please sign in to comment.