Re: [PATCH v2 17/28] mm: memcg/slab: save obj_cgroup for non-root slab objects

From: Johannes Weiner
Date: Mon Feb 03 2020 - 14:53:36 EST


On Mon, Jan 27, 2020 at 09:34:42AM -0800, Roman Gushchin wrote:
> Store the obj_cgroup pointer in the corresponding place of
> page->obj_cgroups for each allocated non-root slab object.
> Make sure that each allocated object holds a reference to obj_cgroup.
>
> Objcg pointer is obtained from the memcg->objcg dereferencing
> in memcg_kmem_get_cache() and passed from pre_alloc_hook to
> post_alloc_hook. Then in case of successful allocation(s) it's
> getting stored in the page->obj_cgroups vector.
>
> The objcg obtaining part look a bit bulky now, but it will be simplified
> by next commits in the series.
>
> Signed-off-by: Roman Gushchin <guro@xxxxxx>
> ---
> include/linux/memcontrol.h | 3 +-
> mm/memcontrol.c | 14 +++++++--
> mm/slab.c | 18 +++++++-----
> mm/slab.h | 60 ++++++++++++++++++++++++++++++++++----
> mm/slub.c | 14 +++++----
> 5 files changed, 88 insertions(+), 21 deletions(-)
>
> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
> index 30bbea3f85e2..54bfb26b5016 100644
> --- a/include/linux/memcontrol.h
> +++ b/include/linux/memcontrol.h
> @@ -1431,7 +1431,8 @@ static inline void memcg_set_shrinker_bit(struct mem_cgroup *memcg,
> }
> #endif
>
> -struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep);
> +struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep,
> + struct obj_cgroup **objcgp);
> void memcg_kmem_put_cache(struct kmem_cache *cachep);
>
> #ifdef CONFIG_MEMCG_KMEM
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 94337ab1ebe9..0e9fe272e688 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -2896,7 +2896,8 @@ static inline bool memcg_kmem_bypass(void)
> * done with it, memcg_kmem_put_cache() must be called to release the
> * reference.
> */
> -struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep)
> +struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep,
> + struct obj_cgroup **objcgp)
> {
> struct mem_cgroup *memcg;
> struct kmem_cache *memcg_cachep;
> @@ -2952,8 +2953,17 @@ struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep)
> */
> if (unlikely(!memcg_cachep))
> memcg_schedule_kmem_cache_create(memcg, cachep);
> - else if (percpu_ref_tryget(&memcg_cachep->memcg_params.refcnt))
> + else if (percpu_ref_tryget(&memcg_cachep->memcg_params.refcnt)) {
> + struct obj_cgroup *objcg = rcu_dereference(memcg->objcg);
> +
> + if (!objcg || !obj_cgroup_tryget(objcg)) {
> + percpu_ref_put(&memcg_cachep->memcg_params.refcnt);
> + goto out_unlock;
> + }

As per the reply to the previous patch: I don't understand why the
objcg requires a pulse check here. As long as the memcg is alive and
can be charged with memory, how can the objcg disappear?