Skip to content

Commit

Permalink
memcg: also test for skip accounting at the page allocation level
Browse files Browse the repository at this point in the history
The memory we used to hold the memcg arrays is currently accounted to
the current memcg.  But that creates a problem, because that memory can
only be freed after the last user is gone.  Our only way to know which
is the last user, is to hook up to freeing time, but the fact that we
still have some in flight kmallocs will prevent freeing to happen.  I
believe therefore to be just easier to account this memory as global
overhead.

This patch (of 2):

Disabling accounting is only relevant for some specific memcg internal
allocations.  Therefore we would initially not have such check at
memcg_kmem_newpage_charge, since direct calls to the page allocator that
are marked with GFP_KMEMCG only happen outside memcg core.  We are
mostly concerned with cache allocations and by having this test at
memcg_kmem_get_cache we are already able to relay the allocation to the
root cache and bypass the memcg caches altogether.

There is one exception, though: the SLUB allocator does not create large
order caches, but rather service large kmallocs directly from the page
allocator.  Therefore, the following sequence, when backed by the SLUB
allocator:

	memcg_stop_kmem_account();
	kmalloc(<large_number>)
	memcg_resume_kmem_account();

would effectively ignore the fact that we should skip accounting, since
it will drive us directly to this function without passing through the
cache selector memcg_kmem_get_cache.  Such large allocations are
extremely rare but can happen, for instance, for the cache arrays.

This was never a problem in practice, because we weren't skipping
accounting for the cache arrays.  All the allocations we were skipping
were fairly small.  However, the fact that we were not skipping those
allocations are a problem and can prevent the memcgs from going away.
As we fix that, we need to make sure that the fix will also work with
the SLUB allocator.

Signed-off-by: Glauber Costa <[email protected]>
Reported-by: Michal Hocko <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Kamezawa Hiroyuki <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
glommer authored and torvalds committed Jul 9, 2013
1 parent d157a55 commit 6d42c23
Showing 1 changed file with 28 additions and 0 deletions.
28 changes: 28 additions & 0 deletions mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -3637,6 +3637,34 @@ __memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **_memcg, int order)
int ret;

*_memcg = NULL;

/*
* Disabling accounting is only relevant for some specific memcg
* internal allocations. Therefore we would initially not have such
* check here, since direct calls to the page allocator that are marked
* with GFP_KMEMCG only happen outside memcg core. We are mostly
* concerned with cache allocations, and by having this test at
* memcg_kmem_get_cache, we are already able to relay the allocation to
* the root cache and bypass the memcg cache altogether.
*
* There is one exception, though: the SLUB allocator does not create
* large order caches, but rather service large kmallocs directly from
* the page allocator. Therefore, the following sequence when backed by
* the SLUB allocator:
*
* memcg_stop_kmem_account();
* kmalloc(<large_number>)
* memcg_resume_kmem_account();
*
* would effectively ignore the fact that we should skip accounting,
* since it will drive us directly to this function without passing
* through the cache selector memcg_kmem_get_cache. Such large
* allocations are extremely rare but can happen, for instance, for the
* cache arrays. We bring this test here.
*/
if (!current->mm || current->memcg_kmem_skip_account)
return true;

memcg = try_get_mem_cgroup_from_mm(current->mm);

/*
Expand Down

0 comments on commit 6d42c23

Please sign in to comment.