[libvirt] [PATCH 3/4] qemu: Don't remove hash entry of other domains
John Ferlan
jferlan at redhat.com
Fri Feb 8 21:09:23 UTC 2013
On 02/08/2013 08:08 AM, Osier Yang wrote:
> qemuProcessStart invokes qemuProcessStop when fails, to avoid
> removing hash entry which belongs to other domain(s), this introduces
> a new virBitmapPtr argument for qemuProcessStop. And qemuProcessStart
> sets the bit for the disk only if it's successfully added into the
> hash table. Thus if the argument is provided for qemuProcessStop, it
> can't remove the hash entry belongs to other domain(s).
> ---
> src/qemu/qemu_conf.c | 5 ++++-
> src/qemu/qemu_conf.h | 3 ++-
> src/qemu/qemu_driver.c | 21 +++++++++++----------
> src/qemu/qemu_migration.c | 14 +++++++-------
> src/qemu/qemu_process.c | 37 +++++++++++++++++++++++++++++--------
> src/qemu/qemu_process.h | 3 ++-
> 6 files changed, 55 insertions(+), 28 deletions(-)
>
> diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
> index 3eeea4b..a6162b6 100644
> --- a/src/qemu/qemu_conf.c
> +++ b/src/qemu/qemu_conf.c
> @@ -773,7 +773,8 @@ cleanup:
> */
> int
> qemuAddSharedDisk(virHashTablePtr sharedDisks,
> - virDomainDiskDefPtr disk)
> + virDomainDiskDefPtr disk,
> + int *added)
> {
> size_t *ref = NULL;
> char *key = NULL;
> @@ -804,6 +805,8 @@ qemuAddSharedDisk(virHashTablePtr sharedDisks,
> }
> }
>
> + if (added)
> + *added = 1;
> VIR_FREE(key);
> return 0;
> }
> diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
> index 8e84bcf..b8b5275 100644
> --- a/src/qemu/qemu_conf.h
> +++ b/src/qemu/qemu_conf.h
> @@ -270,7 +270,8 @@ void qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
> virConnectPtr conn);
>
> int qemuAddSharedDisk(virHashTablePtr sharedDisks,
> - virDomainDiskDefPtr disk)
> + virDomainDiskDefPtr disk,
> + int *added)
> ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
>
> int qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 1dc9789..03fe526 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -2098,7 +2098,7 @@ qemuDomainDestroyFlags(virDomainPtr dom,
> goto endjob;
> }
>
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED, 0, NULL);
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
> @@ -2944,7 +2944,7 @@ qemuDomainSaveInternal(virQEMUDriverPtr driver, virDomainPtr dom,
> goto endjob;
>
> /* Shut it down */
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED, 0, NULL);
> virDomainAuditStop(vm, "saved");
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> @@ -3393,7 +3393,7 @@ static int qemuDomainCoreDump(virDomainPtr dom,
>
> endjob:
> if ((ret == 0) && (flags & VIR_DUMP_CRASH)) {
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED, 0, NULL);
> virDomainAuditStop(vm, "crashed");
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> @@ -4902,7 +4902,7 @@ qemuDomainSaveImageStartVM(virConnectPtr conn,
> }
>
> if (virCommandWait(cmd, NULL) < 0) {
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0, NULL);
> ret = -1;
> }
> VIR_DEBUG("Decompression binary stderr: %s", NULLSTR(errbuf));
> @@ -5850,7 +5850,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
> }
>
> if (ret == 0) {
> - if (qemuAddSharedDisk(driver->sharedDisks, disk) < 0)
> + if (qemuAddSharedDisk(driver->sharedDisks, disk, NULL) < 0)
> VIR_WARN("Failed to add disk '%s' to shared disk table",
> disk->src);
>
> @@ -10677,7 +10677,7 @@ qemuDomainSnapshotCreateActiveInternal(virConnectPtr conn,
> if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_HALT) {
> event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
> VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0, NULL);
> virDomainAuditStop(vm, "from-snapshot");
> /* We already filtered the _HALT flag for persistent domains
> * only, so this end job never drops the last reference. */
> @@ -11232,7 +11232,7 @@ qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
>
> event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
> VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0, NULL);
> virDomainAuditStop(vm, "from-snapshot");
> /* We already filtered the _HALT flag for persistent domains
> * only, so this end job never drops the last reference. */
> @@ -12151,8 +12151,8 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
> goto endjob;
> }
> virResetError(err);
> - qemuProcessStop(driver, vm,
> - VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
> + 0, NULL);
> virDomainAuditStop(vm, "from-snapshot");
> detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
> event = virDomainEventNewFromObj(vm,
> @@ -12265,7 +12265,8 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
>
> if (virDomainObjIsActive(vm)) {
> /* Transitions 4, 7 */
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FROM_SNAPSHOT,
> + 0, NULL);
> virDomainAuditStop(vm, "from-snapshot");
> detail = VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT;
> event = virDomainEventNewFromObj(vm,
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index a75fb4e..365afe3 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -1692,7 +1692,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
> virReportSystemError(errno, "%s",
> _("cannot pass pipe for tunnelled migration"));
> virDomainAuditStart(vm, "migrated", false);
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, 0, NULL);
> goto endjob;
> }
> dataFD[1] = -1; /* 'st' owns the FD now & will close it */
> @@ -3057,7 +3057,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver,
> */
> if (!v3proto) {
> qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(vm, "migrated");
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> @@ -3359,7 +3359,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> if (!(flags & VIR_MIGRATE_OFFLINE)) {
> if (qemuMigrationVPAssociatePortProfiles(vm->def) < 0) {
> qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(vm, "failed");
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> @@ -3398,7 +3398,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> if (v3proto) {
> if (!(flags & VIR_MIGRATE_OFFLINE)) {
> qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(vm, "failed");
> }
> if (newVM)
> @@ -3446,7 +3446,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> */
> if (v3proto) {
> qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(vm, "failed");
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> @@ -3483,7 +3483,7 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
> qemuProcessAutoDestroyRemove(driver, vm);
> } else if (!(flags & VIR_MIGRATE_OFFLINE)) {
> qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(vm, "failed");
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> @@ -3554,7 +3554,7 @@ int qemuMigrationConfirm(virQEMUDriverPtr driver,
> */
> if (retcode == 0) {
> qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(vm, "migrated");
>
> event = virDomainEventNewFromObj(vm,
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 1e0876c..f820c57 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -333,7 +333,7 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> eventReason);
> - qemuProcessStop(driver, vm, stopReason, 0);
> + qemuProcessStop(driver, vm, stopReason, 0, NULL);
> virDomainAuditStop(vm, auditReason);
>
> if (!vm->persistent) {
> @@ -3340,7 +3340,7 @@ error:
> * really is and FAILED means "failed to start" */
> state = VIR_DOMAIN_SHUTOFF_UNKNOWN;
> }
> - qemuProcessStop(driver, obj, state, 0);
> + qemuProcessStop(driver, obj, state, 0, NULL);
> if (!obj->persistent)
> qemuDomainRemoveInactive(driver, obj);
> else
> @@ -3417,7 +3417,8 @@ qemuProcessReconnectHelper(virDomainObjPtr obj,
> } else if (virObjectUnref(obj)) {
> /* We can't spawn a thread and thus connect to monitor.
> * Kill qemu */
> - qemuProcessStop(src->driver, obj, VIR_DOMAIN_SHUTOFF_FAILED, 0);
> + qemuProcessStop(src->driver, obj,
> + VIR_DOMAIN_SHUTOFF_FAILED, 0, NULL);
> if (!obj->persistent)
> qemuDomainRemoveInactive(src->driver, obj);
> else
> @@ -3507,6 +3508,7 @@ int qemuProcessStart(virConnectPtr conn,
> virBitmapPtr nodemask = NULL;
> unsigned int stop_flags;
> virQEMUDriverConfigPtr cfg;
> + virBitmapPtr added_disks = NULL;
>
> /* Okay, these are just internal flags,
> * but doesn't hurt to check */
> @@ -3820,9 +3822,15 @@ int qemuProcessStart(virConnectPtr conn,
> if (cfg->clearEmulatorCapabilities)
> virCommandClearCaps(cmd);
>
> + if (!(added_disks = virBitmapNew(vm->def->ndisks))) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */
> for (i = 0; i < vm->def->ndisks; i++) {
> virDomainDiskDefPtr disk = vm->def->disks[i];
> + int added;
>
> if (vm->def->disks[i]->rawio == 1)
> #ifdef CAP_SYS_RAWIO
> @@ -3832,8 +3840,10 @@ int qemuProcessStart(virConnectPtr conn,
> _("Raw I/O is not supported on this platform"));
> #endif
>
> - if (qemuAddSharedDisk(driver->sharedDisks, disk) < 0)
> + if (qemuAddSharedDisk(driver->sharedDisks, disk, &added) < 0)
> goto cleanup;
> + if (added)
> + ignore_value(virBitmapSetBit(added_disks, i));
>
> if (qemuSetUnprivSGIO(disk) < 0)
> goto cleanup;
> @@ -4049,6 +4059,7 @@ int qemuProcessStart(virConnectPtr conn,
> }
>
> virCommandFree(cmd);
> + virBitmapFree(added_disks);
> VIR_FORCE_CLOSE(logfile);
> virObjectUnref(cfg);
>
> @@ -4062,7 +4073,8 @@ cleanup:
> virBitmapFree(nodemask);
> virCommandFree(cmd);
> VIR_FORCE_CLOSE(logfile);
> - qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED, stop_flags);
> + qemuProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED,
> + stop_flags, added_disks);
Do your virBitmapFree(added_disks) here not in called function...
> virObjectUnref(cfg);
>
> return -1;
> @@ -4113,7 +4125,8 @@ qemuProcessKill(virQEMUDriverPtr driver,
> void qemuProcessStop(virQEMUDriverPtr driver,
> virDomainObjPtr vm,
> virDomainShutoffReason reason,
> - unsigned int flags)
> + unsigned int flags,
> + virBitmapPtr added_disks)
> {
> int ret;
> int retries = 0;
> @@ -4239,9 +4252,17 @@ void qemuProcessStop(virQEMUDriverPtr driver,
>
> for (i = 0; i < vm->def->ndisks; i++) {
> virDomainDiskDefPtr disk = vm->def->disks[i];
> + bool is_added;
Initialize to false, since result can be unchanged if :
int virBitmapGetBit(virBitmapPtr bitmap, size_t b, bool *result)
{
if (bitmap->max_bit <= b)
return -1;
>
> - ignore_value(qemuRemoveSharedDisk(driver->sharedDisks, disk));
> + if (added_disks) {
> + ignore_value(virBitmapGetBit(added_disks, i, &is_added));
> + if (is_added)
> + ignore_value(qemuRemoveSharedDisk(driver->sharedDisks, disk));
> + } else {
> + ignore_value(qemuRemoveSharedDisk(driver->sharedDisks, disk));
> + }
> }
> + virBitmapFree(added_disks);
Let the caller do this. Think of it this way, if you make this call -
the local added_disks ends up NULL, but that is not reflected back in
the caller since this was passed by value and not reference. For some
this is a coding style - caller did the alloc and it should do the free.
>
> /* Clear out dynamically assigned labels */
> for (i = 0; i < vm->def->nseclabels; i++) {
> @@ -4594,7 +4615,7 @@ qemuProcessAutoDestroy(virQEMUDriverPtr driver,
>
> VIR_DEBUG("Killing domain");
> qemuProcessStop(driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED,
> - VIR_QEMU_PROCESS_STOP_MIGRATED);
> + VIR_QEMU_PROCESS_STOP_MIGRATED, NULL);
> virDomainAuditStop(dom, "destroyed");
> event = virDomainEventNewFromObj(dom,
> VIR_DOMAIN_EVENT_STOPPED,
> diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
> index 7c620d4..c4f8a6a 100644
> --- a/src/qemu/qemu_process.h
> +++ b/src/qemu/qemu_process.h
> @@ -68,7 +68,8 @@ typedef enum {
> void qemuProcessStop(virQEMUDriverPtr driver,
> virDomainObjPtr vm,
> virDomainShutoffReason reason,
> - unsigned int flags);
> + unsigned int flags,
> + virBitmapPtr added_disks);
>
> int qemuProcessAttach(virConnectPtr conn,
> virQEMUDriverPtr driver,
>
This is quite a bit of churn for the one place you needed the bitmap.
Would there be need/cause to add a field to the driver struct with the
shared disk bitmap rather than a parameter to qemuProcessStop(). Perhaps
there'd be other uses for it too (just thinking out loud late on snowy
Friday afternoon).
John
More information about the libvir-list
mailing list