qemu: Alter error path cleanup for qemuDomainAttachRNGDevice

Based on recent review comment - rather than have a spate of goto failxxxx,
change to a boolean based model. Ensures that the original error can be
preserved and cleanup is a bit more orderly if more objects are added.
This commit is contained in:
John Ferlan 2016-07-14 18:13:50 -04:00
parent 05bc30d2bb
commit 47208776be

View File

@ -1581,12 +1581,17 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
virDomainRNGDefPtr rng) virDomainRNGDefPtr rng)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virErrorPtr orig_err;
char *devstr = NULL; char *devstr = NULL;
char *charAlias = NULL; char *charAlias = NULL;
char *objAlias = NULL; char *objAlias = NULL;
bool releaseaddr = false;
bool chardevAdded = false;
bool objAdded = false;
virJSONValuePtr props = NULL; virJSONValuePtr props = NULL;
const char *type; const char *type;
int ret = -1; int ret = -1;
int rv;
if (qemuAssignDeviceRNGAlias(vm->def, rng) < 0) if (qemuAssignDeviceRNGAlias(vm->def, rng) < 0)
return -1; return -1;
@ -1607,6 +1612,7 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
rng->source.file)) rng->source.file))
return -1; return -1;
} }
releaseaddr = true;
if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
@ -1631,23 +1637,25 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0) if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0)
goto cleanup; goto cleanup;
/* attach the device - up to a 3 stage process */
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD && if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
qemuMonitorAttachCharDev(priv->mon, charAlias, qemuMonitorAttachCharDev(priv->mon, charAlias,
rng->source.chardev) < 0) rng->source.chardev) < 0)
goto failchardev; goto exit_monitor;
chardevAdded = true;
if (qemuMonitorAddObject(priv->mon, type, objAlias, props) < 0) rv = qemuMonitorAddObject(priv->mon, type, objAlias, props);
goto failbackend; props = NULL; /* qemuMonitorAddObject consumes */
props = NULL; if (rv < 0)
goto exit_monitor;
objAdded = true;
if (qemuMonitorAddDevice(priv->mon, devstr) < 0) if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
goto failfrontend; goto exit_monitor;
if (qemuDomainObjExitMonitor(driver, vm) < 0) { if (qemuDomainObjExitMonitor(driver, vm) < 0) {
vm = NULL; releaseaddr = false;
goto cleanup; goto cleanup;
} }
@ -1659,26 +1667,26 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0); virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0);
cleanup: cleanup:
virJSONValueFree(props); virJSONValueFree(props);
if (ret < 0 && vm) if (ret < 0 && releaseaddr)
qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL); qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL);
VIR_FREE(charAlias); VIR_FREE(charAlias);
VIR_FREE(objAlias); VIR_FREE(objAlias);
VIR_FREE(devstr); VIR_FREE(devstr);
return ret; return ret;
/* rollback */ exit_monitor:
failfrontend: orig_err = virSaveLastError();
ignore_value(qemuMonitorDelObject(priv->mon, objAlias)); if (objAdded)
failbackend: ignore_value(qemuMonitorDelObject(priv->mon, objAlias));
if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD && chardevAdded)
ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias)); ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias));
props = NULL; /* qemuMonitorAddObject consumes on failure */ if (orig_err) {
failchardev: virSetError(orig_err);
if (qemuDomainObjExitMonitor(driver, vm) < 0) { virFreeError(orig_err);
vm = NULL;
goto cleanup;
} }
if (qemuDomainObjExitMonitor(driver, vm) < 0)
releaseaddr = false;
goto audit; goto audit;
} }