device-mapper を使って途中からI/O Error を起こす

device-mapper を使ってデバッグ用にエラーを返すファイルシステムを作ったので関連コマンドをメモしておく。

保存するファイルを準備する

ループバックデバイスへの書き込みを受け取るファイルを準備しておく。

1
2
3
4
$ dd if=/dev/zero of=./test.img bs=1024 count=20000
20000+0 records in
20000+0 records out
20480000 bytes (20 MB) copied, 0.0207247 s, 988 MB/s

ループバックデバイス作成

ループバックデバイスを使って最初のファイルに書き込み口を作る。 ループバックデバイスは /dev/loop<N> に作られる。

1
2
3
4
5
6
# 空いている最初ループバックデバイスを調べる
$ sudo losetup -f
/dev/loop0
$ sudo losetup $(sudo losetup -f) ./test.img
$ sudo losetup /dev/loop0
/dev/loop0: [fc01]:2237716 (/home/masumi...)

ループバックデバイス上にext4を初期化

ext4(ジャーナリング有効(デフォルトだけど))を作ってみる。

1
2
# ファイルシステム作成
$ sudo mkfs -t ext4 -O has_journal /dev/loop0

Errorを起こすデバイスを作る

1
2
3
4
5
6
$ tmp_index=$(expr $(sudo blockdev --getsize /dev/loop0) \- 300); cat <<EOMAP | sudo dmsetup create test_linear; unset tmp_index
0 ${tmp_index} linear /dev/loop0 0
${tmp_index} 300 error
EOMAP
$ ls /dev/mapper
centos-root  centos-swap  control      test_linear

マウントする

ここではtouchでサイズ0のファイルを作っている。デバイスイメージの後半300セクタがErrorデバイスとなりI/O Errorが生じるため、大き目なファイルを作ると失敗する可能性がある。 ただ手元ではext4でジャーナルをしているのに成功してしまう事が多発した。

1
2
$ sudo mount /dev/test_linear ./test.mount.point
$ touch ./test.mount.point/test.file

後処理をする

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# アンマウント
$ sudo umount ./test.mount.point
# マップデバイスの削除
$ sudo dmsetup remove /dev/mapper/test_linear
# デバイスマップの存在確認
$ sudo dmsetup ls

# 使えるようになったループバックデバイスをマウント
$ sudo mount /dev/loop0 ./test.mount.point
$ ls ./test.mount.point
./test.file
# アンマウント
$ sudo umount ./test.mount.point
# ループバックデバイスの破棄
$ sudo losetup -d /dev/loop0
$ sudo losetup -f # 消えているか確認する
/dev/loop0

参考資料

他にもsnapshot デバイスなど面白そうなものもある。

comments powered by Disqus