起源
从https://btrfs.wiki.kernel.org/index.php/FAQ#What_are_the_crash_guarantees_of_overwrite-by-rename.3F
使用重命名覆盖现有文件是原子的。这意味着文件的旧内容或新内容存在。像这样的序列:
echo "oldcontent" > file # make sure oldcontent is on disk sync echo "newcontent" > file.tmp mv -f file.tmp file # *crash*
会给
文件包含“新内容”; file.tmp 不存在
包含“oldcontent”的文件; file.tmp 可能包含“newcontent”、长度为零或根本不存在。
这种方法保证保持file
一致(它将具有“新内容”或“旧内容”),但新数据可能会也可能不会在崩溃后恢复。 (mv file.tmp file
甚至给出更有趣的结果)
问题
我想实现一种在崩溃时恢复操作的方法,这样我就不会丢失“旧内容”或“新内容”。我怎样才能做到这一点?
它能保证有:
- 要么
file
有“旧内容”,要么file.tmp
有“新内容” - 或者
file
有“newcontent”并且file.tmp
不存在:
echo "oldcontent" > file
echo "newcontent" > file.tmp
# make sure files are on disk
sync
# a crash may happen at any time starting from this point.
ln file.tmp file.tmp2
mv -f file.tmp2 file
rm file.tmp
答案1
通过移动sync
after echo "newcontent" > file.tmp
,您可以确保两个文件的内容都在磁盘上。这消除了“files.tmp
可能为零长度”的变体。
剩下的不确定性,如果崩溃发生在之后sync
,只涉及目录条目,IE哪个文件指向哪里。移动 后sync
,剩下的可能性就是您列出的那些:
file
存在并包含“旧内容”,并且file.tmp
存在并包含“新内容”;file
存在并包含“newcontent”,但file.tmp
不存在。
无需通过链接到file.tmp
其他地方来添加额外的故障保护。
移动确实sync
会产生其他后果:特别是,它会为数据丢失留下更多的时间前这sync
。