Linuxカーネルに関する技術情報を集めていくプロジェクトです。現在、Linuxカーネル2.6解読室の第2章までを公開中。
ファイルのトランケート処理は以下の場合に呼び出される。明示的なtruncateシステムコール呼び出しでは、iノード内のi_sizeで示されるところまで解放する。
注意 2000.6.16現時点では、open/truncateシステムコールの延長ではtruncate処理は呼び出されない。VFSレベルではinodeサイズのみ変更しており、実際のファイル切り詰め処理を行う下記関数は呼び出されない。ユーザ見え的にはファイルは小さくなったように見えるので問題無いが、フリーブロックが増えないという小さい問題は残る。再度ファイル拡張が発生したとき処理が高速になるというメリットはある。
ext2_truncate(iノード) 先行拡張したブロックの解放(ext2_discard_prealloc関数) while(ブロックが残っている間) { 直接ブロックの解放(trunc_direct関数) 間接ブロックの解放(trunc_indirect関数) 二段間接ブロックの解放(trunc_dindirect関数) 三段間接ブロックの解放(trunc_tindirect関数) if(全ての解放が完了したら) break if(SYNC属性 かつ iノードがDIRTY) { ◆iノードのディスクへの書き込み(ext2_sync_inode関数) } スケジューラを呼び出し少し待つ(schedule関数) } iノード更新時間更新 ◇iノードの遅延書き込み要求(mark_inode_dirty関数) trunc_direct(iノード) iノードのファイルサイズから解放する直接ブロックの先頭エントリを求める while(iノードに解放する直接ブロックある間) { if(その直接ブロックエントリが空?) continue; iノードのそのブロックが登録されていたエントリをクリア iノードに登録されているブロック数を減らす(メンバi_blocks) ◇iノードの遅延書き込み要求(mark_inode_dirty関数) 連続分したブロックをまとめて解放(ext2_free_blocks関数) } 連続分したブロックをまとめて解放(ext2_free_blocks関数) return 全て解放できたら0、失敗したら1 trunc_indirect(iノード, 間接ブロックが登録されているエントリ番号, 間接ブロックが登録されているエントリ) if(間接ブロックがない) return 0; 間接ブロックを読み出す(bread関数) while(間接ブロックに解放するブロックがある間) { if(解放しようとしているブロックのバッファが使用中) continue; 間接ブロックのそのブロックが登録されていたエントリをクリア iノードに登録されているブロック数を減らす(メンバi_blocks) ◇iノードの遅延書き込み要求(mark_inode_dirty関数) ◇間接ブロックの遅延書き込み要求(mark_buffer_dirty関数) 連続分したブロックをまとめて解放(ext2_free_blocks関数) } 連続分したブロックをまとめて解放(ext2_free_blocks関数) 間接ブロック自体の解放(check_block_empty関数) return 全て解放できたら0、失敗したら1 trunc_dindirect(iノード, 二段間接ブロックが登録されているエントリ番号, 二段間接ブロックが登録されているエントリ) if(二段間接ブロックがない) return 0; 二段間接ブロックを読み出す(bread関数) while(二段間接ブロックに解放する間接ブロックがある間) { 間接ブロックに登録されているデータブロックの解放(trunc_indirect関数) } 二段間接ブロック自体の解放(check_block_empty関数) return 全て解放できたら0、失敗したら1 trunc_tindirect(iノード) if(三段間接ブロックがない) return 0; 三段間接ブロックを読み出す(bread関数) while(三段間接ブロックに解放する二段間接ブロックがある間) { 二間接ブロックに登録されている間接ブロックと データブロックの解放(trunc_dindirect関数) } 三段間接ブロック自体の解放(check_block_empty関数) return 全て解放できたら0、失敗したら1 check_block_empty(inode, bh, ind_bh) if(間接ブロックのバッファがI/O中なら) I/O完了を待ち合わせる if (間接ブロックに何か残っているなら) { if(SYNC属性 かつ 間接ブロックのバッファがDIRTY) { ◆間接ブロックの書き込み(ll_rw_block関数, wait_on_buffer関数) } 間接ブロックのバッファの解放(brelse関数) return 0; } if (他から、この間接ブロックのバッファが参照されている) return 1; if (間接ブロックが空なら) { iノード(または別の間接ブロック)から、この間接ブロックの登録を消す iノードに登録されているブロック数を減らす(メンバi_blocks) ◇iノードの遅延書き込み要求(mark_inode_dirty関数) 間接ブロックのバッファを無効にする(bforget関数) 間接ブロック自体を解放(ext2_free_blocks関数) }
下図は、ファイルトランケート処理の順番を図に表した物である。◆は同期書き込み、◇は遅延書き込みを表している。◆◇の後ろの数字は、その処理の順番を示している。
問題点など
SYNCモードでマウントしたときの問題点
(NIS)HirokazuTakahashi
2000年12月09日 (土) 23時55分06秒 JST1
[PageInfo]
LastUpdate: 2008-08-27 14:18:25, ModifiedBy: hiromichi-m
[Permissions]
view:all, edit:login users, delete/config:members