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

时间:2011-09-15 15:03:30

标签: linux rename ext4 fsync

在没有先调用rename(tmppath, path)的情况下致电fsync(tmppath_fd)是否安全?

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

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)

3 个答案:

答案 0 :(得分:27)

没有。

看看libeatmydata,这个演讲:

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

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

来自MySql的Stewart Smith。

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

答案 1 :(得分:3)

来自ext4 documentation

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(read)造成重大影响。

另一方面,重命名前刷新是在非日记文件系统上进行替换的正确方法。也许这就是为什么ext4最初期望程序中的这种行为,auto_da_alloc选项后来被添加为修复程序。写回(非日记)模式的this ext3补丁试图通过在重命名时异步刷新来帮助粗心程序,以降低数据丢失的可能性。

您可以阅读有关ext4问题here的更多信息。

答案 2 :(得分:1)

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

如果您只关心文件是否完整而不是目录中指定的文件,那么您只需要fsync新文件。也没有必要同步fsync目录,因为它将指向具有完整数据的新文件或旧文件。