ファイルへの書き込みとファイル拡張

writeシステムコールは、vfs sys_write関数にて、ファイルディスクリプタに対応するファイル構造体を見つけ(fget関数)、ファイル構造体に登録されているwriteオペレーションを呼び出す。

ext2ファイルシステムの場合、 通常ファイルではext2_file_write関数が呼び出される。ディレクトリ、シンボリックリンクファイルの場合、このオペレーションは無登録であるため、sys_write処理はエラー終了する。

   ext2_file_write(ファイル構造体、ユーザ領域, ファイルポインタ)
      if(アペンドモードなら) ファイルポインタをファイルエンドにする
      do {
           ファイルブロックに対応したバッファ確保(ext2_getblk関数)
               - ブロックが割り当てられてなければ、自動的に割り当てられる
           if(I/Oサイズがブロックサイズでなく && バッファの中身が無効) {
                ブロックをバッファへ読み込む(ll_rw_block関数, wait_on_buffer関数)
           }
           ユーザ領域のデータをバッファに読み込む(copy_from_user関数)
           ページキャッシュにも書き込み内容を反映(update_vm_cache関数)
           バッファを有効状態にする(mark_buffer_uptodate関数)
           ◇バッファの遅延書き込み要求(mark_buffer_dirty関数)
           if(O_SYNCモードのオープンのとき) {
                if(ある程度バッファが溜まったら) {
                     ◆バッファを同期書き込み(ll_rw_block関数、wait_on_buffer関数)
                     バッファを解放
                }
           } else {
               バッファを解放
           }
      } while(書き込むデータがある間)
      if(O\_SYNCモードのオープンのとき) {
           if(まだ書き込みをしていないバッファにたいして)
                ◆バッファを同期書き込み(ll_rw_block関数、wait_on_buffer関数)
                バッファを解放
           }
      }
      if(ファイル拡張が発生していたら)
          ファイルサイズを変更する(iノードのi_sizeメンバ)
      ファイルポインタを進める
      ◇iノードの遅延書き込み要求(mark_inode_dirty関数)

ネットワークファイルシステムのwriteオペレーションは、generic_file_write関数により、ページキャッシュ経由の書き込みとして実現されるが、それ以外のローカルディスク上のそれぞれが独自のwriteオペレーションを持ち、バッファキャッシュ経由で書き込みが行われる。

問題点

  1. ファイル拡張は、ext2_getblk関数の中で自動的に行われる。 ファイル拡張時の問題点は、ext2_getblk関数を参照のこと。
  2. O_SYNCでopenしているファイルにおいてファイル拡張が発生しても、 ファイルのiノードが遅延書き込みとなっているため、ファイルサイズの 更新が遅れている。ファイル構造的には問題はないが、ユーザが期待している ものとは異なった動作となる。

(NIS)HirokazuTakahashi
2000年06月11日 (日) 22時29分57秒 JST
1