不幸的是戴夫的答案是错的。
并非所有的POSIX系统甚至可能拥有持久存储。如果他们这样做,在系统崩溃后它仍然是“允许的”。对于那些系统来说,no-op fsync()是有意义的,并且这样的fsync()在POSIX下明确允许。在旧目录,新目录,两者或任何其他位置恢复文件也是合法的。 POSIX不保证系统崩溃或文件系统恢复。
真正的问题应该是:
如何做哪些支持通过POSIX API系统持久重命名?
你需要做的fsync()两个,源和目标目录,因为最小的FSYNC()s的应该做的是坚持源或目标目录应该是什么样子等。
fsync(destdirfd)是否也隐式地fsync源目录?
- POSIX一般:没有,没有什么暗示
- EXT3/4:我不知道,如果都改变为源和目标目录在杂志同一事务结束。如果他们这样做,他们会一起承诺。
或者我可能会在电源循环(“崩溃”)后在两个目录中显示文件,即无法保证持久的原子移动操作?
- POSIX一般:没有任何保证,但是你应该FSYNC()两个目录,这可能不是原子耐用
- EXT3/4:您最低限度有多大的fsync()需要依赖于挂载选项。例如。如果使用“dirsync”安装,则不需要这两个fsync()中的任何一个。最多你需要两个fsync(),但我几乎可以肯定一个就足够了(然后是atomic-durable)。
如果我fsync源目录,而不是目的地目录,那也隐含fsync目的地目录?
- POSIX:没有
- EXT3/4:我真的相信在同一事务都结束了,所以它并不重要的人,你的fsync()
- 旧内核的ext3:(如果他们不在同一个事务中)一些不太理想的实现在fsync()上做了太多的同步,我敢打赌它确实提交了之前发生的每一个事务。是的,一个正常的实现将首先将其链接到目标,然后将其从源代码中移除。所以fsync(srcdirfd)也会触发目标的fsync()。
- EXT4/ext3的最新:如果他们不是在同一个交易,你可能能够完全同步他们独立(这样做既)
是否有任何有用的相关测试/调试/学习工具(故障注入器,内省工具,模拟文件系统等)?
对于真正的碰撞,没有。顺便说一下,真正的崩溃超出了内核的观点。硬件可能会重新排序写入(并且无法写入所有内容),从而破坏文件系统。 Ext4对此做了更好的准备,因为它默认启用了写入挂载(挂载选项)(ext3不),并且可以使用日志校验和(也是挂载选项)检测损坏。
而对于学习:找出这两个变化是否以某种方式在期刊中链接! :-P
这里的推理是非常错误的。 - 举例来说,rename()的“atomicity”是指“新路径”,在该路径下应该是旧文件(如果有的话)或重命名的文件,其间没有状态(如其他进程所见) 。 – 2013-05-11 19:02:22
Robert指出,在将新的inode分配给名称方面,rename为“atomic”,新的inode是否指向未刷新的数据不是由POSIX定义的。 – ArekBulski 2015-09-19 18:14:38