Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

slab: embed memcg_cache_params to kmem_cache

Currently, kmem_cache stores a pointer to struct memcg_cache_params
instead of embedding it. The rationale is to save memory when kmem
accounting is disabled. However, the memcg_cache_params has shrivelled
drastically since it was first introduced:

* Initially:

struct memcg_cache_params {
bool is_root_cache;
union {
struct kmem_cache *memcg_caches[0];
struct {
struct mem_cgroup *memcg;
struct list_head list;
struct kmem_cache *root_cache;
bool dead;
atomic_t nr_pages;
struct work_struct destroy;
};
};
};

* Now:

struct memcg_cache_params {
bool is_root_cache;
union {
struct {
struct rcu_head rcu_head;
struct kmem_cache *memcg_caches[0];
};
struct {
struct mem_cgroup *memcg;
struct kmem_cache *root_cache;
};
};
};

So the memory saving does not seem to be a clear win anymore.

OTOH, keeping a pointer to memcg_cache_params struct instead of embedding
it results in touching one more cache line on kmem alloc/free hot paths.
Besides, it makes linking kmem caches in a list chained by a field of
struct memcg_cache_params really painful due to a level of indirection,
while I want to make them linked in the following patch. That said, let
us embed it.

Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Tejun Heo <tj@kernel.org>
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: Dave Chinner <david@fromorbit.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Vladimir Davydov and committed by
Linus Torvalds
f7ce3190 49e7e7ff

