When attaching a disk that requires pr-manager we might need to plug the pr-manager object and start the pr-helper process. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- src/qemu/qemu_hotplug.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_process.c | 4 +-- src/qemu/qemu_process.h | 5 +++ 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index df9e8aa716..2e736873d1 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -348,6 +348,63 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver, } +/** + * qemuDomainMaybeStartPRDaemon: + * @vm: domain object + * @disk: disk to hotplug + * + * Checks if it's needed to start qemu-pr-helper and starts it. + * + * Returns: 0 if qemu-pr-helper is not needed + * 1 if it is needed and was started + * -1 otherwise. + */ +static int +qemuDomainMaybeStartPRDaemon(virDomainObjPtr vm, + virDomainDiskDefPtr disk) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (!virStoragePRDefIsManaged(disk->src->pr)) { + /* @disk itself does not require qemu-pr-helper. */ + return 0; + } + + if (priv->prDaemonRunning) { + /* @disk requires qemu-pr-helper but there's already one running. */ + return 0; + } + + /* @disk requires qemu-pr-helper but none is running. + * Start it now. */ + if (qemuProcessStartPRDaemon(vm, disk) < 0) + return -1; + + return 1; +} + + +static int +qemuMaybeBuildPRManagerInfoProps(virDomainObjPtr vm, + const virDomainDiskDef *disk, + virJSONValuePtr *propsret, + char **aliasret) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + + *propsret = NULL; + *aliasret = NULL; + + if (virStoragePRDefIsManaged(disk->src->pr) && + priv->prDaemonRunning) { + /* @disk requires qemu-pr-helper but there's already one running. */ + return 0; + } + + return qemuBuildPRManagerInfoProps(vm, disk, propsret, aliasret); +} + + /** * qemuDomainAttachDiskGeneric: * @@ -365,12 +422,16 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, char *devstr = NULL; char *drivestr = NULL; char *drivealias = NULL; + char *prmgrAlias = NULL; bool driveAdded = false; bool secobjAdded = false; bool encobjAdded = false; + bool prmgrAdded = false; + bool prdStarted = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virJSONValuePtr secobjProps = NULL; virJSONValuePtr encobjProps = NULL; + virJSONValuePtr prmgrProps = NULL; qemuDomainStorageSourcePrivatePtr srcPriv; qemuDomainSecretInfoPtr secinfo = NULL; qemuDomainSecretInfoPtr encinfo = NULL; @@ -398,6 +459,17 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, if (encinfo && qemuBuildSecretInfoProps(encinfo, &encobjProps) < 0) goto error; + if (qemuMaybeBuildPRManagerInfoProps(vm, disk, &prmgrProps, &prmgrAlias) < 0) + goto error; + + /* Start daemon only after prmgrProps is built. Otherwise + * qemuDomainMaybeStartPRDaemon() might start daemon and set + * priv->prDaemonRunning which confuses props building code. */ + if ((rv = qemuDomainMaybeStartPRDaemon(vm, disk)) < 0) + goto error; + else if (rv > 0) + prdStarted = true; + if (disk->src->haveTLS && qemuDomainAddDiskSrcTLSObject(driver, vm, disk->src, disk->info.alias) < 0) @@ -435,6 +507,15 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, encobjAdded = true; } + if (prmgrProps) { + rv = qemuMonitorAddObject(priv->mon, "pr-manager-helper", prmgrAlias, + prmgrProps); + prmgrProps = NULL; /* qemuMonitorAddObject consumes */ + if (rv < 0) + goto exit_monitor; + prmgrAdded = true; + } + if (qemuMonitorAddDrive(priv->mon, drivestr) < 0) goto exit_monitor; driveAdded = true; @@ -453,12 +534,14 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, ret = 0; cleanup: - virJSONValueFree(secobjProps); + virJSONValueFree(prmgrProps); virJSONValueFree(encobjProps); + virJSONValueFree(secobjProps); qemuDomainSecretDiskDestroy(disk); - VIR_FREE(devstr); - VIR_FREE(drivestr); + VIR_FREE(prmgrAlias); VIR_FREE(drivealias); + VIR_FREE(drivestr); + VIR_FREE(devstr); virObjectUnref(cfg); return ret; @@ -472,6 +555,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, ignore_value(qemuMonitorDelObject(priv->mon, secinfo->s.aes.alias)); if (encobjAdded) ignore_value(qemuMonitorDelObject(priv->mon, encinfo->s.aes.alias)); + if (prmgrAdded) + ignore_value(qemuMonitorDelObject(priv->mon, prmgrAlias)); if (qemuDomainObjExitMonitor(driver, vm) < 0) ret = -2; virErrorRestore(&orig_err); @@ -481,6 +566,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, error: qemuDomainDelDiskSrcTLSObject(driver, vm, disk->src); ignore_value(qemuHotplugPrepareDiskAccess(driver, vm, disk, NULL, true)); + if (prdStarted) + qemuProcessKillPRDaemon(vm); goto cleanup; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 36cfa438ed..b0c22001d1 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2565,7 +2565,7 @@ qemuProcessBuildPRHelperPidfilePath(virDomainObjPtr vm, } -static void +void qemuProcessKillPRDaemon(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv = vm->privateData; @@ -2629,7 +2629,7 @@ qemuProcessStartPRDaemonHook(void *opaque) } -static int +int qemuProcessStartPRDaemon(virDomainObjPtr vm, const virDomainDiskDef *disk) { diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index 3bf66f71b7..eda6695415 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -205,4 +205,9 @@ int qemuProcessRefreshDisks(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob asyncJob); +int qemuProcessStartPRDaemon(virDomainObjPtr vm, + const virDomainDiskDef *disk); + +void qemuProcessKillPRDaemon(virDomainObjPtr vm); + #endif /* __QEMU_PROCESS_H__ */ -- 2.16.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list