diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0ad8561254cdc1669d43946ea19e94e94034bc2b..7a968fb0ec5f2745c111a61719782577921cf612 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1206,6 +1206,7 @@ virCgroupSetMemSwapHardLimit; # util/virclosecallbacks.h virCloseCallbacksGet; +virCloseCallbacksGetConn; virCloseCallbacksNew; virCloseCallbacksRun; virCloseCallbacksSet; diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index 089ba4e2a0db54949410d660050d7ba8a1f29398..65cbe9e9725dab38bf3d71863bd010ab42722588 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -35,6 +35,7 @@ # include "vircgroup.h" # include "virsysinfo.h" # include "virusb.h" +# include "virclosecallbacks.h" # define LXC_DRIVER_NAME "LXC" @@ -101,11 +102,8 @@ struct _virLXCDriver { /* Immutable pointer. self-locking APIs */ virSecurityManagerPtr securityManager; - /* Mapping of 'char *uuidstr' -> virConnectPtr - * of guests which will be automatically killed - * when the virConnectPtr is closed. - * Immutable pointer. Unsafe APIs. XXX */ - virHashTablePtr autodestroy; + /* Immutable pointer, self-locking APIs */ + virCloseCallbacksPtr closeCallbacks; }; virLXCDriverConfigPtr virLXCDriverConfigNew(void); diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 33803887b4b3e9e7db733acdc1ba20dc6a9f0a0a..63d86b99e914794e9ac145480fd1fd47d0f8c288 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -163,7 +163,7 @@ static int lxcConnectClose(virConnectPtr conn) virLXCDriverPtr driver = conn->privateData; lxcDriverLock(driver); - virLXCProcessAutoDestroyRun(driver, conn); + virCloseCallbacksRun(driver->closeCallbacks, conn, driver->domains, driver); lxcDriverUnlock(driver); conn->privateData = NULL; @@ -1591,7 +1591,7 @@ static int lxcStateInitialize(bool privileged, if (!(lxc_driver->xmlopt = lxcDomainXMLConfInit())) goto cleanup; - if (virLXCProcessAutoDestroyInit(lxc_driver) < 0) + if (!(lxc_driver->closeCallbacks = virCloseCallbacksNew())) goto cleanup; /* Get all the running persistent or transient configs first */ @@ -1681,7 +1681,7 @@ static int lxcStateCleanup(void) virObjectUnref(lxc_driver->domains); virDomainEventStateFree(lxc_driver->domainEventState); - virLXCProcessAutoDestroyShutdown(lxc_driver); + virObjectUnref(lxc_driver->closeCallbacks); virSysinfoDefFree(lxc_driver->hostsysinfo); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 4ad69ffc1fcfd7b689cefcedd2a6ad900262b5c3..ff9701f5b728ae049fd83ac3969cb155723d4d3a 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -54,122 +54,45 @@ #define START_POSTFIX ": starting up\n" -int virLXCProcessAutoDestroyInit(virLXCDriverPtr driver) +static virDomainObjPtr +lxcProcessAutoDestroy(virDomainObjPtr dom, + virConnectPtr conn, + void *opaque) { - if (!(driver->autodestroy = virHashCreate(5, NULL))) - return -1; - - return 0; -} - -struct virLXCProcessAutoDestroyData { - virLXCDriverPtr driver; - virConnectPtr conn; -}; - -static void virLXCProcessAutoDestroyDom(void *payload, - const void *name, - void *opaque) -{ - struct virLXCProcessAutoDestroyData *data = opaque; - virConnectPtr conn = payload; - const char *uuidstr = name; - unsigned char uuid[VIR_UUID_BUFLEN]; - virDomainObjPtr dom; + virLXCDriverPtr driver = opaque; virDomainEventPtr event = NULL; virLXCDomainObjPrivatePtr priv; - VIR_DEBUG("conn=%p uuidstr=%s thisconn=%p", conn, uuidstr, data->conn); - - if (data->conn != conn) - return; - - if (virUUIDParse(uuidstr, uuid) < 0) { - VIR_WARN("Failed to parse %s", uuidstr); - return; - } - - if (!(dom = virDomainObjListFindByUUID(data->driver->domains, - uuid))) { - VIR_DEBUG("No domain object to kill"); - return; - } + VIR_DEBUG("driver=%p dom=%s conn=%p", driver, dom->def->name, conn); priv = dom->privateData; VIR_DEBUG("Killing domain"); - virLXCProcessStop(data->driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED); + virLXCProcessStop(driver, dom, VIR_DOMAIN_SHUTOFF_DESTROYED); virDomainAuditStop(dom, "destroyed"); event = virDomainEventNewFromObj(dom, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_DESTROYED); priv->doneStopEvent = true; - if (dom && !dom->persistent) - virDomainObjListRemove(data->driver->domains, dom); + if (dom && !dom->persistent) { + virDomainObjListRemove(driver->domains, dom); + dom = NULL; + } - if (dom) - virObjectUnlock(dom); if (event) - virDomainEventStateQueue(data->driver->domainEventState, event); - virHashRemoveEntry(data->driver->autodestroy, uuidstr); + virDomainEventStateQueue(driver->domainEventState, event); + + return dom; } /* * Precondition: driver is locked */ -void virLXCProcessAutoDestroyRun(virLXCDriverPtr driver, virConnectPtr conn) -{ - struct virLXCProcessAutoDestroyData data = { - driver, conn - }; - VIR_DEBUG("conn=%p", conn); - virHashForEach(driver->autodestroy, virLXCProcessAutoDestroyDom, &data); -} - -void virLXCProcessAutoDestroyShutdown(virLXCDriverPtr driver) -{ - virHashFree(driver->autodestroy); -} - -int virLXCProcessAutoDestroyAdd(virLXCDriverPtr driver, - virDomainObjPtr vm, - virConnectPtr conn) -{ - char uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(vm->def->uuid, uuidstr); - VIR_DEBUG("vm=%s uuid=%s conn=%p", vm->def->name, uuidstr, conn); - if (virHashAddEntry(driver->autodestroy, uuidstr, conn) < 0) - return -1; - return 0; -} - -int virLXCProcessAutoDestroyRemove(virLXCDriverPtr driver, - virDomainObjPtr vm) -{ - char uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(vm->def->uuid, uuidstr); - VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr); - if (virHashRemoveEntry(driver->autodestroy, uuidstr) < 0) - return -1; - return 0; -} - -static virConnectPtr -virLXCProcessAutoDestroyGetConn(virLXCDriverPtr driver, - virDomainObjPtr vm) -{ - char uuidstr[VIR_UUID_STRING_BUFLEN]; - virUUIDFormat(vm->def->uuid, uuidstr); - VIR_DEBUG("vm=%s uuid=%s", vm->def->name, uuidstr); - return virHashLookup(driver->autodestroy, uuidstr); -} - - static int virLXCProcessReboot(virLXCDriverPtr driver, virDomainObjPtr vm) { - virConnectPtr conn = virLXCProcessAutoDestroyGetConn(driver, vm); + virConnectPtr conn = virCloseCallbacksGetConn(driver->closeCallbacks, vm); int reason = vm->state.reason; bool autodestroy = false; int ret = -1; @@ -243,7 +166,8 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver, } /* Stop autodestroy in case guest is restarted */ - virLXCProcessAutoDestroyRemove(driver, vm); + virCloseCallbacksUnset(driver->closeCallbacks, vm, + lxcProcessAutoDestroy); if (priv->monitor) { virLXCMonitorClose(priv->monitor); @@ -1299,7 +1223,8 @@ int virLXCProcessStart(virConnectPtr conn, } if (autoDestroy && - virLXCProcessAutoDestroyAdd(driver, vm, conn) < 0) + virCloseCallbacksSet(driver->closeCallbacks, vm, + conn, lxcProcessAutoDestroy) < 0) goto error; if (virDomainObjSetDefTransient(driver->caps, driver->xmlopt, diff --git a/src/lxc/lxc_process.h b/src/lxc/lxc_process.h index 9eb06f595081314f8218a03a4156e76cfefb3571..9c2d00e658df72320a67d17ebf5b9358d17b6e3d 100644 --- a/src/lxc/lxc_process.h +++ b/src/lxc/lxc_process.h @@ -34,7 +34,6 @@ int virLXCProcessStop(virLXCDriverPtr driver, virDomainObjPtr vm, virDomainShutoffReason reason); -int virLXCProcessAutoDestroyInit(virLXCDriverPtr driver); void virLXCProcessAutoDestroyRun(virLXCDriverPtr driver, virConnectPtr conn); void virLXCProcessAutoDestroyShutdown(virLXCDriverPtr driver); diff --git a/src/util/virclosecallbacks.c b/src/util/virclosecallbacks.c index 2100a6cdd6318b89f89335957d75bb23e3df89b6..a39be6047348ea6c2357687934c429a186f13953 100644 --- a/src/util/virclosecallbacks.c +++ b/src/util/virclosecallbacks.c @@ -208,6 +208,30 @@ virCloseCallbacksGet(virCloseCallbacksPtr closeCallbacks, return cb; } +virConnectPtr +virCloseCallbacksGetConn(virCloseCallbacksPtr closeCallbacks, + virDomainObjPtr vm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virDriverCloseDefPtr closeDef; + virConnectPtr conn = NULL; + + virUUIDFormat(vm->def->uuid, uuidstr); + VIR_DEBUG("vm=%s, uuid=%s", vm->def->name, uuidstr); + + virObjectLock(closeCallbacks); + + closeDef = virHashLookup(closeCallbacks->list, uuidstr); + if (closeDef) + conn = closeDef->conn; + + virObjectUnlock(closeCallbacks); + + VIR_DEBUG("conn=%p", conn); + return conn; +} + + typedef struct _virCloseCallbacksListEntry virCloseCallbacksListEntry; typedef virCloseCallbacksListEntry *virCloseCallbacksListEntryPtr; struct _virCloseCallbacksListEntry { diff --git a/src/util/virclosecallbacks.h b/src/util/virclosecallbacks.h index 31327c49b4f868b0e79bcc361b4a04e543a1efe4..e6b8a9e3e095ea84ca543d25ab9e0b98d1f404b2 100644 --- a/src/util/virclosecallbacks.h +++ b/src/util/virclosecallbacks.h @@ -45,6 +45,9 @@ virCloseCallback virCloseCallbacksGet(virCloseCallbacksPtr closeCallbacks, virDomainObjPtr vm, virConnectPtr conn); +virConnectPtr +virCloseCallbacksGetConn(virCloseCallbacksPtr closeCallbacks, + virDomainObjPtr vm); void virCloseCallbacksRun(virCloseCallbacksPtr closeCallbacks, virConnectPtr conn,