Lions' 本読み (132)

b_flags 属性で xref の続き。notavail 手続きから確認再開。

notavail 手続き

割り込み禁止区間の中で av_ なリストから取り除き、状態に B_BUSY を追加しています。

5008    rbp->av_back->av_forw = rbp->av_forw;
5009    rbp->av_forw->av_back = rbp->av_back;
5010    rbp->b_flags =| B_BUSY;

iodone 手続き

__バッファに対して I/O 完了をマーク_する手続きなので色々な操作が入っています。

  • B_MAP な状態の場合
    • mapfree 手続きを呼び出す
    • 現時点ではスルー (別途確認)
  • B_DONE な状態を追加
  • B_ASYNC な状態の場合
    • brelse 手続きを呼び出してバッファ解放
  • 最後に B_WANTED を b_flags から取り除いて wakeup 手続きを呼び出しています

手続き引用は略。iodone で B_ASYNC 以外は漏れなく wakeup というあたりもアレです。

binit 手続き

初期処理においては全ての要素について b_flags は B_BUSY で初期化されます。

devstart 手続き

バッファの b_flags 属性はコマンド発行時の読み込みか書き込みかの判断に使われています。基本的に B_READ なら読み込みでそれ以外は書き込み、という形。

5111    if (rbp->b_flags&B_READ)
5112            com =| RCOM;
5113    else
5114            com =| WCOM;

これは RH コントローラ用スタートアップルーチンの rhstart でも同様。

5140    if (rbp->b_flags&B_READ)
5141            com =| RHRCOM; else
5142            com =| RHWCOM;

あと map{alloc, free} および swap についてはスルーします。

bflush 手続き

ここ、未確認でした。update という手続きから呼び出される模様。av_ なリストを順に手繰ってバッファの b_flags な属性が遅延書き込みな状態について

5239                    bp->b_flags =| B_ASYNC;
5240                    notavail(bp);
5241                    bwrite(bp);
5242                    goto loop;

ということをしている模様。B_ASYNC を立てて bwrite すると処理完了待ちをしないですね。あと、notavail で av_ なリストから除去しているので 5242 な goto で再度繰り返しをやり直しています。むむむむ的。
次の physio 手続きと geterror 手続きもスルー。

rkstrategy 手続き

ちょっとだけ。mapalloc 手続きがでてきてますね。

5397    if(bp->b_flags&B_PHYS)
5398            mapalloc(bp);

B_PHYS て何だろ。
そしてこれ以降は基本的に B_ERROR なチェックばかりな模様ですのでスルーします。

まとめ

  • 読み込み
    • getblk して B_DONE な状態であれば何もしなくて良い
    • それ以外はドライバに読み込みを依頼
      • b_flags に B_READ を立てておけば読み込んでくれる
    • 先行読み出しについては B_ASYNC を立てておいて読み込み完了後、av_ なリストに格納
      • 読み込まれたバッファは b_ なリストにも含まれているので次の getblk で発見されて notavail される
      • 先行読み出しで B_DONE なバッファについても av_ に格納
  • 書き込み
    • bwrite において b_flags から B_READ、B_DONE、B_ERROR、B_DELWRI が落とされる
    • bwrite では B_ASYNC な状態以外は I/O 完了を待つ
    • B_ASYNC がオンであれば B_DELWRI はオンになっている前提がある模様
      • 少なくとも bflush から bwrite する時は両方オン
    • bdwrite (遅延書き込み) においては該当バッファの b_flags を B_DELWRI と B_DONE にして av_ なリストに追加する
      • B_DONE は_ディスク上に格納されている情報、もしくは格納されるはずの情報を正確に反映している_状態
      • B_DELWRI は_バッファの内容は対応するディスクブロックの内容よりも新しい_状態
    • bawrite は非同期書き込みなので b_flags に B_ASYNC を追加して bwrite 手続きを呼び出すのみ
  • バッファ解放
    • 解放に伴い、解放されたバッファが B_WANTED だった場合、wakeup 手続きを呼び出す
    • 同様に bfreelist が空になっている場合も wakeup 手続きを呼び出す
    • 4882、4883 の処理は確認必要
    • バッファを av_ なリストに戻す時、b_flags からは B_WANTED、B_BUSY、B_ASYNC が取り除かれる
  • getblk
    • incore 的探索において処理対象となるブロックのバッファが発見されたがその状態が B_BUSY だった場合、b_flags に B_WANTED を追加して sleep する
      • bfreelist が空の場合も同様
    • av_ リストから取り出したバッファの状態が B_DELWRI だった場合は非同期書き込みなリクエストを発行する
      • ここでも B_DELWRI と B_ASYNC が両方、な状態になりますね
      • incore な探索をしている間に書き込みが終わると類推
    • av_ リストから確保されたバッファの b_flags は B_BUSY と B_RELOC で上書きの形で初期化される
  • I/O 完了待ち
    • 該当バッファの状態が B_DONE になるまで sleep
  • av_ リストからの除去
    • 該当バッファの b_flags に B_BUSY が追加される
  • I/O 完了処理
    • I/O 完了で該当バッファの b_flags には B_DONE が追加され、B_WANTED は取り除かれて wakeup 手続きが呼び出される
    • B_MAP の場合、mapfree 手続きが呼び出される
    • B_ASYNC の場合、該当バッファは av_ なリストに追加される
  • 初期処理
    • バッファの状態は B_BUSY で初期化される

宿題

備忘まで以下に列挙。

  • breada 手続きの先読みのあたりで、brelse でバッファ解放される部分
    • 非同期 I/O の場合、バッファ解放するあたりの意図の理解、と言えば良いかどうか
  • map{alloc, free} のあたり、何なのか確認のこと
  • physio および geterror 手続きも確認必要
  • 4882、4883 の処理は確認必要