Skip to content

方法Method

崩溃安全的单文件替换

Crash-safe file replacement · Atomic file replacement protocol

用新文件内容先稳定、同目录原子重命名、目录再稳定建立恢复后完整旧版或新版的合同,并区分未知结果与多文件事务。

形式陈述 ​

目标是把已稳定路径/d/state从完整旧内容OLD替换为完整新内容NEW,并满足:任一崩溃点经恢复后,该路径只指向完整OLD或完整NEW;函数向调用者报告持久成功之后,必须指向NEW。

这需要两类前提。第一,文件与目录同步兑现各自成功承诺,设备正确flush。第二,同目录名称替换不但在运行时原子,而且文件系统恢复保证这次rename作为一个元数据事务要么不发布、要么完整发布。OS-16用重做日志实现这项恢复原子性,并保留旧对象直到新名称的提交已受保护。本文同目录替换涉及一个目录项块和至多两个inode元数据块,最多3个不同home块,落在4槽日志容量内;旧文件数据块延迟回收,回收另做受保护事务。仅有POSIX/Linux rename的运行时原子性,不足以单独证明这个崩溃前缀合同。

协议还限定:d及旧state的名称与内容已经稳定;临时文件与state在同一文件系统、同一目录;无其他写者或名称操作者;临时名独占创建、权限设置完成;处理短写、所有返回值和最终错误。不讨论网络文件系统、跨设备移动、链接攻击或静默媒体损坏。

直觉

直接覆盖原文件会让旧数据在新数据完整之前消失。替换协议先准备一份独立的新对象,把完整性建立好,再用一次名称发布决定读者看到哪一份。它把大文件写入和小的命名决策分离。

两个同步点保护不同东西。第一个确保新名字一旦指向新对象,就能恢复其完整内容;第二个确保系统已经承诺保留的名字不会在重启后退回旧对象。

例子与边界

四个阶段与恢复答案 ​

初始state→inode45,内容OLD已稳定。独占创建/d/.state.tmp→inode46,按完整写循环写入NEW并设置所需元数据。接着:

  1. 对inode46的fd成功fsync,确认新内容可恢复
  2. rename临时名到state,原子替换旧名称
  3. 对目录d的fd成功fsync,确认名称变化可恢复
  4. 才向上层报告持久成功
崩溃阶段 恢复后的state 临时名
写临时文件期间 OLD 可能缺失或不完整,不能当新版本
文件fsync成功、rename之前 OLD 可能存在;新对象内容完整
rename已返回、目录fsync未成功 OLD或NEW 取决于恢复的名称事务
目录fsync成功以后 NEW 不再作为待发布入口

第三行允许结果未知,但不允许state缺失或指向半写NEW;这条更强结论依赖前述文件系统rename恢复原子性。没有该假设,就不能从一张API调用表推导出同样的允许结果集合。

已经打开旧state的fd仍引用inode45,可能继续读取OLD;rename之后新open取得inode46。协议保证路径发布,不强迫所有历史打开者瞬间改看NEW。

省略同步或拆开重命名会怎样 ​

若跳过临时文件的fsync,目录事务先稳定,恢复可见state→46但内容为空或部分NEW,破坏完整性。若跳过最后目录fsync就报告持久成功,随后崩溃可能恢复OLD,破坏成功后的承诺。

若先unlink旧state,再rename临时文件,两个调用间有真实的名称空窗,且崩溃可能永久失去state。若临时文件在另一文件系统,rename可能失败为跨设备错误;把它改成复制加删除已经是另一协议,不能声称等价。

推论与应用

证明以名称发布为分界:发布前旧对象从未被覆盖,恢复仍可读OLD;发布后新对象的文件同步已经成功,故其内容是完整NEW。恢复原子性排除名称的中间状态,最后目录同步排除成功后回退。这是由对象完整性、名称原子性和同步顺序共同构成的证明,任何一项缺失都有上面的反例。

rename返回成功而目录fsync报错时,应用不应谎报持久成功,也不应断言替换没有发生。当前名称可能已经是NEW,重启结果却尚未获得相同承诺;盲目“回滚”为OLD还会覆盖别人可能观察或随后写出的结果。应将不确定状态交给有版本号或校验的恢复逻辑。

两个文件各执行本协议,仍可能恢复为A新、B旧。若二者有跨文件不变量,可把二者写入带版本号的新目录/对象集合,再原子发布一个清单或根入口;这需要清单引用全部内容先稳定,以及旧版本回收规则。单文件替换不是任意多资源事务。

参考资料
  • Linux man-pages 6.19,rename(2)与fsync(2),分别支持运行时名称替换与文件/目录同步接口;崩溃前缀结论另依正文声明的文件系统恢复模型。
  • Remzi与Andrea Arpaci-Dusseau,OSTEP: Crash Consistency—FSCK and Journaling,第42章,跨块更新为何需要恢复协议。OS-16的事务选择与完整替换证明为本文构造。
关系图谱5 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

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