残念ながら、デイブの答えは間違っています。
すべてのPOSIXシステムに耐久性のあるストレージがあるとは限りません。その場合でも、システムがクラッシュした後でもホースで接続することは「許可」されています。これらのシステムでは、no-op fsync()が理にかなっており、そのようなfsync()はPOSIXで明示的に許可されています。また、ファイルが古いディレクトリ、新しいディレクトリ、両方、またはその他の場所で回復可能であることも合法です。POSIXは、システムのクラッシュやファイルシステムの回復を保証しません。
本当の質問は次のようになります。
POSIX APIを介してそれをサポートするシステムで永続的な名前変更を行うにはどうすればよいですか?
ソースディレクトリと宛先ディレクトリの両方でfsync()を実行する必要があります。これは、これらのfsync()が実行する必要があるのは、ソースディレクトリまたは宛先ディレクトリがどのように見えるかを永続化することだけだからです。
fsync(destdirfd)も暗黙的にソースディレクトリをfsyncしますか?
- 一般的なPOSIX:いいえ、それを意味するものは何もありません
- ext3 / 4:ソースディレクトリと宛先ディレクトリの両方の変更がジャーナル内の同じトランザクションで終了するかどうかはわかりません。もしそうなら、彼らは両方を一緒にコミットします。
または、電源を入れ直した後(「クラッシュ」)にファイルが両方のディレクトリに表示される可能性があります。つまり、永続的なアトミック移動操作を保証することは不可能ですか。
- 一般的なPOSIX:保証はありませんが、両方のディレクトリをfsync()することになっています。これは、アトミック耐久性がない可能性があります。
- ext3 / 4:最低限必要なfsync()の量は、マウントオプションによって異なります。たとえば、「dirsync」でマウントされている場合、これら2つのfsync()は必要ありません。せいぜい両方のfsync()が必要ですが、ほぼ確実に1つで十分です(その場合は原子耐久性があります)。
宛先ディレクトリの代わりにソースディレクトリをfsyncした場合、それは暗黙的に宛先ディレクトリもfsyncしますか?
- POSIX:いいえ
- ext3 / 4:両方が同じトランザクションになると本当に信じているので、どちらをfsync()にするかは関係ありません。
- 古いカーネルext3:(同じトランザクションにない場合)一部のあまり最適ではない実装は、fsync()での同期が多すぎたため、以前に発生したすべてのトランザクションをコミットしたに違いありません。そして、はい、通常の実装では、最初にそれを宛先にリンクしてから、ソースから削除します。したがって、fsync(srcdirfd)は、宛先のfsync()もトリガーします。
- ext4 /最新のext3:それらが同じトランザクションにない場合は、それらを完全に独立して同期できる可能性があります(両方を実行してください)
関連する有用なテスト/デバッグ/学習ツール(フォールトインジェクター、イントロスペクションツール、モックファイルシステムなど)はありますか?
実際のクラッシュの場合、いいえ。ちなみに、実際のクラッシュはカーネルの視点を超えています。ハードウェアが書き込みを並べ替えて(すべての書き込みに失敗して)、ファイルシステムを破壊する可能性があります。Ext4は、デフォルトで書き込みバリー(マウントオプション)を有効にし(ext3は無効)、ジャーナルチェックサム(マウントオプションも)で破損を検出できるため、これに対してより適切に準備されています。
そして学習のために:両方の変更がジャーナルで何らかの形でリンクされているかどうかを調べてください!:-P