+112 -104
+7 -10
include/linux/slab.h
··· 473 473 #ifndef ARCH_SLAB_MINALIGN 474 474 #define ARCH_SLAB_MINALIGN __alignof__(unsigned long long) 475 475 #endif 476 + 477 + struct memcg_cache_array { 478 + struct rcu_head rcu; 479 + struct kmem_cache *entries[0]; 480 + }; 481 + 476 482 /* 477 483 * This is the main placeholder for memcg-related information in kmem caches. 478 - * struct kmem_cache will hold a pointer to it, so the memory cost while 479 - * disabled is 1 pointer. The runtime cost while enabled, gets bigger than it 480 - * would otherwise be if that would be bundled in kmem_cache: we'll need an 481 - * extra pointer chase. But the trade off clearly lays in favor of not 482 - * penalizing non-users. 483 - * 484 484 * Both the root cache and the child caches will have it. For the root cache, 485 485 * this will hold a dynamically allocated array large enough to hold 486 486 * information about the currently limited memcgs in the system. To allow the ··· 495 495 struct memcg_cache_params { 496 496 bool is_root_cache; 497 497 union { 498 - struct { 499 - struct rcu_head rcu_head; 500 - struct kmem_cache *memcg_caches[0]; 501 - }; 498 + struct memcg_cache_array __rcu *memcg_caches; 502 499 struct { 503 500 struct mem_cgroup *memcg; 504 501 struct kmem_cache *root_cache;
+1 -1
include/linux/slab_def.h
··· 70 70 int obj_offset; 71 71 #endif /* CONFIG_DEBUG_SLAB */ 72 72 #ifdef CONFIG_MEMCG_KMEM 73 - struct memcg_cache_params *memcg_params; 73 + struct memcg_cache_params memcg_params; 74 74 #endif 75 75 76 76 struct kmem_cache_node *node[MAX_NUMNODES];
+1 -1
include/linux/slub_def.h
··· 85 85 struct kobject kobj; /* For sysfs */ 86 86 #endif 87 87 #ifdef CONFIG_MEMCG_KMEM 88 - struct memcg_cache_params *memcg_params; 88 + struct memcg_cache_params memcg_params; 89 89 int max_attr_size; /* for propagation, maximum size of a stored attr */ 90 90 #ifdef CONFIG_SYSFS 91 91 struct kset *memcg_kset;
+5 -6
mm/memcontrol.c
··· 332 332 struct cg_proto tcp_mem; 333 333 #endif 334 334 #if defined(CONFIG_MEMCG_KMEM) 335 - /* Index in the kmem_cache->memcg_params->memcg_caches array */ 335 + /* Index in the kmem_cache->memcg_params.memcg_caches array */ 336 336 int kmemcg_id; 337 337 #endif 338 338 ··· 531 531 532 532 #ifdef CONFIG_MEMCG_KMEM 533 533 /* 534 - * This will be the memcg's index in each cache's ->memcg_params->memcg_caches. 534 + * This will be the memcg's index in each cache's ->memcg_params.memcg_caches. 535 535 * The main reason for not using cgroup id for this: 536 536 * this works better in sparse environments, where we have a lot of memcgs, 537 537 * but only a few kmem-limited. Or also, if we have, for instance, 200 ··· 2667 2667 struct mem_cgroup *memcg; 2668 2668 struct kmem_cache *memcg_cachep; 2669 2669 2670 - VM_BUG_ON(!cachep->memcg_params); 2671 - VM_BUG_ON(!cachep->memcg_params->is_root_cache); 2670 + VM_BUG_ON(!is_root_cache(cachep)); 2672 2671 2673 2672 if (current->memcg_kmem_skip_account) 2674 2673 return cachep; ··· 2701 2702 void __memcg_kmem_put_cache(struct kmem_cache *cachep) 2702 2703 { 2703 2704 if (!is_root_cache(cachep)) 2704 - css_put(&cachep->memcg_params->memcg->css); 2705 + css_put(&cachep->memcg_params.memcg->css); 2705 2706 } 2706 2707 2707 2708 /* ··· 2777 2778 if (PageSlab(page)) { 2778 2779 cachep = page->slab_cache; 2779 2780 if (!is_root_cache(cachep)) 2780 - memcg = cachep->memcg_params->memcg; 2781 + memcg = cachep->memcg_params.memcg; 2781 2782 } else 2782 2783 /* page allocated by alloc_kmem_pages */ 2783 2784 memcg = page->mem_cgroup;
+23 -25
mm/slab.h
··· 86 86 extern void create_boot_cache(struct kmem_cache *, const char *name, 87 87 size_t size, unsigned long flags); 88 88 89 - struct mem_cgroup; 90 - 91 89 int slab_unmergeable(struct kmem_cache *s); 92 90 struct kmem_cache *find_mergeable(size_t size, size_t align, 93 91 unsigned long flags, const char *name, void (*ctor)(void *)); ··· 165 167 #ifdef CONFIG_MEMCG_KMEM 166 168 static inline bool is_root_cache(struct kmem_cache *s) 167 169 { 168 - return !s->memcg_params || s->memcg_params->is_root_cache; 170 + return s->memcg_params.is_root_cache; 169 171 } 170 172 171 173 static inline bool slab_equal_or_root(struct kmem_cache *s, 172 - struct kmem_cache *p) 174 + struct kmem_cache *p) 173 175 { 174 - return (p == s) || 175 - (s->memcg_params && (p == s->memcg_params->root_cache)); 176 + return p == s || p == s->memcg_params.root_cache; 176 177 } 177 178 178 179 /* ··· 182 185 static inline const char *cache_name(struct kmem_cache *s) 183 186 { 184 187 if (!is_root_cache(s)) 185 - return s->memcg_params->root_cache->name; 188 + s = s->memcg_params.root_cache; 186 189 return s->name; 187 190 } 188 191 189 192 /* 190 193 * Note, we protect with RCU only the memcg_caches array, not per-memcg caches. 191 - * That said the caller must assure the memcg's cache won't go away. Since once 192 - * created a memcg's cache is destroyed only along with the root cache, it is 193 - * true if we are going to allocate from the cache or hold a reference to the 194 - * root cache by other means. Otherwise, we should hold either the slab_mutex 195 - * or the memcg's slab_caches_mutex while calling this function and accessing 196 - * the returned value. 194 + * That said the caller must assure the memcg's cache won't go away by either 195 + * taking a css reference to the owner cgroup, or holding the slab_mutex. 197 196 */ 198 197 static inline struct kmem_cache * 199 198 cache_from_memcg_idx(struct kmem_cache *s, int idx) 200 199 { 201 200 struct kmem_cache *cachep; 202 - struct memcg_cache_params *params; 203 - 204 - if (!s->memcg_params) 205 - return NULL; 201 + struct memcg_cache_array *arr; 206 202 207 203 rcu_read_lock(); 208 - params = rcu_dereference(s->memcg_params); 204 + arr = rcu_dereference(s->memcg_params.memcg_caches); 209 205 210 206 /* 211 207 * Make sure we will access the up-to-date value. The code updating 212 208 * memcg_caches issues a write barrier to match this (see 213 - * memcg_register_cache()). 209 + * memcg_create_kmem_cache()). 214 210 */ 215 - cachep = lockless_dereference(params->memcg_caches[idx]); 211 + cachep = lockless_dereference(arr->entries[idx]); 216 212 rcu_read_unlock(); 217 213 218 214 return cachep; ··· 215 225 { 216 226 if (is_root_cache(s)) 217 227 return s; 218 - return s->memcg_params->root_cache; 228 + return s->memcg_params.root_cache; 219 229 } 220 230 221 231 static __always_inline int memcg_charge_slab(struct kmem_cache *s, ··· 225 235 return 0; 226 236 if (is_root_cache(s)) 227 237 return 0; 228 - return memcg_charge_kmem(s->memcg_params->memcg, gfp, 1 << order); 238 + return memcg_charge_kmem(s->memcg_params.memcg, gfp, 1 << order); 229 239 } 230 240 231 241 static __always_inline void memcg_uncharge_slab(struct kmem_cache *s, int order) ··· 234 244 return; 235 245 if (is_root_cache(s)) 236 246 return; 237 - memcg_uncharge_kmem(s->memcg_params->memcg, 1 << order); 247 + memcg_uncharge_kmem(s->memcg_params.memcg, 1 << order); 238 248 } 239 - #else 249 + 250 + extern void slab_init_memcg_params(struct kmem_cache *); 251 + 252 + #else /* !CONFIG_MEMCG_KMEM */ 253 + 240 254 static inline bool is_root_cache(struct kmem_cache *s) 241 255 { 242 256 return true; ··· 276 282 static inline void memcg_uncharge_slab(struct kmem_cache *s, int order) 277 283 { 278 284 } 279 - #endif 285 + 286 + static inline void slab_init_memcg_params(struct kmem_cache *s) 287 + { 288 + } 289 + #endif /* CONFIG_MEMCG_KMEM */ 280 290 281 291 static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) 282 292 {
+72 -59
mm/slab_common.c
··· 106 106 #endif 107 107 108 108 #ifdef CONFIG_MEMCG_KMEM 109 - static int memcg_alloc_cache_params(struct mem_cgroup *memcg, 110 - struct kmem_cache *s, struct kmem_cache *root_cache) 109 + void slab_init_memcg_params(struct kmem_cache *s) 111 110 { 112 - size_t size; 111 + s->memcg_params.is_root_cache = true; 112 + RCU_INIT_POINTER(s->memcg_params.memcg_caches, NULL); 113 + } 113 114 114 - if (!memcg_kmem_enabled()) 115 - return 0; 116 - 117 - if (!memcg) { 118 - size = offsetof(struct memcg_cache_params, memcg_caches); 119 - size += memcg_nr_cache_ids * sizeof(void *); 120 - } else 121 - size = sizeof(struct memcg_cache_params); 122 - 123 - s->memcg_params = kzalloc(size, GFP_KERNEL); 124 - if (!s->memcg_params) 125 - return -ENOMEM; 115 + static int init_memcg_params(struct kmem_cache *s, 116 + struct mem_cgroup *memcg, struct kmem_cache *root_cache) 117 + { 118 + struct memcg_cache_array *arr; 126 119 127 120 if (memcg) { 128 - s->memcg_params->memcg = memcg; 129 - s->memcg_params->root_cache = root_cache; 130 - } else 131 - s->memcg_params->is_root_cache = true; 121 + s->memcg_params.is_root_cache = false; 122 + s->memcg_params.memcg = memcg; 123 + s->memcg_params.root_cache = root_cache; 124 + return 0; 125 + } 132 126 127 + slab_init_memcg_params(s); 128 + 129 + if (!memcg_nr_cache_ids) 130 + return 0; 131 + 132 + arr = kzalloc(sizeof(struct memcg_cache_array) + 133 + memcg_nr_cache_ids * sizeof(void *), 134 + GFP_KERNEL); 135 + if (!arr) 136 + return -ENOMEM; 137 + 138 + RCU_INIT_POINTER(s->memcg_params.memcg_caches, arr); 133 139 return 0; 134 140 } 135 141 136 - static void memcg_free_cache_params(struct kmem_cache *s) 142 + static void destroy_memcg_params(struct kmem_cache *s) 137 143 { 138 - kfree(s->memcg_params); 144 + if (is_root_cache(s)) 145 + kfree(rcu_access_pointer(s->memcg_params.memcg_caches)); 139 146 } 140 147 141 - static int memcg_update_cache_params(struct kmem_cache *s, int num_memcgs) 148 + static int update_memcg_params(struct kmem_cache *s, int new_array_size) 142 149 { 143 - int size; 144 - struct memcg_cache_params *new_params, *cur_params; 150 + struct memcg_cache_array *old, *new; 145 151 146 - BUG_ON(!is_root_cache(s)); 152 + if (!is_root_cache(s)) 153 + return 0; 147 154 148 - size = offsetof(struct memcg_cache_params, memcg_caches); 149 - size += num_memcgs * sizeof(void *); 150 - 151 - new_params = kzalloc(size, GFP_KERNEL); 152 - if (!new_params) 155 + new = kzalloc(sizeof(struct memcg_cache_array) + 156 + new_array_size * sizeof(void *), GFP_KERNEL); 157 + if (!new) 153 158 return -ENOMEM; 154 159 155 - cur_params = s->memcg_params; 156 - memcpy(new_params->memcg_caches, cur_params->memcg_caches, 157 - memcg_nr_cache_ids * sizeof(void *)); 160 + old = rcu_dereference_protected(s->memcg_params.memcg_caches, 161 + lockdep_is_held(&slab_mutex)); 162 + if (old) 163 + memcpy(new->entries, old->entries, 164 + memcg_nr_cache_ids * sizeof(void *)); 158 165 159 - new_params->is_root_cache = true; 160 - 161 - rcu_assign_pointer(s->memcg_params, new_params); 162 - if (cur_params) 163 - kfree_rcu(cur_params, rcu_head); 164 - 166 + rcu_assign_pointer(s->memcg_params.memcg_caches, new); 167 + if (old) 168 + kfree_rcu(old, rcu); 165 169 return 0; 166 170 } 167 171 ··· 176 172 177 173 mutex_lock(&slab_mutex); 178 174 list_for_each_entry(s, &slab_caches, list) { 179 - if (!is_root_cache(s)) 180 - continue; 181 - 182 - ret = memcg_update_cache_params(s, num_memcgs); 175 + ret = update_memcg_params(s, num_memcgs); 183 176 /* 184 177 * Instead of freeing the memory, we'll just leave the caches 185 178 * up to this point in an updated state. ··· 188 187 return ret; 189 188 } 190 189 #else 191 - static inline int memcg_alloc_cache_params(struct mem_cgroup *memcg, 192 - struct kmem_cache *s, struct kmem_cache *root_cache) 190 + static inline int init_memcg_params(struct kmem_cache *s, 191 + struct mem_cgroup *memcg, struct kmem_cache *root_cache) 193 192 { 194 193 return 0; 195 194 } 196 195 197 - static inline void memcg_free_cache_params(struct kmem_cache *s) 196 + static inline void destroy_memcg_params(struct kmem_cache *s) 198 197 { 199 198 } 200 199 #endif /* CONFIG_MEMCG_KMEM */ ··· 312 311 s->align = align; 313 312 s->ctor = ctor; 314 313 315 - err = memcg_alloc_cache_params(memcg, s, root_cache); 314 + err = init_memcg_params(s, memcg, root_cache); 316 315 if (err) 317 316 goto out_free_cache; 318 317 ··· 328 327 return s; 329 328 330 329 out_free_cache: 331 - memcg_free_cache_params(s); 330 + destroy_memcg_params(s); 332 331 kmem_cache_free(kmem_cache, s); 333 332 goto out; 334 333 } ··· 440 439 441 440 #ifdef CONFIG_MEMCG_KMEM 442 441 if (!is_root_cache(s)) { 443 - struct kmem_cache *root_cache = s->memcg_params->root_cache; 444 - int memcg_id = memcg_cache_id(s->memcg_params->memcg); 442 + int idx; 443 + struct memcg_cache_array *arr; 445 444 446 - BUG_ON(root_cache->memcg_params->memcg_caches[memcg_id] != s); 447 - root_cache->memcg_params->memcg_caches[memcg_id] = NULL; 445 + idx = memcg_cache_id(s->memcg_params.memcg); 446 + arr = rcu_dereference_protected(s->memcg_params.root_cache-> 447 + memcg_params.memcg_caches, 448 + lockdep_is_held(&slab_mutex)); 449 + BUG_ON(arr->entries[idx] != s); 450 + arr->entries[idx] = NULL; 448 451 } 449 452 #endif 450 453 list_move(&s->list, release); ··· 486 481 struct kmem_cache *root_cache) 487 482 { 488 483 static char memcg_name_buf[NAME_MAX + 1]; /* protected by slab_mutex */ 489 - int memcg_id = memcg_cache_id(memcg); 484 + struct memcg_cache_array *arr; 490 485 struct kmem_cache *s = NULL; 491 486 char *cache_name; 487 + int idx; 492 488 493 489 get_online_cpus(); 494 490 get_online_mems(); 495 491 496 492 mutex_lock(&slab_mutex); 497 493 494 + idx = memcg_cache_id(memcg); 495 + arr = rcu_dereference_protected(root_cache->memcg_params.memcg_caches, 496 + lockdep_is_held(&slab_mutex)); 497 + 498 498 /* 499 499 * Since per-memcg caches are created asynchronously on first 500 500 * allocation (see memcg_kmem_get_cache()), several threads can try to 501 501 * create the same cache, but only one of them may succeed. 502 502 */ 503 - if (cache_from_memcg_idx(root_cache, memcg_id)) 503 + if (arr->entries[idx]) 504 504 goto out_unlock; 505 505 506 506 cgroup_name(mem_cgroup_css(memcg)->cgroup, 507 507 memcg_name_buf, sizeof(memcg_name_buf)); 508 508 cache_name = kasprintf(GFP_KERNEL, "%s(%d:%s)", root_cache->name, 509 - memcg_cache_id(memcg), memcg_name_buf); 509 + idx, memcg_name_buf); 510 510 if (!cache_name) 511 511 goto out_unlock; 512 512 ··· 535 525 * initialized. 536 526 */ 537 527 smp_wmb(); 538 - root_cache->memcg_params->memcg_caches[memcg_id] = s; 528 + arr->entries[idx] = s; 539 529 540 530 out_unlock: 541 531 mutex_unlock(&slab_mutex); ··· 555 545 556 546 mutex_lock(&slab_mutex); 557 547 list_for_each_entry_safe(s, s2, &slab_caches, list) { 558 - if (is_root_cache(s) || s->memcg_params->memcg != memcg) 548 + if (is_root_cache(s) || s->memcg_params.memcg != memcg) 559 549 continue; 560 550 /* 561 551 * The cgroup is about to be freed and therefore has no charges ··· 574 564 575 565 void slab_kmem_cache_release(struct kmem_cache *s) 576 566 { 577 - memcg_free_cache_params(s); 567 + destroy_memcg_params(s); 578 568 kfree(s->name); 579 569 kmem_cache_free(kmem_cache, s); 580 570 } ··· 650 640 s->name = name; 651 641 s->size = s->object_size = size; 652 642 s->align = calculate_alignment(flags, ARCH_KMALLOC_MINALIGN, size); 643 + 644 + slab_init_memcg_params(s); 645 + 653 646 err = __kmem_cache_create(s, flags); 654 647 655 648 if (err) ··· 993 980 994 981 if (p == slab_caches.next) 995 982 print_slabinfo_header(m); 996 - if (!is_root_cache(s) && s->memcg_params->memcg == memcg) 983 + if (!is_root_cache(s) && s->memcg_params.memcg == memcg) 997 984 cache_show(s, m); 998 985 return 0; 999 986 }
+3 -2
mm/slub.c
··· 3577 3577 p->slab_cache = s; 3578 3578 #endif 3579 3579 } 3580 + slab_init_memcg_params(s); 3580 3581 list_add(&s->list, &slab_caches); 3581 3582 return s; 3582 3583 } ··· 4965 4964 if (is_root_cache(s)) 4966 4965 return; 4967 4966 4968 - root_cache = s->memcg_params->root_cache; 4967 + root_cache = s->memcg_params.root_cache; 4969 4968 4970 4969 /* 4971 4970 * This mean this cache had no attribute written. Therefore, no point ··· 5045 5044 { 5046 5045 #ifdef CONFIG_MEMCG_KMEM 5047 5046 if (!is_root_cache(s)) 5048 - return s->memcg_params->root_cache->memcg_kset; 5047 + return s->memcg_params.root_cache->memcg_kset; 5049 5048 #endif 5050 5049 return slab_kset; 5051 5050 }