mem_cgroup_commit_charge()の処理

カーネルは4.1.15。mem_cgroup_commit_charge()はchargeの処理で呼ばれる関数。

今回はここで使われる関数の詳細は調べないで、大まかな流れを把握するのが目標。

LXRで検索するとmm/filemap.cとかmm/swapfile.c、mm/memory.cなんかから呼ばれてます。 mem_cgroup_commit_charge()自体は40行ほどの関数。引数はcharge対象のpage構造体、所属するmemcgの構造体、最後のlrucareはpageがすでにLRUで管理されているかを示すbool値です。

5522 void mem_cgroup_commit_charge(struct page *page, struct mem_cgroup *memcg,
5523                               bool lrucare)
5524 {
5525         unsigned int nr_pages = 1;
5526 

処理を見ていきます。

5527         VM_BUG_ON_PAGE(!page->mapping, page);
5528         VM_BUG_ON_PAGE(PageLRU(page) && !lrucare, page);
5529 

最初にassertがあります。VM_BUG_ON_PAGEマクロは1番目の引数がif文に使われる条件で、2番目に渡しているpage構造体は値をdumpするのに使います。 最初のチェックは見たままで、2番めのほうはPageLRUマクロではpageがLRUに乗ってるのに、lrucareはfalseっていう矛盾のチェックです。

5530         if (mem_cgroup_disabled())
5531                 return;

memcgが使われてないなら何もしないですよね。

5532         /*
5533          * Swap faults will attempt to charge the same page multiple
5534          * times.  But reuse_swap_page() might have removed the page
5535          * from swapcache already, so we can't check PageSwapCache().
5536          */
5537         if (!memcg)
5538                 return;
5539

swapの処理でcharge済みのページを再度chargeしないようにらしいです。 コメントによるとreuse_swap_page()の場合、swapcacheからpageがなくなっているのでPageSwapCache()を使ってチェックできないと。

5540         commit_charge(page, memcg, lrucare);
5541

commit_charge()は名前の割にchargeの処理してないように見えるけど?今回はここの実装は見ないのでこんな関数を呼ぶよという程度で。

5542         if (PageTransHuge(page)) {
5543                 nr_pages <<= compound_order(page);
5544                 VM_BUG_ON_PAGE(!PageTransHuge(page), page);
5545         }
5546

THP(Transparent Huge Pages)の場合のチェックですね。

5547         local_irq_disable();
5548         mem_cgroup_charge_statistics(memcg, page, nr_pages);
5549         memcg_check_events(memcg, page);
5550         local_irq_enable();
5551

割り込みを無効にして、mem_cgroup_charge_statistics()で実際に値を増やしてますね。↓のような処理があるので。

 836         if (PageAnon(page))
 837                 __this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS],
 838                                 nr_pages);

次にmemcg_check_events()を呼んで、chargeしたことによりsoft limitを超えるかチェックして、超えたら何か処理してます。ここまでやったら割り込みを有効に戻します。

5552         if (do_swap_account && PageSwapCache(page)) {
5553                 swp_entry_t entry = { .val = page_private(page) };
5554                 /*
5555                  * The swap entry might not get freed for a long time,
5556                  * let's not wait for it.  The page already received a
5557                  * memory+swap charge, drop the swap entry duplicate.
5558                  */
5559                 mem_cgroup_uncharge_swap(entry);
5560         }
5561 }

chargeしたのがswap時の場合ですね。if文の条件が真の場合はすでにcharge済みなのでmem_cgroup_uncharge_swap()でunchargeして今回のcharge分を戻します。

( ´ー`)フゥー...

ガベージコレクション

ガベージコレクション