NVMe ドライバの HMB (Host memory buffer) 初期化処理のバグフィックス

私の関わっている業務では Linux kernel をいじることがあるのですが、その中で Linux kernel のドライバのバグを報告して修正してもらった経験があったので、その内容や経緯を紹介したいと思います。

NVMe とは何か HMB とは何か

NVMe HMB機能を使ってみた」が参考になると思います。

NVMe ドライバが HMB 機能をサポートした直後の出来事

2017 年 9 月にリリースされた Linux kernel 4.13 において (4.x リリースは 2, 3 ヶ月ごとにリリースされ 2018 年 8 月の時点では 4.18 が最新リリースとなっている) NVMe ドライバに HMB 機能のサポートが追加されました。東芝メモリ製の HMB をサポートした NVMe デバイスを動作検証できる機会があり、早速試したところ NVMe ドライバが HMB 初期化処理に失敗して、システムが続行不能な状態に陥ってしまいました。

HMB 初期化処理とはどのようなものか

HMB 初期化処理とは NVMe デバイスがアクセス可能なホストのメモリ領域を割り当てて、その領域を NVMe デバイスに活用してもらうよう通知する処理のことで、メモリ割り当ての部分は次のように行われます。

  1. 対象の NVMe デバイスに問い合わせて取得した HMB の推奨メモリサイズ (Host Memory Buffer Preferred Size) と最小メモリサイズ (Host Memory Buffer Minimum Size) を HMB のために割り当てる目標メモリサイズの上限と下限に設定します。
  2. 推奨メモリサイズがゼロの場合は、そのデバイスは HMB をサポートしていないことを意味するので HMB の有効化は行いません。
  3. 上限メモリサイズを NVMe ドライバのモジュールパラメータ max_host_mem_size_mb の設定値で制限します。ここで上限メモリサイズが下限メモリサイズを下回るような値が指定された場合は HMB の有効化は行いません。(HMB をサポートしているデバイスだが、あえて HMB 無効にして使う場合に max_host_mem_size_mb=0 にしたりする)
  4. 適当なチャンクサイズ (具体的な値は後述) で DMA 転送可能なメモリ領域の割り当てを繰り返し、合計メモリサイズが HMB の上限メモリサイズに達するまで行います。
  5. もし途中で、メモリ不足で割り当てることができなくなった場合は、それまでに割り当てることができた合計メモリサイズが HMB の最小メモリサイズを超えていれば、それでよしとして HMB のためのメモリとして使用しますが、達していなければ、それまで割り当てたメモリをすべて開放し、チャンクサイズを半分にして再挑戦します。ただし、チャンクサイズを十分小さくしていっても HMB 最小メモリサイズ以上のメモリを割り当てることができなければ HMB の有効化を諦めます。

不具合の修正

上述した HMB のためのメモリ割り当てを試行する際の一番最初に試すチャンクサイズは Linux kernel 4.13 がリリースされた段階では、ページアロケータが割り当て可能な最大の連続メモリサイズの二倍になっていました。 そのため初回の HMB メモリ割り当ての試みは一つのチャンクも割り当てられずに失敗し (DMA Contiguous Memory Allocator を有効にしていれば成功するかもしれませんが) チャンクサイズを半分のページアロケータの割り当て可能な最大連続サイズにして再挑戦することになります。ところが、この再挑戦する部分に不具合があったため、システムが続行不能な状態に陥っていることが分かりました。

Linux の NVMe ドライバの開発者のための linux-nvme メーリングリストに、上述の再挑戦する部分のコードの不具合の修正するパッチと、一番最初に試すチャンクサイズをページアロケータが割り当て可能な最大の連続メモリサイズの二倍ではなく、最大サイズそのものに変更する提案を送りました。

[PATCH 0/2] nvme-pci: fix rety handling of host memory buffer allocation

これに対して、すぐに NVMe ドライバに HMB サポートを追加した開発者の Christoph Hellwig 氏から、返事とともに不具合のあった原因のコード周辺の見通しを良くしつつ問題も修正するという、より良いパッチが提案されたので、私の環境でも正常動作することを確認し、そのことを伝えました。もうひとつの提案である最初に試すチャンクサイズの変更については同意が得られました。そして、まもなく Linux kernel にマージされました。

stable アップデートへのバックポート

影響を受けるデバイスを使用している人にとっては 4.13 リリース以前に動作していたものが 4.13 で動作しなくなったわけですから深刻な問題ですが、開発途中で安定化の途中である “rc” リリースを使うか、次のメジャーリリース (この場合は 4.14) を待たなければならないかというと、そういうことはありません。人々に影響を及ぼしそうなバグフィックスは stable アップデートという形で、バックポートされることがあり、この修正も 4.13 のリリースに対する stable アップデートである 4.13.5 に取り込まれました。

まとめ

NVMe ドライバに HMB 機能がサポートされた直後にあった不具合について紹介しました。その不具合を修正パッチとともに linux-nvme メーリングリストに報告したところ HMB 機能を追加した開発者によって、私の提案したものよりも良い形で不具合が修正されました。 Linux kernel のバージョンや開発プロセスについて少し触れましたが詳細はカーネルソースに含まれる文書 Documentation/process/2.Process.rst に記述されています。

Tags:,

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

This site uses Akismet to reduce spam. Learn how your comment data is processed.