compaction_suitable()はcompact_zone()の最初に使う関数で、コンパクションしようとしているzoneをコンパクションするかどうか判断する。
compaction_suitable()自体はたいした処理はなく、__compaction_suitable()が実際にチェックをする。
1259 unsigned long compaction_suitable(struct zone *zone, int order, 1260 int alloc_flags, int classzone_idx) 1261 { 1262 unsigned long ret; 1263 1264 ret = __compaction_suitable(zone, order, alloc_flags, classzone_idx); 1265 trace_mm_compaction_suitable(zone, order, ret); 1266 if (ret == COMPACT_NOT_SUITABLE_ZONE) 1267 ret = COMPACT_SKIPPED; 1268 1269 return ret; 1270 }
__compaction_suitable()のコメントを除く割と短めです。
1210 static unsigned long __compaction_suitable(struct zone *zone, int order, 1211 int alloc_flags, int classzone_idx) 1212 { 1213 int fragindex; 1214 unsigned long watermark; 1215
最初のチェックでorderが-1かちぇっくしてますね、これは通常のallocationだとありえませんが、/proc/sys/vm/compact_memoryに値を書き込んでコンパクションを行った場合にorderが-1に設定されます。この場合は常にコンパクションを実行することになります。
1220 if (order == -1) 1221 return COMPACT_CONTINUE; 1222
ちなみに、compact_memoryに値を設定してコンパクションを実行する場合は↓のような流れになり、compact_node() のなかでorderを-1に設定しています。
sysctl_compaction_handler() -> compact_nodes() -> compact_node() -> __compact_pgdat() -> compact_zone()
low_wmark_pages()はzoneのlowのwatermarkを読み出します。
1223 watermark = low_wmark_pages(zone);
zone_watermark_ok()は前回の記事で読んだところです。非ゼロが返ってきた場合はwatermarkを下回っていない場合でした。なのでCOMPACT_PARTIALを返します。COMPACT_PARTIALはmm/compaction.hにて定義されていて、コメントによると、部分的にコンパクションされていて、order分のページを割り当てできる状態とのことです。
1228 if (zone_watermark_ok(zone, order, watermark, classzone_idx, 1229 alloc_flags)) 1230 return COMPACT_PARTIAL; 1231
次はorderを0にしてチェックします。ここでwatermarkを増やしているのは、コメントに書いてありますが、pageのmigration中は短い時間だけどcopyを持つ必要があるからとなってます。あと、orderを0にするのはこれならcompactionできるはずと言うことみたいです。が、これでもダメなら、このzoneのコンパクションを諦めます。
1237 watermark += (2UL << order); 1238 if (!zone_watermark_ok(zone, 0, watermark, classzone_idx, alloc_flags)) 1239 return COMPACT_SKIPPED; 1240
最後に呼び出す関数はfragmentation_index()です。ここの内容は無視できないフラグメンテーション問題への解答は?(1/2) − @ITを読んだほうが分かると思いますm(__)m fragmentation_index()の結果が最終的にこのzoneをコンパクションするかどうかという答えになります。
1252 fragindex = fragmentation_index(zone, order); 1253 if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold) 1254 return COMPACT_NOT_SUITABLE_ZONE; 1255 1256 return COMPACT_CONTINUE; 1257 }
compaction_suitable()を呼んでいるcompact_zone()は結果をこのように処理しています。まあ、COMPACT_CONTINUEが返ってきた場合はコンパクションを継続するというそのままですが。
1281 ret = compaction_suitable(zone, cc->order, cc->alloc_flags, 1282 cc->classzone_idx); 1283 switch (ret) { 1284 case COMPACT_PARTIAL: 1285 case COMPACT_SKIPPED: 1286 /* Compaction is likely to fail */ 1287 return ret; 1288 case COMPACT_CONTINUE: 1289 /* Fall through to compaction */ 1290 ; 1291 }
- 作者: Miran Lipovaca
- 出版社/メーカー: オーム社
- 発売日: 2012/09/21
- メディア: Kindle版
- 購入: 4人 クリック: 9回
- この商品を含むブログを見る