NVMe SSDにfault injectionしてみる

この記事は

Linux kernelのfalult injection機能の(特にNVMe SSDに関連する部分について)
ソースを読んだり、実際に使ってみたりする記事のうちの一つ

記事一覧

その1:fault injectionってなあに
その2:fault injection機能が埋まっている箇所のソースを読む
その3:NVMe SSDにfault injectionしてみる ★今回はこれ

NVMe SSDにfault injectionしてみる

環境準備

OSインストール

なんでもいいんですが
私はVirtualBox上にUbuntu22.04.3をインストールした
SATA(AHCI)コントローラーに接続されているHDDがシステムディスク
NVMeコントローラに接続されているSSDがデータディスク

システムディスクにfalult injectionするのはちょっと不安なので、
NVMe SSDはデータディスクとして準備するのがおすすめ

VirtualBox ストレージ設定

fault injection機能の有効化

Ubuntu22.04.3では、fault injectionは無効になっているため
機能を有効化するためにKernelをビルドする

Linux Kernelのソースを入手する

手順はUbuntuの公式Wiki (と自分の記憶)などを参考にしました

/etc/apt/source.listのdeb-srcの行のコメントをすべて外す

deb-src hogehoge

パッケージのリストを更新

apt update

適当な作業用ディレクトリに移動し、ソースのパッケージをダウンロード

apt-get source linux-image-$(uname -r)

以下三つのファイルが落ちてくるので

以下をたたいてUbuntu向けの修正が反映されたソースを生成する

dpkg-source -x linux_hoge.dsc

Linux Kernelをビルドする

kernelのビルドに必要なパッケージをインストールする

apt install make gcc flex bison libncurses-dev libelf-dev libssl-dev

ソースのルートディレクトリに移動
デフォルトのconfigファイルをKernelビルドに再利用するためコピー

cp /boot/config-hoge ./.config

fault injectionを有効にするよう.configを編集

CONFIG_FAULT_INJECTION=y

make oldconfigたたいてfault injection関係と思われるものはyを選択

Kernelのビルドとdpkgの作成

make -$(nproc) deb-pkg

ビルドしたKernelの適用

apt install linux-headers-hoge_amd64.deb
apt install linux-headers-hoge_amd64.deb

再起動する(ビルドしたKernelで起動しなおす)

/sys/kernel/debug/nvme*が存在することを確認する

root@nodoguro-VirtualBox:/home/nodoguro# ls /sys/kernel/debug/nvme0

nvme0/   nvme0n1/ 

実践編

ターゲットの確認

ターゲットとなるディスクを確認しておく 今回は/dev/nvme0n1

root@nodoguro-VirtualBox:/home/nodoguro# parted -l

Model: ATA VBOX HARDDISK (scsi)

Disk /dev/sda: 107GB

Sector size (logical/physical): 512B/512B

Partition Table: gpt

Disk Flags: 



Number  Start   End    Size   File system  Name                  Flags

 1      1049kB  538MB  537MB  fat32        EFI System Partition  boot, esp

 2      538MB   107GB  107GB  ext4





Error: /dev/nvme0n1: unrecognised disk label

Model: ORCL-VBOX-NVME-VER12 (nvme)                                        

Disk /dev/nvme0n1: 26.8GB

Sector size (logical/physical): 512B/512B

Partition Table: unknown

Disk Flags: 

fault injectionしてみる

今回は公式ドキュメントのnvme-fault-injectionに記載のある以下3種のエラー注入を試してみる

Example 1:Inject default status code with no retry
Example 2: Inject default status code with retry
Example 3: Inject an error into the 10th admin command

今回は、ddコマンドでランダムなデータを書き込んでテストする
正常に終了した場合は以下のようになる

root@nodoguro-VirtualBox:/home/nodoguro# dd if=/dev/urandom of=/dev/nvme0n1 count=10000

10000+0 records in

10000+0 records out

5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.526876 s, 9.7 MB/s

Example 1:Inject default status code with no retry

100%の確率で1度だけfault injectionする
リトライしない

設定
echo 1 > /sys/kernel/debug/nvme0n1/fault_inject/times
echo 100 > /sys/kernel/debug/nvme0n1/fault_inject/probability
結果
root@nodoguro-VirtualBox:/home/nodoguro/source# dd if=/dev/urandom of=/dev/nvme0n1 count=10000

dd: writing to '/dev/nvme0n1': Input/output error

1+0 records in

0+0 records out

0 bytes copied, 0.00110659 s, 0.0 kB/s

エラーでこけていて期待通り

Example 2: Inject default status code with retry

100%の確率で1度だけfault injectionする
リトライする

設定
echo 1 > /sys/kernel/debug/nvme0n1/fault_inject/times
echo 100 > /sys/kernel/debug/nvme0n1/fault_inject/probability
echo 0 > /sys/kernel/debug/nvme0n1/fault_inject/dont_retry
結果
root@nodoguro-VirtualBox:/home/nodoguro/source# dd if=/dev/urandom of=/dev/nvme0n1 count=10000

10000+0 records in

10000+0 records out

5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.600538 s, 8.5 MB/s

リトライするのでエラー見えないで期待通り

Example 3: Inject an error into the 10th admin command

しばらくしてから100%の確率で1度だけfault injectionする
※admin commandと書いてあるが、他と合わせてddで試す

設定
echo 100 > /sys/kernel/debug/nvme0n1/fault_inject/probability
echo 10 > /sys/kernel/debug/nvme0n1/fault_inject/space
echo 1 > /sys/kernel/debug/nvme0n1/fault_inject/times
結果
root@nodoguro-VirtualBox:/home/nodoguro/source# dd if=/dev/urandom of=/dev/nvme0n1 count=10000

dd: writing to '/dev/nvme0n1': Input/output error

73+0 records in

72+0 records out

36864 bytes (37 kB, 36 KiB) copied, 0.00613897 s, 6.0 MB/s

最初はIO成功、途中でIOが失敗しており期待通り

最後に

NVMe SSDへのfault injectionを実際に使ってみるところまでお試しできた
当初の予定通り、使ってみるところまでできて良かった

何か調べたいときに適したツールでサクッと調査できるしぐさに常に憧れがあるが
こういった、Linux Kernelに埋まっている、今はまだ知らない機能たちを触っていくのがそれに近づく一歩な気がしている
(これに関しては使うにはKernelのビルドが必要で超時間がかかっちゃうけどね..)