Upgrade to Pro — share decks privately, control downloads, hide ads and more …

device mapperによるディスクI/O障害のエミュレーション 既存ターゲット編

device mapperによるディスクI/O障害のエミュレーション 既存ターゲット編

以下動画のテキストです
https://youtu.be/8Mbd31KHDR4

Satoru Takeuchi

December 11, 2023
Tweet

More Decks by Satoru Takeuchi

Other Decks in Technology

Transcript

  1. 壊れたときのためにエラー処理がある • I/Oのリトライ ◦ 一時的に起きてすぐ解消することもある • データの破壊検知、修復 • ユーザに対処を任せる 4

    disk ソフトウェア 何らかの異常 対処 理想 • I/Oが最終的に成功する • I/Oが失敗を返して対処がゆだねられる
  2. device mapper • ブロックデバイスに機能追加するためのLinuxカーネルの仕組み • 用語 ◦ ターゲット: device mapperの個々の機能

    ▪ 暗号化、マルチパス化、 ディスク障害エミュレーション など ◦ dmデバイス: device mapperが作るブロックデバイス • 基本はdmsetupコマンドで制御 6 /dev/sda /dev/mapper/<dm device name> 書き込み 書き込み+α 読み出し 読み出し+α
  3. dmsetupのつかいかた • dmデバイスとマップ先デバイスを対応付けるテーブルを作る • dmデバイスを作る • dmデバイスの挙動を動的に変更する 7 $ cat

    table.txt <開始セクタ> <長さ> <ターゲット名> <マップ先デバイス> [<パラメタ>...] ... $ sudo dmsetup create <dmデバイス名> <テーブルファイル> $ ls /dev/mapper/ … <dmデバイス名> … 1セクタ=512バイト $ sudo dmsetup message <dmデバイス名> 0 <コマンド> [<パラメタ>...]
  4. dm-delay • I/Oを遅延させる • テーブルの形式 10 <開始セクタ> <長さ> delay <マップ先デバイス>

    <マップ先開始セクタ > <遅延[ms]> dm-delay disk write 遅延を入れてからwrite read 遅延を入れてからread
  5. 使用例 11 $ sudo dd if=/dev/zero of=/dev/loop0 bs=1M count=1024 oflag=direct

    … 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.615917 s, 1.7 GB/s 通常時のスループットを確認(後で遅延を入れた場合と比較)
  6. 使用例 12 $ sudo dd if=/dev/zero of=/dev/loop0 bs=1M count=1024 oflag=direct

    … 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.615917 s, 1.7 GB/s 通常時のスループットを確認(後で遅延を入れた場合と比較) $ cat test-delay.txt 0 2097152 delay /dev/loop0 0 10 $ sudo dmsetup create test-delay test-delay.txt dmデバイスの作成
  7. 使用例 13 $ sudo dd if=/dev/zero of=/dev/mapper/test-delay bs=1M count=1024 oflag=direct

    $ sudo dd if=/dev/zero of=/dev/loop0 bs=1M count=1024 oflag=direct … 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.615917 s, 1.7 GB/s 通常時のスループットを確認(後で遅延を入れた場合と比較) $ cat test-delay.txt 0 2097152 delay /dev/loop0 0 10 $ sudo dmsetup create test-delay test-delay.txt dmデバイスの作成 dmデバイスにwrite
  8. 使用例 14 $ sudo dd if=/dev/zero of=/dev/mapper/test-delay bs=1M count=1024 oflag=direct

    … 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 16.4044 s, 65.5 MB/s $ sudo dd if=/dev/zero of=/dev/loop0 bs=1M count=1024 oflag=direct … 1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.615917 s, 1.7 GB/s 通常時のスループットを確認(後で遅延を入れた場合と比較) $ cat test-delay.txt 0 2097152 delay /dev/loop0 0 10 $ sudo dmsetup create test-delay test-delay.txt dmデバイスの作成 dmデバイスにwrite すごく遅くなった
  9. dm-flakey • I/Oエラーを一定間隔で発生させる • テーブルの形式 16 <開始セクタ> <長さ> flakey <マップ対象デバイス>

    <マップ先開始セクタ> <成功期間> <失敗期間> dm-delay disk write write(たまに失敗) read read(たまに失敗)
  10. 使用例 17 $ cat test-flakey.txt 0 2097152 flakey /dev/loop0 0

    2 2 $ sudo dmsetup create test-flakey test-flakey.txt dmデバイスの作成 2秒間の正常動作後 2秒間I/Oエラーを出す
  11. 使用例 18 $ cat test-flakey.txt 0 2097152 flakey /dev/loop0 0

    2 2 $ sudo dmsetup create test-flakey test-flakey.txt $ sudo bash -c 'for ((i=0;i<10;i++)) ; do dd if=/dev/mapper/test-flakey of=/dev/null bs=128 count=1 sleep 1 done' dmデバイスの作成 dmデバイスから1秒に1回read
  12. 使用例 19 $ cat test-flakey.txt 0 2097152 flakey /dev/loop0 0

    2 2 $ sudo dmsetup create test-flakey test-flakey.txt $ sudo bash -c 'for ((i=0;i<10;i++)) ; do dd if=/dev/mapper/test-flakey of=/dev/null bs=128 count=1 sleep 1 done' ... 128 bytes copied, 0.000198435 s, 645 kB/s dd: error reading '/dev/mapper/test-flakey': Input/output error ... dd: error reading '/dev/mapper/test-flakey': Input/output error ... 128 bytes copied, 0.000169802 s, 754 kB/s ... 128 bytes copied, 0.000224296 s, 571 kB/s dd: error reading '/dev/mapper/test-flakey': Input/output error ... dmデバイスの作成 dmデバイスから1秒に1回read 仕様通りに動作
  13. dm-flakey上でファイルシステムを作ると… 20 $ sudo mkfs.ext4 -F /dev/loop0 $ sudo dmsetup

    create test-flakey test-flakey.txt $ mount /dev/mapper/test-flakey mnt ファイルシステムが存在するデバイス上にdmデバイスを作成
  14. dm-flakey上でファイルシステムを作ると… 21 $ for ((i=0;i<10;i++)) ; do sudo dd if=/dev/zero

    of=mnt/test.txt bs=1 count=1 oflag=direct sleep 1 done $ sudo mkfs.ext4 -F /dev/loop0 $ sudo dmsetup create test-flakey test-flakey.txt $ mount /dev/mapper/test-flakey mnt ファイルシステムが存在するデバイス上にdmデバイスを作成 ファイルシステム上のファイルに1秒に1回write
  15. dm-flakey上でファイルシステムを作ると… 22 $ for ((i=0;i<10;i++)) ; do sudo dd if=/dev/zero

    of=mnt/test.txt bs=1 count=1 oflag=direct sleep 1 done dd: failed to open 'mnt/test.txt': Input/output error dd: failed to open 'mnt/test.txt': Input/output error dd: failed to open 'mnt/test.txt': Read-only file system … ファイルシステムが存在するデバイス上にdmデバイスを作成 ファイルシステム上のファイルに1秒に1回write すぐにread onlyに $ sudo mkfs.ext4 -F /dev/loop0 $ sudo dmsetup create test-flakey test-flakey.txt $ mount /dev/mapper/test-flakey mnt
  16. カーネルログを見ると… 23 $ sudo dmesg … [10912.976026] EXT4-fs error (device

    dm-0): ext4_journal_check_start:83: comm dd: Detected aborted journal [10912.991408] EXT4-fs (dm-0): Remounting filesystem read-only • ext4はデータが存在するデバイスの挙動が怪しいとreadonlyでremountする ◦ 他のファイルシステムもこのようなフェイルセーフのしくみがある • 📝 dm-flakeyをファイルシステム上のI/Oエラーのエミュレーションに使うのは面倒 ジャーナル処理も失敗
  17. dm-dustの主なメッセージ • 機能の有効化/無効化(デフォルトは無効) • 指定したセクタを疑似不良ブロックにする • 指定したブロックを疑似不良ブロックではなくする • 疑似不良ブロックのリスト ◦

    26 $ sudo dmsetup message <dmデバイス名> 0 addbadblock <ブロック番号> [修復前にI/Oが失敗する回数] $ sudo dmsetup message <dmデバイス名> 0 removebadblock <ブロック番号> $ sudo dmsetup message <dmデバイス名> 0 {enable,disable} $ sudo dmsetup message <dmデバイス名> 0 listbadblocks <ブロック番号>
  18. dm-dustを使う前の準備 • kernel 5.15.0-89-genericではdm-dustは無効化されている • 自前ビルドすれば使える 27 $ git clone

    https://github.com/satoru-takeuchi/youtube-sample $ cd youtube-sample/0063-dm-io-failures-existing-targets $ make -C kernel-modules $ sudo insmod kernel-modules/dm-dust.ko
  19. 使用例 28 $ cat test-dust.txt 0 2097152 dust /dev/loop0 0

    512 $ sudo dmsetup create test-dust test-dust.txt $ sudo dmsetup message test-dust 0 enable $ sudo dmsetup message test-dust 0 addbadblock 0 1 dmデバイスの作成&設定 セクタ0にアクセスすると • readは失敗する • 1回目のwriteは失敗する • 2回目のwriteで不良セクタが消える
  20. 使用例 29 $ cat test-dust.txt 0 2097152 dust /dev/loop0 0

    512 $ sudo dmsetup create test-dust test-dust.txt $ sudo dmsetup message test-dust 0 enable $ sudo dmsetup message test-dust 0 addbadblock 0 1 dmデバイスの作成&設定 セクタ0にアクセスすると • readは失敗する • 1回目のwriteは失敗する • 2回目のwriteで不良セクタが消える $ sudo dd if=/dev/mapper/test-dust of=/dev/null bs=512 count=1 不良ブロックからread
  21. 使用例 30 $ cat test-dust.txt 0 2097152 dust /dev/loop0 0

    512 $ sudo dmsetup create test-dust test-dust.txt $ sudo dmsetup message test-dust 0 enable $ sudo dmsetup message test-dust 0 addbadblock 0 1 $ sudo dd if=/dev/mapper/test-dust of=/dev/null bs=512 count=1 dd: error reading '/dev/mapper/test-dust': Input/output error … dmデバイスの作成&設定 不良blockからのread セクタ0にアクセスすると • readは失敗する • 1回目のwriteは失敗する • 2回目のwriteで不良セクタが消える
  22. 使用例 31 $ cat test-dust.txt 0 2097152 dust /dev/loop0 0

    512 $ sudo dmsetup create test-dust test-dust.txt $ sudo dmsetup message test-dust 0 enable $ sudo dmsetup message test-dust 0 addbadblock 0 1 $ sudo dd if=/dev/mapper/test-dust of=/dev/null bs=512 count=1 dd: error reading '/dev/mapper/test-dust': Input/output error … $ sudo dd if=/dev/zero of=/dev/mapper/test-dust bs=512 count=1 oflag=direct,dsync dd: error writing '/dev/mapper/test-dust': Input/output error … dmデバイスの作成&設定 不良blockへのwrite セクタ0にアクセスすると • readは失敗する • 1回目のwriteは失敗する • 2回目のwriteで不良セクタが消える
  23. 使用例 32 $ cat test-dust.txt 0 2097152 dust /dev/loop0 0

    512 $ sudo dmsetup create test-dust test-dust.txt $ sudo dmsetup message test-dust 0 enable $ sudo dmsetup message test-dust 0 addbadblock 0 1 $ sudo dd if=/dev/mapper/test-dust of=/dev/null bs=512 count=1 dd: error reading '/dev/mapper/test-dust': Input/output error … $ sudo dd if=/dev/zero of=/dev/mapper/test-dust bs=512 count=1 oflag=direct,dsync dd: error writing '/dev/mapper/test-dust': Input/output error … $ sudo dd if=/dev/zero of=/dev/mapper/test-dust bs=512 count=1 oflag=direct,dsync … 512 bytes copied, 0.0134639 s, 38.0 kB/s dmデバイスの作成&設定 不良ブロックへの2度目のwrite セクタ0にアクセスすると • readは失敗する • 1回目のwriteは失敗する • 2回目のwriteで不良セクタが消える
  24. ioctl(FS_IOC_FIEMAP)を使えばわかる • ファイルとextent、extentとブロックの対応が得るためのioctl() • xfs_io -c fiemapコマンドを介して手軽に使える 34 $ xfs_io

    -c fiemap test.txt test.txt: 0: [0..7]: 266240..266247 test.txtの先頭領域を含むextentは ファイルシステムの下にあるブロックデバイスの セクタ266240~266247に存在する
  25. 使用例 35 $ sudo dmsetup message test-dust 0 enable $

    sudo xfs_io -c fiemap mnt/test.txt mnt/test.txt: 0: [0..7]: 266240..266247 $ sudo dmsetup message test-dust 0 addbadblock 266240 dmデバイス上の作成&設定 test.txtファイル先頭のデータに対応 するセクタを不良セクタにする /dev/loop0 /dev/mapper/test-dust filesystem test.txt
  26. 使用例 36 $ sudo dmsetup message test-dust 0 enable $

    sudo xfs_io -c fiemap mnt/test.txt mnt/test.txt: 0: [0..7]: 266240..266247 $ sudo dmsetup message test-dust 0 addbadblock 266240 $ sudo dd if=mnt/test.txt of=/dev/null bs=512 count=1 iflag=direct dmデバイス上の作成&設定 dmデバイス上のファイルからread /dev/loop0 /dev/mapper/test-dust filesystem test.txt
  27. 使用例 37 $ sudo dmsetup message test-dust 0 enable $

    sudo xfs_io -c fiemap mnt/test.txt mnt/test.txt: 0: [0..7]: 266240..266247 $ sudo dmsetup message test-dust 0 addbadblock 266240 $ sudo dd if=mnt/test.txt of=/dev/null bs=512 count=1 iflag=direct dd: error reading 'mnt/test-dust.txt': Input/output error … dmデバイス上の作成&設定 dmデバイス上のファイルからread /dev/loop0 /dev/mapper/test-dust filesystem test.txt
  28. • CoW型、ログ構造型のファイルシステムではうまく機能しない ◦ 例: Btrfs, NILFS ◦ writeするたびにextentとblockの対応関係が変化 dm-dustと相性の悪いファイルシステム 40

    Btrfs 旧データ 不良ブロック 新データ writeするとデータの場所が変わる dm-dust disk 📝 ファイルシステムはなんでもいいなら ext4などのin-placeな更新をするものを使う