This makes root-squash NFS saves more efficient.
* src/qemu/qemu_driver.c (qemudDomainSaveFlag): Use new
virFileOperation flag to open fd only once.
---
src/qemu/qemu_driver.c | 75 +++++++++++++++++++++++++-----------------------
1 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c4d3c85..a73c5b9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1791,6 +1791,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
unsigned long long offset;
virCgroupPtr cgroup = NULL;
virBitmapPtr qemuCaps = NULL;
+ int fd = -1;
memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
@@ -1869,45 +1870,32 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
header.xml_len += pad;
}
- /* Setup hook data needed by virFileOperation hook function */
- hdata.dom = dom;
- hdata.path = path;
- hdata.xml = xml;
- hdata.header = &header;
-
- /* Write header to file, followed by XML */
+ /* Obtain the file handle. */
/* First try creating the file as root */
if (!is_reg) {
- int fd = open(path, O_WRONLY | O_TRUNC);
+ fd = open(path, O_WRONLY | O_TRUNC);
if (fd < 0) {
virReportSystemError(errno, _("unable to open %s"), path);
goto endjob;
}
- if (qemudDomainSaveFileOpHook(fd, &hdata) < 0) {
- VIR_FORCE_CLOSE(fd);
- goto endjob;
- }
- if (VIR_CLOSE(fd) < 0) {
- virReportSystemError(errno, _("unable to close %s"), path);
- goto endjob;
- }
} else {
- if ((rc = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
- S_IRUSR|S_IWUSR,
- getuid(), getgid(),
- qemudDomainSaveFileOpHook, &hdata,
- 0)) < 0) {
+ if ((fd = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
+ S_IRUSR|S_IWUSR,
+ getuid(), getgid(),
+ NULL, NULL,
+ VIR_FILE_OP_RETURN_FD)) < 0) {
/* If we failed as root, and the error was permission-denied
(EACCES or EPERM), assume it's on a network-connected share
where root access is restricted (eg, root-squashed NFS). If the
qemu user (driver->user) is non-root, just set a flag to
bypass security driver shenanigans, and retry the operation
after doing setuid to qemu user */
-
+ rc = fd;
if (((rc != -EACCES) && (rc != -EPERM)) ||
driver->user == getuid()) {
- virReportSystemError(-rc, _("Failed to create domain save file
'%s'"),
+ virReportSystemError(-rc,
+ _("Failed to create domain save file
'%s'"),
path);
goto endjob;
}
@@ -1932,7 +1920,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
default:
/* local file - log the error returned by virFileOperation */
virReportSystemError(-rc,
- _("Failed to create domain save file
'%s'"),
+ _("Failed to create domain save file
'%s'"),
path);
goto endjob;
break;
@@ -1941,13 +1929,15 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
/* Retry creating the file as driver->user */
- if ((rc = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
+ if ((fd = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
driver->user, driver->group,
- qemudDomainSaveFileOpHook, &hdata,
- VIR_FILE_OP_AS_UID)) < 0) {
- virReportSystemError(-rc, _("Error from child process creating
'%s'"),
- path);
+ NULL, NULL,
+ (VIR_FILE_OP_AS_UID |
+ VIR_FILE_OP_RETURN_FD))) < 0) {
+ virReportSystemError(-fd,
+ _("Error from child process creating
'%s'"),
+ path);
goto endjob;
}
@@ -1959,6 +1949,18 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
}
}
+ /* Write header to file, followed by XML */
+ hdata.dom = dom;
+ hdata.path = path;
+ hdata.xml = xml;
+ hdata.header = &header;
+
+ if (qemudDomainSaveFileOpHook(fd, &hdata) < 0) {
+ VIR_FORCE_CLOSE(fd);
+ goto endjob;
+ }
+
+ /* Allow qemu to access file */
if (!is_reg &&
qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
@@ -1986,14 +1988,10 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
const char *args[] = { "cat", NULL };
- /* XXX gross - why don't we reuse the fd already opened earlier */
- int fd = -1;
- if (qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
- priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX)
- fd = open(path, O_WRONLY);
qemuDomainObjEnterMonitorWithDriver(driver, vm);
- if (fd >= 0 && lseek(fd, offset, SEEK_SET) == offset) {
+ if (qemuCapsGet(qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
+ priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
rc = qemuMonitorMigrateToFd(priv->mon,
QEMU_MONITOR_MIGRATE_BACKGROUND,
fd);
@@ -2002,7 +2000,6 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
QEMU_MONITOR_MIGRATE_BACKGROUND,
args, path, offset);
}
- VIR_FORCE_CLOSE(fd);
qemuDomainObjExitMonitorWithDriver(driver, vm);
} else {
const char *prog = qemudSaveCompressionTypeToString(header.compressed);
@@ -2021,6 +2018,11 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver,
virDomainPtr dom,
if (rc < 0)
goto endjob;
+ if (VIR_CLOSE(fd) < 0) {
+ virReportSystemError(errno, _("unable to close %s"), path);
+ goto endjob;
+ }
+
rc = qemuMigrationWaitForCompletion(driver, vm);
if (rc < 0)
@@ -2085,6 +2087,7 @@ endjob:
cleanup:
qemuCapsFree(qemuCaps);
+ VIR_FORCE_CLOSE(fd);
VIR_FREE(xml);
if (ret != 0 && is_reg)
unlink(path);
--
1.7.4