场景:
任务代码(省略错误检查):
// 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的脏数据,因此您无需担心 . 并且写入比严格要求更多的操作系统是符合标准的,所以这就是你将会发现的一般情况,即使它没有保证 . “这不像”完全相同的durabily guarrantees“那么具体,但是非常权威,即使可能已经过时了 .
我试图做的是一个'sync'命令,它可以处理单个文件 . 像fsync / some / file一样,无需同步整个文件系统,例如在shell脚本中使用它 . 现在(从几年前开始)gnu coreutils 'sync'适用于单个文件并且正是这样(open / fsync) . 提交:https://github.com/coreutils/coreutils/commit/8b2bf5295f353016d4f5e6a2317d55b6a8e7fd00
2 回答
No ,
close()
re-open()
fsync()
未提供与fsync()
close()
相同的保证 .来源:我took this question到
linux-fsdevel
邮件列表和got the answer:进一步的相关链接是:
https://wiki.postgresql.org/wiki/Fsync_Errors("fsyncgate")
邮件列表条目PostgreSQL's handling of fsync() errors is unsafe and risks data loss at least on XFS
Writing programs to cope with I/O errors causing lost writes on Linux来自同一作者
特别是,后面的链接描述了如何
关闭FD后
,你将失去所有强制执行的方法
在
fsync()
失败后,您无法再次调用
fsync()
,希望现在您的数据会被写入你must re-do/confirm all writing work如果发生这种情况
POSIX fsync()的当前(2017)规范识别基本功能和可选功能:
如果实现未定义
_POSIX_SYNCHRONIZED_IO
,则重新打开的文件描述符没有未写入的数据要传输到存储设备,因此fsync()
调用实际上是无操作 .如果
_POSIX_SYNCHRONIZED_IO
由实现定义,则重新打开的文件描述符将确保写入与文件关联的任何文件描述符的所有数据都被传输到存储设备 .Conformance上的标准部分包含有关选项和选项组的信息 . Definitions部分有定义382..387,它定义了同步I / O和同步I / O的各个方面(是的,它们是不同的 - 也要注意打开文件描述符和打开文件描述) . 有关同步I / O的含义,请参阅“定义”部分的Realtime部分 .
它定义了:
不清楚“与文件描述符指示的文件关联的所有当前排队的I / O操作”是否适用于进程 . 从概念上讲,我认为应该这样,但措辞不是黑白两色(或淡黄色黑色) . 它当然应该适用于当前进程中引用同一文件的任何打开文件描述符 . 目前尚不清楚它是否适用于当前进程中先前打开(和关闭)的文件描述符 . 如果它适用于所有进程,则它应包括当前进程的排队I / O.如果它不适用于所有进程,则可能不适用于所有进程 .
鉴于此和
fsync()
的基本原理说明,假设fsync()
操作对与关闭文件描述符关联的排队操作没有影响,这是最安全的 . 如果希望fsync()
生效,请在关闭文件描述符之前调用它 .