提交 3eede281 编写于 作者: E Eric Blake

qemu: simplify domain save fd handling

This makes root-squash NFS saves more efficient.

* src/qemu/qemu_driver.c (qemudDomainSaveFlag): Use new
virFileOperation flag to open fd only once.
上级 055d4ff8
...@@ -1824,6 +1824,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -1824,6 +1824,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
unsigned long long offset; unsigned long long offset;
virCgroupPtr cgroup = NULL; virCgroupPtr cgroup = NULL;
virBitmapPtr qemuCaps = NULL; virBitmapPtr qemuCaps = NULL;
int fd = -1;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
...@@ -1902,45 +1903,32 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -1902,45 +1903,32 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
header.xml_len += pad; header.xml_len += pad;
} }
/* Setup hook data needed by virFileOperation hook function */ /* Obtain the file handle. */
hdata.dom = dom;
hdata.path = path;
hdata.xml = xml;
hdata.header = &header;
/* Write header to file, followed by XML */
/* First try creating the file as root */ /* First try creating the file as root */
if (!is_reg) { if (!is_reg) {
int fd = open(path, O_WRONLY | O_TRUNC); fd = open(path, O_WRONLY | O_TRUNC);
if (fd < 0) { if (fd < 0) {
virReportSystemError(errno, _("unable to open %s"), path); virReportSystemError(errno, _("unable to open %s"), path);
goto endjob; 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 { } else {
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_IRUSR|S_IWUSR,
getuid(), getgid(), getuid(), getgid(),
qemudDomainSaveFileOpHook, &hdata, NULL, NULL,
0)) < 0) { VIR_FILE_OP_RETURN_FD)) < 0) {
/* If we failed as root, and the error was permission-denied /* If we failed as root, and the error was permission-denied
(EACCES or EPERM), assume it's on a network-connected share (EACCES or EPERM), assume it's on a network-connected share
where root access is restricted (eg, root-squashed NFS). If the where root access is restricted (eg, root-squashed NFS). If the
qemu user (driver->user) is non-root, just set a flag to qemu user (driver->user) is non-root, just set a flag to
bypass security driver shenanigans, and retry the operation bypass security driver shenanigans, and retry the operation
after doing setuid to qemu user */ after doing setuid to qemu user */
rc = fd;
if (((rc != -EACCES) && (rc != -EPERM)) || if (((rc != -EACCES) && (rc != -EPERM)) ||
driver->user == getuid()) { driver->user == getuid()) {
virReportSystemError(-rc, _("Failed to create domain save file '%s'"), virReportSystemError(-rc,
_("Failed to create domain save file '%s'"),
path); path);
goto endjob; goto endjob;
} }
...@@ -1965,7 +1953,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -1965,7 +1953,7 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
default: default:
/* local file - log the error returned by virFileOperation */ /* local file - log the error returned by virFileOperation */
virReportSystemError(-rc, virReportSystemError(-rc,
_("Failed to create domain save file '%s'"), _("Failed to create domain save file '%s'"),
path); path);
goto endjob; goto endjob;
break; break;
...@@ -1974,13 +1962,15 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -1974,13 +1962,15 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
/* Retry creating the file as driver->user */ /* 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, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
driver->user, driver->group, driver->user, driver->group,
qemudDomainSaveFileOpHook, &hdata, NULL, NULL,
VIR_FILE_OP_AS_UID)) < 0) { (VIR_FILE_OP_AS_UID |
virReportSystemError(-rc, _("Error from child process creating '%s'"), VIR_FILE_OP_RETURN_FD))) < 0) {
path); virReportSystemError(-fd,
_("Error from child process creating '%s'"),
path);
goto endjob; goto endjob;
} }
...@@ -1992,6 +1982,18 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -1992,6 +1982,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 && if (!is_reg &&
qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
...@@ -2019,14 +2021,10 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -2019,14 +2021,10 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
if (header.compressed == QEMUD_SAVE_FORMAT_RAW) { if (header.compressed == QEMUD_SAVE_FORMAT_RAW) {
const char *args[] = { "cat", NULL }; 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); 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, rc = qemuMonitorMigrateToFd(priv->mon,
QEMU_MONITOR_MIGRATE_BACKGROUND, QEMU_MONITOR_MIGRATE_BACKGROUND,
fd); fd);
...@@ -2035,7 +2033,6 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -2035,7 +2033,6 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
QEMU_MONITOR_MIGRATE_BACKGROUND, QEMU_MONITOR_MIGRATE_BACKGROUND,
args, path, offset); args, path, offset);
} }
VIR_FORCE_CLOSE(fd);
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
} else { } else {
const char *prog = qemudSaveCompressionTypeToString(header.compressed); const char *prog = qemudSaveCompressionTypeToString(header.compressed);
...@@ -2054,6 +2051,11 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom, ...@@ -2054,6 +2051,11 @@ static int qemudDomainSaveFlag(struct qemud_driver *driver, virDomainPtr dom,
if (rc < 0) if (rc < 0)
goto endjob; goto endjob;
if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, _("unable to close %s"), path);
goto endjob;
}
rc = qemuMigrationWaitForCompletion(driver, vm); rc = qemuMigrationWaitForCompletion(driver, vm);
if (rc < 0) if (rc < 0)
...@@ -2119,6 +2121,7 @@ endjob: ...@@ -2119,6 +2121,7 @@ endjob:
cleanup: cleanup:
qemuCapsFree(qemuCaps); qemuCapsFree(qemuCaps);
VIR_FORCE_CLOSE(fd);
VIR_FREE(xml); VIR_FREE(xml);
if (ret != 0 && is_reg) if (ret != 0 && is_reg)
unlink(path); unlink(path);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册