読者です 読者をやめる 読者になる 読者になる

slub: allocate_slabでslab object用のページ確保

linux kernel

この記事はLinux Advent Calendar 2014の10日目の記事です。

今回は前回の「slub:slab objectの作成処理を見ていく」で詳細を見なかったnew_slab()でpageを確保するところを見ていきます。

new_slab()では下記のようにallocate_slab()にてページの確保を行います。

1392         page = allocate_slab(s,
1393                 flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node);

ここでpageを確保出来たらslab objectの設定をしていきます。今回はpageの確保部分を見たいのでallocate_slab()を見て行きましょう。
最初はページ確保時のgfpフラグの設定です。flagに__GFP_WAITが立っている場合は一連の処理中に待っても良いので割り込みを有効にしています。

1311 static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
1312 {
1313         struct page *page;
1314         struct kmem_cache_order_objects oo = s->oo;
1315         gfp_t alloc_gfp;
1316 
1317         flags &= gfp_allowed_mask;
1318 
1319         if (flags & __GFP_WAIT)
1320                 local_irq_enable();
1321 
1322         flags |= s->allocflags;
1323 
1324         /*
1325          * Let the initial higher-order allocation fail under memory pressure
1326          * so we fall-back to the minimum order allocation.
1327          */
1328         alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;
1329 

実際にページを確保しているのはalloc_slab_page()です。これは後で見ます。

1330         page = alloc_slab_page(s, alloc_gfp, node, oo);

もしpageの確保ができなかった場合は確保するページ数を減らして再度ページの確保を行います。

1331         if (unlikely(!page)) {
1332                 oo = s->min;
1333                 alloc_gfp = flags;
1334                 /*
1335                  * Allocation may have failed due to fragmentation.
1336                  * Try a lower order alloc if possible
1337                  */
1338                 page = alloc_slab_page(s, alloc_gfp, node, oo);
1339 
1340                 if (page)
1341                         stat(s, ORDER_FALLBACK);
1342         }
1343 

ここはkmemcheckによるデバッグ関連の部分なので飛ばしましょう。

1344         if (kmemcheck_enabled && page
1345                 && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) {
1346                 int pages = 1 << oo_order(oo);
1347 
1348                 kmemcheck_alloc_shadow(page, oo_order(oo), alloc_gfp, node);
1349 
1350                 /*
1351                  * Objects from caches that have a constructor don't get
1352                  * cleared when they're allocated, so we need to do it here.
1353                  */
1354                 if (s->ctor)
1355                         kmemcheck_mark_uninitialized_pages(page, pages);
1356                 else
1357                         kmemcheck_mark_unallocated_pages(page, pages);
1358         }
1359 

割り込みを有効にしていた場合はここで無効に戻します。最終的には__slab_alloc()が最後にlocal_irq_restore()を実行し、元の状態に戻ります。

1360         if (flags & __GFP_WAIT)
1361                 local_irq_disable();

pageが確保できなかったらNULLを返すしかありませんね。

1362         if (!page)
1363                 return NULL;
1364 

ooというのは

1365         page->objects = oo_objects(oo);

kmem_cache_order_objects構造体は以下のような構造です。

 50 /*
 51  * Word size structure that can be atomically updated or read and that
 52  * contains both the order and the number of objects that a slab of the
 53  * given order would contain.
 54  */
 55 struct kmem_cache_order_objects {
 56         unsigned long x;
 57 };

oo_objectsは以下のようにandを取っているだけです。

340 static inline int oo_objects(struct kmem_cache_order_objects x)
341 {
342         return x.x & OO_MASK;
343 }
344 

ここはvmstatの部分なので飛ばしてもOKかな。

1366         mod_zone_page_state(page_zone(page),
1367                 (s->flags & SLAB_RECLAIM_ACCOUNT) ?
1368                 NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
1369                 1 << oo_order(oo));
1370 

最後に確保したページを返す。

1371         return page;
1372 }

先ほど飛ばしたalloc_slab_page()です。確保するpage数は先ほど見たkmem_cache_order_objects構造体にある数値からorderを算出します。これはoo_order()で以下のように行います。

335 static inline int oo_order(struct kmem_cache_order_objects x)
336 {
337         return x.x >> OO_SHIFT;
338 }

ではalloc_slab_page()の中身に。最初は確保するorderを計算。

1289 static inline struct page *alloc_slab_page(struct kmem_cache *s,
1290                 gfp_t flags, int node, struct kmem_cache_order_objects oo)
1291 {
1292         struct page *page;
1293         int order = oo_order(oo);
1294 

__GFP_NOTRACKはkmemcheckによるチェックをしないためらしい。

1295         flags |= __GFP_NOTRACK;
1296 

memcg_charge_slab()はmemory control groupの処理でようは取得したいpage数のアカウンティングができるかどうかのチェックで、アカウンティングできないならメモリが確保できないのでNULLを返すということでしょう。

1297         if (memcg_charge_slab(s, flags, order))
1298                 return NULL;
1299 

ここNUMAノードの指定の有無で呼ぶ関数が変わりますがバディシステムにpageの要求をします。

1300         if (node == NUMA_NO_NODE)
1301                 page = alloc_pages(flags, order);
1302         else
1303                 page = alloc_pages_exact_node(node, flags, order);
1304

pageを確保できなかったらチャージした分を元に戻します。

1305         if (!page)
1306                 memcg_uncharge_slab(s, order);
1307 

最後はpageを返す。

1308         return page;
1309 }

サーバ/インフラ徹底攻略 (WEB+DB PRESS plus)

サーバ/インフラ徹底攻略 (WEB+DB PRESS plus)