12月版 カーネルゆく年くる年、2009年に来る機能はどれだ?
小崎資広
2009/1/5
Googleからクレーム「Linuxでは負荷監視ができない!」
しばしば、Linuxのスケーラビリティ問題で取り上げられる、性能に影響を与えがちなロックの1つに、mmap_semというリードライトセマフォがあります。
このセマフォは、プロセスの仮想アドレス空間を管理するvm_area_structという構造体を保護するために使われています。プロセスのアドレスを引数に取るさまざまなシステムコールや/proc/[pid]/mapsなど、プロセスのメモリ関係の状態を表示するときに使われます。
しかしながらこのセマフォは、上記の用途だけではなく、ページフォルト時にも使われており、ディスクの読み込みが終わるまでセマフォのリードロックを持ち続けます。当然ですが、ディスクの速度はCPUやメモリに比べてはるかに遅いので、書き込みモードでセマフォを取ろうとしているスレッドを長時間待たせてしまいます。
従来の考えでは、この挙動は問題ではないとされてきました。なぜなら、長時間ロックされているとしても、しょせんプロセスごとのロックであるので、ほかのプロセスに迷惑を掛けるわけではありません。また、しょせんリードロックであるので、少数の仮想アドレス空間を変更するシステムコールとしか競合しないからです。
しかし最近Ying Hanは、この挙動がGoogleにおいて大きな問題を引き起こしていると報告しました。この挙動により、/proc/[pid]/mapsの読み込みが長時間遅延され、負荷監視するモニタソフトがうまく動作しなくなってしまったというのです。
当初、この報告は若干奇異な印象を与えました。なぜなら、/procの読み込みもページフォルトもリードロックなので、競合は発生しないように思えたからです。しかしMike WaychisonがGoogleで起きているシナリオを詳しく説明したことにより、事の詳細が明らかになりました。
- まずシステムが高負荷に陥り、100程度のスレッドでページフォルトが発生、各スレッドがmmap_semのリードロックを持ちつつ、I/O待ちでスリープします。
- さらに別のスレッドがmmap()またはmunmap()を呼び出し、その処理の途中でmmap_semのライトロックを要求します。もちろん、すでにリードロックを持っているスレッドがいるのでこれは成功せず、全スレッドがセマフォを離すのをひたすら待つことになります。
- 最後にモニタソフトが/procの読み取りにより、mmap_semのリードロックを要求します。これは成功せず、待たされることになります。なぜなら、Linuxのリードライトセマフォには「ライト優先の原則」があります。書き込みモードでセマフォを待っているスレッドがいるときは、読み込みモードでのセマフォ獲得要求は待たされるのが仕様だからです。
ここで1や2の状態をプログラム作成者が避けることは現実的ではありません。ページフォルトはカーネルのキャッシュ破棄により、開発者の意図とは関係なく発生してしまうものですし、mmap()/munmap()は、malloc()の延長で勝手に呼ばれるシステムコールであり、malloc()を禁止するのはナンセンスです。
また、リードライトロックにおける書き込みモード優先の仕様を変えることもできません。もしこれを変えてしまうと、複数のCPUを搭載するシステムにおいて、あるCPUがmmap()を要求したときに、残りのCPUは/procを繰り返し読むだけで、常時どれかのCPUが読み込みモードでセマフォを持っていることになります。この結果、mmap()用の書き込みモードのロックは永久に成功しません。これは、リードライトセマフォを使っているカーネルの多くの場所にDoS攻撃に対する脆弱(ぜいじゃく)性をもたらすことになります。
結局、以下のアルゴリズムで対処することになりました。
- まず、通常どおりmmap_semをつかむが、RETRYモードでページフォルト関数を呼び出す
- RETRYモード、かつページキャッシュが存在しないケースでは、ページフォルトI/Oを開始後いったんmmap_semを手離し、ページフォルトI/Oが終了するまでスリープする
- 起床後、ページフォルトの一番最初まで処理を巻き戻し、処理を再開。2回目のページフォルト処理は、従来どおりのmmap_semのリードロックを持ったまま待つモードでページフォルト関数を呼び出す
ここでのポイントは2つあります。まず2で処理をそのまま継続せず、いったん最初まで戻す理由について説明しましょう。ページフォルトI/O待ちスリープ中にいったんロックを手放してしまったので、その間に別スレッドがmunmap()を呼び出すなど、状況が変化しているかもしれません。ですから、ページフォルトのあらゆるチェックを最初から行う必要があります。
また3で、従来のページフォルトにフォールバックしている理由ですが、通常は2の段階ですでにメモリにデータが載っているのでI/O待ちは考えなくてよいのですが、高負荷時などは、メモリに載ったページキャッシュがすぐさま破棄されてしまうかもしれません。このようなケースで無限ループとならないための対策を打っているのです。
これにより、ほとんどのケースにおいて、ページフォルトI/O中はmmap_semを離した状態でスリープすることになるので、ロック競合を大幅に減らすことができます。
このパッチは現在-mmにマージされていますが、xmms(注5)が動かなくなったという報告があり、今後の動向が注目されます。Sound系は特殊なmmapの使い方をするので、その影響かもしれません。一方でPeter Zijlstraは、もっとラディカルに、mmap_semを完全に廃止してしまうパッチを準備中のようです。
注5:Linuxでは一般的なMP3プレイヤー。 |
関連記事: | |
/procによるLinuxチューニング http://www.atmarkit.co.jp/flinux/special/proctune/proctune01b.html |
-stableの進ちょく
■2.6.27.y:
- 2.6.27.9(12月13日):Greg K-H
・sched:OS動作中にCPUを取り外したときにデッドロックする問題を修正(注6)
・jbd:チェックポイントI/O中にI/Oエラーが発生した場合にエラーチェックをしていなかったため、データが失われる可能性があった問題を修正
・FASYNCからBKLを外すパッチにバグがあり、競合状態を生んでしまっていたので、BKLを復活
・32bitアーキテクチャかつ非常に大きなメモリを搭載したマシンにおける/proc/pid/pagemapのリグレッションを修正
ほか、87パッチ
注6:普通外さないだろ! と思う人もいるかもしれませんが、XenなどではCPUを論理的に外したり追加したりすることによりゲストOS間のロードバランスを調整しているので、CPU Hotplugはどんな状況でも動いてくれないと困るのです。 |
- 2.6.27.10(12月18日):Greg K-H
・setup_per_zone_pages_min()においてzone->lru_lockではなく、zone->lockを使うよう修正
・cp437のunicode tableを修正
・e1000e:mutexを二重解放してしまう個所があったのを修正
・"sched_clock"のscd->clockの時間が戻ってしまうのを防ぐパッチの取り消し
・x86:VMWareかつVMI使用時にブート時にクラッシュしてしまう問題 ほか、24パッチ
(以上、敬称略)
2/2 |
|
|
||||
|
連載 Linux Kernel Watch |
Linux Squareフォーラム Linuxカーネル関連記事 |
連載:Linux Kernel Watch(連載中) Linuxカーネル開発の現場ではさまざまな提案や議論が交わされています。その中からいくつかのトピックをピックアップしてお伝えします |
|
連載:Linuxファイルシステム技術解説 ファイルシステムにはそれぞれ特性がある。本連載では、基礎技術から各ファイルシステムの特徴、パフォーマンスを検証する |
|
特集:全貌を現したLinuxカーネル2.6[第1章] エンタープライズ向けに刷新されたカーネル・コア ついに全貌が明らかになったカーネル2.6。6月に正式リリースされる予定の次期安定版カーネルの改良点や新機能を詳しく解説する |
|
特集:/procによるLinuxチューニング[前編] /procで理解するOSの状態 Linuxの状態確認や挙動の変更で重要なのが/procファイルシステムである。/procの概念や/procを利用したOSの状態確認方法を解説する |
|
特集:仮想OS「User
Mode Linux」活用法 Linux上で仮想的なLinuxを動かすUMLの仕組みからインストール/管理方法やIPv6などに対応させるカーネル構築までを徹底解説 |
|
Linuxのカーネルメンテナは柔軟なシステム カーネルメンテナが語るコミュニティとIA-64 Linux IA-64 LinuxのカーネルメンテナであるBjorn Helgaas氏。同氏にLinuxカーネルの開発体制などについて伺った |
|
|
- 【 pidof 】コマンド――コマンド名からプロセスIDを探す (2017/7/27)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、コマンド名からプロセスIDを探す「pidof」コマンドです。 - Linuxの「ジョブコントロール」をマスターしよう (2017/7/21)
今回は、コマンドライン環境でのジョブコントロールを試してみましょう。X環境を持たないサーバ管理やリモート接続時に役立つ操作です - 【 pidstat 】コマンド――プロセスのリソース使用量を表示する (2017/7/21)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、プロセスごとのCPUの使用率やI/Oデバイスの使用状況を表示する「pidstat」コマンドです。 - 【 iostat 】コマンド――I/Oデバイスの使用状況を表示する (2017/7/20)
本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、I/Oデバイスの使用状況を表示する「iostat」コマンドです。
|
|