誰得なめも。バージョンは4.1.15。
__initがついているのは以下の3関数。
- mem_cgroup_init()
- enable_swap_account()
- mem_cgroup_swap_init()
当たり前だけど、__initがあるのでカーネル起動時の初期化で呼ばれる。
mem_cgroup_init()はこのような関数。
5774 static int __init mem_cgroup_init(void) 5775 { 5776 int cpu, node; 5777 5778 hotcpu_notifier(memcg_cpu_hotplug_callback, 0); 5779 5780 for_each_possible_cpu(cpu) 5781 INIT_WORK(&per_cpu_ptr(&memcg_stock, cpu)->work, 5782 drain_local_stock); 5783 5784 for_each_node(node) { 5785 struct mem_cgroup_tree_per_node *rtpn; 5786 int zone; 5787 5788 rtpn = kzalloc_node(sizeof(*rtpn), GFP_KERNEL, 5789 node_online(node) ? node : NUMA_NO_NODE); 5790 5791 for (zone = 0; zone < MAX_NR_ZONES; zone++) { 5792 struct mem_cgroup_tree_per_zone *rtpz; 5793 5794 rtpz = &rtpn->rb_tree_per_zone[zone]; 5795 rtpz->rb_root = RB_ROOT; 5796 spin_lock_init(&rtpz->lock); 5797 } 5798 soft_limit_tree.rb_tree_per_node[node] = rtpn; 5799 } 5800 5801 return 0; 5802 } 5803 subsys_initcall(mem_cgroup_init);
hotcpu_notifier()はcpu hotplugの処理なので無視して、最初のfor_each_possible_cpuマクロはper cpuなデータであるstruct memcg_stock_pcpの初期化。memcg_stock_pcp構造体はこのような構造体。現段階では初期化処理しか追っていないので、この構造体の使用目的は未確認。とりあえず、ワークキューがあるのと(struct work_struct)、nr_pagesというどう考えでもページ数の数を保持するであろうメンバ変数があるのでページ関連の操作で使われるのでしょう。
2055 struct memcg_stock_pcp { 2056 struct mem_cgroup *cached; /* this never be root cgroup */ 2057 unsigned int nr_pages; 2058 struct work_struct work; 2059 unsigned long flags; 2060 #define FLUSHING_CACHED_CHARGE 0 2061 }; 2062 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
次のfor_each_nodeマクロでメモリノード単位で処理が行われる。ここで出てくるmem_cgroup_tree_per_node構造体はこんな感じなんだけど、mm/memcontrol.cで定義されてるので他では使われない模様。赤黒木なデータ構造なんですね。
172 struct mem_cgroup_tree_per_node { 173 struct mem_cgroup_tree_per_zone rb_tree_per_zone[MAX_NR_ZONES]; 174 };
そして、各ゾーン(これはZONE_NORMALとかですね。)毎にrbツリーの初期化をします。
5791 for (zone = 0; zone < MAX_NR_ZONES; zone++) { 5792 struct mem_cgroup_tree_per_zone *rtpz; 5793 5794 rtpz = &rtpn->rb_tree_per_zone[zone]; 5795 rtpz->rb_root = RB_ROOT; 5796 spin_lock_init(&rtpz->lock); 5797 }
初期化したものはsoft_limit_treeという変数のrb_tree_per_node配列に突っ込みます。
5798 soft_limit_tree.rb_tree_per_node[node] = rtpn;
soft_limit_treeはこう宣言されていて基本は参照だけみたいです。
180 static struct mem_cgroup_tree soft_limit_tree __read_mostly;
ちなみに、MAX_NR_ZONESはinclude/generated配下のファイルにあるのでビルド時に定義されるようです。
./include/generated/bounds.h:10:#define MAX_NR_ZONES 4 /* __MAX_NR_ZONES # */
2つ目の初期化処理はenable_swap_account()で、これはカーネルの起動時のコマンドラインで渡されたswapaccountの処理ですね。really_do_swap_account変数に値を設定するだけです。
5877 static int __init enable_swap_account(char *s) 5878 { 5879 if (!strcmp(s, "1")) 5880 really_do_swap_account = 1; 5881 else if (!strcmp(s, "0")) 5882 really_do_swap_account = 0; 5883 return 1; 5884 } 5885 __setup("swapaccount=", enable_swap_account); 5886
このコマンドライン引数がなければ呼ばれないですけど。その場合はデフォルト値があるのでそちらが使われます。
5870 /* for remember boot option*/ 5871 #ifdef CONFIG_MEMCG_SWAP_ENABLED 5872 static int really_do_swap_account __initdata = 1; 5873 #else 5874 static int really_do_swap_account __initdata; 5875 #endif
3つ目はmem_cgroup_swap_init()です。memory cgroupがenableで、really_do_swap_accountが1の場合(あえてswapaccount=0を設定しなければ大抵1になってるのでは)に処理があります。
5914 static int __init mem_cgroup_swap_init(void) 5915 { 5916 if (!mem_cgroup_disabled() && really_do_swap_account) { 5917 do_swap_account = 1; 5918 WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys, 5919 memsw_cgroup_files)); 5920 } 5921 return 0; 5922 } 5923 subsys_initcall(mem_cgroup_swap_init);
do_swap_accountを1に設定しているので、swapもアカウンティングするよというのと、cgroup_add_legacy_cftypes()を呼んでいるのでmemory cgroupのファイル作成処理があります。作成するのは以下のファイルです。/sys/kernel/fs/cgroup/memoryに以下のファイルが作られます。
5887 static struct cftype memsw_cgroup_files[] = { 5888 { 5889 .name = "memsw.usage_in_bytes", 5890 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE), 5891 .read_u64 = mem_cgroup_read_u64, 5892 }, 5893 { 5894 .name = "memsw.max_usage_in_bytes", 5895 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE), 5896 .write = mem_cgroup_reset, 5897 .read_u64 = mem_cgroup_read_u64, 5898 }, 5899 { 5900 .name = "memsw.limit_in_bytes", 5901 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT), 5902 .write = mem_cgroup_write, 5903 .read_u64 = mem_cgroup_read_u64, 5904 }, 5905 { 5906 .name = "memsw.failcnt", 5907 .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT), 5908 .write = mem_cgroup_reset, 5909 .read_u64 = mem_cgroup_read_u64, 5910 }, 5911 { }, /* terminate */ 5912 };
cgroup_add_legacy_cftypes()に渡しているmemory_cgrp_subsysは以下のようになってます。
75 struct cgroup_subsys memory_cgrp_subsys __read_mostly; 76 EXPORT_SYMBOL(memory_cgrp_subsys);
初期化処理はこんな感じですね。
- メディア: ウェア&シューズ
- この商品を含むブログを見る