NVMe Revision 1.4: New commands and features (except for NVM Sets and its related features)

# はじめに
　前回投稿の記事から、2019/6/10にリリースされたNVM Express（以降NVMeと表記します）の最新仕様であるリビジョン1.4<sup>[1]</sup>について、新機能や注目（注意）が必要な変更点、をまとめています。

1. NVM Setとその関連機能 → [2019/8/28投稿の記事](https://qiita.com/ken-yossy/items/495cb481e254eb306c55)
2. NVMeリビジョン1.4の新コマンドと新機能（NVM Setとその関連機能を除く）
3. 既存機能に対する変更点のうち注意が必要なもの

　この記事では、NVMeリビジョン1.4の新コマンドと新機能（NVM Setとその関連機能を除く）をまとめます。
　[NVM ExpressのWebサイト](https://nvmexpress.org/)にアップロードされている、Flash Memory Summit 2019での講演資料も参考にしてください<sup>※1</sup>。NVMeリビジョン1.4の注目技術をまとめた資料<sup>[2]</sup>もあります。

※1："Resources"→"Documents and Videos"→"Presentations"と辿ったページにある"FMS19_"から始まるタイトルのファイル名群。もしくは、"Events"→"Flash Memory Summit"と辿ったページのFMS 2019に関する記事の部分。

# サマリ
* 新しいコマンドは`Get LBA Status`と`Verify`の2つ
* その他の新機能は以下の6つ
    * Persistent Event Log
    * Persistent Memory Region
    * Namespace Write Protection
    * Asymmetric Namespace Access
    * SQ Associations
    * UUIDs for Vendor Specific Information
* これらのコマンドや機能は、現状ではデータセンターやエンタープライズ環境での使用を想定している模様

# 新コマンド
　新コマンドは`Get LBA Status`コマンドと`Verify`コマンドの2つです。

## Get LBA Statusコマンド
　`Get LBA Status`コマンドとは、ホストが指定したLBA範囲について、ドライブが「潜在的にデータ回復不能(Potentially Unrecoverable)な」セクタのLBAを返すコマンドです。この`Get LBA Status`コマンドはAdminコマンドです。

　セクタデータが「潜在的にデータ回復不能である」とは、セクタのデータをメディアから読み出すコマンドを発行した場合に、そのコマンドが"Unrecovered Read Error"というステータスで失敗することを意味します。良く「アンコレクタブル(Uncorrectable)」と呼ばれるエラーです。

　読み出し時にアンコレクタブルとなるセクタは、読み出し時に様々な誤り訂正処理が行われるため、読み出し処理に時間がかかることが予想されます。これはシステムの性能低下につながります。
　そこでホストは、この`Get LBA Status`コマンドで読み出し時にアンコレクタブルとなるセクタを予め知っておくことにより、そのセクタに対する読み出し要求をそのドライブに発行するのをやめたり、ゼロデータで上書きするなど、システムの性能低下を防止する対策を打つことができます。

　エンタープライズ向けSSDでは、ある頻度で、ドライブに記録されている全有効データを対象に、正しく読み出せるかどうかチェックする、といった機能を備えた製品もあります。
　このような機能を持つ製品であれば、一定間隔でこの`Get LBA Status`コマンドを発行することで、読み出せなくなってしまったデータのLBAを知ることができます（図1）。

![Get LBA Statusコマンドの使用例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/b1fae681-a41f-23db-9480-36f0c165152d.png "Get LBA Statusコマンドの使用例")
図1：Get LBA Statusコマンドの使用例

　SMART情報や自己診断機能(Device Self-test)の結果およびエラー情報(Error Information)といった`Get Log Page`コマンドで取得できる情報を総合することで同等の情報を得ることができますが、この`Get LBA Status`コマンドを使えば一発で上記の情報を取得できます。
　このことが仕様策定の動機だったと思われます。

　なお、ホストはコントローラに対して、報告内容を、コントローラが既知の回復不能セクタのみとするのか、それとも、指定したLBA領域のデータを検査し、その結果回復不能と判明したセクタも含めるのかを、コマンド発行時に指定することが可能です。

## Verifyコマンド
　`Verify`コマンドは、ドライブが保持しているデータの完全性(integrity)を検査するコマンドです。`Verify`コマンドはNVMコマンドセットのコマンドです。

　類似のコマンドには`Compare`コマンドがありますが、`Compare`コマンドはホストが指定したデータ＋メタデータとドライブが保持するデータ＋メタデータの比較を行うコマンドであるのに対し、`Verify`コマンドはドライブが保持するデータ＋メタデータのみで完全性検査を行うという点が異なります。

![NVMe仕様におけるProtection Information (PI)（520バイトセクタの例）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/3f6c9c6c-9575-e279-491d-442bb6c098d9.png "NVMe仕様におけるProtection Information (PI)（520バイトセクタの例）")
図2：NVMe仕様におけるProtection Information (PI)（520バイトセクタの例）

　NVMe仕様における、各セクタデータに付随する保護情報(Protection Information; PI)は、図2のようなものです。これは、SCSIのProtection Informationと同じ仕様です。なお図2は、512バイトのユーザデータに8バイトの保護情報が付与される520バイトセクタの例です。

　図2の通り、保護情報は3つのデータから構成されます。このうち、`Guard`フィールドはユーザデータ（図2の例では512バイト）から計算したCRC (CRC16)であり、`Reference Tag`フィールドはこのセクタデータに対応するLogical Block Address (LBA)です。

　ドライブは、`Verify`コマンドの処理で以下のチェックを行うことが考えられます。もちろん、この他にドライブ独自のチェック項目を追加することもあり得ます。

1. ユーザデータとPIをメディア（例：NANDフラッシュメモリ）から読み出せること（誤り訂正できること）
2. ユーザデータ（図2の例では512バイト）から計算したCRC (CRC16)が、PIの`Guard`フィールドに格納されている値と一致すること
3. ドライブが管理しているこのセクタデータに対応するLBAと、`Reference Tag`フィールドに格納されているLBAが一致すること

　なお、この8バイトの保護情報を付与するのは**ホストであってドライブ(SSD)ではない**ことに注意です。

![Protection Informationに対応したSSDの製品仕様書（Intel SSD DC3608の製品仕様[3]より抜粋）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/03fe4eca-d5b7-e54f-4839-2a4a4bd0ec63.png)
図3：Protection Informationに対応したSSDの製品仕様書（Intel SSD DC3608の製品仕様[3]より抜粋、赤枠は後から付与したもの）

　SSDの仕様書を見ると、例えば図3のように、512バイトや4096バイト(4KiB)以外のセクタサイズが記載されていることがあります。このことが、Protection Information（"T10 DIF"のこと）をサポートしているかどうかを判別する、最も簡単な方法です。図3の"Sector Size"には「520バイト」が記載されていますので、図2の形式をサポートしていると考えられます。

　上記の通り、`Verify`コマンドはドライブが保持するデータ＋メタデータのみで完全性検査を行うコマンドですが、保護情報(PI)付きでデータが保存されていなくても、ドライブは、極論するとメディアからデータを読み出してエラー訂正によって訂正可能であること、のチェックのみでも構わない仕様となっています。

　`Compare`コマンドと比較して、`Verify`コマンドは比較するデータが不要で、またデータ転送を伴わないため、使いやすいコマンドではありますが、保護情報付きでデータが記録されていない場合は単にデータが読み出せるかどうかの検査にしかなりません。

　ドライブに保護情報付きでデータを記録するのは、現状ではいわゆるエンタープライズやデータセンター環境ですから、まずはそのようなユースケースで使われることになるでしょう。

# その他の新機能
## Persistent Event Log
　Persistent Event Logとは、コントローラが記録したデバイスで発生した様々なイベントの記録を取得するための、新しいログページです。

　このPersistent Event Logの内容は、電源断やコントローラリセットを経ても内容が保持されること、不正な電源断(power failure)の場合でも失う情報は最小限であること（努力目標）、が求められます。そのうえ、デバイスは、記録可能なイベント数として、デバイスの寿命期間中に必要と考えられるだけのイベント数をサポートすることも求められています。ただし、デバイスが予め決めた頻度以上で同一イベントが生起した場合は、以降のイベントを記録しなくても良い、とも記載されています。

　このPersistent Event Logに記録されるイベントの種類(type)は以下の表の通りです。どこかで見たような項目（単語）も含まれていますね……

表1：Persistent Event Logに記録されるイベントの種類(type)
![persistent_event_log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/5a7f7a5b-72c7-a5c9-78ac-2f6a6b3ef17f.png "Persistent Event Logに記録されるイベントの種類(type)") 

　同様の機能（ログ）には、Error InformationとTelemetryが存在します。Error Informationはあくまでエラー情報の記録であってかつ電源断を経るとクリアされること、Telemetryは記録される内容が任意の内容であることに対し、このPersistent Event Logは、記録内容がエラー以外のイベントを含むこと、記録内容が電源断を経ても保持されること、および記録内容（イベント）が予め定義されていること、という点で異なります。

　なお、記録されるデータのサイズはイベント毎に異なります。例えば、Thermal Excursionというデータのサイズが2バイトなのに対して、SMART / Health Informationのデータサイズは512バイトです。

　同じような情報（ログ）が別のフォーマットで分散しているのに比べれば、統一された方法で全ての情報を取得できるほうが望ましいことは確かです。しかし、このリビジョン1.4の時点での仕様では、ログの取得方法がちょっと煩雑すぎるように見えます。今後もっと使いやすい方法に整備されていけば、使われる場面も多くなるのかもしれません。

## Persistent Memory Region
　このオプション機能は、Persistent Memory Region (PMR)と呼ばれる、PCI Express (PCIe)バス上のアドレス空間にマッピングされたホストとデバイスの双方がアクセス可能なメモリ領域を作成・制御する機能です。

　PMRの一番の特徴は、PMRに書き込んだデータは、電源断(power cycle)やコントローラのリセット、およびPMRの有効・無効切り替えを経ても、書き込まれたデータが保持されることです。つまり、Logical Block Address (LBA)でアクセスする記憶領域以外に不揮発な記憶領域を提供する機能ということになります。しかも、アクセス方法はブロックアクセスではなくメモリアクセスが想定されています。

![Persistent Memory Region (PMR)イメージ図
](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/7842c27e-9833-e6e3-bda0-c31defc620e9.png "Persistent Memory Region (PMR)イメージ図
")
図4：Persistent Memory Region (PMR)イメージ図

　さらに、PMRは性能に関する要求がとても高いです。例えば、定常状態(sustained)での書き込みバンド幅が、PCIeの書き込みバンド幅よりも十分に広いことが求められています。もしそうでない場合、弾力的(elastic)なバッファを持つなどしてそのバンド幅のギャップを埋めることが記載されています。
　今年（2019年）7月にAMDが第3世代Ryzenを発表したことで本格的にPCIe Gen4時代が始まりましたが、例えばPCIe Gen4 x3のバンド幅（片方向64GT/s）を満たすのは、少なくともNANDフラッシュメモリでは大変です。そもそも、NANDフラッシュメモリはPMRが指向するメモリアクセスには向きませんし。

　NVMe仕様書にはPMRの具体的な実現方法は記載されていませんが、上記のことから、PMRは例えばIntelのOptaneメモリのようないわゆるStorage Class Memoryで実現することを暗に想定しているのではないか、と考えることができます。
　バッテリーによるバックアップを行うDRAMを搭載しているドライブが、そのDRAM（の一部）をこのPMRに割り当てても実現できるとは思いますが、いずれにしても高価なドライブになりそうです。

　PMRの設定項目には、定常状態での書き込みバンド幅や、上記「弾力的なバッファ」のサイズ、さらにはPMRの状態や、PMRを有効にしてからホストが待つべき時間まで、細かい設定項目が存在します。このため、PMRを効果的に使用するには、デバイス（ドライブ）側はもちろんホスト（OSやライブラリ）側の対応も欠かせません。

　以上のことから、PMRは、現時点ではハイエンドのエンタープライズSSD向け機能、と考えられます。

## Namespace Write Protection
　このオプション機能は、文字通り、Namespaceの書き込み許可に関する制御を実現する機能です。

　Namespaceの書き込み可能および禁止に関する状態は4つ定義されています。以下は、NVMe仕様書に記載の図を引用したものです。

![Namespace Write Protectionに関する状態遷移図（NVMe仕様書より引用）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/17e5d526-6a82-cd5f-8ee0-6f70ca828c98.png "Namespace Write Protectionに関する状態遷移図（NVMe仕様書より引用）")
図5：Namespace Write Protectionに関する状態遷移図（NVMe仕様書より引用）

　図5の4つの状態のうち、特徴的な状態は"Write Protect Until Power Cycle"と"Permanent Write Protect"の2つでしょうか。

　"Write Protect Until Power Cycle"状態とは、「電源断（パワーサイクル）を経るとWrite Protectが外れる」という状態です。また、"Permanent Write Protect"状態とは、一旦遷移すると他の状態に遷移できない（「書き込み禁止」が外れない）状態です。特に、"Permanent Write Protect"状態は非常に「強い」状態となります。

　このため、"Write Protect Until Power Cycle"状態、および"Permanent Write Protect"状態への遷移遷移には、特別な認証(Authentication)を必要とします。
　この「特別な認証」は、Replay Protected Memory Block (RPMB)という機能を使用して実現されます。

　Write ProtectされたNamespaceに対しては、ほとんどすべてのコマンドが失敗します（ステータスコードも決まっています）ので、この機能を使う際には注意が必要です。

　なお、Trusted Computing Group (TCG)など、他の機能でもこの機能と同様の「書き込み禁止」を実現することができますが、それらの関連性は「仕様の範囲外」としています。

## Asymmetric Namespace Access
　複数の物理ポートを持つPCIe接続のSSDや、NVMe over Fabrics (NVMeoF)接続のSSDもしくはストレージシステムにおいて、NVMe仕様で定義する「コントローラ」が複数存在してかつそれら複数のコントローラの間でNamespaceを共有する（複数のコントローラから同一のNamespaceにアクセスする）場合、それら複数のコントローラの間では、共有しているNamespaceに対するアクセス性能が異なる可能性があります。

　そのように、あるNamespaceへのアクセスに性能が異なる複数のパスが存在する状態のことを、「性能が非対称である」ことから"Asymmetric Namespace Access"と呼びます。このオプション機能は、ホストやストレージシステムの管理システムが、"Asymmetric Namespace Access"の状態を把握するためのオプション機能です。

　"Asymmetric Namespace Access"のイメージについては、NVMe仕様書の図がわかりやすいです。

![Asymmetric Namespace AccessとANA Groupのイメージ図（NVMe仕様書より引用）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/e13484f4-83f9-ede7-3e42-99ce2a789dbd.png "Asymmetric Namespace AccessとANA Groupのイメージ図（NVMe仕様書より引用）")
図6：Asymmetric Namespace AccessとANA Groupのイメージ図（NVMe仕様書より引用）

　図6では、Namespace (NS) Aがコントローラ1のプライベートNamespace、NS BとNS Dがコントローラ1～3で共有されたNamespace、NS Cがコントローラ2と3で共有されたNamespace、となっています。そして、NS AとCは単独で、NS BとDは2つのNamespaceで、Asymmetric Namespace Access Group (ANA Group)を構成しています。

　これらのストレージを管理するシステムは、例えば「NS Bにアクセスできる経路（コントローラ）はいくつあって、NS Bにアクセスするにはどのコントローラにコマンドを発行するのが良いのか？」という情報が必要になります。

　上記の情報をホストに返す機能が"ANA Reporting"という機能です。つまり、各コントローラは、自身を経由した各Namespace（実際には各ANA Group）へのアクセスについて、「最適化されている」「最適化されていない」などの情報をホストに提示します。

　コントローラがホストに提供する、コントローラからANA Groupへのアクセスについての状態は、以下の5つです。

1. **ANA Optimized**：このANA Groupへのアクセスは「最適化された状態」である
2. **ANA Non-Optimized**：このANA Groupへのアクセスは「最適化されていない状態」である
3. **ANA Inaccessible**：このANA Groupへのアクセスは「（一時的に）できない状態」である
4. **ANA Persistent Loss**：このANA Groupへのアクセスは「失われた状態」である
5. **ANA Change**：このANA Groupへのアクセスは「状態変化中」である

　以上のことから、この機能は、これまでのフォームファクタとは一線を画すような超大規模ドライブ、もしくは複数のドライブを束ねたストレージシステムを構成するコントローラなどで必要になる機能と考えられます。少なくとも現時点では、搭載ドライブ数が1～2程度のクライアントPCで使うことはないでしょう。

　Flash Memory Summit 2019でのNVMe over Fabrics (NVMeoF)に関する講演資料<sup>[4]</sup>の中に、この機能に関する説明がありましたので、あわせて参照してください。

## SQ Associations
　このオプション機能は、Predictable Latency Modeを使用している環境において、特定のI/O Submission Queueを特定のNVM Setに関連付ける、という機能です。

　この機能の目的は、この関連付けをホストからコントローラに通知することで、Predictable Latency Modeにおける性能の保証をコントローラが行いやすくするため、と記載されています。

　確かに、DTWIN状態（アクセス性能が決定的な状態）のNVM Set（に含まれるNamespace）に対するコマンドは、NDWIN状態（アクセス性能が非決定的な状態）のNVM Setに対するコマンドよりも優先したほうが良さそうです。この機能を使えば、ホストが特定のNVM Setに対するコマンドを特定のI/O Submission Queueにのみ発行することが予めわかりますので、あるNVM SetがDTWIN状態の時は、そのNVM Set用のI/O Submission Queueを優先的にチェックすることができます。

　ただし、この機能でホストから通知された関連付けをコントローラがどう使用するか、について規定はありません。コントローラにとっては、この機能で通知された関連付けはあくまでの「ヒント」扱いです。

## UUIDs for Vendor Specific Information
　このオプション機能は、ベンダ固有(Vendor Specific)のコマンドや設定項目において、その内容やデータの解釈を、ホストから指定された識別子を用いてコントローラ側で切り替える、という機能です。

　例えば、`Get Log Page`コマンドのあるログページに複数の意味（定義）を持たせて、そのログページに対する`Get Log Page`コマンドの引数を使用してそれら複数の定義のうちどの定義の情報を取得するかを決定する、という使い方が想定されています。

　この機能の目的は何なのか、ですが、おそらく、`Get Log Page`コマンドで指定するログページのIDや、`Set/Get Features`コマンドで指定する設定項目のIDの中で、ベンダ固有として使えるIDは数が限られているため、それらを有効活用するためではないか、と推測しています。

　なお、対象となるコマンド（`UUID Index`フィールドを持つコマンド）は、`Get Log Page`コマンド、`Set/Get Features`コマンド、および`Identify`コマンド、の3つです。

# まとめ
　この記事では、2019年6月10日に発行されたNVMeの最新仕様であるリビジョン1.4について、新コマンドと新機能（NVM Setとその関連機能を除く）について、その概要を説明しました。

　記事内でも触れたように、リビジョン1.4での追加・変更機能の多くは、現時点ではエンタープライズやデータセンター環境での活用を前提にしたものであって、クライアント環境からは縁遠いものだと思います。

　とはいえ、一部のクライアント環境において、今後それらエンタープライズやデータセンター環境と同等の機能を求められるようになる可能性は大いにあります。その時に、これらの機能が役に立つかもしれません。

# リファレンス
[1] NVM Express, _"NVM Express<sup>TM</sup> Base Specification"_, Revision 1.4, June 10, 2019
[2] N. Adams, [_"NVMe<sup>TM</sup> Base Spec 1.4 Features Overview_"](https://nvmexpress.org/wp-content/uploads/FMS19_Annual-Update_State-of-the-Union-and-NVMe-Base-Spec-1.4-Features-Overview.pptx)[PPT], Flash Memory Summit 2019, August 6, 2019
[3] Intel, [_"Intel Solid-State Drive DC P3608 Series"_](https://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/ssd-dc-p3608-spec.pdf)[PDF], Product Specification, Sept, 2015（最終閲覧日2019年8月23日）
[4] F. Knight, [_"NVMe-oF<sup>TM</sup> 1.1: Multi Pathing Improvements"_](https://nvmexpress.org/wp-content/uploads/FMS19_NVMe-over-Fabrics_Whats-New-in-Version-1.1.pptx)[PPT], Flash Memory Summit 2019, August 6, 2019

# ライセンス
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="クリエイティブ・コモンズ・ライセンス" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />この記事は<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンス</a>の下に提供されています。