3 ms·
Yeah, the way you're 'supposed' (as near as I can tell) to do this is: read 'foo' write 'foo~' hardlink 'foo~' onto 'foo' unlink 'foo~' on crash:
by a1369209993 6y ago
Yeah, the way you're 'supposed' (as near as I can tell) to do this is:
read 'foo'
write 'foo~'
hardlink 'foo~' onto 'foo'
unlink 'foo~'
on crash:
if 'foo' exists:
it's the correct state for the file
unlink 'foo~'
continue
otherwise:
hardlink 'foo~' onto 'foo'
unlink 'foo~'
I'm not sure Posix actually requires link and unlink to be atomic enough on crash for this work, but it seems to be fine for any sane filesystem (where the fs itself doesn't fall apart in presence of crashes).
- tomtomtom777 6y agoThis doesn't work because the link() syscall fails if the target exists. You use a hardlink only for atomic creation of the initial data: write 'foo~' hardlink 'foo~' onto 'foo' To atomically update you simply use rename: read 'foo' write 'foo~' rename 'foo~' into 'foo' I don't know what dan-robertson's claim is based on, but this surely is atomic even on a crash, as the filesystem will never be in a state where 'foo' contains only partially updated data. That would require some severe fs corruption.
- ynik 6y agoIt doesn't require severe FS corruption. In reality "write 'foo~'" just starts an asynchronous write; it's possible for rename to happen before that async write is complete. So in case of a system crash you might end up seeing partial data in 'foo'. fsync() may or may not protect against that depending on what system we're talking about.
- tomtomtom777 6y agoSure, you are still dependent on constraints to durability and atomicity of the filesystem write of the new data. But this is handled properly in most modern filesystems (ext3,ext4,zfs) by default (as data=ordered ensures data writes precede metadata writes). The point of rename() is to prevent a version to ever exist that mixes the old and the new version, which it always does, regardless of the filesystem.
- deleted 6y ago[deleted]