From 23087cfdbd7380eb41605763986d43c7cd2f603b Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 15 Feb 2016 17:17:02 +0100 Subject: [PATCH] qemu: migration: Refactor code now that we assume support for fd migration After removing capability check for fd migration the code that was left behind didn't make quite sense. The old exec migration would be used in case when pipe() failed. Remove the old code and make failure of pipe() a hard error. This additionally removes usage of virCgroupAllowDevicePath outside of qemu_cgroup.c. --- src/qemu/qemu_driver.c | 8 +-- src/qemu/qemu_migration.c | 119 ++++++++++++-------------------------- src/qemu/qemu_migration.h | 9 ++- 3 files changed, 44 insertions(+), 92 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0af171eb2f..142863e668 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3188,9 +3188,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver, goto cleanup; /* Perform the migration */ - if (qemuMigrationToFile(driver, vm, fd, offset, path, - qemuCompressProgramName(compressed), - bypassSecurityDriver, + if (qemuMigrationToFile(driver, vm, fd, qemuCompressProgramName(compressed), asyncJob) < 0) goto cleanup; @@ -3691,8 +3689,8 @@ doCoreDump(virQEMUDriverPtr driver, if (!qemuMigrationIsAllowed(driver, vm, false, 0)) goto cleanup; - ret = qemuMigrationToFile(driver, vm, fd, 0, path, - qemuCompressProgramName(compress), false, + ret = qemuMigrationToFile(driver, vm, fd, + qemuCompressProgramName(compress), QEMU_ASYNC_JOB_DUMP); } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index f2c7b611ce..39e0e800ab 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -5940,15 +5940,13 @@ qemuMigrationFinish(virQEMUDriverPtr driver, /* Helper function called while vm is active. */ int qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, - int fd, off_t offset, const char *path, + int fd, const char *compressor, - bool bypassSecurityDriver, qemuDomainAsyncJob asyncJob) { qemuDomainObjPrivatePtr priv = vm->privateData; int rc; int ret = -1; - bool restoreLabel = false; virCommandPtr cmd = NULL; int pipeFD[2] = { -1, -1 }; unsigned long saveMigBandwidth = priv->migMaxBandwidth; @@ -5972,54 +5970,27 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, return -1; } - if ((!compressor || pipe(pipeFD) == 0)) { - /* All right! We can use fd migration, which means that qemu - * doesn't have to open() the file, so while we still have to - * grant SELinux access, we can do it on fd and avoid cleanup - * later, as well as skip futzing with cgroup. */ - if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def, - compressor ? pipeFD[1] : fd) < 0) - goto cleanup; - bypassSecurityDriver = true; - } else { - /* Phooey - we have to fall back on exec migration, where qemu - * has to popen() the file by name, and block devices have to be - * given cgroup ACL permission. We might also stumble on - * a race present in some qemu versions where it does a wait() - * that botches pclose. */ - if (virCgroupHasController(priv->cgroup, - VIR_CGROUP_CONTROLLER_DEVICES)) { - int rv = virCgroupAllowDevicePath(priv->cgroup, path, - VIR_CGROUP_DEVICE_RW); - virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path, "rw", rv == 0); - if (rv == 1) { - /* path was not a device, no further need for cgroup */ - } else if (rv < 0) { - goto cleanup; - } - } - if ((!bypassSecurityDriver) && - virSecurityManagerSetSavedStateLabel(driver->securityManager, - vm->def, path) < 0) - goto cleanup; - restoreLabel = true; + if (compressor && pipe(pipeFD) < 0) { + virReportSystemError(errno, "%s", + _("Failed to create pipe for migration")); + return -1; } + /* All right! We can use fd migration, which means that qemu + * doesn't have to open() the file, so while we still have to + * grant SELinux access, we can do it on fd and avoid cleanup + * later, as well as skip futzing with cgroup. */ + if (virSecurityManagerSetImageFDLabel(driver->securityManager, vm->def, + compressor ? pipeFD[1] : fd) < 0) + goto cleanup; + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) goto cleanup; if (!compressor) { - const char *args[] = { "cat", NULL }; - - if (priv->monConfig->type == VIR_DOMAIN_CHR_TYPE_UNIX) { - rc = qemuMonitorMigrateToFd(priv->mon, - QEMU_MONITOR_MIGRATE_BACKGROUND, - fd); - } else { - rc = qemuMonitorMigrateToFile(priv->mon, - QEMU_MONITOR_MIGRATE_BACKGROUND, - args, path, offset); - } + rc = qemuMonitorMigrateToFd(priv->mon, + QEMU_MONITOR_MIGRATE_BACKGROUND, + fd); } else { const char *prog = compressor; const char *args[] = { @@ -6027,33 +5998,28 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, "-c", NULL }; - if (pipeFD[0] != -1) { - cmd = virCommandNewArgs(args); - virCommandSetInputFD(cmd, pipeFD[0]); - virCommandSetOutputFD(cmd, &fd); - virCommandSetErrorBuffer(cmd, &errbuf); - virCommandDoAsyncIO(cmd); - if (virSetCloseExec(pipeFD[1]) < 0) { - virReportSystemError(errno, "%s", - _("Unable to set cloexec flag")); - ignore_value(qemuDomainObjExitMonitor(driver, vm)); - goto cleanup; - } - if (virCommandRunAsync(cmd, NULL) < 0) { - ignore_value(qemuDomainObjExitMonitor(driver, vm)); - goto cleanup; - } - rc = qemuMonitorMigrateToFd(priv->mon, - QEMU_MONITOR_MIGRATE_BACKGROUND, - pipeFD[1]); - if (VIR_CLOSE(pipeFD[0]) < 0 || - VIR_CLOSE(pipeFD[1]) < 0) - VIR_WARN("failed to close intermediate pipe"); - } else { - rc = qemuMonitorMigrateToFile(priv->mon, - QEMU_MONITOR_MIGRATE_BACKGROUND, - args, path, offset); + + cmd = virCommandNewArgs(args); + virCommandSetInputFD(cmd, pipeFD[0]); + virCommandSetOutputFD(cmd, &fd); + virCommandSetErrorBuffer(cmd, &errbuf); + virCommandDoAsyncIO(cmd); + if (virSetCloseExec(pipeFD[1]) < 0) { + virReportSystemError(errno, "%s", + _("Unable to set cloexec flag")); + ignore_value(qemuDomainObjExitMonitor(driver, vm)); + goto cleanup; } + if (virCommandRunAsync(cmd, NULL) < 0) { + ignore_value(qemuDomainObjExitMonitor(driver, vm)); + goto cleanup; + } + rc = qemuMonitorMigrateToFd(priv->mon, + QEMU_MONITOR_MIGRATE_BACKGROUND, + pipeFD[1]); + if (VIR_CLOSE(pipeFD[0]) < 0 || + VIR_CLOSE(pipeFD[1]) < 0) + VIR_WARN("failed to close intermediate pipe"); } if (qemuDomainObjExitMonitor(driver, vm) < 0) goto cleanup; @@ -6100,17 +6066,6 @@ qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, VIR_FREE(errbuf); virCommandFree(cmd); } - if (restoreLabel && (!bypassSecurityDriver) && - virSecurityManagerRestoreSavedStateLabel(driver->securityManager, - vm->def, path) < 0) - VIR_WARN("failed to restore save state label on %s", path); - - if (virCgroupHasController(priv->cgroup, - VIR_CGROUP_CONTROLLER_DEVICES)) { - int rv = virCgroupDenyDevicePath(priv->cgroup, path, - VIR_CGROUP_DEVICE_RWM); - virDomainAuditCgroupPath(vm, priv->cgroup, "deny", path, "rwm", rv == 0); - } if (orig_err) { virSetError(orig_err); diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 2445e13936..2c67a02bf6 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -176,13 +176,12 @@ int qemuMigrationConfirm(virConnectPtr conn, bool qemuMigrationIsAllowed(virQEMUDriverPtr driver, virDomainObjPtr vm, bool remote, unsigned int flags); -int qemuMigrationToFile(virQEMUDriverPtr driver, virDomainObjPtr vm, - int fd, off_t offset, const char *path, +int qemuMigrationToFile(virQEMUDriverPtr driver, + virDomainObjPtr vm, + int fd, const char *compressor, - bool bypassSecurityDriver, qemuDomainAsyncJob asyncJob) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5) - ATTRIBUTE_RETURN_CHECK; + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; int qemuMigrationCancel(virQEMUDriverPtr driver, virDomainObjPtr vm); -- GitLab