Lions' 本読み (129)

朝の続き。breada 手続きについてもう少しきちんと確認して b*write 手続き確認の方向。その他もろもろまで云々できるかどうかは不明です。

breada 手続き

ええと

  • dev, blkno が incore だった場合、bread を呼び出してその戻りを戻す
    • キャッシュに残っていないかも、を考慮して bread 呼び出しと類推
  • dev, blkno が incore でなかった場合、getblk でバッファ確保して b_flags が B_DONE でなければ読み込みリクエストを kickoff
    • 処理完了するまで待合せて終了

というのが読み込み対象のブロックに関する処理になっている模様。ここも朝読みきれていなかったですね。また、先読みの部分については incore でなかった場合に

  • getblk でバッファ確保
  • 確保したバッファの b_flags が B_DONE であれば brelase する
    • む、何だこれ。

細かく見始めるとキリが無いですね。手続きの記述としては以下なカンジ。

4788    if (rablkno && !incore(dev, rablkno)) {
4789            rabp = getblk(dev, rablkno);
4790            if (rabp->b_flags & B_DONE)
4791                    brelse(rabp);

つうか、incore ではなかったけど getblk したら B_DONE だった、というのはどーゆー状態なのかがイメージできぬ。つうか、dev, blkno な処理でも b_flags が B_DONE なら云々なソレがありますね。

4781            rbp = getblk(dev, blkno);
4782            if ((rbp->b_flags&B_DONE) == 0) {
4783                    rbp->b_flags =| B_DONE;
4784                    rbp->b_wcount = -256;
4785                    (*bdevsw[adev.d_major].d_strategy)(rbp);

ここでも incore ではなかったけど、getblk したら B_DONE だった、という形。ちなみに B_DONE というソレを b_flags に立てるのは

  • bdwrite 手続き (遅延書き込み)
  • iodone 手続き (rkintr 手続きから呼び出し)

のみ、な模様。明示的に B_DONE をオトしているのは bwrite 手続きのみに見えます。その後むむむと言いつつテキストをニラんでいたのですが、386p にフラグに関する記述がありますね。

バッファの内容が、ディスク上に格納されている情報、もしくは格納されるはずの情報を正確に反映しているならば、B_DONE フラグをオンにする。

Lions' Commentary on UNIX より引用
なるほど。とりあえず今はあまり深く考えるのは止めておこ。
バッファの状態が最新であれば、ドライバに読み込みリクエストを kickoff する必要はないし、先読み処理対象のバッファの場合は一旦 av_ なリストに置いておくのか。av_ なリストにあるけれど、incore になってる状態?
あ、一旦 brelse するのはそのバッファを待ってる人がいるかも、という配慮があったりするのかどうか。
このあたり色々な意味できちんと辻褄があっているような気がしてくるのでとても面白い、という言い方は不謹慎なのかどうなのか。

もう一つ

B_ASYNC フラグを立てて読み込みリクエストをドライバに投げるとどうなるか、というとどうも iodone の時に同様に brelse されてますね。

5027    if (rbp->b_flags&B_ASYNC)
5028            brelse(rbp);

release とは言え、av_ なリストに追加して欲しい人はどうぞ、と言ってるだけで、実際 b_ なリストには残りっぱなので、という理解で良いのかどうか。
このあたりの微妙なカンジはなんというか芸術的ですね。素晴しい。b_flags 中心にねぶり回してみる、ということもしてみたいです。