Surprisingly, nothing special is happening here. If we are the
first to use the managed helper then spawn it. If not, we're
almost done.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_hotplug.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 6b245bd6a..ded666633 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -350,6 +350,84 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
}
+static int
+qemuBuildPRDefInfoProps(virDomainObjPtr vm,
+ virDomainDiskDefPtr disk,
+ virJSONValuePtr *prmgrProps,
+ const char **prAlias)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuDomainStorageSourcePrivatePtr srcPriv;
+ qemuDomainDiskPRObjectPtr tmp;
+ virJSONValuePtr props = NULL;
+ int ret = -1;
+
+ srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
+
+ *prmgrProps = NULL;
+
+ if (!priv->prHelpers ||
+ !srcPriv->prAlias ||
+ !(tmp = virHashLookup(priv->prHelpers, srcPriv->prAlias)))
+ return 0;
+
+ if (qemuDomainGetPRUsageCount(vm->def, srcPriv->prAlias) != 0) {
+ /* We're not the first ones to use pr-manager with that
+ * alias. Return early and leave @prmgrProps NULL so
+ * that caller knows this. */
+ return 0;
+ }
+
+ if (virJSONValueObjectCreate(&props,
+ "s:path", tmp->path,
+ NULL) < 0)
+ goto cleanup;
+
+ if (qemuProcessSetupPRDaemon(vm, tmp, srcPriv->prAlias) < 0)
+ goto cleanup;
+
+ *prAlias = srcPriv->prAlias;
+ *prmgrProps = props;
+ props = NULL;
+ ret = 0;
+ cleanup:
+ virJSONValueFree(props);
+ return ret;
+}
+
+
+static void
+qemuDestroyPRDefObject(virDomainObjPtr vm,
+ virDomainDiskDefPtr disk)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ qemuDomainStorageSourcePrivatePtr srcPriv;
+ qemuDomainDiskPRObjectPtr tmp;
+
+ srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(disk->src);
+
+ if (!priv->prHelpers ||
+ !srcPriv->prAlias ||
+ !(tmp = virHashLookup(priv->prHelpers, srcPriv->prAlias)))
+ return;
+
+ if (qemuDomainGetPRUsageCount(vm->def, srcPriv->prAlias) > 1) {
+ /* The function might return one or even zero if the
+ * pr-manager is unused depending whether the disk was
+ * added to domain def already or not. Anyway, if the
+ * return value is greater than one we are certain that
+ * there's another disk using it so return early. */
+ return;
+ }
+
+ /* This also kills the pr-manager daemon. See
+ * qemuDomainDiskPRObjectHashFree. */
+ virHashRemoveEntry(priv->prHelpers, srcPriv->prAlias);
+
+ VIR_FREE(srcPriv->prAlias);
+}
+
+
/**
* qemuDomainAttachDiskGeneric:
*
@@ -368,12 +446,15 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
char *devstr = NULL;
char *drivestr = NULL;
char *drivealias = NULL;
+ const char *prAlias = NULL;
bool driveAdded = false;
bool secobjAdded = false;
bool encobjAdded = false;
+ bool prmgrAdded = false;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virJSONValuePtr secobjProps = NULL;
virJSONValuePtr encobjProps = NULL;
+ virJSONValuePtr prmgrProps = NULL;
qemuDomainStorageSourcePrivatePtr srcPriv;
qemuDomainSecretInfoPtr secinfo = NULL;
qemuDomainSecretInfoPtr encinfo = NULL;
@@ -406,6 +487,9 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
disk->info.alias) < 0)
goto error;
+ if (qemuBuildPRDefInfoProps(vm, disk, &prmgrProps, &prAlias) < 0)
+ goto error;
+
if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
goto error;
@@ -438,6 +522,15 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
encobjAdded = true;
}
+ if (prmgrProps) {
+ rv = qemuMonitorAddObject(priv->mon, "pr-manager-helper", prAlias,
+ prmgrProps);
+ prmgrProps = NULL; /* qemuMonitorAddObject consumes */
+ if (rv < 0)
+ goto exit_monitor;
+ prmgrAdded = true;
+ }
+
if (qemuMonitorAddDrive(priv->mon, drivestr) < 0)
goto exit_monitor;
driveAdded = true;
@@ -458,6 +551,7 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
cleanup:
virJSONValueFree(secobjProps);
virJSONValueFree(encobjProps);
+ virJSONValueFree(prmgrProps);
qemuDomainSecretDiskDestroy(disk);
VIR_FREE(devstr);
VIR_FREE(drivestr);
@@ -475,6 +569,8 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
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, prAlias));
if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -2;
virErrorRestore(&orig_err);
@@ -484,6 +580,7 @@ qemuDomainAttachDiskGeneric(virConnectPtr conn,
error:
qemuDomainDelDiskSrcTLSObject(driver, vm, disk->src);
ignore_value(qemuHotplugPrepareDiskAccess(driver, vm, disk, NULL, true));
+ qemuDestroyPRDefObject(vm, disk);
goto cleanup;
}
--
2.13.6