NVMe とストレージ

このページの目次

同じネームスペースに対して複数のパスが存在し、コマンドの完了後も揮発性キャッシュに依存している可能性があります。NVMe を理解するには、⁠ストレージオブジェクト、キュープロトコル、データアドレス、回復状態をそれぞれ明確に位置づける必要があります。

参照目標読書位置
コントローラ、ネームスペース、SQ/CQ第1~2節
LBA、PRP と回復第3~4節
マルチパス、DM、キャッシュモード第5~8節

1. コントローラ、ネームスペース、サブシステム

コントローラはホストのアクセスインターフェースと管理機能を提供し、ネームスペースは論理ブロックアドレス空間を提供します。サブシステムは複数のコントローラを含み、共有ネームスペースを提供できます。ネームスペースは必ずしも独立したNANDチップにマッピングされるわけではなく、単なるパーティションと同等でもありません。

1つのネームスペースは異なるパスからアクセス可能であり、それが同一のストレージオブジェクトとして認識されるかどうかは、サブシステム、NSID、UUID/NGUID/EUIなどの識別子および共有属性を組み合わせる必要があり、容量や /dev 名だけで比較してはいけません。パスが消失するとデバイス番号が変化する可能性があるため、永続的な位置特定には適切な安定した識別子を使用する必要があります。

Identifyコマンドは機能やフォーマットなどの情報を返しますが、実際のI/Oキューリソースはネゴシエーションと作成が必要です。コントローラがサポートする上限、ドライバが実際に使用する数、およびワークロードの現在の並列度は、3つの異なる値です。

2. SQ/CQ:2つのプロデューサ・コンシューマプロトコル

PCIe NVMe:コマンドリングと完了リングはそれぞれ進行する ホストがSQに書き込み コマンドとDMAデータアドレス コントローラが実行 コマンドを取得しデータを転送 コントローラがCQに書き込み CID、ステータス、phaseなど SQ tail通知 ホストが完了を処理 ステータスを確認しCQ領域を返却 完了後にのみ、コマンドが参照するデータリソースを回収可能 割り込みの結合やポーリングが可能であり、CQの消費とコマンドの実行は同じ動作ではない。

PCIeパスにおいて、ホストはコマンドをサブミッションキュー(SQ)に書き込み、プロトコルに従ってコントローラに新しいtailを通知します。コントローラは実行後、コンプリーションキューエントリ(CQE)をCQに書き戻し、ホストは処理してCQ headを進めます。

1つのSQは1つのCQに関連付けられますが、プロトコルでは複数のSQが1つのCQを共有することが許可されています。Linuxドライバではペアで構成されることが多いですが、これはプロトコルで強制されている一対一の対応ではありません。MSI-Xベクトルも各キューに必ずしも一対一でバインドする必要はなく、ポーリングキューでは割り込みを使用しない可能性があります。キューの数はハードウェア、ドライバ、CPUトポロジ、リソースによって決定され、CPUごとに独占され完全にロックフリーであることが保証されるわけではありません。

CQのphaseタグは、リングスロットが現在のラウンドでコントローラによって有効な完了として書き込まれたかどうかを区別するのに役立ちます。ホストが有効な状態を検出すると、DMA/メモリの順序規則に従って他のフィールドを読み取る必要があります。コマンドは順序不同で完了する可能性があり、SQ識別子やコマンド識別子(CID)などを頼りにリクエストを特定する必要があり、最初に送信されたものが最初に終了すると仮定してはいけません。

完了キューを一杯にして1周消費し、スロット0に戻ります。図では意図的に消費済みのCIDバイトを残していますが、それが有効かどうかを決定するのは現在のheadと期待されるphaseであり、スロットが空に見えないかどうかではありません。

図を準備しています
スロットに古いバイトが残っているのに、なぜ新しい完了として扱われないのか?

ホストは現在のheadでCQEのphaseと期待されるphaseを比較し、一致して初めてこのラウンドで消費可能な完了とみなす。ロールオーバーにより期待値が変更されるため、古いバイトは新しいラウンドの完了として誤認されない。

なぜdoorbellは固定の「1回のMMIO」に書けないのか

コマンドの公開前に、関連する書き込みがデバイスによってプロトコル通りに認識可能であることを保証する必要があります。ホストは複数のSQエントリをバッチで公開してから通知したり、CQ headを更新したりします。doorbellバッファ、ポーリング、割り込み結合などのメカニズムは、アクセス頻度を変更します。

そのため、NVMeは制御オーバーヘッドを削減できますが、プラットフォーム間で統一された「I/Oごとに正確に1回のMMIO、AHCIより固定で5倍速い」という結論は存在しません。完了レイテンシは、フラッシュメモリ、キャッシュ、キュー待機、CPU、NUMA、電源状態の影響も受けます。

