mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Call fsync on safeOutputFile
If a system crash occurs after a simple write file + rename operation the target file that was renamed over may end up being empty if the data for the file written had not yet been committed to disk. This is possible because no part of the open file, write data to it, close it and then rename it ensure the data was actually written to disk prior to the rename happening. See this discussion on the btrfs wiki[1]. Fix this possible data loss scenario by calling fsync on the temporary file that is written prior to calling close on it. [1] https://btrfs.wiki.kernel.org/index.php/FAQ#What_are_the_crash_guarantees_of_overwrite-by-rename.3F
This commit is contained in:
1 parent
50703f8ae6
commit
1b2a20c395
1 file changed
+12
-1
@@ -136,8 +136,19 @@ async function getTempFile(prefix, suffix, tmpdir) {
|
||||
* @param {object|string} options - see fs.writeFile, `flag` must not be set.
|
||||
*/
|
||||
async function safeOutputFile(file, data, options={}) {
|
||||
let directory = path.dirname(file);
|
||||
if (!await fs.pathExists(directory)) {
|
||||
await fs.mkdirs(directory);
|
||||
}
|
||||
let temporary = `${file}.tmp`;
|
||||
await fs.outputFile(temporary, data, options);
|
||||
let fd = await fs.open(temporary, "w");
|
||||
try {
|
||||
await fs.writeFile(fd, data, options);
|
||||
await fs.fsync(fd);
|
||||
} finally {
|
||||
await fs.close(fd);
|
||||
}
|
||||
|
||||
await fs.rename(temporary, file);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user