悪質なUSBスティックストールの問題 -LWN.net、2013年11月。
Artem S. Tashkinovは最近、少なくとも一部のLWN読者には馴染みのある問題に遭遇しました。低速のストレージデバイス(USBスティックなど、またはメディアプレーヤー)をLinuxマシンに接続し、それに大量のデータを書き込みます。 システム全体がハングアップします、おそらく数分間。
しかし今回、Artemは興味深い観察を行いました。64ビットカーネルで実行するとシステムが停止しますが、同じハードウェアで32ビットカーネルを使用すると、そのような問題は発生しませんでした。
この記事では、64ビットカーネルでは、ダーティページキャッシュ(別名ライトバックキャッシュ)がデフォルトでメモリの20%まで拡大できることが説明されています。 32ビットのカーネルでは、実質的に180 MBに制限されていました。
Linusは、64ビットでも〜180MBに制限することを提案しましたが、現在のLinux(v4.18)はこれを行いません。 Linusの推奨パッチ を Linux 4.18の現在の関数 と比較します。このような変更に対する最大の議論は、Dave Chinnerからのものでした。彼 指摘 バッファリングを減らしすぎると、ファイルシステムが断片化することになる。彼はまた 観察 その「ストリーミングの場合IO通常、少なくとも5秒のキャッシュダーティ遅延をなくすためのデータ。」
私は混乱しています。 USBスティックのストールによりシステム全体がハングしたのはなぜですか?
コードについて説明した以前の記事 2011年にマージ (Linux 3.2)を読んだので混乱しています。これは、カーネルがダーティページキャッシュをデバイスごとに制御している必要があることを示しています。
No-I/Oダーティスロットリング -LWN.net、2011
そこでFengguangのパッチセットが登場します。彼は、各プロセスが常にダーティにできるページ数を決定できる制御ループを作成しようとしています。制限を超えたプロセスは、ライトバックシステムが追いつくことができるように、しばらくの間単にスリープ状態になります。
[...]
システムの目標は、ダーティページの数をセットポイントに保つことです。物事が狂ったら、力を加えて物事を本来あるべき場所に戻すでしょう。
[...]
ただし、バッキングデバイス(BDI)を考慮しないと、この比率を実際に計算することはできません。プロセスは特定のBDIに保存されているページをダーティ化している可能性があり、システムには現在ダーティページの過剰な影響がある可能性があります。 [...]ダーティページが少ないBDIは、バックログをすばやくクリアできるため、システムが多少汚れている場合でも、おそらくそれ以上の余裕があります。そのため、パッチセットは、特定のBDIが独自のセットポイントおよび観測された帯域幅からどれだけ離れているかを調べる複雑な式を使用して、特定のBDIの計算されたpos_ratioを微調整します。最終結果は変更されたpos_ratioであり、システムが特定のBDIによってバックアップされたページをダーティにする必要があるかどうか、およびどれだけダーティにする必要があるかを記述します。
これよりも前に、デバイスごとの制御が追加されました: Smarter write throttling 、2007 LWN.net。 [デバイスあたり0/23]ダーティスロットリング-v1 。 Linuxバージョン2.6.24 に統合されました。
「USBスティックストール」の記事は、非常に誤解を招く印象を与えます。元のレポートと一連の応答の両方を誤って表している。
Artemは、キャッシュされた書き込みをUSBスティックにフラッシュしたときにシステム全体がハングしたことを報告しませんでした。彼の 元のレポート は、コマンド「sync」の実行に最大「数十分」かかる可能性があるとだけ不満を述べていました。この区別は、Linus Torvaldsによる response で明示されています。
平均的なUSBキーを取り、それを書き込もうとするだけで、実際に再現するのは本当に簡単です。私はランダムなISOイメージでそれをやっただけで、それは苦痛です。 そして、それはバックグラウンドで他のほとんどのことをするのに苦痛であるということではありません、しかしあなたが「同期する」(そしてそれがスクリプトで起こる)何かをたまたま実行した場合、そのことはただぎゅっと止まることになります。 数分。
Jon Corbet は15年の経験があり、Linuxカーネルの開発を毎週報告しています。この回答を書くのは非常に複雑になります:-(。Corbetの記事が間違っているか、不適切なフレーズであるかを示したいのですが、おそらくcloseでした私は2つの異なるレコードを処理して、彼らが同意するか、または同意しない詳細なポイントを探す必要があります。
Lore.kernel.orgのアーカイブを使用して、 元のディスカッション の全体を読みました。メッセージはかなり明確だと思います。
私はその記事が間違っていると100%確信しています。記事の下のコメントでは、少なくとも2人の読者が誤った主張を自分の言葉で繰り返し、誰もそれを訂正していませんでした。記事では、この混乱を3番目の段落で続けています。
これらのデータはすべてI/Oキューを詰まらせ、他の操作を遅らせる可能性があります。そして、誰かが sync() を呼び出すとすぐに、キュー全体が書き込まれるまで停止します。
これは、Linusが「事はただ急に止まるだけだ」と言って混乱している可能性があります。 「モノ」は「sync
を実行するもの(およびスクリプトで発生するもの)」を指します。しかし、Corbetは、「モノ」が「システム全体」を意味するかのように書いています。
Linusによると、これは現実の問題です。しかし、大部分のことは、システム全体のsync()操作をしない呼び出しを行います。[1]
Corbetがこれを「システム全体」と混同するのはなぜですか?私は多くの問題があったと思います、そしてしばらくするとそれらをあなたの頭の中で別々に保つのが難しくなります:-)。また、LWNはデバイスごと(およびプロセスごと)のダーティスロットリングの開発について説明していますが、一般に、そのような詳細についてはあまり書かれていないと思います。多くのドキュメントには、グローバルなダーティリミット設定のみが記載されています。
Artemがスレッドに second report を投稿しました。「サーバーはほとんど停止しており、他のIOリクエストは完了するまでにかなり時間がかかります」。
この2番目のレポートは、USBスティックのハングに関する主張と一致しません。 内部ディスクに10GBのファイルを作成した後に発生しました。これは別の問題です。
レポートは、ダーティリミットを変更することでこれを改善できるかどうかを確認しませんでした。そして、このようなケースのより最近の分析があります。メインディスクのI/Oキューが詰まると、重大な問題が発生します。プログラムコードをオンデマンドでロードしたり、write()+ fsync()を使用してドキュメントやアプリデータを保存したりするために、常に依存しているディスクで長い遅延が発生する可能性があります。
煩わしさの少ないバックグラウンドライトバックに向けて -LWN.net、2016
メモリ管理コードが一定範囲のダーティデータを書き込むことを決定すると、その結果、I/O要求がブロックサブシステムに送信されます。その要求はI/Oスケジューラである程度の時間を費やす可能性がありますが、最終的には宛先デバイスのドライバーにディスパッチされます。
問題は、書き込むダーティデータが多い場合、デバイスに対してキューに入れられたリクエストが膨大な数(数千など)になることです。かなり高速なドライブであっても、その多くの要求を処理するには時間がかかる場合があります。他のアクティビティ(たとえば、Webブラウザーのリンクをクリック、またはアプリケーションの起動)が同じブロックデバイスでI/O要求を生成する場合、それらの要求はその長いキューの後ろに移動し、しばらくの間処理されない場合があります。複数の同期要求が生成された場合(たとえば、新しく起動されたアプリケーションからのページフォールトなど)、これらの要求はそれぞれ、この長いキューを通過する必要がある場合があります。それが物事が止まるように見えるポイントです。
[...]
ほとんどのブロックドライバーは、内部的に独自のキューも保持します。これらの低レベルのキューは、リクエストがそこに到着するまでに、I/Oスケジューラーの制御の対象ではなくなるため(I/Oスケジューラーがある場合)、特に問題になる可能性があります。
これを改善するためにパッチがマージされました 2016年後半(Linux 4.10) 。このコードは、「ライトバックスロットリング」またはWBTと呼ばれます。 Webで_wbt_lat_usec
_を検索すると、これに関するいくつかの記事も見つかります。 (最初のドキュメントは_wb_lat_usec
_について書いていますが、古くなっています)。ライトバックスロットリングは、CFQまたはBFQ I/Oスケジューラでは機能しないことに注意してください。 CFQはデフォルトのI/Oスケジューラとして人気があり、Linux v4.20までのデフォルトのカーネルビルドに含まれています。 CFQはカーネルv5.0 で削除されました。
[〜#〜] ssd [〜#〜] (これはNVMeのように見えます)と " 通常のハードドライブ "。ハードドライブは、「非常にバースト性の高いIOがある、より深いキュー深度のデバイスほど悪くはありませんでした」。
キューに入れられた要求の「数千」についてはわかりませんが、少なくとも数百の要求をキューに入れることができるNVMeデバイスがあります。ほとんどのSATAハードドライブでは、32個のリクエストをキューに入れることができます(「NCQ」)。もちろん、ハードドライブは各リクエストを完了するのに時間がかかります。
「I/Oなしのダーティスロットリング」は、非常に複雑なエンジニアリングシステムです。また、時間の経過とともに調整されました。このコード内にはsomeの制限があったし、今もそうです。
LWNの記述、コード/パッチコメント、および詳細なプレゼンテーションの slides は、多数のシナリオが検討されていることを示しています。これには、悪名高い低速USBスティックv.sが含まれます。高速メインドライブ。テストケースには、「1000同時DD」(つまり、シーケンシャルライター)というフレーズが含まれています。
これまでのところ、ダーティスロットリングコード内の制限をデモンストレーションおよび再現する方法はわかりません。
ダーティスロットリングコードの外にある問題修正の説明をいくつか見ました。私が見つけた最新の修正は2014年でした-後続のセクションを参照してください。 LWNが報告しているスレッドでは、次のことを学びます。
最近のいくつかのリリースでは、このような問題は、再利用の問題が原因で発生しました。この問題は、多数のダーティ/ライトバックページが表示されてうんざりし、IOが完了するのを待ってスタックしました。
[...] systemtapスクリプトがこれらのタイプの領域をキャッチし、修正されたと思います。
Mel Gormanも said いくつかの「未解決の問題」がありました。
まだ問題があります。すべてのダーティページが低速のデバイスによってサポートされている場合、ダーティ制限により、最終的にはダーティページバランシングでストールが発生します[...]
この一節は、報告されたディスカッションスレッドで私が見つけることができる唯一のものでした。それが何を意味しているかを理解したいと思います:-(。または、それをどのように実証するか、そしてなぜそれがArtemとLinusが実行したテストで重要な問題として浮上しなかったのか。
ArtemもLinuxもシステム全体に影響を与える「USBスティックストール」を報告していませんが、これに関する報告は他にもあります。これには、最近のレポートが含まれます-直近の既知の修正のかなり後。
何が違うのかわかりません。おそらく、テスト条件が何らかの点で異なっていたのかもしれませんし、2013年以降にカーネルに新たな問題が発生しているかもしれません...
2014年1月に興味深い修正がありました(カーネルv3.14で適用)。質問では、デフォルトの制限はメモリの20%に設定されていると述べました。実際には、ダーティページキャッシュに使用できるメモリの20%に設定されています。たとえば、カーネルバッファーはTCP/IPネットワークソケットのデータを送信しました。ソケットバッファーを削除してダーティページキャッシュに置き換えることはできません:-)。
問題は、ダーティページキャッシュを優先してデータをスワップアウトできるかのように、カーネルがスワップ可能なメモリをカウントしていたことでした。これは理論的には可能ですが、カーネルはスワッピングを回避するために強くバイアスされており、代わりにページキャッシュのドロップを優先します。この問題は、何だと思いますか?遅いUSBスティックへの書き込みと、システム全体でストールが発生したことに気づいたテストによって説明されました:-)。
Reを参照してください:[パッチ0/2] mm:重いanonとダーティキャッシュによる再利用の停止を減らす
修正は、_dirty_ratio
_がファイルキャッシュの割合としてのみ扱われるようになったことです。
この問題を抱えたカーネル開発者によると、「トリガー条件はかなりありそうです-大量のバッファリングされたIOおよびスワップが構成された高メモリのメモリ使用量-そして、これは実際に発生している可能性が高いです。」したがって、これは2013年以前のsomeユーザーレポートの原因になる可能性があります。
これは別の問題でした: 巨大なページ、遅いドライブ、長い遅延 (LWN.net、2011年11月)。巨大なページに関するこの問題は、 fixed になるはずです。
また、記事の内容にかかわらず、 最新のLinux PCでは実際には巨大なページを使用していないと思います 。これはDebian 10から変更される可能性があります。ただし、Debian 10が可能な限り巨大なページの割り当てを開始しても、 が遅延を課さないことは明らかですdefrag
という別の設定を「常に」に変更します。
私はこれについては調べていませんが、興味深いものでした。
mgorman 2011 :これは、以前のようにダーティページが最後に到達するダーティページが大きな問題であった同期圧縮書き込みによるものであるため、新しいタイプのUSB関連のストールです。 LRU そして回収によって書かれている。
mgorman 2013 :その一般的な領域での作業は、ダーティページがLRUの最後に到達するなどの問題を処理しました (過剰なCPU使用)
これらが2つの異なる「LRUの終わりに到達する」問題である場合、最初の問題は非常に悪い可能性があるように聞こえます。ダーティページが最も長く使用されていないページになると、そのダーティページへの書き込みが完了するまで、メモリ割り当ての試行が遅れるようです。
それが何を意味するにせよ、彼は問題が修正されたと言います。
[1] 1つの例外:しばらくの間、Debianパッケージマネージャーdpkg
はsync()を使用してパフォーマンスを改善しました。 sync()に非常に長い時間がかかる可能性がある正確な問題のため、これは削除されました。彼らはLinuxでsync_file_range()
を使用するアプローチに切り替えました。 Ubuntuバグ#624877、コメント62 を参照してください。
この質問に答える前の試みの一部-これはほとんど冗長になるはずです:
Artemのレポートはどちらも「No-I/Oダーティスロットリング」コードと一致していると説明できます。
ダーティスロットリングコードは、各バッキングデバイスが「他のデバイスに対する現在の平均書き込み速度に関連する」「ライトバックキャッシュの合計」を公平に共有できるようにすることを目的としています。この表現は、 / sys/class/bdi / 。[2]のドキュメントにあります。
最も単純なケースでは、1つのバッキングデバイスのみが書き込まれます。その場合、デバイスの公平な配分は100%です。 write()呼び出しは、ライトバックキャッシュ全体を制御し、それを「セットポイント」に保つために抑制されます。
_dirty_background_ratio
_-バックグラウンドの書き込みを開始するポイント-と_dirty_ratio
_-ライトバックキャッシュのハード制限の中間で書き込みが抑制され始めます。デフォルトでは、これらは使用可能なメモリの10%と20%です。
たとえば、メインディスクへの書き込みだけで最大15%を書き込むことができます。 RAMの量に応じて、ギガバイトのキャッシュ書き込みが可能です。その時点で、write()呼び出しはライトバック速度に合わせて調整され始めますが、それは問題ではありません。ハングの問題は、read()およびfsync()呼び出しが原因であると予想されます。これらの呼び出しは、無関係な大量のIOの背後でスタックします。これは、「ライトバックスロットリング」コードによって対処される特定の問題です。 WBTパッチの提出の一部には問題の説明が含まれており、これによって引き起こされる恐ろしい遅延を示しています。
同様に、USBスティックへの書き込みで15%を完全に満たすことができます。 USBへの以降のwrite()は抑制されます。ただし、メインディスクはフェアシェアを使用しません。メインファイルシステムでwrite()の呼び出しを開始すると、抑制されないか、少なくとも遅延が大幅に減少します。 USBのwrite()はさらに抑制され、2人のライターのバランスが取れると思います。
ライトバックキャッシュ全体が一時的に設定値を超える可能性があります。さらに厳しい場合には、ライトバックキャッシュ全体のハード制限に達する可能性があります。ハード制限のデフォルトは、使用可能なメモリの20%です。構成オプションは_dirty_ratio
_/_dirty_bytes
_です。おそらく、デバイスの速度が低下する可能性があるため(おそらく、ランダムなI/Oパターンが原因で)、これが発生する可能性があり、ダーティスロットリングでは、速度の変化がすぐには認識されません。
[2]このドキュメントでは、特定のパーティション/ファイルシステムに使用できるライトバックキャッシュの割合を手動で制限できることを示唆していることに気付くでしょう。この設定は_/sys/class/bdi/*/max_ratio
_と呼ばれます。 「 制限したいデバイスが現在書き込まれている唯一のデバイスである場合、制限は大きな影響を与えません 」に注意してください。