Stack Overflow と Server Fault には、これに対する優れた回答が既にありますが、いくつかの手法が欠けていました。作業を楽にするために、VM/Linux ブロック デバイス/Linux ファイルシステム/Linux ユーザー空間ライブラリ I/O 障害挿入メカニズムのリストを次に示します。
- Device Mapper の error/flakey/delay/dm-dust デバイスを使用して、合成済みブロック デバイスからのエラー/破損を返したり、IO を遅延/分割したりします (カーネル、カーネルがデバイス マッパー サポートで構築されている必要があり、適切な追加デバイスマッパー モジュール (dm-dust はカーネル>=5.2 でのみ使用可能) であり、デバイス マッパー ユーザー空間ビットを備えています)。
- md のフォールト パーソナリティを使用して、合成されたブロック デバイスに対して定期的なフォールト インジェクションを実行します。
--layout
を参照してください 構成方法については、mdadm man ページのオプションを参照してください (カーネルおよび mdadm ユーザー空間ビット)。 - libfiu を使用して、POSIX API 呼び出しでフォールト挿入を実行します (ユーザー空間、
LD_PRELOAD
で使用できます) ). - Linux カーネルのフォールト インジェクターを使用して、基盤となるブロック デバイスにエラーを挿入します (カーネル、カーネルが
FAIL_MAKE_REQUEST=y
でビルドされている必要があります)。 ). - SystemTap を使用してフォールト インジェクションを実行します (カーネル。カーネルには多くの要素が組み込まれている必要があります)。
- CarybdeFS または PetardFS (FUSE 経由のユーザー空間) を使用して、ファイル システムの障害を挿入します。
- フォールト インジェクション (カーネル) を実行する Linux scsi_debug ドライバーを使用して、合成ブロック デバイスを作成します。
- QEMU 内でシステムを実行し、QEMU を使用して、blkdebug ドライバー (VM) を使用してブロック デバイス エラーを挿入します。
- null_blk デバイスのオプションを使用して合成ブロック デバイスを作成し、障害を挿入します (カーネル>=4.14 ですが、タイムアウト確率などのオプションは 4.17 まで到着せず、カーネルが
BLK_DEV_NULL_BLK_FAULT_INJECTION=y
でビルドされている必要があります。 ). delay
などの NBDkit フィルターを介してホストに提供される、合成されたネットワーク ブロック デバイスを作成します。 またはerror
nbd-client
経由でブロック デバイスを接続します。 (カーネル + NBD ユーザー空間ビット、NBD サポート付きでビルドされたカーネル>=4.18、nbdclient>=3.18 および nbdkit>=1.8.1 を推奨 - 20 分前後の NBDKit デモ ビデオを参照してください)。
おまけ:SQLite にはエラーをシミュレートするための VFS ドライバーがあるため、テスト範囲を広げることができます。
関連:
- テスト中に故障したディスクをシミュレートするにはどうすればよいですか?
- 読み取りエラーのある障害のあるブロック デバイスをシミュレートしますか?
- 読み取りエラーを生成する
- Linux で意図的に I/O エラーを引き起こしますか?
dmsetup
を使用できます error
のいずれかを使用してデバイス マッパー デバイスを作成します。 または flakey
失敗をシミュレートするターゲット。
dmsetup create test --table '0 123 flakey 1 0 /dev/loop0'
ここで、123 はデバイスの長さ (セクター単位) で、/dev/loop0 はエラーをシミュレートする元のデバイスです。エラーの場合、常にエラーを返すため、後続の引数は必要ありません。
I/O のフォールト注入メカニズムが必要です。
Linux では、事前のセットアップを必要とせず、異常なエラーを生成する方法を次に示します (EIO 「入出力エラー」ではなく、ESRCH 「そのようなプロセスはありません」)。
cat /proc/1234/mem
ここで、1234 は、テストしているプロセスと同じユーザーとして実行されているプロセスの PID ですが、そのプロセス自体ではありません。 /proc/$pid/mem
を考えてくれた rubasov の功績 .
プロセス自体の PID を使用すると、EIO を取得できますが、プロセスのメモリにマップされていない領域から読み取っている場合に限ります。最初のページはマップされないため、ファイルを順番に読み取る場合は問題ありませんが、ファイルの途中を直接シークするデータベース プロセスには適していません。
root としてさらにセットアップを行うと、デバイス マッパーを利用して、有効なセクターと不良セクターを含むファイルを作成できます。
もう 1 つのアプローチは、小さな FUSE ファイルシステムを実装することです。 EIO は、ユーザー空間のファイルシステム ドライバーが何か問題を起こした場合のデフォルトのエラー コードであるため、簡単に達成できます。 Perl と Python の両方のバインディングには、開始するための例が付属しています。既存のファイルをほとんどミラーリングしながら、慎重に選択した場所に EIO を挿入するファイルシステムをすばやく作成できます。既存のそのようなファイルシステム:petardfs (記事) がありますが、すぐに使えるかどうかはわかりません。
さらに別の方法は LD_PRELOAD
です ラッパー。既存のものは Libfiu (ユーザー空間でのフォールト インジェクション) です。これは、POSIX API 呼び出しをオーバーロードするライブラリをプリロードすることによって機能します。単純なディレクティブまたは任意の C コードを記述して、通常の動作をオーバーライドできます。