“这需要两类前提。第一,文件与目录同步兑现各自成功承诺,设备正确flush。第二,同目录名称替换不但在运行时原子,而且文件系统恢复保证这次rename作为一个元数据事务要么不发布、要么完整发布…”
形式陈述
持久化保证需要声明故障范围、稳定介质和成功返回含义。OS-16沿用页缓存理路页缓存、脏页与回写代际Page cache and writeback · Dirty page redirty · Buffered file I/O分离应用缓冲、内核页缓存和设备缓存,追踪同一页回写期间再次变脏,并解释write返回为何不足以证明持久化。与设备易失缓存模型:掉电后仅稳定块保留,设备兑现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尚未成功的中间掉电仍可能出现部分新内容。安全文件替换理路崩溃安全的单文件替换Crash-safe file replacement · Atomic file replacement protocol用新文件内容先稳定、同目录原子重命名、目录再稳定建立恢复后完整旧版或新版的合同,并区分未知结果与多文件事务。先构造新对象,再原子发布名称,才为应用建立旧版或新版的恢复不变量。
WAL理路预写日志Write-ahead logging · WAL规定数据页落盘与提交确认前必须先持久化相应日志,使崩溃后的撤销和重做拥有可靠依据。把“日志必须先稳定”作为接口条件;本页说明文件API及存储栈怎样承担该条件。调用函数的名字是请求,不是证据,必须检查返回值、作用对象、排序范围和文件系统支持。
参考资料
- Linux man-pages 6.19,fsync(2),文件与目录、fdatasync元数据范围及错误说明,2026-10-08核查。
- Remzi与Andrea Arpaci-Dusseau,OSTEP: Files and Directories,fsync与目录操作的应用接口。