mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 14:15:28 +00:00
Fix virDomainObj ref handling in QEMU driver
Since the monitor I/O is processed out of band from the main thread(s) invoking monitor commands, the virDomainObj may be deleted by the I/O thread. The qemuDomainObjBeginJob takes an extra reference to protect against final deletion, but this reference is released by the corresponding EndJob call. THus after the EndJob call it may not be valid to reference the virDomainObj any more. To allow callers to detect this, the EndJob call is changed to return the remaining reference count. * src/conf/domain_conf.c: Make virDomainObjUnref return the remaining reference count * src/qemu/qemu_driver.c: Avoid referencing virDomainObjPtr after qemuDomainObjEndJob if it has been deleted.
This commit is contained in:
parent
604c70fd5d
commit
8e7d14953c
@ -231,7 +231,7 @@ static void virDomainObjListDeallocator(void *payload, const char *name ATTRIBUT
|
||||
{
|
||||
virDomainObjPtr obj = payload;
|
||||
virDomainObjLock(obj);
|
||||
if (!virDomainObjUnref(obj))
|
||||
if (virDomainObjUnref(obj) > 0)
|
||||
virDomainObjUnlock(obj);
|
||||
}
|
||||
|
||||
@ -637,9 +637,9 @@ int virDomainObjUnref(virDomainObjPtr dom)
|
||||
if (dom->refs == 0) {
|
||||
virDomainObjUnlock(dom);
|
||||
virDomainObjFree(dom);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return dom->refs;
|
||||
}
|
||||
|
||||
static virDomainObjPtr virDomainObjNew(virConnectPtr conn,
|
||||
|
@ -371,15 +371,18 @@ static int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver,
|
||||
*
|
||||
* To be called after completing the work associated with the
|
||||
* earlier qemuDomainBeginJob() call
|
||||
*
|
||||
* Returns remaining refcount on 'obj', maybe 0 to indicated it
|
||||
* was deleted
|
||||
*/
|
||||
static void qemuDomainObjEndJob(virDomainObjPtr obj)
|
||||
static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
|
||||
{
|
||||
qemuDomainObjPrivatePtr priv = obj->privateData;
|
||||
|
||||
priv->jobActive = 0;
|
||||
virCondSignal(&priv->jobCond);
|
||||
|
||||
virDomainObjUnref(obj);
|
||||
return virDomainObjUnref(obj);
|
||||
}
|
||||
|
||||
|
||||
@ -3039,9 +3042,9 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
|
||||
goto cleanup; /* XXXX free the 'vm' we created ? */
|
||||
|
||||
if (qemudStartVMDaemon(conn, driver, vm, NULL, -1) < 0) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
vm = NULL;
|
||||
goto endjob;
|
||||
}
|
||||
@ -3054,8 +3057,9 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
|
||||
if (dom) dom->id = vm->def->id;
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
virDomainDefFree(def);
|
||||
@ -3110,7 +3114,8 @@ static int qemudDomainSuspend(virDomainPtr dom) {
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -3169,7 +3174,8 @@ static int qemudDomainResume(virDomainPtr dom) {
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -3213,7 +3219,8 @@ static int qemudDomainShutdown(virDomainPtr dom) {
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -3252,16 +3259,17 @@ static int qemudDomainDestroy(virDomainPtr dom) {
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
|
||||
if (!vm->persistent) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
vm = NULL;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -3402,7 +3410,8 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -3452,7 +3461,8 @@ static int qemudDomainGetInfo(virDomainPtr dom,
|
||||
err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
if (err < 0) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -3462,7 +3472,10 @@ static int qemudDomainGetInfo(virDomainPtr dom,
|
||||
else
|
||||
info->memory = balloon;
|
||||
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0) {
|
||||
vm = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
info->memory = vm->def->memory;
|
||||
}
|
||||
@ -3671,15 +3684,16 @@ static int qemudDomainSave(virDomainPtr dom,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_SAVED);
|
||||
if (!vm->persistent) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
vm = NULL;
|
||||
}
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (fd != -1)
|
||||
@ -3766,7 +3780,8 @@ static int qemudDomainCoreDump(virDomainPtr dom,
|
||||
}
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -3827,7 +3842,8 @@ static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -4235,9 +4251,9 @@ static int qemudDomainRestore(virConnectPtr conn,
|
||||
fd = -1;
|
||||
if (ret < 0) {
|
||||
if (!vm->persistent) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains,
|
||||
vm);
|
||||
vm = NULL;
|
||||
}
|
||||
goto endjob;
|
||||
@ -4265,8 +4281,9 @@ static int qemudDomainRestore(virConnectPtr conn,
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
virDomainDefFree(def);
|
||||
@ -4314,7 +4331,10 @@ static char *qemudDomainDumpXML(virDomainPtr dom,
|
||||
qemuDomainObjEnterMonitor(vm);
|
||||
err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0) {
|
||||
vm = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
if (err < 0)
|
||||
goto cleanup;
|
||||
if (err > 0)
|
||||
@ -4547,7 +4567,8 @@ static int qemudDomainStart(virDomainPtr dom) {
|
||||
VIR_DOMAIN_EVENT_STARTED_BOOTED);
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -5338,7 +5359,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
ret = -1;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (cgroup)
|
||||
@ -5672,7 +5694,8 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
|
||||
ret = -1;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
virDomainDeviceDefFree(dev);
|
||||
@ -5996,7 +6019,8 @@ qemudDomainBlockStats (virDomainPtr dom,
|
||||
qemuDomainObjExitMonitor(vm);
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(qemu_dev_name);
|
||||
@ -6214,7 +6238,8 @@ qemudDomainMemoryPeek (virDomainPtr dom,
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(tmp);
|
||||
@ -6708,8 +6733,8 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
|
||||
if (qemust == NULL) {
|
||||
qemudShutdownVMDaemon(NULL, driver, vm);
|
||||
if (!vm->persistent) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
vm = NULL;
|
||||
}
|
||||
virReportSystemError(dconn, errno,
|
||||
@ -6727,8 +6752,9 @@ qemudDomainMigratePrepareTunnel(virConnectPtr dconn,
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
virDomainDefFree(def);
|
||||
@ -6895,8 +6921,8 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
|
||||
* should have already done that.
|
||||
*/
|
||||
if (!vm->persistent) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
vm = NULL;
|
||||
}
|
||||
goto endjob;
|
||||
@ -6908,8 +6934,9 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
|
||||
ret = 0;
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
virDomainDefFree(def);
|
||||
@ -7399,8 +7426,8 @@ qemudDomainMigratePerform (virDomainPtr dom,
|
||||
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
|
||||
if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
|
||||
virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm);
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
vm = NULL;
|
||||
}
|
||||
ret = 0;
|
||||
@ -7424,8 +7451,9 @@ endjob:
|
||||
VIR_DOMAIN_EVENT_RESUMED,
|
||||
VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
|
||||
}
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
@ -7523,15 +7551,16 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
|
||||
VIR_DOMAIN_EVENT_STOPPED,
|
||||
VIR_DOMAIN_EVENT_STOPPED_FAILED);
|
||||
if (!vm->persistent) {
|
||||
qemuDomainObjEndJob(vm);
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
if (qemuDomainObjEndJob(vm) > 0)
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
vm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
endjob:
|
||||
if (vm)
|
||||
qemuDomainObjEndJob(vm);
|
||||
if (vm &&
|
||||
qemuDomainObjEndJob(vm) == 0)
|
||||
vm = NULL;
|
||||
|
||||
cleanup:
|
||||
if (vm)
|
||||
|
Loading…
Reference in New Issue
Block a user