====== 複数のNVMe namespaceを試す ======
NVMeにはNamespace(名前空間)という機能がある。NVMeデバイスの記憶領域を論理的に分割し、それぞれを独立したNVMeストレージのように扱う機能である。
馴染みあるところだとパーティションのようなものだが、ファームウェアレイヤーでの分割となり、名前空間同士には明確な前後関係はなく、OSからは別のデバイスとして見えるのが大きな違い。ハードウェアRAIDの仮想ドライブ、ZFSのデータセットに近い。
名前空間を使うと以下の効能が見込めるとされる。
* 名前空間ごとに異なる暗号鍵によるセキュリティの向上
* オーバープロビジョニングによる書き込み性能、耐久性の向上
* リカバリ領域などの書込み保護
名前空間はオプション機能なので、大半のNVMe SSD製品、特にコンシューマ向けは最大1つの名前空間しかサポートしてなかったりして残念ではあるが、使えれば色々遊べそうな機能だ。個人的には仮想と物理を行き来するような構成でディスク管理の簡単化への期待が高まる(弊宅ではPromoxVEと一部VMのRDM用パーティションが同じSSD上にあり、だいぶ面倒な運用となっている。名前空間でデバイスを割ることができれば、非常にシンプルになるハズ。)
===== 試した環境 =====
* ハードウェア
* Lenovo ThinkServer TS150
* Supermicro X10SRL-F
* SAMSUNG PM9A3 (M.2/U.2)
* 最大32の名前空間に対応
* ソフトウェア
* Ubuntu Server 22.04.2 LTS
FreeBSDerのわたくしといたしましては、FreeBSDの''nvmecontrol''コマンドで試したかったのだけれども、[[https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=269912|バグで名前空間が作れない]]という致命的な問題があったので、やむなくLinux環境で試すこととなった。なお、バグは13.2-RELEASEで修正される模様。
===== 現状の確認 =====
まずは現在のNVMe SSDの状態を確認する。
デバイスの認識状況:
$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
--------------------- ------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 Serial SAMSUNG MZ1L21T9HCLS-00A07 1 0.00 B / 1.92 TB 512 B + 0 B GDC7302Q
使用可能なLBAフォーマット:
$ sudo nvme id-ns -H /dev/nvme0n1 | grep ^LBA
LBA Format 0 : Metadata Size: 0 bytes - Data Size: 512 bytes - Relative Performance: 0 Best (in use)
LBA Format 1 : Metadata Size: 0 bytes - Data Size: 4096 bytes - Relative Performance: 0 Best
既存の名前空間から使用可能なLBA形式を取得しておく。
というのも、後ほど名前空間作成時に使うのだけれども、名前空間がない状態でこのリストを取得する術が無さそうなのだ。いざとなれば、てきとーなLBA形式で名前空間作成後、希望の形式で再フォーマットしてやれば済む話だが、二度手間は避けたいので。
NVMeコントローラの一覧:
$ sudo nvme list-ctrl /dev/nvme0
num of ctrls present: 1
[ 0]:0x6
NVMeデバイスでは複数のコントローラを持つことができ、名前空間はコントローラに割り当てる形となっている。この値も後ほど使うのでメモっておく。
NVMeコントローラの詳細:
$ sudo nvme id-ctrl /dev/nvme0 | grep -E 'nn|nvmcap'
tnvmcap : 1920383410176
unvmcap : 0
nn : 32
''tnvmcap''はTotal NVM Capacity、''unvmcap''はUnallocated NVM Capacityのことで、それぞれNVMeデバイスの合計容量と未確保容量をバイト単位であらわす。
''nn''はNumber of Namespacesで、本記事の肝であり、デバイスがサポートする名前空間の数である。これが1だと話にならない。
上記の実行結果からは、本SSDは最大32個の名前空間が使えるものの、現在の空き容量が0なのでこれ以上の名前空間の追加は不可ということになる。
===== 名前空間の削除 =====
''nvme delete-ns''で既存の名前空間を削除する。
言うまでもないが、削除された名前空間にあったデータは全て消失する。確認プロンプトも出ず、デバイスレベルでの管理情報が消えることとなり、データの復元は個人レベルでは恐らく不可能なので要注意。
$ sudo nvme delete-ns /dev/nvme0 -n 1
delete-ns: Success, deleted nsid:1
unvmcapが増えていることが分かる。
$ sudo nvme id-ctrl /dev/nvme0 | grep nvmcap
tnvmcap : 1920383410176
unvmcap : 1920383410176
===== 名前空間の追加 =====
いよいよ名前空間を追加する。
$ sudo nvme create-ns /dev/nvme0 -f 0 -s 209715200 -c 209715200
create-ns: Success, created nsid:1
引数オプションの意味は下表のとおり。
^ オプション ^ 意味 ^
| ''-f'', ''--flbas'' | LBA形式の指定。''nvme id-ns''で得られた値を指定する。ここでは512バイトセクタとしている。 |
| ''-s'', ''--nsze'' | 名前空間の最大サイズ。-fで指定したブロック数単位で指定する。ここでは100GiB÷512バイト=209715200としている。|
| ''-c'', ''--ncap'' | 名前空間の確保サイズ。-sのブロック数以下で指定する。最大サイズ未満を指定すればオーバープロビジョニング状態となる。|
作成した名前空間はコントローラにアタッチして初めて使えるようになる。
$ sudo nvme attach-ns /dev/nvme0 -n 1 -c 0x6
attach-ns: Success, nsid:1
同じ要領で、もう1つ名前空間を追加する。
$ sudo nvme create-ns /dev/nvme0 -s 209715200 -c 209715200 -f 0
create-ns: Success, created nsid:2
$ sudo nvme attach-ns /dev/nvme0 -n 2 -c 0x6
attach-ns: Success, nsid:2
システムから''nvme0n1'', ''nvme0n2''として認識されていることが分かる。
$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
--------------------- ------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 Serial SAMSUNG MZ1L21T9HCLS-00A07 1 107.37 GB / 107.37 GB 512 B + 0 B GDC7302Q
/dev/nvme0n2 Serial SAMSUNG MZ1L21T9HCLS-00A07 2 107.37 GB / 107.37 GB 512 B + 0 B GDC7302Q
$ lsblk | grep nvme0
nvme0n1 259:0 0 100G 0 disk
nvme0n2 259:1 0 100G 0 disk
それぞれのS.M.A.R.T.はこんな感じ。デバイスが対応していれば、名前空間ごとに固有のS.M.A.R.T.を持つこともできるようだ。
^ nvme0n1 ^ nvme0n2 ^
|$ sudo smartctl -a /dev/nvme0n1
smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.15.0-60-generic] (local build)
Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Model Number: SAMSUNG MZ1L21T9HCLS-00A07
Serial Number: S666NE0Rxxxxxx
Firmware Version: GDC7302Q
PCI Vendor/Subsystem ID: 0x144d
IEEE OUI Identifier: 0x002538
Total NVM Capacity: 1,920,383,410,176 [1.92 TB]
Unallocated NVM Capacity: 1,705,635,045,376 [1.70 TB]
Controller ID: 6
NVMe Version: 1.4
Number of Namespaces: 32
Namespace 1 Size/Capacity: 107,374,182,400 [107 GB]
Namespace 1 Formatted LBA Size: 512
Local Time is: Fri May 5 10:11:28 2023 UTC
Firmware Updates (0x17): 3 Slots, Slot 1 R/O, no Reset required
Optional Admin Commands (0x005f): Security Format Frmw_DL NS_Mngmt Self_Test MI_Snd/Rec
Optional NVM Commands (0x005f): Comp Wr_Unc DS_Mngmt Wr_Zero Sav/Sel_Feat Timestmp
Log Page Attributes (0x0e): Cmd_Eff_Lg Ext_Get_Lg Telmtry_Lg
Maximum Data Transfer Size: 512 Pages
Warning Comp. Temp. Threshold: 77 Celsius
Critical Comp. Temp. Threshold: 85 Celsius
Namespace 1 Features (0x1a): NA_Fields No_ID_Reuse NP_Fields
Supported Power States
St Op Max Active Idle RL RT WL WT Ent_Lat Ex_Lat
0 + 8.25W 8.25W - 0 0 0 0 70 70
Supported LBA Sizes (NSID 0x1)
Id Fmt Data Metadt Rel_Perf
0 + 512 0 0
1 - 4096 0 0
=== START OF SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
SMART/Health Information (NVMe Log 0x02)
Critical Warning: 0x00
Temperature: 51 Celsius
Available Spare: 100%
Available Spare Threshold: 10%
Percentage Used: 13%
Data Units Read: 3,211,446,954 [1.64 PB]
Data Units Written: 3,198,599,733 [1.63 PB]
Host Read Commands: 7,123,174,983
Host Write Commands: 3,057,480,670
Controller Busy Time: 35,138
Power Cycles: 183
Power On Hours: 8,877
Unsafe Shutdowns: 106
Media and Data Integrity Errors: 0
Error Information Log Entries: 14
Warning Comp. Temperature Time: 0
Critical Comp. Temperature Time: 0
Temperature Sensor 1: 51 Celsius
Temperature Sensor 2: 80 Celsius
Error Information (NVMe Log 0x01, 16 of 64 entries)
Num ErrCount SQId CmdId Status PELoc LBA NSID VS
0 14 0 0xb007 0x4238 0x000 0 1 -
1 13 0 0x8007 0x4238 0x000 0 1 -
2 12 0 0x8006 0x4238 0x000 0 1 -
3 11 0 0x7007 0x422a 0x000 0 0 -
|$ sudo smartctl -a /dev/nvme0n2
smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.15.0-60-generic] (local build)
Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Model Number: SAMSUNG MZ1L21T9HCLS-00A07
Serial Number: S666NE0Rxxxxxx
Firmware Version: GDC7302Q
PCI Vendor/Subsystem ID: 0x144d
IEEE OUI Identifier: 0x002538
Total NVM Capacity: 1,920,383,410,176 [1.92 TB]
Unallocated NVM Capacity: 1,705,635,045,376 [1.70 TB]
Controller ID: 6
NVMe Version: 1.4
Number of Namespaces: 32
Namespace 2 Size/Capacity: 107,374,182,400 [107 GB]
Namespace 2 Formatted LBA Size: 512
Local Time is: Fri May 5 10:12:01 2023 UTC
Firmware Updates (0x17): 3 Slots, Slot 1 R/O, no Reset required
Optional Admin Commands (0x005f): Security Format Frmw_DL NS_Mngmt Self_Test MI_Snd/Rec
Optional NVM Commands (0x005f): Comp Wr_Unc DS_Mngmt Wr_Zero Sav/Sel_Feat Timestmp
Log Page Attributes (0x0e): Cmd_Eff_Lg Ext_Get_Lg Telmtry_Lg
Maximum Data Transfer Size: 512 Pages
Warning Comp. Temp. Threshold: 77 Celsius
Critical Comp. Temp. Threshold: 85 Celsius
Namespace 2 Features (0x1a): NA_Fields No_ID_Reuse NP_Fields
Supported Power States
St Op Max Active Idle RL RT WL WT Ent_Lat Ex_Lat
0 + 8.25W 8.25W - 0 0 0 0 70 70
Supported LBA Sizes (NSID 0x2)
Id Fmt Data Metadt Rel_Perf
0 + 512 0 0
1 - 4096 0 0
=== START OF SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
SMART/Health Information (NVMe Log 0x02)
Critical Warning: 0x00
Temperature: 51 Celsius
Available Spare: 100%
Available Spare Threshold: 10%
Percentage Used: 13%
Data Units Read: 3,211,446,954 [1.64 PB]
Data Units Written: 3,198,599,733 [1.63 PB]
Host Read Commands: 7,123,174,983
Host Write Commands: 3,057,480,670
Controller Busy Time: 35,138
Power Cycles: 183
Power On Hours: 8,877
Unsafe Shutdowns: 106
Media and Data Integrity Errors: 0
Error Information Log Entries: 14
Warning Comp. Temperature Time: 0
Critical Comp. Temperature Time: 0
Temperature Sensor 1: 51 Celsius
Temperature Sensor 2: 80 Celsius
Error Information (NVMe Log 0x01, 16 of 64 entries)
Num ErrCount SQId CmdId Status PELoc LBA NSID VS
0 14 0 0xb007 0x4238 0x000 0 1 -
1 13 0 0x8007 0x4238 0x000 0 1 -
2 12 0 0x8006 0x4238 0x000 0 1 -
3 11 0 0x7007 0x422a 0x000 0 0 -
|
===== UEFIやOSからの見え方 =====
実はここからが本題。
複数の名前空間が持てるのは良いが、UEFI (BIOS)やOSから2つ目以降の名前空間はどのように認識されるのだろうか。NVMe Namespaceはハードウェアに近いレイヤーでのデバイス分割技術ではあるものの、PCIデバイスとしてはあくまで1つである。名前空間の実現には、ホストのNVMeドライバに拠るところが大きい気がして、特にPCのUEFI (BIOS)での対応状況が気になるところ。
それぞれのNVMe名前空間からシステムを自由にブートできれば夢が広がリングなのだが、情報がさっぱり見当たらないので実際に試してみた。
==== Linux ====
Linuxの場合、これまで見てきたとおり名前空間は''/dev/nvme0n1'', ''/dev/nvme0n2''という感じで独立したデバイスのように見える。インストール先の選択肢にも上がっており、任意の名前空間にインストールが可能である。
{{ :pc:multiple_nvme_namespaces_in_ubuntu_installer.png |}}
==== FreeBSD ====
FreeBSDでは''/dev/nvme0ns1'', ''/dev/nvme0ns1''のように見える(さらに言うと対応する汎用ディスクレイヤーのデバイスとして''/dev/nvd0'', ''/dev/nvd1''が生えてくる)。こちらも任意の名前空間にインストールが可能である。
{{ :pc:multiple_nvme_namespaces_in_freebsd_installer.png |}}
==== Windows ====
WindowsではLUN違いのデバイスとして見えるようだ。
{{ :pc:multiple_nvme_namespaces_in_windows_server_2016.png |}}
インストーラーでも別ドライブとして認識されており、インストールできると思われる。
{{ :pc:multiple_nvme_namespaces_in_windows_server_2016_installer.png |}}
==== Windows + USB ====
WindowsとNVMe→USB変換器経由で複数名前空間を持つSSDをつないだ時の認識のされ方。
^ 変換チップ ^ 認識のされ方 ^
| ASM2362 | 最初の名前空間のみドライブとして認識される |
| JMS583 | 全く認識されない。名前空間が1つのみのSSDなら問題なく認識されるので、複数名前空間があるとダメっぽい。 |
==== UEFI (BIOS) ====
UEFIからの見え方は、恐らくマザボごとにまちまちである可能性が高い。NVMe対応UEFIは必須として、そのUEFIが持つNVMeドライバの対応状況次第だと思う。
=== ThinkServer TS150 ===
比較的初期のNVMe対応品であると思われるTS150では、名前空間IDが1にあるESPを優先的にブートデバイスとして扱うようだ(あるいは、UEFIの最初のブートエントリが優先されてるのかも)。なお、NSID 1にはUbuntu Server、NSID 2にはFreeBSDをインストールした状態である。
{{ :pc:multiple_nvme_namespaces_in_ts150_uefi.png |}}
UEFIのブートエントリは以下のような感じで、名前空間2にインストールしたFreeBSDも、正しく登録されているようだ。
$ efibootmgr -v
BootCurrent: 0000
Timeout: 1 seconds
BootOrder: 0000,0002,0003
Boot0000* ubuntu HD(1,GPT,0066403c-e597-4cfa-aa56-ad2f79960c92,0x800,0x219800)/File(\EFI\UBUNTU\SHIMX64.EFI)
Boot0002* FreeBSD HD(1,GPT,a0fad4cc-eb36-11ed-bb5d-4ccc6acb7c47,0x28,0x82000)/File(\EFI\FREEBSD\LOADER.EFI)
Boot0003* UEFI OS HD(1,GPT,a0fad4cc-eb36-11ed-bb5d-4ccc6acb7c47,0x28,0x82000)/File(\EFI\BOOT\BOOTX64.EFI)..BO
$ sudo blkid
/dev/nvme0n1p1: UUID="8030-A0AE" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="0066403c-e597-4cfa-aa56-ad2f79960c92"
/dev/nvme0n2p1: SEC_TYPE="msdos" UUID="C23B-12F9" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="efiboot0" PARTUUID="a0fad4cc-eb36-11ed-bb5d-4ccc6acb7c47"
ここで''efibootmgr -n 0003''とし次のブートデバイスをFreeBSDにすると、しっかりFreeBSDが立ち上がってくる。ただしUEFI上でのブートデバイスとしての認識は「ubuntu」のままだった。
一方で、''efibootmgr -o 0003,0002,0000''としてブートオーダーをFreeBSD優先にしても、相変わらずUbuntuが立ち上がってきた。
いまいち釈然としない挙動だが、とりあえず名前空間が分かれていてもブート自体は可能なことは分った。恒常的に起動OSを切り替えたいなら、[[http://www.rodsbooks.com/refind/index.html|rEFInd]]や[[https://github.com/CloverHackyColor/CloverBootloader|CloverBootloader]]あたりを名前空間1に入れておけば良いだろう。
=== Supermicro X10SRL-F ===
SupermicroのマザボX10SRL-Fでは、正しいESPさえあれば名前空間問わずブートデバイスとして検出してくれる模様。
{{ :pc:multiple_nvme_namespaces_in_x10srl-f_uefi.png |}}
どちらも「UEFI OS」となっていて分かりづらいが、上が名前空間1のESPにあるFreeBSDのブートローダ、下が名前空間2のESPにあるProxmox VEのブートローダである。ブートオーダーはPVEが優先となっており、問題なくPVEが起動する。さすがSupermicro。
===== 参考サイト =====
* [[https://narasimhan-v.github.io/2020/06/12/Managing-NVMe-Namespaces.html|Managing Nvme Namespaces | Narasimhan V]]
* [[https://www.drewthorst.com/posts/nvme/namespaces/readme/|NVMe Namespaces · Drew Thorstensen]]
* [[https://metebalci.com/blog/a-quick-tour-of-nvm-express-nvme/|A Quick Tour of NVM Express (NVMe)]]
* [[https://www.bjonnh.net/article/20210721_nvme4k/|Switching your NVME ssd to 4k - Bjonnh.net]]
* 複数Namespaceに対応したSSDリスト
* [[https://www.truenas.com/community/resources/nvme-ssd-namespaces-support-table.178/|NVMe SSD namespaces support table | TrueNAS Community]]
* [[https://forum.level1techs.com/t/nvme-namespaces-little-known-cool-features-of-most-nvme-and-user-programmable-endurance/172660/18|NVMe Namespaces - Little Known Cool Features of (most) NVMe and User-Programmable Endurance - Wikis & How-to Guides - Level1Techs Forums]]