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

ディスクI/O障害のエミュレーション カーネルモジュール自作編

ディスクI/O障害のエミュレーション カーネルモジュール自作編

以下動画のテキストです
https://youtu.be/nbwF9uaw-sQ

Satoru Takeuchi

December 11, 2023
Tweet

More Decks by Satoru Takeuchi

Other Decks in Technology

Transcript

  1. ターゲットをあらわす構造体を作る 4 static struct target_type simple_target = { .name =

    "simple", .version = {0, 0, 1}, .features = DM_TARGET_NOWAIT | DM_TARGET_PASSES_CRYPTO, .module = THIS_MODULE, .ctr = simple_ctr, .dtr = simple_dtr, .map = simple_map, .iterate_devices = simple_iterate_devices, }; dmデバイスのI/Oを下のデバイスに渡す
  2. マップ処理 5 static int simple_map(struct dm_target *ti, struct bio *bio)

    { struct simple_c *sc = ti->private; bio_set_dev(bio, sc->dev->bdev); return DM_MAPIO_REMAPPED; }
  3. マップ処理 6 static int simple_map(struct dm_target *ti, struct bio *bio)

    { struct simple_c *sc = ti->private; bio_set_dev(bio, sc->dev->bdev); return DM_MAPIO_REMAPPED; } 個々のI/Oを管理するデータ • I/Oに使うメモリ領域 • I/O対象デバイス
  4. マップ処理 7 static int simple_map(struct dm_target *ti, struct bio *bio)

    { struct simple_c *sc = ti->private; bio_set_dev(bio, sc->dev->bdev); return DM_MAPIO_REMAPPED; } I/O対象デバイスを マップ先デバイスに書き換え
  5. マップ処理 8 static int simple_map(struct dm_target *ti, struct bio *bio)

    { struct simple_c *sc = ti->private; bio_set_dev(bio, sc->dev->bdev); return DM_MAPIO_REMAPPED; } I/Oをマップ先デバイスに リマップしたことを呼び出し元に伝える
  6. 使用例 9 $ cat test-simple.txt 0 2097152 simple /dev/loop0 $

    sudo dmsetup create test-simple test-simple.txt dmデバイスの作成
  7. 使用例 10 $ cat test-simple.txt 0 2097152 simple /dev/loop0 $

    sudo dmsetup create test-simple test-simple.txt dmデバイスの作成 $ sudo dd if=test-simple.txt of=/dev/mapper/test-simple dmデバイスにwrite
  8. 使用例 11 $ cat test-simple.txt 0 2097152 simple /dev/loop0 $

    sudo dmsetup create test-simple test-simple.txt dmデバイスの作成 dmデバイスにwrite $ sudo dd if=test-simple.txt of=/dev/mapper/test-simple … $ sudo dmsetup remove test-simple $ sudo hexdump -c -n 128 /dev/loop0 0000000 0 2 0 9 7 1 5 2 s i m p l e 0000010 / d e v / l o o p 0 0 \n \0 \0 …
  9. マップ処理 13 static int hello_map(struct dm_target *ti, struct bio *bio)

    {   ... bio_for_each_segment(bvec, bio, iter) { char *segment; struct page *page = bio_iter_page(bio, iter); if (unlikely(page == ZERO_PAGE(0))) break; segment = bvec_kmap_local(&bvec); memcpy(segment, hello, sizeof(hello)); kunmap_local(segment); break; } bio_set_dev(bio, hc->dev->bdev); return DM_MAPIO_REMAPPED; }
  10. マップ処理 14 static int hello_map(struct dm_target *ti, struct bio *bio)

    {   ... bio_for_each_segment(bvec, bio, iter) { char *segment; struct page *page = bio_iter_page(bio, iter); if (unlikely(page == ZERO_PAGE(0))) break; segment = bvec_kmap_local(&bvec); memcpy(segment, hello, sizeof(hello)); kunmap_local(segment); break; } bio_set_dev(bio, hc->dev->bdev); return DM_MAPIO_REMAPPED; } bio内の全領域(データの断片)を走査
  11. マップ処理 15 static int hello_map(struct dm_target *ti, struct bio *bio)

    {   ... bio_for_each_segment(bvec, bio, iter) { char *segment; struct page *page = bio_iter_page(bio, iter); if (unlikely(page == ZERO_PAGE(0))) break; segment = bvec_kmap_local(&bvec); memcpy(segment, hello, sizeof(hello)); kunmap_local(segment); break; } bio_set_dev(bio, hc->dev->bdev); return DM_MAPIO_REMAPPED; } 先頭領域に”Hello!”という文字列を書き込む
  12. マップ処理 16 static int hello_map(struct dm_target *ti, struct bio *bio)

    {   ... bio_for_each_segment(bvec, bio, iter) { char *segment; struct page *page = bio_iter_page(bio, iter); if (unlikely(page == ZERO_PAGE(0))) break; segment = bvec_kmap_local(&bvec); memcpy(segment, hello, sizeof(hello)); kunmap_local(segment); break; } bio_set_dev(bio, hc->dev->bdev); return DM_MAPIO_REMAPPED; } 書き終わったら走査終了 先頭領域以外は触らない
  13. 使用例 17 $ cat test-hello.txt 0 2097152 hello /dev/loop0 $

    sudo dmsetup create test-hello test-hello.txt dmデバイスの作成
  14. 使用例 18 $ cat test-hello.txt 0 2097152 hello /dev/loop0 $

    sudo dmsetup create test-hello test-hello.txt $ sudo dd if=test-hello.txt of=/dev/mapper/test-hello … $ sudo hexdump -c -n 128 /dev/mapper/test-hello dmデバイスの作成 dmデバイスにwrite
  15. 使用例 19 $ cat test-hello.txt 0 2097152 hello /dev/loop0 $

    sudo dmsetup create test-hello test-hello.txt $ sudo dd if=test-hello.txt of=/dev/mapper/test-hello … $ sudo hexdump -c -n 128 /dev/mapper/test-hello 0000000 H e l l o ! \n \0 2 h e l l o 0000010 / d e v / l o o p 0 0 \n \0 \0 \0 … dmデバイスの作成 dmデバイスにwrite データが書き換わった
  16. まとめ • device mapperターゲットの自作により、好きなようにディスクI/O障害をエミュレー ションできる • カーネルモジュールの作り方 ◦ https://github.com/torvalds/linux/blob/master/Documentation/kbuild/modules.rst •

    device mapperのコード ◦ https://github.com/torvalds/linux/blob/master/drivers/md/ • 📝 Rustでdevice mapperのターゲットを書けるようにする試みも ◦ https://lore.kernel.org/lkml/ZJm%2FJfIPMrgXkYpp@boqun-archlinux/T/ 21