Comment by needs
10 years ago
There is an easy way to write data without corruption. First copy your file-to-be-changed as a temporary file or create a temporary file. Then modify the temporary file and write whatever you want in it. Finally, use rename() to atomically replace the old file by the temporary one.
The same logic also apply to directories, although you will have to use links or symlinks to have something really atomic.
It may not work on strangely configured systems, like if your files are spread over different devices over the network (or maybe with NFS). But in those cases you will be able to detect it if you catch errors of rename() and co (and you should catch them of course). So no silver bullet here, but still a good shot.
I'm surprised rename() wasn't mentioned in the article, it's a well known technique to atomically update a file, which is very practical for small-ish files.
Note that in the general case, you should fsync() the temporary file before you rename() it over the original - but ext3 and ext4 in writeback mode added a heuristic to do that automatically, because ext3 in the default ordered mode would effectively do that and many applications came to assume it.
rename is atomic, but it is not guaranteed to be durable. In order for rename to be durable, I've learned that you have to fsync the parent directory.
I was saddened when I learned this. I used to use this old trick for a lot of my systems. I learned it from reading the code of old well-written unix systems programs.
I guess that's not viable if your files are huge monolithic databases.
It also doesn't work if you want to support a non-trivial update rate, or if there's any possibility of contention with another process trying to do the same thing. It's the sort of thing that app writers get addicted to, because it does work in the super-easy case, but it doesn't help at all when you need to solve harder storage problems than updating a single config file once in a while.