All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Hocko <mhocko@suse.cz>
To: Vladimir Davydov <vdavydov@parallels.com>
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	cgroups@vger.kernel.org, devel@openvz.org,
	Johannes Weiner <hannes@cmpxchg.org>,
	Glauber Costa <glommer@gmail.com>,
	Christoph Lameter <cl@linux.com>,
	Pekka Enberg <penberg@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH 3/6] memcg, slab: cleanup barrier usage when accessing memcg_caches
Date: Thu, 19 Dec 2013 10:10:07 +0100	[thread overview]
Message-ID: <20131219091007.GC9331@dhcp22.suse.cz> (raw)
In-Reply-To: <52B29427.9010909@parallels.com>

On Thu 19-12-13 10:37:27, Vladimir Davydov wrote:
> On 12/18/2013 09:14 PM, Michal Hocko wrote:
> > On Wed 18-12-13 17:16:54, Vladimir Davydov wrote:
> >> First, in memcg_create_kmem_cache() we should issue the write barrier
> >> after the kmem_cache is initialized, but before storing the pointer to
> >> it in its parent's memcg_params.
> >>
> >> Second, we should always issue the read barrier after
> >> cache_from_memcg_idx() to conform with the write barrier.
> >>
> >> Third, its better to use smp_* versions of barriers, because we don't
> >> need them on UP systems.
> > Please be (much) more verbose on Why. Barriers are tricky and should be
> > documented accordingly. So if you say that we should issue a barrier
> > always be specific why we should do it.
> 
> In short, we have kmem_cache::memcg_params::memcg_caches is an array of
> pointers to per-memcg caches. We access it lock-free so we should use
> memory barriers during initialization. Obviously we should place a write
> barrier just before we set the pointer in order to make sure nobody will
> see a partially initialized structure. Besides there must be a read
> barrier between reading the pointer and accessing the structure, to
> conform with the write barrier. It's all that similar to rcu_assign and
> rcu_deref. Currently the barrier usage looks rather strange:
> 
> memcg_create_kmem_cache:
>     initialize kmem
>     set the pointer in memcg_caches
>     wmb() // ???
> 
> __memcg_kmem_get_cache:
>     <...>
>     read_barrier_depends() // ???
>     cachep = root_cache->memcg_params->memcg_caches[memcg_id]
>     <...>

Why do we need explicit memory barriers when we can use RCU?
__memcg_kmem_get_cache already dereferences within rcu_read_lock.

Btw. cache_from_memcg_idx is desperately asking for a comment about
required locking.

