重命名()没有fsync()安全吗?

在不调用fsync(tmppath_fd)情况下调用rename(tmppath, path)是否安全?

我希望path始终指向一个完整的文件。 我主要关心的是Ext4 。 rename()在所有未来的Linux内核版本中都承诺是安全的吗?

Python中的使用示例:

 def store_atomically(path, data): tmppath = path + ".tmp" output = open(tmppath, "wb") output.write(data) output.flush() os.fsync(output.fileno()) # The needed fsync(). output.close() os.rename(tmppath, path) 

没有。

看看libeatmydata,这个介绍:

吃我的数据:每个人如何得到文件IO错误

http://www.oscon.com/oscon2008/public/schedule/detail/3172

由MySql的Stewart Smith撰写。

如果它离线/不再可用,我保留一份它的副本:

  • 这里的视频
  • 演示幻灯片 ( 幻灯片的 在线版本 )

从ext4文档 :

 When mounting an ext4 filesystem, the following option are accepted: (*) == default auto_da_alloc(*) Many broken applications don't use fsync() when noauto_da_alloc replacing existing files via patterns such as fd = open("foo.new")/write(fd,..)/close(fd)/ rename("foo.new", "foo"), or worse yet, fd = open("foo", O_TRUNC)/write(fd,..)/close(fd). If auto_da_alloc is enabled, ext4 will detect the replace-via-rename and replace-via-truncate patterns and force that any delayed allocation blocks are allocated such that at the next journal commit, in the default data=ordered mode, the data blocks of the new file are forced to disk before the rename() operation is committed. This provides roughly the same level of guarantees as ext3, and avoids the "zero-length" problem that can happen when a system crashes before the delayed allocation blocks are forced to disk. 

从“破解的应用程序”这个字眼来看,ext4开发者肯定认为这是不好的做法,但是实际上它被广泛使用的方法已经被修补在ext4本身了。

所以如果你的使用符合这个模式,你应该是安全的。

如果没有,我建议你进一步调查,而不是在这里和那里插入fsync只是为了安全。 这可能不是一个好主意,因为fsync可以成为ext3( 读取 )的主要性能。

另一方面,重命名之前刷新是在非日志文件系统上进行替换的正确方法。 也许这就是为什么ext4第一次预期这种行为从程序, auto_da_alloc选项后来被添加为一个修复。 另外这个用于回写(非日志)模式的ext3补丁尝试通过重命名异步刷新来帮助粗心的程序降低数据丢失的可能性。

你可以在这里阅读更多关于ext4的问题。

如果你只关心ext4而不是ext3,那么我建议在重命名之前在新文件上使用fsync。 ext4的fsync性能似乎比ext3好得多,没有很长的延迟。 或者可能是写回是默认模式(至少在我的Linux系统上)。

如果你只关心文件是完整的,而不是在目录中命名的文件,那么你只需要fsync新文件。 因为它将指向具有完整数据的新文件或旧文件,所以不需要同步fsync目录。