SystemTapで真犯人を捕まえろ!(1/4) − @IT(情報元のブックマーク数)

連載最終話、デバッグハックスw、尻尾を捕まえてさらし首→修正→無罪放免w

前回までで「カーネル空間」の「物理メモリ」を消費し過ぎた結果、OS停止に至った可能性があるというところまで突き止めました。今回は、カーネル空間のどの部分を消費し過ぎていたのか、さらには根本的な原因は何だったのかを追求していきます。

 カーネル空間の物理メモリといっても、まずはどの部分のメモリを消費しているのか把握しなければなりません。これを把握するには/proc/meminfoを見るのが最も簡単です。/proc/meminfoの出力例は以下のようなものでした。

SystemTapで真犯人を捕まえろ! (1/4):Linuxトラブルシューティング探偵団 番外編(3) - @IT

alloc_pages()とか関数系を色々調査して、調べるたとのこと。

つまり、通常のAPIは利用していないが、MemFreeのカウントダウンは行っているのです。MemFreeをカウントダウンさせるような処理は、各種メモリ確保APIよりもローレベルな部分で実装されています。Slabやvmalloc、PageTablesなどもすべて、このMemFreeをカウントダウンさせるような共通関数を利用しています。その関数がalloc_pages()(注3)です。

 基本的にこの関数はメモリの統計情報のカウント対象にならないため、直接使うことは望ましくないのですが、ソースコードgrepしてみると、このalloc_pages()を直接呼び出している不届き者は結構います。特に、ドライバのような「一度メモリを確保するともうあまりメモリを必要としない」ルーチンに多く見られます。ほかにも、DMA領域用のメモリ確保など、多くのサブシステムから共通関数として呼び出されています。

 今回もこのalloc_pages()を直接呼び出している部分を中心的に調べるのがよさそうです。しかし、非常に多くの部分で利用されているこの関数の呼び出し元を逐一追っていくのもまた現実的ではありません。どうすれば問題の根源を見つけることができるのでしょうか……?

SystemTapで真犯人を捕まえろ! (2/4):Linuxトラブルシューティング探偵団 番外編(3) - @IT

すげぇなぁ、ここまで解析。

そして、最終的にalloc_pagesとfree_pagesの対応関係が取れていないように見えたのが、NFSから呼び出されているものと、cciss(HP製SMARTアレイのドライバ)から呼び出されているものでした。

SystemTapで真犯人を捕まえろ! (2/4):Linuxトラブルシューティング探偵団 番外編(3) - @IT

やっぱり、Changelogは重要ww

これを糸口にしてカーネルChangeLogを調査してみると、kernel-2.6.10で修正されていることが分かりました(注5)。RHEL 4はkernel-2.6.9ベースのカーネルで構築されているため、このパッチは取り込まれていません。
さらに、ccissのデバイスドライバでは、DMAマスクは32bitマスク(4Gbytes)で定義されています。そのため、x86_64かつIOMMU(注6)を持たないCPUで(注7)、物理メモリを4Gbytes以上搭載していると、この事象が発生することになります。今回はx86_64で50Gbytesものメモリを搭載しているため、十分この条件に当てはまりそうです。

SystemTapで真犯人を捕まえろ! (3/4):Linuxトラブルシューティング探偵団 番外編(3) - @IT

MemFreeって無くなると時々しますが、大丈夫なんですよねぇ。(そりゃ本当にまずいとだめだけど

【第1回で覚えておいてほしいこと】

  • MemFreeが少なくなることを恐れてはいけない
  • freeコマンドの結果は物理メモリ使用量の正確な把握には向かない
  • 物理メモリ使用状況把握にはActive、Inactiveを使うべきである

【第2回で覚えておいてほしいこと】

  • 仮想メモリと物理メモリの違い
  • カーネルにはswapやOOM-Killerなど、物理メモリ枯渇に対する防御機構が存在する
  • 利用可能な物理メモリが極限までなくなるとリブートに至る可能性がある

【第3回で覚えておいてほしいこと】

  • /proc/meminfoの見方
  • カーネルの物理メモリ使用量には把握できない部分があること
  • SystemTapによる解析の有効性
SystemTapで真犯人を捕まえろ! (4/4):Linuxトラブルシューティング探偵団 番外編(3) - @IT

screenshot