diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 8b3acf2957ddf8044aae39424fc2d104f47f68db..bb659731b77f805308fc26bb90736f58f159f1ca 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2206,6 +2206,35 @@ qemuBulildFloppyCommandLineOptions(virCommandPtr cmd, } +static int +qemuBuildDiskUnmanagedPRCommandLine(virCommandPtr cmd, + virStorageSourcePtr src) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virJSONValuePtr props = NULL; + int ret = -1; + + if (!src->pr || + virStoragePRDefIsManaged(src->pr)) + return 0; + + if (!(props = qemuBuildPRManagerInfoProps(src))) + return -1; + + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + goto cleanup; + + virCommandAddArg(cmd, "-object"); + virCommandAddArgBuffer(cmd, &buf); + + ret = 0; + cleanup: + virBufferFreeAndReset(&buf); + virJSONValueFree(props); + return ret; +} + + static int qemuBuildDiskDriveCommandLine(virCommandPtr cmd, const virDomainDef *def, @@ -2273,6 +2302,9 @@ qemuBuildDiskDriveCommandLine(virCommandPtr cmd, } } + if (qemuBuildDiskUnmanagedPRCommandLine(cmd, disk->src) < 0) + return -1; + if (qemuBuildDiskSecinfoCommandLine(cmd, secinfo) < 0) return -1; @@ -9694,58 +9726,77 @@ qemuBuildPanicCommandLine(virCommandPtr cmd, } +static virJSONValuePtr +qemuBuildPRManagerInfoPropsInternal(const char *alias, + const char *path) +{ + virJSONValuePtr ret = NULL; + + if (qemuMonitorCreateObjectProps(&ret, + "pr-manager-helper", alias, + "s:path", path, NULL) < 0) + return NULL; + + return ret; +} + + /** - * qemuBuildPRManagerInfoProps: - * @src: storage source + * qemuBuildPRManagedManagerInfoProps: * - * Build the JSON properties for the pr-manager object. + * Build the JSON properties for the pr-manager object corresponding to the PR + * daemon managed by libvirt. */ virJSONValuePtr -qemuBuildPRManagerInfoProps(virStorageSourcePtr src) +qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivatePtr priv) { + char *path = NULL; virJSONValuePtr ret = NULL; - if (qemuMonitorCreateObjectProps(&ret, - "pr-manager-helper", src->pr->mgralias, - "s:path", src->pr->path, NULL) < 0) + if (!(path = qemuDomainGetManagedPRSocketPath(priv))) return NULL; + ret = qemuBuildPRManagerInfoPropsInternal(qemuDomainGetManagedPRAlias(), + path); + + VIR_FREE(path); return ret; } +/** + * qemuBuildPRManagerInfoProps: + * @src: storage source + * + * Build the JSON properties for the pr-manager object. + */ +virJSONValuePtr +qemuBuildPRManagerInfoProps(virStorageSourcePtr src) +{ + return qemuBuildPRManagerInfoPropsInternal(src->pr->mgralias, src->pr->path); +} + + static int -qemuBuildMasterPRCommandLine(virCommandPtr cmd, - const virDomainDef *def) +qemuBuildManagedPRCommandLine(virCommandPtr cmd, + const virDomainDef *def, + qemuDomainObjPrivatePtr priv) { virBuffer buf = VIR_BUFFER_INITIALIZER; - size_t i; - bool managedAdded = false; virJSONValuePtr props = NULL; int ret = -1; - for (i = 0; i < def->ndisks; i++) { - const virDomainDiskDef *disk = def->disks[i]; - - if (!disk->src->pr) - continue; - - if (virStoragePRDefIsManaged(disk->src->pr)) { - if (managedAdded) - continue; - - managedAdded = true; - } + if (!virDomainDefHasManagedPR(def)) + return 0; - if (!(props = qemuBuildPRManagerInfoProps(disk->src))) - goto cleanup; + if (!(props = qemuBuildPRManagedManagerInfoProps(priv))) + return -1; - if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) - goto cleanup; + if (virQEMUBuildObjectCommandlineFromJSON(&buf, props) < 0) + goto cleanup; - virCommandAddArg(cmd, "-object"); - virCommandAddArgBuffer(cmd, &buf); - } + virCommandAddArg(cmd, "-object"); + virCommandAddArgBuffer(cmd, &buf); ret = 0; cleanup: @@ -9977,7 +10028,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildMasterKeyCommandLine(cmd, priv) < 0) goto error; - if (qemuBuildMasterPRCommandLine(cmd, def) < 0) + if (qemuBuildManagedPRCommandLine(cmd, def, priv) < 0) goto error; if (enableFips) diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 5bf9461846acc3c586fbb4e8666dcc9375010605..f473d3b788353a46a067673aea1d85ee5052953e 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -56,6 +56,7 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver, /* Generate the object properties for pr-manager */ virJSONValuePtr qemuBuildPRManagerInfoProps(virStorageSourcePtr src); +virJSONValuePtr qemuBuildPRManagedManagerInfoProps(qemuDomainObjPrivatePtr priv); /* Generate the object properties for a secret */ int qemuBuildSecretInfoProps(qemuDomainSecretInfoPtr secinfo, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index bea8d6ac85e76675ece0e5fff9a923e269723061..bffd59a419721ee3b0e6aa40822e49ef6f325b72 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -350,60 +350,40 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver, * qemuDomainMaybeStartPRDaemon: * @vm: domain object * @disk: disk to hotplug + * @retProps: properties of the managed pr-manager-helper object which needs + * to be added to the running vm * - * Checks if it's needed to start qemu-pr-helper and starts it. + * Checks if it's needed to start qemu-pr-helper and add the corresponding + * pr-manager-helper object. * - * Returns: 0 if qemu-pr-helper is not needed - * 1 if it is needed and was started - * -1 otherwise. + * Returns: 0 on success, -1 on error. If @retProps is populated the + * qemu-pr-helper daemon was started. */ static int -qemuDomainMaybeStartPRDaemon(virDomainObjPtr vm, - virDomainDiskDefPtr disk) +qemuDomainDiskAttachManagedPR(virDomainObjPtr vm, + virDomainDiskDefPtr disk, + virJSONValuePtr *retProps) { qemuDomainObjPrivatePtr priv = vm->privateData; + virJSONValuePtr props = NULL; + int ret = -1; - 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. */ + if (priv->prDaemonRunning || + !virStorageSourceChainHasManagedPR(disk->src)) return 0; - } - /* @disk requires qemu-pr-helper but none is running. - * Start it now. */ - if (qemuProcessStartManagedPRDaemon(vm) < 0) + if (!(props = qemuBuildPRManagedManagerInfoProps(priv))) return -1; - return 1; -} - - -static int -qemuMaybeBuildPRManagerInfoProps(virDomainObjPtr vm, - const virDomainDiskDef *disk, - virJSONValuePtr *propsret) -{ - qemuDomainObjPrivatePtr priv = vm->privateData; - - *propsret = NULL; - - if (!disk->src->pr) - return 0; - - if (virStoragePRDefIsManaged(disk->src->pr) && - priv->prDaemonRunning) { - /* @disk requires qemu-pr-helper but there's already one running. */ - return 0; - } + if (qemuProcessStartManagedPRDaemon(vm) < 0) + goto cleanup; - if (!(*propsret = qemuBuildPRManagerInfoProps(disk->src))) - return -1; + VIR_STEAL_PTR(*retProps, props); + ret = 0; - return 0; + cleanup: + virJSONValueFree(props); + return ret; } @@ -418,21 +398,21 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, virDomainDiskDefPtr disk) { int ret = -1; - int rv; qemuDomainObjPrivatePtr priv = vm->privateData; virErrorPtr orig_err; char *devstr = NULL; char *drivestr = NULL; char *drivealias = NULL; - char *prmgrAlias = NULL; + char *unmanagedPrmgrAlias = NULL; + char *managedPrmgrAlias = NULL; char *encobjAlias = NULL; char *secobjAlias = NULL; bool driveAdded = false; - bool prdStarted = false; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virJSONValuePtr secobjProps = NULL; virJSONValuePtr encobjProps = NULL; - virJSONValuePtr prmgrProps = NULL; + virJSONValuePtr unmanagedPrmgrProps = NULL; + virJSONValuePtr managedPrmgrProps = NULL; qemuDomainStorageSourcePrivatePtr srcPriv; qemuDomainSecretInfoPtr secinfo = NULL; qemuDomainSecretInfoPtr encinfo = NULL; @@ -460,16 +440,13 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, if (encinfo && qemuBuildSecretInfoProps(encinfo, &encobjProps) < 0) goto error; - if (qemuMaybeBuildPRManagerInfoProps(vm, disk, &prmgrProps) < 0) + if (qemuDomainDiskAttachManagedPR(vm, disk, &managedPrmgrProps) < 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) + if (disk->src->pr && + !virStoragePRDefIsManaged(disk->src->pr) && + !(unmanagedPrmgrProps = qemuBuildPRManagerInfoProps(disk->src))) goto error; - else if (rv > 0) - prdStarted = true; if (disk->src->haveTLS == VIR_TRISTATE_BOOL_YES && qemuDomainAddDiskSrcTLSObject(driver, vm, disk->src) < 0) @@ -497,8 +474,12 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, qemuMonitorAddObject(priv->mon, &encobjProps, &encobjAlias) < 0) goto exit_monitor; - if (prmgrProps && - qemuMonitorAddObject(priv->mon, &prmgrProps, &prmgrAlias) < 0) + if (managedPrmgrProps && + qemuMonitorAddObject(priv->mon, &managedPrmgrProps, &managedPrmgrAlias) < 0) + goto exit_monitor; + + if (unmanagedPrmgrProps && + qemuMonitorAddObject(priv->mon, &unmanagedPrmgrProps, &unmanagedPrmgrAlias) < 0) goto exit_monitor; if (qemuMonitorAddDrive(priv->mon, drivestr) < 0) @@ -519,11 +500,13 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, ret = 0; cleanup: - virJSONValueFree(prmgrProps); + virJSONValueFree(managedPrmgrProps); + virJSONValueFree(unmanagedPrmgrProps); virJSONValueFree(encobjProps); virJSONValueFree(secobjProps); qemuDomainSecretDiskDestroy(disk); - VIR_FREE(prmgrAlias); + VIR_FREE(managedPrmgrAlias); + VIR_FREE(unmanagedPrmgrAlias); VIR_FREE(secobjAlias); VIR_FREE(encobjAlias); VIR_FREE(drivealias); @@ -542,8 +525,10 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, ignore_value(qemuMonitorDelObject(priv->mon, secobjAlias)); if (encobjAlias) ignore_value(qemuMonitorDelObject(priv->mon, encobjAlias)); - if (prmgrAlias) - ignore_value(qemuMonitorDelObject(priv->mon, prmgrAlias)); + if (unmanagedPrmgrAlias) + ignore_value(qemuMonitorDelObject(priv->mon, unmanagedPrmgrAlias)); + if (managedPrmgrAlias) + ignore_value(qemuMonitorDelObject(priv->mon, managedPrmgrAlias)); if (qemuDomainObjExitMonitor(driver, vm) < 0) ret = -2; virErrorRestore(&orig_err); @@ -553,7 +538,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, error: qemuDomainDelDiskSrcTLSObject(driver, vm, disk->src); ignore_value(qemuHotplugPrepareDiskAccess(driver, vm, disk, NULL, true)); - if (prdStarted) + if (priv->prDaemonRunning && + !virDomainDefHasManagedPR(vm->def)) qemuProcessKillManagedPRDaemon(vm); goto cleanup; } diff --git a/tests/qemuxml2argvdata/disk-virtio-scsi-reservations.x86_64-latest.args b/tests/qemuxml2argvdata/disk-virtio-scsi-reservations.x86_64-latest.args index 768bc22f9fd641a93471f2f5efd9bd2c600f1f70..90843a19f54b27732b11dfc91e930a7dccb4ca19 100644 --- a/tests/qemuxml2argvdata/disk-virtio-scsi-reservations.x86_64-latest.args +++ b/tests/qemuxml2argvdata/disk-virtio-scsi-reservations.x86_64-latest.args @@ -11,8 +11,6 @@ QEMU_AUDIO_DRV=none \ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ -object pr-manager-helper,id=pr-helper0,\ path=/tmp/lib/domain--1-QEMUGuest1/pr-helper0.sock \ --object pr-manager-helper,id=pr-helper-scsi0-0-0-1,\ -path=/path/to/qemu-pr-helper.sock \ -machine pc-i440fx-2.12,accel=tcg,usb=off,dump-guest-core=off \ -m 214 \ -realtime mlock=off \ @@ -34,6 +32,8 @@ server,nowait \ if=none,id=drive-scsi0-0-0-0 \ -device scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=0,\ drive=drive-scsi0-0-0-0,id=scsi0-0-0-0,bootindex=1 \ +-object pr-manager-helper,id=pr-helper-scsi0-0-0-1,\ +path=/path/to/qemu-pr-helper.sock \ -drive file=/dev/HostVG/QEMUGuest2,file.pr-manager=pr-helper-scsi0-0-0-1,\ format=raw,if=none,id=drive-scsi0-0-0-1 \ -device scsi-block,bus=scsi0.0,channel=0,scsi-id=0,lun=1,\