在POSIX文件系统中持久重命名文件的正确方法是什么?特别想知道 目录. 。 (如果这取决于OS/FS,我询问有关Linux和Ext3/ext4的问题)。

笔记: :关于耐久的重命名,在Stackoverflow上还有其他问题,但是AFAICT他们没有解决目录(这对我来说很重要 - 我什至没有修改文件数据)。

我目前有(在Python):

dstdirfd = open(dstdirpath, O_DIRECTORY|O_RDONLY)
rename(srcdirpath + '/' + filename, dstdirpath + '/' + filename)
fsync(dstdirfd)

具体问题:

  • 这也暗示着源目录吗?或者我可能最终会在电源周期之后出现在两个目录中的文件(这意味着我必须检查硬链路计数并手动执行恢复),即无法保证持久的原子移动操作?
  • 如果我为源目录 代替 目标目录,这也会暗中fsync目的目录吗?
  • 是否有任何有用的相关测试/调试/学习工具(故障喷射器,内省工具,模拟文件系统等)?

提前致谢。

有帮助吗?

解决方案

posix定义了 重命名功能必须是原子.

因此,如果您重命名(a,b),在任何情况下,您都不应在目录中或两人目录中看到具有文件的状态。无论您对Fsync()或系统是否崩溃,总会有一个完全有一个。

但这并不能解决确保Rename()操作耐用的问题。 posix回答这个问题:

如果定义了_posix_synchronized_io,则fsync()函数应强制所有当前排队的I/O操作与文件描述符Fildes指示的文件关联的I/O操作到同步的I/O完成状态。所有I/O操作应按照同步I/O文件完整性完成为定义完成。

因此,如果您fsync()目录,则必须在此返回时将尚待重命名操作转移到磁盘上。任一个目录的Fsync()应该足够,因为Rename()操作的原子性都要求两个目录的更改是原子同步的。

最后,与另一个答案中提到的博客文章中的主张相反,此解释说明了以下内容:

Fsync()函数旨在强制从缓冲区缓存中的数据写入,并确保在系统崩溃或其他故障后,所有数据都在磁盘上记录到FSYNC()调用时间。由于“缓冲缓存”,“系统崩溃”,“物理写入”和“非挥发性存储”的概念未定义,因此措辞必须更加抽象。

一个声称符合POSIX的系统,并且认为它正确的行为(即不是错误或硬件故障)完成了FSYNC()(),并且不坚持在系统崩溃中的这些更改,必须故意虚假地陈述自己的规格。

(使用其他信息更新回复:特定于Linux的行为与便携式行为)

其他提示

不幸的是,戴夫的答案是错误的。

并非所有POSIX系统甚至都有耐用的存储空间。如果他们这样做,则在系统崩溃后仍可以“允许”它。对于这些系统,no-op fsync()是有道理的,并且在POSIX下明确允许使用此类fsync()。该文件在旧目录,新目录,或任何其他位置都可以恢复也是合法的。 POSIX不保证系统崩溃或文件系统恢复。

真正的问题应该是:

如何对通过POSIX API支持该的系统进行持久重命名?

您需要对两个来源进行fsync() 目标目录,因为应该执行的最小fsync()是坚持源或目标目录的外观。

Fsync(destDirfd)是否也隐含地将源为源目录?

  • POSIX一般:不,没有任何意义
  • ext3/4:我不确定对源和目的地dir是否两者都在期刊中的同一交易中进行。如果他们这样做,他们俩都在一起。

还是我可能最终会在电源周期后出现在两个目录中的文件(“崩溃”),即无法保证持久的原子移动操作?

  • POSIX一般:不保证,但是您应该使用两个目录,这可能是不可原子的
  • ext3/4:您最小需求取决于安装选项的fsync()()。例如,如果使用“ dirsync”安装,则不需要这两个fsync()s中的任何一个。最多您都需要两个fsync(),但是我几乎敢肯定一个人足够了(那时原子 - 育种)。

如果我将源目录而不是目标目录fync,那也暗示着目标目录吗?

  • POSIX:不
  • ext3/4:我真的相信两者最终都进行了同一交易,所以您的哪一个()都没关系
  • 较旧的内核EXT3 :(如果他们不在同一交易中)一些不太理想的实现在FSYNC()上执行了太多同步,我敢打赌,它确实实施了以前发生的每笔交易。是的,普通实现将首先将其链接到目标,然后将其从源中删除。因此,Fsync(SRCDIRFD)也会触发目的地的Fsync()。
  • ext4/最新ext3:如果它们不在同一交易中,您可能能够独立地完全同步(两者)

是否有任何有用的相关测试/调试/学习工具(故障喷射器,内省工具,模拟文件系统等)?

对于真正的崩溃,不。顺便说一句,真正的崩溃超出了内核的观点。硬件可能会重新订购(并且无法编写所有内容),从而破坏文件系统。 EXT4更好地针对此准备,因为它默认可以启用写入障碍(挂载选项)(ext3不),并且可以通过期刊校验和来检测损坏(也是安装选项)。

并且要学习:找出期刊中是否链接了两个更改! :p

您问题的答案将在很大程度上取决于所使用的特定操作系统,所使用的文件系统类型以及源和DEST是否在同一设备上。

我首先要阅读您使用的平台上的重命名(2)MAN页面。

在我看来,就像您想完成文件系统的工作一样。如果您移动文件,则内核和文件系统负责原子操作和故障重新发现,而不是您的代码。

无论如何,本文似乎解决了您有关FSYNC的问题:http://blogs.gnome.org/alexl/2009/03/16/ext4-vs-fsync-my-take/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top