Skip to content

原则Principle

文件同步与目录持久化

fsync and directory durability · fdatasync · File persistence boundary

为write、设备完成、fsync文件与fsync目录各写出准确承诺,区分内容保存、名称保存和多对象原子性。

形式陈述 ​

持久化保证需要声明故障范围、稳定介质和成功返回含义。OS-16沿用页缓存与设备易失缓存模型:掉电后仅稳定块保留,设备兑现flush,已稳定块不发生后续媒体损坏;单块写原子,跨块操作需要恢复协议。

本页为OS-16定义两种同步接口。sync_file(f)等待调用前、由应用已排序且不再并发修改的文件数据及取回它们所需的文件元数据具备恢复保证;sync_dir(d)等待此前目录项变化具备恢复保证。成功后对应承诺在掉电重启后仍成立。保证可以由home块稳定提供,也可以由已提交且可重放日志提供,不要求每个home位置立即改完。

真实API对照限定Linux man-pages 6.19所述fsync,以及支持相应同步、目录同步和正确flush的本地文件系统/存储栈:文件fsync同步内容和文件元数据,但不必同步包含它的目录项;名称持久化需要显式同步相关目录。fdatasync可略去与后续正确读取无关的元数据,文件大小变化等仍须保存。此处不是给所有POSIX实现、网络文件系统或损坏设备一个统一硬件承诺。

直觉

保存了一本书的页,不等于图书目录已经记住它的新名字。文件同步回答能否恢复这个对象的内容,目录同步回答能否恢复名字到对象的连接。创建、重命名和删除都涉及后一类事实。

同步也不天然等于事务。先同步文件A,再同步文件B,断电仍可发生在两次之间;若应用不允许一新一旧,就需要原子发布或事务协议。

例子与边界

同一个更新的四种成功 ​

P对已有且名称已稳定的inode42写abXYefgh。write返回8时,新内容可仅在DRAM;设备普通写成功时,可仅在设备易失缓存;文件fsync成功时,恢复必须保留这些已排序写入及必要元数据。因名称原本已稳定且未改变,这次单纯内容更新不需要凭空再改目录。

若P新建/d/new指向inode43并写入NEW,文件fsync成功可以保护inode43内容,却尚不足以断言重启后一定能通过/d/new找到它。再对目录d成功fsync,才在本页前提下保护这个新名称。目录fsync也不反向替代文件内容同步,除非具体文件系统额外给出更强保证。

成功事件各自承诺什么

错误不是“确定没有写入” ​

如果write返回成功而后来的fsync返回I/O错误,应用不能报告持久提交成功;也不能假定设备完全没变。某些块可能已经稳定,某些没有。应保留可重试或可恢复的应用状态,并按协议处理结果未知;盲目把同一增量操作再做一次,可能重复业务效果。

若应用调用file fsync成功后又写一遍新内容,再马上掉电,第一次fsync不能为之后的写背书,也不是保留旧代的快照;后续原地写如果部分稳定,掉电可留下新旧混合,已经同步过的旧内容不会因此永远可回退。为了清晰界定保存的版本,本文同步区间没有并发写者;并发应用需通过锁、版本或快照确定自己的提交集合。

推论与应用

把程序库flush、内核writeback、设备flush和目录同步画成偏序,能检验声明:用户缓冲未交给内核,file fsync无数据可同步;设备不兑现flush,OS无法凭返回值制造稳定性;名称未同步,即使文件内容完整也可能失去访问入口。

稳定性与原子性应各自证明。一次大write横跨多个块,即使最终fsync成功能保护完整结果,在fsync尚未成功的中间掉电仍可能出现部分新内容。安全文件替换先构造新对象,再原子发布名称,才为应用建立旧版或新版的恢复不变量。

WAL把“日志必须先稳定”作为接口条件;本页说明文件API及存储栈怎样承担该条件。调用函数的名字是请求,不是证据,必须检查返回值、作用对象、排序范围和文件系统支持。

参考资料
  • Linux man-pages 6.19,fsync(2),文件与目录、fdatasync元数据范围及错误说明,2026-10-08核查。
  • Remzi与Andrea Arpaci-Dusseau,OSTEP: Files and Directories,fsync与目录操作的应用接口。
关系图谱5 个相邻概念 · 1 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组