DM-cache
先日、ここに書いたFlashcacheはdm-cacheというキャッシュ機構をベースにしているのだが、こちらの方が実装がより簡素だったのでこちらを読むことにする。
dm-cache
このソフトは名前の通りdevice mapperの仕組みを使ってブロックデバイスを別のブロックデバイスでキャッシュをしようというもの。主たる目的としてはSAN、iSCSIやAoEなんかのアクセスコスト(あるいはレイテンシが大きい)の高いストレージをDASでキャッシュして高速化しようというもののようだ。
実装はヘッダファイルすら分れていないCのコードで、コメントも含めて2000行未満という非常にコンパクト。これならば読めるかなと
初期化
dm_cache_init
コンストラクタ
モジュールロード時じゃなく、実際にdevice mapperでセットアップされたときに実行
デストラクタ
マッパー
device mapper周りはほとんど初見なので大きく外しているかもしれないが、ブロックデバイスに対する操作は一元的にここが呼ばれるみたい。
device mapperはマッパーというだけあって、あるデバイスへの操作を別の操作に写像する機能を作るための仕組み。
linux-2.6/drivers/md以下に実装があって、dm-linear.cが凄くシンプルだった。マッパー内で処理が完結したか、向け直した先で継続するかは戻り値で判断しているみたい(読んでない)で、以下のような宣言があった。
/* * Definitions of return values from target map function. */ #define DM_MAPIO_SUBMITTED 0 #define DM_MAPIO_REMAPPED 1 #define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE
ただ、dm-cacheではこの宣言は使っておらず定数がハードコードされていた。
lookup処理
- キャッシュはセットアソシアティブ方式で管理されているので、連想数だけ線形探索
- 対象ブロックを保持しているキャッシュを見付けたら抜ける
- LRUで置き換え候補用に古いエントリも調べつつ
- ヒットしていたら1
- ミス(かwriteback)だったら置き換えるブロックを返す
ヒット時
- 読み込み
- キャッシュが有効なら向け直して終わり
- それ以外なら自力でBIOを発行し、I/O処理を完結
- 書き込み
- ライトスルーならデータを無効化、向け直して、リマップとして抜ける
- 以降はライトバック時
- キャッシュ状態をダーティに
- ライトバック中、データがまだ無いなら自力でBIOをリストに繋いでI/O処理を完結
- それ以外ならキャッシュデバイスに向けて、マップ処理を抜ける
ライトバック
write_back()
キャッシュから対象ブロックデバイスに書き戻して、キャッシュをクリーンにする
もしかして、キャッシュが一杯になるまで処理が実行されない?
遅延処理
do_work()
リストに繋がれた3つの処理を実行するkernel thread。完了したI/Oの後の辻褄合わせ、ページ取得が必要なI/O、実際のI/Oの3つ。
いずれもI/Oの先はasync処理になっている
スーパーブロック的な構造体
cache contextを保持するstruct cache_cがそれか
キャッシュエントリ毎の情報
inode的な情報cacheblock構造体
Flashcacheとの違い
- エラー処理が適当
- ダーティページの書き戻し処理
- 非同期I/O周りが簡素
- I/Oをまとめて処理する機構がない
雑感とか
- キャッシュのセット内はわりと素朴な線形探索
- キャッシュ容量に対してメモリ上に保持する情報が結構大きくないかな?こんなもん?
- ライトバックが必要な状態で書き戻しが間に合わないうちに更にリクエストが来たら詰まるような
- ライトスルー時にキャッシュに乗せる処理はしないのね。I/O完了を待ち合わせとか面倒だからかな
- dmのブロック算出用のマクロがちょっと混乱しそうになる