3. LBA、NLB、PRPの具体例

論理ブロックサイズ4096バイトを例に、LBA 256から8192バイトを読み取る場合:

フィールドまたは計算結果
起点のバイトオフセット256 × 4096 = 1 MiB
論理ブロック数8192 / 4096 = 2
コマンドNLBゼロベースカウント、1を記入

コマンドの単位を正しく解釈するには、まずネームスペースのフォーマットを確定させる必要があります。

これはLinuxブロック層の512バイトセクター単位とは異なり、ドライバは変換を行う必要があります。実際の struct nvme_command には異なるコマンドフォーマットの共用体が含まれており、フィールドはすべてのコマンドで共通の平坦なメンバの列ではありません。マルチバイトフィールドはプロトコルに従ってリトルエンディエン符号化されます。

PRPはコントローラがアクセス可能なデータアドレスを記述する

コントローラのページサイズは4096バイト、開始オフセットは1024、総長さは8192であり、3つのページが必要です:

データセグメント配置可能なバイト数
第1ページの残り部分4096 − 1024 = 3072
第2ページ4096
第3ページの残りデータ1024

したがって、第1ページの後にさらに2つのページが必要であり、その後でPRP2の意味を判断できます。

  • PRP1は第1セグメントの起点を指し、対応するページ内のオフセットを許可します。
  • 残りのデータが1ページだけで済む場合、PRP2はそのデータページを直接指すことができます。
  • この例では残りを2ページ必要とするため、PRP2はPRPリストを指し、リストによって後続のページアドレスが与えられます。

PRPリストは「PRP2は常に2番目のデータポインタ」という意味ではなく、リストがページを跨ぐ場合、リンクルールがあります。アドレスはDMA APIによって確立され、名前にPhysicalが含まれているからといって、CPU仮想アドレスや変換されていない物理アドレスを直接記入できるわけではありません。

SGLは型や長さなどの情報を含む記述子を使用し、サポートされている機能はコマンドセット、コントローラ、トランスポートによって異なります。NVMe/RDMA、NVMe/TCPのデータ転送は、PCIeホストメモリのPRPメカニズムをそのまま適用することはできません。参照エントリ:NVM Express 仕様およびカーネル include/linux/nvme.h。

4. Linuxでの送信と回復パス

drivers/nvme/host/core.c は共有プロトコルとコントローラ/ネームスペースのライフサイクルを担当し、pci.c はPCIeトランスポートを処理し、tcp.c、rdma.c、fc.c などは各自のトランスポートを処理し、fabrics.c はfabricsの共通部分を提供します。

PCIeの初期化では通常、デバイスと管理キューを有効にした後、機能の取得、リソースのネゴシエーション、I/Oキューの作成、ネームスペースのスキャンが行われます。プローブと回復には非同期ワークが含まれており、特定バージョンの関数名リストを永遠に同期実行される固定順序と見なしてはいけません。

リクエストを送信する際、ドライバはコマンドの設定、データのマップ、リソース失敗の処理を行い、コマンドをコントローラに公開します。キューのロールオーバーにおいて、index & (depth - 1) を無条件に使用してはいけません:このビット演算は深さが2のべき乗の場合にのみ成立します。

タイムアウトはホストが完了を確認していないことを示すだけで、デバイスが書き込みを実行していないことを証明するものではありません。ドライバはステータスに基づいてabort、リセット、再接続、または失敗処理を実施し、古いリクエストと遅延した完了を処理します。上位層は「再試行が成功した」ことから、古い副作用が完全に発生しなかったと推論してはいけません。完了においても、通常のライトキャッシュ、Flush、FUAの永続化セマンティクスを区別する必要があります。

5. ネイティブマルチパスとANA

LinuxのネイティブNVMeマルチパスは、識別子と設定の条件を満たす場合、複数のコントローラのネームスペースパスを1つの論理アクセスオブジェクトに集約します。ANAはパスのアクセス状態(例:最適化済み、非最適化)を記述し、ホストはこれとI/Oポリシーに基づいてパスを選択します。

NUMA、ラウンドロビン、キュー深度などのポリシーは、それらをサポートするバージョンにおいてそれぞれ用途があり、デフォルトポリシーをラウンドロビンに固定してはいけません。実際の状態は実行中のシステムから読み取る必要があります。パス選択はI/Oエレベータの別名ではありません:前者はアクセスパスを選択し、後者はキュー内のリクエストを配置します。

マルチパスはパスの冗長性を高めますが、データのコピー、バックアップ、または独立したディスク間での複製を自動的には提供しません。障害回復中はリクエストがキューイングされるか失敗する可能性があり、レイテンシはコントローラと接続の回復ポリシーの影響を受けます。NVMe multipath を参照してください。