> Nothing prevents some archs from moving initialization after setting the
> pointer, or reading data before reading the pointer to it.
> 
> Of course, I will include a detailed description in the next version of
> this patch.
> 
> Thanks.
> 
> >> Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
> >> Cc: Michal Hocko <mhocko@suse.cz>
> >> Cc: Johannes Weiner <hannes@cmpxchg.org>
> >> Cc: Glauber Costa <glommer@gmail.com>
> >> Cc: Christoph Lameter <cl@linux.com>
> >> Cc: Pekka Enberg <penberg@kernel.org>
> >> Cc: Andrew Morton <akpm@linux-foundation.org>
> >> ---
> >>  mm/memcontrol.c |   24 ++++++++++--------------
> >>  mm/slab.h       |    6 +++++-
> >>  2 files changed, 15 insertions(+), 15 deletions(-)
> >>
> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> >> index e6ad6ff..e37fdb5 100644
> >> --- a/mm/memcontrol.c
> >> +++ b/mm/memcontrol.c
> >> @@ -3429,12 +3429,14 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
> >>  
> >>  	atomic_set(&new_cachep->memcg_params->nr_pages , 0);
> >>  
> >> -	cachep->memcg_params->memcg_caches[idx] = new_cachep;
> >>  	/*
> >> -	 * the readers won't lock, make sure everybody sees the updated value,
> >> -	 * so they won't put stuff in the queue again for no reason
> >> +	 * Since readers won't lock (see cache_from_memcg_idx()), we need a
> >> +	 * barrier here to ensure nobody will see the kmem_cache partially
> >> +	 * initialized.
> >>  	 */
> >> -	wmb();
> >> +	smp_wmb();
> >> +
> >> +	cachep->memcg_params->memcg_caches[idx] = new_cachep;
> >>  out:
> >>  	mutex_unlock(&memcg_cache_mutex);
> >>  	return new_cachep;
> >> @@ -3573,7 +3575,7 @@ struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep,
> >>  					  gfp_t gfp)
> >>  {
> >>  	struct mem_cgroup *memcg;
> >> -	int idx;
> >> +	struct kmem_cache *memcg_cachep;
> >>  
> >>  	VM_BUG_ON(!cachep->memcg_params);
> >>  	VM_BUG_ON(!cachep->memcg_params->is_root_cache);
> >> @@ -3587,15 +3589,9 @@ struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep,
> >>  	if (!memcg_can_account_kmem(memcg))
> >>  		goto out;
> >>  
> >> -	idx = memcg_cache_id(memcg);
> >> -
> >> -	/*
> >> -	 * barrier to mare sure we're always seeing the up to date value.  The
> >> -	 * code updating memcg_caches will issue a write barrier to match this.
> >> -	 */
> >> -	read_barrier_depends();
> >> -	if (likely(cache_from_memcg_idx(cachep, idx))) {
> >> -		cachep = cache_from_memcg_idx(cachep, idx);
> >> +	memcg_cachep = cache_from_memcg_idx(cachep, memcg_cache_id(memcg));
> >> +	if (likely(memcg_cachep)) {
> >> +		cachep = memcg_cachep;
> >>  		goto out;
> >>  	}
> >>  
> >> diff --git a/mm/slab.h b/mm/slab.h
> >> index 0859c42..1d8b53f 100644
> >> --- a/mm/slab.h
> >> +++ b/mm/slab.h
> >> @@ -163,9 +163,13 @@ static inline const char *cache_name(struct kmem_cache *s)
> >>  static inline struct kmem_cache *
> >>  cache_from_memcg_idx(struct kmem_cache *s, int idx)
> >>  {
> >> +	struct kmem_cache *cachep;
> >> +
> >>  	if (!s->memcg_params)
> >>  		return NULL;
> >> -	return s->memcg_params->memcg_caches[idx];
> >> +	cachep = s->memcg_params->memcg_caches[idx];
> >> +	smp_read_barrier_depends();	/* see memcg_register_cache() */
> >> +	return cachep;
> >>  }
> >>  
> >>  static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
> >> -- 
> >> 1.7.10.4
> >>
> 

-- 
Michal Hocko
SUSE Labs

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

WARNING: multiple messages have this Message-ID (diff)
From: Michal Hocko <mhocko@suse.cz>
To: Vladimir Davydov <vdavydov@parallels.com>
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	cgroups@vger.kernel.org, devel@openvz.org,
	Johannes Weiner <hannes@cmpxchg.org>,
	Glauber Costa <glommer@gmail.com>,
	Christoph Lameter <cl@linux.com>,
	Pekka Enberg <penberg@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH 3/6] memcg, slab: cleanup barrier usage when accessing memcg_caches
Date: Thu, 19 Dec 2013 10:10:07 +0100	[thread overview]
Message-ID: <20131219091007.GC9331@dhcp22.suse.cz> (raw)
In-Reply-To: <52B29427.9010909@parallels.com>

On Thu 19-12-13 10:37:27, Vladimir Davydov wrote:
> On 12/18/2013 09:14 PM, Michal Hocko wrote:
> > On Wed 18-12-13 17:16:54, Vladimir Davydov wrote:
> >> First, in memcg_create_kmem_cache() we should issue the write barrier
> >> after the kmem_cache is initialized, but before storing the pointer to
> >> it in its parent's memcg_params.
> >>
> >> Second, we should always issue the read barrier after
> >> cache_from_memcg_idx() to conform with the write barrier.
> >>
> >> Third, its better to use smp_* versions of barriers, because we don't
> >> need them on UP systems.
> > Please be (much) more verbose on Why. Barriers are tricky and should be
> > documented accordingly. So if you say that we should issue a barrier
> > always be specific why we should do it.
> 
> In short, we have kmem_cache::memcg_params::memcg_caches is an array of
> pointers to per-memcg caches. We access it lock-free so we should use
> memory barriers during initialization. Obviously we should place a write
> barrier just before we set the pointer in order to make sure nobody will
> see a partially initialized structure. Besides there must be a read
> barrier between reading the pointer and accessing the structure, to
> conform with the write barrier. It's all that similar to rcu_assign and
> rcu_deref. Currently the barrier usage looks rather strange:
> 
> memcg_create_kmem_cache:
>     initialize kmem
>     set the pointer in memcg_caches
>     wmb() // ???
> 
> __memcg_kmem_get_cache:
>     <...>
>     read_barrier_depends() // ???
>     cachep = root_cache->memcg_params->memcg_caches[memcg_id]
>     <...>

Why do we need explicit memory barriers when we can use RCU?
__memcg_kmem_get_cache already dereferences within rcu_read_lock.

Btw. cache_from_memcg_idx is desperately asking for a comment about
required locking.

> Nothing prevents some archs from moving initialization after setting the
> pointer, or reading data before reading the pointer to it.
> 
> Of course, I will include a detailed description in the next version of
> this patch.
> 
> Thanks.
> 
> >> Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
> >> Cc: Michal Hocko <mhocko@suse.cz>
> >> Cc: Johannes Weiner <hannes@cmpxchg.org>
> >> Cc: Glauber Costa <glommer@gmail.com>
> >> Cc: Christoph Lameter <cl@linux.com>
> >> Cc: Pekka Enberg <penberg@kernel.org>
> >> Cc: Andrew Morton <akpm@linux-foundation.org>
> >> ---
> >>  mm/memcontrol.c |   24 ++++++++++--------------
> >>  mm/slab.h       |    6 +++++-
> >>  2 files changed, 15 insertions(+), 15 deletions(-)
> >>
> >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> >> index e6ad6ff..e37fdb5 100644
> >> --- a/mm/memcontrol.c
> >> +++ b/mm/memcontrol.c
> >> @@ -3429,12 +3429,14 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
> >>  
> >>  	atomic_set(&new_cachep->memcg_params->nr_pages , 0);
> >>  
> >> -	cachep->memcg_params->memcg_caches[idx] = new_cachep;
> >>  	/*
> >> -	 * the readers won't lock, make sure everybody sees the updated value,
> >> -	 * so they won't put stuff in the queue again for no reason
> >> +	 * Since readers won't lock (see cache_from_memcg_idx()), we need a
> >> +	 * barrier here to ensure nobody will see the kmem_cache partially
> >> +	 * initialized.
> >>  	 */
> >> -	wmb();
> >> +	smp_wmb();
> >> +
> >> +	cachep->memcg_params->memcg_caches[idx] = new_cachep;
> >>  out:
> >>  	mutex_unlock(&memcg_cache_mutex);
> >>  	return new_cachep;
> >> @@ -3573,7 +3575,7 @@ struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep,
> >>  					  gfp_t gfp)
> >>  {
> >>  	struct mem_cgroup *memcg;
> >> -	int idx;
> >> +	struct kmem_cache *memcg_cachep;
> >>  
> >>  	VM_BUG_ON(!cachep->memcg_params);
> >>  	VM_BUG_ON(!cachep->memcg_params->is_root_cache);
> >> @@ -3587,15 +3589,9 @@ struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep,
> >>  	if (!memcg_can_account_kmem(memcg))
> >>  		goto out;
> >>  
> >> -	idx = memcg_cache_id(memcg);
> >> -
> >> -	/*
> >> -	 * barrier to mare sure we're always seeing the up to date value.  The
> >> -	 * code updating memcg_caches will issue a write barrier to match this.
> >> -	 */
> >> -	read_barrier_depends();
> >> -	if (likely(cache_from_memcg_idx(cachep, idx))) {
> >> -		cachep = cache_from_memcg_idx(cachep, idx);
> >> +	memcg_cachep = cache_from_memcg_idx(cachep, memcg_cache_id(memcg));
> >> +	if (likely(memcg_cachep)) {
> >> +		cachep = memcg_cachep;
> >>  		goto out;
> >>  	}
> >>  
> >> diff --git a/mm/slab.h b/mm/slab.h
> >> index 0859c42..1d8b53f 100644
> >> --- a/mm/slab.h
> >> +++ b/mm/slab.h
> >> @@ -163,9 +163,13 @@ static inline const char *cache_name(struct kmem_cache *s)
> >>  static inline struct kmem_cache *
> >>  cache_from_memcg_idx(struct kmem_cache *s, int idx)
> >>  {
> >> +	struct kmem_cache *cachep;
> >> +
> >>  	if (!s->memcg_params)
> >>  		return NULL;
> >> -	return s->memcg_params->memcg_caches[idx];
> >> +	cachep = s->memcg_params->memcg_caches[idx];
> >> +	smp_read_barrier_depends();	/* see memcg_register_cache() */
> >> +	return cachep;
> >>  }
> >>  
> >>  static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s)
> >> -- 
> >> 1.7.10.4
> >>
> 

-- 
Michal Hocko
SUSE Labs

  reply	other threads:[~2013-12-19  9:10 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-18 13:16 [PATCH 1/6] slab: cleanup kmem_cache_create_memcg() Vladimir Davydov
2013-12-18 13:16 ` Vladimir Davydov
2013-12-18 13:16 ` Vladimir Davydov
2013-12-18 13:16 ` [PATCH 2/6] memcg, slab: kmem_cache_create_memcg(): free memcg params on error Vladimir Davydov
2013-12-18 13:16   ` Vladimir Davydov
     [not found]   ` <9420ad797a2cfa14c23ad1ba6db615a2a51ffee0.1387372122.git.vdavydov-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-12-18 17:06     ` Michal Hocko
2013-12-18 17:06       ` Michal Hocko
2013-12-18 17:06       ` Michal Hocko
     [not found]       ` <20131218170649.GC31080-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  6:32         ` Vladimir Davydov
2013-12-19  6:32           ` Vladimir Davydov
2013-12-19  6:32           ` Vladimir Davydov
2013-12-19  8:48           ` Michal Hocko
2013-12-19  8:48             ` Michal Hocko
2013-12-19  9:01             ` Vladimir Davydov
2013-12-19  9:01               ` Vladimir Davydov
2013-12-19  9:19               ` Michal Hocko
2013-12-19  9:19                 ` Michal Hocko
2013-12-18 13:16 ` [PATCH 3/6] memcg, slab: cleanup barrier usage when accessing memcg_caches Vladimir Davydov
2013-12-18 13:16   ` Vladimir Davydov
2013-12-18 17:14   ` Michal Hocko
2013-12-18 17:14     ` Michal Hocko
2013-12-19  6:37     ` Vladimir Davydov
2013-12-19  6:37       ` Vladimir Davydov
2013-12-19  9:10       ` Michal Hocko [this message]
2013-12-19  9:10         ` Michal Hocko
2013-12-19  9:16         ` Vladimir Davydov
2013-12-19  9:16           ` Vladimir Davydov
2013-12-19  9:21           ` Michal Hocko
2013-12-19  9:21             ` Michal Hocko
     [not found]             ` <20131219092137.GG9331-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  9:29               ` Vladimir Davydov
2013-12-19  9:29                 ` Vladimir Davydov
2013-12-19  9:29                 ` Vladimir Davydov
2013-12-19  9:36                 ` Michal Hocko
2013-12-19  9:36                   ` Michal Hocko
     [not found]                   ` <20131219093619.GA10855-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  9:53                     ` Vladimir Davydov
2013-12-19  9:53                       ` Vladimir Davydov
2013-12-19  9:53                       ` Vladimir Davydov
2013-12-18 13:16 ` [PATCH 4/6] memcg, slab: check and init memcg_cahes under slab_mutex Vladimir Davydov
2013-12-18 13:16   ` Vladimir Davydov
2013-12-18 17:41   ` Michal Hocko
2013-12-18 17:41     ` Michal Hocko
     [not found]     ` <20131218174105.GE31080-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  7:07       ` Vladimir Davydov
2013-12-19  7:07         ` Vladimir Davydov
2013-12-19  7:07         ` Vladimir Davydov
     [not found]         ` <52B29B2F.7050909-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-12-19  8:00           ` Glauber Costa
2013-12-19  8:00             ` Glauber Costa
2013-12-19  8:00             ` Glauber Costa
2013-12-19  9:12             ` Michal Hocko
2013-12-19  9:12               ` Michal Hocko
2013-12-19  9:17               ` Vladimir Davydov
2013-12-19  9:17                 ` Vladimir Davydov
2013-12-19  9:21             ` Vladimir Davydov
2013-12-19  9:21               ` Vladimir Davydov
2013-12-18 13:16 ` [PATCH 5/6] memcg: clear memcg_params after removing cache from memcg_slab_caches list Vladimir Davydov
2013-12-18 13:16   ` Vladimir Davydov
2013-12-18 13:16 ` [PATCH 6/6] memcg, slab: RCU protect memcg_params for root caches Vladimir Davydov
2013-12-18 13:16   ` Vladimir Davydov
2013-12-19  9:28   ` Michal Hocko
2013-12-19  9:28     ` Michal Hocko
2013-12-19  9:36     ` Vladimir Davydov
2013-12-19  9:36       ` Vladimir Davydov
     [not found]       ` <52B2BE2A.2080509-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-12-19  9:43         ` Michal Hocko
2013-12-19  9:43           ` Michal Hocko
2013-12-19  9:43           ` Michal Hocko
     [not found]           ` <20131219094333.GB10855-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  9:47             ` Vladimir Davydov
2013-12-19  9:47               ` Vladimir Davydov
2013-12-19  9:47               ` Vladimir Davydov
2013-12-19 10:06               ` Michal Hocko
2013-12-19 10:06                 ` Michal Hocko
2013-12-18 16:56 ` [PATCH 1/6] slab: cleanup kmem_cache_create_memcg() Michal Hocko
2013-12-18 16:56   ` Michal Hocko
     [not found]   ` <20131218165603.GB31080-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  6:31     ` Vladimir Davydov
2013-12-19  6:31       ` Vladimir Davydov
2013-12-19  6:31       ` Vladimir Davydov
2013-12-19  8:44       ` Michal Hocko
2013-12-19  8:44         ` Michal Hocko
     [not found]         ` <20131219084447.GA9331-2MMpYkNvuYDjFM9bn6wA6Q@public.gmane.org>
2013-12-19  8:51           ` Vladimir Davydov
2013-12-19  8:51             ` Vladimir Davydov
2013-12-19  8:51             ` Vladimir Davydov
2013-12-19  9:16             ` Michal Hocko
2013-12-19  9:16               ` Michal Hocko
     [not found] ` <6f02b2d079ffd0990ae335339c803337b13ecd8c.1387372122.git.vdavydov-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-12-19  7:27   ` Pekka Enberg
2013-12-19  7:27     ` Pekka Enberg
2013-12-19  7:27     ` Pekka Enberg
2013-12-19  8:17 ` [Devel] " Vasily Averin
2013-12-19  8:17   ` Vasily Averin
     [not found]   ` <52B2AB7C.1010803-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-12-19  8:39     ` Vladimir Davydov
2013-12-19  8:39       ` Vladimir Davydov
2013-12-19  8:39       ` Vladimir Davydov
     [not found]       ` <52B2B0A4.8050009-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-12-19  9:26         ` Vasily Averin
2013-12-19  9:26           ` Vasily Averin
2013-12-19  9:26           ` Vasily Averin
2013-12-19  9:42           ` Vladimir Davydov
2013-12-19  9:42             ` Vladimir Davydov
2013-12-19  9:45           ` Michal Hocko
2013-12-19  9:45             ` Michal Hocko
2013-12-19 10:23           ` Pekka Enberg
2013-12-19 10:23             ` Pekka Enberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131219091007.GC9331@dhcp22.suse.cz \
    --to=mhocko@suse.cz \
    --cc=akpm@linux-foundation.org \
    --cc=cgroups@vger.kernel.org \
    --cc=cl@linux.com \
    --cc=devel@openvz.org \
    --cc=glommer@gmail.com \
    --cc=hannes@cmpxchg.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=penberg@kernel.org \
    --cc=vdavydov@parallels.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.