关闭后调用fsync(2)(2)

时间:2016-05-18 00:51:05

标签: c linux unix filesystems posix

情景:

任务代码(省略错误检查):

// open, write and close
fd = open(name);
write(fd, buf, len);
close(fd);
< more code here **not** issuing read/writes to name but maybe open()ing it >
// open again and fsync
fd = open(name);
fsync(fd);

不再有任务在系统中同时访问name

是否定义了,更重要的是,它是否会同步name引用的inode上可能的未完成写入?即,我会在fsync之后从文件中读回buf吗?

从POSIX http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html我会说它似乎合法......

感谢。

编辑可能18: 感谢您的回答和研究。我把这个问题(在2016年)带到了一个extfs主要开发人员(Ted)并得到了这个答案:“Posix不保证,但在实践中它应该适用于大多数 文件系统,包括ext4。 Posix规范中的关键措辞是:

fsync()函数应该请求打开文件的所有数据                                                  ^^^^^^^^^^^^^^^^^ 由fildes命名的描述符将被传送到存储设备 ^^^^^^^^^^^^^^^^^^^^^^^^^^ 与fildes描述的文件相关联。

它没有说“fildes描述的文件的所有数据......” 说“打开文件描述符的所有数据”。技术上的数据 由另一个文件描述符写的不保证同步到 磁盘。

实际上,文件系统不会尝试使用fd的脏数据 在,所以你不必担心。而且一个写得比什么更多的操作系统 严格要求是符合标准的,所以这就是你 一般来说,即使不能得到保证,也会发现。“这不像”完全相同的杜鹃花保证“那么具体,但是相当权威,即使可能已经过时了。

我试图做的是一个处理单个文件的'sync'命令。 像fsync / some / file一样,无需同步整个文件系统,例如在shell脚本中使用它。 现在(几年前)gnu coreutils'sync'适用于单个文件,并且正是这样(open / fsync)。提交:https://github.com/coreutils/coreutils/commit/8b2bf5295f353016d4f5e6a2317d55b6a8e7fd00

2 个答案:

答案 0 :(得分:3)

close() + re - open() + fsync()不提供与fsync() + close()相同的保证。

来源:我took this questionlinux-fsdevel邮件列表和got the answer

  
    

close()/ re-open()/ fsync()序列是否提供相同的持久性     保证为fsync()/ close()?

  
     

简短的回答是否定的,后者提供了更好的保证。   更长的答案是耐用性保证取决于内核版本,   因为情况在v4.13,v4.14和现在再次发生变化   v4.17-rc和稳定的内核。

进一步相关的链接是:

特别是,后面的链接描述了如何

  • 关闭FD后,您将失去所有强制执行的方法
  • fsync()失败后,您无法再次致电fsync(),希望现在可以写入您的数据
  • must re-do/confirm all writing work如果发生这种情况

答案 1 :(得分:1)

POSIX fsync()的当前(2017)规范 识别基本功能和可选功能:

  

fsync()函数应请求将fildes命名的打开文件描述符的所有数据传输到与fildes描述的文件关联的存储设备。转移的性质是实施定义的。在系统完成该操作或检测到错误之前,fsync()函数不会返回。

     

[SIO]⌦如果定义了_POSIX_SYNCHRONIZED_IOfsync()函数将强制所有当前排队的I / O操作与文件描述符fildes指示的文件关联到同步的I /完成状态。所有I / O操作都应按照同步I / O文件完整性完成的定义完成。 ⌫

如果实现未定义_POSIX_SYNCHRONIZED_IO,则重新打开的文件描述符没有未传输的数据要传输到存储设备,因此fsync()调用实际上是无操作。

如果实现定义了_POSIX_SYNCHRONIZED_IO,那么重新打开的文件描述符将确保写入与文件关联的任何文件描述符的所有数据都被传输到存储设备。

Conformance标准部分包含有关选项和选项组的信息。 Definitions部分有定义382..387,它定义了同步I / O和同步I / O的各个方面(是的,它们不同 - 也要注意打开文件描述符和打开文件描述)。 Realtime上的部分按照“定义”部分的内容,了解同步I / O的含义。

它定义:

  

3.382同步输入和输出

     

用于增强数据输入和输出机制的确定性和健壮性改进机制,以便应用程序可以确保被操作的数据实际存在于辅助大容量存储设备上。

     

3.383同步I / O完成

     

已成功传输或诊断为不成功的I / O操作的状态。

     

3.384同步I / O数据完整性完成

     

对于读取,操作完成或诊断如果不成功。仅当数据图像已成功传输到请求进程时,才完成读取。如果在请求同步读取操作时有任何影响要读取的数据的挂起写入请求,则在读取数据之前会成功传输这些写入请求。

     

用于写入,操作完成或诊断后如果不成功。只有在成功传输写请求中指定的数据并成功传输检索数据所需的所有文件系统信息时,写操作才会完成。

     

在返回调用流程之前,无需成功传输数据检索不需要的文件属性(访问时间,修改时间,状态更改时间)。

     

3.385同步I / O文件完整性完成

     

与同步I / O数据完整性完成相同,并且在返回到调用进程之前成功传输了与I / O操作相关的所有文件属性(包括访问时间,修改时间,状态更改时间)。

     

3.386同步I / O操作

     

对文件执行I / O操作,该文件为应用程序提供数据和文件完整性的保证。

     

3.387同步I / O操作

     

I / O操作,导致请求I / O的线程被阻止进一步使用处理器,直到I / O操作完成。

     

注意:   同步I / O操作并不意味着同步I / O数据完整性完成或同步I / O文件完整性完成。

并非100%清楚“与文件描述符指示的文件关联的所有当前排队的I / O操作”是否适用于进程。 从概念上讲,我认为应该这样,但措辞不是黑白两色(或淡黄色黑色)。它当然应该适用于当前进程中引用同一文件的任何打开文件描述符。目前尚不清楚它是否适用于当前进程中先前打开(和关闭)的文件描述符。如果它适用于所有进程,则它应包括当前进程的排队I / O.如果它不适用于所有进程,则可能不适用于所有进程。

鉴于这一点以及fsync()的基本原理说明,最安全的做法是假设fsync()操作对与关闭文件描述符关联的排队操作没有影响。如果希望fsync()生效,请在关闭文件描述符之前调用它。