">

ほそぼそストレージ研究所

LinuxNVMe操作アプリケーションを作ってみた-5-ErrorInfo

投稿日 2026.04.23 カテゴリ nvme レベル 中級者
nvme linux implementation

はじめに

前回はSMART / Health Information Log を読めるようにしました。次に着手するのは、Error Information Log です。

この log page は、温度や使用率のような健康状態を見るものではなく、controller が保持している error 情報を並べたものです。

今回ここで整理したかったのは、主に次の 3 点でした。

  • Error Information Log はどういうデータフォーマットなのか
  • ELPE がなぜ必要になるのか

特に ELPE は、実装してみると必要だと分かるのですが、初期段階では少し分かりにくかった部分です。

理論: Error Information Log のデータ・フォーマット

Error Information Log は、SMART Log のように 1 ページを丸ごとひとつの構造体として見るというより、64 byte の entry が並んだ配列として見る方が分かりやすいです。
全体のデータ・フォーマットは以下のとおりです。

[07:00] Error Count                           (ECNT) 一意なエラー識別子
[09:08] Submission Queue ID                   (SQID) 該当SQ ID
[11:10] Command ID                            (CID)  該当Command ID
[13:12] Status Info                           (STS)  完了ステータス
[15:14] Parameter Error Location              (PEL) パラメータ異常位置
[23:16] Logical Block address                 (LBA) 異常に関する先頭LBA
[27:24] Namespace Identifier                  (NSID) 関係するNamespace
[28]    Vendor Specific Information Available (VSIA)
[29]    Transport Type
[30]    Command Set Indicator                 (CSI)
[31]    Opcode                                (OPC) 関係するコマンド opcode
[39:32] Command Specific Information          (CSINFO)
[41:40] Transport Type Specific Information   (TTSI)
[62:42] reserved
[63]    Log Page Version                      (LPVER)

これが読めると、「何か error があった」というだけでなく、

  • どの command で起きたか
  • どの queue / namespace に関係するか
  • completion status は何か

を追えるようになります。

実際の出力はこうなる

mock では、次のような形で出力していました。

 ===  Error Log ===
 ---  count     0 ---
Error Count                         : 1
Submission Queue ID                 : 1
Command ID                          : 291
Status Info                         : 2
Parameter Error Location            : 16
Logical Block Address               : 4096
Namespace Identifier                : 1
Vendor Specific Info Available      : 0x00
Transport Type                      : 0x00
Command Set indicator               : 0x00
Opcode                              : 0x02
Command Specific Information        : 0
Transport Type Specific Information : 0
Log Page Version                    : 0x01

real device 側では、有効な error が無い場合に

 ===  Error Log ===
 No Error Log in Nvme

と出るようにしています。

ここで分かるように、Error Information Log は「単一の status を返す」のではなく、entry を順に見ていく log です。

count はページ数ではなく entry 数

今回の実装では、引数に--countオプションを用意しています。これがエントリーをいくつ取るかを意味します。

1 entry は 64 byte なので、

  • count = 1 なら 64 byte
  • count = 2 なら 128 byte

の buffer を用意して Get Log Page を投げることになります。

この時点で、SMART Log とはかなり感覚が違います。

  • SMART Log
    512 byte の 1 page をひとまとまりで読む
  • Error Information Log
    64 byte entry を count 個ぶん読む

という差があるからです。

そのため実装側でも、Error Information Logstd::vector<LogErrorInfo> で受ける形にしました。

ELPE が必要になる

ここで必要になったのが Identify ControllerELPE です。

ELPEError Log Page Entries を表す field で、controller が何件の error entry を保持できるかを示します。

ただし、その値は 0-based です。しかも field 自体は 8bit です。

つまり、

  • ELPE = 0x00 なら最大 1 entry
  • ELPE = 0x0f なら最大 16 entry
  • ELPE = 0x3f なら最大 64 entry
  • ELPE = 0xff なら最大 256 entry
  • 実際の最大件数は常に ELPE + 1

という解釈になります。

実際に自分の手元の device では ELPE = 0x0f でした。つまり最大 16 entry まで保持できることになります。
一方で mock では、少し大きめの値として 0x3f を入れていました。こちらは最大 64 entry です。

8bit なので理論上は最大 256 entry まで持てますが、そこまで error が積み上がる前に別の問題として気付くことの方が多そうです。実際の運用では、最大値そのものよりも「ELPE + 1 で上限が決まる」という考え方の方が重要ですね。

このことが分かると、--count は好きな値をそのまま受け取ればよいわけではなく、

  • controller が保持できる最大件数を超えていないか

を見ておく必要があります。

ELPE を読むために Identify Controller も更新した

最初の Identify Controller 実装では、

  • VID
  • SSVID
  • serial
  • model
  • firmware

のような、個体識別に必要な情報を優先して読んでいました。

Error Information Log を実装する段階で、そこへ ELPE を追加しました。

ここでいう ELPE は、Error Log Page Entries の略です。Identify Controller の中にあるこの 1 byte の field が、Error Information Log の最大 entry 数を決めています。

Identify Controllerで必要になる情報は、今後も必要になったタイミングで追加していきます。

Error Count == 0 は invalid entry とみなす

もうひとつ大きかったのが、Error Count == 0 の扱いです。

Error Information Log では、読み出した entry の先頭 8 byte に Error Count が入っています。
NVMe の仕様上、この値が 0 の時は invalid entry です。

実装としては、

  • 64 byte ごとに LogErrorInfo を組み立てる
  • 最初の Error Count を見る
  • 0 なら vector に積まない

という流れです。

このおかげで、

  • count を多めに要求したが実際の error は少ない
  • そもそも error が無い

という時に、無効な entry までそのまま表示せずに済みます。

No Error Log in Nvme という表示も、この判断とつながっています。

実装の流れ

今回の実装でやっていること自体は、流れにするとかなりシンプルです。

  1. Identify Controller から ELPE を読む
  2. ELPE + 1 を最大 entry 数として扱う
  3. count がそれを超えるなら clamp する
  4. 64 * count byte の buffer を用意する
  5. Get Log Page を投げる
  6. 64 byte ごとに entry を decode する
  7. Error Count == 0 の entry は捨てる
  8. vector に積んで表示する

SMART Log に比べると、decode する項目数はそこまで多くありません。
その代わり、

  • entry 単位で読むこと
  • count をどう解釈するか
  • ELPE で上限を知ること
  • Error Count == 0 を invalid とみなすこと

が実装上では重要です。

まとめ

Error Information Log を実装して分かったのは、ここで重要なのは field 数の多さではなく、entry の並び方と件数の扱い だということでした。

今回整理したポイントは次の通りです。

  • Error Information Log は 64 byte entry の配列として読む
  • count はページ数ではなく entry 数
  • 最大 entry 数は ELPE + 1
  • ELPE を読むために Identify Controller 側の実装も更新する
  • Error Count == 0 の entry は invalid とみなす

SMART Log では単位の解釈が中心でしたが、Error Information Log ではフォーマットと件数の考え方を理解することが中心でした。