diff options
author | Vladimir Davydov <vdavydov@parallels.com> | 2015-02-12 17:59:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-12 21:54:09 -0500 |
commit | 05257a1a3dcc196c197714b5c9a8dd35b7f6aefc (patch) | |
tree | 063e4bafec04171990ce3f95f649a9e3c6dcd6a8 /mm/slab_common.c | |
parent | dbcf73e26cd0b3d66e6db65ab595e664a55e58ff (diff) |
memcg: add rwsem to synchronize against memcg_caches arrays relocation
We need a stable value of memcg_nr_cache_ids in kmem_cache_create()
(memcg_alloc_cache_params() wants it for root caches), where we only
hold the slab_mutex and no memcg-related locks. As a result, we have to
update memcg_nr_cache_ids under the slab_mutex, which we can only take
on the slab's side (see memcg_update_array_size). This looks awkward
and will become even worse when per-memcg list_lru is introduced, which
also wants stable access to memcg_nr_cache_ids.
To get rid of this dependency between the memcg_nr_cache_ids and the
slab_mutex, this patch introduces a special rwsem. The rwsem is held
for writing during memcg_caches arrays relocation and memcg_nr_cache_ids
updates. Therefore one can take it for reading to get a stable access
to memcg_caches arrays and/or memcg_nr_cache_ids.
Currently the semaphore is taken for reading only from
kmem_cache_create, right before taking the slab_mutex, so right now
there's no much point in using rwsem instead of mutex. However, once
list_lru is made per-memcg it will allow list_lru initializations to
proceed concurrently.
Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Greg Thelen <gthelen@google.com>
Cc: Glauber Costa <glommer@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r-- | mm/slab_common.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/mm/slab_common.c b/mm/slab_common.c index f8899eedab68..23f5fcde6043 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
@@ -169,8 +169,8 @@ int memcg_update_all_caches(int num_memcgs) | |||
169 | { | 169 | { |
170 | struct kmem_cache *s; | 170 | struct kmem_cache *s; |
171 | int ret = 0; | 171 | int ret = 0; |
172 | mutex_lock(&slab_mutex); | ||
173 | 172 | ||
173 | mutex_lock(&slab_mutex); | ||
174 | list_for_each_entry(s, &slab_caches, list) { | 174 | list_for_each_entry(s, &slab_caches, list) { |
175 | if (!is_root_cache(s)) | 175 | if (!is_root_cache(s)) |
176 | continue; | 176 | continue; |
@@ -181,11 +181,8 @@ int memcg_update_all_caches(int num_memcgs) | |||
181 | * up to this point in an updated state. | 181 | * up to this point in an updated state. |
182 | */ | 182 | */ |
183 | if (ret) | 183 | if (ret) |
184 | goto out; | 184 | break; |
185 | } | 185 | } |
186 | |||
187 | memcg_update_array_size(num_memcgs); | ||
188 | out: | ||
189 | mutex_unlock(&slab_mutex); | 186 | mutex_unlock(&slab_mutex); |
190 | return ret; | 187 | return ret; |
191 | } | 188 | } |
@@ -369,6 +366,7 @@ kmem_cache_create(const char *name, size_t size, size_t align, | |||
369 | 366 | ||
370 | get_online_cpus(); | 367 | get_online_cpus(); |
371 | get_online_mems(); | 368 | get_online_mems(); |
369 | memcg_get_cache_ids(); | ||
372 | 370 | ||
373 | mutex_lock(&slab_mutex); | 371 | mutex_lock(&slab_mutex); |
374 | 372 | ||
@@ -407,6 +405,7 @@ kmem_cache_create(const char *name, size_t size, size_t align, | |||
407 | out_unlock: | 405 | out_unlock: |
408 | mutex_unlock(&slab_mutex); | 406 | mutex_unlock(&slab_mutex); |
409 | 407 | ||
408 | memcg_put_cache_ids(); | ||
410 | put_online_mems(); | 409 | put_online_mems(); |
411 | put_online_cpus(); | 410 | put_online_cpus(); |
412 | 411 | ||