mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 11:01:19 +00:00
qemu: do crash safe creation of NVRAM file
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 <jtomko@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
2df9031a0e
commit
5e3498744e
@ -4433,6 +4433,7 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
|
|||||||
bool created = false;
|
bool created = false;
|
||||||
const char *master_nvram_path;
|
const char *master_nvram_path;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
|
g_autofree char *tmp_dst_path = NULL;
|
||||||
|
|
||||||
if (!loader || !loader->nvram || virFileExists(loader->nvram))
|
if (!loader || !loader->nvram || virFileExists(loader->nvram))
|
||||||
return 0;
|
return 0;
|
||||||
@ -4463,14 +4464,15 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
|
|||||||
goto cleanup;
|
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,
|
O_WRONLY | O_CREAT | O_EXCL,
|
||||||
S_IRUSR | S_IWUSR,
|
S_IRUSR | S_IWUSR,
|
||||||
cfg->user, cfg->group,
|
cfg->user, cfg->group,
|
||||||
VIR_FILE_OPEN_FORCE_OWNER)) < 0) {
|
VIR_FILE_OPEN_FORCE_OWNER)) < 0) {
|
||||||
virReportSystemError(-dstFD,
|
virReportSystemError(-dstFD,
|
||||||
_("Failed to create file '%s'"),
|
_("Failed to create file '%s'"),
|
||||||
loader->nvram);
|
tmp_dst_path);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4489,7 +4491,7 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
|
|||||||
if (safewrite(dstFD, buf, r) < 0) {
|
if (safewrite(dstFD, buf, r) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Unable to write to file '%s'"),
|
_("Unable to write to file '%s'"),
|
||||||
loader->nvram);
|
tmp_dst_path);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
} while (r);
|
} while (r);
|
||||||
@ -4500,9 +4502,23 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
|
|||||||
master_nvram_path);
|
master_nvram_path);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_fsync(dstFD) < 0) {
|
||||||
|
virReportSystemError(errno, _("cannot sync file '%s'"),
|
||||||
|
tmp_dst_path);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (VIR_CLOSE(dstFD) < 0) {
|
if (VIR_CLOSE(dstFD) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Unable to close file '%s'"),
|
_("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);
|
loader->nvram);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -4513,7 +4529,7 @@ qemuPrepareNVRAM(virQEMUDriver *driver,
|
|||||||
* copy the file content. Roll back. */
|
* copy the file content. Roll back. */
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (created)
|
if (created)
|
||||||
unlink(loader->nvram);
|
unlink(tmp_dst_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FORCE_CLOSE(srcFD);
|
VIR_FORCE_CLOSE(srcFD);
|
||||||
|
Loading…
Reference in New Issue
Block a user