From c96afef6693dfbf783abf5dfa3b60c588920e201 Mon Sep 17 00:00:00 2001 From: jiangdawei15 Date: Thu, 11 Aug 2022 20:57:49 +0800 Subject: [PATCH 08/22] qemu: do crash safe creation of NVRAM file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we crash part way through writing the NVRAM file we end up with an unusable NVRAM on file. To avoid this we need to write to a temporary file and fsync(2) at the end, then rename to the real NVRAM file path. Reviewed-by: Ján Tomko Signed-off-by: Daniel P. Berrangé --- src/qemu/qemu_process.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index b240149f7a..48d39ba97c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4697,7 +4697,8 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, bool created = false; const char *master_nvram_path; ssize_t r; - + g_autofree char *tmp_dst_path = NULL; + if (!loader || !loader->nvram || virFileExists(loader->nvram)) return 0; @@ -4726,7 +4727,9 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, master_nvram_path); goto cleanup; } - if ((dstFD = virFileOpenAs(loader->nvram, + + tmp_dst_path = g_strdup_printf("%s.tmp", loader->nvram); + if ((dstFD = virFileOpenAs(tmp_dst_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, cfg->user, cfg->group, 0)) < 0) { @@ -4750,7 +4753,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, if (safewrite(dstFD, buf, r) < 0) { virReportSystemError(errno, _("Unable to write to file '%s'"), - loader->nvram); + tmp_dst_path); goto cleanup; } } while (r); @@ -4761,9 +4764,24 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, master_nvram_path); goto cleanup; } + + if (g_fsync(dstFD) < 0) { + virReportSystemError(errno, + _("cannot sync file '%s'"), + tmp_dst_path); + goto cleanup; + } + if (VIR_CLOSE(dstFD) < 0) { virReportSystemError(errno, _("Unable to close file '%s'"), + tmp_dst_path); + goto cleanup; + } + + if (rename(tmp_dst_path, loader->nvram) < 0) { + virReportSystemError(errno, + _("Unable to replace '%s'"), loader->nvram); goto cleanup; } @@ -4774,7 +4792,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, * copy the file content. Roll back. */ if (ret < 0) { if (created) - unlink(loader->nvram); + unlink(tmp_dst_path); } VIR_FORCE_CLOSE(srcFD); -- 2.33.0