フォルトインジェクションの使い方

#1 フォルトインジェクションとは？
ディスクアクセス、メモリ獲得等を故意に失敗させるためのカーネル機能です。
この機能を使うことで、普段通過しないエラー処理部を実行することができます。
つまり、エラー処理を実行したあと、システムが正しく動作するかどうかの確認ができます。

openSUSE(Leap 42.3)は、ディスクアクセスのフォルトインジェクションがデフォルトで有効です。
一方、CentOS7は無効です。有効にするためには、カーネルパラメータ(CONFIG_FAULT_INJECTION)を
有効にしてカーネルをコンパイルする必要があります。

ここでは、ディスクアクセスに対するフォルトインジェクションを使ってみます。

#2 環境
VMware Workstation 14 Player上の仮想マシンを使いました。
仮想マシンのOS版数は以下のとりです。

```console:OS版数
master:~ # lsb_release -a
LSB Version:    n/a
Distributor ID: openSUSE project
Description:    openSUSE Leap 42.3
Release:        42.3
Codename:       n/a

master:~ # uname -r
4.4.76-1-default
```

#3 I/Oエラーを発生させる方法
ディスクにデータを書き込む際、I/Oエラーを発生させてみます。

##3.1 事前準備

```console:テスト環境
/root/testをテスト用に使います。
master:~/test # pwd
/root/test

データを書き込むディスクを確認します。/dev/sda2であることがわかります。
master:~/test # df -hT .
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/sda2      btrfs   18G   11G  7.0G  61% /
```

```console:フォルトインジェクションの有効化
probabilityはI/Oエラーの発生確立を指定します。ここでは、100%を指定してみました。
master:~/test # echo 100 > /sys/kernel/debug/fail_make_request/probability
master:~/test # cat /sys/kernel/debug/fail_make_request/probability
100

timesはI/Oエラーの発生回数を指定します。ここでは、I/Oエラーを1回だけ発生させてみます。
master:~/test # echo 1 > /sys/kernel/debug/fail_make_request/times
master:~/test # cat  /sys/kernel/debug/fail_make_request/times
1
```

/dev/sda2に対してデータを書き込むので、
/sys/block/sda/sda2配下のmake-it-failを有効化(=1)します。

```console:フォルトインジェクションの有効化（ディスク毎の設定）
master:~/test # echo 1 > /sys/block/sda/sda2/make-it-fail
master:~/test # cat  /sys/block/sda/sda2/make-it-fail
1
```

##3.2 実行結果の確認
ddコマンドを実行すると、エラー(Input/output error)が表示されていることがわかります。

```console:ファイルへの書き込み
master:~/test # dd if=/dev/zero of=test.dat oflag=direct bs=1024 count=1000
dd: error writing 'test.dat': Input/output error
3+0 records in
2+0 records out
2048 bytes (2.0 kB, 2.0 KiB) copied, 0.00703676 s, 291 kB/s
```

次にログを確認します。
バックトレース中にshould_failという関数(★)が表示されています。
この関数が表示されるというこは、エラー処理が実行されたことを意味します。

```console:ログの確認
master:/sys/block/sda # journalctl -f
(中略)
Jun 28 21:03:48 master kernel: FAULT_INJECTION: forcing a failure.
                               name fail_make_request, interval 1, probability 100, space 0, times 1
Jun 28 21:03:48 master kernel: CPU: 0 PID: 3338 Comm: kworker/u256:2 Tainted: G        W  O     4.4.76-1-default #1
Jun 28 21:03:48 master kernel: Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 05/19/2017
Jun 28 21:03:48 master kernel: Workqueue: btrfs-submit btrfs_submit_helper [btrfs]
Jun 28 21:03:48 master kernel:  0000000000000000 ffffffff81339d97 ffffffff81ede940 0000000000000064
Jun 28 21:03:48 master kernel:  ffffffff813641f7
Jun 28 21:03:48 master kernel:  ffff8800b7a88828 0000000000000008 ffffffff8130440d
Jun 28 21:03:48 master kernel:  ffff880139615f40 0000000000000046 ffff880139615f40 ffffffff810aac52
Jun 28 21:03:48 master kernel: Call Trace:
Jun 28 21:03:48 master kernel:  [<ffffffff81019f29>] dump_trace+0x59/0x320
Jun 28 21:03:48 master kernel:  [<ffffffff8101a2ea>] show_stack_log_lvl+0xfa/0x180
Jun 28 21:03:48 master kernel:  [<ffffffff8101b091>] show_stack+0x21/0x40
Jun 28 21:03:48 master kernel:  [<ffffffff81339d97>] dump_stack+0x5c/0x85
Jun 28 21:03:48 master kernel:  [<ffffffff813641f7>] should_fail+0x107/0x130 ★
Jun 28 21:03:48 master kernel:  [<ffffffff8130440d>] generic_make_request_checks+0x17d/0x660
Jun 28 21:03:48 master kernel:  [<ffffffff81307f74>] generic_make_request+0x24/0x2b0
Jun 28 21:03:48 master kernel:  [<ffffffff8130826e>] submit_bio+0x6e/0x140
Jun 28 21:03:48 master kernel:  [<ffffffffa037e295>] run_scheduled_bios+0x225/0x510 [btrfs]
Jun 28 21:03:48 master kernel:  [<ffffffffa038932d>] normal_work_helper+0xcd/0x340 [btrfs]
Jun 28 21:03:48 master kernel:  [<ffffffff81098f65>] process_one_work+0x155/0x440
Jun 28 21:03:48 master kernel:  [<ffffffff81099aa6>] worker_thread+0x116/0x4b0
Jun 28 21:03:48 master kernel:  [<ffffffff8109f0b2>] kthread+0xd2/0xf0
Jun 28 21:03:48 master kernel:  [<ffffffff8163074f>] ret_from_fork+0x3f/0x70
Jun 28 21:03:48 master kernel: DWARF2 unwinder stuck at ret_from_fork+0x3f/0x70
Jun 28 21:03:48 master kernel:
Jun 28 21:03:48 master kernel: Leftover inexact backtrace:
Jun 28 21:03:48 master kernel:  [<ffffffff8109efe0>] ? kthread_park+0x50/0x50
Jun 28 21:03:48 master kernel: BTRFS error (device sda2): bdev /dev/sda2 errs: wr 20, rd 0, flush 0, corrupt 0, gen 0
```

#Z 参考情報
[Debug Hacks -デバッグを極めるテクニック&ツール](https://www.amazon.co.jp/Debug-Hacks-%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%82%92%E6%A5%B5%E3%82%81%E3%82%8B%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-%E3%83%84%E3%83%BC%E3%83%AB-%E5%90%89%E5%B2%A1/dp/4873114047)