if (dirtiness.is_dirty)
io_res = writeback_mb(wb, res.found_seg, res.found_mb, dirtiness.data_bits, true);
if (!io_res)
if (mark_clean_mb(wb, res.found_mb))
dec_nr_dirty_caches(wb);
この, mbをクリーンしてnr dirty cachesをdecするパスはunlikelyなのでそもそもあまり価値がないから削除してもいい
2.2.0では, 危険. 同じパスに二度入ったことを考えると, 2回目では, HDDにデータがライトバックされていないにも関わらずdirtyではなくなっておりHDDのデータのみが採用される. (従って部分的に古くなる)
現状でも, SSDにフルヒットしたパスはio_resに依存していない. io_resに依存してるものを先にガードで省いてしまう方がコードとしてクリア これはリファクタリングの範疇
これはライトパスを一切いじらないでも安全 なのでまずリードからやって2.1.3とする?(リリースのことを考えると, クリティカルでなければあまり細かいリリースはしない方がいいか?)
リードパスでトータル1日という感じ (形を変えるのはすぐだが, データの合成などを実装するため. わざと実装を誤って, 回帰テストがコケるかどうか見るという手はある. 回帰テストがここをカバーしているかどうかを見るため)
prepare_overwrite内でデータの合成を行ったあと, いきなりmetadataをmark cleanしてしまうのは危険.
if (mark_clean_mb(wb, old_mb))
dec_nr_dirty_caches(wb);
ht_del(wb, old_mb);
もし, このスレッドがRAM bufferに書き込む前に突然死したあとに同キャッシュをreadすると, キャッシュヒット出来ない. (こんなケースが存在するかは不明)
まともな言語で書くならば書いたあとのcallbackとして書くところ (ただし, 参照を持ち続けるため, 良いともいえない)
このうち, ht_delは, 後に新しいブロックに書くために絶対に必要. (書く前にht_registerする仕組みになってるので, ここは棄てるしかないかもしれない) (書いてしまったあとにhtが重複するのもおかしいので, ht_delとregisterをatomicに出来ないならばしょうがない)
ライトパスでデータの合成を行うと,
新しいmbを登録したあと, それをtaintする書き込む前にreadした場合, わけのわからないデータを読みこむことになる潜在バグがありそう. これは全くの新規ライトの場合でもありうる. (古いやつをreplaceするかどうかは関係ないと思う)
安全に行くならば, write_on_rambufferまでmutexで囲むことだが, 性能が落ちる.
今は, mutexの中でHDDにライトバックしてしまうということが救いになってる. 今のままだと, あるブロックに対してライトしてる時は(超一瞬だが)状態が不定ということになりうる.
ht_register(wb, res.head, ret, &res.key);
mutex_unlock(&wb->io_lock);
return ret;
}
/*
* Write bio data to RAM buffer.
*/
static int do_process_write(struct wb_device *wb, struct metablock *write_pos, struct bio *bio)
{
if (taint_mb(wb, write_pos, bio))
inc_nr_dirty_caches(wb);
write_on_rambuffer(wb, write_pos, bio);
まずはReadからやる. Readの変更は単純に設計改善に相当するので, この時点で回帰テストは動作する. Readからやる理由はWriteよりは変更が小さい(ロックの変更がない)というのと, Readに関してSUBMITTEDで返すことが正しいかどうか判断出来ないから.
- バッファをbioのbvecにコピーする汎用関数を作る
- フローを組み替えてテスト
- データ合成をon buffer hit, on ssd hitのケースで実装してそれぞれ回帰テスト. ここでは上記関数をいじって, 敢えてバグるようにして(バイトずれとか), 回帰テストが有効化をあぶり出す
- リファクタリング. ここでReadに関してfixする. 動くならばdevelopにマージする.
実は,
この区間は, writeのための準備期間と考えて, readlockで包めないかな?
その後の部分だけをwrite lockで包む