NANDフラッシュメモリベースSSDのセクタサイズ確認と変更

# はじめに
　[前回の記事](https://qiita.com/ken-yossy/items/28c2086b1cf02ea3442d)で、「現在のNANDフラッシュメモリをメディアとするSSDのほとんどは、論理セクタサイズ512バイトで動作する時はエミュレーション動作している」と説明しました。

　加えて、「エミュレーション動作よりもネイティブ動作のほうがNANDフラッシュメモリの寿命消費効率が良くなる」と説明しました。

　そこで今回の記事では、WindowsとNVMe SSDを例に挙げ、SSDがエミュレーション(512e)動作しているかどうかの確認方法や、ネイティブ(4Kn)動作させる方法（論理セクタサイズの変更方法）を説明します。

　なお、SATA SSDでは標準コマンドセットを使用した論理セクタサイズ変更が可能な製品を見たことがありません。これはATA Packet Interface (ATAPI)コマンドセットのサポートが必要だからです。このため、この記事ではNVMe SSDを使用します。

# まとめ
* Windowsの場合、ドライブの物理・論理セクタサイズは`fsutil`コマンドで確認可能
* NVMe SSDの論理セクタサイズは、`Identify`コマンドで確認が、`Format NVM`コマンドで変更が可能

# エミュレーション(512e)動作確認＠Windows
　ドライブ(SSD)がエミュレーション動作しているかどうかを確認する方法としては、Windowsであれば`fsutil`コマンドを使う方法<sup>[1]</sup>が最も簡単です。

　具体的には、ドライブをNTFSでフォーマットした後に、以下の例のように`fsutil`コマンドを実行します。この例はWindows 11 ProのPCでDドライブ(SSD)の状態を確認したものです。

```
PS C:\Users\ken> fsutil fsinfo ntfsinfo d:
（中略）
Bytes Per Sector  :                512
Bytes Per Physical Sector :        4096
（以下略）
```
図1：fsutilコマンドの実行結果（英語版Windows）

　この結果のうち、**"Bytes Per Sector"が論理セクタサイズ**を、**"Bytes Per Physical Sector"が（ドライブの）物理セクタサイズ**を示します。

　日本語版Windowsでは以下のように表示されます。

```
PS C:\WINDOWS\system32> fsutil fsinfo ntfsinfo c:
（中略）
セクターあたりのバイト数  :                512
物理セクターあたりのバイト数 :        4096
（中略）
PS C:\WINDOWS\system32>
```
図2：fsutilコマンドの実行結果（日本語版Windows）

　このように、**論理セクタサイズが512バイトで物理セクタサイズが512バイトではない状態が512eモード**です。

　MicrosoftのWebページ<sup>[1]</sup>には、`fsutil`コマンドの結果組み合わせ表が掲載されています。表1はその抜粋です。

表1：`fsutil`コマンドの結果からわかるドライブの動作モード(Drive Type)

| Bytes Per Sector value | Bytes Per Physical Sector value | Drive Type |
|:-|:-|:-|
| 4096 | 4096 | 4K native |
| 512 | 4096 | Advanced Format (also known as 512E) |
| 512 | 512 | 512-byte native |

　この表1から、図1と図2の`fsutil`コマンドの結果はどちらも動作モードが512eである、とわかります。

# NVMe SSDのセクタサイズ設定
　ここからは、実機を用いてSSDのセクタサイズ確認や論理セクタサイズ変更を試します。

　はじめに説明した通り、実機にはSATA SSDではなくNVMe SSDを使用します。

　NVMe SSDの場合、SSDの現在の論理セクタサイズと、SSDがサポートする論理セクタサイズは、Namespaceに`Identify`コマンドを発行すると確認できます。

　以下はその例です。これは私の自作Windowsプログラム<sup>[2]</sup>を使い、あるNVMe SSDのNamespaceに`Identify`コマンドを発行した結果です。「★」に続く内容は説明用に追加したコメントです。

```
[M] Namespace Size (NSZE): 1000215216 (sectors)
（中略）
[M] Formatted LBA Size (FLBAS):
        bit [      4] 0 = All of the metadata is transferred as a separate contiguous buffer of data.
        bit [  3:  0] 0 = LBA format is no.0 (LBAF0). ★ 現在のフォーマットは0番
（中略）
[M] LBA Format 0 Support (LBAF0): ★ 論理セクタ(LBA)サイズ512バイト（おそらく512e）
        bit [ 25: 24] 2 = Relative Performance (RP): Good performance
        bit [ 23: 16] 9 = LBA Data Size (LBADS): 512 bytes / sector
        bit [ 15:  0] 0 = Metadata Size (MS): 0 bytes
[O] LBA Format 1 Support (LBAF1): ★ 論理セクタ(LBA)サイズ4096バイト（おそらく4Kn）
        bit [ 25: 24] 1 = Relative Performance (RP): Better performance
        bit [ 23: 16] 12 = LBA Data Size (LBADS): 4096 bytes / sector
        bit [ 15:  0] 0 = Metadata Size (MS): 0 bytes
```

　この結果からわかることは以下の通りです。

* 現在このNamespaceはフォーマット0（＝論理セクタサイズ512バイト）でフォーマットされている
* このNamespaceは、2つのフォーマット（フォーマット0と1）でフォーマット可能
    * フォーマット0は論理セクタサイズ512バイト
    * フォーマット1は論理セクタサイズ4096バイト（＝4Kバイト）で、**フォーマット0より性能が良い**

　この"Relative Performance (RP)"は、数字の小さいほうが、4KiB QD=32のリード性能において性能が高いことを示します（図3）。

![NVMe仕様におけるフォーマットの「相対性能」](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439683/a18b294f-37e6-0e61-17da-5b42a74a6609.png "NVMe仕様におけるフォーマットの「相対性能」")
図3：NVMe仕様<sup>[2]</sup>におけるフォーマットの「相対性能」

# NVMe SSDの論理セクタサイズを4キロバイトに変更する
　そこで、このNVMe SSDのNamespaceのフォーマットをフォーマット1に変更、つまり論理セクタサイズを512バイトから4キロバイトに変えます。

　NVMe SSDの論理セクタサイズ変更にはフォーマット変更が必要ですので、`Format NVM`コマンドを使用します。

　なお、NVMe仕様<sup>[3]</sup>において`Format NVM`コマンドはオプションですので、お使いのNVMe SSDが`Format NVM`コマンドに対応しているかどうか、確認が必要です。

　また残念ながら、Windowsの標準NVMeデバイスドライバを使う場合、WinPEモードでしかこの処理（＝フォーマットを指定した`Format NVM`コマンドの発行）ができません。

　このため、論理セクタサイズの変更はLinuxの`nvme-cli`パッケージを使いました。

:::note warn
　注意：Format NVMコマンドを発行するとそのNamespaceに書き込まれていたデータが読めなくなる可能性がありますので、実行の際は十分に注意してください！！
:::

　`nvme`コマンドを使用した`Format NVM`コマンドの発行は非常に簡単です。

　以下は、先ほどのNVMe SSD (`/dev/nvme0`)に対して、「Namespace 1をフォーマット1（＝論理セクタサイズ4096バイト）でフォーマットする」ことを指示した様子です。

　`-l 1`で「フォーマット1」を指定し、コマンド発行対象としてSSD自体を示す`/dev/nvme0`にIDが1のNamespaceを示す`n1`を付け加えた`/dev/nvme0n1`を指定します。

```
ubuntu@ubuntu:~/Desktop$ sudo nvme format -l 1 /dev/nvme0n1
Success formatting namespace:1
```

　この表示が出力されればフォーマット変更成功です。コマンド処理完了までにかかる時間は製品により変わる可能性があります。

　実際にフォーマット1でフォーマットされたのかどうかを、Namespace 1を対象に`Identify`コマンドを発行して確認すると、下記のようになりました。

```
ubuntu@ubuntu:~/Desktop$ sudo nvme id-ns -H /dev/nvme0n1
NVME Identify Namespace 1:
（中略）
flbas   : 0x1
  [4:4] : 0	Metadata Transferred in Separate Contiguous Buffer
  [3:0] : 0x1	Current LBA Format Selected
（中略）
LBA Format  0 : Metadata Size: 0   bytes - Data Size: 512 bytes - Relative Performance: 0x2 Good 
LBA Format  1 : Metadata Size: 0   bytes - Data Size: 4096 bytes - Relative Performance: 0x1 Better (in use)
```

　"Current LBA Format Selected"が1つまり「フォーマット1」と表示され、"LBA Format 1"の部分にも「現在使用中(in use)」と表示されています。

　これで、論理セクタサイズ4キロバイトでのフォーマットが完了です。

# 論理セクタサイズ4キロバイトのSSDにWindows 11をインストール
　フォーマット変更だけではつまらないので、論理セクタサイズ4キロバイトでフォーマットしたSSDにWindows 11をインストールしました。

　インストールは何も問題なく完了、そこで再度`fsutil`コマンドで論理セクタサイズと物理セクタサイズの状態を確認しました。

```
PS C:\Users\ken> fsutil fsinfo ntfsinfo c:
（中略）
Bytes Per Sector  :                4096
Bytes Per Physical Sector :        4096
（以下略）
```

　冒頭に示した論理セクタサイズ512バイトの場合と比較すれば一目瞭然、"Bytes Per Sector"の部分が4096バイトになっています。これでシステムとして**4Kネイティブ(4Kn)モード**で動作していることになります。

# まとめ
　今回の記事では、WindowsとNVMe SSDを例に挙げ、SSDがエミュレーション(512e)動作しているかどうかの確認方法と、ネイティブ(4Kn)動作させる方法（論理セクタサイズの変更方法）を説明しました。

　現在入手可能なSSDをWindowsで使用すると、デフォルトでは512eモードで動作することが多いです。しかし、SSDの寿命やシステム全体の最適化を考えると、4Knモードで動作させたほうがより良いです。

　もしSSDをお使いであれば、動作モードを確認してみてはいかがでしょうか。

# References
[1] Microsoft, _"[Microsoft support policy for 4K sector hard drives in Windows](https://docs.microsoft.com/en-us/troubleshoot/windows-server/backup-and-storage/support-policy-4k-sector-hard-drives)"_, December 16, 2021（2021年12月27日閲覧）
[2] _[ken-yossy / nvmetool-win](https://github.com/ken-yossy/nvmetool-win)_
[3] NVM Express, _"NVM Express Base Specification"_, Revision 1.4b, September 21, 2020

# ライセンス表記
<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>の下に提供されています。