Skip to content

Commit 2a4db7e

Browse files
Vladimir Davydovtorvalds
authored andcommitted
memcg: free memcg_caches slot on css offline
We need to look up a kmem_cache in ->memcg_params.memcg_caches arrays only on allocations, so there is no need to have the array entries set until css free - we can clear them on css offline. This will allow us to reuse array entries more efficiently and avoid costly array relocations. Signed-off-by: Vladimir Davydov <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Tejun Heo <[email protected]> Cc: Christoph Lameter <[email protected]> Cc: Pekka Enberg <[email protected]> Cc: David Rientjes <[email protected]> Cc: Joonsoo Kim <[email protected]> Cc: Dave Chinner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f100836 commit 2a4db7e

File tree

3 files changed

+65
-22
lines changed

3 files changed

+65
-22
lines changed

include/linux/slab.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,12 @@ int slab_is_available(void);
115115
struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
116116
unsigned long,
117117
void (*)(void *));
118-
#ifdef CONFIG_MEMCG_KMEM
119-
void memcg_create_kmem_cache(struct mem_cgroup *, struct kmem_cache *);
120-
void memcg_destroy_kmem_caches(struct mem_cgroup *);
121-
#endif
122118
void kmem_cache_destroy(struct kmem_cache *);
123119
int kmem_cache_shrink(struct kmem_cache *);
124-
void kmem_cache_free(struct kmem_cache *, void *);
120+
121+
void memcg_create_kmem_cache(struct mem_cgroup *, struct kmem_cache *);
122+
void memcg_deactivate_kmem_caches(struct mem_cgroup *);
123+
void memcg_destroy_kmem_caches(struct mem_cgroup *);
125124

126125
/*
127126
* Please use this macro to create slab caches. Simply specify the
@@ -288,6 +287,7 @@ static __always_inline int kmalloc_index(size_t size)
288287

289288
void *__kmalloc(size_t size, gfp_t flags);
290289
void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags);
290+
void kmem_cache_free(struct kmem_cache *, void *);
291291

292292
#ifdef CONFIG_NUMA
293293
void *__kmalloc_node(size_t size, gfp_t flags, int node);

mm/memcontrol.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ struct mem_cgroup {
334334
#if defined(CONFIG_MEMCG_KMEM)
335335
/* Index in the kmem_cache->memcg_params.memcg_caches array */
336336
int kmemcg_id;
337+
bool kmem_acct_active;
337338
#endif
338339

339340
int last_scanned_node;
@@ -354,7 +355,7 @@ struct mem_cgroup {
354355
#ifdef CONFIG_MEMCG_KMEM
355356
bool memcg_kmem_is_active(struct mem_cgroup *memcg)
356357
{
357-
return memcg->kmemcg_id >= 0;
358+
return memcg->kmem_acct_active;
358359
}
359360
#endif
360361

@@ -585,7 +586,7 @@ static void memcg_free_cache_id(int id);
585586

586587
static void disarm_kmem_keys(struct mem_cgroup *memcg)
587588
{
588-
if (memcg_kmem_is_active(memcg)) {
589+
if (memcg->kmemcg_id >= 0) {
589590
static_key_slow_dec(&memcg_kmem_enabled_key);
590591
memcg_free_cache_id(memcg->kmemcg_id);
591592
}
@@ -2666,17 +2667,19 @@ struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep)
26662667
{
26672668
struct mem_cgroup *memcg;
26682669
struct kmem_cache *memcg_cachep;
2670+
int kmemcg_id;
26692671

26702672
VM_BUG_ON(!is_root_cache(cachep));
26712673

26722674
if (current->memcg_kmem_skip_account)
26732675
return cachep;
26742676

26752677
memcg = get_mem_cgroup_from_mm(current->mm);
2676-
if (!memcg_kmem_is_active(memcg))
2678+
kmemcg_id = ACCESS_ONCE(memcg->kmemcg_id);
2679+
if (kmemcg_id < 0)
26772680
goto out;
26782681

2679-
memcg_cachep = cache_from_memcg_idx(cachep, memcg_cache_id(memcg));
2682+
memcg_cachep = cache_from_memcg_idx(cachep, kmemcg_id);
26802683
if (likely(memcg_cachep))
26812684
return memcg_cachep;
26822685

@@ -3318,8 +3321,8 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg,
33183321
int err = 0;
33193322
int memcg_id;
33203323

3321-
if (memcg_kmem_is_active(memcg))
3322-
return 0;
3324+
BUG_ON(memcg->kmemcg_id >= 0);
3325+
BUG_ON(memcg->kmem_acct_active);
33233326

33243327
/*
33253328
* For simplicity, we won't allow this to be disabled. It also can't
@@ -3362,6 +3365,7 @@ static int memcg_activate_kmem(struct mem_cgroup *memcg,
33623365
* patched.
33633366
*/
33643367
memcg->kmemcg_id = memcg_id;
3368+
memcg->kmem_acct_active = true;
33653369
out:
33663370
return err;
33673371
}
@@ -4041,6 +4045,22 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
40414045
return mem_cgroup_sockets_init(memcg, ss);
40424046
}
40434047

4048+
static void memcg_deactivate_kmem(struct mem_cgroup *memcg)
4049+
{
4050+
if (!memcg->kmem_acct_active)
4051+
return;
4052+
4053+
/*
4054+
* Clear the 'active' flag before clearing memcg_caches arrays entries.
4055+
* Since we take the slab_mutex in memcg_deactivate_kmem_caches(), it
4056+
* guarantees no cache will be created for this cgroup after we are
4057+
* done (see memcg_create_kmem_cache()).
4058+
*/
4059+
memcg->kmem_acct_active = false;
4060+
4061+
memcg_deactivate_kmem_caches(memcg);
4062+
}
4063+
40444064
static void memcg_destroy_kmem(struct mem_cgroup *memcg)
40454065
{
40464066
memcg_destroy_kmem_caches(memcg);
@@ -4052,6 +4072,10 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
40524072
return 0;
40534073
}
40544074

4075+
static void memcg_deactivate_kmem(struct mem_cgroup *memcg)
4076+
{
4077+
}
4078+
40554079
static void memcg_destroy_kmem(struct mem_cgroup *memcg)
40564080
{
40574081
}
@@ -4608,6 +4632,8 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
46084632
spin_unlock(&memcg->event_list_lock);
46094633

46104634
vmpressure_cleanup(&memcg->vmpressure);
4635+
4636+
memcg_deactivate_kmem(memcg);
46114637
}
46124638

