diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0af171eb2fd6073848040225ce896167cfe66167..142863e668112dd83596331dabbefaf30cd62ec2 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 f2c7b611cedfdff1b441a03b18cbdfcc3b5f7a51..39e0e800ab12d18489a0432d597e234ea4fa84d6 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 2445e13936333d3865017ff8bee786471d61142e..2c67a02bf60631ba50223a3add15a8c1fd4e1639 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);