Show page source of internal24-135-ファイルの削除 #25223

[[PageNavi(internal24-navi)]]

{{{ comment
h2w-title:ファイルの削除
}}}
 

= ファイルの削除 = #SECTION031030000000000000000

ファイルの削除は二つの処理から成り立つ。

  1.  ディレクトリエントリからの登録削除
  1.  ファイル実体(ファイルを構成するiノードとデータブロック)の解放

ディレクトリエントリからの登録削除処理は、unlinkシステムコールにおいて行う。ファイルを構成するiノードとデータブロックの解放は、そのファイルへの参照が無くなった時点で行われる(iput関数の延長)。通常はunlinkシステムコールと同時に、どこのディレクトリからも登録されておらず、どのプロセスからも参照されていない状態になるため、ほとんどの場合この二つの処理は同時に行われる。

open中のファイルの削除を行った場合は、unlinkシステムコール上ではファイル実体解放は行われず、closeシステムコールの延長でファイル実体の解放が行われることとなる。

unlinkシステムコールは、vfs sys_unlink(do_unlink)関数においてこれから削除するファイルのdentryを求めた後、親ディレクトリのiノードのunlinkオペレーションを呼び出すことにより実現されている。ext2ファイルシステムの場合は、 ext2_unlink関数が呼び出される。ext2_unlink関数はディレクトリエントリから目的のエントリを消した後、d_delete関数を呼び出す。

{{{
  ext2_unlink(親ディレクトリのiノード, 削除するファイルのdentry)
      削除するディレクトリエントリを検索(ext2_find_entry関数)
      ディレクトリエントリを削除(ext2_delete_entry関数)
      親ディレクトリのiノードの更新時間変更
      ◇親ディレクトリiノードの遅延書き込み要求(mark_inode_dirty関数)
      削除するファイルのiノードのリンク数を1減らす
      ◇削除するファイルのiノードの遅延書き込み要求(mark_inode_dirty関数)
}}}

 [[Embed(internal24-images:img46.gif)]]
 

ファイル実体の削除処理はiput関数が行っている。通常はd_delete関数の処理(vfsが呼び出す)の延長で呼び出され、ファイル本体の解放が行われる。(d_delete関数 → dentry_iput関数 → iput関数)一方open中のファイルの場合は、closeシステムコールから呼び出されるdput関数を通してiput関数がが呼び出される。(dput関数 → dentry_iput関数 → iput関数)iput関数は対象のファイルの参照カウントとリンクカウントが共に0となるとそのスーパブロックに登録されているdelete_inodeオペレーションを呼び出す。

ext2ファイルシステムでは、delete_inodeオペレーションは以下の関数である。

{{{
  ext2_delete_inode(iノード)
      iノードに削除時刻を設定(i_dtimeメンバ)
      ◇iノードの遅延書き込み要求(mark_inode_dirty関数)
      ◆iノードを書き込む(ext2_update_inode関数)
      iノード情報のファイルサイズを0にする(i_sizeメンバ)
      if(iノードにデータブロックが登録されていれば(i_blocksメンバ) ) {
             登録されている全てのブロックの解放を行う(ext2_truncate関数)
      }
      iノードの解放を行う(ext2_free_inode関数)
}}}

 [[Embed(internal24-images:img47.gif)]]
 

'''問題点、捕捉'''

  1.  SYNCモードでマウントしている場合、 解放するiノード情報まで同期書き込みしており、性能上不利である。 また同期書き込みしているデータは、データブロック解放前の 状態であり、次回のファイル生成時に初期化がさぼれるという訳でもない。
  1.  d_delete処理でdentryをキャッシュから外す処理が抜けているため、 unlinkシステムコール出口のdput()でdentryが解放されず、カーネル中に ゴミとして溜まっていく。 unlink本体処理ではdentryをキャッシュから外す処理のみとし、 unlinkシステムコール出口のdputでiノードの解放から、dentryの解放まで 行った方が良さそうに思える。(何か見落としているか?)
  1.  unlinkする対象がリンクされているファイルの場合、リンク数が 0にならないため、iノードの解放ルーチンは呼び出されない。 ただし、削除するファイルのiノードのリンク数を1減らす処理は、	遅延書き込みとして実現されているため、このタイミングでシステムが	クラッシュすると、実際にディレクトリに登録されている数より	iノードのリンク数の方が多いファイルができてしまう。	これはfsckで簡単に修復可能。	もしfsckを行わずに運用した場合でも、このファイルの削除時に	浮きブロックとなるだけであり、ファイルシステム構造破壊には	継らない。
  1.  unlink処理時、リンク数(i_nlink)が0になっていると warningメッセージを出し、強制的にリンク数を1にして	処理を継続している。ファイルシステムが壊れている場合の	処理であるが、二重解放される危険がある。

----

''(NIS)HirokazuTakahashi [[BR]]2000年12月09日 (土) 23時55分06秒 JST''1

[[PageNavi(internal24-navi)]]