46134639
static void mem_cgroup_css_free(struct cgroup_subsys_state *css)

mm/slab_common.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -440,18 +440,8 @@ static int do_kmem_cache_shutdown(struct kmem_cache *s,
440440
*need_rcu_barrier = true;
441441

442442
#ifdef CONFIG_MEMCG_KMEM
443-
if (!is_root_cache(s)) {
444-
int idx;
445-
struct memcg_cache_array *arr;
446-
447-
idx = memcg_cache_id(s->memcg_params.memcg);
448-
arr = rcu_dereference_protected(s->memcg_params.root_cache->
449-
memcg_params.memcg_caches,
450-
lockdep_is_held(&slab_mutex));
451-
BUG_ON(arr->entries[idx] != s);
452-
arr->entries[idx] = NULL;
443+
if (!is_root_cache(s))
453444
list_del(&s->memcg_params.list);
454-
}
455445
#endif
456446
list_move(&s->list, release);
457447
return 0;
@@ -499,6 +489,13 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,
499489

500490
mutex_lock(&slab_mutex);
501491

492+
/*
493+
* The memory cgroup could have been deactivated while the cache
494+
* creation work was pending.
495+
*/
496+
if (!memcg_kmem_is_active(memcg))
497+
goto out_unlock;
498+
502499
idx = memcg_cache_id(memcg);
503500
arr = rcu_dereference_protected(root_cache->memcg_params.memcg_caches,
504501
lockdep_is_held(&slab_mutex));
@@ -548,6 +545,26 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,
548545
put_online_cpus();
549546
}
550547

548+
void memcg_deactivate_kmem_caches(struct mem_cgroup *memcg)
549+
{
550+
int idx;
551+
struct memcg_cache_array *arr;
552+
struct kmem_cache *s;
553+
554+
idx = memcg_cache_id(memcg);
555+
556+
mutex_lock(&slab_mutex);
557+
list_for_each_entry(s, &slab_caches, list) {
558+
if (!is_root_cache(s))
559+
continue;
560+
561+
arr = rcu_dereference_protected(s->memcg_params.memcg_caches,
562+
lockdep_is_held(&slab_mutex));
563+
arr->entries[idx] = NULL;
564+
}
565+
mutex_unlock(&slab_mutex);
566+
}
567+
551568
void memcg_destroy_kmem_caches(struct mem_cgroup *memcg)
552569
{
553570
LIST_HEAD(release);

0 commit comments

Comments
 (0)