aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorVladimir Davydov <vdavydov@parallels.com>2015-02-12 17:59:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-12 21:54:09 -0500
commit05257a1a3dcc196c197714b5c9a8dd35b7f6aefc (patch)
tree063e4bafec04171990ce3f95f649a9e3c6dcd6a8 /mm/memcontrol.c
parentdbcf73e26cd0b3d66e6db65ab595e664a55e58ff (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/memcontrol.c')
-rw-r--r--mm/memcontrol.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 8608fa543b84..6706e5fa5ac0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -544,6 +544,19 @@ static void disarm_sock_keys(struct mem_cgroup *memcg)
544static DEFINE_IDA(memcg_cache_ida); 544static DEFINE_IDA(memcg_cache_ida);
545int memcg_nr_cache_ids; 545int memcg_nr_cache_ids;
546 546
547/* Protects memcg_nr_cache_ids */
548static DECLARE_RWSEM(memcg_cache_ids_sem);
549
550void memcg_get_cache_ids(void)
551{
552 down_read(&memcg_cache_ids_sem);
553}
554
555void memcg_put_cache_ids(void)
556{
557 up_read(&memcg_cache_ids_sem);
558}
559
547/* 560/*
548 * MIN_SIZE is different than 1, because we would like to avoid going through 561 * MIN_SIZE is different than 1, because we would like to avoid going through
549 * the alloc/free process all the time. In a small machine, 4 kmem-limited 562 * the alloc/free process all the time. In a small machine, 4 kmem-limited
@@ -2549,6 +2562,7 @@ static int memcg_alloc_cache_id(void)
2549 * There's no space for the new id in memcg_caches arrays, 2562 * There's no space for the new id in memcg_caches arrays,
2550 * so we have to grow them. 2563 * so we have to grow them.
2551 */ 2564 */
2565 down_write(&memcg_cache_ids_sem);
2552 2566
2553 size = 2 * (id + 1); 2567 size = 2 * (id + 1);
2554 if (size < MEMCG_CACHES_MIN_SIZE) 2568 if (size < MEMCG_CACHES_MIN_SIZE)
@@ -2557,6 +2571,11 @@ static int memcg_alloc_cache_id(void)
2557 size = MEMCG_CACHES_MAX_SIZE; 2571 size = MEMCG_CACHES_MAX_SIZE;
2558 2572
2559 err = memcg_update_all_caches(size); 2573 err = memcg_update_all_caches(size);
2574 if (!err)
2575 memcg_nr_cache_ids = size;
2576
2577 up_write(&memcg_cache_ids_sem);
2578
2560 if (err) { 2579 if (err) {
2561 ida_simple_remove(&memcg_cache_ida, id); 2580 ida_simple_remove(&memcg_cache_ida, id);
2562 return err; 2581 return err;
@@ -2569,16 +2588,6 @@ static void memcg_free_cache_id(int id)
2569 ida_simple_remove(&memcg_cache_ida, id); 2588 ida_simple_remove(&memcg_cache_ida, id);
2570} 2589}
2571 2590
2572/*
2573 * We should update the current array size iff all caches updates succeed. This
2574 * can only be done from the slab side. The slab mutex needs to be held when
2575 * calling this.
2576 */
2577void memcg_update_array_size(int num)
2578{
2579 memcg_nr_cache_ids = num;
2580}
2581
2582struct memcg_kmem_cache_create_work { 2591struct memcg_kmem_cache_create_work {
2583 struct mem_cgroup *memcg; 2592 struct mem_cgroup *memcg;
2584 struct kmem_cache *cachep; 2593 struct kmem_cache *cachep;