この記事はLinux Advent Calendar 2014の3日目の記事です。
kmem_cache_zalloc()、名前だけ見ると単純そうな気がするけど割とそうでもないのでした。この関数は最初のほうは別の関数へのラッパー程度になっていますが、memcg_kmem_get_cache()、__memcg_kmem_get_cache()辺りでちゃんとした処理になります。
これらは kmem_cache_zalloc()から呼ばれるのでまずはdo_kmem_cache_create()が kmem_cache_zalloc()]を呼んでいるのでここからスタートします。 一番目の引数kmem_cacheはstruct kmem_cache *な変数でmm/slab_common.cで定義されていますが、mm/slab.hの方でextern付きで宣言されています。これはカーネルの初期化のタイミングで設定される変数だと思います。変数名と構造体名が一緒なのでlxrで使っている箇所を探しづらい・・・
136 static struct kmem_cache * 137 do_kmem_cache_create(char *name, size_t object_size, size_t size, size_t align, 138 unsigned long flags, void (*ctor)(void *), 139 struct mem_cgroup *memcg, struct kmem_cache *root_cache) 140 { 141 struct kmem_cache *s; 142 int err; 143 144 err = -ENOMEM; 145 s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL); 146 if (!s) 147 goto out;
kmem_cache_zalloc()はこのような関数でGFPフラグに__GFP_ZEROをつけてて納得の処理です。
627 static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags) 628 { 629 return kmem_cache_alloc(k, flags | __GFP_ZERO); 630 } 631
kmem_cache_alloc()はこうです。ここは単にslab_alloc()を呼ぶだけです。
2457 void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) 2458 { 2459 void *ret = slab_alloc(s, gfpflags, _RET_IP_); 2460 2461 trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, 2462 s->size, gfpflags); 2463 2464 return ret; 2465 }
次のslab_alloc()はslab_alloc_node()を呼びます。これもNUMAがあるから適切なnodeからメモリを確保したいよねという感じですね。
2451 static __always_inline void *slab_alloc(struct kmem_cache *s, 2452 gfp_t gfpflags, unsigned long addr) 2453 { 2454 return slab_alloc_node(s, gfpflags, NUMA_NO_NODE, addr); 2455 }
slab_alloc_node()の最初のほうでmemcg_kmem_get_cache()が呼ばれます。slab_pre_alloc_hook()はここでは気にしなくてもOKです。
2373 static __always_inline void *slab_alloc_node(struct kmem_cache *s, 2374 gfp_t gfpflags, int node, unsigned long addr) 2375 { 2376 void **object; 2377 struct kmem_cache_cpu *c; 2378 struct page *page; 2379 unsigned long tid; 2380 2381 if (slab_pre_alloc_hook(s, gfpflags)) 2382 return NULL; 2383 2384 s = memcg_kmem_get_cache(s, gfpflags); 2385 redo:
そしてmemcg_kmem_get_cache()です。一つ一つのif文の意味はあとにして、ここで何をするかというと、cachepを返すパターンというのはkmem_cache_zalloc()の第1引数を返すということで、グローバルに設定されているkmem_cache変数をスラブの管理に使う感じですね。そうじゃない場合に__memcg_kmem_get_cache()が呼ばれます。
534 static __always_inline struct kmem_cache * 535 memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp) 536 { 537 if (!memcg_kmem_enabled()) 538 return cachep; 539 if (gfp & __GFP_NOFAIL) 540 return cachep; 541 if (in_interrupt() || (!current->mm) || (current->flags & PF_KTHREAD)) 542 return cachep; 543 if (unlikely(fatal_signal_pending(current))) 544 return cachep; 545 546 return __memcg_kmem_get_cache(cachep, gfp); 547 }
__memcg_kmem_get_cache()を見ていきます。最初は飛ばして・・・
3249 struct kmem_cache *__memcg_kmem_get_cache(struct kmem_cache *cachep, 3250 gfp_t gfp) 3251 { 3252 struct mem_cgroup *memcg; 3253 struct kmem_cache *memcg_cachep; 3254 3255 VM_BUG_ON(!cachep->memcg_params); 3256 VM_BUG_ON(!cachep->memcg_params->is_root_cache); 3257
まず、current->mmがNULLな場合というのはcurrentプロセスがカーネルスレッドの場合でこの場合はcachepを返す。もしくは current->memcg_kmem_skip_accounが0じゃない場合のところですが、これは後々出てくるんだけど、memcg_schedule_register_cache()が内部でkmalloc()を使います。この時に(kmallocはスラブキャッシュから適切なサイズのメモリを返します)取得しようとしたサイズにあうキャッシュが存在しなかった場合、キャッシュの作成処理が必要なのですが、そうするとスラブキャッシュの作成処理でまた__memcg_kmem_get_cacheが呼ばれてくるのでその時はcachepを返しているというようです。
3258 if (!current->mm || current->memcg_kmem_skip_account) 3259 return cachep; 3260
ここはstruct task_structのcurrentからmem_cgroupを取得するだけ。
3261 rcu_read_lock(); 3262 memcg = mem_cgroup_from_task(rcu_dereference(current->mm->owner)); 3263
memory cgroupでメモリの使用量をアカウンティングできるかどうかのチェック。
3264 if (!memcg_can_account_kmem(memcg)) 3265 goto out; 3266
cache_from_memcg_idx() ここはstruct kmem_cache構造体が持っているmemory cgroupからキャッシュがあるか調べて見つかったらそれをreturnする。
3267 memcg_cachep = cache_from_memcg_idx(cachep, memcg_cache_id(memcg)); 3268 if (likely(memcg_cachep)) { 3269 cachep = memcg_cachep; 3270 goto out; 3271 } 3272
cssとはcgroup subsys stateの模様。渡しているのはstruct cgroup_subsys_state *。
3273 /* The corresponding put will be done in the workqueue. */ 3274 if (!css_tryget_online(&memcg->css)) 3275 goto out; 3276 rcu_read_unlock(); 3277
ここでの最後の処理はmemcg_schedule_register_cache()を呼んでキャッシュの登録。
3278 /* 3279 * If we are in a safe context (can wait, and not in interrupt 3280 * context), we could be be predictable and return right away. 3281 * This would guarantee that the allocation being performed 3282 * already belongs in the new cache. 3283 * 3284 * However, there are some clashes that can arrive from locking. 3285 * For instance, because we acquire the slab_mutex while doing 3286 * memcg_create_kmem_cache, this means no further allocation 3287 * could happen with the slab_mutex held. So it's better to 3288 * defer everything. 3289 */ 3290 memcg_schedule_register_cache(memcg, cachep); 3291 return cachep; 3292 out: 3293 rcu_read_unlock(); 3294 return cachep; 3295 }
memcg_schedule_register_cache()を見る前にcache_from_memcg_idx()を先に。 ここはほぼ見ての通りで、params->memcg_caches[idx]がcachepに設定される。
152 static inline struct kmem_cache * 153 cache_from_memcg_idx(struct kmem_cache *s, int idx) 154 { 155 struct kmem_cache *cachep; 156 struct memcg_cache_params *params; 157 158 if (!s->memcg_params) 159 return NULL; 160 161 rcu_read_lock(); 162 params = rcu_dereference(s->memcg_params); 163 cachep = params->memcg_caches[idx]; 164 rcu_read_unlock(); 165 166 /* 167 * Make sure we will access the up-to-date value. The code updating 168 * memcg_caches issues a write barrier to match this (see 169 * memcg_register_cache()). 170 */ 171 smp_read_barrier_depends(); 172 return cachep; 173 }
ここでデータ構造を確認しておくとstruct kmem_cache構造体にmemcg_paramsという構造体があって、cache_from_memcg_idx()で見ているのはグローバル変数のkmem_cacheに設定されているmemcg_params。
87 #ifdef CONFIG_MEMCG_KMEM 88 struct memcg_cache_params *memcg_params;
struct memcg_paramsはこのような構造体。
531 struct memcg_cache_params { 532 bool is_root_cache; 533 union { 534 struct { 535 struct rcu_head rcu_head; 536 struct kmem_cache *memcg_caches[0]; 537 }; 538 struct { 539 struct mem_cgroup *memcg; 540 struct list_head list; 541 struct kmem_cache *root_cache; 542 atomic_t nr_pages; 543 }; 544 }; 545 };
で、memcg_schedule_register_cache()に進すむ。 ここはmemcg_schedule_register_cache()の前後でアカウンティングのストップとリジュームがありますねという程度。なぜこれをやっているかはコメント参照。kmalloc云々というのは先程のmemcg_kmem_get_cache()でアカウンティングできるかどうか調べていたところに関係してます。
3200 static void memcg_schedule_register_cache(struct mem_cgroup *memcg, 3201 struct kmem_cache *cachep) 3202 { 3203 /* 3204 * We need to stop accounting when we kmalloc, because if the 3205 * corresponding kmalloc cache is not yet created, the first allocation 3206 * in __memcg_schedule_register_cache will recurse. 3207 * 3208 * However, it is better to enclose the whole function. Depending on 3209 * the debugging options enabled, INIT_WORK(), for instance, can 3210 * trigger an allocation. This too, will make us recurse. Because at 3211 * this point we can't allow ourselves back into memcg_kmem_get_cache, 3212 * the safest choice is to do it like this, wrapping the whole function. 3213 */ 3214 memcg_stop_kmem_account(); 3215 __memcg_schedule_register_cache(memcg, cachep); 3216 memcg_resume_kmem_account(); 3217 } 3218
そして__memcg_schedule_register_cache()。 ここでやりたいのはワークキューに突っ込むデータを作って時が来たらmemcg_register_cache_func()を実行するというもの。
3182 static void __memcg_schedule_register_cache(struct mem_cgroup *memcg, 3183 struct kmem_cache *cachep) 3184 { 3185 struct memcg_register_cache_work *cw; 3186 3187 cw = kmalloc(sizeof(*cw), GFP_NOWAIT); 3188 if (cw == NULL) { 3189 css_put(&memcg->css); 3190 return; 3191 } 3192 3193 cw->memcg = memcg; 3194 cw->cachep = cachep; 3195 3196 INIT_WORK(&cw->work, memcg_register_cache_func); 3197 schedule_work(&cw->work); 3198 }
memcy_register_cach_func()はこれで、主要なのはmemcg_register_cache()。
3164 static void memcg_register_cache_func(struct work_struct *w) 3165 { 3166 struct memcg_register_cache_work *cw = 3167 container_of(w, struct memcg_register_cache_work, work); 3168 struct mem_cgroup *memcg = cw->memcg; 3169 struct kmem_cache *cachep = cw->cachep; 3170 3171 mutex_lock(&memcg_slab_mutex); 3172 memcg_register_cache(memcg, cachep); 3173 mutex_unlock(&memcg_slab_mutex); 3174 3175 css_put(&memcg->css); 3176 kfree(cw); 3177 }
memcg_resister_cache()はこのような関数。
3024 static void memcg_register_cache(struct mem_cgroup *memcg, 3025 struct kmem_cache *root_cache) 3026 { 3027 static char memcg_name_buf[NAME_MAX + 1]; /* protected by 3028 memcg_slab_mutex */ 3029 struct kmem_cache *cachep; 3030 int id; 3031 3032 lockdep_assert_held(&memcg_slab_mutex); 3033
memory cgroupは構造体にidを降って関しているらしい。
3034 id = memcg_cache_id(memcg); 3035
またcache_from_memcg_idx()を呼んでいるけ。ここで渡しているのは今までも使っていたcachep。ここで見つかればそれで良しということか。戻り値そのものは捨てているか。
3036 /* 3037 * Since per-memcg caches are created asynchronously on first 3038 * allocation (see memcg_kmem_get_cache()), several threads can try to 3039 * create the same cache, but only one of them may succeed. 3040 */ 3041 if (cache_from_memcg_idx(root_cache, id)) 3042 return; 3043
これは本当にcgroupに名前を設定するだけか。
3044 cgroup_name(memcg->css.cgroup, memcg_name_buf, NAME_MAX + 1);
memcg_create_kmem_cache()はその名の通りの処理でしょう。詳細は後ほど。
3045 cachep = memcg_create_kmem_cache(memcg, root_cache, memcg_name_buf); 3046 /* 3047 * If we could not create a memcg cache, do not complain, because 3048 * that's not critical at all as we can always proceed with the root 3049 * cache. 3050 */ 3051 if (!cachep) 3052 return; 3053
キャッシュが作れたらリストに登録。
3054 list_add(&cachep->memcg_params->list, &memcg->memcg_slab_caches); 3055 3056 /* 3057 * Since readers won't lock (see cache_from_memcg_idx()), we need a 3058 * barrier here to ensure nobody will see the kmem_cache partially 3059 * initialized. 3060 */ 3061 smp_wmb(); 3062
最後にmemcg_paramsのmemcg_cachesのid番目にcachepを設定する。
3063 BUG_ON(root_cache->memcg_params->memcg_caches[id]); 3064 root_cache->memcg_params->memcg_caches[id] = cachep; 3065 }
memcg_create_kmem_cache()です。やっているのはキャッシュの名前を設定してdo_kmem_cache_create()を呼ぶ。そして、また今日の日記の最初からスタートという流れですね。
275 struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg, 276 struct kmem_cache *root_cache, 277 const char *memcg_name) 278 { 279 struct kmem_cache *s = NULL; 280 char *cache_name; 281 282 get_online_cpus(); 283 get_online_mems(); 284 285 mutex_lock(&slab_mutex); 286 287 cache_name = kasprintf(GFP_KERNEL, "%s(%d:%s)", root_cache->name, 288 memcg_cache_id(memcg), memcg_name); 289 if (!cache_name) 290 goto out_unlock; 291 292 s = do_kmem_cache_create(cache_name, root_cache->object_size, 293 root_cache->size, root_cache->align, 294 root_cache->flags, root_cache->ctor, 295 memcg, root_cache); 296 if (IS_ERR(s)) { 297 kfree(cache_name); 298 s = NULL; 299 } 300 301 out_unlock: 302 mutex_unlock(&slab_mutex); 303 304 put_online_mems(); 305 put_online_cpus(); 306 307 return s; 308 }
駆け足気味で見てきましたがまだkmem_cache_zalloc()の処理は全然終わってません\(^o^)/ ここまでみてmemcg_kmem_get_cache()の処理を追えただけでまだまだ先は長いです。 memory cgroupが強敵かも・・・
Effective Ruby あなたのRubyをより輝かせる48の特別な方法
- 作者: Peter J. Jones,arton,長尾高弘
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/16
- メディア: 大型本
- この商品を含むブログ (1件) を見る