NVMe/TCP、RDMA、FCは、NVMeアクセスをそれぞれのトランスポートに拡張します。ネットワークの輻輳、認証/暗号化設定、再接続、ターゲットのバックエンドは、パフォーマンスと信頼性を変更するため、RDMAに条件を無視した固定のマイクロ秒レイテンシを記述してはいけません。

6. SCSI と device-mapper の位置づけ

SCSIの上位ドライバにはディスク(sd)、光学ドライブ(sr)、テープ(st)が含まれます。中層は一般的なコマンド管理とエラー回復を処理し、下位ドライバはHBAまたは特定のトランスポートに接続します。SATAもlibataなどのパスを経由してLinuxではSCSIディスクとして表示される可能性があるため、/dev/sdX だけでは物理バスを名前で判断できません。

device-mapperはターゲットに基づいて論理ブロックアドレスを下位デバイスにマッピングし、複数の層を組み合わせることができます:

ターゲット/メカニズム役割保証されないこと
linear連結またはオフセットマッピング冗長性の自動追加なし
cryptブロック暗号化LUKSフォーマットの個別解析なし、改ざんのすべてをデフォルトで認証しない
thin / thin-pool必要に応じた割り当てと共有スナップショット論理容量がすでに確保された物理空間と等しいわけではない
cache高速デバイスによる低速デバイスのブロックキャッシュダーティデータは依然としてキャッシュデバイスの生存に依存する
writecache特定の永続メディア上のライトキャッシュ汎用ライトスルーキャッシュの名称変更ではない
multipath複数のパスを集約RAIDコピーと等しくない
raidDM内で対応するRAIDメカニズムを使用これに基づいてMD RAIDの開発が停止したと主張できない

LVMはユーザー空間のボリューム管理システムであり、複数のDMターゲットを構成可能であり、「dm-linearコマンドのラッパー」ではありません。MD、DM RAID、LVMのインターフェースと管理関係は明確に区別する必要があります。

Thin pool がデータとメタデータの両方を監視する理由

thinボリュームはまず論理容量を宣言し、実際の書き込み時にデータブロックを割り当てます。スナップショットはブロックを共有し、後続の書き込みで割り当てとマッピングの更新がトリガーされる可能性があります。データプールが満杯になることとメタデータプールが満杯になることは異なる障害であり、キューイング、読み込み専用、またはエラーパスに入る可能性があり、具体的な動作は設定と状態によって決まります。

スナップショットは依然として元のプール内のデータとメタデータに依存しており、独立したバックアップではありません。ファイルの削除が即座にプールのスペースを回収する保証はなく、discard、スナップショット参照、ターゲットのサポート状況によっても異なります。thin provisioning を参照してください。

7. キャッシュモードが故障時にデータがどこにあるか

キャッシュモード確認時に注目すべきデータ位置
writeback最新バージョンはキャッシュデバイス上にのみ存在し、バックエンドは依然として古い状態
writethroughモードに従ってバックエンド書き込み完了後に確認
writearoundキャッシュをバイパスして書き込み、無効化ルールは実装による

モード変更時の障害回復の根拠は、正常時の速度だけを比較してはいけません。

「SSDなら安全、HDDなら危険」というわけではなく、ダーティデータ、マッピングメタデータ、flush規約の永続性を確定させる必要があります。電力損失保護付きのキャッシュデバイスはいくつかの停電リスクを緩和できますが、デバイス自体の破損により、まだ書き戻されていないデータが失われる可能性があります。

dm-cache、dm-writecache、bcacheは異なる実装であり、管理インターフェースや移行/削除フローは共通ではありません。bcacheはbcachefsの略称ではありません。dm-cache、bcache を参照してください。

8. 読み取り専用観察と位置特定

lsblk -o NAME,TYPE,SIZE,LOG-SEC,PHY-SEC,PKNAME,MOUNTPOINTS

nvme-cliをインストールした後、nvme list、nvme list-subsys でオブジェクトとパスを確認でき、nvme id-ctrl / id-ns で指定されたオブジェクトの機能を確認できます。SMARTのpercentage_usedは推定された耐久消耗であり、「残り寿命のカウントダウン」ではありません。エラーカウントは変化傾向と具体的なエラー解釈と組み合わせて確認する必要があります。

アプリケーションからI/Oエラーが見えた場合、論理ボリューム、DM/RAID、ネームスペース/パス、コントローラ、下位デバイスの順で確認します。複数のスタック層にわたる同じデータの統計を物理スループットとして重複して累積しないでください。ブロック層の測定と完了セマンティクスについてはブロックデバイス層を、キーの階層についてはCrypto API とストレージ暗号化を参照してください。