[libvirt] PATCH: 0/28: Thread safety for libvirtd daemon and drivers

The following huge series of patches adds thread safety for the libvirtd daemon and drivers, and makes the daemon multi-threaded in processing RPC calls. This enables multiple clients to be processed in parallel, without blocking each other. It does not change the thread rules for the virConnectPtr object though, so each individual client is still serialized. There are two core places where we have to have synchronization in the threading model this patch series introduces - The libvirt daemon code - A single global server lock (aka struct qemud_server) - One lock per client connection (aka struct qemud_client) - The driver implementations - One lock per driver (aka QEMU, LXC, Test, UML, OpenVZ, Network, Storage, Node Devices) - One lock per primary object in a driver (virDomainObjPtr, virNetworkObjPtr, virStoragePoolObjPtr, virNodeDeviceObjptr instances) For most cases, the big global server / driver locks are only held while obtaining one of the finer grained locks. This gives a fairly good level of concurrency for operations touching different objects. Once this core infrastructure is merged, it will be possible to iterate on impl of drivers to reduce the time locks are held - eg avoid holding a lock while talking to the QEMU monitor interface. To try and make it easier to spot thread locking problems this series refactors alot of methods so that there is only a single return point where the unlock call can be placed, rather than multiple return point which increases the chances of missing an unlock call. This touches a huge amount of code, so I'd like to get this all merged ASAP as it'll be really hard to keep it synced with ongoing changes. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

To facilitate later patches this introduces lock & unlock API calls for each internal object which are just no-ops. Once all the drivers are updated to call this at appropriate places, the stubs will be filled out with actual locking impls. This ensures each intermediate patch still results in a functional system domain_conf.c | 8 ++++++++ domain_conf.h | 2 ++ libvirt_sym.version.in | 8 ++++++++ network_conf.c | 8 ++++++++ network_conf.h | 3 +++ node_device_conf.c | 8 ++++++++ node_device_conf.h | 3 +++ storage_conf.c | 9 +++++++++ storage_conf.h | 3 +++ 9 files changed, 52 insertions(+) Daniel diff --git a/src/domain_conf.c b/src/domain_conf.c --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -3459,4 +3459,12 @@ const char *virDomainDefDefaultEmulator( } +void virDomainObjLock(virDomainObjPtr obj ATTRIBUTE_UNUSED) +{ +} + +void virDomainObjUnlock(virDomainObjPtr obj ATTRIBUTE_UNUSED) +{ +} + #endif /* ! PROXY */ diff --git a/src/domain_conf.h b/src/domain_conf.h --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -591,6 +591,8 @@ const char *virDomainDefDefaultEmulator( virDomainDefPtr def, virCapsPtr caps); +void virDomainObjLock(virDomainObjPtr obj); +void virDomainObjUnlock(virDomainObjPtr obj); VIR_ENUM_DECL(virDomainVirt) VIR_ENUM_DECL(virDomainBoot) diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in +++ b/src/libvirt_sym.version.in @@ -373,6 +373,8 @@ LIBVIRT_PRIVATE_@VERSION@ { virDomainSoundModelTypeToString; virDomainVirtTypeToString; virDomainFSDefFree; + virDomainObjLock; + virDomainObjUnlock; /* domain_event.h */ @@ -477,6 +479,8 @@ LIBVIRT_PRIVATE_@VERSION@ { virNetworkDefParseNode; virNetworkRemoveInactive; virNetworkSaveConfig; + virNetworkObjLock; + virNetworkObjUnlock; /* nodeinfo.h */ @@ -491,6 +495,8 @@ LIBVIRT_PRIVATE_@VERSION@ { virNodeDeviceDefFree; virNodeDevCapsDefFree; virNodeDeviceDefFormat; + virNodeDeviceObjLock; + virNodeDeviceObjUnlock; /* qparams.h */ @@ -544,6 +550,8 @@ LIBVIRT_PRIVATE_@VERSION@ { virStoragePoolFormatFileSystemNetTypeToString; virStorageVolFormatFileSystemTypeToString; virStoragePoolTypeFromString; + virStoragePoolObjLock; + virStoragePoolObjUnlock; /* util.h */ diff --git a/src/network_conf.c b/src/network_conf.c --- a/src/network_conf.c +++ b/src/network_conf.c @@ -811,3 +811,11 @@ int virNetworkDeleteConfig(virConnectPtr return 0; } + +void virNetworkObjLock(virNetworkObjPtr obj ATTRIBUTE_UNUSED) +{ +} + +void virNetworkObjUnlock(virNetworkObjPtr obj ATTRIBUTE_UNUSED) +{ +} diff --git a/src/network_conf.h b/src/network_conf.h --- a/src/network_conf.h +++ b/src/network_conf.h @@ -155,5 +155,8 @@ int virNetworkDeleteConfig(virConnectPtr int virNetworkDeleteConfig(virConnectPtr conn, virNetworkObjPtr net); +void virNetworkObjLock(virNetworkObjPtr obj); +void virNetworkObjUnlock(virNetworkObjPtr obj); + #endif /* __NETWORK_CONF_H__ */ diff --git a/src/node_device_conf.c b/src/node_device_conf.c --- a/src/node_device_conf.c +++ b/src/node_device_conf.c @@ -397,3 +397,11 @@ void virNodeDevCapsDefFree(virNodeDevCap VIR_FREE(caps); } + +void virNodeDeviceObjLock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED) +{ +} + +void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED) +{ +} diff --git a/src/node_device_conf.h b/src/node_device_conf.h --- a/src/node_device_conf.h +++ b/src/node_device_conf.h @@ -190,4 +190,7 @@ void virNodeDeviceObjListFree(virNodeDev void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps); +void virNodeDeviceObjLock(virNodeDeviceObjPtr obj); +void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj); + #endif /* __VIR_NODE_DEVICE_CONF_H__ */ diff --git a/src/storage_conf.c b/src/storage_conf.c --- a/src/storage_conf.c +++ b/src/storage_conf.c @@ -1497,3 +1497,12 @@ char *virStoragePoolSourceListFormat(vir free(virBufferContentAndReset(&buf)); return NULL; } + + +void virStoragePoolObjLock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED) +{ +} + +void virStoragePoolObjUnlock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED) +{ +} diff --git a/src/storage_conf.h b/src/storage_conf.h --- a/src/storage_conf.h +++ b/src/storage_conf.h @@ -326,6 +326,9 @@ char *virStoragePoolSourceListFormat(vir char *virStoragePoolSourceListFormat(virConnectPtr conn, virStoragePoolSourceListPtr def); +void virStoragePoolObjLock(virStoragePoolObjPtr obj); +void virStoragePoolObjUnlock(virStoragePoolObjPtr obj); + enum virStoragePoolFormatFileSystem { VIR_STORAGE_POOL_FS_AUTO = 0, -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:17:09PM +0000, Daniel P. Berrange wrote:
To facilitate later patches this introduces lock & unlock API calls for each internal object which are just no-ops. Once all the drivers are updated to call this at appropriate places, the stubs will be filled out with actual locking impls. This ensures each intermediate patch still results in a functional system
Fine, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

The test driver has alot of convenience macros for for fetching the private internal object impls from the public API parameters. Unfortunately these rather obscure/hide code flow & variable accesses in the test driver, making it hard to determine whether a method is thread safe. So this patch removes all the macros, bringing this driver inline with the style of the other drivers test.c | 899 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 670 insertions(+), 229 deletions(-) Daniel diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -86,80 +86,22 @@ static const virNodeInfo defaultNodeInfo 2, }; -#define GET_DOMAIN(dom, ret) \ - testConnPtr privconn; \ - virDomainObjPtr privdom; \ - \ - privconn = (testConnPtr)dom->conn->privateData; \ - do { \ - if ((privdom = virDomainFindByName(&privconn->domains, \ - (dom)->name)) == NULL) { \ - testError((dom)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); \ - return (ret); \ - } \ - } while (0) -#define GET_NETWORK(net, ret) \ - testConnPtr privconn; \ - virNetworkObjPtr privnet; \ - \ - privconn = (testConnPtr)net->conn->privateData; \ - do { \ - if ((privnet = virNetworkFindByName(&privconn->networks, \ - (net)->name)) == NULL) { \ - testError((net)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); \ - return (ret); \ - } \ - } while (0) -#define GET_POOL(pool, ret) \ - testConnPtr privconn; \ - virStoragePoolObjPtr privpool; \ - \ - privconn = (testConnPtr)pool->conn->privateData; \ - do { \ - if ((privpool = virStoragePoolObjFindByName(&privconn->pools, \ - (pool)->name)) == NULL) {\ - testError((pool)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); \ - return (ret); \ - } \ - } while (0) -#define GET_POOL_FROM_VOL(vol, ret) \ - GET_POOL(testStoragePoolLookupByName((virConnectPtr) \ - vol->conn, \ - vol->pool), ret) -#define GET_VOL(vol, pool, ret) \ - virStorageVolDefPtr privvol; \ - \ - privvol = virStorageVolDefFindByName(pool, vol->name); \ - do { \ - if (!privvol) { \ - testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, \ - _("no storage vol with matching name '%s'"), \ - vol->name); \ - return (ret); \ - } \ - } while (0) \ - -#define GET_CONNECTION(conn) \ - testConnPtr privconn; \ - \ - privconn = (testConnPtr)conn->privateData; - -#define POOL_IS_ACTIVE(pool, ret) \ - if (!virStoragePoolObjIsActive(pool)) { \ - testError(obj->conn, VIR_ERR_INTERNAL_ERROR, \ - _("storage pool '%s' is not active"), pool->def->name); \ - return (ret); \ +#define POOL_IS_ACTIVE(privpool, ret) \ + if (!virStoragePoolObjIsActive(privpool)) { \ + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, \ + _("storage pool '%s' is not active"), pool->name); \ + return (ret); \ } \ -#define POOL_IS_NOT_ACTIVE(pool, ret) \ - if (virStoragePoolObjIsActive(pool)) { \ - testError(obj->conn, VIR_ERR_INTERNAL_ERROR, \ - _("storage pool '%s' is already active"), pool->def->name); \ +#define POOL_IS_NOT_ACTIVE(privpool, ret) \ + if (virStoragePoolObjIsActive(privpool)) { \ + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, \ + _("storage pool '%s' is already active"), pool->name); \ return (ret); \ } \ @@ -169,11 +111,11 @@ static const virNodeInfo defaultNodeInfo static virCapsPtr testBuildCapabilities(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; virCapsPtr caps; virCapsGuestPtr guest; const char *const guest_types[] = { "hvm", "xen" }; int i; - GET_CONNECTION(conn); if ((caps = virCapabilitiesNew(TEST_MODEL, 0, 0)) == NULL) goto no_memory; @@ -673,7 +615,7 @@ static int testOpen(virConnectPtr conn, static int testClose(virConnectPtr conn) { - GET_CONNECTION(conn); + testConnPtr privconn = conn->privateData; virCapabilitiesFree(privconn->caps); virDomainObjListFree(&privconn->domains); @@ -681,7 +623,7 @@ static int testClose(virConnectPtr conn) virStoragePoolObjListFree(&privconn->pools); VIR_FREE (privconn); - conn->privateData = conn; + conn->privateData = NULL; return 0; } @@ -721,15 +663,16 @@ static int testNodeGetInfo(virConnectPtr static int testNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { - GET_CONNECTION(conn); + testConnPtr privconn = conn->privateData; + memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo)); return (0); } static char *testGetCapabilities (virConnectPtr conn) { + testConnPtr privconn = conn->privateData; char *xml; - GET_CONNECTION(conn); if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) { testError(conn, VIR_ERR_NO_MEMORY, NULL); @@ -741,8 +684,8 @@ static char *testGetCapabilities (virCon static int testNumOfDomains(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; unsigned int numActive = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->domains.count ; i++) if (virDomainIsActive(privconn->domains.objs[i])) @@ -755,10 +698,10 @@ testDomainCreateXML(virConnectPtr conn, testDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; virDomainPtr ret; virDomainDefPtr def; virDomainObjPtr dom; - GET_CONNECTION(conn); if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) return NULL; @@ -782,9 +725,9 @@ static virDomainPtr testLookupDomainByID static virDomainPtr testLookupDomainByID(virConnectPtr conn, int id) { + testConnPtr privconn = conn->privateData; virDomainObjPtr dom = NULL; virDomainPtr ret; - GET_CONNECTION(conn); if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); @@ -801,9 +744,9 @@ static virDomainPtr testLookupDomainByUU static virDomainPtr testLookupDomainByUUID(virConnectPtr conn, const unsigned char *uuid) { + testConnPtr privconn = conn->privateData; virDomainPtr ret; virDomainObjPtr dom = NULL; - GET_CONNECTION(conn); if ((dom = virDomainFindByUUID(&privconn->domains, uuid)) == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); @@ -820,9 +763,9 @@ static virDomainPtr testLookupDomainByNa static virDomainPtr testLookupDomainByName(virConnectPtr conn, const char *name) { + testConnPtr privconn = conn->privateData; virDomainPtr ret; virDomainObjPtr dom = NULL; - GET_CONNECTION(conn); if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); @@ -840,8 +783,8 @@ static int testListDomains (virConnectPt int *ids, int maxids) { + testConnPtr privconn = conn->privateData; unsigned int n = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) if (virDomainIsActive(privconn->domains.objs[i])) @@ -852,7 +795,16 @@ static int testListDomains (virConnectPt static int testDestroyDomain (virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } privdom->state = VIR_DOMAIN_SHUTOFF; privdom->def->id = -1; @@ -866,7 +818,16 @@ static int testDestroyDomain (virDomainP static int testResumeDomain (virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (privdom->state != VIR_DOMAIN_PAUSED) { testError(domain->conn, @@ -881,7 +842,16 @@ static int testResumeDomain (virDomainPt static int testPauseDomain (virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (privdom->state == VIR_DOMAIN_SHUTOFF || privdom->state == VIR_DOMAIN_PAUSED) { @@ -897,7 +867,16 @@ static int testPauseDomain (virDomainPtr static int testShutdownDomain (virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (privdom->state == VIR_DOMAIN_SHUTOFF) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, @@ -916,7 +895,16 @@ static int testRebootDomain (virDomainPt static int testRebootDomain (virDomainPtr domain, unsigned int action ATTRIBUTE_UNUSED) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } privdom->state = VIR_DOMAIN_SHUTDOWN; switch (privdom->def->onReboot) { @@ -953,8 +941,17 @@ static int testGetDomainInfo (virDomainP static int testGetDomainInfo (virDomainPtr domain, virDomainInfoPtr info) { + testConnPtr privconn = domain->conn->privateData; struct timeval tv; - GET_DOMAIN(domain, -1); + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (gettimeofday(&tv, NULL) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, @@ -977,9 +974,18 @@ static int testDomainSave(virDomainPtr d static int testDomainSave(virDomainPtr domain, const char *path) { + testConnPtr privconn = domain->conn->privateData; char *xml; int fd, len; - GET_DOMAIN(domain, -1); + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } xml = testDomainDumpXML(domain, 0); if (xml == NULL) { @@ -1037,12 +1043,12 @@ static int testDomainRestore(virConnectP static int testDomainRestore(virConnectPtr conn, const char *path) { + testConnPtr privconn = conn->privateData; char *xml; char magic[15]; int fd, len; virDomainDefPtr def; virDomainObjPtr dom; - GET_CONNECTION(conn); if ((fd = open(path, O_RDONLY)) < 0) { testError(conn, VIR_ERR_INTERNAL_ERROR, @@ -1106,8 +1112,17 @@ static int testDomainCoreDump(virDomainP const char *to, int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = domain->conn->privateData; int fd; - GET_DOMAIN(domain, -1); + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, @@ -1145,7 +1160,16 @@ static char *testGetOSType(virDomainPtr } static unsigned long testGetMaxMemory(virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } return privdom->def->maxmem; } @@ -1153,7 +1177,16 @@ static int testSetMaxMemory(virDomainPtr static int testSetMaxMemory(virDomainPtr domain, unsigned long memory) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } /* XXX validate not over host memory wrt to other domains */ privdom->def->maxmem = memory; @@ -1163,7 +1196,16 @@ static int testSetMemory(virDomainPtr do static int testSetMemory(virDomainPtr domain, unsigned long memory) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (memory > privdom->def->maxmem) { testError(domain->conn, @@ -1177,7 +1219,13 @@ static int testSetMemory(virDomainPtr do static int testSetVcpus(virDomainPtr domain, unsigned int nrCpus) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + if ((privdom = virDomainFindByName(&privconn->domains, + domain->name)) == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } /* We allow more cpus in guest than host */ if (nrCpus > 32) { @@ -1191,8 +1239,14 @@ static int testSetVcpus(virDomainPtr dom static char *testDomainDumpXML(virDomainPtr domain, int flags) { + testConnPtr privconn = domain->conn->privateData; virDomainDefPtr def; - GET_DOMAIN(domain, NULL); + virDomainObjPtr privdom; + if ((privdom = virDomainFindByName(&privconn->domains, + domain->name)) == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } def = (flags & VIR_DOMAIN_XML_INACTIVE) && privdom->newDef ? privdom->newDef : privdom->def; @@ -1203,8 +1257,8 @@ static char *testDomainDumpXML(virDomain } static int testNumOfDefinedDomains(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; unsigned int numInactive = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->domains.count ; i++) if (!virDomainIsActive(privconn->domains.objs[i])) @@ -1216,8 +1270,8 @@ static int testListDefinedDomains(virCon static int testListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) { + testConnPtr privconn = conn->privateData; unsigned int n = 0, i; - GET_CONNECTION(conn); memset(names, 0, sizeof(*names)*maxnames); for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) @@ -1236,10 +1290,10 @@ no_memory: static virDomainPtr testDomainDefineXML(virConnectPtr conn, const char *xml) { + testConnPtr privconn = conn->privateData; virDomainPtr ret; virDomainDefPtr def; virDomainObjPtr dom; - GET_CONNECTION(conn); if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) return NULL; @@ -1262,9 +1316,8 @@ static int testNodeGetCellsFreeMemory(vi static int testNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freemems, int startCell, int maxCells) { + testConnPtr privconn = conn->privateData; int i, j; - - GET_CONNECTION(conn); if (startCell > privconn->numCells) { testError(conn, VIR_ERR_INVALID_ARG, @@ -1283,7 +1336,16 @@ static int testNodeGetCellsFreeMemory(vi static int testDomainCreate(virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (privdom->state != VIR_DOMAIN_SHUTOFF) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, @@ -1298,7 +1360,16 @@ static int testDomainCreate(virDomainPtr } static int testDomainUndefine(virDomainPtr domain) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (privdom->state != VIR_DOMAIN_SHUTOFF) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, @@ -1316,7 +1387,17 @@ static int testDomainGetAutostart(virDom static int testDomainGetAutostart(virDomainPtr domain, int *autostart) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + *autostart = privdom->autostart; return (0); } @@ -1325,7 +1406,17 @@ static int testDomainSetAutostart(virDom static int testDomainSetAutostart(virDomainPtr domain, int autostart) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + privdom->autostart = autostart ? 1 : 0; return (0); } @@ -1347,7 +1438,17 @@ static int testDomainGetSchedulerParams( virSchedParameterPtr params, int *nparams) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + if (*nparams != 1) { testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); return (-1); @@ -1365,7 +1466,17 @@ static int testDomainSetSchedulerParams( virSchedParameterPtr params, int nparams) { - GET_DOMAIN(domain, -1); + testConnPtr privconn = domain->conn->privateData; + virDomainObjPtr privdom; + + privdom = virDomainFindByName(&privconn->domains, + domain->name); + + if (privdom == NULL) { + testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + if (nparams != 1) { testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); return (-1); @@ -1402,8 +1513,8 @@ static virNetworkPtr testLookupNetworkBy static virNetworkPtr testLookupNetworkByUUID(virConnectPtr conn, const unsigned char *uuid) { - virNetworkObjPtr net = NULL; - GET_CONNECTION(conn); + testConnPtr privconn = conn->privateData; + virNetworkObjPtr net; if ((net = virNetworkFindByUUID(&privconn->networks, uuid)) == NULL) { testError (conn, VIR_ERR_NO_NETWORK, NULL); @@ -1416,8 +1527,8 @@ static virNetworkPtr testLookupNetworkBy static virNetworkPtr testLookupNetworkByName(virConnectPtr conn, const char *name) { + testConnPtr privconn = conn->privateData; virNetworkObjPtr net = NULL; - GET_CONNECTION(conn); if ((net = virNetworkFindByName(&privconn->networks, name)) == NULL) { testError (conn, VIR_ERR_NO_NETWORK, NULL); @@ -1429,8 +1540,8 @@ static virNetworkPtr testLookupNetworkBy static int testNumNetworks(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; int numActive = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->networks.count ; i++) if (virNetworkIsActive(privconn->networks.objs[i])) @@ -1440,8 +1551,8 @@ static int testNumNetworks(virConnectPtr } static int testListNetworks(virConnectPtr conn, char **const names, int nnames) { + testConnPtr privconn = conn->privateData; int n = 0, i; - GET_CONNECTION(conn); memset(names, 0, sizeof(*names)*nnames); for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) @@ -1459,8 +1570,8 @@ no_memory: } static int testNumDefinedNetworks(virConnectPtr conn) { + testConnPtr privconn = conn->privateData; int numInactive = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->networks.count ; i++) if (!virNetworkIsActive(privconn->networks.objs[i])) @@ -1470,8 +1581,8 @@ static int testNumDefinedNetworks(virCon } static int testListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { + testConnPtr privconn = conn->privateData; int n = 0, i; - GET_CONNECTION(conn); memset(names, 0, sizeof(*names)*nnames); for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) @@ -1489,9 +1600,9 @@ no_memory: } static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { + testConnPtr privconn = conn->privateData; virNetworkDefPtr def; virNetworkObjPtr net; - GET_CONNECTION(conn); if ((def = virNetworkDefParseString(conn, xml)) == NULL) return NULL; @@ -1507,9 +1618,9 @@ static virNetworkPtr testNetworkCreate(v } static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { + testConnPtr privconn = conn->privateData; virNetworkDefPtr def; virNetworkObjPtr net; - GET_CONNECTION(conn); if ((def = virNetworkDefParseString(conn, xml)) == NULL) return NULL; @@ -1525,7 +1636,16 @@ static virNetworkPtr testNetworkDefine(v } static int testNetworkUndefine(virNetworkPtr network) { - GET_NETWORK(network, -1); + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (virNetworkIsActive(privnet)) { testError(network->conn, VIR_ERR_INTERNAL_ERROR, @@ -1540,7 +1660,16 @@ static int testNetworkUndefine(virNetwor } static int testNetworkStart(virNetworkPtr network) { - GET_NETWORK(network, -1); + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (virNetworkIsActive(privnet)) { testError(network->conn, VIR_ERR_INTERNAL_ERROR, @@ -1554,7 +1683,16 @@ static int testNetworkStart(virNetworkPt } static int testNetworkDestroy(virNetworkPtr network) { - GET_NETWORK(network, -1); + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } privnet->active = 0; if (!privnet->persistent) { @@ -1565,14 +1703,33 @@ static int testNetworkDestroy(virNetwork } static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { - GET_NETWORK(network, NULL); + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } return virNetworkDefFormat(network->conn, privnet->def); } static char *testNetworkGetBridgeName(virNetworkPtr network) { + testConnPtr privconn = network->conn->privateData; char *bridge = NULL; - GET_NETWORK(network, NULL); + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + if (privnet->def->bridge && !(bridge = strdup(privnet->def->bridge))) { testError(network->conn, VIR_ERR_NO_MEMORY, "network"); @@ -1583,14 +1740,34 @@ static char *testNetworkGetBridgeName(vi static int testNetworkGetAutostart(virNetworkPtr network, int *autostart) { - GET_NETWORK(network, -1); + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + *autostart = privnet->autostart; return (0); } static int testNetworkSetAutostart(virNetworkPtr network, int autostart) { - GET_NETWORK(network, -1); + testConnPtr privconn = network->conn->privateData; + virNetworkObjPtr privnet; + + privnet = virNetworkFindByName(&privconn->networks, + network->name); + + if (privnet == NULL) { + testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + privnet->autostart = autostart ? 1 : 0; return (0); } @@ -1633,10 +1810,12 @@ static virStoragePoolPtr static virStoragePoolPtr testStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { + testConnPtr privconn = conn->privateData; virStoragePoolObjPtr pool = NULL; - GET_CONNECTION(conn); - if ((pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid)) == NULL) { + pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid); + + if (pool == NULL) { testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); return NULL; } @@ -1647,10 +1826,12 @@ static virStoragePoolPtr static virStoragePoolPtr testStoragePoolLookupByName(virConnectPtr conn, const char *name) { + testConnPtr privconn = conn->privateData; virStoragePoolObjPtr pool = NULL; - GET_CONNECTION(conn); - if ((pool = virStoragePoolObjFindByName(&privconn->pools, name)) == NULL) { + pool = virStoragePoolObjFindByName(&privconn->pools, name); + + if (pool == NULL) { testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); return NULL; } @@ -1665,9 +1846,8 @@ testStoragePoolLookupByVolume(virStorage static int testStorageNumPools(virConnectPtr conn) { - + testConnPtr privconn = conn->privateData; int numActive = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->pools.count ; i++) if (virStoragePoolObjIsActive(privconn->pools.objs[i])) @@ -1680,8 +1860,8 @@ testStorageListPools(virConnectPtr conn, testStorageListPools(virConnectPtr conn, char **const names, int nnames) { + testConnPtr privconn = conn->privateData; int n = 0, i; - GET_CONNECTION(conn); memset(names, 0, sizeof(*names)*nnames); for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) @@ -1700,9 +1880,8 @@ no_memory: static int testStorageNumDefinedPools(virConnectPtr conn) { - + testConnPtr privconn = conn->privateData; int numInactive = 0, i; - GET_CONNECTION(conn); for (i = 0 ; i < privconn->pools.count ; i++) if (!virStoragePoolObjIsActive(privconn->pools.objs[i])) @@ -1715,8 +1894,8 @@ testStorageListDefinedPools(virConnectPt testStorageListDefinedPools(virConnectPtr conn, char **const names, int nnames) { + testConnPtr privconn = conn->privateData; int n = 0, i; - GET_CONNECTION(conn); memset(names, 0, sizeof(*names)*nnames); for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) @@ -1738,12 +1917,22 @@ testStoragePoolRefresh(virStoragePoolPtr unsigned int flags ATTRIBUTE_UNUSED); static int -testStoragePoolStart(virStoragePoolPtr obj, +testStoragePoolStart(virStoragePoolPtr pool, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL(obj, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + POOL_IS_NOT_ACTIVE(privpool, -1); - if (testStoragePoolRefresh(obj, 0) == 0) + if (testStoragePoolRefresh(pool, 0) == 0) return -1; privpool->active = 1; @@ -1764,9 +1953,9 @@ testStoragePoolCreate(virConnectPtr conn testStoragePoolCreate(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; virStoragePoolDefPtr def; virStoragePoolObjPtr pool; - GET_CONNECTION(conn); if (!(def = virStoragePoolDefParse(conn, xml, NULL))) return NULL; @@ -1797,9 +1986,9 @@ testStoragePoolDefine(virConnectPtr conn testStoragePoolDefine(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; virStoragePoolDefPtr def; virStoragePoolObjPtr pool; - GET_CONNECTION(conn); if (!(def = virStoragePoolDefParse(conn, xml, NULL))) return NULL; @@ -1822,8 +2011,18 @@ testStoragePoolDefine(virConnectPtr conn } static int -testStoragePoolUndefine(virStoragePoolPtr obj) { - GET_POOL(obj, -1); +testStoragePoolUndefine(virStoragePoolPtr pool) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + POOL_IS_NOT_ACTIVE(privpool, -1); virStoragePoolObjRemove(&privconn->pools, privpool); @@ -1832,9 +2031,19 @@ testStoragePoolUndefine(virStoragePoolPt } static int -testStoragePoolBuild(virStoragePoolPtr obj, +testStoragePoolBuild(virStoragePoolPtr pool, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL(obj, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + POOL_IS_NOT_ACTIVE(privpool, -1); return 0; @@ -1842,9 +2051,23 @@ testStoragePoolBuild(virStoragePoolPtr o static int -testStoragePoolDestroy(virStoragePoolPtr obj) { - GET_POOL(obj, -1); - POOL_IS_ACTIVE(privpool, -1); +testStoragePoolDestroy(virStoragePoolPtr pool) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + return -1; + } privpool->active = 0; @@ -1856,9 +2079,19 @@ testStoragePoolDestroy(virStoragePoolPtr static int -testStoragePoolDelete(virStoragePoolPtr obj, +testStoragePoolDelete(virStoragePoolPtr pool, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL(obj, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + POOL_IS_NOT_ACTIVE(privpool, -1); return 0; @@ -1866,19 +2099,42 @@ testStoragePoolDelete(virStoragePoolPtr static int -testStoragePoolRefresh(virStoragePoolPtr obj, +testStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL(obj, -1); - POOL_IS_ACTIVE(privpool, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + return -1; + } return 0; } static int -testStoragePoolGetInfo(virStoragePoolPtr obj, +testStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr info) { - GET_POOL(obj, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } memset(info, 0, sizeof(virStoragePoolInfo)); if (privpool->active) @@ -1893,17 +2149,35 @@ testStoragePoolGetInfo(virStoragePoolPtr } static char * -testStoragePoolDumpXML(virStoragePoolPtr obj, +testStoragePoolDumpXML(virStoragePoolPtr pool, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL(obj, NULL); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; - return virStoragePoolDefFormat(obj->conn, privpool->def); + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + return virStoragePoolDefFormat(pool->conn, privpool->def); } static int -testStoragePoolGetAutostart(virStoragePoolPtr obj, +testStoragePoolGetAutostart(virStoragePoolPtr pool, int *autostart) { - GET_POOL(obj, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (!privpool->configFile) { *autostart = 0; @@ -1915,12 +2189,21 @@ testStoragePoolGetAutostart(virStoragePo } static int -testStoragePoolSetAutostart(virStoragePoolPtr obj, +testStoragePoolSetAutostart(virStoragePoolPtr pool, int autostart) { - GET_POOL(obj, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } if (!privpool->configFile) { - testError(obj->conn, VIR_ERR_INVALID_ARG, + testError(pool->conn, VIR_ERR_INVALID_ARG, "%s", _("pool has no config file")); return -1; } @@ -1936,25 +2219,54 @@ testStoragePoolSetAutostart(virStoragePo static int -testStoragePoolNumVolumes(virStoragePoolPtr obj) { - GET_POOL(obj, -1); - POOL_IS_ACTIVE(privpool, -1); +testStoragePoolNumVolumes(virStoragePoolPtr pool) { + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + return -1; + } return privpool->volumes.count; } static int -testStoragePoolListVolumes(virStoragePoolPtr obj, +testStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int maxnames) { - GET_POOL(obj, -1); - POOL_IS_ACTIVE(privpool, -1); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; int i = 0, n = 0; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + return -1; + } memset(names, 0, maxnames); for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) { if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) { - testError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("name")); + testError(pool->conn, VIR_ERR_NO_MEMORY, "%s", _("name")); goto cleanup; } } @@ -1971,39 +2283,56 @@ testStoragePoolListVolumes(virStoragePoo static virStorageVolPtr -testStorageVolumeLookupByName(virStoragePoolPtr obj, +testStorageVolumeLookupByName(virStoragePoolPtr pool, const char *name ATTRIBUTE_UNUSED) { - GET_POOL(obj, NULL); - POOL_IS_ACTIVE(privpool, NULL); - virStorageVolDefPtr vol = virStorageVolDefFindByName(privpool, name); + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; - if (!vol) { - testError(obj->conn, VIR_ERR_INVALID_STORAGE_VOL, + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + return NULL; + } + + privvol = virStorageVolDefFindByName(privpool, name); + + if (!privvol) { + testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, _("no storage vol with matching name '%s'"), name); return NULL; } - return virGetStorageVol(obj->conn, privpool->def->name, - vol->name, vol->key); + return virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); } static virStorageVolPtr testStorageVolumeLookupByKey(virConnectPtr conn, const char *key) { - GET_CONNECTION(conn); + testConnPtr privconn = conn->privateData; unsigned int i; for (i = 0 ; i < privconn->pools.count ; i++) { if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { - virStorageVolDefPtr vol = + virStorageVolDefPtr privvol = virStorageVolDefFindByKey(privconn->pools.objs[i], key); - if (vol) + if (privvol) return virGetStorageVol(conn, privconn->pools.objs[i]->def->name, - vol->name, - vol->key); + privvol->name, + privvol->key); } } @@ -2015,19 +2344,19 @@ static virStorageVolPtr static virStorageVolPtr testStorageVolumeLookupByPath(virConnectPtr conn, const char *path) { - GET_CONNECTION(conn); + testConnPtr privconn = conn->privateData; unsigned int i; for (i = 0 ; i < privconn->pools.count ; i++) { if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { - virStorageVolDefPtr vol = + virStorageVolDefPtr privvol = virStorageVolDefFindByPath(privconn->pools.objs[i], path); - if (vol) + if (privvol) return virGetStorageVol(conn, privconn->pools.objs[i]->def->name, - vol->name, - vol->key); + privvol->name, + privvol->key); } } @@ -2037,31 +2366,47 @@ testStorageVolumeLookupByPath(virConnect } static virStorageVolPtr -testStorageVolumeCreateXML(virStoragePoolPtr obj, +testStorageVolumeCreateXML(virStoragePoolPtr pool, const char *xmldesc, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL(obj, NULL); - POOL_IS_ACTIVE(privpool, NULL); - virStorageVolDefPtr vol; + testConnPtr privconn = pool->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; - vol = virStorageVolDefParse(obj->conn, privpool->def, xmldesc, NULL); - if (vol == NULL) + privpool = virStoragePoolObjFindByName(&privconn->pools, + pool->name); + + if (privpool == NULL) { + testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + + if (!virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), pool->name); + return NULL; + } + + + privvol = virStorageVolDefParse(pool->conn, privpool->def, xmldesc, NULL); + if (privvol == NULL) return NULL; - if (virStorageVolDefFindByName(privpool, vol->name)) { - testError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, + if (virStorageVolDefFindByName(privpool, privvol->name)) { + testError(pool->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("storage vol already exists")); - virStorageVolDefFree(vol); + virStorageVolDefFree(privvol); return NULL; } /* Make sure enough space */ - if ((privpool->def->allocation + vol->allocation) > + if ((privpool->def->allocation + privvol->allocation) > privpool->def->capacity) { - testError(obj->conn, VIR_ERR_INTERNAL_ERROR, + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("Not enough free space in pool for volume '%s'"), - vol->name); - virStorageVolDefFree(vol); + privvol->name); + virStorageVolDefFree(privvol); return NULL; } privpool->def->available = (privpool->def->capacity - @@ -2069,46 +2414,72 @@ testStorageVolumeCreateXML(virStoragePoo if (VIR_REALLOC_N(privpool->volumes.objs, privpool->volumes.count+1) < 0) { - testError(obj->conn, VIR_ERR_NO_MEMORY, NULL); - virStorageVolDefFree(vol); + testError(pool->conn, VIR_ERR_NO_MEMORY, NULL); + virStorageVolDefFree(privvol); return NULL; } - if (VIR_ALLOC_N(vol->target.path, strlen(privpool->def->target.path) + - 1 + strlen(vol->name) + 1) < 0) { - virStorageVolDefFree(vol); - testError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("target")); + if (VIR_ALLOC_N(privvol->target.path, + strlen(privpool->def->target.path) + + 1 + strlen(privvol->name) + 1) < 0) { + virStorageVolDefFree(privvol); + testError(pool->conn, VIR_ERR_NO_MEMORY, "%s", _("target")); return NULL; } - strcpy(vol->target.path, privpool->def->target.path); - strcat(vol->target.path, "/"); - strcat(vol->target.path, vol->name); - vol->key = strdup(vol->target.path); - if (vol->key == NULL) { - virStorageVolDefFree(vol); - testError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", + strcpy(privvol->target.path, privpool->def->target.path); + strcat(privvol->target.path, "/"); + strcat(privvol->target.path, privvol->name); + privvol->key = strdup(privvol->target.path); + if (privvol->key == NULL) { + virStorageVolDefFree(privvol); + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage vol key")); return NULL; } - privpool->def->allocation += vol->allocation; + privpool->def->allocation += privvol->allocation; privpool->def->available = (privpool->def->capacity - privpool->def->allocation); - privpool->volumes.objs[privpool->volumes.count++] = vol; + privpool->volumes.objs[privpool->volumes.count++] = privvol; - return virGetStorageVol(obj->conn, privpool->def->name, vol->name, - vol->key); + return virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); } static int -testStorageVolumeDelete(virStorageVolPtr obj, +testStorageVolumeDelete(virStorageVolPtr vol, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL_FROM_VOL(obj, -1); - POOL_IS_ACTIVE(privpool, -1); - GET_VOL(obj, privpool, -1); + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; int i; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + return -1; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + return -1; + } + privpool->def->allocation -= privvol->allocation; privpool->def->available = (privpool->def->capacity - @@ -2151,11 +2522,34 @@ static int testStorageVolumeTypeForPool( } static int -testStorageVolumeGetInfo(virStorageVolPtr obj, +testStorageVolumeGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info) { - GET_POOL_FROM_VOL(obj, -1); - POOL_IS_ACTIVE(privpool, -1); - GET_VOL(obj, privpool, -1); + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; + + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + return -1; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + return -1; + } memset(info, 0, sizeof(*info)); info->type = testStorageVolumeTypeForPool(privpool->def->type); @@ -2166,25 +2560,72 @@ testStorageVolumeGetInfo(virStorageVolPt } static char * -testStorageVolumeGetXMLDesc(virStorageVolPtr obj, +testStorageVolumeGetXMLDesc(virStorageVolPtr vol, unsigned int flags ATTRIBUTE_UNUSED) { - GET_POOL_FROM_VOL(obj, NULL); - POOL_IS_ACTIVE(privpool, NULL); - GET_VOL(obj, privpool, NULL); + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; - return virStorageVolDefFormat(obj->conn, privpool->def, privvol); + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + return NULL; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + return NULL; + } + + return virStorageVolDefFormat(vol->conn, privpool->def, privvol); } static char * -testStorageVolumeGetPath(virStorageVolPtr obj) { - GET_POOL_FROM_VOL(obj, NULL); - POOL_IS_ACTIVE(privpool, NULL); - GET_VOL(obj, privpool, NULL); +testStorageVolumeGetPath(virStorageVolPtr vol) { + testConnPtr privconn = vol->conn->privateData; + virStoragePoolObjPtr privpool; + virStorageVolDefPtr privvol; char *ret; + + + privpool = virStoragePoolObjFindByName(&privconn->pools, + vol->pool); + + if (privpool == NULL) { + testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + privvol = virStorageVolDefFindByName(privpool, vol->name); + + if (privvol == NULL) { + testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching name '%s'"), + vol->name); + return NULL; + } + + if (!virStoragePoolObjIsActive(privpool)) { + testError(vol->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is not active"), vol->pool); + return NULL; + } ret = strdup(privvol->target.path); if (ret == NULL) { - testError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("path")); + testError(vol->conn, VIR_ERR_NO_MEMORY, "%s", _("path")); return NULL; } return ret; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:20:28PM +0000, Daniel P. Berrange wrote:
The test driver has alot of convenience macros for for fetching the private internal object impls from the public API parameters. Unfortunately these rather obscure/hide code flow & variable accesses in the test driver, making it hard to determine whether a method is thread safe. So this patch removes all the macros, bringing this driver inline with the style of the other drivers
test.c | 899 ++++++++++++++++++++++++++++++++++++++++++++++++-----------------
the alternative viewpoint is if such macros can't be generalized, but with the goal of uniformizing code for locking, yes this makes sense. that's a big patch but everything is systematic. Didn't spot anything +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch reduces the number of return points in methods in the test driver. This is done by switching most 'return -1' calls into a 'goto cleanup' centralizing all cleanup in methods. test.c | 812 ++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 511 insertions(+), 301 deletions(-) Daniel diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -86,24 +86,6 @@ static const virNodeInfo defaultNodeInfo 2, }; - - - - - -#define POOL_IS_ACTIVE(privpool, ret) \ - if (!virStoragePoolObjIsActive(privpool)) { \ - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, \ - _("storage pool '%s' is not active"), pool->name); \ - return (ret); \ - } \ - -#define POOL_IS_NOT_ACTIVE(privpool, ret) \ - if (virStoragePoolObjIsActive(privpool)) { \ - testError(pool->conn, VIR_ERR_INTERNAL_ERROR, \ - _("storage pool '%s' is already active"), pool->name); \ - return (ret); \ - } \ #define testError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \ @@ -674,10 +656,8 @@ static char *testGetCapabilities (virCon testConnPtr privconn = conn->privateData; char *xml; - if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) { + if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) testError(conn, VIR_ERR_NO_MEMORY, NULL); - return NULL; - } return xml; } @@ -699,25 +679,26 @@ testDomainCreateXML(virConnectPtr conn, unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = conn->privateData; - virDomainPtr ret; + virDomainPtr ret = NULL; virDomainDefPtr def; virDomainObjPtr dom; if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) - return NULL; + goto cleanup; if ((dom = virDomainAssignDef(conn, &privconn->domains, def)) == NULL) { virDomainDefFree(def); - return NULL; + goto cleanup; } dom->state = VIR_DOMAIN_RUNNING; dom->def->id = privconn->nextDomID++; ret = virGetDomain(conn, def->name, def->uuid); - if (!ret) - return NULL; - ret->id = def->id; + if (ret) + ret->id = def->id; + +cleanup: return ret; } @@ -726,18 +707,19 @@ static virDomainPtr testLookupDomainByID int id) { testConnPtr privconn = conn->privateData; - virDomainObjPtr dom = NULL; - virDomainPtr ret; + virDomainPtr ret = NULL; + virDomainObjPtr dom; if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (!ret) - return NULL; - ret->id = dom->def->id; + if (ret) + ret->id = dom->def->id; + +cleanup: return ret; } @@ -745,18 +727,19 @@ static virDomainPtr testLookupDomainByUU const unsigned char *uuid) { testConnPtr privconn = conn->privateData; - virDomainPtr ret; - virDomainObjPtr dom = NULL; + virDomainPtr ret = NULL; + virDomainObjPtr dom ; if ((dom = virDomainFindByUUID(&privconn->domains, uuid)) == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (!ret) - return NULL; - ret->id = dom->def->id; + if (ret) + ret->id = dom->def->id; + +cleanup: return ret; } @@ -764,18 +747,19 @@ static virDomainPtr testLookupDomainByNa const char *name) { testConnPtr privconn = conn->privateData; - virDomainPtr ret; - virDomainObjPtr dom = NULL; + virDomainPtr ret = NULL; + virDomainObjPtr dom; if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } ret = virGetDomain(conn, dom->def->name, dom->def->uuid); - if (!ret) - return NULL; - ret->id = dom->def->id; + if (ret) + ret->id = dom->def->id; + +cleanup: return ret; } @@ -797,13 +781,14 @@ static int testDestroyDomain (virDomainP { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } privdom->state = VIR_DOMAIN_SHUTOFF; @@ -813,44 +798,52 @@ static int testDestroyDomain (virDomainP virDomainRemoveInactive(&privconn->domains, privdom); } - return (0); + + ret = 0; +cleanup: + return ret; } static int testResumeDomain (virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (privdom->state != VIR_DOMAIN_PAUSED) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("domain '%s' not paused"), domain->name); - return -1; + goto cleanup; } privdom->state = VIR_DOMAIN_RUNNING; - return (0); + ret = 0; + +cleanup: + return ret; } static int testPauseDomain (virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (privdom->state == VIR_DOMAIN_SHUTOFF || @@ -858,37 +851,43 @@ static int testPauseDomain (virDomainPtr testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"), domain->name); - return -1; + goto cleanup; } privdom->state = VIR_DOMAIN_PAUSED; - return (0); + ret = 0; + +cleanup: + return ret; } static int testShutdownDomain (virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (privdom->state == VIR_DOMAIN_SHUTOFF) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("domain '%s' not running"), domain->name); - return -1; + goto cleanup; } privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; privdom->def->id = -1; + ret = 0; - return (0); +cleanup: + return ret; } /* Similar behaviour as shutdown */ @@ -897,13 +896,14 @@ static int testRebootDomain (virDomainPt { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } privdom->state = VIR_DOMAIN_SHUTDOWN; @@ -935,7 +935,10 @@ static int testRebootDomain (virDomainPt break; } - return (0); + ret = 0; + +cleanup: + return ret; } static int testGetDomainInfo (virDomainPtr domain, @@ -944,19 +947,20 @@ static int testGetDomainInfo (virDomainP testConnPtr privconn = domain->conn->privateData; struct timeval tv; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (gettimeofday(&tv, NULL) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day")); - return (-1); + goto cleanup; } info->state = privdom->state; @@ -964,7 +968,10 @@ static int testGetDomainInfo (virDomainP info->maxMem = privdom->def->maxmem; info->nrVirtCpu = privdom->def->vcpus; info->cpuTime = ((tv.tv_sec * 1000ll * 1000ll * 1000ll) + (tv.tv_usec * 1000ll)); - return (0); + ret = 0; + +cleanup: + return ret; } static char *testDomainDumpXML(virDomainPtr domain, int flags); @@ -975,16 +982,18 @@ static int testDomainSave(virDomainPtr d const char *path) { testConnPtr privconn = domain->conn->privateData; - char *xml; - int fd, len; + char *xml = NULL; + int fd = -1; + int len; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } xml = testDomainDumpXML(domain, 0); @@ -992,120 +1001,132 @@ static int testDomainSave(virDomainPtr d testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("saving domain '%s' failed to allocate space for metadata: %s"), domain->name, strerror(errno)); - return (-1); + goto cleanup; } if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("saving domain '%s' to '%s': open failed: %s"), domain->name, path, strerror(errno)); - return (-1); + goto cleanup; } len = strlen(xml); if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("saving domain '%s' to '%s': write failed: %s"), domain->name, path, strerror(errno)); - close(fd); - return (-1); + goto cleanup; } if (safewrite(fd, (char*)&len, sizeof(len)) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("saving domain '%s' to '%s': write failed: %s"), domain->name, path, strerror(errno)); - close(fd); - return (-1); + goto cleanup; } if (safewrite(fd, xml, len) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("saving domain '%s' to '%s': write failed: %s"), domain->name, path, strerror(errno)); - VIR_FREE(xml); - close(fd); - return (-1); + goto cleanup; } - VIR_FREE(xml); + if (close(fd) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("saving domain '%s' to '%s': write failed: %s"), domain->name, path, strerror(errno)); - close(fd); - return (-1); + goto cleanup; } + fd = -1; + privdom->state = VIR_DOMAIN_SHUTOFF; if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom); } - return 0; + ret = 0; + +cleanup: + VIR_FREE(xml); + + /* Don't report failure in close or unlink, because + * in either case we're already in a failure scenario + * and have reported a earlier error */ + if (ret != 0) { + if (fd != -1) + close(fd); + unlink(path); + } + + return ret; } static int testDomainRestore(virConnectPtr conn, const char *path) { testConnPtr privconn = conn->privateData; - char *xml; + char *xml = NULL; char magic[15]; - int fd, len; - virDomainDefPtr def; + int fd = -1; + int len; + virDomainDefPtr def = NULL; virDomainObjPtr dom; + int ret = -1; if ((fd = open(path, O_RDONLY)) < 0) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot read domain image")); - return (-1); + goto cleanup; } if (read(fd, magic, sizeof(magic)) != sizeof(magic)) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("incomplete save header")); - close(fd); - return (-1); + goto cleanup; } if (memcmp(magic, TEST_SAVE_MAGIC, sizeof(magic))) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("mismatched header magic")); - close(fd); - return (-1); + goto cleanup; } if (read(fd, (char*)&len, sizeof(len)) != sizeof(len)) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("failed to read metadata length")); - close(fd); - return (-1); + goto cleanup; } if (len < 1 || len > 8192) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("length of metadata out of range")); - close(fd); - return (-1); + goto cleanup; } if (VIR_ALLOC_N(xml, len+1) < 0) { testError(conn, VIR_ERR_NO_MEMORY, "xml"); - close(fd); - return (-1); + goto cleanup; } if (read(fd, xml, len) != len) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("incomplete metdata")); - close(fd); - return (-1); + goto cleanup; } xml[len] = '\0'; - close(fd); def = virDomainDefParseString(conn, privconn->caps, xml); - VIR_FREE(xml); if (!def) - return -1; + goto cleanup; if ((dom = virDomainAssignDef(conn, &privconn->domains, - def)) == NULL) { - virDomainDefFree(def); - return -1; - } + def)) == NULL) + goto cleanup; + dom->state = VIR_DOMAIN_RUNNING; dom->def->id = privconn->nextDomID++; - return dom->def->id; + def = NULL; + ret = dom->def->id; + +cleanup: + virDomainDefFree(def); + VIR_FREE(xml); + if (fd != -1) + close(fd); + return ret; } static int testDomainCoreDump(virDomainPtr domain, @@ -1113,43 +1134,47 @@ static int testDomainCoreDump(virDomainP int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = domain->conn->privateData; - int fd; + int fd = -1; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if ((fd = open(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("domain '%s' coredump: failed to open %s: %s"), domain->name, to, strerror (errno)); - return (-1); + goto cleanup; } if (safewrite(fd, TEST_SAVE_MAGIC, sizeof(TEST_SAVE_MAGIC)) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("domain '%s' coredump: failed to write header to %s: %s"), domain->name, to, strerror (errno)); - close(fd); - return (-1); + goto cleanup; } if (close(fd) < 0) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("domain '%s' coredump: write failed: %s: %s"), domain->name, to, strerror (errno)); - close(fd); - return (-1); + goto cleanup; } privdom->state = VIR_DOMAIN_SHUTOFF; if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom); } - return 0; + ret = 0; + +cleanup: + if (fd != -1) + close(fd); + return ret; } static char *testGetOSType(virDomainPtr dom) { @@ -1162,16 +1187,20 @@ static unsigned long testGetMaxMemory(vi static unsigned long testGetMaxMemory(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + unsigned long ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } - return privdom->def->maxmem; + ret = privdom->def->maxmem; + +cleanup: + return ret; } static int testSetMaxMemory(virDomainPtr domain, @@ -1179,18 +1208,22 @@ static int testSetMaxMemory(virDomainPtr { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } /* XXX validate not over host memory wrt to other domains */ privdom->def->maxmem = memory; - return (0); + ret = 0; + +cleanup: + return ret; } static int testSetMemory(virDomainPtr domain, @@ -1198,43 +1231,52 @@ static int testSetMemory(virDomainPtr do { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (memory > privdom->def->maxmem) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto cleanup; } privdom->def->memory = memory; - return (0); + ret = 0; + +cleanup: + return ret; } static int testSetVcpus(virDomainPtr domain, unsigned int nrCpus) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; + if ((privdom = virDomainFindByName(&privconn->domains, domain->name)) == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } /* We allow more cpus in guest than host */ if (nrCpus > 32) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return (-1); + goto cleanup; } privdom->def->vcpus = nrCpus; - return (0); + ret = 0; + +cleanup: + return ret; } static char *testDomainDumpXML(virDomainPtr domain, int flags) @@ -1242,18 +1284,23 @@ static char *testDomainDumpXML(virDomain testConnPtr privconn = domain->conn->privateData; virDomainDefPtr def; virDomainObjPtr privdom; + char *ret = NULL; + if ((privdom = virDomainFindByName(&privconn->domains, domain->name)) == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } def = (flags & VIR_DOMAIN_XML_INACTIVE) && privdom->newDef ? privdom->newDef : privdom->def; - return virDomainDefFormat(domain->conn, - def, - flags); + ret = virDomainDefFormat(domain->conn, + def, + flags); + +cleanup: + return ret; } static int testNumOfDefinedDomains(virConnectPtr conn) { @@ -1291,25 +1338,27 @@ static virDomainPtr testDomainDefineXML( static virDomainPtr testDomainDefineXML(virConnectPtr conn, const char *xml) { testConnPtr privconn = conn->privateData; - virDomainPtr ret; + virDomainPtr ret = NULL; virDomainDefPtr def; virDomainObjPtr dom; if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) - return NULL; + goto cleanup; if ((dom = virDomainAssignDef(conn, &privconn->domains, def)) == NULL) { - virDomainDefFree(def); - return NULL; + goto cleanup; } dom->persistent = 1; dom->def->id = -1; ret = virGetDomain(conn, def->name, def->uuid); - if (!ret) - return NULL; - ret->id = -1; + def = NULL; + if (ret) + ret->id = -1; + +cleanup: + virDomainDefFree(def); return ret; } @@ -1318,11 +1367,12 @@ static int testNodeGetCellsFreeMemory(vi int startCell, int maxCells) { testConnPtr privconn = conn->privateData; int i, j; + int ret = -1; if (startCell > privconn->numCells) { testError(conn, VIR_ERR_INVALID_ARG, "%s", _("Range exceeds available cells")); - return -1; + goto cleanup; } for (i = startCell, j = 0; @@ -1330,58 +1380,66 @@ static int testNodeGetCellsFreeMemory(vi ++i, ++j) { freemems[j] = privconn->cells[i].mem; } + ret = j; - return j; +cleanup: + return ret; } static int testDomainCreate(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (privdom->state != VIR_DOMAIN_SHUTOFF) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("Domain '%s' is already running"), domain->name); - return (-1); + goto cleanup; } domain->id = privdom->def->id = privconn->nextDomID++; privdom->state = VIR_DOMAIN_RUNNING; + ret = 0; - return (0); +cleanup: + return ret; } static int testDomainUndefine(virDomainPtr domain) { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (privdom->state != VIR_DOMAIN_SHUTOFF) { testError(domain->conn, VIR_ERR_INTERNAL_ERROR, _("Domain '%s' is still running"), domain->name); - return (-1); + goto cleanup; } privdom->state = VIR_DOMAIN_SHUTOFF; virDomainRemoveInactive(&privconn->domains, privdom); + ret = 0; - return (0); +cleanup: + return ret; } static int testDomainGetAutostart(virDomainPtr domain, @@ -1389,17 +1447,21 @@ static int testDomainGetAutostart(virDom { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } *autostart = privdom->autostart; - return (0); + ret = 0; + +cleanup: + return ret; } @@ -1408,29 +1470,33 @@ static int testDomainSetAutostart(virDom { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } privdom->autostart = autostart ? 1 : 0; - return (0); + ret = 0; + +cleanup: + return ret; } static char *testDomainGetSchedulerType(virDomainPtr domain, int *nparams) { - char *type; + char *type = NULL; + *nparams = 1; type = strdup("fair"); - if (!type) { + if (!type) testError(domain->conn, VIR_ERR_NO_MEMORY, "schedular"); - return (NULL); - } + return type; } @@ -1440,25 +1506,29 @@ static int testDomainGetSchedulerParams( { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (*nparams != 1) { testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); - return (-1); + goto cleanup; } strcpy(params[0].field, "weight"); params[0].type = VIR_DOMAIN_SCHED_FIELD_UINT; /* XXX */ /*params[0].value.ui = privdom->weight;*/ params[0].value.ui = 50; - return 0; + ret = 0; + +cleanup: + return ret; } @@ -1468,30 +1538,34 @@ static int testDomainSetSchedulerParams( { testConnPtr privconn = domain->conn->privateData; virDomainObjPtr privdom; + int ret = -1; privdom = virDomainFindByName(&privconn->domains, domain->name); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (nparams != 1) { testError(domain->conn, VIR_ERR_INVALID_ARG, "nparams"); - return (-1); + goto cleanup; } if (STRNEQ(params[0].field, "weight")) { testError(domain->conn, VIR_ERR_INVALID_ARG, "field"); - return (-1); + goto cleanup; } if (params[0].type != VIR_DOMAIN_SCHED_FIELD_UINT) { testError(domain->conn, VIR_ERR_INVALID_ARG, "type"); - return (-1); + goto cleanup; } /* XXX */ /*privdom->weight = params[0].value.ui;*/ - return 0; + ret = 0; + +cleanup: + return ret; } static virDrvOpenStatus testOpenNetwork(virConnectPtr conn, @@ -1515,27 +1589,35 @@ static virNetworkPtr testLookupNetworkBy { testConnPtr privconn = conn->privateData; virNetworkObjPtr net; + virNetworkPtr ret = NULL; if ((net = virNetworkFindByUUID(&privconn->networks, uuid)) == NULL) { testError (conn, VIR_ERR_NO_NETWORK, NULL); - return NULL; + goto cleanup; } - return virGetNetwork(conn, net->def->name, net->def->uuid); + ret = virGetNetwork(conn, net->def->name, net->def->uuid); + +cleanup: + return ret; } static virNetworkPtr testLookupNetworkByName(virConnectPtr conn, const char *name) { testConnPtr privconn = conn->privateData; - virNetworkObjPtr net = NULL; + virNetworkObjPtr net; + virNetworkPtr ret = NULL; if ((net = virNetworkFindByName(&privconn->networks, name)) == NULL) { testError (conn, VIR_ERR_NO_NETWORK, NULL); - return NULL; + goto cleanup; } - return virGetNetwork(conn, net->def->name, net->def->uuid); + ret = virGetNetwork(conn, net->def->name, net->def->uuid); + +cleanup: + return ret; } @@ -1566,7 +1648,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); - return (-1); + return -1; } static int testNumDefinedNetworks(virConnectPtr conn) { @@ -1596,102 +1678,119 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); - return (-1); + return -1; } static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { testConnPtr privconn = conn->privateData; virNetworkDefPtr def; virNetworkObjPtr net; + virNetworkPtr ret = NULL; if ((def = virNetworkDefParseString(conn, xml)) == NULL) - return NULL; + goto cleanup; if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL) { - virNetworkDefFree(def); - return NULL; + goto cleanup; } net->active = 1; + def = NULL; - return virGetNetwork(conn, def->name, def->uuid); + ret = virGetNetwork(conn, def->name, def->uuid); + +cleanup: + virNetworkDefFree(def); + return ret; } static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { testConnPtr privconn = conn->privateData; virNetworkDefPtr def; virNetworkObjPtr net; + virNetworkPtr ret = NULL; if ((def = virNetworkDefParseString(conn, xml)) == NULL) - return NULL; + goto cleanup; if ((net = virNetworkAssignDef(conn, &privconn->networks, def)) == NULL) { - virNetworkDefFree(def); - return NULL; + goto cleanup; } net->persistent = 1; + def = NULL; - return virGetNetwork(conn, def->name, def->uuid); + ret = virGetNetwork(conn, def->name, def->uuid); + +cleanup: + virNetworkDefFree(def); + return ret; } static int testNetworkUndefine(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; + int ret = -1; privnet = virNetworkFindByName(&privconn->networks, network->name); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (virNetworkIsActive(privnet)) { testError(network->conn, VIR_ERR_INTERNAL_ERROR, _("Network '%s' is still running"), network->name); - return (-1); + goto cleanup; } virNetworkRemoveInactive(&privconn->networks, privnet); + ret = 0; - return (0); +cleanup: + return ret; } static int testNetworkStart(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; + int ret = -1; privnet = virNetworkFindByName(&privconn->networks, network->name); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (virNetworkIsActive(privnet)) { testError(network->conn, VIR_ERR_INTERNAL_ERROR, _("Network '%s' is already running"), network->name); - return (-1); + goto cleanup; } privnet->active = 1; + ret = 0; - return (0); +cleanup: + return ret; } static int testNetworkDestroy(virNetworkPtr network) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; + int ret = -1; privnet = virNetworkFindByName(&privconn->networks, network->name); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } privnet->active = 0; @@ -1699,22 +1798,29 @@ static int testNetworkDestroy(virNetwork virNetworkRemoveInactive(&privconn->networks, privnet); } - return (0); + ret = 0; + +cleanup: + return ret; } static char *testNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; + char *ret = NULL; privnet = virNetworkFindByName(&privconn->networks, network->name); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } - return virNetworkDefFormat(network->conn, privnet->def); + ret = virNetworkDefFormat(network->conn, privnet->def); + +cleanup: + return ret; } static char *testNetworkGetBridgeName(virNetworkPtr network) { @@ -1727,14 +1833,16 @@ static char *testNetworkGetBridgeName(vi if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } if (privnet->def->bridge && !(bridge = strdup(privnet->def->bridge))) { testError(network->conn, VIR_ERR_NO_MEMORY, "network"); - return NULL; + goto cleanup; } + +cleanup: return bridge; } @@ -1742,34 +1850,42 @@ static int testNetworkGetAutostart(virNe int *autostart) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; + int ret = -1; privnet = virNetworkFindByName(&privconn->networks, network->name); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } *autostart = privnet->autostart; - return (0); + ret = 0; + +cleanup: + return ret; } static int testNetworkSetAutostart(virNetworkPtr network, int autostart) { testConnPtr privconn = network->conn->privateData; virNetworkObjPtr privnet; + int ret = -1; privnet = virNetworkFindByName(&privconn->networks, network->name); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } privnet->autostart = autostart ? 1 : 0; - return (0); + ret = 0; + +cleanup: + return ret; } @@ -1811,32 +1927,40 @@ testStoragePoolLookupByUUID(virConnectPt testStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { testConnPtr privconn = conn->privateData; - virStoragePoolObjPtr pool = NULL; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid); if (pool == NULL) { testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); - return NULL; + goto cleanup; } - return virGetStoragePool(conn, pool->def->name, pool->def->uuid); + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + return ret; } static virStoragePoolPtr testStoragePoolLookupByName(virConnectPtr conn, const char *name) { testConnPtr privconn = conn->privateData; - virStoragePoolObjPtr pool = NULL; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; pool = virStoragePoolObjFindByName(&privconn->pools, name); if (pool == NULL) { testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); - return NULL; + goto cleanup; } - return virGetStoragePool(conn, pool->def->name, pool->def->uuid); + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + return ret; } static virStoragePoolPtr @@ -1875,7 +1999,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); - return (-1); + return -1; } static int @@ -1909,7 +2033,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); - return (-1); + return -1; } static int @@ -1921,22 +2045,29 @@ testStoragePoolStart(virStoragePoolPtr p unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } - POOL_IS_NOT_ACTIVE(privpool, -1); + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } if (testStoragePoolRefresh(pool, 0) == 0) - return -1; + goto cleanup; privpool->active = 1; + ret = 0; - return 0; +cleanup: + return ret; } static char * @@ -1956,30 +2087,37 @@ testStoragePoolCreate(virConnectPtr conn testConnPtr privconn = conn->privateData; virStoragePoolDefPtr def; virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; if (!(def = virStoragePoolDefParse(conn, xml, NULL))) - return NULL; + goto cleanup; - if (virStoragePoolObjFindByUUID(&privconn->pools, def->uuid) || - virStoragePoolObjFindByName(&privconn->pools, def->name)) { + pool = virStoragePoolObjFindByUUID(&privconn->pools, def->uuid); + if (!pool) + pool = virStoragePoolObjFindByName(&privconn->pools, def->name); + if (pool) { testError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool already exists")); - virStoragePoolDefFree(def); - return NULL; + goto cleanup; } if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) { - virStoragePoolDefFree(def); return NULL; } + def = NULL; if (testStoragePoolObjSetDefaults(pool) == -1) { virStoragePoolObjRemove(&privconn->pools, pool); - return NULL; + pool = NULL; + goto cleanup; } pool->active = 1; - return virGetStoragePool(conn, pool->def->name, pool->def->uuid); + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + virStoragePoolDefFree(def); + return ret; } static virStoragePoolPtr @@ -1989,45 +2127,58 @@ testStoragePoolDefine(virConnectPtr conn testConnPtr privconn = conn->privateData; virStoragePoolDefPtr def; virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; if (!(def = virStoragePoolDefParse(conn, xml, NULL))) - return NULL; + goto cleanup; def->capacity = defaultPoolCap; def->allocation = defaultPoolAlloc; def->available = defaultPoolCap - defaultPoolAlloc; if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) { - virStoragePoolDefFree(def); - return NULL; + goto cleanup; } + def = NULL; if (testStoragePoolObjSetDefaults(pool) == -1) { virStoragePoolObjRemove(&privconn->pools, pool); - return NULL; + pool = NULL; + goto cleanup; } - return virGetStoragePool(conn, pool->def->name, pool->def->uuid); + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + virStoragePoolDefFree(def); + return ret; } static int testStoragePoolUndefine(virStoragePoolPtr pool) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } - POOL_IS_NOT_ACTIVE(privpool, -1); + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } virStoragePoolObjRemove(&privconn->pools, privpool); + ret = 0; - return 0; +cleanup: + return ret; } static int @@ -2035,18 +2186,24 @@ testStoragePoolBuild(virStoragePoolPtr p unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } - POOL_IS_NOT_ACTIVE(privpool, -1); + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } - return 0; +cleanup: + return ret; } @@ -2054,27 +2211,30 @@ testStoragePoolDestroy(virStoragePoolPtr testStoragePoolDestroy(virStoragePoolPtr pool) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), pool->name); - return -1; + goto cleanup; } privpool->active = 0; if (privpool->configFile == NULL) virStoragePoolObjRemove(&privconn->pools, privpool); + ret = 0; - return 0; +cleanup: + return ret; } @@ -2083,18 +2243,26 @@ testStoragePoolDelete(virStoragePoolPtr unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } - POOL_IS_NOT_ACTIVE(privpool, -1); + if (virStoragePoolObjIsActive(privpool)) { + testError(pool->conn, VIR_ERR_INTERNAL_ERROR, + _("storage pool '%s' is already active"), pool->name); + goto cleanup; + } - return 0; + ret = 0; + +cleanup: + return ret; } @@ -2103,22 +2271,25 @@ testStoragePoolRefresh(virStoragePoolPtr unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), pool->name); - return -1; + goto cleanup; } + ret = 0; - return 0; +cleanup: + return ret; } @@ -2127,13 +2298,14 @@ testStoragePoolGetInfo(virStoragePoolPtr virStoragePoolInfoPtr info) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } memset(info, 0, sizeof(virStoragePoolInfo)); @@ -2144,8 +2316,10 @@ testStoragePoolGetInfo(virStoragePoolPtr info->capacity = privpool->def->capacity; info->allocation = privpool->def->allocation; info->available = privpool->def->available; + ret = 0; - return 0; +cleanup: + return ret; } static char * @@ -2153,16 +2327,20 @@ testStoragePoolDumpXML(virStoragePoolPtr unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + char *ret = NULL; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } - return virStoragePoolDefFormat(pool->conn, privpool->def); + ret = virStoragePoolDefFormat(pool->conn, privpool->def); + +cleanup: + return ret; } static int @@ -2170,13 +2348,14 @@ testStoragePoolGetAutostart(virStoragePo int *autostart) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (!privpool->configFile) { @@ -2184,8 +2363,10 @@ testStoragePoolGetAutostart(virStoragePo } else { *autostart = privpool->autostart; } + ret = 0; - return 0; +cleanup: + return ret; } static int @@ -2193,28 +2374,28 @@ testStoragePoolSetAutostart(virStoragePo int autostart) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (!privpool->configFile) { testError(pool->conn, VIR_ERR_INVALID_ARG, "%s", _("pool has no config file")); - return -1; + goto cleanup; } autostart = (autostart != 0); + privpool->autostart = autostart; + ret = 0; - if (privpool->autostart == autostart) - return 0; - - privpool->autostart = autostart; - return 0; +cleanup: + return ret; } @@ -2222,22 +2403,26 @@ testStoragePoolNumVolumes(virStoragePool testStoragePoolNumVolumes(virStoragePoolPtr pool) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), pool->name); - return -1; + goto cleanup; } - return privpool->volumes.count; + ret = privpool->volumes.count; + +cleanup: + return ret; } static int @@ -2248,22 +2433,23 @@ testStoragePoolListVolumes(virStoragePoo virStoragePoolObjPtr privpool; int i = 0, n = 0; + memset(names, 0, maxnames); + privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), pool->name); - return -1; + goto cleanup; } - memset(names, 0, maxnames); for (i = 0 ; i < privpool->volumes.count && n < maxnames ; i++) { if ((names[n++] = strdup(privpool->volumes.objs[i]->name)) == NULL) { testError(pool->conn, VIR_ERR_NO_MEMORY, "%s", _("name")); @@ -2288,20 +2474,21 @@ testStorageVolumeLookupByName(virStorage testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; virStorageVolDefPtr privvol; + virStorageVolPtr ret = NULL; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), pool->name); - return NULL; + goto cleanup; } privvol = virStorageVolDefFindByName(privpool, name); @@ -2309,11 +2496,14 @@ testStorageVolumeLookupByName(virStorage if (!privvol) { testError(pool->conn, VIR_ERR_INVALID_STORAGE_VOL, _("no storage vol with matching name '%s'"), name); - return NULL; + goto cleanup; } - return virGetStorageVol(pool->conn, privpool->def->name, - privvol->name, privvol->key); + ret = virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); + +cleanup: + return ret; } @@ -2322,23 +2512,28 @@ testStorageVolumeLookupByKey(virConnectP const char *key) { testConnPtr privconn = conn->privateData; unsigned int i; + virStorageVolPtr ret = NULL; for (i = 0 ; i < privconn->pools.count ; i++) { if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { virStorageVolDefPtr privvol = virStorageVolDefFindByKey(privconn->pools.objs[i], key); - if (privvol) - return virGetStorageVol(conn, - privconn->pools.objs[i]->def->name, - privvol->name, - privvol->key); + if (privvol) { + ret = virGetStorageVol(conn, + privconn->pools.objs[i]->def->name, + privvol->name, + privvol->key); + break; + } } } - testError(conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching key '%s'"), key); - return NULL; + if (!ret) + testError(conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching key '%s'"), key); + + return ret; } static virStorageVolPtr @@ -2346,23 +2541,28 @@ testStorageVolumeLookupByPath(virConnect const char *path) { testConnPtr privconn = conn->privateData; unsigned int i; + virStorageVolPtr ret = NULL; for (i = 0 ; i < privconn->pools.count ; i++) { if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { virStorageVolDefPtr privvol = virStorageVolDefFindByPath(privconn->pools.objs[i], path); - if (privvol) - return virGetStorageVol(conn, - privconn->pools.objs[i]->def->name, - privvol->name, - privvol->key); + if (privvol) { + ret = virGetStorageVol(conn, + privconn->pools.objs[i]->def->name, + privvol->name, + privvol->key); + break; + } } } - testError(conn, VIR_ERR_INVALID_STORAGE_VOL, - _("no storage vol with matching path '%s'"), path); - return NULL; + if (!ret) + testError(conn, VIR_ERR_INVALID_STORAGE_VOL, + _("no storage vol with matching path '%s'"), path); + + return ret; } static virStorageVolPtr @@ -2371,33 +2571,33 @@ testStorageVolumeCreateXML(virStoragePoo unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = pool->conn->privateData; virStoragePoolObjPtr privpool; - virStorageVolDefPtr privvol; + virStorageVolDefPtr privvol = NULL; + virStorageVolPtr ret = NULL; privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), pool->name); - return NULL; + goto cleanup; } privvol = virStorageVolDefParse(pool->conn, privpool->def, xmldesc, NULL); if (privvol == NULL) - return NULL; + goto cleanup; if (virStorageVolDefFindByName(privpool, privvol->name)) { testError(pool->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("storage vol already exists")); - virStorageVolDefFree(privvol); - return NULL; + goto cleanup; } /* Make sure enough space */ @@ -2406,8 +2606,7 @@ testStorageVolumeCreateXML(virStoragePoo testError(pool->conn, VIR_ERR_INTERNAL_ERROR, _("Not enough free space in pool for volume '%s'"), privvol->name); - virStorageVolDefFree(privvol); - return NULL; + goto cleanup; } privpool->def->available = (privpool->def->capacity - privpool->def->allocation); @@ -2415,16 +2614,14 @@ testStorageVolumeCreateXML(virStoragePoo if (VIR_REALLOC_N(privpool->volumes.objs, privpool->volumes.count+1) < 0) { testError(pool->conn, VIR_ERR_NO_MEMORY, NULL); - virStorageVolDefFree(privvol); - return NULL; + goto cleanup; } if (VIR_ALLOC_N(privvol->target.path, strlen(privpool->def->target.path) + 1 + strlen(privvol->name) + 1) < 0) { - virStorageVolDefFree(privvol); testError(pool->conn, VIR_ERR_NO_MEMORY, "%s", _("target")); - return NULL; + goto cleanup; } strcpy(privvol->target.path, privpool->def->target.path); @@ -2432,10 +2629,9 @@ testStorageVolumeCreateXML(virStoragePoo strcat(privvol->target.path, privvol->name); privvol->key = strdup(privvol->target.path); if (privvol->key == NULL) { - virStorageVolDefFree(privvol); testError(pool->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage vol key")); - return NULL; + goto cleanup; } privpool->def->allocation += privvol->allocation; @@ -2443,9 +2639,14 @@ testStorageVolumeCreateXML(virStoragePoo privpool->def->allocation); privpool->volumes.objs[privpool->volumes.count++] = privvol; + privvol = NULL; - return virGetStorageVol(pool->conn, privpool->def->name, - privvol->name, privvol->key); + ret = virGetStorageVol(pool->conn, privpool->def->name, + privvol->name, privvol->key); + +cleanup: + virStorageVolDefFree(privvol); + return ret; } static int @@ -2455,13 +2656,14 @@ testStorageVolumeDelete(virStorageVolPtr virStoragePoolObjPtr privpool; virStorageVolDefPtr privvol; int i; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } @@ -2471,13 +2673,13 @@ testStorageVolumeDelete(virStorageVolPtr testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, _("no storage vol with matching name '%s'"), vol->name); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(vol->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), vol->pool); - return -1; + goto cleanup; } @@ -2504,8 +2706,10 @@ testStorageVolumeDelete(virStorageVolPtr break; } } + ret = 0; - return 0; +cleanup: + return ret; } @@ -2527,13 +2731,14 @@ testStorageVolumeGetInfo(virStorageVolPt testConnPtr privconn = vol->conn->privateData; virStoragePoolObjPtr privpool; virStorageVolDefPtr privvol; + int ret = -1; privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return -1; + goto cleanup; } privvol = virStorageVolDefFindByName(privpool, vol->name); @@ -2542,21 +2747,23 @@ testStorageVolumeGetInfo(virStorageVolPt testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, _("no storage vol with matching name '%s'"), vol->name); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(vol->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), vol->pool); - return -1; + goto cleanup; } memset(info, 0, sizeof(*info)); info->type = testStorageVolumeTypeForPool(privpool->def->type); info->capacity = privvol->capacity; info->allocation = privvol->allocation; + ret = 0; - return 0; +cleanup: + return ret; } static char * @@ -2565,13 +2772,14 @@ testStorageVolumeGetXMLDesc(virStorageVo testConnPtr privconn = vol->conn->privateData; virStoragePoolObjPtr privpool; virStorageVolDefPtr privvol; + char *ret = NULL; privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } privvol = virStorageVolDefFindByName(privpool, vol->name); @@ -2580,16 +2788,19 @@ testStorageVolumeGetXMLDesc(virStorageVo testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, _("no storage vol with matching name '%s'"), vol->name); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(vol->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), vol->pool); - return NULL; + goto cleanup; } - return virStorageVolDefFormat(vol->conn, privpool->def, privvol); + ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol); + +cleanup: + return ret; } static char * @@ -2597,15 +2808,14 @@ testStorageVolumeGetPath(virStorageVolPt testConnPtr privconn = vol->conn->privateData; virStoragePoolObjPtr privpool; virStorageVolDefPtr privvol; - char *ret; - + char *ret = NULL; privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return NULL; + goto cleanup; } privvol = virStorageVolDefFindByName(privpool, vol->name); @@ -2614,20 +2824,20 @@ testStorageVolumeGetPath(virStorageVolPt testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL, _("no storage vol with matching name '%s'"), vol->name); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(privpool)) { testError(vol->conn, VIR_ERR_INTERNAL_ERROR, _("storage pool '%s' is not active"), vol->pool); - return NULL; + goto cleanup; } ret = strdup(privvol->target.path); - if (ret == NULL) { + if (ret == NULL) testError(vol->conn, VIR_ERR_NO_MEMORY, "%s", _("path")); - return NULL; - } + +cleanup: return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:23:18PM +0000, Daniel P. Berrange wrote:
This patch reduces the number of return points in methods in the test driver. This is done by switching most 'return -1' calls into a 'goto cleanup' centralizing all cleanup in methods.
test.c | 812 ++++++++++++++++++++++++++++++++++++++++-------------------------
Okay, that makes the code a bit bigger, but the reason is fine. The biggest risk is that we now rely a lot more on local variable initializations, hopefully the compiler will report if we missed one. +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the test driver thread safe, adding a global driver lock, and the neccessary locking calls on domain/network/storagepool objects. You'll notice there are many calls to virDomainObjUnlock but very few corresponding calls to virDomainObjLock This is because the contract of virDomainFindByUUID declares that the object it returns is already locked. Methods which create / delete virDomainObj instances have to keep the global driver lock held for their whole duration, but others can drop it immediately after getting the virDomainObjPtr instance. src/test.c | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++----- tests/virsh-all | 1 2 files changed, 420 insertions(+), 41 deletions(-) Daniel diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -58,6 +58,8 @@ typedef struct _testCell *testCellPtr; #define MAX_CELLS 128 struct _testConn { + PTHREAD_MUTEX_T(lock); + char path[PATH_MAX]; int nextDomID; virCapsPtr caps; @@ -90,6 +92,16 @@ static const virNodeInfo defaultNodeInfo #define testError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) + +static void testDriverLock(testConnPtr driver) +{ + pthread_mutex_lock(&driver->lock); +} + +static void testDriverUnlock(testConnPtr driver) +{ + pthread_mutex_unlock(&driver->lock); +} static virCapsPtr testBuildCapabilities(virConnectPtr conn) { @@ -200,6 +212,8 @@ static int testOpenDefault(virConnectPtr return VIR_DRV_OPEN_ERROR; } conn->privateData = privconn; + pthread_mutex_init(&privconn->lock, NULL); + testDriverLock(privconn); if (gettimeofday(&tv, NULL) < 0) { testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day")); @@ -232,6 +246,7 @@ static int testOpenDefault(virConnectPtr domobj->def->id = privconn->nextDomID++; domobj->state = VIR_DOMAIN_RUNNING; domobj->persistent = 1; + virDomainObjUnlock(domobj); if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) goto error; @@ -241,6 +256,7 @@ static int testOpenDefault(virConnectPtr } netobj->active = 1; netobj->persistent = 1; + virNetworkObjUnlock(netobj); if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL))) goto error; @@ -250,10 +266,15 @@ static int testOpenDefault(virConnectPtr virStoragePoolDefFree(pooldef); goto error; } - if (testStoragePoolObjSetDefaults(poolobj) == -1) + + if (testStoragePoolObjSetDefaults(poolobj) == -1) { + virStoragePoolObjUnlock(poolobj); goto error; + } poolobj->active = 1; + virStoragePoolObjUnlock(poolobj); + testDriverUnlock(privconn); return VIR_DRV_OPEN_SUCCESS; error: @@ -261,6 +282,7 @@ error: virNetworkObjListFree(&privconn->networks); virStoragePoolObjListFree(&privconn->pools); virCapabilitiesFree(privconn->caps); + testDriverUnlock(privconn); VIR_FREE(privconn); return VIR_DRV_OPEN_ERROR; } @@ -307,6 +329,8 @@ static int testOpenFromFile(virConnectPt return VIR_DRV_OPEN_ERROR; } conn->privateData = privconn; + pthread_mutex_init(&privconn->lock, NULL); + testDriverLock(privconn); if (!(privconn->caps = testBuildCapabilities(conn))) goto error; @@ -445,6 +469,7 @@ static int testOpenFromFile(virConnectPt dom->state = VIR_DOMAIN_RUNNING; dom->def->id = privconn->nextDomID++; dom->persistent = 1; + virDomainObjUnlock(dom); } if (domains != NULL) VIR_FREE(domains); @@ -478,8 +503,8 @@ static int testOpenFromFile(virConnectPt virNetworkDefFree(def); goto error; } - net->persistent = 1; + virNetworkObjUnlock(net); } if (networks != NULL) VIR_FREE(networks); @@ -529,15 +554,19 @@ static int testOpenFromFile(virConnectPt goto error; } - if (testStoragePoolObjSetDefaults(pool) == -1) + if (testStoragePoolObjSetDefaults(pool) == -1) { + virStoragePoolObjUnlock(pool); goto error; + } pool->active = 1; + virStoragePoolObjUnlock(pool); } if (pools != NULL) VIR_FREE(pools); xmlXPathFreeContext(ctxt); xmlFreeDoc(xml); + testDriverUnlock(privconn); return (0); @@ -552,6 +581,7 @@ static int testOpenFromFile(virConnectPt virDomainObjListFree(&privconn->domains); virNetworkObjListFree(&privconn->networks); virStoragePoolObjListFree(&privconn->pools); + testDriverUnlock(privconn); VIR_FREE(privconn); conn->privateData = NULL; return VIR_DRV_OPEN_ERROR; @@ -598,11 +628,12 @@ static int testClose(virConnectPtr conn) static int testClose(virConnectPtr conn) { testConnPtr privconn = conn->privateData; - + testDriverLock(privconn); virCapabilitiesFree(privconn->caps); virDomainObjListFree(&privconn->domains); virNetworkObjListFree(&privconn->networks); virStoragePoolObjListFree(&privconn->pools); + testDriverUnlock(privconn); VIR_FREE (privconn); conn->privateData = NULL; @@ -646,8 +677,9 @@ static int testNodeGetInfo(virConnectPtr virNodeInfoPtr info) { testConnPtr privconn = conn->privateData; - + testDriverLock(privconn); memcpy(info, &privconn->nodeInfo, sizeof(virNodeInfo)); + testDriverUnlock(privconn); return (0); } @@ -655,10 +687,10 @@ static char *testGetCapabilities (virCon { testConnPtr privconn = conn->privateData; char *xml; - + testDriverLock(privconn); if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) testError(conn, VIR_ERR_NO_MEMORY, NULL); - + testDriverUnlock(privconn); return xml; } @@ -667,9 +699,11 @@ static int testNumOfDomains(virConnectPt testConnPtr privconn = conn->privateData; unsigned int numActive = 0, i; + testDriverLock(privconn); for (i = 0 ; i < privconn->domains.count ; i++) if (virDomainIsActive(privconn->domains.objs[i])) numActive++; + testDriverUnlock(privconn); return numActive; } @@ -681,8 +715,9 @@ testDomainCreateXML(virConnectPtr conn, testConnPtr privconn = conn->privateData; virDomainPtr ret = NULL; virDomainDefPtr def; - virDomainObjPtr dom; + virDomainObjPtr dom = NULL; + testDriverLock(privconn); if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) goto cleanup; @@ -699,6 +734,9 @@ testDomainCreateXML(virConnectPtr conn, ret->id = def->id; cleanup: + if (dom) + virDomainObjUnlock(dom); + testDriverUnlock(privconn); return ret; } @@ -710,7 +748,11 @@ static virDomainPtr testLookupDomainByID virDomainPtr ret = NULL; virDomainObjPtr dom; - if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) { + testDriverLock(privconn); + dom = virDomainFindByID(&privconn->domains, id); + testDriverUnlock(privconn); + + if (dom == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } @@ -720,6 +762,8 @@ static virDomainPtr testLookupDomainByID ret->id = dom->def->id; cleanup: + if (dom) + virDomainObjUnlock(dom); return ret; } @@ -730,7 +774,11 @@ static virDomainPtr testLookupDomainByUU virDomainPtr ret = NULL; virDomainObjPtr dom ; - if ((dom = virDomainFindByUUID(&privconn->domains, uuid)) == NULL) { + testDriverLock(privconn); + dom = virDomainFindByUUID(&privconn->domains, uuid); + testDriverUnlock(privconn); + + if (dom == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } @@ -740,6 +788,8 @@ static virDomainPtr testLookupDomainByUU ret->id = dom->def->id; cleanup: + if (dom) + virDomainObjUnlock(dom); return ret; } @@ -750,7 +800,11 @@ static virDomainPtr testLookupDomainByNa virDomainPtr ret = NULL; virDomainObjPtr dom; - if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) { + testDriverLock(privconn); + dom = virDomainFindByName(&privconn->domains, name); + testDriverUnlock(privconn); + + if (dom == NULL) { testError (conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } @@ -760,6 +814,8 @@ static virDomainPtr testLookupDomainByNa ret->id = dom->def->id; cleanup: + if (dom) + virDomainObjUnlock(dom); return ret; } @@ -770,9 +826,14 @@ static int testListDomains (virConnectPt testConnPtr privconn = conn->privateData; unsigned int n = 0, i; - for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) + testDriverLock(privconn); + for (i = 0 ; i < privconn->domains.count && n < maxids ; i++) { + virDomainObjLock(privconn->domains.objs[i]); if (virDomainIsActive(privconn->domains.objs[i])) ids[n++] = privconn->domains.objs[i]->def->id; + virDomainObjUnlock(privconn->domains.objs[i]); + } + testDriverUnlock(privconn); return n; } @@ -783,6 +844,7 @@ static int testDestroyDomain (virDomainP virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -797,10 +859,14 @@ static int testDestroyDomain (virDomainP if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom); + privdom = NULL; } ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -810,8 +876,10 @@ static int testResumeDomain (virDomainPt virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -829,6 +897,8 @@ static int testResumeDomain (virDomainPt ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -838,8 +908,10 @@ static int testPauseDomain (virDomainPtr virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -858,6 +930,8 @@ static int testPauseDomain (virDomainPtr ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -867,6 +941,7 @@ static int testShutdownDomain (virDomain virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -884,9 +959,17 @@ static int testShutdownDomain (virDomain privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; privdom->def->id = -1; + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -898,6 +981,7 @@ static int testRebootDomain (virDomainPt virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -935,9 +1019,18 @@ static int testRebootDomain (virDomainPt break; } + if (privdom->state == VIR_DOMAIN_SHUTOFF && !privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } + ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -949,8 +1042,10 @@ static int testGetDomainInfo (virDomainP virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -971,6 +1066,8 @@ static int testGetDomainInfo (virDomainP ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -988,6 +1085,7 @@ static int testDomainSave(virDomainPtr d virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -1042,6 +1140,7 @@ static int testDomainSave(virDomainPtr d if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom); + privdom = NULL; } ret = 0; @@ -1056,7 +1155,9 @@ cleanup: close(fd); unlink(path); } - + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -1069,7 +1170,7 @@ static int testDomainRestore(virConnectP int fd = -1; int len; virDomainDefPtr def = NULL; - virDomainObjPtr dom; + virDomainObjPtr dom = NULL; int ret = -1; if ((fd = open(path, O_RDONLY)) < 0) { @@ -1108,6 +1209,7 @@ static int testDomainRestore(virConnectP } xml[len] = '\0'; + testDriverLock(privconn); def = virDomainDefParseString(conn, privconn->caps, xml); if (!def) goto cleanup; @@ -1126,6 +1228,9 @@ cleanup: VIR_FREE(xml); if (fd != -1) close(fd); + if (dom) + virDomainObjUnlock(dom); + testDriverUnlock(privconn); return ret; } @@ -1138,6 +1243,7 @@ static int testDomainCoreDump(virDomainP virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -1168,12 +1274,16 @@ static int testDomainCoreDump(virDomainP if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom); + privdom = NULL; } ret = 0; cleanup: if (fd != -1) close(fd); + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -1189,8 +1299,10 @@ static unsigned long testGetMaxMemory(vi virDomainObjPtr privdom; unsigned long ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1200,6 +1312,8 @@ static unsigned long testGetMaxMemory(vi ret = privdom->def->maxmem; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1210,8 +1324,10 @@ static int testSetMaxMemory(virDomainPtr virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1223,6 +1339,8 @@ static int testSetMaxMemory(virDomainPtr ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1233,8 +1351,10 @@ static int testSetMemory(virDomainPtr do virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1251,6 +1371,8 @@ static int testSetMemory(virDomainPtr do ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1260,8 +1382,12 @@ static int testSetVcpus(virDomainPtr dom virDomainObjPtr privdom; int ret = -1; - if ((privdom = virDomainFindByName(&privconn->domains, - domain->name)) == NULL) { + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto cleanup; } @@ -1276,6 +1402,8 @@ static int testSetVcpus(virDomainPtr dom ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1286,8 +1414,12 @@ static char *testDomainDumpXML(virDomain virDomainObjPtr privdom; char *ret = NULL; - if ((privdom = virDomainFindByName(&privconn->domains, - domain->name)) == NULL) { + testDriverLock(privconn); + privdom = virDomainFindByName(&privconn->domains, + domain->name); + testDriverUnlock(privconn); + + if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); goto cleanup; } @@ -1300,6 +1432,8 @@ static char *testDomainDumpXML(virDomain flags); cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1307,9 +1441,14 @@ static int testNumOfDefinedDomains(virCo testConnPtr privconn = conn->privateData; unsigned int numInactive = 0, i; - for (i = 0 ; i < privconn->domains.count ; i++) + testDriverLock(privconn); + for (i = 0 ; i < privconn->domains.count ; i++) { + virDomainObjLock(privconn->domains.objs[i]); if (!virDomainIsActive(privconn->domains.objs[i])) numInactive++; + virDomainObjUnlock(privconn->domains.objs[i]); + } + testDriverUnlock(privconn); return numInactive; } @@ -1320,11 +1459,18 @@ static int testListDefinedDomains(virCon testConnPtr privconn = conn->privateData; unsigned int n = 0, i; + testDriverLock(privconn); memset(names, 0, sizeof(*names)*maxnames); - for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) + for (i = 0 ; i < privconn->domains.count && n < maxnames ; i++) { + virDomainObjLock(privconn->domains.objs[i]); if (!virDomainIsActive(privconn->domains.objs[i]) && - !(names[n++] = strdup(privconn->domains.objs[i]->def->name))) + !(names[n++] = strdup(privconn->domains.objs[i]->def->name))) { + virDomainObjUnlock(privconn->domains.objs[i]); goto no_memory; + } + virDomainObjUnlock(privconn->domains.objs[i]); + } + testDriverUnlock(privconn); return n; @@ -1332,6 +1478,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < maxnames ; n++) VIR_FREE(names[n]); + testDriverUnlock(privconn); return -1; } @@ -1340,8 +1487,9 @@ static virDomainPtr testDomainDefineXML( testConnPtr privconn = conn->privateData; virDomainPtr ret = NULL; virDomainDefPtr def; - virDomainObjPtr dom; + virDomainObjPtr dom = NULL; + testDriverLock(privconn); if ((def = virDomainDefParseString(conn, privconn->caps, xml)) == NULL) goto cleanup; @@ -1359,6 +1507,9 @@ static virDomainPtr testDomainDefineXML( cleanup: virDomainDefFree(def); + if (dom) + virDomainObjUnlock(dom); + testDriverUnlock(privconn); return ret; } @@ -1369,6 +1520,7 @@ static int testNodeGetCellsFreeMemory(vi int i, j; int ret = -1; + testDriverLock(privconn); if (startCell > privconn->numCells) { testError(conn, VIR_ERR_INVALID_ARG, "%s", _("Range exceeds available cells")); @@ -1383,6 +1535,7 @@ static int testNodeGetCellsFreeMemory(vi ret = j; cleanup: + testDriverUnlock(privconn); return ret; } @@ -1392,6 +1545,7 @@ static int testDomainCreate(virDomainPtr virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -1411,6 +1565,9 @@ static int testDomainCreate(virDomainPtr ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -1419,6 +1576,7 @@ static int testDomainUndefine(virDomainP virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); @@ -1434,11 +1592,16 @@ static int testDomainUndefine(virDomainP } privdom->state = VIR_DOMAIN_SHUTOFF; + virDomainObjUnlock(privdom); virDomainRemoveInactive(&privconn->domains, privdom); + privdom = NULL; ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; } @@ -1449,8 +1612,10 @@ static int testDomainGetAutostart(virDom virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1461,6 +1626,8 @@ static int testDomainGetAutostart(virDom ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1472,8 +1639,10 @@ static int testDomainSetAutostart(virDom virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1484,6 +1653,8 @@ static int testDomainSetAutostart(virDom ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1508,8 +1679,10 @@ static int testDomainGetSchedulerParams( virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1528,6 +1701,8 @@ static int testDomainGetSchedulerParams( ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1540,8 +1715,10 @@ static int testDomainSetSchedulerParams( virDomainObjPtr privdom; int ret = -1; + testDriverLock(privconn); privdom = virDomainFindByName(&privconn->domains, domain->name); + testDriverUnlock(privconn); if (privdom == NULL) { testError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1565,6 +1742,8 @@ static int testDomainSetSchedulerParams( ret = 0; cleanup: + if (privdom) + virDomainObjUnlock(privdom); return ret; } @@ -1591,7 +1770,11 @@ static virNetworkPtr testLookupNetworkBy virNetworkObjPtr net; virNetworkPtr ret = NULL; - if ((net = virNetworkFindByUUID(&privconn->networks, uuid)) == NULL) { + testDriverLock(privconn); + net = virNetworkFindByUUID(&privconn->networks, uuid); + testDriverUnlock(privconn); + + if (net == NULL) { testError (conn, VIR_ERR_NO_NETWORK, NULL); goto cleanup; } @@ -1599,6 +1782,8 @@ static virNetworkPtr testLookupNetworkBy ret = virGetNetwork(conn, net->def->name, net->def->uuid); cleanup: + if (net) + virNetworkObjUnlock(net); return ret; } @@ -1609,7 +1794,11 @@ static virNetworkPtr testLookupNetworkBy virNetworkObjPtr net; virNetworkPtr ret = NULL; - if ((net = virNetworkFindByName(&privconn->networks, name)) == NULL) { + testDriverLock(privconn); + net = virNetworkFindByName(&privconn->networks, name); + testDriverUnlock(privconn); + + if (net == NULL) { testError (conn, VIR_ERR_NO_NETWORK, NULL); goto cleanup; } @@ -1617,6 +1806,8 @@ static virNetworkPtr testLookupNetworkBy ret = virGetNetwork(conn, net->def->name, net->def->uuid); cleanup: + if (net) + virNetworkObjUnlock(net); return ret; } @@ -1625,9 +1816,14 @@ static int testNumNetworks(virConnectPtr testConnPtr privconn = conn->privateData; int numActive = 0, i; - for (i = 0 ; i < privconn->networks.count ; i++) + testDriverLock(privconn); + for (i = 0 ; i < privconn->networks.count ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); if (virNetworkIsActive(privconn->networks.objs[i])) numActive++; + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); return numActive; } @@ -1636,11 +1832,18 @@ static int testListNetworks(virConnectPt testConnPtr privconn = conn->privateData; int n = 0, i; + testDriverLock(privconn); memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) + for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); if (virNetworkIsActive(privconn->networks.objs[i]) && - !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) + !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) { + virNetworkObjUnlock(privconn->networks.objs[i]); goto no_memory; + } + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); return n; @@ -1648,6 +1851,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); + testDriverUnlock(privconn); return -1; } @@ -1655,9 +1859,14 @@ static int testNumDefinedNetworks(virCon testConnPtr privconn = conn->privateData; int numInactive = 0, i; - for (i = 0 ; i < privconn->networks.count ; i++) + testDriverLock(privconn); + for (i = 0 ; i < privconn->networks.count ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); if (!virNetworkIsActive(privconn->networks.objs[i])) numInactive++; + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); return numInactive; } @@ -1666,11 +1875,18 @@ static int testListDefinedNetworks(virCo testConnPtr privconn = conn->privateData; int n = 0, i; + testDriverLock(privconn); memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) + for (i = 0 ; i < privconn->networks.count && n < nnames ; i++) { + virNetworkObjLock(privconn->networks.objs[i]); if (!virNetworkIsActive(privconn->networks.objs[i]) && - !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) + !(names[n++] = strdup(privconn->networks.objs[i]->def->name))) { + virNetworkObjUnlock(privconn->networks.objs[i]); goto no_memory; + } + virNetworkObjUnlock(privconn->networks.objs[i]); + } + testDriverUnlock(privconn); return n; @@ -1678,15 +1894,17 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); + testDriverUnlock(privconn); return -1; } static virNetworkPtr testNetworkCreate(virConnectPtr conn, const char *xml) { testConnPtr privconn = conn->privateData; virNetworkDefPtr def; - virNetworkObjPtr net; + virNetworkObjPtr net = NULL; virNetworkPtr ret = NULL; + testDriverLock(privconn); if ((def = virNetworkDefParseString(conn, xml)) == NULL) goto cleanup; @@ -1701,15 +1919,19 @@ static virNetworkPtr testNetworkCreate(v cleanup: virNetworkDefFree(def); + if (net) + virNetworkObjUnlock(net); + testDriverUnlock(privconn); return ret; } static virNetworkPtr testNetworkDefine(virConnectPtr conn, const char *xml) { testConnPtr privconn = conn->privateData; virNetworkDefPtr def; - virNetworkObjPtr net; + virNetworkObjPtr net = NULL; virNetworkPtr ret = NULL; + testDriverLock(privconn); if ((def = virNetworkDefParseString(conn, xml)) == NULL) goto cleanup; @@ -1724,6 +1946,9 @@ static virNetworkPtr testNetworkDefine(v cleanup: virNetworkDefFree(def); + if (net) + virNetworkObjUnlock(net); + testDriverUnlock(privconn); return ret; } @@ -1732,6 +1957,7 @@ static int testNetworkUndefine(virNetwor virNetworkObjPtr privnet; int ret = -1; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); @@ -1748,9 +1974,13 @@ static int testNetworkUndefine(virNetwor virNetworkRemoveInactive(&privconn->networks, privnet); + privnet = NULL; ret = 0; cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + testDriverUnlock(privconn); return ret; } @@ -1759,8 +1989,10 @@ static int testNetworkStart(virNetworkPt virNetworkObjPtr privnet; int ret = -1; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); + testDriverUnlock(privconn); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1777,6 +2009,8 @@ static int testNetworkStart(virNetworkPt ret = 0; cleanup: + if (privnet) + virNetworkObjUnlock(privnet); return ret; } @@ -1785,6 +2019,7 @@ static int testNetworkDestroy(virNetwork virNetworkObjPtr privnet; int ret = -1; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); @@ -1797,10 +2032,14 @@ static int testNetworkDestroy(virNetwork if (!privnet->persistent) { virNetworkRemoveInactive(&privconn->networks, privnet); + privnet = NULL; } ret = 0; cleanup: + if (privnet) + virNetworkObjUnlock(privnet); + testDriverUnlock(privconn); return ret; } @@ -1809,8 +2048,10 @@ static char *testNetworkDumpXML(virNetwo virNetworkObjPtr privnet; char *ret = NULL; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); + testDriverUnlock(privconn); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1820,6 +2061,8 @@ static char *testNetworkDumpXML(virNetwo ret = virNetworkDefFormat(network->conn, privnet->def); cleanup: + if (privnet) + virNetworkObjUnlock(privnet); return ret; } @@ -1828,8 +2071,10 @@ static char *testNetworkGetBridgeName(vi char *bridge = NULL; virNetworkObjPtr privnet; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); + testDriverUnlock(privconn); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1843,6 +2088,8 @@ static char *testNetworkGetBridgeName(vi } cleanup: + if (privnet) + virNetworkObjUnlock(privnet); return bridge; } @@ -1852,8 +2099,10 @@ static int testNetworkGetAutostart(virNe virNetworkObjPtr privnet; int ret = -1; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); + testDriverUnlock(privconn); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1864,6 +2113,8 @@ static int testNetworkGetAutostart(virNe ret = 0; cleanup: + if (privnet) + virNetworkObjUnlock(privnet); return ret; } @@ -1873,8 +2124,10 @@ static int testNetworkSetAutostart(virNe virNetworkObjPtr privnet; int ret = -1; + testDriverLock(privconn); privnet = virNetworkFindByName(&privconn->networks, network->name); + testDriverUnlock(privconn); if (privnet == NULL) { testError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -1885,6 +2138,8 @@ static int testNetworkSetAutostart(virNe ret = 0; cleanup: + if (privnet) + virNetworkObjUnlock(privnet); return ret; } @@ -1930,7 +2185,9 @@ testStoragePoolLookupByUUID(virConnectPt virStoragePoolObjPtr pool; virStoragePoolPtr ret = NULL; + testDriverLock(privconn); pool = virStoragePoolObjFindByUUID(&privconn->pools, uuid); + testDriverUnlock(privconn); if (pool == NULL) { testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); @@ -1940,6 +2197,8 @@ testStoragePoolLookupByUUID(virConnectPt ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -1950,7 +2209,9 @@ testStoragePoolLookupByName(virConnectPt virStoragePoolObjPtr pool; virStoragePoolPtr ret = NULL; + testDriverLock(privconn); pool = virStoragePoolObjFindByName(&privconn->pools, name); + testDriverUnlock(privconn); if (pool == NULL) { testError (conn, VIR_ERR_NO_STORAGE_POOL, NULL); @@ -1960,6 +2221,8 @@ testStoragePoolLookupByName(virConnectPt ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -1973,9 +2236,11 @@ testStorageNumPools(virConnectPtr conn) testConnPtr privconn = conn->privateData; int numActive = 0, i; + testDriverLock(privconn); for (i = 0 ; i < privconn->pools.count ; i++) if (virStoragePoolObjIsActive(privconn->pools.objs[i])) numActive++; + testDriverUnlock(privconn); return numActive; } @@ -1987,11 +2252,18 @@ testStorageListPools(virConnectPtr conn, testConnPtr privconn = conn->privateData; int n = 0, i; + testDriverLock(privconn); memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) + for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); if (virStoragePoolObjIsActive(privconn->pools.objs[i]) && - !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) + !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) { + virStoragePoolObjUnlock(privconn->pools.objs[i]); goto no_memory; + } + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); return n; @@ -1999,6 +2271,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); + testDriverUnlock(privconn); return -1; } @@ -2007,9 +2280,14 @@ testStorageNumDefinedPools(virConnectPtr testConnPtr privconn = conn->privateData; int numInactive = 0, i; - for (i = 0 ; i < privconn->pools.count ; i++) + testDriverLock(privconn); + for (i = 0 ; i < privconn->pools.count ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); if (!virStoragePoolObjIsActive(privconn->pools.objs[i])) numInactive++; + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); return numInactive; } @@ -2021,11 +2299,18 @@ testStorageListDefinedPools(virConnectPt testConnPtr privconn = conn->privateData; int n = 0, i; + testDriverLock(privconn); memset(names, 0, sizeof(*names)*nnames); - for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) + for (i = 0 ; i < privconn->pools.count && n < nnames ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); if (!virStoragePoolObjIsActive(privconn->pools.objs[i]) && - !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) + !(names[n++] = strdup(privconn->pools.objs[i]->def->name))) { + virStoragePoolObjUnlock(privconn->pools.objs[i]); goto no_memory; + } + virStoragePoolObjUnlock(privconn->pools.objs[i]); + } + testDriverUnlock(privconn); return n; @@ -2033,6 +2318,7 @@ no_memory: testError(conn, VIR_ERR_NO_MEMORY, NULL); for (n = 0 ; n < nnames ; n++) VIR_FREE(names[n]); + testDriverUnlock(privconn); return -1; } @@ -2047,8 +2333,10 @@ testStoragePoolStart(virStoragePoolPtr p virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2067,6 +2355,8 @@ testStoragePoolStart(virStoragePoolPtr p ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2086,9 +2376,10 @@ testStoragePoolCreate(virConnectPtr conn unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = conn->privateData; virStoragePoolDefPtr def; - virStoragePoolObjPtr pool; + virStoragePoolObjPtr pool = NULL; virStoragePoolPtr ret = NULL; + testDriverLock(privconn); if (!(def = virStoragePoolDefParse(conn, xml, NULL))) goto cleanup; @@ -2117,6 +2408,9 @@ testStoragePoolCreate(virConnectPtr conn cleanup: virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + testDriverUnlock(privconn); return ret; } @@ -2126,9 +2420,10 @@ testStoragePoolDefine(virConnectPtr conn unsigned int flags ATTRIBUTE_UNUSED) { testConnPtr privconn = conn->privateData; virStoragePoolDefPtr def; - virStoragePoolObjPtr pool; + virStoragePoolObjPtr pool = NULL; virStoragePoolPtr ret = NULL; + testDriverLock(privconn); if (!(def = virStoragePoolDefParse(conn, xml, NULL))) goto cleanup; @@ -2151,6 +2446,9 @@ testStoragePoolDefine(virConnectPtr conn cleanup: virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + testDriverUnlock(privconn); return ret; } @@ -2160,6 +2458,7 @@ testStoragePoolUndefine(virStoragePoolPt virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); @@ -2178,6 +2477,9 @@ testStoragePoolUndefine(virStoragePoolPt ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + testDriverUnlock(privconn); return ret; } @@ -2188,8 +2490,10 @@ testStoragePoolBuild(virStoragePoolPtr p virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2203,6 +2507,8 @@ testStoragePoolBuild(virStoragePoolPtr p } cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2213,6 +2519,7 @@ testStoragePoolDestroy(virStoragePoolPtr virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); @@ -2229,11 +2536,16 @@ testStoragePoolDestroy(virStoragePoolPtr privpool->active = 0; - if (privpool->configFile == NULL) + if (privpool->configFile == NULL) { virStoragePoolObjRemove(&privconn->pools, privpool); + privpool = NULL; + } ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); + testDriverUnlock(privconn); return ret; } @@ -2245,8 +2557,10 @@ testStoragePoolDelete(virStoragePoolPtr virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2262,6 +2576,8 @@ testStoragePoolDelete(virStoragePoolPtr ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2273,8 +2589,10 @@ testStoragePoolRefresh(virStoragePoolPtr virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2289,6 +2607,8 @@ testStoragePoolRefresh(virStoragePoolPtr ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2300,8 +2620,10 @@ testStoragePoolGetInfo(virStoragePoolPtr virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2319,6 +2641,8 @@ testStoragePoolGetInfo(virStoragePoolPtr ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2329,8 +2653,10 @@ testStoragePoolDumpXML(virStoragePoolPtr virStoragePoolObjPtr privpool; char *ret = NULL; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2340,6 +2666,8 @@ testStoragePoolDumpXML(virStoragePoolPtr ret = virStoragePoolDefFormat(pool->conn, privpool->def); cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2350,8 +2678,10 @@ testStoragePoolGetAutostart(virStoragePo virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2366,6 +2696,8 @@ testStoragePoolGetAutostart(virStoragePo ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2376,8 +2708,10 @@ testStoragePoolSetAutostart(virStoragePo virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2395,6 +2729,8 @@ testStoragePoolSetAutostart(virStoragePo ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2405,8 +2741,10 @@ testStoragePoolNumVolumes(virStoragePool virStoragePoolObjPtr privpool; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2422,6 +2760,8 @@ testStoragePoolNumVolumes(virStoragePool ret = privpool->volumes.count; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2434,9 +2774,10 @@ testStoragePoolListVolumes(virStoragePoo int i = 0, n = 0; memset(names, 0, maxnames); - + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2457,6 +2798,7 @@ testStoragePoolListVolumes(virStoragePoo } } + virStoragePoolObjUnlock(privpool); return n; cleanup: @@ -2464,6 +2806,8 @@ testStoragePoolListVolumes(virStoragePoo VIR_FREE(names[i]); memset(names, 0, maxnames); + if (privpool) + virStoragePoolObjUnlock(privpool); return -1; } @@ -2476,8 +2820,10 @@ testStorageVolumeLookupByName(virStorage virStorageVolDefPtr privvol; virStorageVolPtr ret = NULL; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2503,6 +2849,8 @@ testStorageVolumeLookupByName(virStorage privvol->name, privvol->key); cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2514,7 +2862,9 @@ testStorageVolumeLookupByKey(virConnectP unsigned int i; virStorageVolPtr ret = NULL; + testDriverLock(privconn); for (i = 0 ; i < privconn->pools.count ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { virStorageVolDefPtr privvol = virStorageVolDefFindByKey(privconn->pools.objs[i], key); @@ -2524,10 +2874,13 @@ testStorageVolumeLookupByKey(virConnectP privconn->pools.objs[i]->def->name, privvol->name, privvol->key); + virStoragePoolObjUnlock(privconn->pools.objs[i]); break; } } + virStoragePoolObjUnlock(privconn->pools.objs[i]); } + testDriverUnlock(privconn); if (!ret) testError(conn, VIR_ERR_INVALID_STORAGE_VOL, @@ -2543,7 +2896,9 @@ testStorageVolumeLookupByPath(virConnect unsigned int i; virStorageVolPtr ret = NULL; + testDriverLock(privconn); for (i = 0 ; i < privconn->pools.count ; i++) { + virStoragePoolObjLock(privconn->pools.objs[i]); if (virStoragePoolObjIsActive(privconn->pools.objs[i])) { virStorageVolDefPtr privvol = virStorageVolDefFindByPath(privconn->pools.objs[i], path); @@ -2553,10 +2908,13 @@ testStorageVolumeLookupByPath(virConnect privconn->pools.objs[i]->def->name, privvol->name, privvol->key); + virStoragePoolObjUnlock(privconn->pools.objs[i]); break; } + virStoragePoolObjUnlock(privconn->pools.objs[i]); } } + testDriverUnlock(privconn); if (!ret) testError(conn, VIR_ERR_INVALID_STORAGE_VOL, @@ -2574,8 +2932,10 @@ testStorageVolumeCreateXML(virStoragePoo virStorageVolDefPtr privvol = NULL; virStorageVolPtr ret = NULL; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, pool->name); + testDriverUnlock(privconn); if (privpool == NULL) { testError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2646,6 +3006,8 @@ testStorageVolumeCreateXML(virStoragePoo cleanup: virStorageVolDefFree(privvol); + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2658,8 +3020,10 @@ testStorageVolumeDelete(virStorageVolPtr int i; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); + testDriverUnlock(privconn); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2709,6 +3073,8 @@ testStorageVolumeDelete(virStorageVolPtr ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2733,8 +3099,10 @@ testStorageVolumeGetInfo(virStorageVolPt virStorageVolDefPtr privvol; int ret = -1; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); + testDriverUnlock(privconn); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2763,6 +3131,8 @@ testStorageVolumeGetInfo(virStorageVolPt ret = 0; cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2774,8 +3144,10 @@ testStorageVolumeGetXMLDesc(virStorageVo virStorageVolDefPtr privvol; char *ret = NULL; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); + testDriverUnlock(privconn); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2800,6 +3172,8 @@ testStorageVolumeGetXMLDesc(virStorageVo ret = virStorageVolDefFormat(vol->conn, privpool->def, privvol); cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } @@ -2810,8 +3184,10 @@ testStorageVolumeGetPath(virStorageVolPt virStorageVolDefPtr privvol; char *ret = NULL; + testDriverLock(privconn); privpool = virStoragePoolObjFindByName(&privconn->pools, vol->pool); + testDriverUnlock(privconn); if (privpool == NULL) { testError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -2838,6 +3214,8 @@ testStorageVolumeGetPath(virStorageVolPt testError(vol->conn, VIR_ERR_NO_MEMORY, "%s", _("path")); cleanup: + if (privpool) + virStoragePoolObjUnlock(privpool); return ret; } diff --git a/tests/virsh-all b/tests/virsh-all --- a/tests/virsh-all +++ b/tests/virsh-all @@ -22,6 +22,7 @@ fi fi test -z "$srcdir" && srcdir=$(pwd) +test -z "$abs_top_srcdir" && abs_top_srcdir=$(pwd)/.. . "$srcdir/test-lib.sh" fail=0 -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:27:14PM +0000, Daniel P. Berrange wrote:
This patch makes the test driver thread safe, adding a global driver lock, and the neccessary locking calls on domain/network/storagepool objects.
You'll notice there are many calls to
virDomainObjUnlock
but very few corresponding calls to
virDomainObjLock
This is because the contract of virDomainFindByUUID declares that the object it returns is already locked.
Methods which create / delete virDomainObj instances have to keep the global driver lock held for their whole duration, but others can drop it immediately after getting the virDomainObjPtr instance.
Okay, what about virDomainFindByID and virDomainFindByName ? They lock too or we are just avoiding them ?
+++ b/src/test.c @@ -58,6 +58,8 @@ typedef struct _testCell *testCellPtr; #define MAX_CELLS 128
struct _testConn { + PTHREAD_MUTEX_T(lock); +
hum, [...]
+ +static void testDriverLock(testConnPtr driver) +{ + pthread_mutex_lock(&driver->lock); +} + +static void testDriverUnlock(testConnPtr driver) +{ + pthread_mutex_unlock(&driver->lock); +}
static virCapsPtr testBuildCapabilities(virConnectPtr conn) { @@ -200,6 +212,8 @@ static int testOpenDefault(virConnectPtr return VIR_DRV_OPEN_ERROR; } conn->privateData = privconn; + pthread_mutex_init(&privconn->lock, NULL);
Can we abstract the mutex types and ops a little ? if libvirt were to be ported to a platform/compiler where pthreads are not available they would be able to fallback to xmlMutexPtr from libvirt which is ported to all platforms where libxml2 is usable (as far as I know).
+ testDriverLock(privconn);
if (gettimeofday(&tv, NULL) < 0) { testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day")); @@ -232,6 +246,7 @@ static int testOpenDefault(virConnectPtr domobj->def->id = privconn->nextDomID++; domobj->state = VIR_DOMAIN_RUNNING; domobj->persistent = 1; + virDomainObjUnlock(domobj);
the locking path is unclear here testOpenDefault uses virDomainAssignDef which then relies on virDomainFindByName() which would lock the domain object, right ?
if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML))) goto error; @@ -241,6 +256,7 @@ static int testOpenDefault(virConnectPtr } netobj->active = 1; netobj->persistent = 1; + virNetworkObjUnlock(netobj);
same with virNetworkAssignDef()
if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL))) goto error; @@ -250,10 +266,15 @@ static int testOpenDefault(virConnectPtr virStoragePoolDefFree(pooldef); goto error; } - if (testStoragePoolObjSetDefaults(poolobj) == -1) + + if (testStoragePoolObjSetDefaults(poolobj) == -1) { + virStoragePoolObjUnlock(poolobj); goto error;
ideally done in the error: switch but this makes things harder
+ } poolobj->active = 1; + virStoragePoolObjUnlock(poolobj);
+ testDriverUnlock(privconn); return VIR_DRV_OPEN_SUCCESS;
error: @@ -261,6 +282,7 @@ error: virNetworkObjListFree(&privconn->networks); virStoragePoolObjListFree(&privconn->pools); virCapabilitiesFree(privconn->caps); + testDriverUnlock(privconn); VIR_FREE(privconn); return VIR_DRV_OPEN_ERROR; } @@ -307,6 +329,8 @@ static int testOpenFromFile(virConnectPt
okay, similar to testOpenDefault() [...]
@@ -710,7 +748,11 @@ static virDomainPtr testLookupDomainByID virDomainPtr ret = NULL; virDomainObjPtr dom;
- if ((dom = virDomainFindByID(&privconn->domains, id)) == NULL) { + testDriverLock(privconn); + dom = virDomainFindByID(&privconn->domains, id); + testDriverUnlock(privconn);
so all virDomainFindBy__ do the locking, fine. [...]
@@ -750,7 +800,11 @@ static virDomainPtr testLookupDomainByNa virDomainPtr ret = NULL; virDomainObjPtr dom;
- if ((dom = virDomainFindByName(&privconn->domains, name)) == NULL) { + testDriverLock(privconn); + dom = virDomainFindByName(&privconn->domains, name); + testDriverUnlock(privconn); + + if (dom == NULL) {
actually a lot of those sequences are common, and correspond to the macros. later we may want to refactor maybe [...]
@@ -797,10 +859,14 @@ static int testDestroyDomain (virDomainP if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom);
will virDomainRemoveInactive also remove the lock before destroying the object ? the answer is surely in a later patch [...]
@@ -884,9 +959,17 @@ static int testShutdownDomain (virDomain privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; privdom->def->id = -1; + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } ret = 0;
hum, not specific to threading, we are improving the driver here.
cleanup: + if (privdom) + virDomainObjUnlock(privdom); + testDriverUnlock(privconn); return ret; }
okay, others functions are easier, but it's still painful to review.
diff --git a/tests/virsh-all b/tests/virsh-all --- a/tests/virsh-all +++ b/tests/virsh-all @@ -22,6 +22,7 @@ fi fi
test -z "$srcdir" && srcdir=$(pwd) +test -z "$abs_top_srcdir" && abs_top_srcdir=$(pwd)/.. . "$srcdir/test-lib.sh"
??? I hope it's worth the effort, it's a lot of complexity added. One of the things which worries me is that detecting errors will be hard, you end up with a locked server that can be far from trivial to debug. I'm really wondering how we could automate testing or at least ease the debug, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Mon, Dec 01, 2008 at 06:26:03PM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:27:14PM +0000, Daniel P. Berrange wrote:
This patch makes the test driver thread safe, adding a global driver lock, and the neccessary locking calls on domain/network/storagepool objects.
You'll notice there are many calls to
virDomainObjUnlock
but very few corresponding calls to
virDomainObjLock
This is because the contract of virDomainFindByUUID declares that the object it returns is already locked.
Methods which create / delete virDomainObj instances have to keep the global driver lock held for their whole duration, but others can drop it immediately after getting the virDomainObjPtr instance.
Okay, what about virDomainFindByID and virDomainFindByName ? They lock too or we are just avoiding them ?
All the virXXXXFindByYYY methods return a locked object. I'll be documenting writing a doc about the threading rules for the internal code to explain this more clearlyl....
+++ b/src/test.c @@ -58,6 +58,8 @@ typedef struct _testCell *testCellPtr; #define MAX_CELLS 128
struct _testConn { + PTHREAD_MUTEX_T(lock); +
hum, [...]
+ +static void testDriverLock(testConnPtr driver) +{ + pthread_mutex_lock(&driver->lock); +} + +static void testDriverUnlock(testConnPtr driver) +{ + pthread_mutex_unlock(&driver->lock); +}
static virCapsPtr testBuildCapabilities(virConnectPtr conn) { @@ -200,6 +212,8 @@ static int testOpenDefault(virConnectPtr return VIR_DRV_OPEN_ERROR; } conn->privateData = privconn; + pthread_mutex_init(&privconn->lock, NULL);
Can we abstract the mutex types and ops a little ? if libvirt were to be ported to a platform/compiler where pthreads are not available they would be able to fallback to xmlMutexPtr from libvirt which is ported to all platforms where libxml2 is usable (as far as I know).
The internal.h header already arranges for all this to compile away to nothing if pthread.h is not present, so there's no need for any wrappers. xmlMutexPtr is not sufficient, because other in the code also use condition variables for which there are no wrappers in libxml. That said, all modern UNIX, Linux, OS-X and Windows have pthread libraries available, so I don't think there's any important platform where we'll need to disable this.
+ testDriverLock(privconn);
if (gettimeofday(&tv, NULL) < 0) { testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day")); @@ -232,6 +246,7 @@ static int testOpenDefault(virConnectPtr domobj->def->id = privconn->nextDomID++; domobj->state = VIR_DOMAIN_RUNNING; domobj->persistent = 1; + virDomainObjUnlock(domobj);
the locking path is unclear here testOpenDefault uses virDomainAssignDef which then relies on virDomainFindByName() which would lock the domain object, right ?
Yes, the virXXXXAssignDef method is declared to return a locked object.
[...]
@@ -797,10 +859,14 @@ static int testDestroyDomain (virDomainP if (!privdom->persistent) { virDomainRemoveInactive(&privconn->domains, privdom);
will virDomainRemoveInactive also remove the lock before destroying the object ? the answer is surely in a later patch
You are required to hold both the driver lock, and the privdom lock when calling this. It will unlock the domain object and then free it. It may seemm redudant for the caller to lock the privdom, and then have virDomainRemoveInactive immediately unlock it again, but this ensures no other thread still has an active lock on the object & cannot re-acquire one since we hold the global driver lock.
@@ -884,9 +959,17 @@ static int testShutdownDomain (virDomain privdom->state = VIR_DOMAIN_SHUTOFF; domain->id = -1; privdom->def->id = -1; + if (!privdom->persistent) { + virDomainRemoveInactive(&privconn->domains, + privdom); + privdom = NULL; + } ret = 0;
hum, not specific to threading, we are improving the driver here.
Yes, i noticed that bug while fixing this.
diff --git a/tests/virsh-all b/tests/virsh-all --- a/tests/virsh-all +++ b/tests/virsh-all @@ -22,6 +22,7 @@ fi fi
test -z "$srcdir" && srcdir=$(pwd) +test -z "$abs_top_srcdir" && abs_top_srcdir=$(pwd)/.. . "$srcdir/test-lib.sh"
???
It allows you to rnu the test by just doing ./virsh-all Rather than tedious make check TESTS=virsh-all
I hope it's worth the effort, it's a lot of complexity added. One of the things which worries me is that detecting errors will be hard, you end up with a locked server that can be far from trivial to debug. I'm really wondering how we could automate testing or at least ease the debug,
It occurred to me that a static analysis tool like CIL really ought to be able to check correctness fairly easily. Rich has discussed this a little before http://et.redhat.com/~rjones/cil-analysis-of-libvirt/ Basically since we have a known set of functions which lock the object and CIL can give us the code flow within a method, we ought to be able to write something that looks at each call of virDomainFindByUUID, and then traces the code paths to functiuon return, and validates that the unlock call was made. It could likewise check for people calling things before acquiring the lock. Would be an interesting project..... :-) Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 05:44:14PM +0000, Daniel P. Berrange wrote:
On Mon, Dec 01, 2008 at 06:26:03PM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:27:14PM +0000, Daniel P. Berrange wrote: I hope it's worth the effort, it's a lot of complexity added. One of the things which worries me is that detecting errors will be hard, you end up with a locked server that can be far from trivial to debug. I'm really wondering how we could automate testing or at least ease the debug,
It occurred to me that a static analysis tool like CIL really ought to be able to check correctness fairly easily. Rich has discussed this a little before
http://et.redhat.com/~rjones/cil-analysis-of-libvirt/
Basically since we have a known set of functions which lock the object and CIL can give us the code flow within a method, we ought to be able to write something that looks at each call of virDomainFindByUUID, and then traces the code paths to functiuon return, and validates that the unlock call was made. It could likewise check for people calling things before acquiring the lock.
Would be an interesting project..... :-)
Trying out Rich's demo code I got it to generate before & after control flow diagrams of the 'domain create' functiuon n the QEMU driver http://fedorapeople.org/~berrange/libvirt/qemudDomainCreateBefore.png http://fedorapeople.org/~berrange/libvirt/qemudDomainCreateAfter.png The main problem I had was that CIL doesn't underderstand the 'bool' data type, so I had to hack gnulib/lib/c-ctype.{h,c}, src/cgroup.c and src/xmlrpc.{h,c} to do a s/bool/char/. Be nice to get rid of these directly in our source tree, or find a compile flag to automatically turn 'bool' into 'char' ? Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Daniel Veillard <veillard@redhat.com> wrote: ...
I hope it's worth the effort, it's a lot of complexity added. One of the things which worries me is that detecting errors will be hard, you end up with a locked server that can be far from trivial to debug. I'm really wondering how we could automate testing or at least ease the debug,
Exactly my sentiment. We really do need some sort of automatic code analysis, maybe using CIL, as Dan suggests. Even something really simple would help: I found myself wishing emacs would highlight and graphically-connect matching lock/unlock pairs in the same function, which would make it easier to see any unmatched ones.

When adding the node device APIs we never added a stub for the test driver, so the test driver was connecting to the daemon for node device APIS, which rather defeats the purpose of the test driver. This patch doesn't implement the node device APIs, just stubs out the open/close methods so we don't call into the daemon. test.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) Daniel diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -3220,6 +3220,22 @@ cleanup: } +static virDrvOpenStatus testDevMonOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + if (STRNEQ(conn->driver->name, "Test")) + return VIR_DRV_OPEN_DECLINED; + + conn->devMonPrivateData = conn->privateData; + return VIR_DRV_OPEN_SUCCESS; +} + +static int testDevMonClose(virConnectPtr conn) { + conn->devMonPrivateData = NULL; + return 0; +} + + static virDriver testDriver = { VIR_DRV_TEST, "Test", @@ -3343,6 +3359,14 @@ static virStorageDriver testStorageDrive .volGetPath = testStorageVolumeGetPath, }; +static virDeviceMonitor testDevMonitor = { + .name = "Test", + .open = testDevMonOpen, + .close = testDevMonClose, +}; + + + /** * testRegister: * @@ -3357,5 +3381,8 @@ testRegister(void) return -1; if (virRegisterStorageDriver(&testStorageDriver) < 0) return -1; + if (virRegisterDeviceMonitor(&testDevMonitor) < 0) + return -1; + return 0; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:29:25PM +0000, Daniel P. Berrange wrote:
When adding the node device APIs we never added a stub for the test driver, so the test driver was connecting to the daemon for node device APIS, which rather defeats the purpose of the test driver. This patch doesn't implement the node device APIs, just stubs out the open/close methods so we don't call into the daemon.
heh :-) +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch reduces the number of return points in the QEMU driver methods centralizing all cleanup code. It also removes a bunch of unnecessary type casts, since void * automatically casts to any type. Finally it separates out variable declarations from variable initializations since the initializations will need to be protected with the locked critical section. qemu_driver.c | 1227 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 671 insertions(+), 556 deletions(-) Daniel diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -1075,7 +1075,7 @@ static int qemudDispatchVMFailure(struct static void qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) { - struct qemud_driver *driver = (struct qemud_driver *)opaque; + struct qemud_driver *driver = opaque; virDomainObjPtr vm = NULL; unsigned int i; @@ -1236,7 +1236,7 @@ static virDrvOpenStatus qemudOpen(virCon } static int qemudClose(virConnectPtr conn) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; /* Get rid of callbacks registered for this conn */ virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks); @@ -1308,14 +1308,12 @@ static int qemudGetNodeInfo(virConnectPt static char *qemudGetCapabilities(virConnectPtr conn) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; char *xml; - if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) { + if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for capabilities support")); - return NULL; - } return xml; } @@ -1329,11 +1327,12 @@ qemudNodeGetCellsFreeMemory(virConnectPt int maxCells) { int n, lastCell, numCells; + int ret = -1; if (numa_available() < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s", _("NUMA not supported on this host")); - return -1; + goto cleanup; } lastCell = startCell + maxCells - 1; if (lastCell > numa_max_node()) @@ -1344,22 +1343,26 @@ qemudNodeGetCellsFreeMemory(virConnectPt if (numa_node_size64(n, &mem) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to query NUMA free memory")); - return -1; + goto cleanup; } freeMems[numCells++] = mem; } - return numCells; + ret = numCells; + +cleanup: + return ret; } static unsigned long long qemudNodeGetFreeMemory (virConnectPtr conn) { - unsigned long long freeMem = 0; + unsigned long long freeMem = -1; int n; + if (numa_available() < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s", _("NUMA not supported on this host")); - return -1; + goto cleanup; } for (n = 0 ; n <= numa_max_node() ; n++) { @@ -1367,11 +1370,12 @@ qemudNodeGetFreeMemory (virConnectPtr co if (numa_node_size64(n, &mem) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to query NUMA free memory")); - return -1; + goto cleanup; } freeMem += mem; } +cleanup: return freeMem; } @@ -1415,57 +1419,72 @@ static int qemudGetProcessInfo(unsigned static virDomainPtr qemudDomainLookupByID(virConnectPtr conn, int id) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, id); - virDomainPtr dom; + struct qemud_driver *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + + vm = virDomainFindByID(&driver->domains, id); if (!vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid); - virDomainPtr dom; + struct qemud_driver *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByUUID(&driver->domains, uuid); if (!vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, const char *name) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByName(&driver->domains, name); - virDomainPtr dom; + struct qemud_driver *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByName(&driver->domains, name); if (!vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } static int qemudGetVersion(virConnectPtr conn, unsigned long *version) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; + int ret = -1; + if (qemudExtractVersion(conn, driver) < 0) - return -1; + goto cleanup; *version = qemu_driver->qemuVersion; - return 0; + ret = 0; + +cleanup: + return ret; } static char * @@ -1491,7 +1510,7 @@ qemudGetHostname (virConnectPtr conn) } static int qemudListDomains(virConnectPtr conn, int *ids, int nids) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; int got = 0, i; for (i = 0 ; i < driver->domains.count && got < nids ; i++) @@ -1501,7 +1520,7 @@ static int qemudListDomains(virConnectPt return got; } static int qemudNumDomains(virConnectPtr conn) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; int n = 0, i; for (i = 0 ; i < driver->domains.count ; i++) @@ -1512,21 +1531,20 @@ static int qemudNumDomains(virConnectPtr } static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { + struct qemud_driver *driver = conn->privateData; virDomainDefPtr def; virDomainObjPtr vm; - virDomainPtr dom; - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + virDomainPtr dom = NULL; if (!(def = virDomainDefParseString(conn, driver->caps, xml))) - return NULL; + goto cleanup; vm = virDomainFindByName(&driver->domains, def->name); if (vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain '%s' is already defined"), def->name); - virDomainDefFree(def); - return NULL; + goto cleanup; } vm = virDomainFindByUUID(&driver->domains, def->uuid); if (vm) { @@ -1536,21 +1554,20 @@ static virDomainPtr qemudDomainCreate(vi qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain with uuid '%s' is already defined"), uuidstr); - virDomainDefFree(def); - return NULL; + goto cleanup; } if (!(vm = virDomainAssignDef(conn, &driver->domains, - def))) { - virDomainDefFree(def); - return NULL; - } + def))) + goto cleanup; + + def = NULL; if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) { virDomainRemoveInactive(&driver->domains, vm); - return NULL; + goto cleanup; } qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED, @@ -1558,102 +1575,124 @@ static virDomainPtr qemudDomainCreate(vi dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: + virDomainDefFree(def); + return dom; } static int qemudDomainSuspend(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; + struct qemud_driver *driver = dom->conn->privateData; char *info; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + virDomainObjPtr vm; + int ret = -1; + + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } - if (vm->state == VIR_DOMAIN_PAUSED) - return 0; + if (vm->state != VIR_DOMAIN_PAUSED) { + if (qemudMonitorCommand(driver, vm, "stop", &info) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("suspend operation failed")); + goto cleanup; + } + vm->state = VIR_DOMAIN_PAUSED; + qemudDebug("Reply %s", info); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_SUSPENDED, + VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); + VIR_FREE(info); + } + ret = 0; - if (qemudMonitorCommand(driver, vm, "stop", &info) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - "%s", _("suspend operation failed")); - return -1; - } - vm->state = VIR_DOMAIN_PAUSED; - qemudDebug("Reply %s", info); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_SUSPENDED, - VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); - VIR_FREE(info); - return 0; +cleanup: + return ret; } static int qemudDomainResume(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; + struct qemud_driver *driver = dom->conn->privateData; char *info; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + virDomainObjPtr vm; + int ret = -1; + + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } - if (vm->state == VIR_DOMAIN_RUNNING) - return 0; - if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, - "%s", _("resume operation failed")); - return -1; + if (vm->state == VIR_DOMAIN_PAUSED) { + if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("resume operation failed")); + goto cleanup; + } + vm->state = VIR_DOMAIN_RUNNING; + qemudDebug("Reply %s", info); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); + VIR_FREE(info); } - vm->state = VIR_DOMAIN_RUNNING; - qemudDebug("Reply %s", info); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_RESUMED, - VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); - VIR_FREE(info); - return 0; + ret = 0; + +cleanup: + return ret; } static int qemudDomainShutdown(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; char* info; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (qemudMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("shutdown operation failed")); - return -1; + goto cleanup; } VIR_FREE(info); - return 0; + ret = 0; + +cleanup: + return ret; } static int qemudDomainDestroy(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } qemudShutdownVMDaemon(dom->conn, driver, vm); @@ -1663,106 +1702,128 @@ static int qemudDomainDestroy(virDomainP if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); - return 0; + ret = 0; + +cleanup: + return ret; } static char *qemudDomainGetOSType(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - char *type; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *type = NULL; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - if (!(type = strdup(vm->def->os.type))) { + if (!(type = strdup(vm->def->os.type))) qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for ostype")); - return NULL; - } + +cleanup: return type; } /* Returns max memory in kb, 0 if error */ static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + unsigned long ret = 0; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return 0; + goto cleanup; } - return vm->def->maxmem; + ret = vm->def->maxmem; + +cleanup: + return ret; } static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return -1; + goto cleanup; } if (newmax < vm->def->memory) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s", _("cannot set max memory lower than current memory")); - return -1; + goto cleanup;; } vm->def->maxmem = newmax; - return 0; + ret = 0; + +cleanup: + return ret; } static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return -1; + goto cleanup; } if (virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("cannot set memory of an active domain")); - return -1; + goto cleanup; } if (newmem > vm->def->maxmem) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s", _("cannot set memory higher than max memory")); - return -1; + goto cleanup; } vm->def->memory = newmem; - return 0; + ret = 0; + +cleanup: + return ret; } static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } info->state = vm->state; @@ -1772,14 +1833,17 @@ static int qemudDomainGetInfo(virDomainP } else { if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain")); - return -1; + goto cleanup; } } info->maxMem = vm->def->maxmem; info->memory = vm->def->memory; info->nrVirtCpu = vm->def->vcpus; - return 0; + ret = 0; + +cleanup: + return ret; } @@ -1878,28 +1942,32 @@ struct qemud_save_header { static int qemudDomainSave(virDomainPtr dom, const char *path) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); - char *command, *info; - int fd; - char *safe_path; - char *xml; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *command = NULL; + char *info = NULL; + int fd = -1; + char *safe_path = NULL; + char *xml = NULL; struct qemud_save_header header; + int ret = -1; memset(&header, 0, sizeof(header)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); header.version = QEMUD_SAVE_VERSION; + vm = virDomainFindByID(&driver->domains, dom->id); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } /* Pause */ @@ -1908,7 +1976,7 @@ static int qemudDomainSave(virDomainPtr if (qemudDomainSuspend(dom) != 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to pause domain")); - return -1; + goto cleanup; } } @@ -1917,7 +1985,7 @@ static int qemudDomainSave(virDomainPtr if (!xml) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to get domain xml")); - return -1; + goto cleanup; } header.xml_len = strlen(xml) + 1; @@ -1925,51 +1993,49 @@ static int qemudDomainSave(virDomainPtr if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("failed to create '%s'"), path); - VIR_FREE(xml); - return -1; + goto cleanup; } if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to write save header")); - close(fd); - VIR_FREE(xml); return -1; } if (safewrite(fd, xml, header.xml_len) != header.xml_len) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to write xml")); - close(fd); - VIR_FREE(xml); - return -1; + goto cleanup; } - close(fd); - VIR_FREE(xml); + if (close(fd) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + _("unable to save file %s %s"), + path, strerror(errno)); + goto cleanup; + } + fd = -1; /* Migrate to file */ safe_path = qemudEscapeShellArg(path); if (!safe_path) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); - return -1; + goto cleanup; } if (asprintf (&command, "migrate \"exec:" "dd of='%s' oflag=append conv=notrunc 2>/dev/null" "\"", safe_path) == -1) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); - VIR_FREE(safe_path); - return -1; + command = NULL; + goto cleanup; } - free(safe_path); if (qemudMonitorCommand(driver, vm, command, &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("migrate operation failed")); - VIR_FREE(command); - return -1; + goto cleanup; } DEBUG ("migrate reply: %s", info); @@ -1980,13 +2046,8 @@ static int qemudDomainSave(virDomainPtr qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("'migrate' not supported by this qemu")); - VIR_FREE(info); - VIR_FREE(command); - return -1; + goto cleanup; } - - VIR_FREE(info); - VIR_FREE(command); /* Shut it down */ qemudShutdownVMDaemon(dom->conn, driver, vm); @@ -1996,45 +2057,62 @@ static int qemudDomainSave(virDomainPtr if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); - return 0; + ret = 0; + +cleanup: + if (fd != -1) + close(fd); + VIR_FREE(xml); + VIR_FREE(safe_path); + VIR_FREE(command); + VIR_FREE(info); + if (ret != 0) + unlink(path); + + return ret; } static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; int max; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return -1; + goto cleanup; } if (virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("cannot change vcpu count of an active domain")); - return -1; + goto cleanup; } if ((max = qemudDomainGetMaxVcpus(dom)) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("could not determine max vcpus for the domain")); - return -1; + goto cleanup; } if (nvcpus > max) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("requested vcpus is greater than max allowable" " vcpus for the domain: %d > %d"), nvcpus, max); - return -1; + goto cleanup; } vm->def->vcpus = nvcpus; - return 0; + ret = 0; + +cleanup: + return ret; } @@ -2044,27 +2122,29 @@ qemudDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, int maplen) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; cpu_set_t mask; int i, maxcpu; virNodeInfo nodeinfo; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s",_("cannot pin vcpus on an inactive domain")); - return -1; + goto cleanup; } if (vcpu > (vm->nvcpupids-1)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("vcpu number out of range %d > %d"), vcpu, vm->nvcpupids); - return -1; + goto cleanup; } if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0) - return -1; + goto cleanup; maxcpu = maplen * 8; if (maxcpu > nodeinfo.cpus) @@ -2080,15 +2160,17 @@ qemudDomainPinVcpu(virDomainPtr dom, if (sched_setaffinity(vm->vcpupids[vcpu], sizeof(mask), &mask) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("cannot set affinity: %s"), strerror(errno)); - return -1; + goto cleanup; } } else { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("cpu affinity is not supported")); - return -1; + goto cleanup; } + ret = 0; - return 0; +cleanup: + return ret; } static int @@ -2097,19 +2179,21 @@ qemudDomainGetVcpus(virDomainPtr dom, int maxinfo, unsigned char *cpumaps, int maplen) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; virNodeInfo nodeinfo; int i, v, maxcpu; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s",_("cannot pin vcpus on an inactive domain")); - return -1; + goto cleanup; } if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0) - return -1; + goto cleanup; maxcpu = maplen * 8; if (maxcpu > nodeinfo.cpus) @@ -2119,141 +2203,133 @@ qemudDomainGetVcpus(virDomainPtr dom, if (maxinfo > vm->nvcpupids) maxinfo = vm->nvcpupids; - if (maxinfo < 1) - return 0; + if (maxinfo >= 1) { + if (info != NULL) { + memset(info, 0, sizeof(*info) * maxinfo); + for (i = 0 ; i < maxinfo ; i++) { + info[i].number = i; + info[i].state = VIR_VCPU_RUNNING; + /* XXX cpu time, current pCPU mapping */ + } + } - if (info != NULL) { - memset(info, 0, sizeof(*info) * maxinfo); - for (i = 0 ; i < maxinfo ; i++) { - info[i].number = i; - info[i].state = VIR_VCPU_RUNNING; - /* XXX cpu time, current pCPU mapping */ + if (cpumaps != NULL) { + memset(cpumaps, 0, maplen * maxinfo); + if (vm->vcpupids != NULL) { + for (v = 0 ; v < maxinfo ; v++) { + cpu_set_t mask; + unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v); + CPU_ZERO(&mask); + + if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, + _("cannot get affinity: %s"), strerror(errno)); + goto cleanup; + } + + for (i = 0 ; i < maxcpu ; i++) + if (CPU_ISSET(i, &mask)) + VIR_USE_CPU(cpumap, i); + } + } else { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, + "%s", _("cpu affinity is not available")); + goto cleanup; + } } } + ret = maxinfo; - if (cpumaps != NULL) { - memset(cpumaps, 0, maplen * maxinfo); - if (vm->vcpupids != NULL) { - for (v = 0 ; v < maxinfo ; v++) { - cpu_set_t mask; - unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v); - CPU_ZERO(&mask); - - if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, - _("cannot get affinity: %s"), strerror(errno)); - return -1; - } - - for (i = 0 ; i < maxcpu ; i++) - if (CPU_ISSET(i, &mask)) - VIR_USE_CPU(cpumap, i); - } - } else { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, - "%s", _("cpu affinity is not available")); - return -1; - } - } - - return maxinfo; +cleanup: + return ret; } #endif /* HAVE_SCHED_GETAFFINITY */ static int qemudDomainGetMaxVcpus(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; const char *type; - int ret; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return -1; + goto cleanup; } if (!(type = virDomainVirtTypeToString(vm->def->virtType))) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, _("unknown virt type in domain definition '%d'"), vm->def->virtType); - return -1; + goto cleanup; } - if ((ret = qemudGetMaxVCPUs(dom->conn, type)) < 0) { - return -1; - } + ret = qemudGetMaxVCPUs(dom->conn, type); +cleanup: return ret; } static int qemudDomainRestore(virConnectPtr conn, - const char *path) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; - virDomainDefPtr def; + const char *path) { + struct qemud_driver *driver = conn->privateData; + virDomainDefPtr def = NULL; virDomainObjPtr vm; - int fd; - int ret; - char *xml; + int fd = -1; + int ret = -1; + char *xml = NULL; struct qemud_save_header header; /* Verify the header and read the XML */ if ((fd = open(path, O_RDONLY)) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot read domain image")); - return -1; + goto cleanup; } if (saferead(fd, &header, sizeof(header)) != sizeof(header)) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to read qemu header")); - close(fd); - return -1; + goto cleanup; } if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("image magic is incorrect")); - close(fd); - return -1; + goto cleanup; } if (header.version > QEMUD_SAVE_VERSION) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("image version is not supported (%d > %d)"), header.version, QEMUD_SAVE_VERSION); - close(fd); - return -1; + goto cleanup; } if (VIR_ALLOC_N(xml, header.xml_len) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); - close(fd); - return -1; + goto cleanup; } if (saferead(fd, xml, header.xml_len) != header.xml_len) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML")); - close(fd); - VIR_FREE(xml); - return -1; + goto cleanup; } /* Create a domain from this XML */ if (!(def = virDomainDefParseString(conn, driver->caps, xml))) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to parse XML")); - close(fd); - VIR_FREE(xml); - return -1; + goto cleanup; } - VIR_FREE(xml); /* Ensure the name and UUID don't already exist in an active VM */ vm = virDomainFindByUUID(&driver->domains, def->uuid); @@ -2262,8 +2338,7 @@ static int qemudDomainRestore(virConnect if (vm && virDomainIsActive(vm)) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain is already active as '%s'"), vm->def->name); - close(fd); - return -1; + goto cleanup; } if (!(vm = virDomainAssignDef(conn, @@ -2271,15 +2346,15 @@ static int qemudDomainRestore(virConnect def))) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to assign new VM")); - virDomainDefFree(def); - close(fd); - return -1; + goto cleanup; } + def = NULL; /* Set the migration source and start it up. */ vm->stdin_fd = fd; ret = qemudStartVMDaemon(conn, driver, vm, "stdio"); close(fd); + fd = -1; vm->stdin_fd = -1; if (ret < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, @@ -2287,7 +2362,7 @@ static int qemudDomainRestore(virConnect if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); - return -1; + goto cleanup; } qemudDomainEventDispatch(driver, vm, @@ -2300,36 +2375,49 @@ static int qemudDomainRestore(virConnect if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to resume domain")); - return -1; + goto cleanup; } VIR_FREE(info); vm->state = VIR_DOMAIN_RUNNING; } + ret = 0; - return 0; +cleanup: + virDomainDefFree(def); + VIR_FREE(xml); + if (fd != -1) + close(fd); + + return ret; } static char *qemudDomainDumpXML(virDomainPtr dom, int flags ATTRIBUTE_UNUSED) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *ret = NULL; + + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - return virDomainDefFormat(dom->conn, - (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? - vm->newDef : vm->def, - flags); + ret = virDomainDefFormat(dom->conn, + (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? + vm->newDef : vm->def, + flags); + +cleanup: + return ret; } static int qemudListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; int got = 0, i; for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { @@ -2351,7 +2439,7 @@ static int qemudListDefinedDomains(virCo } static int qemudNumDefinedDomains(virConnectPtr conn) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; int n = 0, i; for (i = 0 ; i < driver->domains.count ; i++) @@ -2363,35 +2451,37 @@ static int qemudNumDefinedDomains(virCon static int qemudDomainStart(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - int ret; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL); - if (ret < 0) - return ret; - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); - return 0; + if (ret != -1) + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + +cleanup: + return ret; } static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; virDomainDefPtr def; virDomainObjPtr vm; - virDomainPtr dom; + virDomainPtr dom = NULL; int newVM = 1; if (!(def = virDomainDefParseString(conn, driver->caps, xml))) - return NULL; + goto cleanup; vm = virDomainFindByName(&driver->domains, def->name); if (vm) @@ -2401,7 +2491,7 @@ static virDomainPtr qemudDomainDefine(vi &driver->domains, def))) { virDomainDefFree(def); - return NULL; + goto cleanup; } vm->persistent = 1; @@ -2410,7 +2500,7 @@ static virDomainPtr qemudDomainDefine(vi vm->newDef ? vm->newDef : vm->def) < 0) { virDomainRemoveInactive(&driver->domains, vm); - return NULL; + goto cleanup; } qemudDomainEventDispatch(driver, vm, @@ -2421,33 +2511,37 @@ static virDomainPtr qemudDomainDefine(vi dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } static int qemudDomainUndefine(virDomainPtr dom) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain")); - return -1; + goto cleanup; } if (!vm->persistent) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot undefine transient domain")); - return -1; + goto cleanup; } if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0) - return -1; + goto cleanup; qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_UNDEFINED, @@ -2455,12 +2549,14 @@ static int qemudDomainUndefine(virDomain virDomainRemoveInactive(&driver->domains, vm); + ret = 0; - return 0; +cleanup: + return ret; } /* Return the disks name for use in monitor commands */ -static char *qemudDiskDeviceName(const virDomainPtr dom, +static char *qemudDiskDeviceName(const virConnectPtr conn, const virDomainDiskDefPtr disk) { int busid, devid; @@ -2468,7 +2564,7 @@ static char *qemudDiskDeviceName(const v char *devname; if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("cannot convert disk '%s' to bus/device index"), disk->dst); return NULL; @@ -2494,36 +2590,30 @@ static char *qemudDiskDeviceName(const v ret = asprintf(&devname, "virtio%d", devid); break; default: - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, _("Unsupported disk name mapping for bus '%s'"), virDomainDiskBusTypeToString(disk->bus)); return NULL; } if (ret == -1) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return NULL; } return devname; } -static int qemudDomainChangeEjectableMedia(virDomainPtr dom, +static int qemudDomainChangeEjectableMedia(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainDiskDefPtr origdisk = NULL, newdisk; char *cmd, *reply, *safe_path; char *devname = NULL; unsigned int qemuCmdFlags; int i; - - if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - return -1; - } origdisk = NULL; newdisk = dev->data.disk; @@ -2536,7 +2626,7 @@ static int qemudDomainChangeEjectableMed } if (!origdisk) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, _("No device with bus '%s' and target '%s'"), virDomainDiskBusTypeToString(newdisk->bus), newdisk->dst); @@ -2546,14 +2636,14 @@ static int qemudDomainChangeEjectableMed if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qemuCmdFlags) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, _("Cannot determine QEMU argv syntax %s"), vm->def->emulator); return -1; } if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) { - if (!(devname = qemudDiskDeviceName(dom, newdisk))) + if (!(devname = qemudDiskDeviceName(conn, newdisk))) return -1; } else { /* Back compat for no -drive option */ @@ -2563,7 +2653,7 @@ static int qemudDomainChangeEjectableMed STREQ(newdisk->dst, "hdc")) devname = strdup("cdrom"); else { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, _("Emulator version does not support removable " "media for device '%s' and target '%s'"), virDomainDiskDeviceTypeToString(newdisk->device), @@ -2572,7 +2662,7 @@ static int qemudDomainChangeEjectableMed } if (!devname) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return -1; } } @@ -2580,12 +2670,12 @@ static int qemudDomainChangeEjectableMed if (newdisk->src) { safe_path = qemudEscapeMonitorArg(newdisk->src); if (!safe_path) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); VIR_FREE(devname); return -1; } if (asprintf (&cmd, "change %s \"%s\"", devname, safe_path) == -1) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); VIR_FREE(safe_path); VIR_FREE(devname); return -1; @@ -2593,14 +2683,14 @@ static int qemudDomainChangeEjectableMed VIR_FREE(safe_path); } else if (asprintf(&cmd, "eject %s", devname) == -1) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); VIR_FREE(devname); return -1; } VIR_FREE(devname); if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot change cdrom media")); VIR_FREE(cmd); return -1; @@ -2611,7 +2701,7 @@ static int qemudDomainChangeEjectableMed * No message is printed on success it seems */ DEBUG ("ejectable media change reply: %s", reply); if (strstr(reply, "\ndevice ")) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("changing cdrom media failed")); VIR_FREE(reply); VIR_FREE(cmd); @@ -2627,37 +2717,32 @@ static int qemudDomainChangeEjectableMed return 0; } -static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) +static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); int ret, i; char *cmd, *reply, *s; char *safe_path; const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus); - if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - return -1; - } - for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("target %s already exists"), dev->data.disk->dst); return -1; } } if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return -1; } safe_path = qemudEscapeMonitorArg(dev->data.disk->src); if (!safe_path) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); return -1; } @@ -2666,12 +2751,12 @@ static int qemudDomainAttachPciDiskDevic safe_path, type); VIR_FREE(safe_path); if (ret == -1) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return ret; } if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("cannot attach %s disk"), type); VIR_FREE(cmd); return -1; @@ -2688,7 +2773,7 @@ static int qemudDomainAttachPciDiskDevic if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1) qemudLog(QEMUD_WARN, "%s", _("Unable to parse slot number\n")); } else { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("adding %s disk failed"), type); VIR_FREE(reply); VIR_FREE(cmd); @@ -2704,36 +2789,31 @@ static int qemudDomainAttachPciDiskDevic return 0; } -static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) +static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); int ret, i; char *safe_path; char *cmd, *reply; - if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - return -1; - } - for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("target %s already exists"), dev->data.disk->dst); return -1; } } if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return -1; } safe_path = qemudEscapeMonitorArg(dev->data.disk->src); if (!safe_path) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("out of memory")); return -1; } @@ -2741,12 +2821,12 @@ static int qemudDomainAttachUsbMassstora ret = asprintf(&cmd, "usb_add disk:%s", safe_path); VIR_FREE(safe_path); if (ret == -1) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return ret; } if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot attach usb disk")); VIR_FREE(cmd); return -1; @@ -2756,7 +2836,7 @@ static int qemudDomainAttachUsbMassstora /* If the command failed qemu prints: * Could not add ... */ if (strstr(reply, "Could not add ")) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("adding usb disk failed")); VIR_FREE(reply); @@ -2773,20 +2853,16 @@ static int qemudDomainAttachUsbMassstora return 0; } -static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) +static int qemudDomainAttachHostDevice(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); int ret; char *cmd, *reply; - if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - return -1; - } if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return -1; } @@ -2800,12 +2876,12 @@ static int qemudDomainAttachHostDevice(v dev->data.hostdev->source.subsys.usb.device); } if (ret == -1) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); return -1; } if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot attach usb device")); VIR_FREE(cmd); return -1; @@ -2815,7 +2891,7 @@ static int qemudDomainAttachHostDevice(v /* If the command failed qemu prints: * Could not add ... */ if (strstr(reply, "Could not add ")) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("adding usb device failed")); VIR_FREE(reply); @@ -2832,78 +2908,73 @@ static int qemudDomainAttachHostDevice(v static int qemudDomainAttachDevice(virDomainPtr dom, const char *xml) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - virDomainDeviceDefPtr dev; - int ret = 0, supported = 0; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + virDomainDeviceDefPtr dev = NULL; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot attach device on inactive domain")); - return -1; + goto cleanup; } dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml); - if (dev == NULL) { - return -1; - } + if (dev == NULL) + goto cleanup; + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { switch (dev->data.disk->device) { - case VIR_DOMAIN_DISK_DEVICE_CDROM: - case VIR_DOMAIN_DISK_DEVICE_FLOPPY: - supported = 1; - ret = qemudDomainChangeEjectableMedia(dom, dev); - break; - case VIR_DOMAIN_DISK_DEVICE_DISK: - if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { - supported = 1; - ret = qemudDomainAttachUsbMassstorageDevice(dom, dev); - } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || - dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - supported = 1; - ret = qemudDomainAttachPciDiskDevice(dom, dev); - } - break; + case VIR_DOMAIN_DISK_DEVICE_CDROM: + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + ret = qemudDomainChangeEjectableMedia(dom->conn, driver, vm, dev); + break; + case VIR_DOMAIN_DISK_DEVICE_DISK: + if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { + ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, driver, vm, dev); + } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || + dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { + ret = qemudDomainAttachPciDiskDevice(dom->conn, driver, vm, dev); + } + break; + default: + qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, + "%s", _("this disk device type cannot be attached")); + goto cleanup; } } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && - dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && - dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - supported = 1; - ret = qemudDomainAttachHostDevice(dom, dev); + dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { + ret = qemudDomainAttachHostDevice(dom->conn, driver, vm, dev); + } else { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, + "%s", _("this device type cannot be attached")); + goto cleanup; } - if (!supported) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, - "%s", _("this device type cannot be attached")); - ret = -1; - } - - VIR_FREE(dev); +cleanup: + virDomainDeviceDefFree(dev); return ret; } -static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) +static int qemudDomainDetachPciDiskDevice(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); int i, ret = -1; - char *cmd, *reply; + char *cmd = NULL; + char *reply = NULL; virDomainDiskDefPtr detach = NULL; - - if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - return -1; - } for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { @@ -2913,48 +2984,45 @@ static int qemudDomainDetachPciDiskDevic } if (!detach) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("disk %s not found"), dev->data.disk->dst); - return -1; + goto cleanup; } if (detach->slotnum < 1) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("disk %s cannot be detached - invalid slot number %d"), detach->dst, detach->slotnum); - return -1; + goto cleanup; } - ret = asprintf(&cmd, "pci_del 0 %d", detach->slotnum); - if (ret == -1) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); - return ret; + if (asprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) { + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + cmd = NULL; + goto cleanup; } if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("failed to execute detach disk %s command"), detach->dst); - VIR_FREE(cmd); - return -1; + goto cleanup; } DEBUG ("pci_del reply: %s", reply); /* If the command fails due to a wrong slot qemu prints: invalid slot, * nothing is printed on success */ if (strstr(reply, "invalid slot")) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("failed to detach disk %s: invalid slot %d"), - detach->dst, detach->slotnum); - ret = -1; - goto out; + detach->dst, detach->slotnum); + goto cleanup; } if (vm->def->ndisks > 1) { vm->def->disks[i] = vm->def->disks[--vm->def->ndisks]; if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) { - qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); - ret = -1; - goto out; + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + goto cleanup; } qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks), virDomainDiskQSort); @@ -2963,7 +3031,8 @@ static int qemudDomainDetachPciDiskDevic vm->def->ndisks = 0; } ret = 0; -out: + +cleanup: VIR_FREE(reply); VIR_FREE(cmd); return ret; @@ -2971,114 +3040,118 @@ out: static int qemudDomainDetachDevice(virDomainPtr dom, const char *xml) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - virDomainDeviceDefPtr dev; - int ret = 0; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + virDomainDeviceDefPtr dev = NULL; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot attach device on inactive domain")); - return -1; + goto cleanup; } dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml); - if (dev == NULL) { - return -1; - } + if (dev == NULL) + goto cleanup; + if (dev->type == VIR_DOMAIN_DEVICE_DISK && dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK && (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)) - ret = qemudDomainDetachPciDiskDevice(dom, dev); - else { + ret = qemudDomainDetachPciDiskDevice(dom->conn, driver, vm, dev); + else qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("only SCSI or virtio disk device can be detached dynamically")); - ret = -1; - } - VIR_FREE(dev); +cleanup: + virDomainDeviceDefFree(dev); return ret; } static int qemudDomainGetAutostart(virDomainPtr dom, int *autostart) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } *autostart = vm->autostart; + ret = 0; - return 0; +cleanup: + return ret; } static int qemudDomainSetAutostart(virDomainPtr dom, int autostart) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; char *configFile = NULL, *autostartLink = NULL; int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (!vm->persistent) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot set autostart for transient domain")); - return -1; + goto cleanup; } autostart = (autostart != 0); - if (vm->autostart == autostart) - return 0; + if (vm->autostart != autostart) { + if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL) + goto cleanup; + if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL) + goto cleanup; - if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL) - goto cleanup; - if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL) - goto cleanup; + if (autostart) { + int err; - if (autostart) { - int err; + if ((err = virFileMakePath(driver->autostartDir))) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + driver->autostartDir, strerror(err)); + goto cleanup; + } - if ((err = virFileMakePath(driver->autostartDir))) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create autostart directory %s: %s"), - driver->autostartDir, strerror(err)); - goto cleanup; + if (symlink(configFile, autostartLink) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("Failed to create symlink '%s to '%s': %s"), + autostartLink, configFile, strerror(errno)); + goto cleanup; + } + } else { + if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("Failed to delete symlink '%s': %s"), + autostartLink, strerror(errno)); + goto cleanup; + } } - if (symlink(configFile, autostartLink) < 0) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _("Failed to create symlink '%s to '%s': %s"), - autostartLink, configFile, strerror(errno)); - goto cleanup; - } - } else { - if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _("Failed to delete symlink '%s': %s"), - autostartLink, strerror(errno)); - goto cleanup; - } + vm->autostart = autostart; } - - vm->autostart = autostart; ret = 0; cleanup: @@ -3097,25 +3170,25 @@ qemudDomainBlockStats (virDomainPtr dom, const char *path, struct _virDomainBlockStats *stats) { - struct qemud_driver *driver = - (struct qemud_driver *)dom->conn->privateData; + struct qemud_driver *driver = dom->conn->privateData; char *dummy, *info = NULL; const char *p, *eol; const char *qemu_dev_name = NULL; size_t len; int i, ret = -1; - const virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + virDomainObjPtr vm; virDomainDiskDefPtr disk = NULL; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive (vm)) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } for (i = 0 ; i < vm->def->ndisks ; i++) { @@ -3128,18 +3201,18 @@ qemudDomainBlockStats (virDomainPtr dom, if (!disk) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("invalid path: %s"), path); - return -1; + goto cleanup; } - qemu_dev_name = qemudDiskDeviceName(dom, disk); + qemu_dev_name = qemudDiskDeviceName(dom->conn, disk); if (!qemu_dev_name) - return -1; + goto cleanup; len = strlen (qemu_dev_name); if (qemudMonitorCommand (driver, vm, "info blockstats", &info) < 0) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("'info blockstats' command failed")); - goto out; + goto cleanup; } DEBUG ("info blockstats reply: %s", info); @@ -3152,7 +3225,7 @@ qemudDomainBlockStats (virDomainPtr dom, qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("'info blockstats' not supported by this qemu")); - goto out; + goto cleanup; } stats->rd_req = -1; @@ -3204,7 +3277,7 @@ qemudDomainBlockStats (virDomainPtr dom, p++; } ret = 0; - goto out; + goto cleanup; } /* Skip to next line. */ @@ -3216,59 +3289,70 @@ qemudDomainBlockStats (virDomainPtr dom, /* If we reach here then the device was not found. */ qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("device not found: %s (%s)"), path, qemu_dev_name); - out: + cleanup: VIR_FREE(qemu_dev_name); VIR_FREE(info); return ret; } +#ifdef __linux__ static int qemudDomainInterfaceStats (virDomainPtr dom, const char *path, struct _virDomainInterfaceStats *stats) { -#ifdef __linux__ - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; int i; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } if (!path || path[0] == '\0') { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path")); - return -1; + goto cleanup; } /* Check the path is one of the domain's network interfaces. */ for (i = 0 ; i < vm->def->nnets ; i++) { if (vm->def->nets[i]->ifname && - STREQ (vm->def->nets[i]->ifname, path)) - goto ok; + STREQ (vm->def->nets[i]->ifname, path)) { + ret = 0; + break; + } } - qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, - _("invalid path, '%s' is not a known interface"), path); - return -1; - ok: + if (ret == 0) + ret = linuxDomainInterfaceStats (dom->conn, path, stats); + else + qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, + _("invalid path, '%s' is not a known interface"), path); - return linuxDomainInterfaceStats (dom->conn, path, stats); +cleanup: + return ret; +} #else +static int +qemudDomainInterfaceStats (virDomainPtr dom, + const char *path ATTRIBUTE_UNUSED, + struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED) qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", __FUNCTION__); return -1; +} #endif -} static int qemudDomainBlockPeek (virDomainPtr dom, @@ -3277,55 +3361,62 @@ qemudDomainBlockPeek (virDomainPtr dom, void *buffer, unsigned int flags ATTRIBUTE_UNUSED) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - int fd, ret = -1, i; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int fd = -1, ret = -1, i; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (!path || path[0] == '\0') { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path")); - return -1; + goto cleanup; } /* Check the path belongs to this domain. */ for (i = 0 ; i < vm->def->ndisks ; i++) { if (vm->def->disks[i]->src != NULL && - STREQ (vm->def->disks[i]->src, path)) - goto found; - } - qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, - "%s", _("invalid path")); - return -1; - -found: - /* The path is correct, now try to open it and get its size. */ - fd = open (path, O_RDONLY); - if (fd == -1) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, - "%s", strerror (errno)); - goto done; + STREQ (vm->def->disks[i]->src, path)) { + ret = 0; + break; + } } - /* Seek and read. */ - /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should - * be 64 bits on all platforms. - */ - if (lseek (fd, offset, SEEK_SET) == (off_t) -1 || - saferead (fd, buffer, size) == (ssize_t) -1) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, - "%s", strerror (errno)); - goto done; + if (ret == 0) { + ret = -1; + /* The path is correct, now try to open it and get its size. */ + fd = open (path, O_RDONLY); + if (fd == -1) { + qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, + "%s", strerror (errno)); + goto cleanup; + } + + /* Seek and read. */ + /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should + * be 64 bits on all platforms. + */ + if (lseek (fd, offset, SEEK_SET) == (off_t) -1 || + saferead (fd, buffer, size) == (ssize_t) -1) { + qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, + "%s", strerror (errno)); + goto cleanup; + } + + ret = 0; + } else { + qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, + "%s", _("invalid path")); } - ret = 0; - done: - if (fd >= 0) close (fd); +cleanup: + if (fd >= 0) + close (fd); return ret; } @@ -3335,35 +3426,37 @@ qemudDomainMemoryPeek (virDomainPtr dom, void *buffer, unsigned int flags) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); - char cmd[256], *info; + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char cmd[256], *info = NULL; char tmp[] = TEMPDIR "/qemu.mem.XXXXXX"; int fd = -1, ret = -1; + + vm = virDomainFindByID(&driver->domains, dom->id); + + if (!vm) { + qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + _("no domain with matching id %d"), dom->id); + goto cleanup; + } if (flags != VIR_MEMORY_VIRTUAL) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s", _("QEMU driver only supports virtual memory addrs")); - return -1; - } - - if (!vm) { - qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } /* Create a temporary filename. */ if ((fd = mkstemp (tmp)) == -1) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, "%s", strerror (errno)); - return -1; + goto cleanup; } /* Issue the memsave command. */ @@ -3371,21 +3464,22 @@ qemudDomainMemoryPeek (virDomainPtr dom, if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("'memsave' command failed")); - goto done; + goto cleanup; } DEBUG ("memsave reply: %s", info); - free (info); /* Read the memory file into buffer. */ if (saferead (fd, buffer, size) == (ssize_t) -1) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, "%s", strerror (errno)); - goto done; + goto cleanup; } ret = 0; -done: + +cleanup: + VIR_FREE(info); if (fd >= 0) close (fd); unlink (tmp); return ret; @@ -3398,20 +3492,26 @@ qemudDomainEventRegister (virConnectPtr void *opaque, virFreeCallback freecb) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; + int ret; - return virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, - callback, opaque, freecb); + ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, + callback, opaque, freecb); + + return ret; } static int qemudDomainEventDeregister (virConnectPtr conn, void *callback) { - struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; + struct qemud_driver *driver = conn->privateData; + int ret; - return virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, - callback); + ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, + callback); + + return ret; } static void qemudDomainEventDispatch (struct qemud_driver *driver, @@ -3462,18 +3562,21 @@ qemudDomainMigratePrepare2 (virConnectPt const char *dom_xml) { static int port = 0; - struct qemud_driver *driver = (struct qemud_driver *)dconn->privateData; - virDomainDefPtr def; + struct qemud_driver *driver = dconn->privateData; + virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; int this_port; char hostname [HOST_NAME_MAX+1]; char migrateFrom [64]; const char *p; + int ret = -1;; + + *uri_out = NULL; if (!dom_xml) { qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("no domain XML passed")); - return -1; + goto cleanup; } /* The URI passed in may be NULL or a string "tcp://somehostname:port". @@ -3494,14 +3597,15 @@ qemudDomainMigratePrepare2 (virConnectPt if (gethostname (hostname, HOST_NAME_MAX+1) == -1) { qemudReportError (dconn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, "%s", strerror (errno)); - return -1; + goto cleanup; } /* Caller frees */ if (asprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) { qemudReportError (dconn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", strerror (errno)); - return -1; + *uri_out = NULL; + goto cleanup; } } else { /* Check the URI starts with "tcp:". We will escape the @@ -3511,7 +3615,7 @@ qemudDomainMigratePrepare2 (virConnectPt if (!STREQLEN (uri_in, "tcp:", 6)) { qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG, "%s", _("only tcp URIs are supported for KVM migrations")); - return -1; + goto cleanup; } /* Get the port number. */ @@ -3521,7 +3625,7 @@ qemudDomainMigratePrepare2 (virConnectPt if (this_port == -1 || p-uri_in != strlen (uri_in)) { qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG, "%s", _("URI did not have ':port' at the end")); - return -1; + goto cleanup; } } @@ -3529,7 +3633,7 @@ qemudDomainMigratePrepare2 (virConnectPt if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml))) { qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to parse XML")); - return -1; + goto cleanup; } /* Target domain name, maybe renamed. */ @@ -3546,6 +3650,7 @@ qemudDomainMigratePrepare2 (virConnectPt if (virUUIDGenerate (def->uuid) == -1) { qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("could not generate random UUID")); + goto cleanup; } #endif @@ -3555,8 +3660,7 @@ qemudDomainMigratePrepare2 (virConnectPt qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain with the same name or UUID already exists as '%s'"), vm->def->name); - virDomainDefFree(def); - return -1; + goto cleanup; } } @@ -3565,9 +3669,9 @@ qemudDomainMigratePrepare2 (virConnectPt def))) { qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to assign new VM")); - virDomainDefFree(def); - return -1; + goto cleanup; } + def = NULL; /* Domain starts inactive, even if the domain XML had an id field. */ vm->def->id = -1; @@ -3582,13 +3686,20 @@ qemudDomainMigratePrepare2 (virConnectPt if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); - return -1; + goto cleanup; } qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); + ret = 0; - return 0; +cleanup: + virDomainDefFree(def); + if (ret != 0) { + VIR_FREE(*uri_out); + } + + return ret; } /* Perform is the second step, and it runs on the source host. */ @@ -3601,22 +3712,24 @@ qemudDomainMigratePerform (virDomainPtr const char *dname ATTRIBUTE_UNUSED, unsigned long resource) { - struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; char *safe_uri; char cmd[HOST_NAME_MAX+50]; - char *info; + char *info = NULL; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } if (!virDomainIsActive(vm)) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("domain is not running")); - return -1; + goto cleanup; } if (!(flags & VIR_MIGRATE_LIVE)) { @@ -3645,7 +3758,7 @@ qemudDomainMigratePerform (virDomainPtr if (!safe_uri) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, "%s", strerror (errno)); - return -1; + goto cleanup; } snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri); VIR_FREE (safe_uri); @@ -3653,7 +3766,7 @@ qemudDomainMigratePerform (virDomainPtr if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("migrate operation failed")); - return -1; + goto cleanup; } DEBUG ("migrate reply: %s", info); @@ -3662,11 +3775,8 @@ qemudDomainMigratePerform (virDomainPtr if (strstr(info, "fail") != NULL) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("migrate failed: %s"), info); - VIR_FREE(info); - return -1; + goto cleanup; } - - VIR_FREE (info); /* Clean up the source domain. */ qemudShutdownVMDaemon (dom->conn, driver, vm); @@ -3675,8 +3785,11 @@ qemudDomainMigratePerform (virDomainPtr VIR_DOMAIN_EVENT_STOPPED_MIGRATED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); + ret = 0; - return 0; +cleanup: + VIR_FREE(info); + return ret; } /* Finish is the third and final step, and it runs on the destination host. */ @@ -3689,15 +3802,16 @@ qemudDomainMigrateFinish2 (virConnectPtr unsigned long flags ATTRIBUTE_UNUSED, int retcode) { - struct qemud_driver *driver = (struct qemud_driver *)dconn->privateData; - virDomainObjPtr vm = virDomainFindByName(&driver->domains, dname); - virDomainPtr dom; + struct qemud_driver *driver = dconn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; char *info = NULL; + vm = virDomainFindByName(&driver->domains, dname); if (!vm) { qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching name %s"), dname); - return NULL; + goto cleanup; } /* Did the migration go as planned? If yes, return the domain @@ -3710,7 +3824,6 @@ qemudDomainMigrateFinish2 (virConnectPtr qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_RESUMED, VIR_DOMAIN_EVENT_RESUMED_MIGRATED); - return dom; } else { qemudShutdownVMDaemon (dconn, driver, vm); qemudDomainEventDispatch(driver, vm, @@ -3718,8 +3831,10 @@ qemudDomainMigrateFinish2 (virConnectPtr VIR_DOMAIN_EVENT_STOPPED_FAILED); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); - return NULL; } + +cleanup: + return dom; } static virDriver qemuDriver = { -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:31:56PM +0000, Daniel P. Berrange wrote:
This patch reduces the number of return points in the QEMU driver methods centralizing all cleanup code. It also removes a bunch of unnecessary type casts, since void * automatically casts to any type. Finally it separates out variable declarations from variable initializations since the initializations will need to be protected with the locked critical section.
IMHO the superfluous cast were harmless so could have been preserved, but it's not a big deal, [...]
+ if (vm->state != VIR_DOMAIN_PAUSED) { + if (qemudMonitorCommand(driver, vm, "stop", &info) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("suspend operation failed")); + goto cleanup; + } + vm->state = VIR_DOMAIN_PAUSED; + qemudDebug("Reply %s", info); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_SUSPENDED, + VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); + VIR_FREE(info);
qemudMonitorCommand has no comment on when the reply field may or not be initialized. The code shows it's only if it returns 0 but that's worth a comment or VIR_FREE(info); should be moved in the cleanup part. The code is right but any small change here may generate a leak, and that's true for most of the entry points. [...]
static int qemudDomainSave(virDomainPtr dom, const char *path) {
+cleanup: + if (fd != -1) + close(fd); + VIR_FREE(xml); + VIR_FREE(safe_path); + VIR_FREE(command); + VIR_FREE(info); + if (ret != 0) + unlink(path); + + return ret; }
Considering the complexity for the function, I would not be surprized if that patch isn't cleaning up a couple of leaks on errors. Good to have a systematic freeing. [...]
@@ -2271,15 +2346,15 @@ static int qemudDomainRestore(virConnect def))) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to assign new VM")); - virDomainDefFree(def); - close(fd); - return -1; + goto cleanup; } + def = NULL;
Hum, okay, but that function is harder to review [...]
static int qemudDomainStart(virDomainPtr dom) { [...] ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL); - if (ret < 0) - return ret; - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); - return 0; + if (ret != -1) + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED);
small semantic change, but since -1 is the only error code, fine [...]
/* Return the disks name for use in monitor commands */ -static char *qemudDiskDeviceName(const virDomainPtr dom, +static char *qemudDiskDeviceName(const virConnectPtr conn, const virDomainDiskDefPtr disk) {
a bit fo refactoring [...]
-static int qemudDomainChangeEjectableMedia(virDomainPtr dom, +static int qemudDomainChangeEjectableMedia(virConnectPtr conn, + struct qemud_driver *driver, + virDomainObjPtr vm, virDomainDeviceDefPtr dev)
here too [...]
- VIR_FREE(dev); +cleanup: + virDomainDeviceDefFree(dev); return ret; }
hum, that was a leak here apparently [...]
+ if (asprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) { + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); + cmd = NULL;
If memory allocation wasn’t possible, or some other error occurs, these functions will return -1, and the contents of strp is undefined. gasp, fine :-) Okay, independantly of the threading this sis a good cleanup patch which should be applied, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the QEMU driver threadsafe with the exception of the domain events code. qemu_conf.h | 2 qemu_driver.c | 458 ++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 337 insertions(+), 123 deletions(-) Daniel diff --git a/src/qemu_conf.h b/src/qemu_conf.h --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -51,6 +51,8 @@ enum qemud_cmd_flags { /* Main driver state */ struct qemud_driver { + PTHREAD_MUTEX_T(lock); + unsigned int qemuVersion; int nextvmid; diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -76,6 +76,15 @@ static int qemudShutdown(void); #define qemudLog(level, msg...) fprintf(stderr, msg) +static void qemuDriverLock(struct qemud_driver *driver) +{ + pthread_mutex_lock(&driver->lock); +} +static void qemuDriverUnlock(struct qemud_driver *driver) +{ + pthread_mutex_unlock(&driver->lock); +} + static int qemudSetCloseExec(int fd) { int flags; if ((flags = fcntl(fd, F_GETFD)) < 0) @@ -141,6 +150,7 @@ qemudAutostartConfigs(struct qemud_drive for (i = 0 ; i < driver->domains.count ; i++) { virDomainObjPtr vm = driver->domains.objs[i]; + virDomainObjLock(vm); if (vm->autostart && !virDomainIsActive(vm)) { int ret = qemudStartVMDaemon(NULL, driver, vm, NULL); @@ -154,6 +164,7 @@ qemudAutostartConfigs(struct qemud_drive VIR_DOMAIN_EVENT_STARTED_BOOTED); } } + virDomainObjUnlock(vm); } } @@ -172,12 +183,15 @@ qemudStartup(void) { if (VIR_ALLOC(qemu_driver) < 0) return -1; + pthread_mutex_init(&qemu_driver->lock, NULL); + qemuDriverLock(qemu_driver); + /* Don't have a dom0 so start from 1 */ qemu_driver->nextvmid = 1; /* Init callback list */ if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0) - return -1; + goto out_of_memory; if (!uid) { if (asprintf(&qemu_driver->logDir, @@ -190,7 +204,7 @@ qemudStartup(void) { if (!(pw = getpwuid(uid))) { qemudLog(QEMUD_ERR, _("Failed to find user record for uid '%d': %s\n"), uid, strerror(errno)); - goto out_nouid; + goto error; } if (asprintf(&qemu_driver->logDir, @@ -229,20 +243,22 @@ qemudStartup(void) { &qemu_driver->domains, qemu_driver->configDir, qemu_driver->autostartDir, - NULL, NULL) < 0) { - qemudShutdown(); - return -1; - } + NULL, NULL) < 0) + goto error; qemudAutostartConfigs(qemu_driver); - return 0; - - out_of_memory: + qemuDriverUnlock(qemu_driver); + + return 0; + +out_of_memory: qemudLog (QEMUD_ERR, "%s", _("qemudStartup: out of memory\n")); - out_nouid: +error: + if (qemu_driver) + qemuDriverUnlock(qemu_driver); VIR_FREE(base); - VIR_FREE(qemu_driver); + qemudShutdown(); return -1; } @@ -267,6 +283,7 @@ qemudReload(void) { if (!qemu_driver) return 0; + qemuDriverLock(qemu_driver); virDomainLoadAllConfigs(NULL, qemu_driver->caps, &qemu_driver->domains, @@ -275,6 +292,7 @@ qemudReload(void) { qemudNotifyLoadDomain, qemu_driver); qemudAutostartConfigs(qemu_driver); + qemuDriverUnlock(qemu_driver); return 0; } @@ -290,16 +308,18 @@ static int static int qemudActive(void) { unsigned int i; + int active = 0; if (!qemu_driver) return 0; + qemuDriverLock(qemu_driver); for (i = 0 ; i < qemu_driver->domains.count ; i++) if (virDomainIsActive(qemu_driver->domains.objs[i])) - return 1; - - /* Otherwise we're happy to deal with a shutdown */ - return 0; + active = 1; + + qemuDriverUnlock(qemu_driver); + return active; } /** @@ -314,16 +334,16 @@ qemudShutdown(void) { if (!qemu_driver) return -1; + qemuDriverLock(qemu_driver); virCapabilitiesFree(qemu_driver->caps); /* shutdown active VMs */ for (i = 0 ; i < qemu_driver->domains.count ; i++) { virDomainObjPtr dom = qemu_driver->domains.objs[i]; + virDomainObjLock(dom); if (virDomainIsActive(dom)) qemudShutdownVMDaemon(NULL, qemu_driver, dom); - if (!dom->persistent) - virDomainRemoveInactive(&qemu_driver->domains, - dom); + virDomainObjUnlock(dom); } virDomainObjListFree(&qemu_driver->domains); @@ -340,6 +360,7 @@ qemudShutdown(void) { if (qemu_driver->brctl) brShutdown(qemu_driver->brctl); + qemuDriverUnlock(qemu_driver); VIR_FREE(qemu_driver); return 0; @@ -1047,38 +1068,15 @@ static void qemudShutdownVMDaemon(virCon } } -static int qemudDispatchVMLog(struct qemud_driver *driver, virDomainObjPtr vm, int fd) { - if (qemudVMData(driver, vm, fd) < 0) { - qemudShutdownVMDaemon(NULL, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_FAILED); - if (!vm->persistent) - virDomainRemoveInactive(&driver->domains, - vm); - } - return 0; -} - -static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr vm, - int fd ATTRIBUTE_UNUSED) { - qemudShutdownVMDaemon(NULL, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - if (!vm->persistent) - virDomainRemoveInactive(&driver->domains, - vm); - return 0; -} - static void qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) { struct qemud_driver *driver = opaque; virDomainObjPtr vm = NULL; unsigned int i; - + int quit = 0, failed = 0; + + qemuDriverLock(driver); for (i = 0 ; i < driver->domains.count ; i++) { if (virDomainIsActive(driver->domains.objs[i]) && (driver->domains.objs[i]->stdout_watch == watch || @@ -1089,18 +1087,38 @@ qemudDispatchVMEvent(int watch, int fd, } if (!vm) - return; + goto cleanup; if (vm->stdout_fd != fd && vm->stderr_fd != fd) { - qemudDispatchVMFailure(driver, vm, fd); - return; - } - - if (events == VIR_EVENT_HANDLE_READABLE) - qemudDispatchVMLog(driver, vm, fd); - else - qemudDispatchVMFailure(driver, vm, fd); + failed = 1; + } else { + if (events & VIR_EVENT_HANDLE_READABLE) { + if (qemudVMData(driver, vm, fd) < 0) + failed = 1; + } else { + quit = 1; + } + } + + if (failed || quit) { + qemudShutdownVMDaemon(NULL, driver, vm); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + quit ? + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN : + VIR_DOMAIN_EVENT_STOPPED_FAILED); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, + vm); + vm = NULL; + } + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); } static int @@ -1311,9 +1329,11 @@ static char *qemudGetCapabilities(virCon struct qemud_driver *driver = conn->privateData; char *xml; + qemuDriverLock(driver); if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for capabilities support")); + qemuDriverUnlock(driver); return xml; } @@ -1423,7 +1443,9 @@ static virDomainPtr qemudDomainLookupByI virDomainObjPtr vm; virDomainPtr dom = NULL; + qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, id); + qemuDriverUnlock(driver); if (!vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); @@ -1434,15 +1456,21 @@ static virDomainPtr qemudDomainLookupByI if (dom) dom->id = vm->def->id; cleanup: - return dom; -} + if (vm) + virDomainObjUnlock(vm); + return dom; +} + static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { struct qemud_driver *driver = conn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, uuid); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -1452,15 +1480,21 @@ static virDomainPtr qemudDomainLookupByU if (dom) dom->id = vm->def->id; cleanup: - return dom; -} + if (vm) + virDomainObjUnlock(vm); + return dom; +} + static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, const char *name) { struct qemud_driver *driver = conn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; + qemuDriverLock(driver); vm = virDomainFindByName(&driver->domains, name); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -1470,6 +1504,8 @@ static virDomainPtr qemudDomainLookupByN if (dom) dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -1477,6 +1513,7 @@ static int qemudGetVersion(virConnectPtr struct qemud_driver *driver = conn->privateData; int ret = -1; + qemuDriverLock(driver); if (qemudExtractVersion(conn, driver) < 0) goto cleanup; @@ -1484,6 +1521,7 @@ static int qemudGetVersion(virConnectPtr ret = 0; cleanup: + qemuDriverUnlock(driver); return ret; } @@ -1513,29 +1551,42 @@ static int qemudListDomains(virConnectPt struct qemud_driver *driver = conn->privateData; int got = 0, i; - for (i = 0 ; i < driver->domains.count && got < nids ; i++) + qemuDriverLock(driver); + for (i = 0 ; i < driver->domains.count && got < nids ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) ids[got++] = driver->domains.objs[i]->def->id; + virDomainObjUnlock(driver->domains.objs[i]); + } + qemuDriverUnlock(driver); return got; } + static int qemudNumDomains(virConnectPtr conn) { struct qemud_driver *driver = conn->privateData; int n = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + qemuDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + qemuDriverUnlock(driver); return n; } + static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { struct qemud_driver *driver = conn->privateData; virDomainDefPtr def; - virDomainObjPtr vm; - virDomainPtr dom = NULL; - + virDomainObjPtr vm = NULL; + virDomainPtr dom = NULL; + + qemuDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) goto cleanup; @@ -1567,6 +1618,7 @@ static virDomainPtr qemudDomainCreate(vi if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; goto cleanup; } qemudDomainEventDispatch(driver, vm, @@ -1578,7 +1630,9 @@ static virDomainPtr qemudDomainCreate(vi cleanup: virDomainDefFree(def); - + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return dom; } @@ -1589,7 +1643,10 @@ static int qemudDomainSuspend(virDomainP virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); goto cleanup; @@ -1615,6 +1672,8 @@ static int qemudDomainSuspend(virDomainP ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1625,7 +1684,10 @@ static int qemudDomainResume(virDomainPt virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); @@ -1652,6 +1714,8 @@ static int qemudDomainResume(virDomainPt ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1662,7 +1726,10 @@ static int qemudDomainShutdown(virDomain char* info; int ret = -1; - vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); @@ -1678,8 +1745,9 @@ static int qemudDomainShutdown(virDomain ret = 0; cleanup: - return ret; - + if (vm) + virDomainObjUnlock(vm); + return ret; } @@ -1688,6 +1756,7 @@ static int qemudDomainDestroy(virDomainP virDomainObjPtr vm; int ret = -1; + qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -1699,12 +1768,17 @@ static int qemudDomainDestroy(virDomainP qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_DESTROYED); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); - ret = 0; - -cleanup: + vm = NULL; + } + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -1714,7 +1788,9 @@ static char *qemudDomainGetOSType(virDom virDomainObjPtr vm; char *type = NULL; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1726,6 +1802,8 @@ static char *qemudDomainGetOSType(virDom "%s", _("failed to allocate space for ostype")); cleanup: + if (vm) + virDomainObjUnlock(vm); return type; } @@ -1735,7 +1813,10 @@ static unsigned long qemudDomainGetMaxMe virDomainObjPtr vm; unsigned long ret = 0; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1748,6 +1829,8 @@ static unsigned long qemudDomainGetMaxMe ret = vm->def->maxmem; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1756,7 +1839,10 @@ static int qemudDomainSetMaxMemory(virDo virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1776,6 +1862,8 @@ static int qemudDomainSetMaxMemory(virDo ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1784,7 +1872,9 @@ static int qemudDomainSetMemory(virDomai virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1810,6 +1900,8 @@ static int qemudDomainSetMemory(virDomai ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1819,7 +1911,9 @@ static int qemudDomainGetInfo(virDomainP virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1843,6 +1937,8 @@ static int qemudDomainGetInfo(virDomainP ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1956,6 +2052,7 @@ static int qemudDomainSave(virDomainPtr memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); header.version = QEMUD_SAVE_VERSION; + qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { @@ -2054,9 +2151,11 @@ static int qemudDomainSave(virDomainPtr qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_SAVED); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } ret = 0; cleanup: @@ -2068,7 +2167,9 @@ cleanup: VIR_FREE(info); if (ret != 0) unlink(path); - + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -2079,7 +2180,10 @@ static int qemudDomainSetVcpus(virDomain int max; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -2112,6 +2216,8 @@ static int qemudDomainSetVcpus(virDomain ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -2129,7 +2235,10 @@ qemudDomainPinVcpu(virDomainPtr dom, virNodeInfo nodeinfo; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s",_("cannot pin vcpus on an inactive domain")); @@ -2170,6 +2279,8 @@ qemudDomainPinVcpu(virDomainPtr dom, ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -2185,7 +2296,10 @@ qemudDomainGetVcpus(virDomainPtr dom, int i, v, maxcpu; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!virDomainIsActive(vm)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s",_("cannot pin vcpus on an inactive domain")); @@ -2241,6 +2355,8 @@ qemudDomainGetVcpus(virDomainPtr dom, ret = maxinfo; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } #endif /* HAVE_SCHED_GETAFFINITY */ @@ -2252,7 +2368,10 @@ static int qemudDomainGetMaxVcpus(virDom const char *type; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -2272,6 +2391,8 @@ static int qemudDomainGetMaxVcpus(virDom ret = qemudGetMaxVCPUs(dom->conn, type); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -2280,12 +2401,13 @@ static int qemudDomainRestore(virConnect const char *path) { struct qemud_driver *driver = conn->privateData; virDomainDefPtr def = NULL; - virDomainObjPtr vm; + virDomainObjPtr vm = NULL; int fd = -1; int ret = -1; char *xml = NULL; struct qemud_save_header header; + qemuDriverLock(driver); /* Verify the header and read the XML */ if ((fd = open(path, O_RDONLY)) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, @@ -2359,9 +2481,11 @@ static int qemudDomainRestore(virConnect if (ret < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to start VM")); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } goto cleanup; } @@ -2387,7 +2511,9 @@ cleanup: VIR_FREE(xml); if (fd != -1) close(fd); - + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -2398,7 +2524,10 @@ static char *qemudDomainDumpXML(virDomai virDomainObjPtr vm; char *ret = NULL; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -2411,6 +2540,8 @@ static char *qemudDomainDumpXML(virDomai flags); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -2420,21 +2551,27 @@ static int qemudListDefinedDomains(virCo struct qemud_driver *driver = conn->privateData; int got = 0, i; + qemuDriverLock(driver); for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) { if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); - goto cleanup; - } - } - } - + virDomainObjUnlock(driver->domains.objs[i]); + goto cleanup; + } + } + virDomainObjUnlock(driver->domains.objs[i]); + } + + qemuDriverUnlock(driver); return got; cleanup: for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); + qemuDriverUnlock(driver); return -1; } @@ -2442,9 +2579,11 @@ static int qemudNumDefinedDomains(virCon struct qemud_driver *driver = conn->privateData; int n = 0, i; + qemuDriverLock(driver); for (i = 0 ; i < driver->domains.count ; i++) if (!virDomainIsActive(driver->domains.objs[i])) n++; + qemuDriverUnlock(driver); return n; } @@ -2455,7 +2594,10 @@ static int qemudDomainStart(virDomainPtr virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -2469,6 +2611,8 @@ static int qemudDomainStart(virDomainPtr VIR_DOMAIN_EVENT_STARTED_BOOTED); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -2476,16 +2620,19 @@ static virDomainPtr qemudDomainDefine(vi static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { struct qemud_driver *driver = conn->privateData; virDomainDefPtr def; - virDomainObjPtr vm; + virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; int newVM = 1; + qemuDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) goto cleanup; vm = virDomainFindByName(&driver->domains, def->name); - if (vm) + if (vm) { + virDomainObjUnlock(vm); newVM = 0; + } if (!(vm = virDomainAssignDef(conn, &driver->domains, @@ -2500,6 +2647,7 @@ static virDomainPtr qemudDomainDefine(vi vm->newDef ? vm->newDef : vm->def) < 0) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; goto cleanup; } @@ -2513,6 +2661,9 @@ static virDomainPtr qemudDomainDefine(vi if (dom) dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return dom; } @@ -2521,7 +2672,9 @@ static int qemudDomainUndefine(virDomain virDomainObjPtr vm; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -2549,9 +2702,13 @@ static int qemudDomainUndefine(virDomain virDomainRemoveInactive(&driver->domains, vm); - ret = 0; - -cleanup: + vm = NULL; + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -2913,6 +3070,7 @@ static int qemudDomainAttachDevice(virDo virDomainDeviceDefPtr dev = NULL; int ret = -1; + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -2964,6 +3122,9 @@ static int qemudDomainAttachDevice(virDo cleanup: virDomainDeviceDefFree(dev); + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -3045,6 +3206,7 @@ static int qemudDomainDetachDevice(virDo virDomainDeviceDefPtr dev = NULL; int ret = -1; + qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -3074,16 +3236,22 @@ static int qemudDomainDetachDevice(virDo cleanup: virDomainDeviceDefFree(dev); + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } static int qemudDomainGetAutostart(virDomainPtr dom, - int *autostart) { - struct qemud_driver *driver = dom->conn->privateData; - virDomainObjPtr vm; - int ret = -1; - - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + int *autostart) { + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -3094,6 +3262,8 @@ static int qemudDomainGetAutostart(virDo ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -3104,7 +3274,10 @@ static int qemudDomainSetAutostart(virDo char *configFile = NULL, *autostartLink = NULL; int ret = -1; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -3157,7 +3330,8 @@ cleanup: cleanup: VIR_FREE(configFile); VIR_FREE(autostartLink); - + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -3179,7 +3353,9 @@ qemudDomainBlockStats (virDomainPtr dom, virDomainObjPtr vm; virDomainDiskDefPtr disk = NULL; - vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverUnlock(driver); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); @@ -3292,6 +3468,8 @@ qemudDomainBlockStats (virDomainPtr dom, cleanup: VIR_FREE(qemu_dev_name); VIR_FREE(info); + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -3306,7 +3484,10 @@ qemudDomainInterfaceStats (virDomainPtr int i; int ret = -1; - vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); @@ -3341,6 +3522,8 @@ qemudDomainInterfaceStats (virDomainPtr _("invalid path, '%s' is not a known interface"), path); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } #else @@ -3365,7 +3548,10 @@ qemudDomainBlockPeek (virDomainPtr dom, virDomainObjPtr vm; int fd = -1, ret = -1, i; - vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + qemuDriverUnlock(driver); + if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -3417,6 +3603,8 @@ cleanup: cleanup: if (fd >= 0) close (fd); + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -3432,7 +3620,9 @@ qemudDomainMemoryPeek (virDomainPtr dom, char tmp[] = TEMPDIR "/qemu.mem.XXXXXX"; int fd = -1, ret = -1; - vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverLock(driver); + vm = virDomainFindByID(&driver->domains, dom->id); + qemuDriverUnlock(driver); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -3482,6 +3672,8 @@ cleanup: VIR_FREE(info); if (fd >= 0) close (fd); unlink (tmp); + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -3495,8 +3687,10 @@ qemudDomainEventRegister (virConnectPtr struct qemud_driver *driver = conn->privateData; int ret; + qemuDriverLock(driver); ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, callback, opaque, freecb); + qemuDriverUnlock(driver); return ret; } @@ -3508,8 +3702,10 @@ qemudDomainEventDeregister (virConnectPt struct qemud_driver *driver = conn->privateData; int ret; + qemuDriverLock(driver); ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, callback); + qemuDriverUnlock(driver); return ret; } @@ -3573,6 +3769,7 @@ qemudDomainMigratePrepare2 (virConnectPt *uri_out = NULL; + qemuDriverLock(driver); if (!dom_xml) { qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("no domain XML passed")); @@ -3683,9 +3880,10 @@ qemudDomainMigratePrepare2 (virConnectPt if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom) < 0) { qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to start listening VM")); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); - + vm = NULL; + } goto cleanup; } qemudDomainEventDispatch(driver, vm, @@ -3698,7 +3896,9 @@ cleanup: if (ret != 0) { VIR_FREE(*uri_out); } - + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -3719,6 +3919,7 @@ qemudDomainMigratePerform (virDomainPtr char *info = NULL; int ret = -1; + qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -3783,12 +3984,17 @@ qemudDomainMigratePerform (virDomainPtr qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_MIGRATED); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); - ret = 0; - -cleanup: - VIR_FREE(info); + vm = NULL; + } + ret = 0; + +cleanup: + VIR_FREE(info); + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -3807,6 +4013,7 @@ qemudDomainMigrateFinish2 (virConnectPtr virDomainPtr dom = NULL; char *info = NULL; + qemuDriverLock(driver); vm = virDomainFindByName(&driver->domains, dname); if (!vm) { qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN, @@ -3829,11 +4036,16 @@ qemudDomainMigrateFinish2 (virConnectPtr qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STOPPED, VIR_DOMAIN_EVENT_STOPPED_FAILED); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); - } - -cleanup: + vm = NULL; + } + } + +cleanup: + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return dom; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:33:06PM +0000, Daniel P. Berrange wrote:
This patch makes the QEMU driver threadsafe with the exception of the domain events code. @@ -229,20 +243,22 @@ qemudStartup(void) { [...] +error: + if (qemu_driver) + qemuDriverUnlock(qemu_driver); VIR_FREE(base); - VIR_FREE(qemu_driver); + qemudShutdown();
okay the clean way to free the driver structure
@@ -314,16 +334,16 @@ qemudShutdown(void) { if (!qemu_driver) return -1;
+ qemuDriverLock(qemu_driver); virCapabilitiesFree(qemu_driver->caps);
/* shutdown active VMs */ for (i = 0 ; i < qemu_driver->domains.count ; i++) { virDomainObjPtr dom = qemu_driver->domains.objs[i]; + virDomainObjLock(dom); if (virDomainIsActive(dom)) qemudShutdownVMDaemon(NULL, qemu_driver, dom); - if (!dom->persistent) - virDomainRemoveInactive(&qemu_driver->domains, - dom); + virDomainObjUnlock(dom); }
virDomainObjListFree(&qemu_driver->domains); @@ -340,6 +360,7 @@ qemudShutdown(void) { if (qemu_driver->brctl) brShutdown(qemu_driver->brctl);
+ qemuDriverUnlock(qemu_driver); VIR_FREE(qemu_driver);
return 0;
We don't remove anymore the non-persistent domain on shutdown ? Is that because we can hook this to the event lifecycle processing ?
@@ -1089,18 +1087,38 @@ qemudDispatchVMEvent(int watch, int fd, [...] + if (failed || quit) { + qemudShutdownVMDaemon(NULL, driver, vm); + qemudDomainEventDispatch(driver, vm, + VIR_DOMAIN_EVENT_STOPPED, + quit ? + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN : + VIR_DOMAIN_EVENT_STOPPED_FAILED); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, + vm); + vm = NULL; + } + }
seems to be done here now, okay I could not spot anything on the locking side, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Tue, Dec 02, 2008 at 10:45:32AM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:33:06PM +0000, Daniel P. Berrange wrote:
This patch makes the QEMU driver threadsafe with the exception of the domain events code. @@ -229,20 +243,22 @@ qemudStartup(void) { [...] +error: + if (qemu_driver) + qemuDriverUnlock(qemu_driver); VIR_FREE(base); - VIR_FREE(qemu_driver); + qemudShutdown();
okay the clean way to free the driver structure
@@ -314,16 +334,16 @@ qemudShutdown(void) { if (!qemu_driver) return -1;
+ qemuDriverLock(qemu_driver); virCapabilitiesFree(qemu_driver->caps);
/* shutdown active VMs */ for (i = 0 ; i < qemu_driver->domains.count ; i++) { virDomainObjPtr dom = qemu_driver->domains.objs[i]; + virDomainObjLock(dom); if (virDomainIsActive(dom)) qemudShutdownVMDaemon(NULL, qemu_driver, dom); - if (!dom->persistent) - virDomainRemoveInactive(&qemu_driver->domains, - dom); + virDomainObjUnlock(dom); }
virDomainObjListFree(&qemu_driver->domains); @@ -340,6 +360,7 @@ qemudShutdown(void) { if (qemu_driver->brctl) brShutdown(qemu_driver->brctl);
+ qemuDriverUnlock(qemu_driver); VIR_FREE(qemu_driver);
return 0;
We don't remove anymore the non-persistent domain on shutdown ? Is that because we can hook this to the event lifecycle processing ?
Thq qemudShutdown() method is invoked when the daemon itself is shutting down completely. There's no need to call the individual object deletion virDomainRemoveInactive() in this case, because a few lines later we do a virDomainObjListFree() which bulk removes all of them. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch adds thread safety to the domain events processing code of the QEMU driver. This entailed rather a large refactoring of the domain events code and its quite complicated to explain. - A convenient helper is added for creating event queues virDomainEventQueuePtr virDomainEventQueueNew(void); - Convenient helpers are added for creating virDomainEventPtr instances from a variety of sources - each driver has different needs virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail); virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail); virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail); virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail); - The virDomainEvent struct held a reference to a virDomainPtr object. This is replaced with a direct triple (id, name, uuid), avoiding the need to instantiate virDomainPtr objects deep inside the QEMU code. - The virDomainEventQueuePush() method is changed to take a virDomainEventPtr object, rather than a virDomainPtr object These last two changes are important to allow safe re-entrancy of the event dispatch process. The virDomainEventPtr instance can be allocated within a critical section lockde on the virDomainObjPtr instance, while the event is queued outside the critical section, while only the driver lock is held. Without this we'd have to hold the per-driver lock over a much larger block of code which hurts concurrancy. The QEMU driver cannot directly dispatch events, instead we have to follow the remote driver and maintain a queue of pending events, and use a timer to flush them. Again this is neccessary to improve concurrency & provide safe re-entrancy. Since we have two driver maintaining queues of evnts I add more helper functions to allow code sharing - Send a single vent to a list of callbacks: void virDomainEventDispatch(virDomainEventPtr event, virDomainEventCallbackListPtr cbs, virDomainEventDispatchFunc dispatch, void *opaque); - Send a set of queued events to a list of callbacks void virDomainEventQueueDispatch(virDomainEventQueuePtr queue, virDomainEventCallbackListPtr cbs, virDomainEventDispatchFunc dispatch, void *opaque); The virDomainEventDispatchFunc is what is invoked to finally dispatch a single event, to a single registered callback. The default impl just invokes the callback directly. The QEMU driver, however, uses a wrapper which first releases its driver lock, invokes the callback, and then re-aquires the lock. As a further complication it is not safe for virDomainEventUnregister to actually remove the callback from the list directly. Instead we add a helper that simply marks it as removed, and then actually purge it from a safe point in the code, when its guarenteed that the driver isn't in the middle of dispatching. As well as making the QEMU driver thread safe, this also takes the opportunity to refactor the Xen / remote drivers to use more helpers domain_event.c | 191 +++++++++++++++++++++++---- domain_event.h | 51 ++++++- libvirt_sym.version.in | 16 ++ qemu_conf.h | 3 qemu_driver.c | 339 +++++++++++++++++++++++++++++++------------------ remote_internal.c | 93 +++++-------- xen_inotify.c | 135 ++++++++++--------- xen_unified.c | 30 +--- xen_unified.h | 4 xs_internal.c | 56 +++----- 10 files changed, 594 insertions(+), 324 deletions(-) Daniel diff --git a/src/domain_event.c b/src/domain_event.c --- a/src/domain_event.c +++ b/src/domain_event.c @@ -125,6 +125,49 @@ virDomainEventCallbackListRemoveConn(vir return 0; } +int virDomainEventCallbackListMarkDelete(virConnectPtr conn, + virDomainEventCallbackListPtr cbList, + virConnectDomainEventCallback callback) +{ + int i; + for (i = 0 ; i < cbList->count ; i++) { + if (cbList->callbacks[i]->conn == conn && + cbList->callbacks[i]->cb == callback) { + cbList->callbacks[i]->deleted = 1; + return 0; + } + } + return -1; +} + +int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList) +{ + int old_count = cbList->count; + int i; + for (i = 0 ; i < cbList->count ; i++) { + if (cbList->callbacks[i]->deleted) { + virFreeCallback freecb = cbList->callbacks[i]->freecb; + if (freecb) + (*freecb)(cbList->callbacks[i]->opaque); + virUnrefConnect(cbList->callbacks[i]->conn); + VIR_FREE(cbList->callbacks[i]); + + if (i < (cbList->count - 1)) + memmove(cbList->callbacks + i, + cbList->callbacks + i + 1, + sizeof(*(cbList->callbacks)) * + (cbList->count - (i + 1))); + cbList->count--; + i--; + } + } + if (cbList->count < old_count && + VIR_REALLOC_N(cbList->callbacks, cbList->count) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + return 0; +} + /** * virDomainEventCallbackListAdd: * @conn: pointer to the connection @@ -182,6 +225,62 @@ virDomainEventCallbackListAdd(virConnect return 0; } +void virDomainEventFree(virDomainEventPtr event) +{ + if (!event) + return; + + VIR_FREE(event->name); + VIR_FREE(event); +} + + +virDomainEventQueuePtr virDomainEventQueueNew(void) +{ + virDomainEventQueuePtr ret; + + if (VIR_ALLOC(ret) < 0) + return NULL; + + return ret; +} + +virDomainEventPtr virDomainEventNew(int id, const char *name, + const unsigned char *uuid, + int type, int detail) +{ + virDomainEventPtr event; + + if (VIR_ALLOC(event) < 0) + return NULL; + + event->type = type; + event->detail = detail; + if (!(event->name = strdup(name))) { + VIR_FREE(event); + return NULL; + } + event->id = id; + memcpy(event->uuid, uuid, VIR_UUID_BUFLEN); + + return event; +} + +virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail) +{ + return virDomainEventNew(dom->id, dom->name, dom->uuid, type, detail); +} + +virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail) +{ + return virDomainEventNewFromDef(obj->def, type, detail); +} + +virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail) +{ + return virDomainEventNew(def->id, def->name, def->uuid, type, detail); +} + /** * virDomainEventQueueFree: * @queue: pointer to the queue @@ -192,14 +291,18 @@ virDomainEventQueueFree(virDomainEventQu virDomainEventQueueFree(virDomainEventQueuePtr queue) { int i; - for ( i=0 ; i<queue->count ; i++ ) { - VIR_FREE(queue->events[i]); + if (!queue) + return; + + for (i = 0; i < queue->count ; i++) { + virDomainEventFree(queue->events[i]); } + VIR_FREE(queue->events); VIR_FREE(queue); } /** - * virDomainEventCallbackQueuePop: + * virDomainEventQueuePop: * @evtQueue: the queue of events * * Internal function to pop off, and return the front of the queue @@ -208,7 +311,7 @@ virDomainEventQueueFree(virDomainEventQu * Returns: virDomainEventPtr on success NULL on failure. */ virDomainEventPtr -virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue) +virDomainEventQueuePop(virDomainEventQueuePtr evtQueue) { virDomainEventPtr ret; @@ -232,9 +335,8 @@ virDomainEventCallbackQueuePop(virDomain } /** - * virDomainEventCallbackQueuePush: + * virDomainEventQueuePush: * @evtQueue: the dom event queue - * @dom: the domain to add * @event: the event to add * * Internal function to push onto the back of an virDomainEventQueue @@ -242,37 +344,76 @@ virDomainEventCallbackQueuePop(virDomain * Returns: 0 on success, -1 on failure */ int -virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, - virDomainPtr dom, - int event, - int detail) +virDomainEventQueuePush(virDomainEventQueuePtr evtQueue, + virDomainEventPtr event) { - virDomainEventPtr domEvent; - - /* Check incoming */ - if ( !evtQueue ) { + if (!evtQueue) { return -1; } - - /* Allocate new event */ - if (VIR_ALLOC(domEvent) < 0) { - DEBUG0("Error allocating event"); - return -1; - } - domEvent->dom = dom; - domEvent->event = event; - domEvent->detail = detail; /* Make space on queue */ if (VIR_REALLOC_N(evtQueue->events, evtQueue->count + 1) < 0) { DEBUG0("Error reallocating queue"); - VIR_FREE(domEvent); return -1; } - evtQueue->events[evtQueue->count] = domEvent; + evtQueue->events[evtQueue->count] = event; evtQueue->count++; return 0; } + +void virDomainEventDispatchDefaultFunc(virConnectPtr conn, + virDomainEventPtr event, + virConnectDomainEventCallback cb, + void *cbopaque, + void *opaque ATTRIBUTE_UNUSED) +{ + virDomainPtr dom = virGetDomain(conn, event->name, event->uuid); + if (dom) { + dom->id = event->id; + (*cb)(conn, dom, event->type, event->detail, cbopaque); + virDomainFree(dom); + } +} + + +void virDomainEventDispatch(virDomainEventPtr event, + virDomainEventCallbackListPtr callbacks, + virDomainEventDispatchFunc dispatch, + void *opaque) +{ + int i; + /* Cache this now, since we may be dropping the lock, + and have more callbacks added. We're guarenteed not + to have any removed */ + int cbCount = callbacks->count; + + for (i = 0 ; i < cbCount ; i++) { + if (callbacks->callbacks[i] && + !callbacks->callbacks[i]->deleted) { + (*dispatch)(callbacks->callbacks[i]->conn, + event, + callbacks->callbacks[i]->cb, + callbacks->callbacks[i]->opaque, + opaque); + } + } +} + + +void virDomainEventQueueDispatch(virDomainEventQueuePtr queue, + virDomainEventCallbackListPtr callbacks, + virDomainEventDispatchFunc dispatch, + void *opaque) +{ + int i; + + for (i = 0 ; i < queue->count ; i++) { + virDomainEventDispatch(queue->events[i], callbacks, dispatch, opaque); + virDomainEventFree(queue->events[i]); + } + VIR_FREE(queue->events); + queue->count = 0; +} diff --git a/src/domain_event.h b/src/domain_event.h --- a/src/domain_event.h +++ b/src/domain_event.h @@ -22,16 +22,17 @@ #include "internal.h" - #ifndef __DOMAIN_EVENT_H__ #define __DOMAIN_EVENT_H__ + +#include "domain_conf.h" struct _virDomainEventCallback { virConnectPtr conn; virConnectDomainEventCallback cb; void *opaque; virFreeCallback freecb; - + int deleted; }; typedef struct _virDomainEventCallback virDomainEventCallback; typedef virDomainEventCallback *virDomainEventCallbackPtr; @@ -58,13 +59,20 @@ int virDomainEventCallbackListRemoveConn int virDomainEventCallbackListRemoveConn(virConnectPtr conn, virDomainEventCallbackListPtr cbList); +int virDomainEventCallbackListMarkDelete(virConnectPtr conn, + virDomainEventCallbackListPtr cbList, + virConnectDomainEventCallback callback); +int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList); + /** * Dispatching domain events that come in while * in a call / response rpc */ struct _virDomainEvent { - virDomainPtr dom; - int event; + int id; + char *name; + unsigned char uuid[VIR_UUID_BUFLEN]; + int type; int detail; }; typedef struct _virDomainEvent virDomainEvent; @@ -77,15 +85,40 @@ typedef struct _virDomainEventQueue virD typedef struct _virDomainEventQueue virDomainEventQueue; typedef virDomainEventQueue *virDomainEventQueuePtr; -int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, - virDomainPtr dom, - int event, - int detail); +virDomainEventQueuePtr virDomainEventQueueNew(void); + +virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail); +virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail); +virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail); +virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail); + +int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue, + virDomainEventPtr event); virDomainEventPtr -virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue); +virDomainEventQueuePop(virDomainEventQueuePtr evtQueue); +void virDomainEventFree(virDomainEventPtr event); void virDomainEventQueueFree(virDomainEventQueuePtr queue); +typedef void (*virDomainEventDispatchFunc)(virConnectPtr conn, + virDomainEventPtr event, + virConnectDomainEventCallback cb, + void *cbopaque, + void *opaque); +void virDomainEventDispatchDefaultFunc(virConnectPtr conn, + virDomainEventPtr event, + virConnectDomainEventCallback cb, + void *cbopaque, + void *opaque); + +void virDomainEventDispatch(virDomainEventPtr event, + virDomainEventCallbackListPtr cbs, + virDomainEventDispatchFunc dispatch, + void *opaque); +void virDomainEventQueueDispatch(virDomainEventQueuePtr queue, + virDomainEventCallbackListPtr cbs, + virDomainEventDispatchFunc dispatch, + void *opaque); #endif diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in +++ b/src/libvirt_sym.version.in @@ -382,9 +382,21 @@ LIBVIRT_PRIVATE_@VERSION@ { virDomainEventCallbackListFree; virDomainEventCallbackListRemove; virDomainEventCallbackListRemoveConn; + virDomainEventCallbackListMarkDelete; + virDomainEventCallbackListPurgeMarked; + virDomainEventQueueNew; virDomainEventQueueFree; - virDomainEventCallbackQueuePop; - virDomainEventCallbackQueuePush; + virDomainEventQueuePop; + virDomainEventQueuePush; + virDomainEventNew; + virDomainEventNewFromDom; + virDomainEventNewFromObj; + virDomainEventNewFromDef; + virDomainEventFree; + virDomainEventDispatchDefaultFunc; + virDomainEventDispatch; + virDomainEventQueueDispatch; + /* driver.h */ diff --git a/src/qemu_conf.h b/src/qemu_conf.h --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -71,6 +71,9 @@ struct qemud_driver { /* An array of callbacks */ virDomainEventCallbackListPtr domainEventCallbacks; + virDomainEventQueuePtr domainEventQueue; + int domainEventTimer; + int domainEventDispatching; }; /* Port numbers used for KVM migration. */ diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -115,10 +115,10 @@ static int qemudSetNonBlock(int fd) { } -static void qemudDomainEventDispatch (struct qemud_driver *driver, - virDomainObjPtr vm, - int event, - int detail); + +static void qemuDomainEventFlush(int timer, void *opaque); +static void qemuDomainEventQueue(struct qemud_driver *driver, + virDomainEventPtr event); static void qemudDispatchVMEvent(int watch, int fd, @@ -160,8 +160,12 @@ qemudAutostartConfigs(struct qemud_drive vm->def->name, err ? err->message : NULL); } else { - qemudDomainEventDispatch(driver, vm, VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); + virDomainEventPtr event = + virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + if (event) + qemuDomainEventQueue(driver, event); } } virDomainObjUnlock(vm); @@ -192,6 +196,12 @@ qemudStartup(void) { /* Init callback list */ if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0) goto out_of_memory; + if (!(qemu_driver->domainEventQueue = virDomainEventQueueNew())) + goto out_of_memory; + + if ((qemu_driver->domainEventTimer = + virEventAddTimeout(-1, qemuDomainEventFlush, qemu_driver, NULL)) < 0) + goto error; if (!uid) { if (asprintf(&qemu_driver->logDir, @@ -266,10 +276,14 @@ static void qemudNotifyLoadDomain(virDom { struct qemud_driver *driver = opaque; - if (newVM) - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_DEFINED, - VIR_DOMAIN_EVENT_DEFINED_ADDED); + if (newVM) { + virDomainEventPtr event = + virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_DEFINED, + VIR_DOMAIN_EVENT_DEFINED_ADDED); + if (event) + qemuDomainEventQueue(driver, event); + } } /** @@ -356,6 +370,10 @@ qemudShutdown(void) { /* Free domain callback list */ virDomainEventCallbackListFree(qemu_driver->domainEventCallbacks); + virDomainEventQueueFree(qemu_driver->domainEventQueue); + + if (qemu_driver->domainEventTimer != -1) + virEventRemoveTimeout(qemu_driver->domainEventTimer); if (qemu_driver->brctl) brShutdown(qemu_driver->brctl); @@ -1073,6 +1091,7 @@ qemudDispatchVMEvent(int watch, int fd, qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) { struct qemud_driver *driver = opaque; virDomainObjPtr vm = NULL; + virDomainEventPtr event = NULL; unsigned int i; int quit = 0, failed = 0; @@ -1102,12 +1121,12 @@ qemudDispatchVMEvent(int watch, int fd, } if (failed || quit) { + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + quit ? + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN : + VIR_DOMAIN_EVENT_STOPPED_FAILED); qemudShutdownVMDaemon(NULL, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - quit ? - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN : - VIR_DOMAIN_EVENT_STOPPED_FAILED); if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); @@ -1118,6 +1137,8 @@ cleanup: cleanup: if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); } @@ -1585,6 +1606,7 @@ static virDomainPtr qemudDomainCreate(vi virDomainDefPtr def; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; + virDomainEventPtr event = NULL; qemuDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) @@ -1621,9 +1643,10 @@ static virDomainPtr qemudDomainCreate(vi vm = NULL; goto cleanup; } - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1632,6 +1655,8 @@ cleanup: virDomainDefFree(def); if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return dom; } @@ -1642,6 +1667,7 @@ static int qemudDomainSuspend(virDomainP char *info; virDomainObjPtr vm; int ret = -1; + virDomainEventPtr event = NULL; qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); @@ -1664,16 +1690,22 @@ static int qemudDomainSuspend(virDomainP } vm->state = VIR_DOMAIN_PAUSED; qemudDebug("Reply %s", info); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_SUSPENDED, - VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); - VIR_FREE(info); - } - ret = 0; - -cleanup: - if (vm) - virDomainObjUnlock(vm); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_SUSPENDED, + VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); + VIR_FREE(info); + } + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + + if (event) { + qemuDriverLock(driver); + qemuDomainEventQueue(driver, event); + qemuDriverUnlock(driver); + } return ret; } @@ -1683,6 +1715,7 @@ static int qemudDomainResume(virDomainPt char *info; virDomainObjPtr vm; int ret = -1; + virDomainEventPtr event = NULL; qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); @@ -1706,16 +1739,21 @@ static int qemudDomainResume(virDomainPt } vm->state = VIR_DOMAIN_RUNNING; qemudDebug("Reply %s", info); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_RESUMED, - VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); - VIR_FREE(info); - } - ret = 0; - -cleanup: - if (vm) - virDomainObjUnlock(vm); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); + VIR_FREE(info); + } + ret = 0; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (event) { + qemuDriverLock(driver); + qemuDomainEventQueue(driver, event); + qemuDriverUnlock(driver); + } return ret; } @@ -1755,6 +1793,7 @@ static int qemudDomainDestroy(virDomainP struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; + virDomainEventPtr event = NULL; qemuDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); @@ -1765,9 +1804,9 @@ static int qemudDomainDestroy(virDomainP } qemudShutdownVMDaemon(dom->conn, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_DESTROYED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); @@ -1778,6 +1817,8 @@ cleanup: cleanup: if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; } @@ -2047,6 +2088,7 @@ static int qemudDomainSave(virDomainPtr char *xml = NULL; struct qemud_save_header header; int ret = -1; + virDomainEventPtr event = NULL; memset(&header, 0, sizeof(header)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); @@ -2148,9 +2190,9 @@ static int qemudDomainSave(virDomainPtr /* Shut it down */ qemudShutdownVMDaemon(dom->conn, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SAVED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SAVED); if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); @@ -2169,6 +2211,8 @@ cleanup: unlink(path); if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; } @@ -2406,6 +2450,7 @@ static int qemudDomainRestore(virConnect int ret = -1; char *xml = NULL; struct qemud_save_header header; + virDomainEventPtr event = NULL; qemuDriverLock(driver); /* Verify the header and read the XML */ @@ -2489,9 +2534,9 @@ static int qemudDomainRestore(virConnect goto cleanup; } - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_RESTORED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_RESTORED); /* If it was running before, resume it now. */ if (header.was_running) { @@ -2513,6 +2558,8 @@ cleanup: close(fd); if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; } @@ -2593,6 +2640,7 @@ static int qemudDomainStart(virDomainPtr struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; int ret = -1; + virDomainEventPtr event = NULL; qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -2606,13 +2654,18 @@ static int qemudDomainStart(virDomainPtr ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL); if (ret != -1) - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); - -cleanup: - if (vm) - virDomainObjUnlock(vm); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (event) { + qemuDriverLock(driver); + qemuDomainEventQueue(driver, event); + qemuDriverUnlock(driver); + } return ret; } @@ -2622,6 +2675,7 @@ static virDomainPtr qemudDomainDefine(vi virDomainDefPtr def; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; + virDomainEventPtr event = NULL; int newVM = 1; qemuDriverLock(driver); @@ -2651,18 +2705,20 @@ static virDomainPtr qemudDomainDefine(vi goto cleanup; } - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_DEFINED, - newVM ? - VIR_DOMAIN_EVENT_DEFINED_ADDED : - VIR_DOMAIN_EVENT_DEFINED_UPDATED); - - dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) dom->id = vm->def->id; - -cleanup: - if (vm) - virDomainObjUnlock(vm); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_DEFINED, + newVM ? + VIR_DOMAIN_EVENT_DEFINED_ADDED : + VIR_DOMAIN_EVENT_DEFINED_UPDATED); + + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) dom->id = vm->def->id; + +cleanup: + if (vm) + virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return dom; } @@ -2670,6 +2726,7 @@ static int qemudDomainUndefine(virDomain static int qemudDomainUndefine(virDomainPtr dom) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainEventPtr event = NULL; int ret = -1; qemuDriverLock(driver); @@ -2696,9 +2753,9 @@ static int qemudDomainUndefine(virDomain if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0) goto cleanup; - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_UNDEFINED, - VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_UNDEFINED, + VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); virDomainRemoveInactive(&driver->domains, vm); @@ -2708,6 +2765,8 @@ cleanup: cleanup: if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; } @@ -3703,41 +3762,69 @@ qemudDomainEventDeregister (virConnectPt int ret; qemuDriverLock(driver); - ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, - callback); - qemuDriverUnlock(driver); - - return ret; -} - -static void qemudDomainEventDispatch (struct qemud_driver *driver, - virDomainObjPtr vm, - int event, - int detail) -{ - int i; - virDomainEventCallbackListPtr cbList; - - cbList = driver->domainEventCallbacks; - - for(i=0 ; i < cbList->count ; i++) { - if(cbList->callbacks[i] && cbList->callbacks[i]->cb) { - virConnectPtr conn = cbList->callbacks[i]->conn; - virDomainPtr dom = virGetDomain(conn, vm->def->name, - vm->def->uuid); - if (dom) { - dom->id = virDomainIsActive(vm) ? vm->def->id : -1; - DEBUG("Dispatching callback %p %p event %d detail %d", - cbList->callbacks[i], - cbList->callbacks[i]->cb, event, detail); - cbList->callbacks[i]->cb(cbList->callbacks[i]->conn, - dom, event, detail, - cbList->callbacks[i]->opaque); - virDomainFree(dom); - } - } - } - + if (driver->domainEventDispatching) + ret = virDomainEventCallbackListMarkDelete(conn, driver->domainEventCallbacks, + callback); + else + ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, + callback); + qemuDriverUnlock(driver); + + return ret; +} + +static void qemuDomainEventDispatchFunc(virConnectPtr conn, + virDomainEventPtr event, + virConnectDomainEventCallback cb, + void *cbopaque, + void *opaque) +{ + struct qemud_driver *driver = opaque; + + /* Drop the lock whle dispatching, for sake of re-entrancy */ + qemuDriverUnlock(driver); + virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL); + qemuDriverLock(driver); +} + +static void qemuDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque) +{ + struct qemud_driver *driver = opaque; + virDomainEventQueue tempQueue; + + qemuDriverLock(driver); + + driver->domainEventDispatching = 1; + + /* Copy the queue, so we're reentrant safe */ + tempQueue.count = driver->domainEventQueue->count; + tempQueue.events = driver->domainEventQueue->events; + driver->domainEventQueue->count = 0; + driver->domainEventQueue->events = NULL; + + virEventUpdateTimeout(driver->domainEventTimer, -1); + virDomainEventQueueDispatch(&tempQueue, + driver->domainEventCallbacks, + qemuDomainEventDispatchFunc, + driver); + + /* Purge any deleted callbacks */ + virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks); + + driver->domainEventDispatching = 0; + qemuDriverUnlock(driver); +} + + +/* driver must be locked before calling */ +static void qemuDomainEventQueue(struct qemud_driver *driver, + virDomainEventPtr event) +{ + if (virDomainEventQueuePush(driver->domainEventQueue, + event) < 0) + virDomainEventFree(event); + if (qemu_driver->domainEventQueue->count == 1) + virEventUpdateTimeout(driver->domainEventTimer, 0); } /* Migration support. */ @@ -3765,6 +3852,7 @@ qemudDomainMigratePrepare2 (virConnectPt char hostname [HOST_NAME_MAX+1]; char migrateFrom [64]; const char *p; + virDomainEventPtr event = NULL; int ret = -1;; *uri_out = NULL; @@ -3886,9 +3974,10 @@ qemudDomainMigratePrepare2 (virConnectPt } goto cleanup; } - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_MIGRATED); + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_MIGRATED); ret = 0; cleanup: @@ -3898,6 +3987,8 @@ cleanup: } if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; } @@ -3914,6 +4005,7 @@ qemudDomainMigratePerform (virDomainPtr { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; + virDomainEventPtr event = NULL; char *safe_uri; char cmd[HOST_NAME_MAX+50]; char *info = NULL; @@ -3940,9 +4032,12 @@ qemudDomainMigratePerform (virDomainPtr DEBUG ("stop reply: %s", info); VIR_FREE(info); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_SUSPENDED, - VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_SUSPENDED, + VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED); + if (event) + qemuDomainEventQueue(driver, event); + event = NULL; } if (resource > 0) { @@ -3981,9 +4076,10 @@ qemudDomainMigratePerform (virDomainPtr /* Clean up the source domain. */ qemudShutdownVMDaemon (dom->conn, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_MIGRATED); + + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_MIGRATED); if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; @@ -3994,6 +4090,8 @@ cleanup: VIR_FREE(info); if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; } @@ -4011,6 +4109,7 @@ qemudDomainMigrateFinish2 (virConnectPtr struct qemud_driver *driver = dconn->privateData; virDomainObjPtr vm; virDomainPtr dom = NULL; + virDomainEventPtr event = NULL; char *info = NULL; qemuDriverLock(driver); @@ -4028,14 +4127,14 @@ qemudDomainMigrateFinish2 (virConnectPtr dom = virGetDomain (dconn, vm->def->name, vm->def->uuid); VIR_FREE(info); vm->state = VIR_DOMAIN_RUNNING; - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_RESUMED, - VIR_DOMAIN_EVENT_RESUMED_MIGRATED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_RESUMED, + VIR_DOMAIN_EVENT_RESUMED_MIGRATED); } else { qemudShutdownVMDaemon (dconn, driver, vm); - qemudDomainEventDispatch(driver, vm, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_FAILED); + event = virDomainEventNewFromObj(vm, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_FAILED); if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; @@ -4045,6 +4144,8 @@ cleanup: cleanup: if (vm) virDomainObjUnlock(vm); + if (event) + qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return dom; } diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -5484,59 +5484,62 @@ remoteRegister (void) * * Read the event data off the wire */ -static int -remoteDomainReadEvent(virConnectPtr conn, XDR *xdr, - virDomainPtr *dom, int *event, int *detail) +static virDomainEventPtr +remoteDomainReadEvent(virConnectPtr conn, XDR *xdr) { remote_domain_event_ret ret; + virDomainPtr dom; + virDomainEventPtr event = NULL; memset (&ret, 0, sizeof ret); /* unmarshall parameters, and process it*/ if (! xdr_remote_domain_event_ret(xdr, &ret) ) { error (conn, VIR_ERR_RPC, _("remoteDomainProcessEvent: unmarshalling ret")); - return -1; - } - - *dom = get_nonnull_domain(conn,ret.dom); - *event = ret.event; - *detail = ret.detail; - - return 0; + return NULL; + } + + dom = get_nonnull_domain(conn,ret.dom); + if (!dom) + return NULL; + + event = virDomainEventNewFromDom(dom, ret.event, ret.detail); + + virDomainFree(dom); + return event; } static void remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr) { - virDomainPtr dom; - int event, detail, i; - struct private_data *priv = conn->privateData; - - if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) { - DEBUG0("Calling domain event callbacks (no queue)"); - for(i=0 ; i < priv->callbackList->count ; i++) { - if (priv->callbackList->callbacks[i] ) - priv->callbackList->callbacks[i]->cb( - conn, dom, event, detail, - priv->callbackList->callbacks[i]->opaque); - } - } + struct private_data *priv = conn->privateData; + virDomainEventPtr event; + + event = remoteDomainReadEvent(conn, xdr); + if (!event) + return; + + DEBUG0("Calling domain event callbacks (no queue)"); + virDomainEventDispatch(event, priv->callbackList, + virDomainEventDispatchDefaultFunc, NULL); + virDomainEventFree(event); } static void remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr) { - virDomainPtr dom; - int event, detail; - struct private_data *priv = conn->privateData; - - if(!remoteDomainReadEvent(conn, xdr, &dom, &event, &detail)) - { - if( virDomainEventCallbackQueuePush(priv->domainEvents, - dom, event, detail) < 0 ) { - DEBUG("%s", "Error adding event to queue"); - } - } + struct private_data *priv = conn->privateData; + virDomainEventPtr event; + + event = remoteDomainReadEvent(conn, xdr); + if (!event) + return; + + if (virDomainEventQueuePush(priv->domainEvents, + event) < 0) + DEBUG0("Error adding event to queue"); + + virDomainEventFree(event); } /** remoteDomainEventFired: @@ -5618,26 +5621,10 @@ void void remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) { - int i; - virDomainEventPtr domEvent; - void *user_data = NULL; virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; - while( (domEvent = virDomainEventCallbackQueuePop(priv->domainEvents)) ) { - DEBUG(" Flushing %p", domEvent); - for (i=0 ; i < priv->callbackList->count ; i++) { - if( priv->callbackList->callbacks[i] ) { - user_data = priv->callbackList->callbacks[i]->opaque; - priv->callbackList->callbacks[i]->cb(domEvent->dom->conn, - domEvent->dom, - domEvent->event, - domEvent->detail, - user_data); - } - } - VIR_FREE(domEvent); - } - + virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList, + virDomainEventDispatchDefaultFunc, NULL); virEventUpdateTimeout(priv->eventFlushTimer, -1); } diff --git a/src/xen_inotify.c b/src/xen_inotify.c --- a/src/xen_inotify.c +++ b/src/xen_inotify.c @@ -92,30 +92,33 @@ struct xenUnifiedDriver xenInotifyDriver NULL, /* domainSetSchedulerParameters */ }; -static virDomainPtr -xenInotifyXenCacheLookup(virConnectPtr conn, const char *filename) { +static int +xenInotifyXenCacheLookup(const char *filename, + char **name, unsigned char *uuid) { xenXMConfCachePtr entry; - virDomainPtr dom; if (!(entry = virHashLookup(xenXMGetConfigCache(), filename))) { DEBUG("No config found for %s", filename); - return NULL; + return -1; } - if(!(dom = virGetDomain(conn, entry->def->name, - (unsigned char*)entry->def->uuid))) { + *name = strdup(entry->def->name); + memcpy(uuid, entry->def->uuid, VIR_UUID_BUFLEN); + + if (!*name) { DEBUG0("Error getting dom from def"); - return NULL; + return -1; } - return dom; + return 0; } -static virDomainPtr -xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename) { +static int +xenInotifyXendDomainsDirLookup(virConnectPtr conn, const char *filename, + char **name, unsigned char *uuid) { int i; virDomainPtr dom; const char *uuid_str; - unsigned char uuid[VIR_UUID_BUFLEN]; + unsigned char rawuuid[VIR_UUID_BUFLEN]; /* xend is managing domains. we will get * a filename in the manner: @@ -123,57 +126,70 @@ xenInotifyXendDomainsDirLookup(virConnec */ uuid_str = filename + strlen(LIBVIRTD_DOMAINS_DIR) + 1; - if (virUUIDParse(uuid_str, uuid) < 0) { + if (virUUIDParse(uuid_str, rawuuid) < 0) { virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, "parsing uuid %s", uuid_str); - return (NULL); + return -1; } /* call directly into xend here, as driver may not yet be set during open while we are building our initial list of domains */ DEBUG("Looking for dom with uuid: %s", uuid_str); - if(!(dom = xenDaemonLookupByUUID(conn, uuid))) { + /* XXX Should not have to go via a virDomainPtr obj instance */ + if(!(dom = xenDaemonLookupByUUID(conn, rawuuid))) { /* If we are here, the domain has gone away. search for, and create a domain from the stored list info */ for (i=0; i<configInfoList->count; i++) { if (!memcmp(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN)) { - if(!(dom = virGetDomain(conn, configInfoList->doms[i]->name, - configInfoList->doms[i]->uuid))) { + *name = strdup(configInfoList->doms[i]->name); + if (!*name) { virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, "finding dom for %s", uuid_str); - return NULL; + return -1; } + memcpy(uuid, configInfoList->doms[i]->uuid, VIR_UUID_BUFLEN); DEBUG0("Found dom on list"); - return dom; + return 0; } } virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("finding dom on config list")); - return NULL; + "%s", _("finding dom on config list")); + return -1; } + if (!(*name = strdup(dom->name))) + return -1; + memcpy(uuid, dom->uuid, VIR_UUID_BUFLEN); + virDomainFree(dom); /* succeeded too find domain by uuid */ - return dom; + return 0; } -static virDomainPtr -xenInotifyDomainLookup(virConnectPtr conn, const char *filename) { - virDomainPtr dom; - virDomainInfo info; +static int +xenInotifyDomainLookup(virConnectPtr conn, + const char *filename, + char **name, unsigned char *uuid) { + if (useXenConfigCache) + return xenInotifyXenCacheLookup(filename, name, uuid); + else + return xenInotifyXendDomainsDirLookup(conn, filename, name, uuid); +} - dom = useXenConfigCache ? xenInotifyXenCacheLookup(conn, filename) : - xenInotifyXendDomainsDirLookup(conn, filename); +static virDomainEventPtr +xenInotifyDomainEventFromFile(virConnectPtr conn, + const char *filename, + int type, int detail) { + virDomainEventPtr event; + char *name = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; - if(dom) { - if ( (useXenConfigCache ? xenXMDomainGetInfo(dom, &info) : - xenDaemonDomainGetInfo(dom, &info)) < 0) - dom->id = -1; - else - dom->id = (info.state == VIR_DOMAIN_SHUTOFF) ? -1 : dom->id; - return dom; - } - return NULL; + if (xenInotifyDomainLookup(conn, filename, &name, uuid) < 0) + return NULL; + + event = virDomainEventNew(-1, name, uuid, type, detail); + VIR_FREE(name); + return event; } static int @@ -215,21 +231,22 @@ static int static int xenInotifyXendDomainsDirAddEntry(virConnectPtr conn, const char *fname) { - virDomainPtr dom = xenInotifyDomainLookup(conn, fname); - if(!dom) { + char *name = NULL; + unsigned char uuid[VIR_UUID_BUFLEN]; + if (xenInotifyDomainLookup(conn, fname, &name, uuid) < 0) { virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("Error looking up domain")); + "%s", _("Error looking up domain")); return -1; } if( xenUnifiedAddDomainInfo(configInfoList, - dom->id, dom->name, dom->uuid) < 0) { + -1, name, uuid) < 0) { virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config cache")); - virUnrefDomain(dom); + VIR_FREE(name); return -1; } - virUnrefDomain(dom); + VIR_FREE(name); return 0; } @@ -260,7 +277,6 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUS char *tmp, *name; virConnectPtr conn = (virConnectPtr) data; xenUnifiedPrivatePtr priv = NULL; - virDomainPtr dom = NULL; DEBUG0("got inotify event"); @@ -300,16 +316,15 @@ reread: snprintf(fname, 1024, "%s/%s", configDir, name); if (e->mask & (IN_DELETE | IN_MOVED_FROM)) { - if (!(dom = xenInotifyDomainLookup(conn, fname))) { + virDomainEventPtr event = + xenInotifyDomainEventFromFile(conn, fname, + VIR_DOMAIN_EVENT_UNDEFINED, + VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); + if (!event) + xenUnifiedDomainEventDispatch(conn->privateData, event); + else virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("looking up dom")); - continue; - } - - xenUnifiedDomainEventDispatch(conn->privateData, dom, - VIR_DOMAIN_EVENT_UNDEFINED, - VIR_DOMAIN_EVENT_UNDEFINED_REMOVED); - + "%s", _("looking up dom")); if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) { virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, @@ -317,21 +332,23 @@ reread: return; } } else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) { + virDomainEventPtr event; if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) { virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Error adding file to config cache")); return; } - if (!(dom = xenInotifyDomainLookup(conn, fname))) { + event = xenInotifyDomainEventFromFile(conn, fname, + VIR_DOMAIN_EVENT_DEFINED, + VIR_DOMAIN_EVENT_DEFINED_ADDED); + + if (event) + xenUnifiedDomainEventDispatch(conn->privateData, event); + else virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR, - "%s", _("looking up dom")); - continue; - } + "%s", _("looking up dom")); - xenUnifiedDomainEventDispatch(conn->privateData, dom, - VIR_DOMAIN_EVENT_DEFINED, - VIR_DOMAIN_EVENT_DEFINED_ADDED); } } diff --git a/src/xen_unified.c b/src/xen_unified.c --- a/src/xen_unified.c +++ b/src/xen_unified.c @@ -1583,28 +1583,14 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDom * */ void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv, - virDomainPtr dom, - int event, - int detail) + virDomainEventPtr event) { - int i; - virDomainEventCallbackListPtr cbList; + if (!priv || !priv->domainEventCallbacks) + return; - if(!priv) return; - - cbList = priv->domainEventCallbacks; - if(!cbList) return; - - for(i=0 ; i < cbList->count ; i++) { - if(cbList->callbacks[i] && cbList->callbacks[i]->cb) { - if (dom) { - DEBUG("Dispatching callback %p %p event %d", - cbList->callbacks[i], - cbList->callbacks[i]->cb, event); - cbList->callbacks[i]->cb(cbList->callbacks[i]->conn, - dom, event, detail, - cbList->callbacks[i]->opaque); - } - } - } + virDomainEventDispatch(event, + priv->domainEventCallbacks, + virDomainEventDispatchDefaultFunc, + NULL); + virDomainEventFree(event); } diff --git a/src/xen_unified.h b/src/xen_unified.h --- a/src/xen_unified.h +++ b/src/xen_unified.h @@ -182,9 +182,7 @@ int xenUnifiedRemoveDomainInfo(xenUnifi int id, char *name, unsigned char *uuid); void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv, - virDomainPtr dom, - int event, - int detail); + virDomainEventPtr event); unsigned long xenUnifiedVersion(void); #endif /* __VIR_XEN_UNIFIED_H__ */ diff --git a/src/xs_internal.c b/src/xs_internal.c --- a/src/xs_internal.c +++ b/src/xs_internal.c @@ -1215,7 +1215,7 @@ retry: } if (!found) { - virDomainPtr dom; + virDomainEventPtr event; char *name; unsigned char uuid[VIR_UUID_BUFLEN]; @@ -1229,21 +1229,15 @@ retry: continue; } - dom = virGetDomain(conn, name, uuid); - if (dom) { - dom->id = new_domids[i]; + event = virDomainEventNew(new_domids[i], name, uuid, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); + if (event) + xenUnifiedDomainEventDispatch(priv, event); - /* This domain was not in the old list. Emit an event */ - xenUnifiedDomainEventDispatch(priv, dom, - VIR_DOMAIN_EVENT_STARTED, - VIR_DOMAIN_EVENT_STARTED_BOOTED); - - /* Add to the list */ - xenUnifiedAddDomainInfo(activeDomainList, - new_domids[i], name, uuid); - - virUnrefDomain(dom); - } + /* Add to the list */ + xenUnifiedAddDomainInfo(activeDomainList, + new_domids[i], name, uuid); VIR_FREE(name); } @@ -1299,24 +1293,22 @@ retry: } if (!found) { - virDomainPtr dom = virGetDomain(conn, - activeDomainList->doms[j]->name, - activeDomainList->doms[j]->uuid); - if(dom) { - dom->id = -1; - /* This domain was not in the new list. Emit an event */ - xenUnifiedDomainEventDispatch(priv, dom, - VIR_DOMAIN_EVENT_STOPPED, - VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); - /* Remove from the list */ - xenUnifiedRemoveDomainInfo(activeDomainList, - activeDomainList->doms[j]->id, - activeDomainList->doms[j]->name, - activeDomainList->doms[j]->uuid); + virDomainEventPtr event = + virDomainEventNew(-1, + activeDomainList->doms[j]->name, + activeDomainList->doms[j]->uuid, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); + if (event) + xenUnifiedDomainEventDispatch(priv, event); - virUnrefDomain(dom); - removed = 1; - } + /* Remove from the list */ + xenUnifiedRemoveDomainInfo(activeDomainList, + activeDomainList->doms[j]->id, + activeDomainList->doms[j]->name, + activeDomainList->doms[j]->uuid); + + removed = 1; } } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:47:21PM +0000, Daniel P. Berrange wrote:
This patch adds thread safety to the domain events processing code of the QEMU driver. This entailed rather a large refactoring of the domain events code and its quite complicated to explain.
- A convenient helper is added for creating event queues
virDomainEventQueuePtr virDomainEventQueueNew(void);
- Convenient helpers are added for creating virDomainEventPtr instances from a variety of sources - each driver has different needs
virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned char *uuid, int type, int detail); virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int detail); virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, int detail); virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, int detail);
- The virDomainEvent struct held a reference to a virDomainPtr object. This is replaced with a direct triple (id, name, uuid), avoiding the need to instantiate virDomainPtr objects deep inside the QEMU code.
- The virDomainEventQueuePush() method is changed to take a virDomainEventPtr object, rather than a virDomainPtr object
These last two changes are important to allow safe re-entrancy of the event dispatch process. The virDomainEventPtr instance can be allocated within a critical section lockde on the virDomainObjPtr instance, while the event is queued outside the critical section, while only the driver lock is held. Without this we'd have to hold the per-driver lock over a much larger block of code which hurts concurrancy.
The QEMU driver cannot directly dispatch events, instead we have to follow the remote driver and maintain a queue of pending events, and use a timer to flush them. Again this is neccessary to improve concurrency & provide safe re-entrancy.
Since we have two driver maintaining queues of evnts I add more helper functions to allow code sharing
- Send a single vent to a list of callbacks:
void virDomainEventDispatch(virDomainEventPtr event, virDomainEventCallbackListPtr cbs, virDomainEventDispatchFunc dispatch, void *opaque);
- Send a set of queued events to a list of callbacks
void virDomainEventQueueDispatch(virDomainEventQueuePtr queue, virDomainEventCallbackListPtr cbs, virDomainEventDispatchFunc dispatch, void *opaque);
The virDomainEventDispatchFunc is what is invoked to finally dispatch a single event, to a single registered callback. The default impl just invokes the callback directly. The QEMU driver, however, uses a wrapper which first releases its driver lock, invokes the callback, and then re-aquires the lock.
As a further complication it is not safe for virDomainEventUnregister to actually remove the callback from the list directly. Instead we add a helper that simply marks it as removed, and then actually purge it from a safe point in the code, when its guarenteed that the driver isn't in the middle of dispatching.
As well as making the QEMU driver thread safe, this also takes the opportunity to refactor the Xen / remote drivers to use more helpers
I must admit I'm a bit lost ...
@@ -192,14 +291,18 @@ virDomainEventQueueFree(virDomainEventQu virDomainEventQueueFree(virDomainEventQueuePtr queue) { int i; - for ( i=0 ; i<queue->count ; i++ ) { - VIR_FREE(queue->events[i]); + if (!queue) + return; + + for (i = 0; i < queue->count ; i++) { + virDomainEventFree(queue->events[i]); } + VIR_FREE(queue->events); VIR_FREE(queue); }
okay we were leaking queue->events here ! [...]
struct _virDomainEventCallback { virConnectPtr conn; virConnectDomainEventCallback cb; void *opaque; virFreeCallback freecb; - + int deleted; };
Yup, I'm lost here ... seems we are making something asynchronous here
struct _virDomainEvent { - virDomainPtr dom; - int event; + int id; + char *name; + unsigned char uuid[VIR_UUID_BUFLEN]; + int type; int detail; };
Okay we don't want to held references anymore. But the lookups will require search and locking, I completely fail to build a mental representation where I can figure out why we don't risk deadlocks there. There is a risk of lock reentrancy I'm sure but I can't see the model. [...]
diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in +++ b/src/libvirt_sym.version.in @@ -382,9 +382,21 @@ LIBVIRT_PRIVATE_@VERSION@ { virDomainEventCallbackListFree; virDomainEventCallbackListRemove; virDomainEventCallbackListRemoveConn; + virDomainEventCallbackListMarkDelete; + virDomainEventCallbackListPurgeMarked; + virDomainEventQueueNew; virDomainEventQueueFree; - virDomainEventCallbackQueuePop; - virDomainEventCallbackQueuePush; + virDomainEventQueuePop; + virDomainEventQueuePush; + virDomainEventNew; + virDomainEventNewFromDom; + virDomainEventNewFromObj; + virDomainEventNewFromDef; + virDomainEventFree; + virDomainEventDispatchDefaultFunc; + virDomainEventDispatch; + virDomainEventQueueDispatch; +
reminds me I need to make room in libvirt_sym.version.in for APIs introduced post 0.5.0, I have the (trivial) patch, will post it asap. I'm lost, I failed to figure out most of the remaining of this patch, but don't consider this a blocker, ... Still I'm worried about the increased complexity of the code and making harder for people to contribute patches or drivers. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch reduces the number of exit paths in the LXC driver, much like the earlier patches for other drivers lxc_driver.c | 278 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 154 insertions(+), 124 deletions(-) Daniel diff --git a/src/lxc_driver.c b/src/lxc_driver.c --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -103,65 +103,68 @@ static virDomainPtr lxcDomainLookupByID( static virDomainPtr lxcDomainLookupByID(virConnectPtr conn, int id) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, id); - virDomainPtr dom; + lxc_driver_t *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByID(&driver->domains, id); if (!vm) { lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) { + if (dom) dom->id = vm->def->id; - } +cleanup: return dom; } static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid); - virDomainPtr dom; + lxc_driver_t *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByUUID(&driver->domains, uuid); if (!vm) { lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) { + if (dom) dom->id = vm->def->id; - } +cleanup: return dom; } static virDomainPtr lxcDomainLookupByName(virConnectPtr conn, const char *name) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - virDomainObjPtr vm = virDomainFindByName(&driver->domains, name); - virDomainPtr dom; + lxc_driver_t *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByName(&driver->domains, name); if (!vm) { lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) { + if (dom) dom->id = vm->def->id; - } +cleanup: return dom; } static int lxcListDomains(virConnectPtr conn, int *ids, int nids) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; + lxc_driver_t *driver = conn->privateData; int got = 0, i; for (i = 0 ; i < driver->domains.count && got < nids ; i++) @@ -170,8 +173,9 @@ static int lxcListDomains(virConnectPtr return got; } + static int lxcNumDomains(virConnectPtr conn) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; + lxc_driver_t *driver = conn->privateData; int n = 0, i; for (i = 0 ; i < driver->domains.count ; i++) @@ -183,7 +187,7 @@ static int lxcNumDomains(virConnectPtr c static int lxcListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; + lxc_driver_t *driver = conn->privateData; int got = 0, i; for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { @@ -206,7 +210,7 @@ static int lxcListDefinedDomains(virConn static int lxcNumDefinedDomains(virConnectPtr conn) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; + lxc_driver_t *driver = conn->privateData; int n = 0, i; for (i = 0 ; i < driver->domains.count ; i++) @@ -220,86 +224,91 @@ static int lxcNumDefinedDomains(virConne static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; - virDomainDefPtr def; + lxc_driver_t *driver = conn->privateData; + virDomainDefPtr def = NULL; virDomainObjPtr vm; - virDomainPtr dom; + virDomainPtr dom = NULL; if (!(def = virDomainDefParseString(conn, driver->caps, xml))) - return NULL; + goto cleanup; if ((def->nets != NULL) && !(driver->have_netns)) { lxcError(conn, NULL, VIR_ERR_NO_SUPPORT, "%s", _("System lacks NETNS support")); - virDomainDefFree(def); - return NULL; + goto cleanup; } - if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { - virDomainDefFree(def); - return NULL; - } + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) + goto cleanup; + def = NULL; vm->persistent = 1; if (virDomainSaveConfig(conn, driver->configDir, vm->newDef ? vm->newDef : vm->def) < 0) { virDomainRemoveInactive(&driver->domains, vm); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) { + if (dom) dom->id = vm->def->id; - } +cleanup: + virDomainDefFree(def); return dom; } static int lxcDomainUndefine(virDomainPtr dom) { - lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (virDomainIsActive(vm)) { lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain")); - return -1; + goto cleanup; } if (!vm->persistent) { lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot undefine transient domain")); - return -1; + goto cleanup; } if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, - vm) <0) - return -1; + vm) < 0) + goto cleanup; virDomainRemoveInactive(&driver->domains, vm); + ret = 0; - return 0; +cleanup: + return ret; } static int lxcDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { - lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } info->state = vm->state; @@ -313,40 +322,52 @@ static int lxcDomainGetInfo(virDomainPtr info->maxMem = vm->def->maxmem; info->memory = vm->def->memory; info->nrVirtCpu = 1; + ret = 0; - return 0; +cleanup: + return ret; } static char *lxcGetOSType(virDomainPtr dom) { - lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *ret = NULL; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - return strdup(vm->def->os.type); + ret = strdup(vm->def->os.type); + +cleanup: + return ret; } static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { - lxc_driver_t *driver = (lxc_driver_t *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *ret = NULL; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - return virDomainDefFormat(dom->conn, - (flags & VIR_DOMAIN_XML_INACTIVE) && - vm->newDef ? vm->newDef : vm->def, - flags); + ret = virDomainDefFormat(dom->conn, + (flags & VIR_DOMAIN_XML_INACTIVE) && + vm->newDef ? vm->newDef : vm->def, + flags); + +cleanup: + return ret; } @@ -855,27 +876,27 @@ cleanup: */ static int lxcDomainStart(virDomainPtr dom) { - int rc = -1; - virConnectPtr conn = dom->conn; - lxc_driver_t *driver = (lxc_driver_t *)(conn->privateData); - virDomainObjPtr vm = virDomainFindByName(&driver->domains, dom->name); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByName(&driver->domains, dom->name); if (!vm) { - lxcError(conn, dom, VIR_ERR_INVALID_DOMAIN, + lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, _("no domain named %s"), dom->name); goto cleanup; } if ((vm->def->nets != NULL) && !(driver->have_netns)) { - lxcError(conn, NULL, VIR_ERR_NO_SUPPORT, + lxcError(dom->conn, NULL, VIR_ERR_NO_SUPPORT, "%s", _("System lacks NETNS support")); goto cleanup; } - rc = lxcVmStart(conn, driver, vm); + ret = lxcVmStart(dom->conn, driver, vm); cleanup: - return rc; + return ret; } /** @@ -892,38 +913,36 @@ lxcDomainCreateAndStart(virConnectPtr co lxcDomainCreateAndStart(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { - lxc_driver_t *driver = (lxc_driver_t *)conn->privateData; + lxc_driver_t *driver = conn->privateData; virDomainObjPtr vm; virDomainDefPtr def; virDomainPtr dom = NULL; if (!(def = virDomainDefParseString(conn, driver->caps, xml))) - goto return_point; + goto cleanup; if ((def->nets != NULL) && !(driver->have_netns)) { - virDomainDefFree(def); lxcError(conn, NULL, VIR_ERR_NO_SUPPORT, "%s", _("System lacks NETNS support")); - goto return_point; + goto cleanup; } - if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { - virDomainDefFree(def); - goto return_point; - } + if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) + goto cleanup; + def = NULL; if (lxcVmStart(conn, driver, vm) < 0) { virDomainRemoveInactive(&driver->domains, vm); - goto return_point; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (dom) { + if (dom) dom->id = vm->def->id; - } -return_point: +cleanup: + virDomainDefFree(def); return dom; } @@ -937,16 +956,21 @@ return_point: */ static int lxcDomainShutdown(virDomainPtr dom) { - lxc_driver_t *driver = (lxc_driver_t*)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, _("no domain with id %d"), dom->id); - return -1; + goto cleanup; } - return lxcVmTerminate(dom->conn, driver, vm, 0); + ret = lxcVmTerminate(dom->conn, driver, vm, 0); + +cleanup: + return ret; } @@ -960,16 +984,21 @@ static int lxcDomainShutdown(virDomainPt */ static int lxcDomainDestroy(virDomainPtr dom) { - lxc_driver_t *driver = (lxc_driver_t*)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + lxc_driver_t *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, _("no domain with id %d"), dom->id); - return -1; + goto cleanup; } - return lxcVmTerminate(dom->conn, driver, vm, SIGKILL); + ret = lxcVmTerminate(dom->conn, driver, vm, SIGKILL); + +cleanup: + return ret; } static int lxcCheckNetNsSupport(void) @@ -1146,86 +1175,87 @@ static char *lxcGetSchedulerType(virDoma return strdup("posix"); } -static int lxcSetSchedulerParameters(virDomainPtr _domain, +static int lxcSetSchedulerParameters(virDomainPtr domain, virSchedParameterPtr params, int nparams) { int i; - int rc; - virCgroupPtr group; - virDomainObjPtr domain; + virCgroupPtr group = NULL; + virDomainObjPtr vm = NULL; + int ret = -1; if (virCgroupHaveSupport() != 0) - return 0; + goto cleanup; - domain = virDomainFindByUUID(&lxc_driver->domains, _domain->uuid); - if (domain == NULL) { - lxcError(NULL, _domain, VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), _domain->uuid); - return -EINVAL; + vm = virDomainFindByUUID(&lxc_driver->domains, domain->uuid); + if (vm == NULL) { + lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), domain->uuid); + goto cleanup; } - rc = virCgroupForDomain(domain->def, "lxc", &group); - if (rc != 0) - return rc; + if (virCgroupForDomain(vm->def, "lxc", &group) != 0) + goto cleanup; for (i = 0; i < nparams; i++) { virSchedParameterPtr param = ¶ms[i]; if (STREQ(param->field, "cpu_shares")) { - rc = virCgroupSetCpuShares(group, params[i].value.ui); + if (virCgroupSetCpuShares(group, params[i].value.ui) != 0) + goto cleanup; } else { - lxcError(NULL, _domain, VIR_ERR_INVALID_ARG, + lxcError(NULL, domain, VIR_ERR_INVALID_ARG, _("Invalid parameter `%s'"), param->field); - rc = -ENOENT; - goto out; + goto cleanup; } } + ret = 0; - rc = 0; -out: +cleanup: virCgroupFree(&group); - return rc; + return ret; } -static int lxcGetSchedulerParameters(virDomainPtr _domain, +static int lxcGetSchedulerParameters(virDomainPtr domain, virSchedParameterPtr params, int *nparams) { - int rc = 0; - virCgroupPtr group; - virDomainObjPtr domain; + virCgroupPtr group = NULL; + virDomainObjPtr vm = NULL; unsigned long val; + int ret = -1; if (virCgroupHaveSupport() != 0) - return 0; + goto cleanup; if ((*nparams) != 1) { - lxcError(NULL, _domain, VIR_ERR_INVALID_ARG, + lxcError(NULL, domain, VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); - return -1; + goto cleanup; } - domain = virDomainFindByUUID(&lxc_driver->domains, _domain->uuid); - if (domain == NULL) { - lxcError(NULL, _domain, VIR_ERR_INTERNAL_ERROR, - _("No such domain %s"), _domain->uuid); - return -ENOENT; + vm = virDomainFindByUUID(&lxc_driver->domains, domain->uuid); + if (vm == NULL) { + lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR, + _("No such domain %s"), domain->uuid); + goto cleanup; } - rc = virCgroupForDomain(domain->def, "lxc", &group); - if (rc != 0) - return rc; + if (virCgroupForDomain(vm->def, "lxc", &group) != 0) + goto cleanup; - rc = virCgroupGetCpuShares(group, &val); + if (virCgroupGetCpuShares(group, &val) != 0) + goto cleanup; params[0].value.ul = val; strncpy(params[0].field, "cpu_shares", sizeof(params[0].field)); params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG; + ret = 0; + +cleanup: virCgroupFree(&group); - - return rc; + return ret; } /* Function Tables */ -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:49:23PM +0000, Daniel P. Berrange wrote:
This patch reduces the number of exit paths in the LXC driver, much like the earlier patches for other drivers
Okay, looks simple, +1 ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the LXC driver thread safe following the same pattern as the Test/QEMU drivers lxc_conf.h | 2 lxc_driver.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 151 insertions(+), 38 deletions(-) Daniel diff --git a/src/lxc_conf.h b/src/lxc_conf.h --- a/src/lxc_conf.h +++ b/src/lxc_conf.h @@ -36,6 +36,8 @@ typedef struct __lxc_driver lxc_driver_t; struct __lxc_driver { + PTHREAD_MUTEX_T(lock); + virCapsPtr caps; virDomainObjList domains; diff --git a/src/lxc_driver.c b/src/lxc_driver.c --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -54,6 +54,16 @@ static lxc_driver_t *lxc_driver = NULL; static lxc_driver_t *lxc_driver = NULL; /* Functions */ + +static void lxcDriverLock(lxc_driver_t *driver) +{ + pthread_mutex_lock(&driver->lock); +} +static void lxcDriverUnlock(lxc_driver_t *driver) +{ + pthread_mutex_unlock(&driver->lock); +} + static int lxcProbe(void) { @@ -107,7 +117,10 @@ static virDomainPtr lxcDomainLookupByID( virDomainObjPtr vm; virDomainPtr dom = NULL; + lxcDriverLock(driver); vm = virDomainFindByID(&driver->domains, id); + lxcDriverUnlock(driver); + if (!vm) { lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -118,6 +131,8 @@ static virDomainPtr lxcDomainLookupByID( dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -128,7 +143,10 @@ static virDomainPtr lxcDomainLookupByUUI virDomainObjPtr vm; virDomainPtr dom = NULL; + lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, uuid); + lxcDriverUnlock(driver); + if (!vm) { lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -139,6 +157,8 @@ static virDomainPtr lxcDomainLookupByUUI dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -149,7 +169,9 @@ static virDomainPtr lxcDomainLookupByNam virDomainObjPtr vm; virDomainPtr dom = NULL; + lxcDriverLock(driver); vm = virDomainFindByName(&driver->domains, name); + lxcDriverUnlock(driver); if (!vm) { lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -160,6 +182,8 @@ static virDomainPtr lxcDomainLookupByNam dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -167,9 +191,14 @@ static int lxcListDomains(virConnectPtr lxc_driver_t *driver = conn->privateData; int got = 0, i; - for (i = 0 ; i < driver->domains.count && got < nids ; i++) + lxcDriverLock(driver); + for (i = 0 ; i < driver->domains.count && got < nids ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) ids[got++] = driver->domains.objs[i]->def->id; + virDomainObjUnlock(driver->domains.objs[i]); + } + lxcDriverUnlock(driver); return got; } @@ -178,9 +207,14 @@ static int lxcNumDomains(virConnectPtr c lxc_driver_t *driver = conn->privateData; int n = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + lxcDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + lxcDriverUnlock(driver); return n; } @@ -190,21 +224,27 @@ static int lxcListDefinedDomains(virConn lxc_driver_t *driver = conn->privateData; int got = 0, i; + lxcDriverLock(driver); for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) { if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { lxcError(conn, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); + virDomainObjUnlock(driver->domains.objs[i]); goto cleanup; } } + virDomainObjUnlock(driver->domains.objs[i]); } + lxcDriverUnlock(driver); return got; cleanup: for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); + lxcDriverUnlock(driver); return -1; } @@ -213,9 +253,14 @@ static int lxcNumDefinedDomains(virConne lxc_driver_t *driver = conn->privateData; int n = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + lxcDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + lxcDriverUnlock(driver); return n; } @@ -226,9 +271,10 @@ static virDomainPtr lxcDomainDefine(virC { lxc_driver_t *driver = conn->privateData; virDomainDefPtr def = NULL; - virDomainObjPtr vm; + virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; + lxcDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) goto cleanup; @@ -247,6 +293,7 @@ static virDomainPtr lxcDomainDefine(virC driver->configDir, vm->newDef ? vm->newDef : vm->def) < 0) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; goto cleanup; } @@ -256,6 +303,9 @@ static virDomainPtr lxcDomainDefine(virC cleanup: virDomainDefFree(def); + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); return dom; } @@ -265,6 +315,7 @@ static int lxcDomainUndefine(virDomainPt virDomainObjPtr vm; int ret = -1; + lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -291,9 +342,13 @@ static int lxcDomainUndefine(virDomainPt goto cleanup; virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); return ret; } @@ -304,7 +359,10 @@ static int lxcDomainGetInfo(virDomainPtr virDomainObjPtr vm; int ret = -1; + lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -325,6 +383,8 @@ static int lxcDomainGetInfo(virDomainPtr ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -334,7 +394,10 @@ static char *lxcGetOSType(virDomainPtr d virDomainObjPtr vm; char *ret = NULL; + lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -344,6 +407,8 @@ static char *lxcGetOSType(virDomainPtr d ret = strdup(vm->def->os.type); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -354,7 +419,10 @@ static char *lxcDomainDumpXML(virDomainP virDomainObjPtr vm; char *ret = NULL; + lxcDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + lxcDriverUnlock(driver); + if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -367,6 +435,8 @@ static char *lxcDomainDumpXML(virDomainP flags); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -880,6 +950,7 @@ static int lxcDomainStart(virDomainPtr d virDomainObjPtr vm; int ret = -1; + lxcDriverLock(driver); vm = virDomainFindByName(&driver->domains, dom->name); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -896,6 +967,9 @@ static int lxcDomainStart(virDomainPtr d ret = lxcVmStart(dom->conn, driver, vm); cleanup: + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); return ret; } @@ -914,10 +988,11 @@ lxcDomainCreateAndStart(virConnectPtr co const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { lxc_driver_t *driver = conn->privateData; - virDomainObjPtr vm; + virDomainObjPtr vm = NULL; virDomainDefPtr def; virDomainPtr dom = NULL; + lxcDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) goto cleanup; @@ -934,6 +1009,7 @@ lxcDomainCreateAndStart(virConnectPtr co if (lxcVmStart(conn, driver, vm) < 0) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; goto cleanup; } @@ -943,6 +1019,9 @@ lxcDomainCreateAndStart(virConnectPtr co cleanup: virDomainDefFree(def); + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); return dom; } @@ -960,6 +1039,7 @@ static int lxcDomainShutdown(virDomainPt virDomainObjPtr vm; int ret = -1; + lxcDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -968,8 +1048,15 @@ static int lxcDomainShutdown(virDomainPt } ret = lxcVmTerminate(dom->conn, driver, vm, 0); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } cleanup: + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); return ret; } @@ -988,6 +1075,7 @@ static int lxcDomainDestroy(virDomainPtr virDomainObjPtr vm; int ret = -1; + lxcDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { lxcError(dom->conn, dom, VIR_ERR_INVALID_DOMAIN, @@ -996,8 +1084,15 @@ static int lxcDomainDestroy(virDomainPtr } ret = lxcVmTerminate(dom->conn, driver, vm, SIGKILL); + if (!vm->persistent) { + virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } cleanup: + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); return ret; } @@ -1029,33 +1124,29 @@ static int lxcStartup(void) if (VIR_ALLOC(lxc_driver) < 0) { return -1; } + pthread_mutex_init(&lxc_driver->lock, NULL); + lxcDriverLock(lxc_driver); /* Check that this is a container enabled kernel */ if(lxcContainerAvailable(0) < 0) - return -1; + goto cleanup; lxc_driver->have_netns = lxcCheckNetNsSupport(); /* Call function to load lxc driver configuration information */ - if (lxcLoadDriverConfig(lxc_driver) < 0) { - lxcShutdown(); - return -1; - } + if (lxcLoadDriverConfig(lxc_driver) < 0) + goto cleanup; - if ((lxc_driver->caps = lxcCapsInit()) == NULL) { - lxcShutdown(); - return -1; - } + if ((lxc_driver->caps = lxcCapsInit()) == NULL) + goto cleanup; if (virDomainLoadAllConfigs(NULL, lxc_driver->caps, &lxc_driver->domains, lxc_driver->configDir, lxc_driver->autostartDir, - NULL, NULL) < 0) { - lxcShutdown(); - return -1; - } + NULL, NULL) < 0) + goto cleanup; for (i = 0 ; i < lxc_driver->domains.count ; i++) { virDomainObjPtr vm = lxc_driver->domains.objs[i]; @@ -1095,17 +1186,13 @@ static int lxcStartup(void) } } + lxcDriverUnlock(lxc_driver); return 0; -} -static void lxcFreeDriver(lxc_driver_t *driver) -{ - virCapabilitiesFree(driver->caps); - VIR_FREE(driver->configDir); - VIR_FREE(driver->autostartDir); - VIR_FREE(driver->stateDir); - VIR_FREE(driver->logDir); - VIR_FREE(driver); +cleanup: + lxcDriverUnlock(lxc_driver); + lxcShutdown(); + return -1; } static int lxcShutdown(void) @@ -1113,8 +1200,16 @@ static int lxcShutdown(void) if (lxc_driver == NULL) return(-1); + lxcDriverLock(lxc_driver); virDomainObjListFree(&lxc_driver->domains); - lxcFreeDriver(lxc_driver); + + virCapabilitiesFree(lxc_driver->caps); + VIR_FREE(lxc_driver->configDir); + VIR_FREE(lxc_driver->autostartDir); + VIR_FREE(lxc_driver->stateDir); + VIR_FREE(lxc_driver->logDir); + lxcDriverUnlock(lxc_driver); + VIR_FREE(lxc_driver); lxc_driver = NULL; return 0; @@ -1130,16 +1225,21 @@ static int static int lxcActive(void) { unsigned int i; + int active = 0; if (lxc_driver == NULL) return(0); - for (i = 0 ; i < lxc_driver->domains.count ; i++) + lxcDriverLock(lxc_driver); + for (i = 0 ; i < lxc_driver->domains.count ; i++) { + virDomainObjLock(lxc_driver->domains.objs[i]); if (virDomainIsActive(lxc_driver->domains.objs[i])) - return 1; + active = 1; + virDomainObjUnlock(lxc_driver->domains.objs[i]); + } + lxcDriverUnlock(lxc_driver); - /* Otherwise we're happy to deal with a shutdown */ - return 0; + return active; } static int lxcVersion(virConnectPtr conn, unsigned long *version) @@ -1179,15 +1279,19 @@ static int lxcSetSchedulerParameters(vir virSchedParameterPtr params, int nparams) { + lxc_driver_t *driver = domain->conn->privateData; int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; int ret = -1; if (virCgroupHaveSupport() != 0) - goto cleanup; + return -1; - vm = virDomainFindByUUID(&lxc_driver->domains, domain->uuid); + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + lxcDriverUnlock(driver); + if (vm == NULL) { lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR, _("No such domain %s"), domain->uuid); @@ -1213,7 +1317,8 @@ static int lxcSetSchedulerParameters(vir cleanup: virCgroupFree(&group); - + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1221,21 +1326,25 @@ static int lxcGetSchedulerParameters(vir virSchedParameterPtr params, int *nparams) { + lxc_driver_t *driver = domain->conn->privateData; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; unsigned long val; int ret = -1; if (virCgroupHaveSupport() != 0) - goto cleanup; + return -1; if ((*nparams) != 1) { lxcError(NULL, domain, VIR_ERR_INVALID_ARG, "%s", _("Invalid parameter count")); - goto cleanup; + return -1; } - vm = virDomainFindByUUID(&lxc_driver->domains, domain->uuid); + lxcDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, domain->uuid); + lxcDriverUnlock(driver); + if (vm == NULL) { lxcError(NULL, domain, VIR_ERR_INTERNAL_ERROR, _("No such domain %s"), domain->uuid); @@ -1255,6 +1364,8 @@ static int lxcGetSchedulerParameters(vir cleanup: virCgroupFree(&group); + if (vm) + virDomainObjUnlock(vm); return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:50:30PM +0000, Daniel P. Berrange wrote:
This patch makes the LXC driver thread safe following the same pattern as the Test/QEMU drivers
okay that starts to look familiar,
cleanup: virDomainDefFree(def); + if (vm) + virDomainObjUnlock(vm);
Maybe it's just simpler to make virDomainObjUnlock accept and ignore NULL rather than doing that check in all driver functions. Okay, I didn't spot anything, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch reduces the number of return points in the UML driver methods Makefile.maint | 1 src/uml_driver.c | 410 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 243 insertions(+), 168 deletions(-) Daniel diff --git a/Makefile.maint b/Makefile.maint --- a/Makefile.maint +++ b/Makefile.maint @@ -355,6 +355,7 @@ msg_gen_function += virDomainReportError msg_gen_function += virDomainReportError msg_gen_function += virReportErrorHelper msg_gen_function += lxcError +msg_gen_function += umlError # Uncomment the following and run "make syntax-check" to see diagnostics # that are not yet marked for translation, but that need to be rewritten diff --git a/src/uml_driver.c b/src/uml_driver.c --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -883,7 +883,7 @@ static virDrvOpenStatus umlOpen(virConne } static int umlClose(virConnectPtr conn) { - /*struct uml_driver *driver = (struct uml_driver *)conn->privateData;*/ + /*struct uml_driver *driver = conn->privateData;*/ conn->privateData = NULL; @@ -904,11 +904,9 @@ static char *umlGetCapabilities(virConne struct uml_driver *driver = (struct uml_driver *)conn->privateData; char *xml; - if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) { + if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for capabilities support")); - return NULL; - } return xml; } @@ -922,11 +920,12 @@ umlNodeGetCellsFreeMemory(virConnectPtr int maxCells) { int n, lastCell, numCells; + int ret = -1; if (numa_available() < 0) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s", _("NUMA not supported on this host")); - return -1; + goto cleanup; } lastCell = startCell + maxCells - 1; if (lastCell > numa_max_node()) @@ -937,22 +936,27 @@ umlNodeGetCellsFreeMemory(virConnectPtr if (numa_node_size64(n, &mem) < 0) { umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to query NUMA free memory")); - return -1; + goto cleanup; } freeMems[numCells++] = mem; } - return numCells; + ret = numCells; + +cleanup: + return ret; } static unsigned long long umlNodeGetFreeMemory (virConnectPtr conn) { unsigned long long freeMem = 0; + unsigned long long ret = -1; int n; + if (numa_available() < 0) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, "%s", _("NUMA not supported on this host")); - return -1; + goto cleanup; } for (n = 0 ; n <= numa_max_node() ; n++) { @@ -960,12 +964,14 @@ umlNodeGetFreeMemory (virConnectPtr conn if (numa_node_size64(n, &mem) < 0) { umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to query NUMA free memory")); - return -1; + goto cleanup; } freeMem += mem; } + ret = freeMem; - return freeMem; +cleanup: + return ret; } #endif @@ -1009,46 +1015,57 @@ static virDomainPtr umlDomainLookupByID( static virDomainPtr umlDomainLookupByID(virConnectPtr conn, int id) { struct uml_driver *driver = (struct uml_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, id); - virDomainPtr dom; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByID(&driver->domains, id); if (!vm) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } + static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { struct uml_driver *driver = (struct uml_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid); - virDomainPtr dom; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByUUID(&driver->domains, uuid); if (!vm) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } + static virDomainPtr umlDomainLookupByName(virConnectPtr conn, const char *name) { struct uml_driver *driver = (struct uml_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByName(&driver->domains, name); - virDomainPtr dom; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByName(&driver->domains, name); if (!vm) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: return dom; } @@ -1092,7 +1109,7 @@ umlGetHostname (virConnectPtr conn) } static int umlListDomains(virConnectPtr conn, int *ids, int nids) { - struct uml_driver *driver = (struct uml_driver *)conn->privateData; + struct uml_driver *driver = conn->privateData; int got = 0, i; for (i = 0 ; i < driver->domains.count && got < nids ; i++) @@ -1102,7 +1119,7 @@ static int umlListDomains(virConnectPtr return got; } static int umlNumDomains(virConnectPtr conn) { - struct uml_driver *driver = (struct uml_driver *)conn->privateData; + struct uml_driver *driver = conn->privateData; int n = 0, i; for (i = 0 ; i < driver->domains.count ; i++) @@ -1113,21 +1130,20 @@ static int umlNumDomains(virConnectPtr c } static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { + struct uml_driver *driver = conn->privateData; virDomainDefPtr def; virDomainObjPtr vm; - virDomainPtr dom; - struct uml_driver *driver = (struct uml_driver *)conn->privateData; + virDomainPtr dom = NULL; if (!(def = virDomainDefParseString(conn, driver->caps, xml))) - return NULL; + goto cleanup; vm = virDomainFindByName(&driver->domains, def->name); if (vm) { umlReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain '%s' is already defined"), def->name); - virDomainDefFree(def); - return NULL; + goto cleanup; } vm = virDomainFindByUUID(&driver->domains, def->uuid); if (vm) { @@ -1137,168 +1153,196 @@ static virDomainPtr umlDomainCreate(virC umlReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain with uuid '%s' is already defined"), uuidstr); - virDomainDefFree(def); - return NULL; + goto cleanup; } if (!(vm = virDomainAssignDef(conn, &driver->domains, - def))) { - virDomainDefFree(def); - return NULL; - } + def))) + goto cleanup; + def = NULL; if (umlStartVMDaemon(conn, driver, vm) < 0) { virDomainRemoveInactive(&driver->domains, vm); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: + virDomainDefFree(def); + return dom; } static int umlDomainShutdown(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); - char* info; + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *info; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } #if 0 if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("shutdown operation failed")); - return -1; + goto cleanup; } + ret = 0; #endif + +cleanup: VIR_FREE(info); - return 0; + return ret; } static int umlDomainDestroy(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; } umlShutdownVMDaemon(dom->conn, driver, vm); if (!vm->persistent) virDomainRemoveInactive(&driver->domains, vm); + ret = 0; - return 0; +cleanup: + return ret; } static char *umlDomainGetOSType(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - char *type; + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *type = NULL; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - if (!(type = strdup(vm->def->os.type))) { + if (!(type = strdup(vm->def->os.type))) umlReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for ostype")); - return NULL; - } + +cleanup: return type; } /* Returns max memory in kb, 0 if error */ static unsigned long umlDomainGetMaxMemory(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + unsigned long ret = 0; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return 0; + goto cleanup; } + ret = vm->def->maxmem; - return vm->def->maxmem; +cleanup: + return ret; } static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid '%s'"), uuidstr); - return -1; + goto cleanup; } if (newmax < vm->def->memory) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, "%s", _("cannot set max memory lower than current memory")); - return -1; + goto cleanup; } + vm->def->maxmem = newmax; + ret = 0; - vm->def->maxmem = newmax; - return 0; +cleanup: + return ret; } static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(dom->uuid, uuidstr); umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - _("no domain with matching uuid '%s'"), uuidstr); - return -1; + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; } if (virDomainIsActive(vm)) { umlReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, - "%s", _("cannot set memory of an active domain")); - return -1; + "%s", _("cannot set memory of an active domain")); + goto cleanup; } if (newmem > vm->def->maxmem) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, - "%s", _("cannot set memory higher than max memory")); - return -1; + "%s", _("cannot set memory higher than max memory")); + goto cleanup; } vm->def->memory = newmem; - return 0; + ret = 0; + +cleanup: + return ret; } static int umlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } info->state = vm->state; @@ -1307,38 +1351,48 @@ static int umlDomainGetInfo(virDomainPtr info->cpuTime = 0; } else { if (umlGetProcessInfo(&(info->cpuTime), vm->pid) < 0) { - umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain")); - return -1; + umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("cannot read cputime for domain")); + goto cleanup; } } info->maxMem = vm->def->maxmem; info->memory = vm->def->memory; info->nrVirtCpu = vm->def->vcpus; - return 0; + ret = 0; + +cleanup: + return ret; } static char *umlDomainDumpXML(virDomainPtr dom, int flags ATTRIBUTE_UNUSED) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *ret = NULL; + + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - return virDomainDefFormat(dom->conn, - (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? - vm->newDef : vm->def, - flags); + ret = virDomainDefFormat(dom->conn, + (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? + vm->newDef : vm->def, + flags); + +cleanup: + return ret; } static int umlListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { - struct uml_driver *driver = (struct uml_driver *)conn->privateData; + struct uml_driver *driver = conn->privateData; int got = 0, i; for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { @@ -1360,7 +1414,7 @@ static int umlListDefinedDomains(virConn } static int umlNumDefinedDomains(virConnectPtr conn) { - struct uml_driver *driver = (struct uml_driver *)conn->privateData; + struct uml_driver *driver = conn->privateData; int n = 0, i; for (i = 0 ; i < driver->domains.count ; i++) @@ -1372,34 +1426,38 @@ static int umlNumDefinedDomains(virConne static int umlDomainStart(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } - return umlStartVMDaemon(dom->conn, driver, vm); + ret = umlStartVMDaemon(dom->conn, driver, vm); + +cleanup: + return ret; } static virDomainPtr umlDomainDefine(virConnectPtr conn, const char *xml) { - struct uml_driver *driver = (struct uml_driver *)conn->privateData; + struct uml_driver *driver = conn->privateData; virDomainDefPtr def; virDomainObjPtr vm; - virDomainPtr dom; + virDomainPtr dom = NULL; if (!(def = virDomainDefParseString(conn, driver->caps, xml))) - return NULL; + goto cleanup; if (!(vm = virDomainAssignDef(conn, &driver->domains, - def))) { - virDomainDefFree(def); - return NULL; - } + def))) + goto cleanup; + def = NULL; vm->persistent = 1; if (virDomainSaveConfig(conn, @@ -1407,66 +1465,77 @@ static virDomainPtr umlDomainDefine(virC vm->newDef ? vm->newDef : vm->def) < 0) { virDomainRemoveInactive(&driver->domains, vm); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; + +cleanup: + virDomainDefFree(def); return dom; } static int umlDomainUndefine(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (virDomainIsActive(vm)) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain")); - return -1; + goto cleanup; } if (!vm->persistent) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot undefine transient domain")); - return -1; + goto cleanup; } if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0) - return -1; + goto cleanup; virDomainRemoveInactive(&driver->domains, vm); + ret = 0; - return 0; +cleanup: + return ret; } static int umlDomainGetAutostart(virDomainPtr dom, int *autostart) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } *autostart = vm->autostart; + ret = 0; - return 0; +cleanup: + return ret; } static int umlDomainSetAutostart(virDomainPtr dom, int autostart) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; + struct uml_driver *driver = dom->conn->privateData; virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); char *configFile = NULL, *autostartLink = NULL; int ret = -1; @@ -1474,51 +1543,50 @@ static int umlDomainSetAutostart(virDoma if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (!vm->persistent) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot set autostart for transient domain")); - return -1; + goto cleanup; } autostart = (autostart != 0); - if (vm->autostart == autostart) - return 0; + if (vm->autostart != autostart) { + if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL) + goto cleanup; + if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL) + goto cleanup; - if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL) - goto cleanup; - if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL) - goto cleanup; + if (autostart) { + int err; - if (autostart) { - int err; + if ((err = virFileMakePath(driver->autostartDir))) { + umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + driver->autostartDir, strerror(err)); + goto cleanup; + } - if ((err = virFileMakePath(driver->autostartDir))) { - umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _("cannot create autostart directory %s: %s"), - driver->autostartDir, strerror(err)); - goto cleanup; + if (symlink(configFile, autostartLink) < 0) { + umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("Failed to create symlink '%s to '%s': %s"), + autostartLink, configFile, strerror(errno)); + goto cleanup; + } + } else { + if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { + umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("Failed to delete symlink '%s': %s"), + autostartLink, strerror(errno)); + goto cleanup; + } } - if (symlink(configFile, autostartLink) < 0) { - umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _("Failed to create symlink '%s to '%s': %s"), - autostartLink, configFile, strerror(errno)); - goto cleanup; - } - } else { - if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { - umlReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, - _("Failed to delete symlink '%s': %s"), - autostartLink, strerror(errno)); - goto cleanup; - } + vm->autostart = autostart; } - - vm->autostart = autostart; ret = 0; cleanup: @@ -1536,54 +1604,60 @@ umlDomainBlockPeek (virDomainPtr dom, void *buffer, unsigned int flags ATTRIBUTE_UNUSED) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - int fd, ret = -1, i; + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int fd = -1, ret = -1, i; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid")); - return -1; + goto cleanup; } if (!path || path[0] == '\0') { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, _("NULL or empty path")); - return -1; + goto cleanup; } /* Check the path belongs to this domain. */ for (i = 0 ; i < vm->def->ndisks ; i++) { if (vm->def->disks[i]->src != NULL && - STREQ (vm->def->disks[i]->src, path)) - goto found; - } - umlReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, - _("invalid path")); - return -1; - -found: - /* The path is correct, now try to open it and get its size. */ - fd = open (path, O_RDONLY); - if (fd == -1) { - umlReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, - "%s", strerror (errno)); - goto done; + STREQ (vm->def->disks[i]->src, path)) { + ret = 0; + break; + } } - /* Seek and read. */ - /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should - * be 64 bits on all platforms. - */ - if (lseek (fd, offset, SEEK_SET) == (off_t) -1 || - saferead (fd, buffer, size) == (ssize_t) -1) { - umlReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, - "%s", strerror (errno)); - goto done; + if (ret == 0) { + ret = -1; + /* The path is correct, now try to open it and get its size. */ + fd = open (path, O_RDONLY); + if (fd == -1) { + umlReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, + "%s", strerror (errno)); + goto cleanup; + } + + /* Seek and read. */ + /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should + * be 64 bits on all platforms. + */ + if (lseek (fd, offset, SEEK_SET) == (off_t) -1 || + saferead (fd, buffer, size) == (ssize_t) -1) { + umlReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, + "%s", strerror (errno)); + goto cleanup; + } + + ret = 0; + } else { + umlReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, + _("invalid path")); } - ret = 0; - done: +cleanup: if (fd >= 0) close (fd); return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

"Daniel P. Berrange" <berrange@redhat.com> wrote:
static int umlDomainShutdown(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); - char* info; + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *info; + int ret = -1;
+ vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; }
#if 0 if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("shutdown operation failed")); - return -1; + goto cleanup; } + ret = 0; #endif + +cleanup: VIR_FREE(info); - return 0; + return ret;
}
info should be initialised to NULL, otherwise the VIR_FREE will fail. With the umlMonitorCommand if'ed out this is also broken before the patch, which is how I came to notice it. Ron

Ron Yorston <rmy@tigress.co.uk> wrote:
static int umlDomainShutdown(virDomainPtr dom) { ... + char *info; ... VIR_FREE(info); ... info should be initialised to NULL, otherwise the VIR_FREE will fail. With the umlMonitorCommand if'ed out this is also broken before the
"Daniel P. Berrange" <berrange@redhat.com> wrote: patch, which is how I came to notice it.
Ron
Thanks for reporting that! I'll commit the following shortly: Mon Nov 30 10:28:21 CET 2008 Jim Meyering <meyering@redhat.com> uml: don't free an uninitialized variable * src/uml_driver.c (umlDomainShutdown): Initialize "info". Patch and bug report from Ron Yorston <rmy@tigress.co.uk>.
From c0cc0c4be0ba4add32c5c3a71941a21b514ca15c Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyering@redhat.com> Date: Mon, 1 Dec 2008 10:30:10 +0100 Subject: [PATCH] uml: don't free an uninitialized variable
* src/uml_driver.c (umlDomainShutdown): Initialize "info". Patch and bug report from Ron Yorston <rmy@tigress.co.uk>. --- src/uml_driver.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/src/uml_driver.c b/src/uml_driver.c index 1ce1d78..dcf3f66 100644 --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -1163,7 +1163,7 @@ static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml, static int umlDomainShutdown(virDomainPtr dom) { struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); - char* info; + char *info = NULL; if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -1672,4 +1672,3 @@ int umlRegister(void) { virRegisterStateDriver(¨StateDriver); return 0; } - -- 1.6.0.4.1101.g642f8

Jim Meyering <jim@meyering.net> wrote:
Ron Yorston <rmy@tigress.co.uk> wrote:
static int umlDomainShutdown(virDomainPtr dom) { ... + char *info; ... VIR_FREE(info); ... info should be initialised to NULL, otherwise the VIR_FREE will fail. With the umlMonitorCommand if'ed out this is also broken before the
"Daniel P. Berrange" <berrange@redhat.com> wrote: patch, which is how I came to notice it.
Ron
Thanks for reporting that! I'll commit the following shortly:
Mon Nov 30 10:28:21 CET 2008 Jim Meyering <meyering@redhat.com>
uml: don't free an uninitialized variable * src/uml_driver.c (umlDomainShutdown): Initialize "info". Patch and bug report from Ron Yorston <rmy@tigress.co.uk>.
Committed.

On Mon, Dec 01, 2008 at 09:16:10AM +0000, Ron Yorston wrote:
"Daniel P. Berrange" <berrange@redhat.com> wrote:
static int umlDomainShutdown(virDomainPtr dom) { - struct uml_driver *driver = (struct uml_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); - char* info; + struct uml_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *info; + int ret = -1;
+ vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); - return -1; + goto cleanup; }
#if 0 if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { umlReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("shutdown operation failed")); - return -1; + goto cleanup; } + ret = 0; #endif + +cleanup: VIR_FREE(info); - return 0; + return ret;
}
info should be initialised to NULL, otherwise the VIR_FREE will fail. With the umlMonitorCommand if'ed out this is also broken before the patch, which is how I came to notice it.
Yes indeed this entire method is on my hit list, since it actually needs implementing for real ! Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch makes the UML driver thread safe uml_conf.h | 2 uml_driver.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 172 insertions(+), 39 deletions(-) Daniel diff --git a/src/uml_conf.h b/src/uml_conf.h --- a/src/uml_conf.h +++ b/src/uml_conf.h @@ -39,6 +39,8 @@ /* Main driver state */ struct uml_driver { + PTHREAD_MUTEX_T(lock); + unsigned int umlVersion; int nextvmid; diff --git a/src/uml_driver.c b/src/uml_driver.c --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -73,6 +73,15 @@ static int umlShutdown(void); #define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg) #define umlLog(level, msg...) fprintf(stderr, msg) + +static void umlDriverLock(struct uml_driver *driver) +{ + pthread_mutex_lock(&driver->lock); +} +static void umlDriverUnlock(struct uml_driver *driver) +{ + pthread_mutex_unlock(&driver->lock); +} static int umlOpenMonitor(virConnectPtr conn, @@ -288,13 +297,16 @@ umlStartup(void) { if (VIR_ALLOC(uml_driver) < 0) return -1; + pthread_mutex_init(¨_driver->lock, NULL); + umlDriverLock(uml_driver); + /* Don't have a dom0 so start from 1 */ uml_driver->nextvmid = 1; if (!(pw = getpwuid(uid))) { umlLog(UML_ERR, _("Failed to find user record for uid '%d': %s\n"), uid, strerror(errno)); - goto out_nouid; + goto error; } if (!uid) { @@ -338,49 +350,45 @@ umlStartup(void) { if ((uml_driver->inotifyFD = inotify_init()) < 0) { umlLog(UML_ERR, "%s", _("cannot initialize inotify")); - goto out_nouid; + goto error; } if (virFileMakePath(uml_driver->monitorDir) < 0) { umlLog(UML_ERR, _("Failed to create monitor directory %s: %s"), uml_driver->monitorDir, strerror(errno)); - umlShutdown(); - return -1; + goto error; } if ((uml_driver->inotifyWatch = inotify_add_watch(uml_driver->inotifyFD, uml_driver->monitorDir, - IN_CREATE | IN_MODIFY | IN_DELETE)) < 0) { - umlShutdown(); - return -1; - } + IN_CREATE | IN_MODIFY | IN_DELETE)) < 0) + goto error; if (virEventAddHandle(uml_driver->inotifyFD, POLLIN, - umlInotifyEvent, uml_driver, NULL) < 0) { - umlShutdown(); - return -1; - } + umlInotifyEvent, uml_driver, NULL) < 0) + goto error; if (virDomainLoadAllConfigs(NULL, uml_driver->caps, ¨_driver->domains, uml_driver->configDir, uml_driver->autostartDir, - NULL, NULL) < 0) { - umlShutdown(); - return -1; - } + NULL, NULL) < 0) + goto error; + umlAutostartConfigs(uml_driver); + umlDriverUnlock(uml_driver); return 0; - out_of_memory: +out_of_memory: umlLog (UML_ERR, "%s", _("umlStartup: out of memory\n")); - out_nouid: +error: VIR_FREE(base); - VIR_FREE(uml_driver); + umlDriverUnlock(uml_driver); + umlShutdown(); return -1; } @@ -395,6 +403,7 @@ umlReload(void) { if (!uml_driver) return 0; + umlDriverLock(uml_driver); virDomainLoadAllConfigs(NULL, uml_driver->caps, ¨_driver->domains, @@ -403,6 +412,7 @@ umlReload(void) { NULL, NULL); umlAutostartConfigs(uml_driver); + umlDriverUnlock(uml_driver); return 0; } @@ -418,16 +428,21 @@ static int static int umlActive(void) { unsigned int i; + int active = 0; if (!uml_driver) return 0; - for (i = 0 ; i < uml_driver->domains.count ; i++) + umlDriverLock(uml_driver); + for (i = 0 ; i < uml_driver->domains.count ; i++) { + virDomainObjLock(uml_driver->domains.objs[i]); if (virDomainIsActive(uml_driver->domains.objs[i])) - return 1; + active = 1; + virDomainObjUnlock(uml_driver->domains.objs[i]); + } + umlDriverUnlock(uml_driver); - /* Otherwise we're happy to deal with a shutdown */ - return 0; + return active; } /** @@ -442,6 +457,7 @@ umlShutdown(void) { if (!uml_driver) return -1; + umlDriverLock(uml_driver); virEventRemoveHandle(uml_driver->inotifyWatch); close(uml_driver->inotifyFD); virCapabilitiesFree(uml_driver->caps); @@ -451,9 +467,6 @@ umlShutdown(void) { virDomainObjPtr dom = uml_driver->domains.objs[i]; if (virDomainIsActive(dom)) umlShutdownVMDaemon(NULL, uml_driver, dom); - if (!dom->persistent) - virDomainRemoveInactive(¨_driver->domains, - dom); } virDomainObjListFree(¨_driver->domains); @@ -466,6 +479,7 @@ umlShutdown(void) { if (uml_driver->brctl) brShutdown(uml_driver->brctl); + umlDriverUnlock(uml_driver); VIR_FREE(uml_driver); return 0; @@ -904,9 +918,11 @@ static char *umlGetCapabilities(virConne struct uml_driver *driver = (struct uml_driver *)conn->privateData; char *xml; + umlDriverLock(driver); if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for capabilities support")); + umlDriverUnlock(driver); return xml; } @@ -1018,7 +1034,10 @@ static virDomainPtr umlDomainLookupByID( virDomainObjPtr vm; virDomainPtr dom = NULL; + umlDriverLock(driver); vm = virDomainFindByID(&driver->domains, id); + umlDriverUnlock(driver); + if (!vm) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -1028,6 +1047,8 @@ static virDomainPtr umlDomainLookupByID( if (dom) dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -1037,7 +1058,10 @@ static virDomainPtr umlDomainLookupByUUI virDomainObjPtr vm; virDomainPtr dom = NULL; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, uuid); + umlDriverUnlock(driver); + if (!vm) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -1047,6 +1071,8 @@ static virDomainPtr umlDomainLookupByUUI if (dom) dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -1056,7 +1082,10 @@ static virDomainPtr umlDomainLookupByNam virDomainObjPtr vm; virDomainPtr dom = NULL; + umlDriverLock(driver); vm = virDomainFindByName(&driver->domains, name); + umlDriverUnlock(driver); + if (!vm) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -1066,24 +1095,33 @@ static virDomainPtr umlDomainLookupByNam if (dom) dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } static int umlGetVersion(virConnectPtr conn, unsigned long *version) { + struct uml_driver *driver = conn->privateData; struct utsname ut; int major, minor, micro; + int ret = -1; uname(&ut); + umlDriverLock(driver); if (sscanf(ut.release, "%u.%u.%u", &major, &minor, µ) != 3) { umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("cannot parse version %s"), ut.release); - return -1; + goto cleanup; } - *version = uml_driver->umlVersion; - return 0; + *version = driver->umlVersion; + ret = 0; + +cleanup: + umlDriverUnlock(driver); + return ret; } static char * @@ -1112,9 +1150,14 @@ static int umlListDomains(virConnectPtr struct uml_driver *driver = conn->privateData; int got = 0, i; - for (i = 0 ; i < driver->domains.count && got < nids ; i++) + umlDriverLock(driver); + for (i = 0 ; i < driver->domains.count && got < nids ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) ids[got++] = driver->domains.objs[i]->def->id; + virDomainObjUnlock(driver->domains.objs[i]); + } + umlDriverUnlock(driver); return got; } @@ -1122,9 +1165,14 @@ static int umlNumDomains(virConnectPtr c struct uml_driver *driver = conn->privateData; int n = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + umlDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + umlDriverUnlock(driver); return n; } @@ -1132,9 +1180,10 @@ static virDomainPtr umlDomainCreate(virC unsigned int flags ATTRIBUTE_UNUSED) { struct uml_driver *driver = conn->privateData; virDomainDefPtr def; - virDomainObjPtr vm; + virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; + umlDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) goto cleanup; @@ -1165,6 +1214,7 @@ static virDomainPtr umlDomainCreate(virC if (umlStartVMDaemon(conn, driver, vm) < 0) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; goto cleanup; } @@ -1173,7 +1223,9 @@ static virDomainPtr umlDomainCreate(virC cleanup: virDomainDefFree(def); - + if (vm) + virDomainObjUnlock(vm); + umlDriverUnlock(driver); return dom; } @@ -1184,7 +1236,9 @@ static int umlDomainShutdown(virDomainPt char *info; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); + umlDriverUnlock(driver); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); @@ -1202,8 +1256,9 @@ static int umlDomainShutdown(virDomainPt cleanup: VIR_FREE(info); + if (vm) + virDomainObjUnlock(vm); return ret; - } @@ -1212,6 +1267,7 @@ static int umlDomainDestroy(virDomainPtr virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByID(&driver->domains, dom->id); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -1220,12 +1276,17 @@ static int umlDomainDestroy(virDomainPtr } umlShutdownVMDaemon(dom->conn, driver, vm); - if (!vm->persistent) + if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; + } ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); + umlDriverUnlock(driver); return ret; } @@ -1235,7 +1296,9 @@ static char *umlDomainGetOSType(virDomai virDomainObjPtr vm; char *type = NULL; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1247,6 +1310,8 @@ static char *umlDomainGetOSType(virDomai "%s", _("failed to allocate space for ostype")); cleanup: + if (vm) + virDomainObjUnlock(vm); return type; } @@ -1256,7 +1321,10 @@ static unsigned long umlDomainGetMaxMemo virDomainObjPtr vm; unsigned long ret = 0; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1268,6 +1336,8 @@ static unsigned long umlDomainGetMaxMemo ret = vm->def->maxmem; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1276,7 +1346,10 @@ static int umlDomainSetMaxMemory(virDoma virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1295,6 +1368,8 @@ static int umlDomainSetMaxMemory(virDoma ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1303,7 +1378,10 @@ static int umlDomainSetMemory(virDomainP virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -1329,6 +1407,8 @@ static int umlDomainSetMemory(virDomainP ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1338,7 +1418,10 @@ static int umlDomainGetInfo(virDomainPtr virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1363,6 +1446,8 @@ static int umlDomainGetInfo(virDomainPtr ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1373,7 +1458,10 @@ static char *umlDomainDumpXML(virDomainP virDomainObjPtr vm; char *ret = NULL; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1386,6 +1474,8 @@ static char *umlDomainDumpXML(virDomainP flags); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1395,21 +1485,27 @@ static int umlListDefinedDomains(virConn struct uml_driver *driver = conn->privateData; int got = 0, i; + umlDriverLock(driver); for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) { if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); + virDomainObjUnlock(driver->domains.objs[i]); goto cleanup; } } + virDomainObjUnlock(driver->domains.objs[i]); } + umlDriverUnlock(driver); return got; cleanup: for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); + umlDriverUnlock(driver); return -1; } @@ -1417,9 +1513,14 @@ static int umlNumDefinedDomains(virConne struct uml_driver *driver = conn->privateData; int n = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + umlDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) n++; + virDomainObjUnlock(driver->domains.objs[i]); + } + umlDriverUnlock(driver); return n; } @@ -1430,6 +1531,7 @@ static int umlDomainStart(virDomainPtr d virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -1440,6 +1542,9 @@ static int umlDomainStart(virDomainPtr d ret = umlStartVMDaemon(dom->conn, driver, vm); cleanup: + if (vm) + virDomainObjUnlock(vm); + umlDriverUnlock(driver); return ret; } @@ -1447,9 +1552,10 @@ static virDomainPtr umlDomainDefine(virC static virDomainPtr umlDomainDefine(virConnectPtr conn, const char *xml) { struct uml_driver *driver = conn->privateData; virDomainDefPtr def; - virDomainObjPtr vm; + virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; + umlDriverLock(driver); if (!(def = virDomainDefParseString(conn, driver->caps, xml))) goto cleanup; @@ -1465,6 +1571,7 @@ static virDomainPtr umlDomainDefine(virC vm->newDef ? vm->newDef : vm->def) < 0) { virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; goto cleanup; } @@ -1473,6 +1580,9 @@ static virDomainPtr umlDomainDefine(virC cleanup: virDomainDefFree(def); + if (vm) + virDomainObjUnlock(vm); + umlDriverUnlock(driver); return dom; } @@ -1481,7 +1591,9 @@ static int umlDomainUndefine(virDomainPt virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1505,9 +1617,13 @@ static int umlDomainUndefine(virDomainPt virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); + umlDriverUnlock(driver); return ret; } @@ -1519,7 +1635,10 @@ static int umlDomainGetAutostart(virDoma virDomainObjPtr vm; int ret = -1; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -1530,15 +1649,21 @@ static int umlDomainGetAutostart(virDoma ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } static int umlDomainSetAutostart(virDomainPtr dom, int autostart) { struct uml_driver *driver = dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + virDomainObjPtr vm; char *configFile = NULL, *autostartLink = NULL; int ret = -1; + + umlDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); if (!vm) { umlReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, @@ -1592,7 +1717,8 @@ cleanup: cleanup: VIR_FREE(configFile); VIR_FREE(autostartLink); - + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -1608,7 +1734,10 @@ umlDomainBlockPeek (virDomainPtr dom, virDomainObjPtr vm; int fd = -1, ret = -1, i; + umlDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + umlDriverUnlock(driver); + if (!vm) { umlReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid")); @@ -1659,6 +1788,8 @@ umlDomainBlockPeek (virDomainPtr dom, cleanup: if (fd >= 0) close (fd); + if (vm) + virDomainObjUnlock(vm); return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:53:17PM +0000, Daniel P. Berrange wrote:
This patch makes the UML driver thread safe
[...]
@@ -1395,21 +1485,27 @@ static int umlListDefinedDomains(virConn struct uml_driver *driver = conn->privateData; int got = 0, i;
+ umlDriverLock(driver); for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) { if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); + virDomainObjUnlock(driver->domains.objs[i]); goto cleanup; } } + virDomainObjUnlock(driver->domains.objs[i]); } + umlDriverUnlock(driver);
return got;
cleanup:
since this is an error code path, I would rather change the label to error: ... Okay otherwise nothing spotted, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Tue, Dec 02, 2008 at 12:05:10PM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:53:17PM +0000, Daniel P. Berrange wrote:
This patch makes the UML driver thread safe
[...]
@@ -1395,21 +1485,27 @@ static int umlListDefinedDomains(virConn struct uml_driver *driver = conn->privateData; int got = 0, i;
+ umlDriverLock(driver); for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) { if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); + virDomainObjUnlock(driver->domains.objs[i]); goto cleanup; } } + virDomainObjUnlock(driver->domains.objs[i]); } + umlDriverUnlock(driver);
return got;
cleanup:
since this is an error code path, I would rather change the label to error: ...
That's a good idea - we should define a standard naming for this usage 'cleanup' to be used where error & normal conditions shared the same exit path of a method. 'error' to be used where error path is completely separate from the normal exit path. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Tue, Dec 02, 2008 at 11:06:38AM +0000, Daniel P. Berrange wrote:
On Tue, Dec 02, 2008 at 12:05:10PM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:53:17PM +0000, Daniel P. Berrange wrote:
This patch makes the UML driver thread safe
[...]
@@ -1395,21 +1485,27 @@ static int umlListDefinedDomains(virConn struct uml_driver *driver = conn->privateData; int got = 0, i;
+ umlDriverLock(driver); for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) { if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) { umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); + virDomainObjUnlock(driver->domains.objs[i]); goto cleanup; } } + virDomainObjUnlock(driver->domains.objs[i]); } + umlDriverUnlock(driver);
return got;
cleanup:
since this is an error code path, I would rather change the label to error: ...
That's a good idea - we should define a standard naming for this usage
'cleanup' to be used where error & normal conditions shared the same exit path of a method.
'error' to be used where error path is completely separate from the normal exit path.
yup since we're going to have labels on a lot of functions for exit we should try to standardize their use and name. The set of patches does this mostly, just a small incremental improvement, and then we can document it in the HACKING file. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch reduces the number of return points in the network driver methods network_driver.c | 275 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 159 insertions(+), 116 deletions(-) Daniel diff --git a/src/network_driver.c b/src/network_driver.c --- a/src/network_driver.c +++ b/src/network_driver.c @@ -118,7 +118,7 @@ networkStartup(void) { char *base = NULL; if (VIR_ALLOC(driverState) < 0) - return -1; + goto error; if (!uid) { if (asprintf(&driverState->logDir, @@ -160,19 +160,20 @@ networkStartup(void) { if (virNetworkLoadAllConfigs(NULL, &driverState->networks, driverState->networkConfigDir, - driverState->networkAutostartDir) < 0) { - networkShutdown(); - return -1; - } + driverState->networkAutostartDir) < 0) + goto error; + networkAutostartConfigs(driverState); return 0; - out_of_memory: +out_of_memory: networkLog (NETWORK_ERR, "%s", _("networkStartup: out of memory\n")); + +error: VIR_FREE(base); - VIR_FREE(driverState); + networkShutdown(); return -1; } @@ -214,16 +215,18 @@ static int static int networkActive(void) { unsigned int i; + int active = 0; if (!driverState) return 0; - for (i = 0 ; i < driverState->networks.count ; i++) - if (virNetworkIsActive(driverState->networks.objs[i])) - return 1; + for (i = 0 ; i < driverState->networks.count ; i++) { + virNetworkObjPtr net = driverState->networks.objs[i]; + if (virNetworkIsActive(net)) + active = 1; + } - /* Otherwise we're happy to deal with a shutdown */ - return 0; + return active; } /** @@ -239,10 +242,12 @@ networkShutdown(void) { return -1; /* shutdown active networks */ - for (i = 0 ; i < driverState->networks.count ; i++) - if (virNetworkIsActive(driverState->networks.objs[i])) + for (i = 0 ; i < driverState->networks.count ; i++) { + virNetworkObjPtr net = driverState->networks.objs[i]; + if (virNetworkIsActive(net)) networkShutdownNetworkDaemon(NULL, driverState, driverState->networks.objs[i]); + } /* free inactive networks */ virNetworkObjListFree(&driverState->networks); @@ -804,35 +809,42 @@ static int networkShutdownNetworkDaemon( } -static virNetworkPtr networkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED, - const unsigned char *uuid) { - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, uuid); - virNetworkPtr net; +static virNetworkPtr networkLookupByUUID(virConnectPtr conn, + const unsigned char *uuid) { + struct network_driver *driver = conn->networkPrivateData; + virNetworkObjPtr network; + virNetworkPtr ret = NULL; + network = virNetworkFindByUUID(&driver->networks, uuid); if (!network) { networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK, "%s", _("no network with matching uuid")); - return NULL; + goto cleanup; } - net = virGetNetwork(conn, network->def->name, network->def->uuid); - return net; + ret = virGetNetwork(conn, network->def->name, network->def->uuid); + +cleanup: + return ret; } -static virNetworkPtr networkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED, - const char *name) { - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByName(&driver->networks, name); - virNetworkPtr net; +static virNetworkPtr networkLookupByName(virConnectPtr conn, + const char *name) { + struct network_driver *driver = conn->networkPrivateData; + virNetworkObjPtr network; + virNetworkPtr ret = NULL; + + network = virNetworkFindByName(&driver->networks, name); if (!network) { networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK, "%s", _("no network with matching name")); - return NULL; + goto cleanup; } - net = virGetNetwork(conn, network->def->name, network->def->uuid); - return net; + ret = virGetNetwork(conn, network->def->name, network->def->uuid); + +cleanup: + return ret; } static virDrvOpenStatus networkOpenNetwork(virConnectPtr conn, @@ -852,7 +864,7 @@ static int networkCloseNetwork(virConnec static int networkNumNetworks(virConnectPtr conn) { int nactive = 0, i; - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; + struct network_driver *driver = conn->networkPrivateData; for (i = 0 ; i < driver->networks.count ; i++) if (virNetworkIsActive(driver->networks.objs[i])) @@ -862,7 +874,7 @@ static int networkNumNetworks(virConnect } static int networkListNetworks(virConnectPtr conn, char **const names, int nnames) { - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; + struct network_driver *driver = conn->networkPrivateData; int got = 0, i; for (i = 0 ; i < driver->networks.count && got < nnames ; i++) { @@ -885,7 +897,7 @@ static int networkListNetworks(virConnec static int networkNumDefinedNetworks(virConnectPtr conn) { int ninactive = 0, i; - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; + struct network_driver *driver = conn->networkPrivateData; for (i = 0 ; i < driver->networks.count ; i++) if (!virNetworkIsActive(driver->networks.objs[i])) @@ -895,7 +907,7 @@ static int networkNumDefinedNetworks(vir } static int networkListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; + struct network_driver *driver = conn->networkPrivateData; int got = 0, i; for (i = 0 ; i < driver->networks.count && got < nnames ; i++) { @@ -917,45 +929,47 @@ static int networkListDefinedNetworks(vi } static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) { - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; + struct network_driver *driver = conn->networkPrivateData; virNetworkDefPtr def; virNetworkObjPtr network; - virNetworkPtr net; + virNetworkPtr ret = NULL; if (!(def = virNetworkDefParseString(conn, xml))) - return NULL; + goto cleanup; if (!(network = virNetworkAssignDef(conn, &driver->networks, - def))) { - virNetworkDefFree(def); - return NULL; - } + def))) + goto cleanup; + def = NULL; if (networkStartNetworkDaemon(conn, driver, network) < 0) { virNetworkRemoveInactive(&driver->networks, network); - return NULL; + goto cleanup; } - net = virGetNetwork(conn, network->def->name, network->def->uuid); - return net; + ret = virGetNetwork(conn, network->def->name, network->def->uuid); + +cleanup: + virNetworkDefFree(def); + return ret; } static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) { - struct network_driver *driver = (struct network_driver *)conn->networkPrivateData; + struct network_driver *driver = conn->networkPrivateData; virNetworkDefPtr def; virNetworkObjPtr network; + virNetworkPtr ret = NULL; if (!(def = virNetworkDefParseString(conn, xml))) - return NULL; + goto cleanup; if (!(network = virNetworkAssignDef(conn, &driver->networks, - def))) { - virNetworkDefFree(def); - return NULL; - } + def))) + goto cleanup; + def = NULL; if (virNetworkSaveConfig(conn, driver->networkConfigDir, @@ -963,158 +977,187 @@ static virNetworkPtr networkDefine(virCo network) < 0) { virNetworkRemoveInactive(&driver->networks, network); - return NULL; + goto cleanup; } - return virGetNetwork(conn, network->def->name, network->def->uuid); + ret = virGetNetwork(conn, network->def->name, network->def->uuid); + +cleanup: + virNetworkDefFree(def); + return ret; } static int networkUndefine(virNetworkPtr net) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + int ret = -1; + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_DOMAIN, - "%s", _("no network with matching uuid")); - return -1; + "%s", _("no network with matching uuid")); + goto cleanup; } if (virNetworkIsActive(network)) { networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, - "%s", _("network is still active")); - return -1; + "%s", _("network is still active")); + goto cleanup; } if (virNetworkDeleteConfig(net->conn, network) < 0) - return -1; + goto cleanup; virNetworkRemoveInactive(&driver->networks, network); + ret = 0; - return 0; +cleanup: + return ret; } static int networkStart(virNetworkPtr net) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + int ret = -1; + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, - "%s", _("no network with matching uuid")); - return -1; + "%s", _("no network with matching uuid")); + goto cleanup; } - return networkStartNetworkDaemon(net->conn, driver, network); + ret = networkStartNetworkDaemon(net->conn, driver, network); + +cleanup: + return ret; } static int networkDestroy(virNetworkPtr net) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); - int ret; + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + int ret = -1; + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, - "%s", _("no network with matching uuid")); - return -1; + "%s", _("no network with matching uuid")); + goto cleanup; } ret = networkShutdownNetworkDaemon(net->conn, driver, network); +cleanup: return ret; } static char *networkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + char *ret = NULL; + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, - "%s", _("no network with matching uuid")); - return NULL; + "%s", _("no network with matching uuid")); + goto cleanup; } - return virNetworkDefFormat(net->conn, network->def); + ret = virNetworkDefFormat(net->conn, network->def); + +cleanup: + return ret; } static char *networkGetBridgeName(virNetworkPtr net) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); - char *bridge; + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + char *bridge = NULL; + + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, - "%s", _("no network with matching id")); - return NULL; + "%s", _("no network with matching id")); + goto cleanup; } bridge = strdup(network->def->bridge); - if (!bridge) { + if (!bridge) networkReportError(net->conn, NULL, net, VIR_ERR_NO_MEMORY, - "%s", _("failed to allocate space for network bridge string")); - return NULL; - } + "%s", _("failed to allocate space for network bridge string")); + +cleanup: return bridge; } static int networkGetAutostart(virNetworkPtr net, int *autostart) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + int ret = -1; + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); - return -1; + goto cleanup; } *autostart = network->autostart; + ret = 0; - return 0; +cleanup: + return ret; } static int networkSetAutostart(virNetworkPtr net, int autostart) { - struct network_driver *driver = (struct network_driver *)net->conn->networkPrivateData; - virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, net->uuid); + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + int ret = -1; + network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); - return -1; + goto cleanup; } autostart = (autostart != 0); - if (network->autostart == autostart) - return 0; + if (network->autostart != autostart) { + if (autostart) { + int err; - if (autostart) { - int err; + if ((err = virFileMakePath(driver->networkAutostartDir))) { + networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + driver->networkAutostartDir, strerror(err)); + goto cleanup; + } - if ((err = virFileMakePath(driver->networkAutostartDir))) { - networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, - _("cannot create autostart directory %s: %s"), - driver->networkAutostartDir, strerror(err)); - return -1; + if (symlink(network->configFile, network->autostartLink) < 0) { + networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, + _("Failed to create symlink '%s' to '%s': %s"), + network->autostartLink, network->configFile, strerror(errno)); + goto cleanup; + } + } else { + if (unlink(network->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { + networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, + _("Failed to delete symlink '%s': %s"), + network->autostartLink, strerror(errno)); + goto cleanup; + } } - if (symlink(network->configFile, network->autostartLink) < 0) { - networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, - _("Failed to create symlink '%s' to '%s': %s"), - network->autostartLink, network->configFile, strerror(errno)); - return -1; - } - } else { - if (unlink(network->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) { - networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR, - _("Failed to delete symlink '%s': %s"), - network->autostartLink, strerror(errno)); - return -1; - } + network->autostart = autostart; } + ret = 0; - network->autostart = autostart; - - return 0; +cleanup: + return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:55:03PM +0000, Daniel P. Berrange wrote:
This patch reduces the number of return points in the network driver methods
okay, looks fine, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the network driver thread safe, following the pattern of the earlier patches network_driver.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 125 insertions(+), 11 deletions(-) Daniel diff --git a/src/network_driver.c b/src/network_driver.c --- a/src/network_driver.c +++ b/src/network_driver.c @@ -59,6 +59,8 @@ /* Main driver state */ struct network_driver { + PTHREAD_MUTEX_T(lock); + virNetworkObjList networks; iptablesContext *iptables; @@ -67,6 +69,16 @@ struct network_driver { char *networkAutostartDir; char *logDir; }; + + +static void networkDriverLock(struct network_driver *driver) +{ + pthread_mutex_lock(&driver->lock); +} +static void networkDriverUnlock(struct network_driver *driver) +{ + pthread_mutex_unlock(&driver->lock); +} static int networkShutdown(void); @@ -95,6 +107,7 @@ networkAutostartConfigs(struct network_d unsigned int i; for (i = 0 ; i < driver->networks.count ; i++) { + virNetworkObjLock(driver->networks.objs[i]); if (driver->networks.objs[i]->autostart && !virNetworkIsActive(driver->networks.objs[i]) && networkStartNetworkDaemon(NULL, driver, driver->networks.objs[i]) < 0) { @@ -103,6 +116,7 @@ networkAutostartConfigs(struct network_d driver->networks.objs[i]->def->name, err ? err->message : NULL); } + virNetworkObjUnlock(driver->networks.objs[i]); } } @@ -119,6 +133,9 @@ networkStartup(void) { if (VIR_ALLOC(driverState) < 0) goto error; + + pthread_mutex_init(&driverState->lock, NULL); + networkDriverLock(driverState); if (!uid) { if (asprintf(&driverState->logDir, @@ -165,6 +182,8 @@ networkStartup(void) { networkAutostartConfigs(driverState); + networkDriverUnlock(driverState); + return 0; out_of_memory: @@ -172,6 +191,9 @@ out_of_memory: "%s", _("networkStartup: out of memory\n")); error: + if (driverState) + networkDriverUnlock(driverState); + VIR_FREE(base); networkShutdown(); return -1; @@ -188,6 +210,7 @@ networkReload(void) { if (!driverState) return 0; + networkDriverLock(driverState); virNetworkLoadAllConfigs(NULL, &driverState->networks, driverState->networkConfigDir, @@ -200,7 +223,7 @@ networkReload(void) { } networkAutostartConfigs(driverState); - + networkDriverUnlock(driverState); return 0; } @@ -220,12 +243,15 @@ networkActive(void) { if (!driverState) return 0; + networkDriverLock(driverState); for (i = 0 ; i < driverState->networks.count ; i++) { virNetworkObjPtr net = driverState->networks.objs[i]; + virNetworkObjLock(net); if (virNetworkIsActive(net)) active = 1; + virNetworkObjUnlock(net); } - + networkDriverUnlock(driverState); return active; } @@ -241,12 +267,16 @@ networkShutdown(void) { if (!driverState) return -1; + networkDriverLock(driverState); + /* shutdown active networks */ for (i = 0 ; i < driverState->networks.count ; i++) { virNetworkObjPtr net = driverState->networks.objs[i]; + virNetworkObjLock(net); if (virNetworkIsActive(net)) networkShutdownNetworkDaemon(NULL, driverState, driverState->networks.objs[i]); + virNetworkObjUnlock(net); } /* free inactive networks */ @@ -260,6 +290,8 @@ networkShutdown(void) { brShutdown(driverState->brctl); if (driverState->iptables) iptablesContextFree(driverState->iptables); + + networkDriverUnlock(driverState); VIR_FREE(driverState); @@ -801,10 +833,6 @@ static int networkShutdownNetworkDaemon( network->newDef = NULL; } - if (!network->configFile) - virNetworkRemoveInactive(&driver->networks, - network); - return 0; } @@ -815,7 +843,9 @@ static virNetworkPtr networkLookupByUUID virNetworkObjPtr network; virNetworkPtr ret = NULL; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, uuid); + networkDriverUnlock(driver); if (!network) { networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK, "%s", _("no network with matching uuid")); @@ -825,6 +855,8 @@ static virNetworkPtr networkLookupByUUID ret = virGetNetwork(conn, network->def->name, network->def->uuid); cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } @@ -834,7 +866,9 @@ static virNetworkPtr networkLookupByName virNetworkObjPtr network; virNetworkPtr ret = NULL; + networkDriverLock(driver); network = virNetworkFindByName(&driver->networks, name); + networkDriverUnlock(driver); if (!network) { networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK, "%s", _("no network with matching name")); @@ -844,6 +878,8 @@ static virNetworkPtr networkLookupByName ret = virGetNetwork(conn, network->def->name, network->def->uuid); cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } @@ -866,9 +902,14 @@ static int networkNumNetworks(virConnect int nactive = 0, i; struct network_driver *driver = conn->networkPrivateData; - for (i = 0 ; i < driver->networks.count ; i++) + networkDriverLock(driver); + for (i = 0 ; i < driver->networks.count ; i++) { + virNetworkObjLock(driver->networks.objs[i]); if (virNetworkIsActive(driver->networks.objs[i])) nactive++; + virNetworkObjUnlock(driver->networks.objs[i]); + } + networkDriverUnlock(driver); return nactive; } @@ -877,19 +918,26 @@ static int networkListNetworks(virConnec struct network_driver *driver = conn->networkPrivateData; int got = 0, i; + networkDriverLock(driver); for (i = 0 ; i < driver->networks.count && got < nnames ; i++) { + virNetworkObjLock(driver->networks.objs[i]); if (virNetworkIsActive(driver->networks.objs[i])) { if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) { + virNetworkObjUnlock(driver->networks.objs[i]); networkReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); goto cleanup; } got++; } + virNetworkObjUnlock(driver->networks.objs[i]); } + networkDriverUnlock(driver); + return got; cleanup: + networkDriverUnlock(driver); for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); return -1; @@ -899,9 +947,14 @@ static int networkNumDefinedNetworks(vir int ninactive = 0, i; struct network_driver *driver = conn->networkPrivateData; - for (i = 0 ; i < driver->networks.count ; i++) + networkDriverLock(driver); + for (i = 0 ; i < driver->networks.count ; i++) { + virNetworkObjLock(driver->networks.objs[i]); if (!virNetworkIsActive(driver->networks.objs[i])) ninactive++; + virNetworkObjUnlock(driver->networks.objs[i]); + } + networkDriverUnlock(driver); return ninactive; } @@ -910,19 +963,25 @@ static int networkListDefinedNetworks(vi struct network_driver *driver = conn->networkPrivateData; int got = 0, i; + networkDriverLock(driver); for (i = 0 ; i < driver->networks.count && got < nnames ; i++) { + virNetworkObjLock(driver->networks.objs[i]); if (!virNetworkIsActive(driver->networks.objs[i])) { if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) { + virNetworkObjUnlock(driver->networks.objs[i]); networkReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "%s", _("failed to allocate space for VM name string")); goto cleanup; } got++; } + virNetworkObjUnlock(driver->networks.objs[i]); } + networkDriverUnlock(driver); return got; cleanup: + networkDriverUnlock(driver); for (i = 0 ; i < got ; i++) VIR_FREE(names[i]); return -1; @@ -931,8 +990,10 @@ static virNetworkPtr networkCreate(virCo static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) { struct network_driver *driver = conn->networkPrivateData; virNetworkDefPtr def; - virNetworkObjPtr network; + virNetworkObjPtr network = NULL; virNetworkPtr ret = NULL; + + networkDriverLock(driver); if (!(def = virNetworkDefParseString(conn, xml))) goto cleanup; @@ -944,8 +1005,10 @@ static virNetworkPtr networkCreate(virCo def = NULL; if (networkStartNetworkDaemon(conn, driver, network) < 0) { + virNetworkObjUnlock(network); virNetworkRemoveInactive(&driver->networks, network); + network = NULL; goto cleanup; } @@ -953,14 +1016,19 @@ static virNetworkPtr networkCreate(virCo cleanup: virNetworkDefFree(def); + if (network) + virNetworkObjUnlock(network); + networkDriverUnlock(driver); return ret; } static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) { struct network_driver *driver = conn->networkPrivateData; virNetworkDefPtr def; - virNetworkObjPtr network; + virNetworkObjPtr network = NULL; virNetworkPtr ret = NULL; + + networkDriverLock(driver); if (!(def = virNetworkDefParseString(conn, xml))) goto cleanup; @@ -975,8 +1043,10 @@ static virNetworkPtr networkDefine(virCo driver->networkConfigDir, driver->networkAutostartDir, network) < 0) { + virNetworkObjUnlock(network); virNetworkRemoveInactive(&driver->networks, network); + network = NULL; goto cleanup; } @@ -984,13 +1054,18 @@ static virNetworkPtr networkDefine(virCo cleanup: virNetworkDefFree(def); + if (network) + virNetworkObjUnlock(network); + networkDriverUnlock(driver); return ret; } static int networkUndefine(virNetworkPtr net) { struct network_driver *driver = net->conn->networkPrivateData; - virNetworkObjPtr network; + virNetworkObjPtr network = NULL; int ret = -1; + + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); if (!network) { @@ -1008,11 +1083,16 @@ static int networkUndefine(virNetworkPtr if (virNetworkDeleteConfig(net->conn, network) < 0) goto cleanup; + virNetworkObjUnlock(network); virNetworkRemoveInactive(&driver->networks, network); + network = NULL; ret = 0; cleanup: + if (network) + virNetworkObjUnlock(network); + networkDriverUnlock(driver); return ret; } @@ -1021,7 +1101,10 @@ static int networkStart(virNetworkPtr ne virNetworkObjPtr network; int ret = -1; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); + if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); @@ -1031,6 +1114,8 @@ static int networkStart(virNetworkPtr ne ret = networkStartNetworkDaemon(net->conn, driver, network); cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } @@ -1039,7 +1124,10 @@ static int networkDestroy(virNetworkPtr virNetworkObjPtr network; int ret = -1; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); + if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); @@ -1047,8 +1135,15 @@ static int networkDestroy(virNetworkPtr } ret = networkShutdownNetworkDaemon(net->conn, driver, network); + if (!network->configFile) { + virNetworkRemoveInactive(&driver->networks, + network); + network = NULL; + } cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } @@ -1057,7 +1152,10 @@ static char *networkDumpXML(virNetworkPt virNetworkObjPtr network; char *ret = NULL; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); + if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); @@ -1067,6 +1165,8 @@ static char *networkDumpXML(virNetworkPt ret = virNetworkDefFormat(net->conn, network->def); cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } @@ -1075,7 +1175,10 @@ static char *networkGetBridgeName(virNet virNetworkObjPtr network; char *bridge = NULL; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); + if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching id")); @@ -1088,6 +1191,8 @@ static char *networkGetBridgeName(virNet "%s", _("failed to allocate space for network bridge string")); cleanup: + if (network) + virNetworkObjUnlock(network); return bridge; } @@ -1097,7 +1202,9 @@ static int networkGetAutostart(virNetwor virNetworkObjPtr network; int ret = -1; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); @@ -1108,6 +1215,8 @@ static int networkGetAutostart(virNetwor ret = 0; cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } @@ -1117,7 +1226,10 @@ static int networkSetAutostart(virNetwor virNetworkObjPtr network; int ret = -1; + networkDriverLock(driver); network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); + if (!network) { networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK, "%s", _("no network with matching uuid")); @@ -1157,6 +1269,8 @@ static int networkSetAutostart(virNetwor ret = 0; cleanup: + if (network) + virNetworkObjUnlock(network); return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:55:51PM +0000, Daniel P. Berrange wrote:
This patch makes the network driver thread safe, following the pattern of the earlier patches
@@ -95,6 +107,7 @@ networkAutostartConfigs(struct network_d unsigned int i;
Hum, you're not locking the driver itself during the loop ? If a concurrent call were to remove one of the network object in the meantime, that would lead to potentially random memory accesses no ?
for (i = 0 ; i < driver->networks.count ; i++) { + virNetworkObjLock(driver->networks.objs[i]); if (driver->networks.objs[i]->autostart && !virNetworkIsActive(driver->networks.objs[i]) && networkStartNetworkDaemon(NULL, driver, driver->networks.objs[i]) < 0) { @@ -103,6 +116,7 @@ networkAutostartConfigs(struct network_d driver->networks.objs[i]->def->name, err ? err->message : NULL); } + virNetworkObjUnlock(driver->networks.objs[i]); } }
[...]
cleanup: + if (network) + virNetworkObjUnlock(network);
like for domain, I would suggest the unlocking accessor to accept NULL and drop all the if constructs If there is a good reason networkAutostartConfigs() doesn't need to lock the top level driver lock, okay, otherwise +1 after fix, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Dec 03, 2008 at 10:32:58AM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:55:51PM +0000, Daniel P. Berrange wrote:
This patch makes the network driver thread safe, following the pattern of the earlier patches
@@ -95,6 +107,7 @@ networkAutostartConfigs(struct network_d unsigned int i;
Hum, you're not locking the driver itself during the loop ? If a concurrent call were to remove one of the network object in the meantime, that would lead to potentially random memory accesses no ?
There are only two callers of this method, and they both already hold the driver lock - networkStartup() and networkReload().
[...]
cleanup: + if (network) + virNetworkObjUnlock(network);
like for domain, I would suggest the unlocking accessor to accept NULL and drop all the if constructs
I've thought about doing that, but wasn't really sure whether it was good idea or not. I thought it might hide bugs, but on balance it would certainly simplify alot of code. If people generally think its worth allowing NULL in the Unlock routine, i'll make it so. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Dec 03, 2008 at 09:44:50AM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 10:32:58AM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:55:51PM +0000, Daniel P. Berrange wrote:
This patch makes the network driver thread safe, following the pattern of the earlier patches
@@ -95,6 +107,7 @@ networkAutostartConfigs(struct network_d unsigned int i;
Hum, you're not locking the driver itself during the loop ? If a concurrent call were to remove one of the network object in the meantime, that would lead to potentially random memory accesses no ?
There are only two callers of this method, and they both already hold the driver lock - networkStartup() and networkReload().
I realized that when digging more in the storage case... see next mail :-)
cleanup: + if (network) + virNetworkObjUnlock(network);
like for domain, I would suggest the unlocking accessor to accept NULL and drop all the if constructs
I've thought about doing that, but wasn't really sure whether it was good idea or not. I thought it might hide bugs, but on balance it would certainly simplify alot of code. If people generally think its worth allowing NULL in the Unlock routine, i'll make it so.
well we did a similar change for freeing ... Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Daniel Veillard <veillard@redhat.com> wrote:
On Wed, Dec 03, 2008 at 09:44:50AM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 10:32:58AM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:55:51PM +0000, Daniel P. Berrange wrote:
This patch makes the network driver thread safe, following the pattern of the earlier patches
@@ -95,6 +107,7 @@ networkAutostartConfigs(struct network_d unsigned int i;
Hum, you're not locking the driver itself during the loop ? If a concurrent call were to remove one of the network object in the meantime, that would lead to potentially random memory accesses no ?
There are only two callers of this method, and they both already hold the driver lock - networkStartup() and networkReload().
I realized that when digging more in the storage case... see next mail :-)
cleanup: + if (network) + virNetworkObjUnlock(network);
like for domain, I would suggest the unlocking accessor to accept NULL and drop all the if constructs
I've thought about doing that, but wasn't really sure whether it was good idea or not. I thought it might hide bugs, but on balance it would certainly simplify alot of code. If people generally think its worth allowing NULL in the Unlock routine, i'll make it so.
well we did a similar change for freeing ...
And if you do that, you can automatically detect any unnecessary if-before-unlock tests by adding virNetworkObjUnlock to the useless_free_options list in Makefile.cfg ;-)

This patch reduces the number of return points in the storage driver methods storage_driver.c | 570 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 313 insertions(+), 257 deletions(-) Daniel diff --git a/src/storage_driver.c b/src/storage_driver.c --- a/src/storage_driver.c +++ b/src/storage_driver.c @@ -254,36 +254,40 @@ static virStoragePoolPtr static virStoragePoolPtr storagePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, uuid); - virStoragePoolPtr ret; + virStorageDriverStatePtr driver = conn->storagePrivateData; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; + pool = virStoragePoolObjFindByUUID(&driver->pools, uuid); if (!pool) { virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL, "%s", _("no pool with matching uuid")); - return NULL; + goto cleanup; } ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: return ret; } static virStoragePoolPtr storagePoolLookupByName(virConnectPtr conn, const char *name) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, name); - virStoragePoolPtr ret; + virStorageDriverStatePtr driver = conn->storagePrivateData; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; + pool = virStoragePoolObjFindByName(&driver->pools, name); if (!pool) { virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL, "%s", _("no pool with matching name")); - return NULL; + goto cleanup; } ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: return ret; } @@ -311,8 +315,7 @@ storageClose(virConnectPtr conn) { static int storageNumPools(virConnectPtr conn) { - virStorageDriverStatePtr driver - = (virStorageDriverStatePtr)conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i, nactive = 0; for (i = 0 ; i < driver->pools.count ; i++) @@ -326,8 +329,7 @@ storageListPools(virConnectPtr conn, storageListPools(virConnectPtr conn, char **const names, int nnames) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; int got = 0, i; for (i = 0 ; i < driver->pools.count && got < nnames ; i++) { @@ -353,8 +355,7 @@ storageListPools(virConnectPtr conn, static int storageNumDefinedPools(virConnectPtr conn) { - virStorageDriverStatePtr driver - = (virStorageDriverStatePtr)conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i, nactive = 0; for (i = 0 ; i < driver->pools.count ; i++) @@ -368,8 +369,7 @@ storageListDefinedPools(virConnectPtr co storageListDefinedPools(virConnectPtr conn, char **const names, int nnames) { - virStorageDriverStatePtr driver - = (virStorageDriverStatePtr)conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; int got = 0, i; for (i = 0 ; i < driver->pools.count && got < nnames ; i++) { @@ -401,19 +401,21 @@ storageFindPoolSources(virConnectPtr con { int backend_type; virStorageBackendPtr backend; + char *ret = NULL; backend_type = virStoragePoolTypeFromString(type); if (backend_type < 0) - return NULL; + goto cleanup; backend = virStorageBackendForType(backend_type); if (backend == NULL) - return NULL; + goto cleanup; if (backend->findPoolSources) - return backend->findPoolSources(conn, srcSpec, flags); + ret = backend->findPoolSources(conn, srcSpec, flags); - return NULL; +cleanup: + return ret; } @@ -421,46 +423,47 @@ storagePoolCreate(virConnectPtr conn, storagePoolCreate(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr )conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; virStoragePoolDefPtr def; virStoragePoolObjPtr pool; - virStoragePoolPtr ret; + virStoragePoolPtr ret = NULL; virStorageBackendPtr backend; if (!(def = virStoragePoolDefParse(conn, xml, NULL))) - return NULL; + goto cleanup; - if (virStoragePoolObjFindByUUID(&driver->pools, def->uuid) || - virStoragePoolObjFindByName(&driver->pools, def->name)) { + pool = virStoragePoolObjFindByUUID(&driver->pools, def->uuid); + if (!pool) + pool = virStoragePoolObjFindByName(&driver->pools, def->name); + + if (pool) { virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool already exists")); - virStoragePoolDefFree(def); - return NULL; + goto cleanup; } - if ((backend = virStorageBackendForType(def->type)) == NULL) { - virStoragePoolDefFree(def); - return NULL; - } + if ((backend = virStorageBackendForType(def->type)) == NULL) + goto cleanup; - if (!(pool = virStoragePoolObjAssignDef(conn, &driver->pools, def))) { - virStoragePoolDefFree(def); - return NULL; - } + if (!(pool = virStoragePoolObjAssignDef(conn, &driver->pools, def))) + goto cleanup; + def = NULL; if (backend->startPool && backend->startPool(conn, pool) < 0) - return NULL; + goto cleanup; + if (backend->refreshPool(conn, pool) < 0) { if (backend->stopPool) backend->stopPool(conn, pool); - return NULL; + goto cleanup; } pool->active = 1; ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); +cleanup: + virStoragePoolDefFree(def); return ret; } @@ -468,55 +471,55 @@ storagePoolDefine(virConnectPtr conn, storagePoolDefine(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver - = (virStorageDriverStatePtr )conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; virStoragePoolDefPtr def; virStoragePoolObjPtr pool; - virStoragePoolPtr ret; + virStoragePoolPtr ret = NULL; virStorageBackendPtr backend; if (!(def = virStoragePoolDefParse(conn, xml, NULL))) - return NULL; + goto cleanup; - if ((backend = virStorageBackendForType(def->type)) == NULL) { - virStoragePoolDefFree(def); - return NULL; - } + if ((backend = virStorageBackendForType(def->type)) == NULL) + goto cleanup; - if (!(pool = virStoragePoolObjAssignDef(conn, &driver->pools, def))) { - virStoragePoolDefFree(def); - return NULL; - } + if (!(pool = virStoragePoolObjAssignDef(conn, &driver->pools, def))) + goto cleanup; + def = NULL; if (virStoragePoolObjSaveDef(conn, driver, pool, def) < 0) { virStoragePoolObjRemove(&driver->pools, pool); - return NULL; + goto cleanup; } ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); + +cleanup: + virStoragePoolDefFree(def); return ret; } static int storagePoolUndefine(virStoragePoolPtr obj) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } if (virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("pool is still active")); - return -1; + goto cleanup; } if (virStoragePoolObjDeleteDef(obj->conn, pool) < 0) - return -1; + goto cleanup; if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) storageLog("Failed to delete autostart link '%s': %s", @@ -526,105 +529,112 @@ storagePoolUndefine(virStoragePoolPtr ob VIR_FREE(pool->autostartLink); virStoragePoolObjRemove(&driver->pools, pool); + ret = 0; - return 0; +cleanup: + return ret; } static int storagePoolStart(virStoragePoolPtr obj, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } - if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { - return -1; - } + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) + goto cleanup; if (virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("pool already active")); - return -1; + goto cleanup; } if (backend->startPool && backend->startPool(obj->conn, pool) < 0) - return -1; + goto cleanup; + if (backend->refreshPool(obj->conn, pool) < 0) { if (backend->stopPool) backend->stopPool(obj->conn, pool); - return -1; + goto cleanup; } pool->active = 1; + ret = 0; - return 0; +cleanup: + return ret; } static int storagePoolBuild(virStoragePoolPtr obj, unsigned int flags) { - virStorageDriverStatePtr driver - = (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } - if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { - return -1; - } + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) + goto cleanup; if (virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is already active")); - return -1; + goto cleanup; } if (backend->buildPool && backend->buildPool(obj->conn, pool, flags) < 0) - return -1; + goto cleanup; + ret = 0; - return 0; +cleanup: + return ret; } static int storagePoolDestroy(virStoragePoolPtr obj) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } - if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { - return -1; - } + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) + goto cleanup; if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return -1; + goto cleanup; } if (backend->stopPool && backend->stopPool(obj->conn, pool) < 0) - return -1; + goto cleanup; virStoragePoolObjClearVols(pool); @@ -632,74 +642,77 @@ storagePoolDestroy(virStoragePoolPtr obj if (pool->configFile == NULL) virStoragePoolObjRemove(&driver->pools, pool); + ret = 0; - return 0; +cleanup: + return ret; } static int storagePoolDelete(virStoragePoolPtr obj, unsigned int flags) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } - if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { - return -1; - } + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) + goto cleanup; if (virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is still active")); - return -1; + goto cleanup; } if (!backend->deletePool) { virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT, "%s", _("pool does not support volume delete")); - return -1; + goto cleanup; } if (backend->deletePool(obj->conn, pool, flags) < 0) - return -1; + goto cleanup; + ret = 0; - return 0; +cleanup: + return ret; } static int storagePoolRefresh(virStoragePoolPtr obj, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; - int ret = 0; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } - if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { - return -1; - } + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) + goto cleanup; if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return -1; + goto cleanup; } virStoragePoolObjClearVols(pool); - if ((ret = backend->refreshPool(obj->conn, pool)) < 0) { + if (backend->refreshPool(obj->conn, pool) < 0) { if (backend->stopPool) backend->stopPool(obj->conn, pool); @@ -707,8 +720,11 @@ storagePoolRefresh(virStoragePoolPtr obj if (pool->configFile == NULL) virStoragePoolObjRemove(&driver->pools, pool); + goto cleanup; } + ret = 0; +cleanup: return ret; } @@ -716,20 +732,20 @@ static int static int storagePoolGetInfo(virStoragePoolPtr obj, virStoragePoolInfoPtr info) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } - if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { - return -1; - } + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) + goto cleanup; memset(info, 0, sizeof(virStoragePoolInfo)); if (pool->active) @@ -739,37 +755,44 @@ storagePoolGetInfo(virStoragePoolPtr obj info->capacity = pool->def->capacity; info->allocation = pool->def->allocation; info->available = pool->def->available; + ret = 0; - return 0; +cleanup: + return ret; } static char * storagePoolDumpXML(virStoragePoolPtr obj, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; + char *ret = NULL; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return NULL; + goto cleanup; } - return virStoragePoolDefFormat(obj->conn, pool->def); + ret = virStoragePoolDefFormat(obj->conn, pool->def); + +cleanup: + return ret; } static int storagePoolGetAutostart(virStoragePoolPtr obj, int *autostart) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no pool with matching uuid")); - return -1; + goto cleanup; } if (!pool->configFile) { @@ -777,110 +800,118 @@ storagePoolGetAutostart(virStoragePoolPt } else { *autostart = pool->autostart; } + ret = 0; - return 0; +cleanup: + return ret; } static int storagePoolSetAutostart(virStoragePoolPtr obj, int autostart) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no pool with matching uuid")); - return -1; + goto cleanup; } if (!pool->configFile) { virStorageReportError(obj->conn, VIR_ERR_INVALID_ARG, "%s", _("pool has no config file")); - return -1; + goto cleanup; } autostart = (autostart != 0); - if (pool->autostart == autostart) - return 0; + if (pool->autostart != autostart) { + if (autostart) { + int err; - if (autostart) { - int err; + if ((err = virFileMakePath(driver->autostartDir))) { + virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, + _("cannot create autostart directory %s: %s"), + driver->autostartDir, strerror(err)); + goto cleanup; + } - if ((err = virFileMakePath(driver->autostartDir))) { - virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, - _("cannot create autostart directory %s: %s"), - driver->autostartDir, strerror(err)); - return -1; + if (symlink(pool->configFile, pool->autostartLink) < 0) { + virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to create symlink '%s' to '%s': %s"), + pool->autostartLink, pool->configFile, + strerror(errno)); + goto cleanup; + } + } else { + if (unlink(pool->autostartLink) < 0 && + errno != ENOENT && errno != ENOTDIR) { + virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, + _("Failed to delete symlink '%s': %s"), + pool->autostartLink, strerror(errno)); + goto cleanup; + } } - if (symlink(pool->configFile, pool->autostartLink) < 0) { - virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, - _("Failed to create symlink '%s' to '%s': %s"), - pool->autostartLink, pool->configFile, - strerror(errno)); - return -1; - } - } else { - if (unlink(pool->autostartLink) < 0 && - errno != ENOENT && errno != ENOTDIR) { - virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, - _("Failed to delete symlink '%s': %s"), - pool->autostartLink, strerror(errno)); - return -1; - } + pool->autostart = autostart; } + ret = 0; - pool->autostart = autostart; - - return 0; +cleanup: + return ret; } static int storagePoolNumVolumes(virStoragePoolPtr obj) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; + int ret = -1; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return -1; + goto cleanup; } + ret = pool->volumes.count; - return pool->volumes.count; +cleanup: + return ret; } static int storagePoolListVolumes(virStoragePoolPtr obj, char **const names, int maxnames) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; int i, n = 0; + memset(names, 0, maxnames); + + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return -1; + goto cleanup; } - memset(names, 0, maxnames); for (i = 0 ; i < pool->volumes.count && n < maxnames ; i++) { if ((names[n++] = strdup(pool->volumes.objs[i]->name)) == NULL) { virStorageReportError(obj->conn, VIR_ERR_NO_MEMORY, @@ -893,7 +924,7 @@ storagePoolListVolumes(virStoragePoolPtr cleanup: for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[i]); + VIR_FREE(names[n]); memset(names, 0, maxnames); return -1; @@ -903,21 +934,22 @@ static virStorageVolPtr static virStorageVolPtr storageVolumeLookupByName(virStoragePoolPtr obj, const char *name) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageVolDefPtr vol; + virStorageVolPtr ret = NULL; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return NULL; + goto cleanup; } vol = virStorageVolDefFindByName(pool, name); @@ -925,44 +957,51 @@ storageVolumeLookupByName(virStoragePool if (!vol) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage vol with matching name")); - return NULL; + goto cleanup; } - return virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key); + ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key); + +cleanup: + return ret; } static virStorageVolPtr storageVolumeLookupByKey(virConnectPtr conn, const char *key) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i; + virStorageVolPtr ret = NULL; for (i = 0 ; i < driver->pools.count ; i++) { if (virStoragePoolObjIsActive(driver->pools.objs[i])) { virStorageVolDefPtr vol = virStorageVolDefFindByKey(driver->pools.objs[i], key); - if (vol) - return virGetStorageVol(conn, + if (vol) { + ret = virGetStorageVol(conn, driver->pools.objs[i]->def->name, vol->name, vol->key); + break; + } } } - virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL, - "%s", _("no storage vol with matching key")); - return NULL; + if (!ret) + virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL, + "%s", _("no storage vol with matching key")); + + return ret; } static virStorageVolPtr storageVolumeLookupByPath(virConnectPtr conn, const char *path) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)conn->storagePrivateData; + virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i; + virStorageVolPtr ret = NULL; for (i = 0 ; i < driver->pools.count ; i++) { if (virStoragePoolObjIsActive(driver->pools.objs[i])) { @@ -978,132 +1017,140 @@ storageVolumeLookupByPath(virConnectPtr * propagating the return code */ if (stable_path == NULL) - return NULL; + goto cleanup; vol = virStorageVolDefFindByPath(driver->pools.objs[i], stable_path); VIR_FREE(stable_path); - if (vol) - return virGetStorageVol(conn, - driver->pools.objs[i]->def->name, - vol->name, - vol->key); + if (vol) { + ret = virGetStorageVol(conn, + driver->pools.objs[i]->def->name, + vol->name, + vol->key); + break; + } } } - virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL, - "%s", _("no storage vol with matching path")); - return NULL; + if (!ret) + virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL, + "%s", _("no storage vol with matching path")); + +cleanup: + return ret; } static virStorageVolPtr storageVolumeCreateXML(virStoragePoolPtr obj, const char *xmldesc, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; - virStorageVolDefPtr vol; + virStorageVolDefPtr vol = NULL; + virStorageVolPtr ret = NULL; + pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return NULL; + goto cleanup; } if ((backend = virStorageBackendForType(pool->def->type)) == NULL) - return NULL; + goto cleanup; vol = virStorageVolDefParse(obj->conn, pool->def, xmldesc, NULL); if (vol == NULL) - return NULL; + goto cleanup; if (virStorageVolDefFindByName(pool, vol->name)) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("storage vol already exists")); - virStorageVolDefFree(vol); - return NULL; + goto cleanup; } if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count+1) < 0) { virStorageReportError(obj->conn, VIR_ERR_NO_MEMORY, NULL); - virStorageVolDefFree(vol); - return NULL; + goto cleanup; } if (!backend->createVol) { virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT, "%s", _("storage pool does not support volume creation")); - virStorageVolDefFree(vol); - return NULL; + goto cleanup; } if (backend->createVol(obj->conn, pool, vol) < 0) { - virStorageVolDefFree(vol); - return NULL; + goto cleanup; } pool->volumes.objs[pool->volumes.count++] = vol; + vol = NULL; - return virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key); + ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key); + +cleanup: + virStorageVolDefFree(vol); + return ret; } static int storageVolumeDelete(virStorageVolPtr obj, unsigned int flags) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; - virStorageVolDefPtr vol; + virStorageVolDefPtr vol = NULL; unsigned int i; + int ret = -1; + pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return -1; + goto cleanup; } if ((backend = virStorageBackendForType(pool->def->type)) == NULL) - return -1; + goto cleanup; vol = virStorageVolDefFindByName(pool, obj->name); if (!vol) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage vol with matching name")); - return -1; + goto cleanup; } if (!backend->deleteVol) { virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT, "%s", _("storage pool does not support vol deletion")); - virStorageVolDefFree(vol); - return -1; + + goto cleanup; } - if (backend->deleteVol(obj->conn, pool, vol, flags) < 0) { - return -1; - } + if (backend->deleteVol(obj->conn, pool, vol, flags) < 0) + goto cleanup; for (i = 0 ; i < pool->volumes.count ; i++) { if (pool->volumes.objs[i] == vol) { virStorageVolDefFree(vol); + vol = NULL; if (i < (pool->volumes.count - 1)) memmove(pool->volumes.objs + i, pool->volumes.objs + i + 1, @@ -1117,29 +1164,33 @@ storageVolumeDelete(virStorageVolPtr obj break; } } + ret = 0; - return 0; +cleanup: + virStorageVolDefFree(vol); + return ret; } static int storageVolumeGetInfo(virStorageVolPtr obj, virStorageVolInfoPtr info) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; virStorageVolDefPtr vol; + int ret = -1; + pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return -1; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return -1; + goto cleanup; } vol = virStorageVolDefFindByName(pool, obj->name); @@ -1147,43 +1198,46 @@ storageVolumeGetInfo(virStorageVolPtr ob if (!vol) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage vol with matching name")); - return -1; + goto cleanup; } if ((backend = virStorageBackendForType(pool->def->type)) == NULL) - return -1; + goto cleanup; if (backend->refreshVol && backend->refreshVol(obj->conn, pool, vol) < 0) - return -1; + goto cleanup; memset(info, 0, sizeof(*info)); info->type = vol->type; info->capacity = vol->capacity; info->allocation = vol->allocation; + ret = 0; - return 0; +cleanup: + return ret; } static char * storageVolumeGetXMLDesc(virStorageVolPtr obj, unsigned int flags ATTRIBUTE_UNUSED) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; + virStoragePoolObjPtr pool; virStorageBackendPtr backend; virStorageVolDefPtr vol; + char *ret = NULL; + pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return NULL; + goto cleanup; } vol = virStorageVolDefFindByName(pool, obj->name); @@ -1191,33 +1245,35 @@ storageVolumeGetXMLDesc(virStorageVolPtr if (!vol) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage vol with matching name")); - return NULL; + goto cleanup; } if ((backend = virStorageBackendForType(pool->def->type)) == NULL) - return NULL; + goto cleanup; - return virStorageVolDefFormat(obj->conn, pool->def, vol); + ret = virStorageVolDefFormat(obj->conn, pool->def, vol); + +cleanup: + return ret; } static char * storageVolumeGetPath(virStorageVolPtr obj) { - virStorageDriverStatePtr driver = - (virStorageDriverStatePtr)obj->conn->storagePrivateData; + virStorageDriverStatePtr driver = obj->conn->storagePrivateData; virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); virStorageVolDefPtr vol; - char *ret; + char *ret = NULL; if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); - return NULL; + goto cleanup; } if (!virStoragePoolObjIsActive(pool)) { virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("storage pool is not active")); - return NULL; + goto cleanup; } vol = virStorageVolDefFindByName(pool, obj->name); @@ -1225,14 +1281,14 @@ storageVolumeGetPath(virStorageVolPtr ob if (!vol) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage vol with matching name")); - return NULL; + goto cleanup; } ret = strdup(vol->target.path); - if (ret == NULL) { + if (ret == NULL) virStorageReportError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("path")); - return NULL; - } + +cleanup: return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

"Daniel P. Berrange" <berrange@redhat.com> wrote:
This patch reduces the number of return points in the storage driver methods ... diff --git a/src/storage_driver.c b/src/storage_driver.c ... @@ -893,7 +924,7 @@ storagePoolListVolumes(virStoragePoolPtr
cleanup: for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[i]); + VIR_FREE(names[n]);
memset(names, 0, maxnames); return -1;
This might be worth putting in a separate bug-fix patch. At first I thought this was fixing a serious bug, but you can see that i is always smaller than maxnames, so the fix is just plugging a leak. However, in looking at this I spotted a real problem: There are numerous statements like this: memset(names, 0, maxnames); That zeros out only 1/4 or 1/8 of the memory it should. It should be doing this: memset(names, 0, maxnames * sizeof (*names)); These bugs are independent of your 28-part patch, Dan, i.e., also on the trunk: $ git grep memset.names|grep -v sizeof src/storage_driver.c: memset(names, 0, nnames); src/storage_driver.c: memset(names, 0, nnames); src/storage_driver.c: memset(names, 0, maxnames); src/storage_driver.c: memset(names, 0, maxnames); src/test.c: memset(names, 0, maxnames); src/test.c: memset(names, 0, maxnames); I'll post the fix (relative to the trunk) separately.

On Tue, Dec 02, 2008 at 03:02:17PM +0100, Jim Meyering wrote:
"Daniel P. Berrange" <berrange@redhat.com> wrote:
This patch reduces the number of return points in the storage driver methods ... diff --git a/src/storage_driver.c b/src/storage_driver.c ... @@ -893,7 +924,7 @@ storagePoolListVolumes(virStoragePoolPtr
cleanup: for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[i]); + VIR_FREE(names[n]);
memset(names, 0, maxnames); return -1;
This might be worth putting in a separate bug-fix patch. At first I thought this was fixing a serious bug, but you can see that i is always smaller than maxnames, so the fix is just plugging a leak.
However, in looking at this I spotted a real problem: There are numerous statements like this:
memset(names, 0, maxnames);
That zeros out only 1/4 or 1/8 of the memory it should. It should be doing this:
memset(names, 0, maxnames * sizeof (*names));
memset() is horribly error prone - also have the classic of getting the 2 & 3rd args the wrong way around. How about adding to memory.h something like #define VIR_ZERO(buf, nelement) \ memset(buf, 0, sizeof(*(buf)) * nelement) also using your xalloc_oversized magic ? Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

"Daniel P. Berrange" <berrange@redhat.com> wrote:
On Tue, Dec 02, 2008 at 03:02:17PM +0100, Jim Meyering wrote:
"Daniel P. Berrange" <berrange@redhat.com> wrote:
This patch reduces the number of return points in the storage driver methods ... diff --git a/src/storage_driver.c b/src/storage_driver.c ... @@ -893,7 +924,7 @@ storagePoolListVolumes(virStoragePoolPtr
cleanup: for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[i]); + VIR_FREE(names[n]);
memset(names, 0, maxnames); return -1;
This might be worth putting in a separate bug-fix patch. At first I thought this was fixing a serious bug, but you can see that i is always smaller than maxnames, so the fix is just plugging a leak.
However, in looking at this I spotted a real problem: There are numerous statements like this:
memset(names, 0, maxnames);
That zeros out only 1/4 or 1/8 of the memory it should. It should be doing this:
memset(names, 0, maxnames * sizeof (*names));
memset() is horribly error prone - also have the classic of getting the 2 & 3rd args the wrong way around. How about adding to memory.h something like
#define VIR_ZERO(buf, nelement) \ memset(buf, 0, sizeof(*(buf)) * nelement)
Sure, I'll do that after your 28-part change goes in. But how about a more generic name like MEM_ZERO? #define MEM_ZERO(buf, nelement) \ memset((buf), 0, sizeof(*(buf)) * (nelement))
also using your xalloc_oversized magic ?
If you want to automatically handle oversized memset, we'd have to make it a function and change all users to test the return value. That'd be pretty invasive. With malloc/realloc/calloc, where everyone was already testing the return value, it was easy. But testing memset's return value isn't useful, so no one does that. An alternative is to abort on detection of an oversized count*size. That's not library friendly at all, but better than memory corruption or other run-time misbehavior.

On Tue, Dec 02, 2008 at 03:32:28PM +0100, Jim Meyering wrote:
"Daniel P. Berrange" <berrange@redhat.com> wrote:
On Tue, Dec 02, 2008 at 03:02:17PM +0100, Jim Meyering wrote:
"Daniel P. Berrange" <berrange@redhat.com> wrote:
This patch reduces the number of return points in the storage driver methods ... diff --git a/src/storage_driver.c b/src/storage_driver.c ... @@ -893,7 +924,7 @@ storagePoolListVolumes(virStoragePoolPtr
cleanup: for (n = 0 ; n < maxnames ; n++) - VIR_FREE(names[i]); + VIR_FREE(names[n]);
memset(names, 0, maxnames); return -1;
This might be worth putting in a separate bug-fix patch. At first I thought this was fixing a serious bug, but you can see that i is always smaller than maxnames, so the fix is just plugging a leak.
However, in looking at this I spotted a real problem: There are numerous statements like this:
memset(names, 0, maxnames);
That zeros out only 1/4 or 1/8 of the memory it should. It should be doing this:
memset(names, 0, maxnames * sizeof (*names));
memset() is horribly error prone - also have the classic of getting the 2 & 3rd args the wrong way around. How about adding to memory.h something like
#define VIR_ZERO(buf, nelement) \ memset(buf, 0, sizeof(*(buf)) * nelement)
Sure, I'll do that after your 28-part change goes in.
But how about a more generic name like MEM_ZERO?
#define MEM_ZERO(buf, nelement) \ memset((buf), 0, sizeof(*(buf)) * (nelement))
Sure, works for me.
also using your xalloc_oversized magic ?
If you want to automatically handle oversized memset, we'd have to make it a function and change all users to test the return value. That'd be pretty invasive. With malloc/realloc/calloc, where everyone was already testing the return value, it was easy. But testing memset's return value isn't useful, so no one does that.
Ok, lets ignore that bit of the idea - chances are the caller will already have had the check for oversized data when they allocated the array they're passing. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch makes the storage driver thread safe storage_conf.h | 2 storage_driver.c | 240 +++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 202 insertions(+), 40 deletions(-) Daniel diff --git a/src/storage_conf.h b/src/storage_conf.h --- a/src/storage_conf.h +++ b/src/storage_conf.h @@ -248,6 +248,8 @@ typedef virStorageDriverState *virStorag typedef virStorageDriverState *virStorageDriverStatePtr; struct _virStorageDriverState { + PTHREAD_MUTEX_T(lock); + virStoragePoolObjList pools; char *configDir; diff --git a/src/storage_driver.c b/src/storage_driver.c --- a/src/storage_driver.c +++ b/src/storage_driver.c @@ -47,6 +47,14 @@ static virStorageDriverStatePtr driverSt static int storageDriverShutdown(void); +static void storageDriverLock(virStorageDriverStatePtr driver) +{ + pthread_mutex_lock(&driver->lock); +} +static void storageDriverUnlock(virStorageDriverStatePtr driver) +{ + pthread_mutex_unlock(&driver->lock); +} static void storageDriverAutostart(virStorageDriverStatePtr driver) { @@ -100,6 +108,9 @@ storageDriverStartup(void) { if (VIR_ALLOC(driverState) < 0) return -1; + pthread_mutex_init(&driverState->lock, NULL); + storageDriverLock(driverState); + if (!uid) { if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL) goto out_of_memory; @@ -132,8 +143,7 @@ storageDriverStartup(void) { "%s/storage/autostart", base) == -1) goto out_of_memory; - free(base); - base = NULL; + VIR_FREE(base); /* if (virStorageLoadDriverConfig(driver, driverConf) < 0) { @@ -145,19 +155,19 @@ storageDriverStartup(void) { if (virStoragePoolLoadAllConfigs(NULL, &driverState->pools, driverState->configDir, - driverState->autostartDir) < 0) { - storageDriverShutdown(); - return -1; - } + driverState->autostartDir) < 0) + goto error; storageDriverAutostart(driverState); + storageDriverUnlock(driverState); return 0; - out_of_memory: +out_of_memory: storageLog("virStorageStartup: out of memory"); - free(base); - free(driverState); - driverState = NULL; +error: + VIR_FREE(base); + storageDriverUnlock(driverState); + storageDriverShutdown(); return -1; } @@ -172,11 +182,13 @@ storageDriverReload(void) { if (!driverState) return -1; + storageDriverLock(driverState); virStoragePoolLoadAllConfigs(NULL, &driverState->pools, driverState->configDir, driverState->autostartDir); storageDriverAutostart(driverState); + storageDriverUnlock(driverState); return 0; } @@ -191,19 +203,22 @@ static int static int storageDriverActive(void) { unsigned int i; + int active = 0; if (!driverState) return 0; - /* If we've any active networks or guests, then we - * mark this driver as active - */ - for (i = 0 ; i < driverState->pools.count ; i++) + storageDriverLock(driverState); + + for (i = 0 ; i < driverState->pools.count ; i++) { + virStoragePoolObjLock(driverState->pools.objs[i]); if (virStoragePoolObjIsActive(driverState->pools.objs[i])) - return 1; + active = 1; + virStoragePoolObjUnlock(driverState->pools.objs[i]); + } - /* Otherwise we're happy to deal with a shutdown */ - return 0; + storageDriverUnlock(driverState); + return active; } /** @@ -218,6 +233,7 @@ storageDriverShutdown(void) { if (!driverState) return -1; + storageDriverLock(driverState); /* shutdown active pools */ for (i = 0 ; i < driverState->pools.count ; i++) { virStoragePoolObjPtr pool = driverState->pools.objs[i]; @@ -244,6 +260,7 @@ storageDriverShutdown(void) { VIR_FREE(driverState->configDir); VIR_FREE(driverState->autostartDir); + storageDriverUnlock(driverState); VIR_FREE(driverState); return 0; @@ -258,7 +275,10 @@ storagePoolLookupByUUID(virConnectPtr co virStoragePoolObjPtr pool; virStoragePoolPtr ret = NULL; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL, "%s", _("no pool with matching uuid")); @@ -268,6 +288,8 @@ storagePoolLookupByUUID(virConnectPtr co ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -278,7 +300,10 @@ storagePoolLookupByName(virConnectPtr co virStoragePoolObjPtr pool; virStoragePoolPtr ret = NULL; + storageDriverLock(driver); pool = virStoragePoolObjFindByName(&driver->pools, name); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL, "%s", _("no pool with matching name")); @@ -288,6 +313,8 @@ storagePoolLookupByName(virConnectPtr co ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -318,9 +345,14 @@ storageNumPools(virConnectPtr conn) { virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i, nactive = 0; - for (i = 0 ; i < driver->pools.count ; i++) + storageDriverLock(driver); + for (i = 0 ; i < driver->pools.count ; i++) { + virStoragePoolObjLock(driver->pools.objs[i]); if (virStoragePoolObjIsActive(driver->pools.objs[i])) nactive++; + virStoragePoolObjUnlock(driver->pools.objs[i]); + } + storageDriverUnlock(driver); return nactive; } @@ -332,23 +364,27 @@ storageListPools(virConnectPtr conn, virStorageDriverStatePtr driver = conn->storagePrivateData; int got = 0, i; + storageDriverLock(driver); for (i = 0 ; i < driver->pools.count && got < nnames ; i++) { + virStoragePoolObjLock(driver->pools.objs[i]); if (virStoragePoolObjIsActive(driver->pools.objs[i])) { if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) { + virStoragePoolObjUnlock(driver->pools.objs[i]); virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("names")); goto cleanup; } got++; } + virStoragePoolObjUnlock(driver->pools.objs[i]); } + storageDriverUnlock(driver); return got; cleanup: - for (i = 0 ; i < got ; i++) { - free(names[i]); - names[i] = NULL; - } + storageDriverUnlock(driver); + for (i = 0 ; i < got ; i++) + VIR_FREE(names[i]); memset(names, 0, nnames); return -1; } @@ -358,9 +394,14 @@ storageNumDefinedPools(virConnectPtr con virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i, nactive = 0; - for (i = 0 ; i < driver->pools.count ; i++) + storageDriverLock(driver); + for (i = 0 ; i < driver->pools.count ; i++) { + virStoragePoolObjLock(driver->pools.objs[i]); if (!virStoragePoolObjIsActive(driver->pools.objs[i])) nactive++; + virStoragePoolObjUnlock(driver->pools.objs[i]); + } + storageDriverUnlock(driver); return nactive; } @@ -372,19 +413,25 @@ storageListDefinedPools(virConnectPtr co virStorageDriverStatePtr driver = conn->storagePrivateData; int got = 0, i; + storageDriverLock(driver); for (i = 0 ; i < driver->pools.count && got < nnames ; i++) { + virStoragePoolObjLock(driver->pools.objs[i]); if (!virStoragePoolObjIsActive(driver->pools.objs[i])) { if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) { + virStoragePoolObjUnlock(driver->pools.objs[i]); virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("names")); goto cleanup; } got++; } + virStoragePoolObjUnlock(driver->pools.objs[i]); } + storageDriverUnlock(driver); return got; cleanup: + storageDriverUnlock(driver); for (i = 0 ; i < got ; i++) { free(names[i]); names[i] = NULL; @@ -393,6 +440,8 @@ storageListDefinedPools(virConnectPtr co return -1; } +/* This method is required to be re-entrant / thread safe, so + uses no driver lock */ static char * storageFindPoolSources(virConnectPtr conn, const char *type, @@ -425,10 +474,11 @@ storagePoolCreate(virConnectPtr conn, unsigned int flags ATTRIBUTE_UNUSED) { virStorageDriverStatePtr driver = conn->storagePrivateData; virStoragePoolDefPtr def; - virStoragePoolObjPtr pool; + virStoragePoolObjPtr pool = NULL; virStoragePoolPtr ret = NULL; virStorageBackendPtr backend; + storageDriverLock(driver); if (!(def = virStoragePoolDefParse(conn, xml, NULL))) goto cleanup; @@ -464,6 +514,9 @@ storagePoolCreate(virConnectPtr conn, cleanup: virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + storageDriverUnlock(driver); return ret; } @@ -473,10 +526,11 @@ storagePoolDefine(virConnectPtr conn, unsigned int flags ATTRIBUTE_UNUSED) { virStorageDriverStatePtr driver = conn->storagePrivateData; virStoragePoolDefPtr def; - virStoragePoolObjPtr pool; + virStoragePoolObjPtr pool = NULL; virStoragePoolPtr ret = NULL; virStorageBackendPtr backend; + storageDriverLock(driver); if (!(def = virStoragePoolDefParse(conn, xml, NULL))) goto cleanup; @@ -496,6 +550,9 @@ storagePoolDefine(virConnectPtr conn, cleanup: virStoragePoolDefFree(def); + if (pool) + virStoragePoolObjUnlock(pool); + storageDriverUnlock(driver); return ret; } @@ -505,6 +562,7 @@ storagePoolUndefine(virStoragePoolPtr ob virStoragePoolObjPtr pool; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, @@ -529,9 +587,13 @@ storagePoolUndefine(virStoragePoolPtr ob VIR_FREE(pool->autostartLink); virStoragePoolObjRemove(&driver->pools, pool); + pool = NULL; ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); + storageDriverUnlock(driver); return ret; } @@ -543,7 +605,10 @@ storagePoolStart(virStoragePoolPtr obj, virStorageBackendPtr backend; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -572,6 +637,8 @@ storagePoolStart(virStoragePoolPtr obj, ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -583,7 +650,10 @@ storagePoolBuild(virStoragePoolPtr obj, virStorageBackendPtr backend; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -605,6 +675,8 @@ storagePoolBuild(virStoragePoolPtr obj, ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -616,7 +688,9 @@ storagePoolDestroy(virStoragePoolPtr obj virStorageBackendPtr backend; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -640,11 +714,16 @@ storagePoolDestroy(virStoragePoolPtr obj pool->active = 0; - if (pool->configFile == NULL) + if (pool->configFile == NULL) { virStoragePoolObjRemove(&driver->pools, pool); + pool = NULL; + } ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); + storageDriverUnlock(driver); return ret; } @@ -657,7 +736,10 @@ storagePoolDelete(virStoragePoolPtr obj, virStorageBackendPtr backend; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -683,6 +765,8 @@ storagePoolDelete(virStoragePoolPtr obj, ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -695,7 +779,10 @@ storagePoolRefresh(virStoragePoolPtr obj virStorageBackendPtr backend; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -718,13 +805,17 @@ storagePoolRefresh(virStoragePoolPtr obj pool->active = 0; - if (pool->configFile == NULL) + if (pool->configFile == NULL) { virStoragePoolObjRemove(&driver->pools, pool); + pool = NULL; + } goto cleanup; } ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -737,7 +828,10 @@ storagePoolGetInfo(virStoragePoolPtr obj virStorageBackendPtr backend; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -758,6 +852,8 @@ storagePoolGetInfo(virStoragePoolPtr obj ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -768,7 +864,10 @@ storagePoolDumpXML(virStoragePoolPtr obj virStoragePoolObjPtr pool; char *ret = NULL; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -778,6 +877,8 @@ storagePoolDumpXML(virStoragePoolPtr obj ret = virStoragePoolDefFormat(obj->conn, pool->def); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -788,7 +889,10 @@ storagePoolGetAutostart(virStoragePoolPt virStoragePoolObjPtr pool; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no pool with matching uuid")); @@ -803,6 +907,8 @@ storagePoolGetAutostart(virStoragePoolPt ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -813,7 +919,10 @@ storagePoolSetAutostart(virStoragePoolPt virStoragePoolObjPtr pool; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no pool with matching uuid")); @@ -861,6 +970,8 @@ storagePoolSetAutostart(virStoragePoolPt ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -871,7 +982,10 @@ storagePoolNumVolumes(virStoragePoolPtr virStoragePoolObjPtr pool; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -886,6 +1000,8 @@ storagePoolNumVolumes(virStoragePoolPtr ret = pool->volumes.count; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -899,7 +1015,10 @@ storagePoolListVolumes(virStoragePoolPtr memset(names, 0, maxnames); + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -920,9 +1039,12 @@ storagePoolListVolumes(virStoragePoolPtr } } + virStoragePoolObjUnlock(pool); return n; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); for (n = 0 ; n < maxnames ; n++) VIR_FREE(names[n]); @@ -939,7 +1061,10 @@ storageVolumeLookupByName(virStoragePool virStorageVolDefPtr vol; virStorageVolPtr ret = NULL; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -963,6 +1088,8 @@ storageVolumeLookupByName(virStoragePool ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -974,20 +1101,22 @@ storageVolumeLookupByKey(virConnectPtr c unsigned int i; virStorageVolPtr ret = NULL; - for (i = 0 ; i < driver->pools.count ; i++) { + storageDriverLock(driver); + for (i = 0 ; i < driver->pools.count && !ret ; i++) { + virStoragePoolObjLock(driver->pools.objs[i]); if (virStoragePoolObjIsActive(driver->pools.objs[i])) { virStorageVolDefPtr vol = virStorageVolDefFindByKey(driver->pools.objs[i], key); - if (vol) { + if (vol) ret = virGetStorageVol(conn, - driver->pools.objs[i]->def->name, - vol->name, - vol->key); - break; - } + driver->pools.objs[i]->def->name, + vol->name, + vol->key); } + virStoragePoolObjUnlock(driver->pools.objs[i]); } + storageDriverUnlock(driver); if (!ret) virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL, @@ -1003,7 +1132,9 @@ storageVolumeLookupByPath(virConnectPtr unsigned int i; virStorageVolPtr ret = NULL; - for (i = 0 ; i < driver->pools.count ; i++) { + storageDriverLock(driver); + for (i = 0 ; i < driver->pools.count && !ret ; i++) { + virStoragePoolObjLock(driver->pools.objs[i]); if (virStoragePoolObjIsActive(driver->pools.objs[i])) { virStorageVolDefPtr vol; const char *stable_path; @@ -1016,21 +1147,22 @@ storageVolumeLookupByPath(virConnectPtr * virStorageReportError if it fails; we just need to keep * propagating the return code */ - if (stable_path == NULL) + if (stable_path == NULL) { + virStoragePoolObjUnlock(driver->pools.objs[i]); goto cleanup; + } vol = virStorageVolDefFindByPath(driver->pools.objs[i], stable_path); VIR_FREE(stable_path); - if (vol) { + if (vol) ret = virGetStorageVol(conn, driver->pools.objs[i]->def->name, vol->name, vol->key); - break; - } } + virStoragePoolObjUnlock(driver->pools.objs[i]); } if (!ret) @@ -1038,6 +1170,7 @@ storageVolumeLookupByPath(virConnectPtr "%s", _("no storage vol with matching path")); cleanup: + storageDriverUnlock(driver); return ret; } @@ -1051,7 +1184,10 @@ storageVolumeCreateXML(virStoragePoolPtr virStorageVolDefPtr vol = NULL; virStorageVolPtr ret = NULL; + storageDriverLock(driver); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -1089,6 +1225,7 @@ storageVolumeCreateXML(virStoragePoolPtr goto cleanup; } + /* XXX ought to drop pool lock while creating instance */ if (backend->createVol(obj->conn, pool, vol) < 0) { goto cleanup; } @@ -1100,6 +1237,8 @@ storageVolumeCreateXML(virStoragePoolPtr cleanup: virStorageVolDefFree(vol); + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -1113,7 +1252,10 @@ storageVolumeDelete(virStorageVolPtr obj unsigned int i; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -1168,6 +1310,8 @@ storageVolumeDelete(virStorageVolPtr obj cleanup: virStorageVolDefFree(vol); + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -1180,7 +1324,10 @@ storageVolumeGetInfo(virStorageVolPtr ob virStorageVolDefPtr vol; int ret = -1; + storageDriverLock(driver); pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -1215,6 +1362,8 @@ storageVolumeGetInfo(virStorageVolPtr ob ret = 0; cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } @@ -1227,7 +1376,10 @@ storageVolumeGetXMLDesc(virStorageVolPtr virStorageVolDefPtr vol; char *ret = NULL; + storageDriverLock(driver); pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + storageDriverUnlock(driver); + if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, "%s", _("no storage pool with matching uuid")); @@ -1254,15 +1406,21 @@ storageVolumeGetXMLDesc(virStorageVolPtr ret = virStorageVolDefFormat(obj->conn, pool->def, vol); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } static char * storageVolumeGetPath(virStorageVolPtr obj) { virStorageDriverStatePtr driver = obj->conn->storagePrivateData; - virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + virStoragePoolObjPtr pool; virStorageVolDefPtr vol; char *ret = NULL; + + storageDriverLock(driver); + pool = virStoragePoolObjFindByName(&driver->pools, obj->pool); + storageDriverUnlock(driver); if (!pool) { virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL, @@ -1289,6 +1447,8 @@ storageVolumeGetPath(virStorageVolPtr ob virStorageReportError(obj->conn, VIR_ERR_NO_MEMORY, "%s", _("path")); cleanup: + if (pool) + virStoragePoolObjUnlock(pool); return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:57:47PM +0000, Daniel P. Berrange wrote:
This patch makes the storage driver thread safe [...] static void storageDriverAutostart(virStorageDriverStatePtr driver) {
Hum, there is something I find incherent, in the network side we don't lock the driver but we lock the individual objects in the autostart. Here we don't lock anything. In both case they are started at the end of the Startup method, which does lock the driver. So it seems in the network case we don't need to lock the individual objects unless I'm mistaken
@@ -172,11 +182,13 @@ storageDriverReload(void) { if (!driverState) return -1;
+ storageDriverLock(driverState); virStoragePoolLoadAllConfigs(NULL, &driverState->pools, driverState->configDir, driverState->autostartDir); storageDriverAutostart(driverState); + storageDriverUnlock(driverState);
return 0;
Hum there is something potentially nasty here: - suppose you call reload - you lock the main driver - you don't lock any of the individual objects - another thread is busy on a long standing operation in one of the storage objects - reload still goes in, virStoragePoolDefParse creates a brand new object and virStoragePoolObjAssignDef frees the object used by the other thread. I didn't find any locking in virStoragePoolObjAssignDef or virStoragePoolLoadAllConfigs. Maybe on reload operation it's safer to just lock the driver and all storage objects before reloading all configs and autostarting. [...]
@@ -393,6 +440,8 @@ storageListDefinedPools(virConnectPtr co return -1; }
+/* This method is required to be re-entrant / thread safe, so + uses no driver lock */
Well virStorageBackendFindPoolSources prototype has no comment so it's hard to guess... Okay, there is a couple issues I raise here, I'm not sure if it's misunderstanding or genuine problems though... Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Dec 03, 2008 at 10:59:20AM +0100, Daniel Veillard wrote:
On Sun, Nov 30, 2008 at 11:57:47PM +0000, Daniel P. Berrange wrote:
This patch makes the storage driver thread safe [...] static void storageDriverAutostart(virStorageDriverStatePtr driver) {
Hum, there is something I find incherent, in the network side we don't lock the driver but we lock the individual objects in the autostart. Here we don't lock anything. In both case they are started at the end of the Startup method, which does lock the driver. So it seems in the network case we don't need to lock the individual objects unless I'm mistaken
That is a bug in this storage patch. We should be locking the storage pools here, because someone could send us a SIGHUP to do a reload while someone else is using a storage pool.
@@ -172,11 +182,13 @@ storageDriverReload(void) { if (!driverState) return -1;
+ storageDriverLock(driverState); virStoragePoolLoadAllConfigs(NULL, &driverState->pools, driverState->configDir, driverState->autostartDir); storageDriverAutostart(driverState); + storageDriverUnlock(driverState);
return 0;
Hum there is something potentially nasty here: - suppose you call reload - you lock the main driver - you don't lock any of the individual objects - another thread is busy on a long standing operation in one of the storage objects - reload still goes in, virStoragePoolDefParse creates a brand new object and virStoragePoolObjAssignDef frees the object used by the other thread.
Yes that is precisely the scenario we need the locking in autostart for. I'll fix this patch....
I didn't find any locking in virStoragePoolObjAssignDef or virStoragePoolLoadAllConfigs. Maybe on reload operation it's safer to just lock the driver and all storage objects before reloading all configs and autostarting.
There's two scenarios in AssignDef - Updating config of an existing object. In this case virStoragePoolObjFindByName will already have locked it for us - Creating a new object - in this case we call virStoragePoolObjLock explicitly. So, I believe AssignDef locking is OK here. LoadAllConfigs is also OK because its use of objects all comes via AssignDef which returns a locked object.
[...]
@@ -393,6 +440,8 @@ storageListDefinedPools(virConnectPtr co return -1; }
+/* This method is required to be re-entrant / thread safe, so + uses no driver lock */
Well virStorageBackendFindPoolSources prototype has no comment so it's hard to guess...
Okay, there is a couple issues I raise here, I'm not sure if it's misunderstanding or genuine problems though...
genuine bugs ! Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch reduces the number of exit paths in the OpenVZ driver methods openvz_driver.c | 392 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 224 insertions(+), 168 deletions(-) Daniel diff --git a/src/openvz_driver.c b/src/openvz_driver.c --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -155,96 +155,101 @@ static int openvzDomainDefineCmd(virConn static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id) { - struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; + struct openvz_driver *driver = conn->privateData; virDomainObjPtr vm; - virDomainPtr dom; + virDomainPtr dom = NULL; vm = virDomainFindByID(&driver->domains, id); - if (!vm) { openvzError(conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (!dom) - return NULL; + if (dom) + dom->id = vm->def->id; - dom->id = vm->def->id; +cleanup: return dom; } static int openvzGetVersion(virConnectPtr conn, unsigned long *version) { - struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; + struct openvz_driver *driver = conn->privateData; *version = driver->version; return 0; } static char *openvzGetOSType(virDomainPtr dom) { - struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - char *ret; + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *ret = NULL; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } if (!(ret = strdup(vm->def->os.type))) openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL); +cleanup: return ret; } static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid); - virDomainPtr dom; + struct openvz_driver *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByUUID(&driver->domains, uuid); if (!vm) { openvzError(conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (!dom) - return NULL; + if (dom) + dom->id = vm->def->id; - dom->id = vm->def->id; +cleanup: return dom; } static virDomainPtr openvzDomainLookupByName(virConnectPtr conn, - const char *name) { - struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; - virDomainObjPtr vm = virDomainFindByName(&driver->domains, name); - virDomainPtr dom; + const char *name) { + struct openvz_driver *driver = conn->privateData; + virDomainObjPtr vm; + virDomainPtr dom = NULL; + vm = virDomainFindByName(&driver->domains, name); if (!vm) { openvzError(conn, VIR_ERR_NO_DOMAIN, NULL); - return NULL; + goto cleanup; } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); - if (!dom) - return NULL; + if (dom) + dom->id = vm->def->id; - dom->id = vm->def->id; +cleanup: return dom; } static int openvzDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { - struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } info->state = vm->state; @@ -255,80 +260,110 @@ static int openvzDomainGetInfo(virDomain if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) { openvzError(dom->conn, VIR_ERR_OPERATION_FAILED, _("cannot read cputime for domain %d"), dom->id); - return -1; + goto cleanup; } } info->maxMem = vm->def->maxmem; info->memory = vm->def->memory; info->nrVirtCpu = vm->def->vcpus; - return 0; + ret = 0; + +cleanup: + return ret; } static char *openvzDomainDumpXML(virDomainPtr dom, int flags) { - struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + char *ret = NULL; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return NULL; + goto cleanup; } - return virDomainDefFormat(dom->conn, vm->def, flags); + ret = virDomainDefFormat(dom->conn, vm->def, flags); + +cleanup: + return ret; } +#define PROGRAM_SENTINAL ((char *)0x1) +static void openvzSetProgramSentinal(const char **prog, const char *key) +{ + const char **tmp = prog; + while (tmp && *tmp) { + if (*tmp == PROGRAM_SENTINAL) { + *tmp = key; + break; + } + tmp++; + } +} static int openvzDomainShutdown(virDomainPtr dom) { - struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - const char *prog[] = {VZCTL, "--quiet", "stop", vm ? vm->def->name : NULL, NULL}; + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + const char *prog[] = {VZCTL, "--quiet", "stop", PROGRAM_SENTINAL, NULL}; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } + openvzSetProgramSentinal(prog, vm->def->name); if (vm->state != VIR_DOMAIN_RUNNING) { openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("domain is not in running state")); - return -1; + goto cleanup; } if (virRun(dom->conn, prog, NULL) < 0) - return -1; + goto cleanup; vm->def->id = -1; vm->state = VIR_DOMAIN_SHUTOFF; + ret = 0; - return 0; +cleanup: + return ret; } static int openvzDomainReboot(virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED) { - struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - const char *prog[] = {VZCTL, "--quiet", "restart", vm ? vm->def->name : NULL, NULL}; + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + const char *prog[] = {VZCTL, "--quiet", "restart", PROGRAM_SENTINAL, NULL}; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } + openvzSetProgramSentinal(prog, vm->def->name); if (vm->state != VIR_DOMAIN_RUNNING) { openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("domain is not in running state")); - return -1; + goto cleanup; } if (virRun(dom->conn, prog, NULL) < 0) - return -1; + goto cleanup; + ret = 0; - return 0; +cleanup: + return ret; } static char * @@ -379,7 +414,7 @@ openvzDomainSetNetwork(virConnectPtr con int rc = 0, narg; const char *prog[OPENVZ_MAX_ARG]; char macaddr[VIR_MAC_STRING_BUFLEN]; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; + struct openvz_driver *driver = conn->privateData; char *opt = NULL; #define ADD_ARG_LIT(thisarg) \ @@ -508,7 +543,7 @@ openvzDomainSetNetworkConfig(virConnectP virBuffer buf = VIR_BUFFER_INITIALIZER; char *param; int first = 1; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; + struct openvz_driver *driver = conn->privateData; for (i = 0 ; i < def->nnets ; i++) { if (driver->version < VZCTL_BRIDGE_MIN_VERSION && @@ -551,7 +586,7 @@ static virDomainPtr static virDomainPtr openvzDomainDefineXML(virConnectPtr conn, const char *xml) { - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; + struct openvz_driver *driver = conn->privateData; virDomainDefPtr vmdef = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; @@ -559,12 +594,11 @@ openvzDomainDefineXML(virConnectPtr conn prog[0] = NULL; if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL) - return NULL; + goto cleanup; if (vmdef->os.init == NULL && !(vmdef->os.init = strdup("/sbin/init"))) { - virDomainDefFree(vmdef); - return NULL; + goto cleanup; } vm = virDomainFindByName(&driver->domains, vmdef->name); @@ -572,18 +606,16 @@ openvzDomainDefineXML(virConnectPtr conn openvzError(conn, VIR_ERR_OPERATION_FAILED, _("Already an OPENVZ VM active with the id '%s'"), vmdef->name); - virDomainDefFree(vmdef); - return NULL; + goto cleanup; } - if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) { - virDomainDefFree(vmdef); - return NULL; - } + if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) + goto cleanup; + vmdef = NULL; - if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) { + if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vm->def) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Error creating command for container")); - goto exit; + goto cleanup; } //TODO: set quota @@ -591,31 +623,32 @@ openvzDomainDefineXML(virConnectPtr conn if (virRun(conn, prog, NULL) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); - goto exit; + goto cleanup; } - if (openvzSetDefinedUUID(strtoI(vmdef->name), vmdef->uuid) < 0) { + if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set UUID")); - goto exit; + goto cleanup; } - if (openvzDomainSetNetworkConfig(conn, vmdef) < 0) - goto exit; + if (openvzDomainSetNetworkConfig(conn, vm->def) < 0) + goto cleanup; + + if (vm->def->vcpus > 0) { + if (openvzDomainSetVcpus(dom, vm->def->vcpus) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Could not set number of virtual cpu")); + goto cleanup; + } + } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = -1; - if (vmdef->vcpus > 0) { - if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("Could not set number of virtual cpu")); - goto exit; - } - } - - exit: +cleanup: + virDomainDefFree(vmdef); cmdExecFree(prog); return dom; } @@ -624,82 +657,79 @@ openvzDomainCreateXML(virConnectPtr conn openvzDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { + struct openvz_driver *driver = conn->privateData; virDomainDefPtr vmdef = NULL; virDomainObjPtr vm = NULL; virDomainPtr dom = NULL; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; - const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL}; + const char *progstart[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL}; const char *progcreate[OPENVZ_MAX_ARG]; progcreate[0] = NULL; if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL) - return NULL; + goto cleanup; if (vmdef->os.init == NULL && - !(vmdef->os.init = strdup("/sbin/init"))) { - virDomainDefFree(vmdef); - return NULL; - } + !(vmdef->os.init = strdup("/sbin/init"))) + goto cleanup; vm = virDomainFindByName(&driver->domains, vmdef->name); if (vm) { openvzError(conn, VIR_ERR_OPERATION_FAILED, _("Already an OPENVZ VM defined with the id '%s'"), vmdef->name); - virDomainDefFree(vmdef); - return NULL; + goto cleanup; } - if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) { - virDomainDefFree(vmdef); - return NULL; - } + if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) + goto cleanup; + vmdef = NULL; - if (openvzDomainDefineCmd(conn, progcreate, OPENVZ_MAX_ARG, vmdef) < 0) { + if (openvzDomainDefineCmd(conn, progcreate, OPENVZ_MAX_ARG, vm->def) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("Error creating command for container")); - goto exit; + "%s", _("Error creating command for container")); + goto cleanup; } if (virRun(conn, progcreate, NULL) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); - goto exit; + goto cleanup; } - if (openvzSetDefinedUUID(strtoI(vmdef->name), vmdef->uuid) < 0) { + if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set UUID")); - goto exit; + goto cleanup; } - if (openvzDomainSetNetworkConfig(conn, vmdef) < 0) - goto exit; + if (openvzDomainSetNetworkConfig(conn, vm->def) < 0) + goto cleanup; - progstart[3] = vmdef->name; + openvzSetProgramSentinal(progstart, vm->def->name); if (virRun(conn, progstart, NULL) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); - goto exit; + goto cleanup; } - vm->pid = strtoI(vmdef->name); + vm->pid = strtoI(vm->def->name); vm->def->id = vm->pid; vm->state = VIR_DOMAIN_RUNNING; + + if (vm->def->vcpus > 0) { + if (openvzDomainSetVcpus(dom, vm->def->vcpus) < 0) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Could not set number of virtual cpu")); + goto cleanup; + } + } dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; - if (vmdef->vcpus > 0) { - if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("Could not set number of virtual cpu")); - goto exit; - } - } - - exit: +cleanup: + virDomainDefFree(vmdef); cmdExecFree(progcreate); return dom; } @@ -707,110 +737,128 @@ static int static int openvzDomainCreate(virDomainPtr dom) { - struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; - virDomainObjPtr vm = virDomainFindByName(&driver->domains, dom->name); - const char *prog[] = {VZCTL, "--quiet", "start", vm ? vm->def->name : NULL, NULL }; + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + const char *prog[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL }; + int ret = -1; + vm = virDomainFindByName(&driver->domains, dom->name); if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching id")); - return -1; + "%s", _("no domain with matching id")); + goto cleanup; } if (vm->state != VIR_DOMAIN_SHUTOFF) { openvzError(dom->conn, VIR_ERR_OPERATION_DENIED, - "%s", _("domain is not in shutoff state")); - return -1; + "%s", _("domain is not in shutoff state")); + goto cleanup; } + openvzSetProgramSentinal(prog, vm->def->name); if (virRun(dom->conn, prog, NULL) < 0) { openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, - _("Could not exec %s"), VZCTL); - return -1; + _("Could not exec %s"), VZCTL); + goto cleanup; } vm->pid = strtoI(vm->def->name); vm->def->id = vm->pid; vm->state = VIR_DOMAIN_RUNNING; + ret = 0; - return 0; +cleanup: + return ret; } static int openvzDomainUndefine(virDomainPtr dom) { - virConnectPtr conn= dom->conn; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - const char *prog[] = { VZCTL, "--quiet", "destroy", vm ? vm->def->name : NULL, NULL }; + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + const char *prog[] = { VZCTL, "--quiet", "destroy", PROGRAM_SENTINAL, NULL }; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - openvzError(conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); + goto cleanup; } if (virDomainIsActive(vm)) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain")); - return -1; + openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain")); + goto cleanup; } - if (virRun(conn, prog, NULL) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, - _("Could not exec %s"), VZCTL); - return -1; + openvzSetProgramSentinal(prog, vm->def->name); + if (virRun(dom->conn, prog, NULL) < 0) { + openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, + _("Could not exec %s"), VZCTL); + goto cleanup; } virDomainRemoveInactive(&driver->domains, vm); + ret = 0; - return 0; +cleanup: + return ret; } static int openvzDomainSetAutostart(virDomainPtr dom, int autostart) { - virConnectPtr conn= dom->conn; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); - const char *prog[] = { VZCTL, "--quiet", "set", vm ? vm->def->name : NULL, + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + const char *prog[] = { VZCTL, "--quiet", "set", PROGRAM_SENTINAL, "--onboot", autostart ? "yes" : "no", "--save", NULL }; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - openvzError(conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); + goto cleanup; } - if (virRun(conn, prog, NULL) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); - return -1; + openvzSetProgramSentinal(prog, vm->def->name); + if (virRun(dom->conn, prog, NULL) < 0) { + openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); + goto cleanup; } + ret = 0; - return 0; +cleanup: + return ret; } static int openvzDomainGetAutostart(virDomainPtr dom, int *autostart) { - virConnectPtr conn= dom->conn; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; char value[1024]; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - openvzError(conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, + "%s", _("no domain with matching uuid")); + goto cleanup; } if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("Could not read container config")); - return -1; + openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("Could not read container config")); + goto cleanup; } *autostart = 0; if (STREQ(value,"yes")) *autostart = 1; + ret = 0; - return 0; +cleanup: + return ret; } static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type) { @@ -828,24 +876,25 @@ static int openvzDomainGetMaxVcpus(virDo } static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { - virConnectPtr conn= dom->conn; - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; - virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); + struct openvz_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; char str_vcpus[32]; - const char *prog[] = { VZCTL, "--quiet", "set", vm ? vm->def->name : NULL, + const char *prog[] = { VZCTL, "--quiet", "set", PROGRAM_SENTINAL, "--cpus", str_vcpus, "--save", NULL }; unsigned int pcpus; + int ret = -1; + vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - openvzError(conn, VIR_ERR_INVALID_DOMAIN, + openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); - return -1; + goto cleanup; } if (nvcpus <= 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, + openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("VCPUs should be >= 1")); - return -1; + goto cleanup; } pcpus = openvzGetNodeCPUs(); @@ -855,14 +904,18 @@ static int openvzDomainSetVcpus(virDomai snprintf(str_vcpus, 31, "%d", nvcpus); str_vcpus[31] = '\0'; - if (virRun(conn, prog, NULL) < 0) { - openvzError(conn, VIR_ERR_INTERNAL_ERROR, + openvzSetProgramSentinal(prog, vm->def->name); + if (virRun(dom->conn, prog, NULL) < 0) { + openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL); - return -1; + goto cleanup; } vm->def->vcpus = nvcpus; - return 0; + ret = 0; + +cleanup: + return ret; } static int openvzProbe(void) @@ -919,7 +972,7 @@ cleanup: }; static int openvzClose(virConnectPtr conn) { - struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; + struct openvz_driver *driver = conn->privateData; openvzFreeDriver(driver); conn->privateData = NULL; @@ -937,9 +990,12 @@ static int openvzGetNodeInfo(virConnectP } static char *openvzGetCapabilities(virConnectPtr conn) { - struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; + struct openvz_driver *driver = conn->privateData; + char *ret; - return virCapabilitiesFormatXML(driver->caps); + ret = virCapabilitiesFormatXML(driver->caps); + + return ret; } static int openvzListDomains(virConnectPtr conn, int *ids, int nids) { @@ -1074,7 +1130,7 @@ Version: 2.2 } static int openvzNumDefinedDomains(virConnectPtr conn) { - struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; + struct openvz_driver *driver = conn->privateData; int ninactive = 0, i; for (i = 0 ; i < driver->domains.count ; i++) -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:58:50PM +0000, Daniel P. Berrange wrote:
This patch reduces the number of exit paths in the OpenVZ driver methods
[...]
+#define PROGRAM_SENTINAL ((char *)0x1) +static void openvzSetProgramSentinal(const char **prog, const char *key) +{ + const char **tmp = prog; + while (tmp && *tmp) { + if (*tmp == PROGRAM_SENTINAL) { + *tmp = key; + break; + } + tmp++; + } +} okay, it's a bit weird, maybe a small comment like
/* * used to update the command line when the domain parameter name is * known. */ would help people trying to read the code :-) [...] fine by me, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the OpenVZ driver thread safe openvz_conf.h | 2 + openvz_driver.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 3 deletions(-) Daniel diff --git a/src/openvz_conf.h b/src/openvz_conf.h --- a/src/openvz_conf.h +++ b/src/openvz_conf.h @@ -53,6 +53,8 @@ enum { OPENVZ_WARN, OPENVZ_ERR }; #define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1) struct openvz_driver { + PTHREAD_MUTEX_T(lock); + virCapsPtr caps; virDomainObjList domains; int version; diff --git a/src/openvz_driver.c b/src/openvz_driver.c --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -66,6 +66,16 @@ static int openvzGetMaxVCPUs(virConnectP static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type); static int openvzDomainGetMaxVcpus(virDomainPtr dom); static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); + +static void openvzDriverLock(struct openvz_driver *driver) +{ + pthread_mutex_lock(&driver->lock); +} + +static void openvzDriverUnlock(struct openvz_driver *driver) +{ + pthread_mutex_unlock(&driver->lock); +} struct openvz_driver ovz_driver; @@ -159,7 +169,10 @@ static virDomainPtr openvzDomainLookupBy virDomainObjPtr vm; virDomainPtr dom = NULL; + openvzDriverLock(driver); vm = virDomainFindByID(&driver->domains, id); + openvzDriverUnlock(driver); + if (!vm) { openvzError(conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -170,12 +183,16 @@ static virDomainPtr openvzDomainLookupBy dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } static int openvzGetVersion(virConnectPtr conn, unsigned long *version) { struct openvz_driver *driver = conn->privateData; + openvzDriverLock(driver); *version = driver->version; + openvzDriverUnlock(driver); return 0; } @@ -185,7 +202,10 @@ static char *openvzGetOSType(virDomainPt virDomainObjPtr vm; char *ret = NULL; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -195,6 +215,8 @@ static char *openvzGetOSType(virDomainPt openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -205,7 +227,10 @@ static virDomainPtr openvzDomainLookupBy virDomainObjPtr vm; virDomainPtr dom = NULL; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -216,6 +241,8 @@ static virDomainPtr openvzDomainLookupBy dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -225,7 +252,10 @@ static virDomainPtr openvzDomainLookupBy virDomainObjPtr vm; virDomainPtr dom = NULL; + openvzDriverLock(driver); vm = virDomainFindByName(&driver->domains, name); + openvzDriverUnlock(driver); + if (!vm) { openvzError(conn, VIR_ERR_NO_DOMAIN, NULL); goto cleanup; @@ -236,6 +266,8 @@ static virDomainPtr openvzDomainLookupBy dom->id = vm->def->id; cleanup: + if (vm) + virDomainObjUnlock(vm); return dom; } @@ -245,7 +277,10 @@ static int openvzDomainGetInfo(virDomain virDomainObjPtr vm; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -270,6 +305,8 @@ static int openvzDomainGetInfo(virDomain ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -279,7 +316,10 @@ static char *openvzDomainDumpXML(virDoma virDomainObjPtr vm; char *ret = NULL; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -289,6 +329,8 @@ static char *openvzDomainDumpXML(virDoma ret = virDomainDefFormat(dom->conn, vm->def, flags); cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -312,7 +354,10 @@ static int openvzDomainShutdown(virDomai const char *prog[] = {VZCTL, "--quiet", "stop", PROGRAM_SENTINAL, NULL}; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -334,6 +379,8 @@ static int openvzDomainShutdown(virDomai ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -344,7 +391,10 @@ static int openvzDomainReboot(virDomainP const char *prog[] = {VZCTL, "--quiet", "restart", PROGRAM_SENTINAL, NULL}; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -363,6 +413,8 @@ static int openvzDomainReboot(virDomainP ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -593,6 +645,7 @@ openvzDomainDefineXML(virConnectPtr conn const char *prog[OPENVZ_MAX_ARG]; prog[0] = NULL; + openvzDriverLock(driver); if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL) goto cleanup; @@ -650,12 +703,15 @@ cleanup: cleanup: virDomainDefFree(vmdef); cmdExecFree(prog); + if (vm) + virDomainObjUnlock(vm); + openvzDriverUnlock(driver); return dom; } static virDomainPtr openvzDomainCreateXML(virConnectPtr conn, const char *xml, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags ATTRIBUTE_UNUSED) { struct openvz_driver *driver = conn->privateData; virDomainDefPtr vmdef = NULL; @@ -665,6 +721,7 @@ openvzDomainCreateXML(virConnectPtr conn const char *progcreate[OPENVZ_MAX_ARG]; progcreate[0] = NULL; + openvzDriverLock(driver); if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL) goto cleanup; @@ -731,6 +788,9 @@ cleanup: cleanup: virDomainDefFree(vmdef); cmdExecFree(progcreate); + if (vm) + virDomainObjUnlock(vm); + openvzDriverUnlock(driver); return dom; } @@ -742,7 +802,10 @@ openvzDomainCreate(virDomainPtr dom) const char *prog[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL }; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByName(&driver->domains, dom->name); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching id")); @@ -768,6 +831,8 @@ openvzDomainCreate(virDomainPtr dom) ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -779,6 +844,7 @@ openvzDomainUndefine(virDomainPtr dom) const char *prog[] = { VZCTL, "--quiet", "destroy", PROGRAM_SENTINAL, NULL }; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -798,9 +864,13 @@ openvzDomainUndefine(virDomainPtr dom) } virDomainRemoveInactive(&driver->domains, vm); + vm = NULL; ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); + openvzDriverUnlock(driver); return ret; } @@ -814,7 +884,10 @@ openvzDomainSetAutostart(virDomainPtr do "--save", NULL }; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; @@ -828,6 +901,8 @@ openvzDomainSetAutostart(virDomainPtr do ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -839,7 +914,10 @@ openvzDomainGetAutostart(virDomainPtr do char value[1024]; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -858,6 +936,8 @@ openvzDomainGetAutostart(virDomainPtr do ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -884,7 +964,10 @@ static int openvzDomainSetVcpus(virDomai unsigned int pcpus; int ret = -1; + openvzDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); + openvzDriverUnlock(driver); + if (!vm) { openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid")); @@ -915,6 +998,8 @@ static int openvzDomainSetVcpus(virDomai ret = 0; cleanup: + if (vm) + virDomainObjUnlock(vm); return ret; } @@ -993,7 +1078,9 @@ static char *openvzGetCapabilities(virCo struct openvz_driver *driver = conn->privateData; char *ret; + openvzDriverLock(driver); ret = virCapabilitiesFormatXML(driver->caps); + openvzDriverUnlock(driver); return ret; } @@ -1036,9 +1123,14 @@ static int openvzNumDomains(virConnectPt struct openvz_driver *driver = conn->privateData; int nactive = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + openvzDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (virDomainIsActive(driver->domains.objs[i])) nactive++; + virDomainObjUnlock(driver->domains.objs[i]); + } + openvzDriverUnlock(driver); return nactive; } @@ -1133,9 +1225,14 @@ static int openvzNumDefinedDomains(virCo struct openvz_driver *driver = conn->privateData; int ninactive = 0, i; - for (i = 0 ; i < driver->domains.count ; i++) + openvzDriverLock(driver); + for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (!virDomainIsActive(driver->domains.objs[i])) ninactive++; + virDomainObjUnlock(driver->domains.objs[i]); + } + openvzDriverUnlock(driver); return ninactive; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:59:55PM +0000, Daniel P. Berrange wrote:
This patch makes the OpenVZ driver thread safe
Quite regular, looks just fine, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch reduces the number of return paths in the node device driver methods In doing this I noticed an annoying problem in the public API contract for virNodeDeviceGetParent. It returns a 'const char *', but the remote driver is actually returning an malloc'd string requiring the caller to free it, while the node_device driver is returning a const string the caller must not free. Ideally we would not have the 'const' annotation but changing that now is ABI change, so instead I work around it, by making all drivers return a malloc'd string, but then caching this in the virNodeDevicePtr object. This mallc'd string is then free'd when the object is released. This allows us to work around the public API contract problem datatypes.c | 1 datatypes.h | 1 libvirt.c | 14 ++++++++---- node_device.c | 65 ++++++++++++++++++++++++++++++++++++++-------------------- 4 files changed, 54 insertions(+), 27 deletions(-) Daniel diff --git a/src/datatypes.c b/src/datatypes.c --- a/src/datatypes.c +++ b/src/datatypes.c @@ -861,6 +861,7 @@ virReleaseNodeDevice(virNodeDevicePtr de dev->magic = -1; VIR_FREE(dev->name); + VIR_FREE(dev->parent); VIR_FREE(dev); DEBUG("unref connection %p %d", conn, conn->refs); diff --git a/src/datatypes.h b/src/datatypes.h --- a/src/datatypes.h +++ b/src/datatypes.h @@ -199,6 +199,7 @@ struct _virNodeDevice { int refs; /* reference count */ virConnectPtr conn; /* pointer back to the connection */ char *name; /* device name (unique on node) */ + char *parent; /* parent device name */ }; diff --git a/src/libvirt.c b/src/libvirt.c --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5689,11 +5689,15 @@ const char *virNodeDeviceGetParent(virNo return NULL; } - if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceGetParent) - return dev->conn->deviceMonitor->deviceGetParent (dev); - - virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); - return NULL; + if (!dev->parent) { + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceGetParent) { + dev->parent = dev->conn->deviceMonitor->deviceGetParent (dev); + } else { + virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; + } + } + return dev->parent; } /** diff --git a/src/node_device.c b/src/node_device.c --- a/src/node_device.c +++ b/src/node_device.c @@ -91,66 +91,84 @@ static virNodeDevicePtr nodeDeviceLookup const char *name) { virDeviceMonitorStatePtr driver = conn->devMonPrivateData; - virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, name); + virNodeDeviceObjPtr obj; + virNodeDevicePtr ret = NULL; + obj = virNodeDeviceFindByName(&driver->devs, name); if (!obj) { virNodeDeviceReportError(conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); - return NULL; + goto cleanup; } - return virGetNodeDevice(conn, name); + ret = virGetNodeDevice(conn, name); +cleanup: + return ret; } static char *nodeDeviceDumpXML(virNodeDevicePtr dev, unsigned int flags ATTRIBUTE_UNUSED) { virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData; - virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, dev->name); + virNodeDeviceObjPtr obj; + char *ret = NULL; + obj = virNodeDeviceFindByName(&driver->devs, dev->name); if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); - return NULL; + goto cleanup; } - return virNodeDeviceDefFormat(dev->conn, obj->def); + ret = virNodeDeviceDefFormat(dev->conn, obj->def); + +cleanup: + return ret; } static char *nodeDeviceGetParent(virNodeDevicePtr dev) { virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData; - virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, dev->name); + virNodeDeviceObjPtr obj; + char *ret = NULL; + obj = virNodeDeviceFindByName(&driver->devs, dev->name); if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); - return NULL; + goto cleanup; } - return obj->def->parent; + ret = strdup(obj->def->parent); + +cleanup: + return ret; } static int nodeDeviceNumOfCaps(virNodeDevicePtr dev) { virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData; - virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, dev->name); + virNodeDeviceObjPtr obj; virNodeDevCapsDefPtr caps; int ncaps = 0; + int ret = -1; + obj = virNodeDeviceFindByName(&driver->devs, dev->name); if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); - return -1; + goto cleanup; } for (caps = obj->def->caps; caps; caps = caps->next) ++ncaps; + ret = ncaps; - return ncaps; +cleanup: + return ret; } @@ -158,29 +176,32 @@ nodeDeviceListCaps(virNodeDevicePtr dev, nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) { virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData; - virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, dev->name); + virNodeDeviceObjPtr obj; virNodeDevCapsDefPtr caps; int ncaps = 0; + int ret = -1; + obj = virNodeDeviceFindByName(&driver->devs, dev->name); if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); - return -1; + goto cleanup; } for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) { names[ncaps] = strdup(virNodeDevCapTypeToString(caps->type)); if (names[ncaps++] == NULL) - goto failure; + goto cleanup; } + ret = ncaps; - return ncaps; - - failure: - --ncaps; - while (--ncaps >= 0) - VIR_FREE(names[ncaps]); - return -1; +cleanup: + if (ret == -1) { + --ncaps; + while (--ncaps >= 0) + VIR_FREE(names[ncaps]); + } + return ret; } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:03:39AM +0000, Daniel P. Berrange wrote:
This patch reduces the number of return paths in the node device driver methods
In doing this I noticed an annoying problem in the public API contract for virNodeDeviceGetParent. It returns a 'const char *', but the remote driver is actually returning an malloc'd string requiring the caller to free it, while the node_device driver is returning a const string the caller must not free. Ideally we would not have the 'const' annotation but changing that now is ABI change, so instead I work around it, by making all drivers return a malloc'd string, but then caching this in the virNodeDevicePtr object. This mallc'd string is then free'd when the object is released. This allows us to work around the public API contract problem
argh, understood ! [...]
static char *nodeDeviceGetParent(virNodeDevicePtr dev) { [...] - return obj->def->parent; + ret = strdup(obj->def->parent);
I guess we should report allocation error, even if it probably doesn't help much at that point.
+cleanup: + return ret; }
Okay +1, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the node device driver thread safe. Almost. There is on outstanding problem in that the 'reload' method is implemented by just calling shutdown/startup. This causes the mutex we're locking on to be free'd and re-allocated. I'll fix this up later. libvirt_sym.version.in | 1 node_device.c | 53 ++++++++++++++- node_device.h | 4 + node_device_conf.h | 3 node_device_devkit.c | 41 ++++++++---- node_device_hal.c | 166 +++++++++++++++++++++++++++++++++---------------- 6 files changed, 199 insertions(+), 69 deletions(-) Daniel diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in +++ b/src/libvirt_sym.version.in @@ -509,6 +509,7 @@ LIBVIRT_PRIVATE_@VERSION@ { virNodeDeviceDefFormat; virNodeDeviceObjLock; virNodeDeviceObjUnlock; + virNodeDeviceAssignDef; /* qparams.h */ diff --git a/src/node_device.c b/src/node_device.c --- a/src/node_device.c +++ b/src/node_device.c @@ -29,7 +29,7 @@ #include "virterror_internal.h" #include "datatypes.h" #include "memory.h" - +#include "logging.h" #include "node_device_conf.h" #include "node_device.h" @@ -44,6 +44,17 @@ static int dev_has_cap(const virNodeDevi return 0; } + +void nodeDeviceLock(virDeviceMonitorStatePtr driver) +{ + DEBUG("LOCK node %p", driver); + pthread_mutex_lock(&driver->lock); +} +void nodeDeviceUnlock(virDeviceMonitorStatePtr driver) +{ + DEBUG("UNLOCK node %p", driver); + pthread_mutex_unlock(&driver->lock); +} static int nodeNumOfDevices(virConnectPtr conn, const char *cap, @@ -71,15 +82,24 @@ nodeListDevices(virConnectPtr conn, int ndevs = 0; unsigned int i; - for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) + nodeDeviceLock(driver); + for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) { + virNodeDeviceObjLock(driver->devs.objs[i]); if (cap == NULL || - dev_has_cap(driver->devs.objs[i], cap)) - if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) + dev_has_cap(driver->devs.objs[i], cap)) { + if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) { + virNodeDeviceObjUnlock(driver->devs.objs[i]); goto failure; + } + } + virNodeDeviceObjUnlock(driver->devs.objs[i]); + } + nodeDeviceUnlock(driver); return ndevs; failure: + nodeDeviceUnlock(driver); --ndevs; while (--ndevs >= 0) VIR_FREE(names[ndevs]); @@ -94,7 +114,10 @@ static virNodeDevicePtr nodeDeviceLookup virNodeDeviceObjPtr obj; virNodeDevicePtr ret = NULL; + nodeDeviceLock(driver); obj = virNodeDeviceFindByName(&driver->devs, name); + nodeDeviceUnlock(driver); + if (!obj) { virNodeDeviceReportError(conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); @@ -104,6 +127,8 @@ static virNodeDevicePtr nodeDeviceLookup ret = virGetNodeDevice(conn, name); cleanup: + if (obj) + virNodeDeviceObjUnlock(obj); return ret; } @@ -114,7 +139,10 @@ static char *nodeDeviceDumpXML(virNodeDe virNodeDeviceObjPtr obj; char *ret = NULL; + nodeDeviceLock(driver); obj = virNodeDeviceFindByName(&driver->devs, dev->name); + nodeDeviceUnlock(driver); + if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); @@ -124,6 +152,8 @@ static char *nodeDeviceDumpXML(virNodeDe ret = virNodeDeviceDefFormat(dev->conn, obj->def); cleanup: + if (obj) + virNodeDeviceObjUnlock(obj); return ret; } @@ -134,7 +164,10 @@ static char *nodeDeviceGetParent(virNode virNodeDeviceObjPtr obj; char *ret = NULL; + nodeDeviceLock(driver); obj = virNodeDeviceFindByName(&driver->devs, dev->name); + nodeDeviceUnlock(driver); + if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); @@ -144,6 +177,8 @@ static char *nodeDeviceGetParent(virNode ret = strdup(obj->def->parent); cleanup: + if (obj) + virNodeDeviceObjUnlock(obj); return ret; } @@ -156,7 +191,10 @@ static int nodeDeviceNumOfCaps(virNodeDe int ncaps = 0; int ret = -1; + nodeDeviceLock(driver); obj = virNodeDeviceFindByName(&driver->devs, dev->name); + nodeDeviceUnlock(driver); + if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); @@ -168,6 +206,8 @@ static int nodeDeviceNumOfCaps(virNodeDe ret = ncaps; cleanup: + if (obj) + virNodeDeviceObjUnlock(obj); return ret; } @@ -181,7 +221,10 @@ nodeDeviceListCaps(virNodeDevicePtr dev, int ncaps = 0; int ret = -1; + nodeDeviceLock(driver); obj = virNodeDeviceFindByName(&driver->devs, dev->name); + nodeDeviceUnlock(driver); + if (!obj) { virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, "%s", _("no node device with matching name")); @@ -196,6 +239,8 @@ nodeDeviceListCaps(virNodeDevicePtr dev, ret = ncaps; cleanup: + if (obj) + virNodeDeviceObjUnlock(obj); if (ret == -1) { --ncaps; while (--ncaps >= 0) diff --git a/src/node_device.h b/src/node_device.h --- a/src/node_device.h +++ b/src/node_device.h @@ -26,6 +26,7 @@ #include "internal.h" #include "driver.h" +#include "node_device_conf.h" #ifdef HAVE_HAL int halNodeRegister(void); @@ -34,6 +35,9 @@ int devkitNodeRegister(void); int devkitNodeRegister(void); #endif +void nodeDeviceLock(virDeviceMonitorStatePtr driver); +void nodeDeviceUnlock(virDeviceMonitorStatePtr driver); + void registerCommonNodeFuncs(virDeviceMonitorPtr mon); int nodedevRegister(void); diff --git a/src/node_device_conf.h b/src/node_device_conf.h --- a/src/node_device_conf.h +++ b/src/node_device_conf.h @@ -158,7 +158,8 @@ typedef struct _virDeviceMonitorState vi typedef struct _virDeviceMonitorState virDeviceMonitorState; typedef virDeviceMonitorState *virDeviceMonitorStatePtr; struct _virDeviceMonitorState { - int dbusWatch; + PTHREAD_MUTEX_T(lock); + virNodeDeviceObjList devs; /* currently-known devices */ void *privateData; /* driver-specific private data */ }; diff --git a/src/node_device_devkit.c b/src/node_device_devkit.c --- a/src/node_device_devkit.c +++ b/src/node_device_devkit.c @@ -237,6 +237,7 @@ static void dev_create(void *_dkdev, voi DevkitDevice *dkdev = _dkdev; const char *sysfs_path = devkit_device_get_native_path(dkdev); virNodeDeviceObjPtr dev = NULL; + virNodeDeviceDefPtr def = NULL; const char *name; int rv; @@ -250,31 +251,39 @@ static void dev_create(void *_dkdev, voi else ++name; - if (VIR_ALLOC(dev) < 0 || VIR_ALLOC(dev->def) < 0) + if (VIR_ALLOC(def) < 0) goto failure; - dev->privateData = dkdev; - - if ((dev->def->name = strdup(name)) == NULL) + if ((def->name = strdup(name)) == NULL) goto failure; // TODO: Find device parent, if any - rv = gather_capabilities(dkdev, &dev->def->caps); + rv = gather_capabilities(dkdev, &def->caps); if (rv != 0) goto failure; - if (VIR_REALLOC_N(driverState->devs.objs, driverState->devs.count + 1) < 0) + nodeDeviceLock(driverState); + dev = virNodeDeviceAssignDef(NULL, + &driverState->devs, + def); + + if (!dev) { + nodeDeviceUnlock(driverState); goto failure; + } - driverState->devs.objs[driverState->devs.count++] = dev; + dev->privateData = dkdev; + dev->privateFree = NULL; /* XXX some free func needed ? */ + virNodeDeviceObjUnlock(dev); + + nodeDeviceUnlock(driverState); return; failure: DEBUG("FAILED TO ADD dev %s", name); - if (dev) - virNodeDeviceDefFree(dev->def); - VIR_FREE(dev); + if (def) + virNodeDeviceDefFree(def); } @@ -292,8 +301,8 @@ static int devkitDeviceMonitorStartup(vo if (VIR_ALLOC(driverState) < 0) return -1; - // TODO: Is it really ok to call this multiple times?? - // Is there something analogous to call on close? + pthread_mutex_init(&driverState->lock, NULL); + g_type_init(); /* Get new devkit_client and connect to daemon */ @@ -362,10 +371,14 @@ static int devkitDeviceMonitorShutdown(v static int devkitDeviceMonitorShutdown(void) { if (driverState) { - DevkitClient *devkit_client = DRV_STATE_DKCLIENT(driverState); + DevkitClient *devkit_client; + + nodeDeviceLock(driverState); + devkit_client = DRV_STATE_DKCLIENT(driverState); virNodeDeviceObjListFree(&driverState->devs); if (devkit_client) g_object_unref(devkit_client); + nodeDeviceLock(driverState); VIR_FREE(driverState); return 0; } @@ -375,6 +388,8 @@ static int devkitDeviceMonitorShutdown(v static int devkitDeviceMonitorReload(void) { + /* XXX This isn't thread safe because its free'ing the thing + * we're locking */ (void)devkitDeviceMonitorShutdown(); return devkitDeviceMonitorStartup(); } diff --git a/src/node_device_hal.c b/src/node_device_hal.c --- a/src/node_device_hal.c +++ b/src/node_device_hal.c @@ -403,53 +403,62 @@ static void free_udi(void *udi) VIR_FREE(udi); } -static void dev_create(char *udi) +static void dev_create(const char *udi) { - LibHalContext *ctx = DRV_STATE_HAL_CTX(driverState); + LibHalContext *ctx; char *parent_key = NULL; - virNodeDeviceObjPtr dev; + virNodeDeviceObjPtr dev = NULL; + virNodeDeviceDefPtr def = NULL; const char *name = hal_name(udi); int rv; + char *privData = strdup(udi); - if (VIR_ALLOC(dev) < 0 || VIR_ALLOC(dev->def) < 0) + if (!privData) + return; + + nodeDeviceLock(driverState); + ctx = DRV_STATE_HAL_CTX(driverState); + + if (VIR_ALLOC(def) < 0) goto failure; - dev->privateData = udi; - dev->privateFree = free_udi; - - if ((dev->def->name = strdup(name)) == NULL) + if ((def->name = strdup(name)) == NULL) goto failure; if (get_str_prop(ctx, udi, "info.parent", &parent_key) == 0) { - dev->def->parent = strdup(hal_name(parent_key)); + def->parent = strdup(hal_name(parent_key)); VIR_FREE(parent_key); - if (dev->def->parent == NULL) + if (def->parent == NULL) goto failure; } - rv = gather_capabilities(ctx, udi, &dev->def->caps); + rv = gather_capabilities(ctx, udi, &def->caps); if (rv != 0) goto failure; - if (dev->def->caps == NULL) { - virNodeDeviceDefFree(dev->def); - VIR_FREE(dev); - VIR_FREE(udi); - return; - } + if (def->caps == NULL) + goto cleanup; - if (VIR_REALLOC_N(driverState->devs.objs, driverState->devs.count + 1) < 0) + dev = virNodeDeviceAssignDef(NULL, + &driverState->devs, + def); + + if (!dev) goto failure; - driverState->devs.objs[driverState->devs.count++] = dev; + dev->privateData = privData; + dev->privateFree = free_udi; + virNodeDeviceObjUnlock(dev); + nodeDeviceUnlock(driverState); return; failure: DEBUG("FAILED TO ADD dev %s", name); - if (dev) - virNodeDeviceDefFree(dev->def); - VIR_FREE(dev); - VIR_FREE(udi); +cleanup: + VIR_FREE(privData); + if (def) + virNodeDeviceDefFree(def); + nodeDeviceUnlock(driverState); } @@ -457,7 +466,7 @@ static void device_added(LibHalContext * const char *udi) { DEBUG0(hal_name(udi)); - dev_create(strdup(udi)); + dev_create(udi); } @@ -465,12 +474,16 @@ static void device_removed(LibHalContext const char *udi) { const char *name = hal_name(udi); - virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); + virNodeDeviceObjPtr dev; + + nodeDeviceLock(driverState); + dev = virNodeDeviceFindByName(&driverState->devs,name); DEBUG0(name); if (dev) virNodeDeviceObjRemove(&driverState->devs, dev); else DEBUG("no device named %s", name); + nodeDeviceUnlock(driverState); } @@ -478,12 +491,18 @@ static void device_cap_added(LibHalConte const char *udi, const char *cap) { const char *name = hal_name(udi); - virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); + virNodeDeviceObjPtr dev; + + nodeDeviceLock(driverState); + dev = virNodeDeviceFindByName(&driverState->devs,name); + nodeDeviceUnlock(driverState); DEBUG("%s %s", cap, name); - if (dev) + if (dev) { (void)gather_capability(ctx, udi, cap, &dev->def->caps); - else + virNodeDeviceObjUnlock(dev); + } else { DEBUG("no device named %s", name); + } } @@ -492,16 +511,20 @@ static void device_cap_lost(LibHalContex const char *cap) { const char *name = hal_name(udi); - virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); + virNodeDeviceObjPtr dev; + + nodeDeviceLock(driverState); + dev = virNodeDeviceFindByName(&driverState->devs,name); DEBUG("%s %s", cap, name); if (dev) { /* Simply "rediscover" device -- incrementally handling changes * to sub-capabilities (like net.80203) is nasty ... so avoid it. */ virNodeDeviceObjRemove(&driverState->devs, dev); - dev_create(strdup(udi)); + dev_create(udi); } else DEBUG("no device named %s", name); + nodeDeviceUnlock(driverState); } @@ -512,7 +535,10 @@ static void device_prop_modified(LibHalC dbus_bool_t is_added ATTRIBUTE_UNUSED) { const char *name = hal_name(udi); - virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); + virNodeDeviceObjPtr dev; + + nodeDeviceLock(driverState); + dev = virNodeDeviceFindByName(&driverState->devs,name); DEBUG("%s %s", key, name); if (dev) { /* Simply "rediscover" device -- incrementally handling changes @@ -520,9 +546,10 @@ static void device_prop_modified(LibHalC * specific ways) is nasty ... so avoid it. */ virNodeDeviceObjRemove(&driverState->devs, dev); - dev_create(strdup(udi)); + dev_create(udi); } else DEBUG("no device named %s", name); + nodeDeviceUnlock(driverState); } @@ -531,8 +558,8 @@ static void dbus_watch_callback(int fdat int events, void *opaque) { DBusWatch *watch = opaque; - LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState); - DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); + LibHalContext *hal_ctx; + DBusConnection *dbus_conn; int dbus_flags = 0; if (events & VIR_EVENT_HANDLE_READABLE) @@ -546,6 +573,10 @@ static void dbus_watch_callback(int fdat (void)dbus_watch_handle(watch, dbus_flags); + nodeDeviceLock(driverState); + hal_ctx = DRV_STATE_HAL_CTX(driverState); + dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); + nodeDeviceUnlock(driverState); while (dbus_connection_dispatch(dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) /* keep dispatching while data remains */; } @@ -566,42 +597,63 @@ static int xlate_dbus_watch_flags(int db } +struct nodeDeviceWatchInfo +{ + int watch; +}; + +static void nodeDeviceWatchFree(void *data) { + struct nodeDeviceWatchInfo *info = data; + VIR_FREE(info); +} + static dbus_bool_t add_dbus_watch(DBusWatch *watch, - void *data) + void *data ATTRIBUTE_UNUSED) { int flags = 0; - virDeviceMonitorStatePtr state = data; + struct nodeDeviceWatchInfo *info; + + if (VIR_ALLOC(info) < 0) + return 0; if (dbus_watch_get_enabled(watch)) flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch)); - if ((state->dbusWatch = - virEventAddHandle(dbus_watch_get_unix_fd(watch), flags, - dbus_watch_callback, watch, NULL)) < 0) + info->watch = virEventAddHandle(dbus_watch_get_unix_fd(watch), flags, + dbus_watch_callback, watch, NULL); + if (info->watch < 0) { + VIR_FREE(info); return 0; + } + dbus_watch_set_data(watch, info, nodeDeviceWatchFree); + return 1; } -static void remove_dbus_watch(DBusWatch *watch ATTRIBUTE_UNUSED, - void *data) +static void remove_dbus_watch(DBusWatch *watch, + void *data ATTRIBUTE_UNUSED) { - virDeviceMonitorStatePtr state = data; + struct nodeDeviceWatchInfo *info; - (void)virEventRemoveHandle(state->dbusWatch); + info = dbus_watch_get_data(watch); + + (void)virEventRemoveHandle(info->watch); } static void toggle_dbus_watch(DBusWatch *watch, - void *data) + void *data ATTRIBUTE_UNUSED) { int flags = 0; - virDeviceMonitorStatePtr state = data; + struct nodeDeviceWatchInfo *info; if (dbus_watch_get_enabled(watch)) flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch)); - (void)virEventUpdateHandle(state->dbusWatch, flags); + info = dbus_watch_get_data(watch); + + (void)virEventUpdateHandle(info->watch, flags); } @@ -619,6 +671,9 @@ static int halDeviceMonitorStartup(void) if (VIR_ALLOC(driverState) < 0) return -1; + + pthread_mutex_init(&driverState->lock, NULL); + nodeDeviceLock(driverState); /* Allocate and initialize a new HAL context */ dbus_error_init(&err); @@ -647,7 +702,7 @@ static int halDeviceMonitorStartup(void) add_dbus_watch, remove_dbus_watch, toggle_dbus_watch, - driverState, NULL)) { + NULL, NULL)) { fprintf(stderr, "%s: dbus_connection_set_watch_functions failed\n", __FUNCTION__); goto failure; @@ -665,14 +720,18 @@ static int halDeviceMonitorStartup(void) /* Populate with known devices */ driverState->privateData = hal_ctx; + + nodeDeviceUnlock(driverState); udi = libhal_get_all_devices(hal_ctx, &num_devs, &err); if (udi == NULL) { fprintf(stderr, "%s: libhal_get_all_devices failed\n", __FUNCTION__); goto failure; } - for (i = 0; i < num_devs; i++) + for (i = 0; i < num_devs; i++) { dev_create(udi[i]); - free(udi); + VIR_FREE(udi[i]); + } + VIR_FREE(udi); return 0; @@ -686,9 +745,10 @@ static int halDeviceMonitorStartup(void) (void)libhal_ctx_free(hal_ctx); if (udi) { for (i = 0; i < num_devs; i++) - free(udi[i]); - free(udi); + VIR_FREE(udi[i]); + VIR_FREE(udi); } + nodeDeviceUnlock(driverState); VIR_FREE(driverState); return -1; @@ -698,10 +758,12 @@ static int halDeviceMonitorShutdown(void static int halDeviceMonitorShutdown(void) { if (driverState) { + nodeDeviceLock(driverState); LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState); virNodeDeviceObjListFree(&driverState->devs); (void)libhal_ctx_shutdown(hal_ctx, NULL); (void)libhal_ctx_free(hal_ctx); + nodeDeviceUnlock(driverState); VIR_FREE(driverState); return 0; } @@ -711,6 +773,8 @@ static int halDeviceMonitorShutdown(void static int halDeviceMonitorReload(void) { + /* XXX This isn't thread safe because its free'ing the thing + * we're locking */ (void)halDeviceMonitorShutdown(); return halDeviceMonitorStartup(); } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:05:40AM +0000, Daniel P. Berrange wrote:
This patch makes the node device driver thread safe. Almost.
There is on outstanding problem in that the 'reload' method is implemented by just calling shutdown/startup. This causes the mutex we're locking on to be free'd and re-allocated. I'll fix this up later.
reload operatiosn are IMHO one of the most dangerous ops in that thread safe attempts, that's one of the operations where specific testing will be a really good idea. [...]
failure: + nodeDeviceUnlock(driver); --ndevs; while (--ndevs >= 0) VIR_FREE(names[ndevs]);
In general we use error: as the label for error exit paths, failure: is being used only in src/node_device[_devkit/_hal].c: , probably worth standardizing on the same label while we're at it. I will update HACKING to indicate the 3 usual label goto usages in libvirt code: cleanup: common exit cleanup code error: error exit cleanup code retry: attempt at retrying an operation which failed due to a temporary state like a signal interrupting an I/O okay, there is more cleanups and refactoring in that patch, making the change a bit harder to follow (especially in the DevKit part) but I didn't found anything :-) +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch fills in the previous stub methods for locking/unlocking internal objects. With the following methods return a locked object virDomainFindByID virDomainFindByName virDomainFindByUUID virDomainAssignDef All the other methods accepting a virDomainObjPtr instance, require that the object first be locked. For virDomainDefPtr objects, if they are standalone, no locking is required (hence why the Xen driver isn't touched in any of these patches). If they are associated with a virDomainObjPtr though, this parent object must be locked. The same applies for virNetworkObjPtr, virStoragePoolObjPtr and the virNodeDeviceObjPtr objects & their methods. domain_conf.c | 40 ++++++++++++++++++++++++++++++++++++---- domain_conf.h | 2 ++ network_conf.c | 46 ++++++++++++++++++++++++++++++++++++++-------- network_conf.h | 2 ++ node_device_conf.c | 28 +++++++++++++++++++++++++++- node_device_conf.h | 2 ++ storage_conf.c | 35 ++++++++++++++++++++++++++++++++--- storage_conf.h | 2 ++ 8 files changed, 141 insertions(+), 16 deletions(-) Daniel diff --git a/src/domain_conf.c b/src/domain_conf.c --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -151,10 +151,13 @@ virDomainObjPtr virDomainFindByID(const { unsigned int i; - for (i = 0 ; i < doms->count ; i++) + for (i = 0 ; i < doms->count ; i++) { + virDomainObjLock(doms->objs[i]); if (virDomainIsActive(doms->objs[i]) && doms->objs[i]->def->id == id) return doms->objs[i]; + virDomainObjUnlock(doms->objs[i]); + } return NULL; } @@ -165,9 +168,12 @@ virDomainObjPtr virDomainFindByUUID(cons { unsigned int i; - for (i = 0 ; i < doms->count ; i++) + for (i = 0 ; i < doms->count ; i++) { + virDomainObjLock(doms->objs[i]); if (!memcmp(doms->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN)) return doms->objs[i]; + virDomainObjUnlock(doms->objs[i]); + } return NULL; } @@ -177,9 +183,12 @@ virDomainObjPtr virDomainFindByName(cons { unsigned int i; - for (i = 0 ; i < doms->count ; i++) + for (i = 0 ; i < doms->count ; i++) { + virDomainObjLock(doms->objs[i]); if (STREQ(doms->objs[i]->def->name, name)) return doms->objs[i]; + virDomainObjUnlock(doms->objs[i]); + } return NULL; } @@ -455,6 +464,8 @@ virDomainObjPtr virDomainAssignDef(virCo return NULL; } + pthread_mutex_init(&domain->lock, NULL); + virDomainObjLock(domain); domain->state = VIR_DOMAIN_SHUTOFF; domain->def = def; @@ -475,8 +486,12 @@ void virDomainRemoveInactive(virDomainOb { unsigned int i; + virDomainObjUnlock(dom); + for (i = 0 ; i < doms->count ; i++) { + virDomainObjLock(doms->objs[i]); if (doms->objs[i] == dom) { + virDomainObjUnlock(doms->objs[i]); virDomainObjFree(doms->objs[i]); if (i < (doms->count - 1)) @@ -490,6 +505,7 @@ void virDomainRemoveInactive(virDomainOb break; } + virDomainObjUnlock(doms->objs[i]); } } @@ -3337,8 +3353,10 @@ int virDomainLoadAllConfigs(virConnectPt entry->d_name, notify, opaque); - if (dom) + if (dom) { + virDomainObjUnlock(dom); dom->persistent = 1; + } } closedir(dir); @@ -3459,6 +3477,19 @@ const char *virDomainDefDefaultEmulator( } +#ifdef HAVE_PTHREAD_H + +void virDomainObjLock(virDomainObjPtr obj) +{ + pthread_mutex_lock(&obj->lock); +} + +void virDomainObjUnlock(virDomainObjPtr obj) +{ + pthread_mutex_unlock(&obj->lock); +} + +#else void virDomainObjLock(virDomainObjPtr obj ATTRIBUTE_UNUSED) { } @@ -3466,5 +3497,6 @@ void virDomainObjUnlock(virDomainObjPtr void virDomainObjUnlock(virDomainObjPtr obj ATTRIBUTE_UNUSED) { } +#endif #endif /* ! PROXY */ diff --git a/src/domain_conf.h b/src/domain_conf.h --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -454,6 +454,8 @@ typedef struct _virDomainObj virDomainOb typedef struct _virDomainObj virDomainObj; typedef virDomainObj *virDomainObjPtr; struct _virDomainObj { + PTHREAD_MUTEX_T(lock); + int stdin_fd; int stdout_fd; int stdout_watch; diff --git a/src/network_conf.c b/src/network_conf.c --- a/src/network_conf.c +++ b/src/network_conf.c @@ -58,9 +58,12 @@ virNetworkObjPtr virNetworkFindByUUID(co { unsigned int i; - for (i = 0 ; i < nets->count ; i++) + for (i = 0 ; i < nets->count ; i++) { + virNetworkObjLock(nets->objs[i]); if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN)) return nets->objs[i]; + virNetworkObjUnlock(nets->objs[i]); + } return NULL; } @@ -70,9 +73,12 @@ virNetworkObjPtr virNetworkFindByName(co { unsigned int i; - for (i = 0 ; i < nets->count ; i++) + for (i = 0 ; i < nets->count ; i++) { + virNetworkObjLock(nets->objs[i]); if (STREQ(nets->objs[i]->def->name, name)) return nets->objs[i]; + virNetworkObjUnlock(nets->objs[i]); + } return NULL; } @@ -157,7 +163,8 @@ virNetworkObjPtr virNetworkAssignDef(vir virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL); return NULL; } - + pthread_mutex_init(&network->lock, NULL); + virNetworkObjLock(network); network->def = def; if (VIR_REALLOC_N(nets->objs, nets->count + 1) < 0) { @@ -178,8 +185,11 @@ void virNetworkRemoveInactive(virNetwork { unsigned int i; + virNetworkObjUnlock(net); for (i = 0 ; i < nets->count ; i++) { + virNetworkObjLock(nets->objs[i]); if (nets->objs[i] == net) { + virNetworkObjUnlock(nets->objs[i]); virNetworkObjFree(nets->objs[i]); if (i < (nets->count - 1)) @@ -193,6 +203,7 @@ void virNetworkRemoveInactive(virNetwork break; } + virNetworkObjUnlock(nets->objs[i]); } } @@ -770,6 +781,8 @@ int virNetworkLoadAllConfigs(virConnectP } while ((entry = readdir(dir))) { + virNetworkObjPtr net; + if (entry->d_name[0] == '.') continue; @@ -778,11 +791,13 @@ int virNetworkLoadAllConfigs(virConnectP /* NB: ignoring errors, so one malformed config doesn't kill the whole process */ - virNetworkLoadConfig(conn, - nets, - configDir, - autostartDir, - entry->d_name); + net = virNetworkLoadConfig(conn, + nets, + configDir, + autostartDir, + entry->d_name); + if (net) + virNetworkObjUnlock(net); } closedir(dir); @@ -812,6 +827,19 @@ int virNetworkDeleteConfig(virConnectPtr return 0; } +#ifdef HAVE_PTHREAD_H + +void virNetworkObjLock(virNetworkObjPtr obj) +{ + pthread_mutex_lock(&obj->lock); +} + +void virNetworkObjUnlock(virNetworkObjPtr obj) +{ + pthread_mutex_unlock(&obj->lock); +} + +#else void virNetworkObjLock(virNetworkObjPtr obj ATTRIBUTE_UNUSED) { } @@ -819,3 +847,5 @@ void virNetworkObjUnlock(virNetworkObjPt void virNetworkObjUnlock(virNetworkObjPtr obj ATTRIBUTE_UNUSED) { } + +#endif diff --git a/src/network_conf.h b/src/network_conf.h --- a/src/network_conf.h +++ b/src/network_conf.h @@ -82,6 +82,8 @@ typedef struct _virNetworkObj virNetwork typedef struct _virNetworkObj virNetworkObj; typedef virNetworkObj *virNetworkObjPtr; struct _virNetworkObj { + PTHREAD_MUTEX_T(lock); + pid_t dnsmasqPid; unsigned int active : 1; unsigned int autostart : 1; diff --git a/src/node_device_conf.c b/src/node_device_conf.c --- a/src/node_device_conf.c +++ b/src/node_device_conf.c @@ -59,9 +59,12 @@ virNodeDeviceObjPtr virNodeDeviceFindByN { unsigned int i; - for (i = 0; i < devs->count; i++) + for (i = 0; i < devs->count; i++) { + virNodeDeviceObjLock(devs->objs[i]); if (STREQ(devs->objs[i]->def->name, name)) return devs->objs[i]; + virNodeDeviceObjUnlock(devs->objs[i]); + } return NULL; } @@ -125,6 +128,8 @@ virNodeDeviceObjPtr virNodeDeviceAssignD return NULL; } + pthread_mutex_init(&device->lock, NULL); + virNodeDeviceObjLock(device); device->def = def; if (VIR_REALLOC_N(devs->objs, devs->count+1) < 0) { @@ -144,8 +149,12 @@ void virNodeDeviceObjRemove(virNodeDevic { unsigned int i; + virNodeDeviceObjUnlock(dev); + for (i = 0; i < devs->count; i++) { + virNodeDeviceObjLock(dev); if (devs->objs[i] == dev) { + virNodeDeviceObjUnlock(dev); virNodeDeviceObjFree(devs->objs[i]); if (i < (devs->count - 1)) @@ -159,6 +168,7 @@ void virNodeDeviceObjRemove(virNodeDevic break; } + virNodeDeviceObjUnlock(dev); } } @@ -398,6 +408,20 @@ void virNodeDevCapsDefFree(virNodeDevCap } +#ifdef HAVE_PTHREAD_H + +void virNodeDeviceObjLock(virNodeDeviceObjPtr obj) +{ + pthread_mutex_lock(&obj->lock); +} + +void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj) +{ + pthread_mutex_unlock(&obj->lock); +} + +#else + void virNodeDeviceObjLock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED) { } @@ -405,3 +429,5 @@ void virNodeDeviceObjUnlock(virNodeDevic void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED) { } + +#endif diff --git a/src/node_device_conf.h b/src/node_device_conf.h --- a/src/node_device_conf.h +++ b/src/node_device_conf.h @@ -142,6 +142,8 @@ typedef struct _virNodeDeviceObj virNode typedef struct _virNodeDeviceObj virNodeDeviceObj; typedef virNodeDeviceObj *virNodeDeviceObjPtr; struct _virNodeDeviceObj { + PTHREAD_MUTEX_T(lock); + virNodeDeviceDefPtr def; /* device definition */ void *privateData; /* driver-specific private data */ void (*privateFree)(void *data); /* destructor for private data */ diff --git a/src/storage_conf.c b/src/storage_conf.c --- a/src/storage_conf.c +++ b/src/storage_conf.c @@ -305,8 +305,12 @@ virStoragePoolObjRemove(virStoragePoolOb { unsigned int i; + virStoragePoolObjUnlock(pool); + for (i = 0 ; i < pools->count ; i++) { + virStoragePoolObjLock(pools->objs[i]); if (pools->objs[i] == pool) { + virStoragePoolObjUnlock(pools->objs[i]); virStoragePoolObjFree(pools->objs[i]); if (i < (pools->count - 1)) @@ -320,6 +324,7 @@ virStoragePoolObjRemove(virStoragePoolOb break; } + virStoragePoolObjUnlock(pools->objs[i]); } } @@ -1143,9 +1148,12 @@ virStoragePoolObjFindByUUID(virStoragePo const unsigned char *uuid) { unsigned int i; - for (i = 0 ; i < pools->count ; i++) + for (i = 0 ; i < pools->count ; i++) { + virStoragePoolObjLock(pools->objs[i]); if (!memcmp(pools->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN)) return pools->objs[i]; + virStoragePoolObjUnlock(pools->objs[i]); + } return NULL; } @@ -1155,9 +1163,12 @@ virStoragePoolObjFindByName(virStoragePo const char *name) { unsigned int i; - for (i = 0 ; i < pools->count ; i++) + for (i = 0 ; i < pools->count ; i++) { + virStoragePoolObjLock(pools->objs[i]); if (STREQ(pools->objs[i]->def->name, name)) return pools->objs[i]; + virStoragePoolObjUnlock(pools->objs[i]); + } return NULL; } @@ -1233,6 +1244,8 @@ virStoragePoolObjAssignDef(virConnectPtr return NULL; } + pthread_mutex_init(&pool->lock, NULL); + virStoragePoolObjLock(pool); pool->active = 0; pool->def = def; @@ -1317,6 +1330,7 @@ virStoragePoolLoadAllConfigs(virConnectP char *xml = NULL; char path[PATH_MAX]; char autostartLink[PATH_MAX]; + virStoragePoolObjPtr pool; if (entry->d_name[0] == '.') continue; @@ -1341,7 +1355,9 @@ virStoragePoolLoadAllConfigs(virConnectP if (virFileReadAll(path, 8192, &xml) < 0) continue; - virStoragePoolObjLoad(conn, pools, entry->d_name, path, xml, autostartLink); + pool = virStoragePoolObjLoad(conn, pools, entry->d_name, path, xml, autostartLink); + if (pool) + virStoragePoolObjUnlock(pool); VIR_FREE(xml); } @@ -1499,6 +1515,18 @@ char *virStoragePoolSourceListFormat(vir } +#ifdef HAVE_PTHREAD_H + +void virStoragePoolObjLock(virStoragePoolObjPtr obj) +{ + pthread_mutex_lock(&obj->lock); +} + +void virStoragePoolObjUnlock(virStoragePoolObjPtr obj) +{ + pthread_mutex_unlock(&obj->lock); +} +#else void virStoragePoolObjLock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED) { } @@ -1506,3 +1534,4 @@ void virStoragePoolObjUnlock(virStorageP void virStoragePoolObjUnlock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED) { } +#endif diff --git a/src/storage_conf.h b/src/storage_conf.h --- a/src/storage_conf.h +++ b/src/storage_conf.h @@ -223,6 +223,8 @@ typedef virStoragePoolObj *virStoragePoo typedef virStoragePoolObj *virStoragePoolObjPtr; struct _virStoragePoolObj { + PTHREAD_MUTEX_T(lock); + char *configFile; char *autostartLink; int active; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:09:21AM +0000, Daniel P. Berrange wrote:
This patch fills in the previous stub methods for locking/unlocking internal objects.
With the following methods return a locked object
virDomainFindByID virDomainFindByName virDomainFindByUUID virDomainAssignDef
All the other methods accepting a virDomainObjPtr instance, require that the object first be locked.
For virDomainDefPtr objects, if they are standalone, no locking is required (hence why the Xen driver isn't touched in any of these patches). If they are associated with a virDomainObjPtr though, this parent object must be locked.
The same applies for virNetworkObjPtr, virStoragePoolObjPtr and the virNodeDeviceObjPtr objects & their methods.
I've just realized my first posting of this code http://www.redhat.com/archives/libvir-list/2008-October/msg00419.html actually added documentation comments against each method specifying the locking rules, but I've missed that this time. I will write an additional patch to document this for these internal APIs. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:09:21AM +0000, Daniel P. Berrange wrote:
This patch fills in the previous stub methods for locking/unlocking internal objects.
With the following methods return a locked object
virDomainFindByID virDomainFindByName virDomainFindByUUID virDomainAssignDef
All the other methods accepting a virDomainObjPtr instance, require that the object first be locked.
For virDomainDefPtr objects, if they are standalone, no locking is required (hence why the Xen driver isn't touched in any of these patches). If they are associated with a virDomainObjPtr though, this parent object must be locked.
The same applies for virNetworkObjPtr, virStoragePoolObjPtr and the virNodeDeviceObjPtr objects & their methods.
okay,
+#ifdef HAVE_PTHREAD_H + +void virNetworkObjLock(virNetworkObjPtr obj) +{ + pthread_mutex_lock(&obj->lock); +} + +void virNetworkObjUnlock(virNetworkObjPtr obj) +{ + pthread_mutex_unlock(&obj->lock); +}
+1 I would just catch the NULL parameter and return there, it's IMHO nicer to just do that in the (un)locking function than in every cleanup path, and I guess Jim agrees (though not 100% sure about his answer :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This refactors the libvirtd RPC call dispatcher code to be driven off a table lookup, rather than a giant switch. This dramatically reduces the stack usage of this dispatcher and makes the code more efficient, since GCC wasn't optimizing away the switch into a table lookup. There's not been any change since last time i posted this really. b/qemud/Makefile.am | 24 b/qemud/remote.c | 61 +- b/qemud/remote_dispatch_args.h | 101 ++++ b/qemud/remote_dispatch_ret.h | 88 +++ b/qemud/remote_dispatch_table.h | 594 +++++++++++++++++++++++ b/qemud/remote_generate_stubs.pl | 189 ++----- qemud/remote_dispatch_localvars.h | 185 ------- qemud/remote_dispatch_proc_switch.h | 898 ------------------------------------ 8 files changed, 896 insertions(+), 1244 deletions(-) Daniel diff --git a/qemud/Makefile.am b/qemud/Makefile.am --- a/qemud/Makefile.am +++ b/qemud/Makefile.am @@ -5,8 +5,9 @@ DAEMON_SOURCES = \ qemud.c qemud.h \ remote.c \ remote_dispatch_prototypes.h \ - remote_dispatch_localvars.h \ - remote_dispatch_proc_switch.h \ + remote_dispatch_table.h \ + remote_dispatch_args.h \ + remote_dispatch_ret.h \ remote_protocol.h remote_protocol.c AVAHI_SOURCES = \ @@ -179,17 +180,22 @@ endif remote.c: remote_dispatch_prototypes.h \ - remote_dispatch_localvars.h \ - remote_dispatch_proc_switch.h + remote_dispatch_table.h \ + remote_dispatch_args.h \ + remote_dispatch_ret.h remote_dispatch_prototypes.h: $(srcdir)/remote_generate_stubs.pl remote_protocol.x - perl -w $(srcdir)/remote_generate_stubs.pl -i $(srcdir)/remote_protocol.x > $@ + perl -w $(srcdir)/remote_generate_stubs.pl -p $(srcdir)/remote_protocol.x > $@ -remote_dispatch_localvars.h: $(srcdir)/remote_generate_stubs.pl remote_protocol.x - perl -w $(srcdir)/remote_generate_stubs.pl -v $(srcdir)/remote_protocol.x > $@ +remote_dispatch_table.h: $(srcdir)/remote_generate_stubs.pl remote_protocol.x + perl -w $(srcdir)/remote_generate_stubs.pl -t $(srcdir)/remote_protocol.x > $@ -remote_dispatch_proc_switch.h: $(srcdir)/remote_generate_stubs.pl remote_protocol.x - perl -w $(srcdir)/remote_generate_stubs.pl -w $(srcdir)/remote_protocol.x > $@ +remote_dispatch_args.h: $(srcdir)/remote_generate_stubs.pl remote_protocol.x + perl -w $(srcdir)/remote_generate_stubs.pl -a $(srcdir)/remote_protocol.x > $@ + +remote_dispatch_ret.h: $(srcdir)/remote_generate_stubs.pl remote_protocol.x + perl -w $(srcdir)/remote_generate_stubs.pl -r $(srcdir)/remote_protocol.x > $@ + if LIBVIRT_INIT_SCRIPTS_RED_HAT install-init: libvirtd.init diff --git a/qemud/remote.c b/qemud/remote.c --- a/qemud/remote.c +++ b/qemud/remote.c @@ -71,11 +71,30 @@ static void make_nonnull_node_device (re #include "remote_dispatch_prototypes.h" +typedef union { +#include "remote_dispatch_args.h" +} dispatch_args; + +typedef union { +#include "remote_dispatch_ret.h" +} dispatch_ret; + + typedef int (*dispatch_fn) (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, - char *args, - char *ret); + dispatch_args *args, + dispatch_ret *ret); + +typedef struct { + dispatch_fn fn; + xdrproc_t args_filter; + xdrproc_t ret_filter; +} dispatch_data; + +static const dispatch_data const dispatch_table[] = { +#include "remote_dispatch_table.h" +}; /* Prototypes */ static void @@ -94,13 +113,13 @@ remoteDispatchClientRequest (struct qemu { XDR xdr; remote_message_header req, rep; - dispatch_fn fn; - xdrproc_t args_filter = (xdrproc_t) xdr_void; - xdrproc_t ret_filter = (xdrproc_t) xdr_void; - char *args = NULL, *ret = NULL; + dispatch_args args; + dispatch_ret ret; + const dispatch_data *data = NULL; int rv, len; -#include "remote_dispatch_localvars.h" + memset(&args, 0, sizeof args); + memset(&ret, 0, sizeof ret); /* Parse the header. */ xdrmem_create (&xdr, client->buffer, client->bufferLength, XDR_DECODE); @@ -155,31 +174,27 @@ remoteDispatchClientRequest (struct qemu } } - /* Based on the procedure number, dispatch. In future we may base - * this on the version number as well. - */ - switch (req.proc) { -#include "remote_dispatch_proc_switch.h" - - default: + if (req.proc >= ARRAY_CARDINALITY(dispatch_table) || + dispatch_table[req.proc].fn == NULL) { remoteDispatchError (client, &req, _("unknown procedure: %d"), req.proc); xdr_destroy (&xdr); return; } - /* Parse args. */ - if (!(*args_filter) (&xdr, args)) { + data = &(dispatch_table[req.proc]); + + /* De-serialize args off the wire */ + if (!((data->args_filter)(&xdr, &args))) { remoteDispatchError (client, &req, "%s", _("parse args failed")); xdr_destroy (&xdr); - return; } xdr_destroy (&xdr); /* Call function. */ - rv = fn (server, client, &req, args, ret); - xdr_free (args_filter, args); + rv = (data->fn)(server, client, &req, &args, &ret); + xdr_free (data->args_filter, (char*)&args); /* Dispatch function must return -2, -1 or 0. Anything else is * an internal error. @@ -210,25 +225,25 @@ remoteDispatchClientRequest (struct qemu if (!xdr_int (&xdr, &len)) { remoteDispatchError (client, &req, "%s", _("dummy length")); xdr_destroy (&xdr); - if (rv == 0) xdr_free (ret_filter, ret); + if (rv == 0) xdr_free (data->ret_filter, (char*)&ret); return; } if (!xdr_remote_message_header (&xdr, &rep)) { remoteDispatchError (client, &req, "%s", _("serialise reply header")); xdr_destroy (&xdr); - if (rv == 0) xdr_free (ret_filter, ret); + if (rv == 0) xdr_free (data->ret_filter, (char*)&ret); return; } /* If OK, serialise return structure, if error serialise error. */ if (rv == 0) { - if (!(*ret_filter) (&xdr, ret)) { + if (!((data->ret_filter) (&xdr, &ret))) { remoteDispatchError (client, &req, "%s", _("serialise return struct")); xdr_destroy (&xdr); return; } - xdr_free (ret_filter, ret); + xdr_free (data->ret_filter, (char*)&ret); } else /* error */ { virErrorPtr verr; remote_error error; diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h new file mode 100644 --- /dev/null +++ b/qemud/remote_dispatch_args.h @@ -0,0 +1,101 @@ +/* Automatically generated by remote_generate_stubs.pl. + * Do not edit this file. Any changes you make will be lost. + */ + + remote_open_args val_remote_open_args; + remote_get_max_vcpus_args val_remote_get_max_vcpus_args; + remote_domain_attach_device_args val_remote_domain_attach_device_args; + remote_domain_create_args val_remote_domain_create_args; + remote_domain_create_xml_args val_remote_domain_create_xml_args; + remote_domain_define_xml_args val_remote_domain_define_xml_args; + remote_domain_destroy_args val_remote_domain_destroy_args; + remote_domain_detach_device_args val_remote_domain_detach_device_args; + remote_domain_dump_xml_args val_remote_domain_dump_xml_args; + remote_domain_get_autostart_args val_remote_domain_get_autostart_args; + remote_domain_get_info_args val_remote_domain_get_info_args; + remote_domain_get_max_memory_args val_remote_domain_get_max_memory_args; + remote_domain_get_max_vcpus_args val_remote_domain_get_max_vcpus_args; + remote_domain_get_os_type_args val_remote_domain_get_os_type_args; + remote_domain_get_vcpus_args val_remote_domain_get_vcpus_args; + remote_list_defined_domains_args val_remote_list_defined_domains_args; + remote_domain_lookup_by_id_args val_remote_domain_lookup_by_id_args; + remote_domain_lookup_by_name_args val_remote_domain_lookup_by_name_args; + remote_domain_lookup_by_uuid_args val_remote_domain_lookup_by_uuid_args; + remote_domain_pin_vcpu_args val_remote_domain_pin_vcpu_args; + remote_domain_reboot_args val_remote_domain_reboot_args; + remote_domain_resume_args val_remote_domain_resume_args; + remote_domain_set_autostart_args val_remote_domain_set_autostart_args; + remote_domain_set_max_memory_args val_remote_domain_set_max_memory_args; + remote_domain_set_memory_args val_remote_domain_set_memory_args; + remote_domain_set_vcpus_args val_remote_domain_set_vcpus_args; + remote_domain_shutdown_args val_remote_domain_shutdown_args; + remote_domain_suspend_args val_remote_domain_suspend_args; + remote_domain_undefine_args val_remote_domain_undefine_args; + remote_list_defined_networks_args val_remote_list_defined_networks_args; + remote_list_domains_args val_remote_list_domains_args; + remote_list_networks_args val_remote_list_networks_args; + remote_network_create_args val_remote_network_create_args; + remote_network_create_xml_args val_remote_network_create_xml_args; + remote_network_define_xml_args val_remote_network_define_xml_args; + remote_network_destroy_args val_remote_network_destroy_args; + remote_network_dump_xml_args val_remote_network_dump_xml_args; + remote_network_get_autostart_args val_remote_network_get_autostart_args; + remote_network_get_bridge_name_args val_remote_network_get_bridge_name_args; + remote_network_lookup_by_name_args val_remote_network_lookup_by_name_args; + remote_network_lookup_by_uuid_args val_remote_network_lookup_by_uuid_args; + remote_network_set_autostart_args val_remote_network_set_autostart_args; + remote_network_undefine_args val_remote_network_undefine_args; + remote_domain_core_dump_args val_remote_domain_core_dump_args; + remote_domain_restore_args val_remote_domain_restore_args; + remote_domain_save_args val_remote_domain_save_args; + remote_domain_get_scheduler_type_args val_remote_domain_get_scheduler_type_args; + remote_domain_get_scheduler_parameters_args val_remote_domain_get_scheduler_parameters_args; + remote_domain_set_scheduler_parameters_args val_remote_domain_set_scheduler_parameters_args; + remote_supports_feature_args val_remote_supports_feature_args; + remote_domain_migrate_prepare_args val_remote_domain_migrate_prepare_args; + remote_domain_migrate_perform_args val_remote_domain_migrate_perform_args; + remote_domain_migrate_finish_args val_remote_domain_migrate_finish_args; + remote_domain_block_stats_args val_remote_domain_block_stats_args; + remote_domain_interface_stats_args val_remote_domain_interface_stats_args; + remote_auth_sasl_start_args val_remote_auth_sasl_start_args; + remote_auth_sasl_step_args val_remote_auth_sasl_step_args; + remote_list_storage_pools_args val_remote_list_storage_pools_args; + remote_list_defined_storage_pools_args val_remote_list_defined_storage_pools_args; + remote_find_storage_pool_sources_args val_remote_find_storage_pool_sources_args; + remote_storage_pool_create_xml_args val_remote_storage_pool_create_xml_args; + remote_storage_pool_define_xml_args val_remote_storage_pool_define_xml_args; + remote_storage_pool_create_args val_remote_storage_pool_create_args; + remote_storage_pool_build_args val_remote_storage_pool_build_args; + remote_storage_pool_destroy_args val_remote_storage_pool_destroy_args; + remote_storage_pool_delete_args val_remote_storage_pool_delete_args; + remote_storage_pool_undefine_args val_remote_storage_pool_undefine_args; + remote_storage_pool_refresh_args val_remote_storage_pool_refresh_args; + remote_storage_pool_lookup_by_name_args val_remote_storage_pool_lookup_by_name_args; + remote_storage_pool_lookup_by_uuid_args val_remote_storage_pool_lookup_by_uuid_args; + remote_storage_pool_lookup_by_volume_args val_remote_storage_pool_lookup_by_volume_args; + remote_storage_pool_get_info_args val_remote_storage_pool_get_info_args; + remote_storage_pool_dump_xml_args val_remote_storage_pool_dump_xml_args; + remote_storage_pool_get_autostart_args val_remote_storage_pool_get_autostart_args; + remote_storage_pool_set_autostart_args val_remote_storage_pool_set_autostart_args; + remote_storage_pool_num_of_volumes_args val_remote_storage_pool_num_of_volumes_args; + remote_storage_pool_list_volumes_args val_remote_storage_pool_list_volumes_args; + remote_storage_vol_create_xml_args val_remote_storage_vol_create_xml_args; + remote_storage_vol_delete_args val_remote_storage_vol_delete_args; + remote_storage_vol_lookup_by_name_args val_remote_storage_vol_lookup_by_name_args; + remote_storage_vol_lookup_by_key_args val_remote_storage_vol_lookup_by_key_args; + remote_storage_vol_lookup_by_path_args val_remote_storage_vol_lookup_by_path_args; + remote_storage_vol_get_info_args val_remote_storage_vol_get_info_args; + remote_storage_vol_dump_xml_args val_remote_storage_vol_dump_xml_args; + remote_storage_vol_get_path_args val_remote_storage_vol_get_path_args; + remote_node_get_cells_free_memory_args val_remote_node_get_cells_free_memory_args; + remote_domain_block_peek_args val_remote_domain_block_peek_args; + remote_domain_memory_peek_args val_remote_domain_memory_peek_args; + remote_domain_migrate_prepare2_args val_remote_domain_migrate_prepare2_args; + remote_domain_migrate_finish2_args val_remote_domain_migrate_finish2_args; + remote_node_num_of_devices_args val_remote_node_num_of_devices_args; + remote_node_list_devices_args val_remote_node_list_devices_args; + remote_node_device_lookup_by_name_args val_remote_node_device_lookup_by_name_args; + remote_node_device_dump_xml_args val_remote_node_device_dump_xml_args; + remote_node_device_get_parent_args val_remote_node_device_get_parent_args; + remote_node_device_num_of_caps_args val_remote_node_device_num_of_caps_args; + remote_node_device_list_caps_args val_remote_node_device_list_caps_args; diff --git a/qemud/remote_dispatch_localvars.h b/qemud/remote_dispatch_localvars.h deleted file mode 100644 --- a/qemud/remote_dispatch_localvars.h +++ /dev/null @@ -1,185 +0,0 @@ -/* Automatically generated by remote_generate_stubs.pl. - * Do not edit this file. Any changes you make will be lost. - */ - -remote_domain_lookup_by_uuid_args lv_remote_domain_lookup_by_uuid_args; -remote_domain_lookup_by_uuid_ret lv_remote_domain_lookup_by_uuid_ret; -remote_storage_pool_list_volumes_args lv_remote_storage_pool_list_volumes_args; -remote_storage_pool_list_volumes_ret lv_remote_storage_pool_list_volumes_ret; -remote_domain_events_deregister_ret lv_remote_domain_events_deregister_ret; -remote_node_device_get_parent_args lv_remote_node_device_get_parent_args; -remote_node_device_get_parent_ret lv_remote_node_device_get_parent_ret; -remote_domain_shutdown_args lv_remote_domain_shutdown_args; -remote_list_defined_domains_args lv_remote_list_defined_domains_args; -remote_list_defined_domains_ret lv_remote_list_defined_domains_ret; -remote_get_capabilities_ret lv_remote_get_capabilities_ret; -remote_storage_vol_create_xml_args lv_remote_storage_vol_create_xml_args; -remote_storage_vol_create_xml_ret lv_remote_storage_vol_create_xml_ret; -remote_domain_set_max_memory_args lv_remote_domain_set_max_memory_args; -remote_auth_sasl_init_ret lv_remote_auth_sasl_init_ret; -remote_domain_get_os_type_args lv_remote_domain_get_os_type_args; -remote_domain_get_os_type_ret lv_remote_domain_get_os_type_ret; -remote_domain_get_autostart_args lv_remote_domain_get_autostart_args; -remote_domain_get_autostart_ret lv_remote_domain_get_autostart_ret; -remote_domain_set_vcpus_args lv_remote_domain_set_vcpus_args; -remote_get_hostname_ret lv_remote_get_hostname_ret; -remote_domain_events_register_ret lv_remote_domain_events_register_ret; -remote_network_undefine_args lv_remote_network_undefine_args; -remote_domain_create_args lv_remote_domain_create_args; -remote_network_destroy_args lv_remote_network_destroy_args; -remote_storage_vol_lookup_by_key_args lv_remote_storage_vol_lookup_by_key_args; -remote_storage_vol_lookup_by_key_ret lv_remote_storage_vol_lookup_by_key_ret; -remote_storage_pool_lookup_by_uuid_args lv_remote_storage_pool_lookup_by_uuid_args; -remote_storage_pool_lookup_by_uuid_ret lv_remote_storage_pool_lookup_by_uuid_ret; -remote_domain_pin_vcpu_args lv_remote_domain_pin_vcpu_args; -remote_list_defined_networks_args lv_remote_list_defined_networks_args; -remote_list_defined_networks_ret lv_remote_list_defined_networks_ret; -remote_network_create_xml_args lv_remote_network_create_xml_args; -remote_network_create_xml_ret lv_remote_network_create_xml_ret; -remote_node_device_list_caps_args lv_remote_node_device_list_caps_args; -remote_node_device_list_caps_ret lv_remote_node_device_list_caps_ret; -remote_open_args lv_remote_open_args; -remote_storage_pool_refresh_args lv_remote_storage_pool_refresh_args; -remote_storage_vol_lookup_by_path_args lv_remote_storage_vol_lookup_by_path_args; -remote_storage_vol_lookup_by_path_ret lv_remote_storage_vol_lookup_by_path_ret; -remote_list_domains_args lv_remote_list_domains_args; -remote_list_domains_ret lv_remote_list_domains_ret; -remote_network_define_xml_args lv_remote_network_define_xml_args; -remote_network_define_xml_ret lv_remote_network_define_xml_ret; -remote_get_type_ret lv_remote_get_type_ret; -remote_domain_block_peek_args lv_remote_domain_block_peek_args; -remote_domain_block_peek_ret lv_remote_domain_block_peek_ret; -remote_storage_vol_delete_args lv_remote_storage_vol_delete_args; -remote_network_dump_xml_args lv_remote_network_dump_xml_args; -remote_network_dump_xml_ret lv_remote_network_dump_xml_ret; -remote_domain_reboot_args lv_remote_domain_reboot_args; -remote_domain_set_memory_args lv_remote_domain_set_memory_args; -remote_storage_pool_destroy_args lv_remote_storage_pool_destroy_args; -remote_domain_set_scheduler_parameters_args lv_remote_domain_set_scheduler_parameters_args; -remote_auth_polkit_ret lv_remote_auth_polkit_ret; -remote_auth_sasl_start_args lv_remote_auth_sasl_start_args; -remote_auth_sasl_start_ret lv_remote_auth_sasl_start_ret; -remote_domain_interface_stats_args lv_remote_domain_interface_stats_args; -remote_domain_interface_stats_ret lv_remote_domain_interface_stats_ret; -remote_storage_pool_dump_xml_args lv_remote_storage_pool_dump_xml_args; -remote_storage_pool_dump_xml_ret lv_remote_storage_pool_dump_xml_ret; -remote_storage_pool_create_xml_args lv_remote_storage_pool_create_xml_args; -remote_storage_pool_create_xml_ret lv_remote_storage_pool_create_xml_ret; -remote_storage_pool_build_args lv_remote_storage_pool_build_args; -remote_storage_pool_delete_args lv_remote_storage_pool_delete_args; -remote_storage_pool_lookup_by_volume_args lv_remote_storage_pool_lookup_by_volume_args; -remote_storage_pool_lookup_by_volume_ret lv_remote_storage_pool_lookup_by_volume_ret; -remote_domain_get_max_vcpus_args lv_remote_domain_get_max_vcpus_args; -remote_domain_get_max_vcpus_ret lv_remote_domain_get_max_vcpus_ret; -remote_node_device_num_of_caps_args lv_remote_node_device_num_of_caps_args; -remote_node_device_num_of_caps_ret lv_remote_node_device_num_of_caps_ret; -remote_domain_get_info_args lv_remote_domain_get_info_args; -remote_domain_get_info_ret lv_remote_domain_get_info_ret; -remote_storage_pool_num_of_volumes_args lv_remote_storage_pool_num_of_volumes_args; -remote_storage_pool_num_of_volumes_ret lv_remote_storage_pool_num_of_volumes_ret; -remote_supports_feature_args lv_remote_supports_feature_args; -remote_supports_feature_ret lv_remote_supports_feature_ret; -remote_domain_lookup_by_name_args lv_remote_domain_lookup_by_name_args; -remote_domain_lookup_by_name_ret lv_remote_domain_lookup_by_name_ret; -remote_storage_pool_set_autostart_args lv_remote_storage_pool_set_autostart_args; -remote_domain_resume_args lv_remote_domain_resume_args; -remote_network_get_bridge_name_args lv_remote_network_get_bridge_name_args; -remote_network_get_bridge_name_ret lv_remote_network_get_bridge_name_ret; -remote_domain_destroy_args lv_remote_domain_destroy_args; -remote_find_storage_pool_sources_args lv_remote_find_storage_pool_sources_args; -remote_find_storage_pool_sources_ret lv_remote_find_storage_pool_sources_ret; -remote_node_num_of_devices_args lv_remote_node_num_of_devices_args; -remote_node_num_of_devices_ret lv_remote_node_num_of_devices_ret; -remote_auth_sasl_step_args lv_remote_auth_sasl_step_args; -remote_auth_sasl_step_ret lv_remote_auth_sasl_step_ret; -remote_domain_migrate_finish_args lv_remote_domain_migrate_finish_args; -remote_domain_migrate_finish_ret lv_remote_domain_migrate_finish_ret; -remote_domain_get_vcpus_args lv_remote_domain_get_vcpus_args; -remote_domain_get_vcpus_ret lv_remote_domain_get_vcpus_ret; -remote_domain_get_scheduler_parameters_args lv_remote_domain_get_scheduler_parameters_args; -remote_domain_get_scheduler_parameters_ret lv_remote_domain_get_scheduler_parameters_ret; -remote_node_get_info_ret lv_remote_node_get_info_ret; -remote_node_device_dump_xml_args lv_remote_node_device_dump_xml_args; -remote_node_device_dump_xml_ret lv_remote_node_device_dump_xml_ret; -remote_node_device_lookup_by_name_args lv_remote_node_device_lookup_by_name_args; -remote_node_device_lookup_by_name_ret lv_remote_node_device_lookup_by_name_ret; -remote_network_lookup_by_name_args lv_remote_network_lookup_by_name_args; -remote_network_lookup_by_name_ret lv_remote_network_lookup_by_name_ret; -remote_domain_memory_peek_args lv_remote_domain_memory_peek_args; -remote_domain_memory_peek_ret lv_remote_domain_memory_peek_ret; -remote_num_of_defined_domains_ret lv_remote_num_of_defined_domains_ret; -remote_node_list_devices_args lv_remote_node_list_devices_args; -remote_node_list_devices_ret lv_remote_node_list_devices_ret; -remote_domain_block_stats_args lv_remote_domain_block_stats_args; -remote_domain_block_stats_ret lv_remote_domain_block_stats_ret; -remote_domain_detach_device_args lv_remote_domain_detach_device_args; -remote_num_of_storage_pools_ret lv_remote_num_of_storage_pools_ret; -remote_domain_save_args lv_remote_domain_save_args; -remote_domain_migrate_prepare_args lv_remote_domain_migrate_prepare_args; -remote_domain_migrate_prepare_ret lv_remote_domain_migrate_prepare_ret; -remote_domain_create_xml_args lv_remote_domain_create_xml_args; -remote_domain_create_xml_ret lv_remote_domain_create_xml_ret; -remote_domain_undefine_args lv_remote_domain_undefine_args; -remote_node_get_cells_free_memory_args lv_remote_node_get_cells_free_memory_args; -remote_node_get_cells_free_memory_ret lv_remote_node_get_cells_free_memory_ret; -remote_domain_get_scheduler_type_args lv_remote_domain_get_scheduler_type_args; -remote_domain_get_scheduler_type_ret lv_remote_domain_get_scheduler_type_ret; -remote_get_version_ret lv_remote_get_version_ret; -remote_domain_suspend_args lv_remote_domain_suspend_args; -remote_storage_pool_lookup_by_name_args lv_remote_storage_pool_lookup_by_name_args; -remote_storage_pool_lookup_by_name_ret lv_remote_storage_pool_lookup_by_name_ret; -remote_network_set_autostart_args lv_remote_network_set_autostart_args; -remote_network_get_autostart_args lv_remote_network_get_autostart_args; -remote_network_get_autostart_ret lv_remote_network_get_autostart_ret; -remote_storage_pool_create_args lv_remote_storage_pool_create_args; -remote_auth_list_ret lv_remote_auth_list_ret; -remote_num_of_defined_storage_pools_ret lv_remote_num_of_defined_storage_pools_ret; -remote_domain_core_dump_args lv_remote_domain_core_dump_args; -remote_list_defined_storage_pools_args lv_remote_list_defined_storage_pools_args; -remote_list_defined_storage_pools_ret lv_remote_list_defined_storage_pools_ret; -remote_domain_event_ret lv_remote_domain_event_ret; -remote_domain_get_max_memory_args lv_remote_domain_get_max_memory_args; -remote_domain_get_max_memory_ret lv_remote_domain_get_max_memory_ret; -remote_num_of_domains_ret lv_remote_num_of_domains_ret; -remote_list_networks_args lv_remote_list_networks_args; -remote_list_networks_ret lv_remote_list_networks_ret; -remote_storage_pool_undefine_args lv_remote_storage_pool_undefine_args; -remote_domain_migrate_finish2_args lv_remote_domain_migrate_finish2_args; -remote_domain_migrate_finish2_ret lv_remote_domain_migrate_finish2_ret; -remote_domain_set_autostart_args lv_remote_domain_set_autostart_args; -remote_storage_pool_get_autostart_args lv_remote_storage_pool_get_autostart_args; -remote_storage_pool_get_autostart_ret lv_remote_storage_pool_get_autostart_ret; -remote_node_get_free_memory_ret lv_remote_node_get_free_memory_ret; -remote_domain_migrate_prepare2_args lv_remote_domain_migrate_prepare2_args; -remote_domain_migrate_prepare2_ret lv_remote_domain_migrate_prepare2_ret; -remote_storage_vol_get_path_args lv_remote_storage_vol_get_path_args; -remote_storage_vol_get_path_ret lv_remote_storage_vol_get_path_ret; -remote_domain_lookup_by_id_args lv_remote_domain_lookup_by_id_args; -remote_domain_lookup_by_id_ret lv_remote_domain_lookup_by_id_ret; -remote_get_uri_ret lv_remote_get_uri_ret; -remote_domain_attach_device_args lv_remote_domain_attach_device_args; -remote_num_of_networks_ret lv_remote_num_of_networks_ret; -remote_storage_pool_get_info_args lv_remote_storage_pool_get_info_args; -remote_storage_pool_get_info_ret lv_remote_storage_pool_get_info_ret; -remote_list_storage_pools_args lv_remote_list_storage_pools_args; -remote_list_storage_pools_ret lv_remote_list_storage_pools_ret; -remote_domain_restore_args lv_remote_domain_restore_args; -remote_network_create_args lv_remote_network_create_args; -remote_num_of_defined_networks_ret lv_remote_num_of_defined_networks_ret; -remote_storage_vol_lookup_by_name_args lv_remote_storage_vol_lookup_by_name_args; -remote_storage_vol_lookup_by_name_ret lv_remote_storage_vol_lookup_by_name_ret; -remote_storage_pool_define_xml_args lv_remote_storage_pool_define_xml_args; -remote_storage_pool_define_xml_ret lv_remote_storage_pool_define_xml_ret; -remote_network_lookup_by_uuid_args lv_remote_network_lookup_by_uuid_args; -remote_network_lookup_by_uuid_ret lv_remote_network_lookup_by_uuid_ret; -remote_storage_vol_get_info_args lv_remote_storage_vol_get_info_args; -remote_storage_vol_get_info_ret lv_remote_storage_vol_get_info_ret; -remote_domain_define_xml_args lv_remote_domain_define_xml_args; -remote_domain_define_xml_ret lv_remote_domain_define_xml_ret; -remote_storage_vol_dump_xml_args lv_remote_storage_vol_dump_xml_args; -remote_storage_vol_dump_xml_ret lv_remote_storage_vol_dump_xml_ret; -remote_domain_dump_xml_args lv_remote_domain_dump_xml_args; -remote_domain_dump_xml_ret lv_remote_domain_dump_xml_ret; -remote_get_max_vcpus_args lv_remote_get_max_vcpus_args; -remote_get_max_vcpus_ret lv_remote_get_max_vcpus_ret; -remote_domain_migrate_perform_args lv_remote_domain_migrate_perform_args; diff --git a/qemud/remote_dispatch_proc_switch.h b/qemud/remote_dispatch_proc_switch.h deleted file mode 100644 --- a/qemud/remote_dispatch_proc_switch.h +++ /dev/null @@ -1,898 +0,0 @@ -/* Automatically generated by remote_generate_stubs.pl. - * Do not edit this file. Any changes you make will be lost. - */ - -case REMOTE_PROC_AUTH_LIST: - fn = (dispatch_fn) remoteDispatchAuthList; - ret_filter = (xdrproc_t) xdr_remote_auth_list_ret; - ret = (char *) &lv_remote_auth_list_ret; - memset (&lv_remote_auth_list_ret, 0, sizeof lv_remote_auth_list_ret); - break; -case REMOTE_PROC_AUTH_POLKIT: - fn = (dispatch_fn) remoteDispatchAuthPolkit; - ret_filter = (xdrproc_t) xdr_remote_auth_polkit_ret; - ret = (char *) &lv_remote_auth_polkit_ret; - memset (&lv_remote_auth_polkit_ret, 0, sizeof lv_remote_auth_polkit_ret); - break; -case REMOTE_PROC_AUTH_SASL_INIT: - fn = (dispatch_fn) remoteDispatchAuthSaslInit; - ret_filter = (xdrproc_t) xdr_remote_auth_sasl_init_ret; - ret = (char *) &lv_remote_auth_sasl_init_ret; - memset (&lv_remote_auth_sasl_init_ret, 0, sizeof lv_remote_auth_sasl_init_ret); - break; -case REMOTE_PROC_AUTH_SASL_START: - fn = (dispatch_fn) remoteDispatchAuthSaslStart; - args_filter = (xdrproc_t) xdr_remote_auth_sasl_start_args; - args = (char *) &lv_remote_auth_sasl_start_args; - memset (&lv_remote_auth_sasl_start_args, 0, sizeof lv_remote_auth_sasl_start_args); - ret_filter = (xdrproc_t) xdr_remote_auth_sasl_start_ret; - ret = (char *) &lv_remote_auth_sasl_start_ret; - memset (&lv_remote_auth_sasl_start_ret, 0, sizeof lv_remote_auth_sasl_start_ret); - break; -case REMOTE_PROC_AUTH_SASL_STEP: - fn = (dispatch_fn) remoteDispatchAuthSaslStep; - args_filter = (xdrproc_t) xdr_remote_auth_sasl_step_args; - args = (char *) &lv_remote_auth_sasl_step_args; - memset (&lv_remote_auth_sasl_step_args, 0, sizeof lv_remote_auth_sasl_step_args); - ret_filter = (xdrproc_t) xdr_remote_auth_sasl_step_ret; - ret = (char *) &lv_remote_auth_sasl_step_ret; - memset (&lv_remote_auth_sasl_step_ret, 0, sizeof lv_remote_auth_sasl_step_ret); - break; -case REMOTE_PROC_CLOSE: - fn = (dispatch_fn) remoteDispatchClose; - break; -case REMOTE_PROC_DOMAIN_ATTACH_DEVICE: - fn = (dispatch_fn) remoteDispatchDomainAttachDevice; - args_filter = (xdrproc_t) xdr_remote_domain_attach_device_args; - args = (char *) &lv_remote_domain_attach_device_args; - memset (&lv_remote_domain_attach_device_args, 0, sizeof lv_remote_domain_attach_device_args); - break; -case REMOTE_PROC_DOMAIN_BLOCK_PEEK: - fn = (dispatch_fn) remoteDispatchDomainBlockPeek; - args_filter = (xdrproc_t) xdr_remote_domain_block_peek_args; - args = (char *) &lv_remote_domain_block_peek_args; - memset (&lv_remote_domain_block_peek_args, 0, sizeof lv_remote_domain_block_peek_args); - ret_filter = (xdrproc_t) xdr_remote_domain_block_peek_ret; - ret = (char *) &lv_remote_domain_block_peek_ret; - memset (&lv_remote_domain_block_peek_ret, 0, sizeof lv_remote_domain_block_peek_ret); - break; -case REMOTE_PROC_DOMAIN_BLOCK_STATS: - fn = (dispatch_fn) remoteDispatchDomainBlockStats; - args_filter = (xdrproc_t) xdr_remote_domain_block_stats_args; - args = (char *) &lv_remote_domain_block_stats_args; - memset (&lv_remote_domain_block_stats_args, 0, sizeof lv_remote_domain_block_stats_args); - ret_filter = (xdrproc_t) xdr_remote_domain_block_stats_ret; - ret = (char *) &lv_remote_domain_block_stats_ret; - memset (&lv_remote_domain_block_stats_ret, 0, sizeof lv_remote_domain_block_stats_ret); - break; -case REMOTE_PROC_DOMAIN_CORE_DUMP: - fn = (dispatch_fn) remoteDispatchDomainCoreDump; - args_filter = (xdrproc_t) xdr_remote_domain_core_dump_args; - args = (char *) &lv_remote_domain_core_dump_args; - memset (&lv_remote_domain_core_dump_args, 0, sizeof lv_remote_domain_core_dump_args); - break; -case REMOTE_PROC_DOMAIN_CREATE: - fn = (dispatch_fn) remoteDispatchDomainCreate; - args_filter = (xdrproc_t) xdr_remote_domain_create_args; - args = (char *) &lv_remote_domain_create_args; - memset (&lv_remote_domain_create_args, 0, sizeof lv_remote_domain_create_args); - break; -case REMOTE_PROC_DOMAIN_CREATE_XML: - fn = (dispatch_fn) remoteDispatchDomainCreateXml; - args_filter = (xdrproc_t) xdr_remote_domain_create_xml_args; - args = (char *) &lv_remote_domain_create_xml_args; - memset (&lv_remote_domain_create_xml_args, 0, sizeof lv_remote_domain_create_xml_args); - ret_filter = (xdrproc_t) xdr_remote_domain_create_xml_ret; - ret = (char *) &lv_remote_domain_create_xml_ret; - memset (&lv_remote_domain_create_xml_ret, 0, sizeof lv_remote_domain_create_xml_ret); - break; -case REMOTE_PROC_DOMAIN_DEFINE_XML: - fn = (dispatch_fn) remoteDispatchDomainDefineXml; - args_filter = (xdrproc_t) xdr_remote_domain_define_xml_args; - args = (char *) &lv_remote_domain_define_xml_args; - memset (&lv_remote_domain_define_xml_args, 0, sizeof lv_remote_domain_define_xml_args); - ret_filter = (xdrproc_t) xdr_remote_domain_define_xml_ret; - ret = (char *) &lv_remote_domain_define_xml_ret; - memset (&lv_remote_domain_define_xml_ret, 0, sizeof lv_remote_domain_define_xml_ret); - break; -case REMOTE_PROC_DOMAIN_DESTROY: - fn = (dispatch_fn) remoteDispatchDomainDestroy; - args_filter = (xdrproc_t) xdr_remote_domain_destroy_args; - args = (char *) &lv_remote_domain_destroy_args; - memset (&lv_remote_domain_destroy_args, 0, sizeof lv_remote_domain_destroy_args); - break; -case REMOTE_PROC_DOMAIN_DETACH_DEVICE: - fn = (dispatch_fn) remoteDispatchDomainDetachDevice; - args_filter = (xdrproc_t) xdr_remote_domain_detach_device_args; - args = (char *) &lv_remote_domain_detach_device_args; - memset (&lv_remote_domain_detach_device_args, 0, sizeof lv_remote_domain_detach_device_args); - break; -case REMOTE_PROC_DOMAIN_DUMP_XML: - fn = (dispatch_fn) remoteDispatchDomainDumpXml; - args_filter = (xdrproc_t) xdr_remote_domain_dump_xml_args; - args = (char *) &lv_remote_domain_dump_xml_args; - memset (&lv_remote_domain_dump_xml_args, 0, sizeof lv_remote_domain_dump_xml_args); - ret_filter = (xdrproc_t) xdr_remote_domain_dump_xml_ret; - ret = (char *) &lv_remote_domain_dump_xml_ret; - memset (&lv_remote_domain_dump_xml_ret, 0, sizeof lv_remote_domain_dump_xml_ret); - break; -case REMOTE_PROC_DOMAIN_EVENT: - fn = (dispatch_fn) remoteDispatchDomainEvent; - ret_filter = (xdrproc_t) xdr_remote_domain_event_ret; - ret = (char *) &lv_remote_domain_event_ret; - memset (&lv_remote_domain_event_ret, 0, sizeof lv_remote_domain_event_ret); - break; -case REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER: - fn = (dispatch_fn) remoteDispatchDomainEventsDeregister; - ret_filter = (xdrproc_t) xdr_remote_domain_events_deregister_ret; - ret = (char *) &lv_remote_domain_events_deregister_ret; - memset (&lv_remote_domain_events_deregister_ret, 0, sizeof lv_remote_domain_events_deregister_ret); - break; -case REMOTE_PROC_DOMAIN_EVENTS_REGISTER: - fn = (dispatch_fn) remoteDispatchDomainEventsRegister; - ret_filter = (xdrproc_t) xdr_remote_domain_events_register_ret; - ret = (char *) &lv_remote_domain_events_register_ret; - memset (&lv_remote_domain_events_register_ret, 0, sizeof lv_remote_domain_events_register_ret); - break; -case REMOTE_PROC_DOMAIN_GET_AUTOSTART: - fn = (dispatch_fn) remoteDispatchDomainGetAutostart; - args_filter = (xdrproc_t) xdr_remote_domain_get_autostart_args; - args = (char *) &lv_remote_domain_get_autostart_args; - memset (&lv_remote_domain_get_autostart_args, 0, sizeof lv_remote_domain_get_autostart_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_autostart_ret; - ret = (char *) &lv_remote_domain_get_autostart_ret; - memset (&lv_remote_domain_get_autostart_ret, 0, sizeof lv_remote_domain_get_autostart_ret); - break; -case REMOTE_PROC_DOMAIN_GET_INFO: - fn = (dispatch_fn) remoteDispatchDomainGetInfo; - args_filter = (xdrproc_t) xdr_remote_domain_get_info_args; - args = (char *) &lv_remote_domain_get_info_args; - memset (&lv_remote_domain_get_info_args, 0, sizeof lv_remote_domain_get_info_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_info_ret; - ret = (char *) &lv_remote_domain_get_info_ret; - memset (&lv_remote_domain_get_info_ret, 0, sizeof lv_remote_domain_get_info_ret); - break; -case REMOTE_PROC_DOMAIN_GET_MAX_MEMORY: - fn = (dispatch_fn) remoteDispatchDomainGetMaxMemory; - args_filter = (xdrproc_t) xdr_remote_domain_get_max_memory_args; - args = (char *) &lv_remote_domain_get_max_memory_args; - memset (&lv_remote_domain_get_max_memory_args, 0, sizeof lv_remote_domain_get_max_memory_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_max_memory_ret; - ret = (char *) &lv_remote_domain_get_max_memory_ret; - memset (&lv_remote_domain_get_max_memory_ret, 0, sizeof lv_remote_domain_get_max_memory_ret); - break; -case REMOTE_PROC_DOMAIN_GET_MAX_VCPUS: - fn = (dispatch_fn) remoteDispatchDomainGetMaxVcpus; - args_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_args; - args = (char *) &lv_remote_domain_get_max_vcpus_args; - memset (&lv_remote_domain_get_max_vcpus_args, 0, sizeof lv_remote_domain_get_max_vcpus_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret; - ret = (char *) &lv_remote_domain_get_max_vcpus_ret; - memset (&lv_remote_domain_get_max_vcpus_ret, 0, sizeof lv_remote_domain_get_max_vcpus_ret); - break; -case REMOTE_PROC_DOMAIN_GET_OS_TYPE: - fn = (dispatch_fn) remoteDispatchDomainGetOsType; - args_filter = (xdrproc_t) xdr_remote_domain_get_os_type_args; - args = (char *) &lv_remote_domain_get_os_type_args; - memset (&lv_remote_domain_get_os_type_args, 0, sizeof lv_remote_domain_get_os_type_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_os_type_ret; - ret = (char *) &lv_remote_domain_get_os_type_ret; - memset (&lv_remote_domain_get_os_type_ret, 0, sizeof lv_remote_domain_get_os_type_ret); - break; -case REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS: - fn = (dispatch_fn) remoteDispatchDomainGetSchedulerParameters; - args_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_args; - args = (char *) &lv_remote_domain_get_scheduler_parameters_args; - memset (&lv_remote_domain_get_scheduler_parameters_args, 0, sizeof lv_remote_domain_get_scheduler_parameters_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret; - ret = (char *) &lv_remote_domain_get_scheduler_parameters_ret; - memset (&lv_remote_domain_get_scheduler_parameters_ret, 0, sizeof lv_remote_domain_get_scheduler_parameters_ret); - break; -case REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE: - fn = (dispatch_fn) remoteDispatchDomainGetSchedulerType; - args_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_type_args; - args = (char *) &lv_remote_domain_get_scheduler_type_args; - memset (&lv_remote_domain_get_scheduler_type_args, 0, sizeof lv_remote_domain_get_scheduler_type_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret; - ret = (char *) &lv_remote_domain_get_scheduler_type_ret; - memset (&lv_remote_domain_get_scheduler_type_ret, 0, sizeof lv_remote_domain_get_scheduler_type_ret); - break; -case REMOTE_PROC_DOMAIN_GET_VCPUS: - fn = (dispatch_fn) remoteDispatchDomainGetVcpus; - args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_args; - args = (char *) &lv_remote_domain_get_vcpus_args; - memset (&lv_remote_domain_get_vcpus_args, 0, sizeof lv_remote_domain_get_vcpus_args); - ret_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_ret; - ret = (char *) &lv_remote_domain_get_vcpus_ret; - memset (&lv_remote_domain_get_vcpus_ret, 0, sizeof lv_remote_domain_get_vcpus_ret); - break; -case REMOTE_PROC_DOMAIN_INTERFACE_STATS: - fn = (dispatch_fn) remoteDispatchDomainInterfaceStats; - args_filter = (xdrproc_t) xdr_remote_domain_interface_stats_args; - args = (char *) &lv_remote_domain_interface_stats_args; - memset (&lv_remote_domain_interface_stats_args, 0, sizeof lv_remote_domain_interface_stats_args); - ret_filter = (xdrproc_t) xdr_remote_domain_interface_stats_ret; - ret = (char *) &lv_remote_domain_interface_stats_ret; - memset (&lv_remote_domain_interface_stats_ret, 0, sizeof lv_remote_domain_interface_stats_ret); - break; -case REMOTE_PROC_DOMAIN_LOOKUP_BY_ID: - fn = (dispatch_fn) remoteDispatchDomainLookupById; - args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_args; - args = (char *) &lv_remote_domain_lookup_by_id_args; - memset (&lv_remote_domain_lookup_by_id_args, 0, sizeof lv_remote_domain_lookup_by_id_args); - ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_ret; - ret = (char *) &lv_remote_domain_lookup_by_id_ret; - memset (&lv_remote_domain_lookup_by_id_ret, 0, sizeof lv_remote_domain_lookup_by_id_ret); - break; -case REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME: - fn = (dispatch_fn) remoteDispatchDomainLookupByName; - args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_args; - args = (char *) &lv_remote_domain_lookup_by_name_args; - memset (&lv_remote_domain_lookup_by_name_args, 0, sizeof lv_remote_domain_lookup_by_name_args); - ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_ret; - ret = (char *) &lv_remote_domain_lookup_by_name_ret; - memset (&lv_remote_domain_lookup_by_name_ret, 0, sizeof lv_remote_domain_lookup_by_name_ret); - break; -case REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID: - fn = (dispatch_fn) remoteDispatchDomainLookupByUuid; - args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args; - args = (char *) &lv_remote_domain_lookup_by_uuid_args; - memset (&lv_remote_domain_lookup_by_uuid_args, 0, sizeof lv_remote_domain_lookup_by_uuid_args); - ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret; - ret = (char *) &lv_remote_domain_lookup_by_uuid_ret; - memset (&lv_remote_domain_lookup_by_uuid_ret, 0, sizeof lv_remote_domain_lookup_by_uuid_ret); - break; -case REMOTE_PROC_DOMAIN_MEMORY_PEEK: - fn = (dispatch_fn) remoteDispatchDomainMemoryPeek; - args_filter = (xdrproc_t) xdr_remote_domain_memory_peek_args; - args = (char *) &lv_remote_domain_memory_peek_args; - memset (&lv_remote_domain_memory_peek_args, 0, sizeof lv_remote_domain_memory_peek_args); - ret_filter = (xdrproc_t) xdr_remote_domain_memory_peek_ret; - ret = (char *) &lv_remote_domain_memory_peek_ret; - memset (&lv_remote_domain_memory_peek_ret, 0, sizeof lv_remote_domain_memory_peek_ret); - break; -case REMOTE_PROC_DOMAIN_MIGRATE_FINISH: - fn = (dispatch_fn) remoteDispatchDomainMigrateFinish; - args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish_args; - args = (char *) &lv_remote_domain_migrate_finish_args; - memset (&lv_remote_domain_migrate_finish_args, 0, sizeof lv_remote_domain_migrate_finish_args); - ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish_ret; - ret = (char *) &lv_remote_domain_migrate_finish_ret; - memset (&lv_remote_domain_migrate_finish_ret, 0, sizeof lv_remote_domain_migrate_finish_ret); - break; -case REMOTE_PROC_DOMAIN_MIGRATE_FINISH2: - fn = (dispatch_fn) remoteDispatchDomainMigrateFinish2; - args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_args; - args = (char *) &lv_remote_domain_migrate_finish2_args; - memset (&lv_remote_domain_migrate_finish2_args, 0, sizeof lv_remote_domain_migrate_finish2_args); - ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_ret; - ret = (char *) &lv_remote_domain_migrate_finish2_ret; - memset (&lv_remote_domain_migrate_finish2_ret, 0, sizeof lv_remote_domain_migrate_finish2_ret); - break; -case REMOTE_PROC_DOMAIN_MIGRATE_PERFORM: - fn = (dispatch_fn) remoteDispatchDomainMigratePerform; - args_filter = (xdrproc_t) xdr_remote_domain_migrate_perform_args; - args = (char *) &lv_remote_domain_migrate_perform_args; - memset (&lv_remote_domain_migrate_perform_args, 0, sizeof lv_remote_domain_migrate_perform_args); - break; -case REMOTE_PROC_DOMAIN_MIGRATE_PREPARE: - fn = (dispatch_fn) remoteDispatchDomainMigratePrepare; - args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_args; - args = (char *) &lv_remote_domain_migrate_prepare_args; - memset (&lv_remote_domain_migrate_prepare_args, 0, sizeof lv_remote_domain_migrate_prepare_args); - ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_ret; - ret = (char *) &lv_remote_domain_migrate_prepare_ret; - memset (&lv_remote_domain_migrate_prepare_ret, 0, sizeof lv_remote_domain_migrate_prepare_ret); - break; -case REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2: - fn = (dispatch_fn) remoteDispatchDomainMigratePrepare2; - args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare2_args; - args = (char *) &lv_remote_domain_migrate_prepare2_args; - memset (&lv_remote_domain_migrate_prepare2_args, 0, sizeof lv_remote_domain_migrate_prepare2_args); - ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret; - ret = (char *) &lv_remote_domain_migrate_prepare2_ret; - memset (&lv_remote_domain_migrate_prepare2_ret, 0, sizeof lv_remote_domain_migrate_prepare2_ret); - break; -case REMOTE_PROC_DOMAIN_PIN_VCPU: - fn = (dispatch_fn) remoteDispatchDomainPinVcpu; - args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_args; - args = (char *) &lv_remote_domain_pin_vcpu_args; - memset (&lv_remote_domain_pin_vcpu_args, 0, sizeof lv_remote_domain_pin_vcpu_args); - break; -case REMOTE_PROC_DOMAIN_REBOOT: - fn = (dispatch_fn) remoteDispatchDomainReboot; - args_filter = (xdrproc_t) xdr_remote_domain_reboot_args; - args = (char *) &lv_remote_domain_reboot_args; - memset (&lv_remote_domain_reboot_args, 0, sizeof lv_remote_domain_reboot_args); - break; -case REMOTE_PROC_DOMAIN_RESTORE: - fn = (dispatch_fn) remoteDispatchDomainRestore; - args_filter = (xdrproc_t) xdr_remote_domain_restore_args; - args = (char *) &lv_remote_domain_restore_args; - memset (&lv_remote_domain_restore_args, 0, sizeof lv_remote_domain_restore_args); - break; -case REMOTE_PROC_DOMAIN_RESUME: - fn = (dispatch_fn) remoteDispatchDomainResume; - args_filter = (xdrproc_t) xdr_remote_domain_resume_args; - args = (char *) &lv_remote_domain_resume_args; - memset (&lv_remote_domain_resume_args, 0, sizeof lv_remote_domain_resume_args); - break; -case REMOTE_PROC_DOMAIN_SAVE: - fn = (dispatch_fn) remoteDispatchDomainSave; - args_filter = (xdrproc_t) xdr_remote_domain_save_args; - args = (char *) &lv_remote_domain_save_args; - memset (&lv_remote_domain_save_args, 0, sizeof lv_remote_domain_save_args); - break; -case REMOTE_PROC_DOMAIN_SET_AUTOSTART: - fn = (dispatch_fn) remoteDispatchDomainSetAutostart; - args_filter = (xdrproc_t) xdr_remote_domain_set_autostart_args; - args = (char *) &lv_remote_domain_set_autostart_args; - memset (&lv_remote_domain_set_autostart_args, 0, sizeof lv_remote_domain_set_autostart_args); - break; -case REMOTE_PROC_DOMAIN_SET_MAX_MEMORY: - fn = (dispatch_fn) remoteDispatchDomainSetMaxMemory; - args_filter = (xdrproc_t) xdr_remote_domain_set_max_memory_args; - args = (char *) &lv_remote_domain_set_max_memory_args; - memset (&lv_remote_domain_set_max_memory_args, 0, sizeof lv_remote_domain_set_max_memory_args); - break; -case REMOTE_PROC_DOMAIN_SET_MEMORY: - fn = (dispatch_fn) remoteDispatchDomainSetMemory; - args_filter = (xdrproc_t) xdr_remote_domain_set_memory_args; - args = (char *) &lv_remote_domain_set_memory_args; - memset (&lv_remote_domain_set_memory_args, 0, sizeof lv_remote_domain_set_memory_args); - break; -case REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS: - fn = (dispatch_fn) remoteDispatchDomainSetSchedulerParameters; - args_filter = (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args; - args = (char *) &lv_remote_domain_set_scheduler_parameters_args; - memset (&lv_remote_domain_set_scheduler_parameters_args, 0, sizeof lv_remote_domain_set_scheduler_parameters_args); - break; -case REMOTE_PROC_DOMAIN_SET_VCPUS: - fn = (dispatch_fn) remoteDispatchDomainSetVcpus; - args_filter = (xdrproc_t) xdr_remote_domain_set_vcpus_args; - args = (char *) &lv_remote_domain_set_vcpus_args; - memset (&lv_remote_domain_set_vcpus_args, 0, sizeof lv_remote_domain_set_vcpus_args); - break; -case REMOTE_PROC_DOMAIN_SHUTDOWN: - fn = (dispatch_fn) remoteDispatchDomainShutdown; - args_filter = (xdrproc_t) xdr_remote_domain_shutdown_args; - args = (char *) &lv_remote_domain_shutdown_args; - memset (&lv_remote_domain_shutdown_args, 0, sizeof lv_remote_domain_shutdown_args); - break; -case REMOTE_PROC_DOMAIN_SUSPEND: - fn = (dispatch_fn) remoteDispatchDomainSuspend; - args_filter = (xdrproc_t) xdr_remote_domain_suspend_args; - args = (char *) &lv_remote_domain_suspend_args; - memset (&lv_remote_domain_suspend_args, 0, sizeof lv_remote_domain_suspend_args); - break; -case REMOTE_PROC_DOMAIN_UNDEFINE: - fn = (dispatch_fn) remoteDispatchDomainUndefine; - args_filter = (xdrproc_t) xdr_remote_domain_undefine_args; - args = (char *) &lv_remote_domain_undefine_args; - memset (&lv_remote_domain_undefine_args, 0, sizeof lv_remote_domain_undefine_args); - break; -case REMOTE_PROC_FIND_STORAGE_POOL_SOURCES: - fn = (dispatch_fn) remoteDispatchFindStoragePoolSources; - args_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_args; - args = (char *) &lv_remote_find_storage_pool_sources_args; - memset (&lv_remote_find_storage_pool_sources_args, 0, sizeof lv_remote_find_storage_pool_sources_args); - ret_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_ret; - ret = (char *) &lv_remote_find_storage_pool_sources_ret; - memset (&lv_remote_find_storage_pool_sources_ret, 0, sizeof lv_remote_find_storage_pool_sources_ret); - break; -case REMOTE_PROC_GET_CAPABILITIES: - fn = (dispatch_fn) remoteDispatchGetCapabilities; - ret_filter = (xdrproc_t) xdr_remote_get_capabilities_ret; - ret = (char *) &lv_remote_get_capabilities_ret; - memset (&lv_remote_get_capabilities_ret, 0, sizeof lv_remote_get_capabilities_ret); - break; -case REMOTE_PROC_GET_HOSTNAME: - fn = (dispatch_fn) remoteDispatchGetHostname; - ret_filter = (xdrproc_t) xdr_remote_get_hostname_ret; - ret = (char *) &lv_remote_get_hostname_ret; - memset (&lv_remote_get_hostname_ret, 0, sizeof lv_remote_get_hostname_ret); - break; -case REMOTE_PROC_GET_MAX_VCPUS: - fn = (dispatch_fn) remoteDispatchGetMaxVcpus; - args_filter = (xdrproc_t) xdr_remote_get_max_vcpus_args; - args = (char *) &lv_remote_get_max_vcpus_args; - memset (&lv_remote_get_max_vcpus_args, 0, sizeof lv_remote_get_max_vcpus_args); - ret_filter = (xdrproc_t) xdr_remote_get_max_vcpus_ret; - ret = (char *) &lv_remote_get_max_vcpus_ret; - memset (&lv_remote_get_max_vcpus_ret, 0, sizeof lv_remote_get_max_vcpus_ret); - break; -case REMOTE_PROC_GET_TYPE: - fn = (dispatch_fn) remoteDispatchGetType; - ret_filter = (xdrproc_t) xdr_remote_get_type_ret; - ret = (char *) &lv_remote_get_type_ret; - memset (&lv_remote_get_type_ret, 0, sizeof lv_remote_get_type_ret); - break; -case REMOTE_PROC_GET_URI: - fn = (dispatch_fn) remoteDispatchGetUri; - ret_filter = (xdrproc_t) xdr_remote_get_uri_ret; - ret = (char *) &lv_remote_get_uri_ret; - memset (&lv_remote_get_uri_ret, 0, sizeof lv_remote_get_uri_ret); - break; -case REMOTE_PROC_GET_VERSION: - fn = (dispatch_fn) remoteDispatchGetVersion; - ret_filter = (xdrproc_t) xdr_remote_get_version_ret; - ret = (char *) &lv_remote_get_version_ret; - memset (&lv_remote_get_version_ret, 0, sizeof lv_remote_get_version_ret); - break; -case REMOTE_PROC_LIST_DEFINED_DOMAINS: - fn = (dispatch_fn) remoteDispatchListDefinedDomains; - args_filter = (xdrproc_t) xdr_remote_list_defined_domains_args; - args = (char *) &lv_remote_list_defined_domains_args; - memset (&lv_remote_list_defined_domains_args, 0, sizeof lv_remote_list_defined_domains_args); - ret_filter = (xdrproc_t) xdr_remote_list_defined_domains_ret; - ret = (char *) &lv_remote_list_defined_domains_ret; - memset (&lv_remote_list_defined_domains_ret, 0, sizeof lv_remote_list_defined_domains_ret); - break; -case REMOTE_PROC_LIST_DEFINED_NETWORKS: - fn = (dispatch_fn) remoteDispatchListDefinedNetworks; - args_filter = (xdrproc_t) xdr_remote_list_defined_networks_args; - args = (char *) &lv_remote_list_defined_networks_args; - memset (&lv_remote_list_defined_networks_args, 0, sizeof lv_remote_list_defined_networks_args); - ret_filter = (xdrproc_t) xdr_remote_list_defined_networks_ret; - ret = (char *) &lv_remote_list_defined_networks_ret; - memset (&lv_remote_list_defined_networks_ret, 0, sizeof lv_remote_list_defined_networks_ret); - break; -case REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS: - fn = (dispatch_fn) remoteDispatchListDefinedStoragePools; - args_filter = (xdrproc_t) xdr_remote_list_defined_storage_pools_args; - args = (char *) &lv_remote_list_defined_storage_pools_args; - memset (&lv_remote_list_defined_storage_pools_args, 0, sizeof lv_remote_list_defined_storage_pools_args); - ret_filter = (xdrproc_t) xdr_remote_list_defined_storage_pools_ret; - ret = (char *) &lv_remote_list_defined_storage_pools_ret; - memset (&lv_remote_list_defined_storage_pools_ret, 0, sizeof lv_remote_list_defined_storage_pools_ret); - break; -case REMOTE_PROC_LIST_DOMAINS: - fn = (dispatch_fn) remoteDispatchListDomains; - args_filter = (xdrproc_t) xdr_remote_list_domains_args; - args = (char *) &lv_remote_list_domains_args; - memset (&lv_remote_list_domains_args, 0, sizeof lv_remote_list_domains_args); - ret_filter = (xdrproc_t) xdr_remote_list_domains_ret; - ret = (char *) &lv_remote_list_domains_ret; - memset (&lv_remote_list_domains_ret, 0, sizeof lv_remote_list_domains_ret); - break; -case REMOTE_PROC_LIST_NETWORKS: - fn = (dispatch_fn) remoteDispatchListNetworks; - args_filter = (xdrproc_t) xdr_remote_list_networks_args; - args = (char *) &lv_remote_list_networks_args; - memset (&lv_remote_list_networks_args, 0, sizeof lv_remote_list_networks_args); - ret_filter = (xdrproc_t) xdr_remote_list_networks_ret; - ret = (char *) &lv_remote_list_networks_ret; - memset (&lv_remote_list_networks_ret, 0, sizeof lv_remote_list_networks_ret); - break; -case REMOTE_PROC_LIST_STORAGE_POOLS: - fn = (dispatch_fn) remoteDispatchListStoragePools; - args_filter = (xdrproc_t) xdr_remote_list_storage_pools_args; - args = (char *) &lv_remote_list_storage_pools_args; - memset (&lv_remote_list_storage_pools_args, 0, sizeof lv_remote_list_storage_pools_args); - ret_filter = (xdrproc_t) xdr_remote_list_storage_pools_ret; - ret = (char *) &lv_remote_list_storage_pools_ret; - memset (&lv_remote_list_storage_pools_ret, 0, sizeof lv_remote_list_storage_pools_ret); - break; -case REMOTE_PROC_NETWORK_CREATE: - fn = (dispatch_fn) remoteDispatchNetworkCreate; - args_filter = (xdrproc_t) xdr_remote_network_create_args; - args = (char *) &lv_remote_network_create_args; - memset (&lv_remote_network_create_args, 0, sizeof lv_remote_network_create_args); - break; -case REMOTE_PROC_NETWORK_CREATE_XML: - fn = (dispatch_fn) remoteDispatchNetworkCreateXml; - args_filter = (xdrproc_t) xdr_remote_network_create_xml_args; - args = (char *) &lv_remote_network_create_xml_args; - memset (&lv_remote_network_create_xml_args, 0, sizeof lv_remote_network_create_xml_args); - ret_filter = (xdrproc_t) xdr_remote_network_create_xml_ret; - ret = (char *) &lv_remote_network_create_xml_ret; - memset (&lv_remote_network_create_xml_ret, 0, sizeof lv_remote_network_create_xml_ret); - break; -case REMOTE_PROC_NETWORK_DEFINE_XML: - fn = (dispatch_fn) remoteDispatchNetworkDefineXml; - args_filter = (xdrproc_t) xdr_remote_network_define_xml_args; - args = (char *) &lv_remote_network_define_xml_args; - memset (&lv_remote_network_define_xml_args, 0, sizeof lv_remote_network_define_xml_args); - ret_filter = (xdrproc_t) xdr_remote_network_define_xml_ret; - ret = (char *) &lv_remote_network_define_xml_ret; - memset (&lv_remote_network_define_xml_ret, 0, sizeof lv_remote_network_define_xml_ret); - break; -case REMOTE_PROC_NETWORK_DESTROY: - fn = (dispatch_fn) remoteDispatchNetworkDestroy; - args_filter = (xdrproc_t) xdr_remote_network_destroy_args; - args = (char *) &lv_remote_network_destroy_args; - memset (&lv_remote_network_destroy_args, 0, sizeof lv_remote_network_destroy_args); - break; -case REMOTE_PROC_NETWORK_DUMP_XML: - fn = (dispatch_fn) remoteDispatchNetworkDumpXml; - args_filter = (xdrproc_t) xdr_remote_network_dump_xml_args; - args = (char *) &lv_remote_network_dump_xml_args; - memset (&lv_remote_network_dump_xml_args, 0, sizeof lv_remote_network_dump_xml_args); - ret_filter = (xdrproc_t) xdr_remote_network_dump_xml_ret; - ret = (char *) &lv_remote_network_dump_xml_ret; - memset (&lv_remote_network_dump_xml_ret, 0, sizeof lv_remote_network_dump_xml_ret); - break; -case REMOTE_PROC_NETWORK_GET_AUTOSTART: - fn = (dispatch_fn) remoteDispatchNetworkGetAutostart; - args_filter = (xdrproc_t) xdr_remote_network_get_autostart_args; - args = (char *) &lv_remote_network_get_autostart_args; - memset (&lv_remote_network_get_autostart_args, 0, sizeof lv_remote_network_get_autostart_args); - ret_filter = (xdrproc_t) xdr_remote_network_get_autostart_ret; - ret = (char *) &lv_remote_network_get_autostart_ret; - memset (&lv_remote_network_get_autostart_ret, 0, sizeof lv_remote_network_get_autostart_ret); - break; -case REMOTE_PROC_NETWORK_GET_BRIDGE_NAME: - fn = (dispatch_fn) remoteDispatchNetworkGetBridgeName; - args_filter = (xdrproc_t) xdr_remote_network_get_bridge_name_args; - args = (char *) &lv_remote_network_get_bridge_name_args; - memset (&lv_remote_network_get_bridge_name_args, 0, sizeof lv_remote_network_get_bridge_name_args); - ret_filter = (xdrproc_t) xdr_remote_network_get_bridge_name_ret; - ret = (char *) &lv_remote_network_get_bridge_name_ret; - memset (&lv_remote_network_get_bridge_name_ret, 0, sizeof lv_remote_network_get_bridge_name_ret); - break; -case REMOTE_PROC_NETWORK_LOOKUP_BY_NAME: - fn = (dispatch_fn) remoteDispatchNetworkLookupByName; - args_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_args; - args = (char *) &lv_remote_network_lookup_by_name_args; - memset (&lv_remote_network_lookup_by_name_args, 0, sizeof lv_remote_network_lookup_by_name_args); - ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_ret; - ret = (char *) &lv_remote_network_lookup_by_name_ret; - memset (&lv_remote_network_lookup_by_name_ret, 0, sizeof lv_remote_network_lookup_by_name_ret); - break; -case REMOTE_PROC_NETWORK_LOOKUP_BY_UUID: - fn = (dispatch_fn) remoteDispatchNetworkLookupByUuid; - args_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_args; - args = (char *) &lv_remote_network_lookup_by_uuid_args; - memset (&lv_remote_network_lookup_by_uuid_args, 0, sizeof lv_remote_network_lookup_by_uuid_args); - ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret; - ret = (char *) &lv_remote_network_lookup_by_uuid_ret; - memset (&lv_remote_network_lookup_by_uuid_ret, 0, sizeof lv_remote_network_lookup_by_uuid_ret); - break; -case REMOTE_PROC_NETWORK_SET_AUTOSTART: - fn = (dispatch_fn) remoteDispatchNetworkSetAutostart; - args_filter = (xdrproc_t) xdr_remote_network_set_autostart_args; - args = (char *) &lv_remote_network_set_autostart_args; - memset (&lv_remote_network_set_autostart_args, 0, sizeof lv_remote_network_set_autostart_args); - break; -case REMOTE_PROC_NETWORK_UNDEFINE: - fn = (dispatch_fn) remoteDispatchNetworkUndefine; - args_filter = (xdrproc_t) xdr_remote_network_undefine_args; - args = (char *) &lv_remote_network_undefine_args; - memset (&lv_remote_network_undefine_args, 0, sizeof lv_remote_network_undefine_args); - break; -case REMOTE_PROC_NODE_DEVICE_DUMP_XML: - fn = (dispatch_fn) remoteDispatchNodeDeviceDumpXml; - args_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_args; - args = (char *) &lv_remote_node_device_dump_xml_args; - memset (&lv_remote_node_device_dump_xml_args, 0, sizeof lv_remote_node_device_dump_xml_args); - ret_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_ret; - ret = (char *) &lv_remote_node_device_dump_xml_ret; - memset (&lv_remote_node_device_dump_xml_ret, 0, sizeof lv_remote_node_device_dump_xml_ret); - break; -case REMOTE_PROC_NODE_DEVICE_GET_PARENT: - fn = (dispatch_fn) remoteDispatchNodeDeviceGetParent; - args_filter = (xdrproc_t) xdr_remote_node_device_get_parent_args; - args = (char *) &lv_remote_node_device_get_parent_args; - memset (&lv_remote_node_device_get_parent_args, 0, sizeof lv_remote_node_device_get_parent_args); - ret_filter = (xdrproc_t) xdr_remote_node_device_get_parent_ret; - ret = (char *) &lv_remote_node_device_get_parent_ret; - memset (&lv_remote_node_device_get_parent_ret, 0, sizeof lv_remote_node_device_get_parent_ret); - break; -case REMOTE_PROC_NODE_DEVICE_LIST_CAPS: - fn = (dispatch_fn) remoteDispatchNodeDeviceListCaps; - args_filter = (xdrproc_t) xdr_remote_node_device_list_caps_args; - args = (char *) &lv_remote_node_device_list_caps_args; - memset (&lv_remote_node_device_list_caps_args, 0, sizeof lv_remote_node_device_list_caps_args); - ret_filter = (xdrproc_t) xdr_remote_node_device_list_caps_ret; - ret = (char *) &lv_remote_node_device_list_caps_ret; - memset (&lv_remote_node_device_list_caps_ret, 0, sizeof lv_remote_node_device_list_caps_ret); - break; -case REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME: - fn = (dispatch_fn) remoteDispatchNodeDeviceLookupByName; - args_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_args; - args = (char *) &lv_remote_node_device_lookup_by_name_args; - memset (&lv_remote_node_device_lookup_by_name_args, 0, sizeof lv_remote_node_device_lookup_by_name_args); - ret_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret; - ret = (char *) &lv_remote_node_device_lookup_by_name_ret; - memset (&lv_remote_node_device_lookup_by_name_ret, 0, sizeof lv_remote_node_device_lookup_by_name_ret); - break; -case REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS: - fn = (dispatch_fn) remoteDispatchNodeDeviceNumOfCaps; - args_filter = (xdrproc_t) xdr_remote_node_device_num_of_caps_args; - args = (char *) &lv_remote_node_device_num_of_caps_args; - memset (&lv_remote_node_device_num_of_caps_args, 0, sizeof lv_remote_node_device_num_of_caps_args); - ret_filter = (xdrproc_t) xdr_remote_node_device_num_of_caps_ret; - ret = (char *) &lv_remote_node_device_num_of_caps_ret; - memset (&lv_remote_node_device_num_of_caps_ret, 0, sizeof lv_remote_node_device_num_of_caps_ret); - break; -case REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY: - fn = (dispatch_fn) remoteDispatchNodeGetCellsFreeMemory; - args_filter = (xdrproc_t) xdr_remote_node_get_cells_free_memory_args; - args = (char *) &lv_remote_node_get_cells_free_memory_args; - memset (&lv_remote_node_get_cells_free_memory_args, 0, sizeof lv_remote_node_get_cells_free_memory_args); - ret_filter = (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret; - ret = (char *) &lv_remote_node_get_cells_free_memory_ret; - memset (&lv_remote_node_get_cells_free_memory_ret, 0, sizeof lv_remote_node_get_cells_free_memory_ret); - break; -case REMOTE_PROC_NODE_GET_FREE_MEMORY: - fn = (dispatch_fn) remoteDispatchNodeGetFreeMemory; - ret_filter = (xdrproc_t) xdr_remote_node_get_free_memory_ret; - ret = (char *) &lv_remote_node_get_free_memory_ret; - memset (&lv_remote_node_get_free_memory_ret, 0, sizeof lv_remote_node_get_free_memory_ret); - break; -case REMOTE_PROC_NODE_GET_INFO: - fn = (dispatch_fn) remoteDispatchNodeGetInfo; - ret_filter = (xdrproc_t) xdr_remote_node_get_info_ret; - ret = (char *) &lv_remote_node_get_info_ret; - memset (&lv_remote_node_get_info_ret, 0, sizeof lv_remote_node_get_info_ret); - break; -case REMOTE_PROC_NODE_LIST_DEVICES: - fn = (dispatch_fn) remoteDispatchNodeListDevices; - args_filter = (xdrproc_t) xdr_remote_node_list_devices_args; - args = (char *) &lv_remote_node_list_devices_args; - memset (&lv_remote_node_list_devices_args, 0, sizeof lv_remote_node_list_devices_args); - ret_filter = (xdrproc_t) xdr_remote_node_list_devices_ret; - ret = (char *) &lv_remote_node_list_devices_ret; - memset (&lv_remote_node_list_devices_ret, 0, sizeof lv_remote_node_list_devices_ret); - break; -case REMOTE_PROC_NODE_NUM_OF_DEVICES: - fn = (dispatch_fn) remoteDispatchNodeNumOfDevices; - args_filter = (xdrproc_t) xdr_remote_node_num_of_devices_args; - args = (char *) &lv_remote_node_num_of_devices_args; - memset (&lv_remote_node_num_of_devices_args, 0, sizeof lv_remote_node_num_of_devices_args); - ret_filter = (xdrproc_t) xdr_remote_node_num_of_devices_ret; - ret = (char *) &lv_remote_node_num_of_devices_ret; - memset (&lv_remote_node_num_of_devices_ret, 0, sizeof lv_remote_node_num_of_devices_ret); - break; -case REMOTE_PROC_NUM_OF_DEFINED_DOMAINS: - fn = (dispatch_fn) remoteDispatchNumOfDefinedDomains; - ret_filter = (xdrproc_t) xdr_remote_num_of_defined_domains_ret; - ret = (char *) &lv_remote_num_of_defined_domains_ret; - memset (&lv_remote_num_of_defined_domains_ret, 0, sizeof lv_remote_num_of_defined_domains_ret); - break; -case REMOTE_PROC_NUM_OF_DEFINED_NETWORKS: - fn = (dispatch_fn) remoteDispatchNumOfDefinedNetworks; - ret_filter = (xdrproc_t) xdr_remote_num_of_defined_networks_ret; - ret = (char *) &lv_remote_num_of_defined_networks_ret; - memset (&lv_remote_num_of_defined_networks_ret, 0, sizeof lv_remote_num_of_defined_networks_ret); - break; -case REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS: - fn = (dispatch_fn) remoteDispatchNumOfDefinedStoragePools; - ret_filter = (xdrproc_t) xdr_remote_num_of_defined_storage_pools_ret; - ret = (char *) &lv_remote_num_of_defined_storage_pools_ret; - memset (&lv_remote_num_of_defined_storage_pools_ret, 0, sizeof lv_remote_num_of_defined_storage_pools_ret); - break; -case REMOTE_PROC_NUM_OF_DOMAINS: - fn = (dispatch_fn) remoteDispatchNumOfDomains; - ret_filter = (xdrproc_t) xdr_remote_num_of_domains_ret; - ret = (char *) &lv_remote_num_of_domains_ret; - memset (&lv_remote_num_of_domains_ret, 0, sizeof lv_remote_num_of_domains_ret); - break; -case REMOTE_PROC_NUM_OF_NETWORKS: - fn = (dispatch_fn) remoteDispatchNumOfNetworks; - ret_filter = (xdrproc_t) xdr_remote_num_of_networks_ret; - ret = (char *) &lv_remote_num_of_networks_ret; - memset (&lv_remote_num_of_networks_ret, 0, sizeof lv_remote_num_of_networks_ret); - break; -case REMOTE_PROC_NUM_OF_STORAGE_POOLS: - fn = (dispatch_fn) remoteDispatchNumOfStoragePools; - ret_filter = (xdrproc_t) xdr_remote_num_of_storage_pools_ret; - ret = (char *) &lv_remote_num_of_storage_pools_ret; - memset (&lv_remote_num_of_storage_pools_ret, 0, sizeof lv_remote_num_of_storage_pools_ret); - break; -case REMOTE_PROC_OPEN: - fn = (dispatch_fn) remoteDispatchOpen; - args_filter = (xdrproc_t) xdr_remote_open_args; - args = (char *) &lv_remote_open_args; - memset (&lv_remote_open_args, 0, sizeof lv_remote_open_args); - break; -case REMOTE_PROC_STORAGE_POOL_BUILD: - fn = (dispatch_fn) remoteDispatchStoragePoolBuild; - args_filter = (xdrproc_t) xdr_remote_storage_pool_build_args; - args = (char *) &lv_remote_storage_pool_build_args; - memset (&lv_remote_storage_pool_build_args, 0, sizeof lv_remote_storage_pool_build_args); - break; -case REMOTE_PROC_STORAGE_POOL_CREATE: - fn = (dispatch_fn) remoteDispatchStoragePoolCreate; - args_filter = (xdrproc_t) xdr_remote_storage_pool_create_args; - args = (char *) &lv_remote_storage_pool_create_args; - memset (&lv_remote_storage_pool_create_args, 0, sizeof lv_remote_storage_pool_create_args); - break; -case REMOTE_PROC_STORAGE_POOL_CREATE_XML: - fn = (dispatch_fn) remoteDispatchStoragePoolCreateXml; - args_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_args; - args = (char *) &lv_remote_storage_pool_create_xml_args; - memset (&lv_remote_storage_pool_create_xml_args, 0, sizeof lv_remote_storage_pool_create_xml_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_ret; - ret = (char *) &lv_remote_storage_pool_create_xml_ret; - memset (&lv_remote_storage_pool_create_xml_ret, 0, sizeof lv_remote_storage_pool_create_xml_ret); - break; -case REMOTE_PROC_STORAGE_POOL_DEFINE_XML: - fn = (dispatch_fn) remoteDispatchStoragePoolDefineXml; - args_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_args; - args = (char *) &lv_remote_storage_pool_define_xml_args; - memset (&lv_remote_storage_pool_define_xml_args, 0, sizeof lv_remote_storage_pool_define_xml_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_ret; - ret = (char *) &lv_remote_storage_pool_define_xml_ret; - memset (&lv_remote_storage_pool_define_xml_ret, 0, sizeof lv_remote_storage_pool_define_xml_ret); - break; -case REMOTE_PROC_STORAGE_POOL_DELETE: - fn = (dispatch_fn) remoteDispatchStoragePoolDelete; - args_filter = (xdrproc_t) xdr_remote_storage_pool_delete_args; - args = (char *) &lv_remote_storage_pool_delete_args; - memset (&lv_remote_storage_pool_delete_args, 0, sizeof lv_remote_storage_pool_delete_args); - break; -case REMOTE_PROC_STORAGE_POOL_DESTROY: - fn = (dispatch_fn) remoteDispatchStoragePoolDestroy; - args_filter = (xdrproc_t) xdr_remote_storage_pool_destroy_args; - args = (char *) &lv_remote_storage_pool_destroy_args; - memset (&lv_remote_storage_pool_destroy_args, 0, sizeof lv_remote_storage_pool_destroy_args); - break; -case REMOTE_PROC_STORAGE_POOL_DUMP_XML: - fn = (dispatch_fn) remoteDispatchStoragePoolDumpXml; - args_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_args; - args = (char *) &lv_remote_storage_pool_dump_xml_args; - memset (&lv_remote_storage_pool_dump_xml_args, 0, sizeof lv_remote_storage_pool_dump_xml_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret; - ret = (char *) &lv_remote_storage_pool_dump_xml_ret; - memset (&lv_remote_storage_pool_dump_xml_ret, 0, sizeof lv_remote_storage_pool_dump_xml_ret); - break; -case REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART: - fn = (dispatch_fn) remoteDispatchStoragePoolGetAutostart; - args_filter = (xdrproc_t) xdr_remote_storage_pool_get_autostart_args; - args = (char *) &lv_remote_storage_pool_get_autostart_args; - memset (&lv_remote_storage_pool_get_autostart_args, 0, sizeof lv_remote_storage_pool_get_autostart_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_autostart_ret; - ret = (char *) &lv_remote_storage_pool_get_autostart_ret; - memset (&lv_remote_storage_pool_get_autostart_ret, 0, sizeof lv_remote_storage_pool_get_autostart_ret); - break; -case REMOTE_PROC_STORAGE_POOL_GET_INFO: - fn = (dispatch_fn) remoteDispatchStoragePoolGetInfo; - args_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_args; - args = (char *) &lv_remote_storage_pool_get_info_args; - memset (&lv_remote_storage_pool_get_info_args, 0, sizeof lv_remote_storage_pool_get_info_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_ret; - ret = (char *) &lv_remote_storage_pool_get_info_ret; - memset (&lv_remote_storage_pool_get_info_ret, 0, sizeof lv_remote_storage_pool_get_info_ret); - break; -case REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES: - fn = (dispatch_fn) remoteDispatchStoragePoolListVolumes; - args_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_args; - args = (char *) &lv_remote_storage_pool_list_volumes_args; - memset (&lv_remote_storage_pool_list_volumes_args, 0, sizeof lv_remote_storage_pool_list_volumes_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret; - ret = (char *) &lv_remote_storage_pool_list_volumes_ret; - memset (&lv_remote_storage_pool_list_volumes_ret, 0, sizeof lv_remote_storage_pool_list_volumes_ret); - break; -case REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME: - fn = (dispatch_fn) remoteDispatchStoragePoolLookupByName; - args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args; - args = (char *) &lv_remote_storage_pool_lookup_by_name_args; - memset (&lv_remote_storage_pool_lookup_by_name_args, 0, sizeof lv_remote_storage_pool_lookup_by_name_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret; - ret = (char *) &lv_remote_storage_pool_lookup_by_name_ret; - memset (&lv_remote_storage_pool_lookup_by_name_ret, 0, sizeof lv_remote_storage_pool_lookup_by_name_ret); - break; -case REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID: - fn = (dispatch_fn) remoteDispatchStoragePoolLookupByUuid; - args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args; - args = (char *) &lv_remote_storage_pool_lookup_by_uuid_args; - memset (&lv_remote_storage_pool_lookup_by_uuid_args, 0, sizeof lv_remote_storage_pool_lookup_by_uuid_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret; - ret = (char *) &lv_remote_storage_pool_lookup_by_uuid_ret; - memset (&lv_remote_storage_pool_lookup_by_uuid_ret, 0, sizeof lv_remote_storage_pool_lookup_by_uuid_ret); - break; -case REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME: - fn = (dispatch_fn) remoteDispatchStoragePoolLookupByVolume; - args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_args; - args = (char *) &lv_remote_storage_pool_lookup_by_volume_args; - memset (&lv_remote_storage_pool_lookup_by_volume_args, 0, sizeof lv_remote_storage_pool_lookup_by_volume_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_ret; - ret = (char *) &lv_remote_storage_pool_lookup_by_volume_ret; - memset (&lv_remote_storage_pool_lookup_by_volume_ret, 0, sizeof lv_remote_storage_pool_lookup_by_volume_ret); - break; -case REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES: - fn = (dispatch_fn) remoteDispatchStoragePoolNumOfVolumes; - args_filter = (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_args; - args = (char *) &lv_remote_storage_pool_num_of_volumes_args; - memset (&lv_remote_storage_pool_num_of_volumes_args, 0, sizeof lv_remote_storage_pool_num_of_volumes_args); - ret_filter = (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_ret; - ret = (char *) &lv_remote_storage_pool_num_of_volumes_ret; - memset (&lv_remote_storage_pool_num_of_volumes_ret, 0, sizeof lv_remote_storage_pool_num_of_volumes_ret); - break; -case REMOTE_PROC_STORAGE_POOL_REFRESH: - fn = (dispatch_fn) remoteDispatchStoragePoolRefresh; - args_filter = (xdrproc_t) xdr_remote_storage_pool_refresh_args; - args = (char *) &lv_remote_storage_pool_refresh_args; - memset (&lv_remote_storage_pool_refresh_args, 0, sizeof lv_remote_storage_pool_refresh_args); - break; -case REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART: - fn = (dispatch_fn) remoteDispatchStoragePoolSetAutostart; - args_filter = (xdrproc_t) xdr_remote_storage_pool_set_autostart_args; - args = (char *) &lv_remote_storage_pool_set_autostart_args; - memset (&lv_remote_storage_pool_set_autostart_args, 0, sizeof lv_remote_storage_pool_set_autostart_args); - break; -case REMOTE_PROC_STORAGE_POOL_UNDEFINE: - fn = (dispatch_fn) remoteDispatchStoragePoolUndefine; - args_filter = (xdrproc_t) xdr_remote_storage_pool_undefine_args; - args = (char *) &lv_remote_storage_pool_undefine_args; - memset (&lv_remote_storage_pool_undefine_args, 0, sizeof lv_remote_storage_pool_undefine_args); - break; -case REMOTE_PROC_STORAGE_VOL_CREATE_XML: - fn = (dispatch_fn) remoteDispatchStorageVolCreateXml; - args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_args; - args = (char *) &lv_remote_storage_vol_create_xml_args; - memset (&lv_remote_storage_vol_create_xml_args, 0, sizeof lv_remote_storage_vol_create_xml_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_ret; - ret = (char *) &lv_remote_storage_vol_create_xml_ret; - memset (&lv_remote_storage_vol_create_xml_ret, 0, sizeof lv_remote_storage_vol_create_xml_ret); - break; -case REMOTE_PROC_STORAGE_VOL_DELETE: - fn = (dispatch_fn) remoteDispatchStorageVolDelete; - args_filter = (xdrproc_t) xdr_remote_storage_vol_delete_args; - args = (char *) &lv_remote_storage_vol_delete_args; - memset (&lv_remote_storage_vol_delete_args, 0, sizeof lv_remote_storage_vol_delete_args); - break; -case REMOTE_PROC_STORAGE_VOL_DUMP_XML: - fn = (dispatch_fn) remoteDispatchStorageVolDumpXml; - args_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_args; - args = (char *) &lv_remote_storage_vol_dump_xml_args; - memset (&lv_remote_storage_vol_dump_xml_args, 0, sizeof lv_remote_storage_vol_dump_xml_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret; - ret = (char *) &lv_remote_storage_vol_dump_xml_ret; - memset (&lv_remote_storage_vol_dump_xml_ret, 0, sizeof lv_remote_storage_vol_dump_xml_ret); - break; -case REMOTE_PROC_STORAGE_VOL_GET_INFO: - fn = (dispatch_fn) remoteDispatchStorageVolGetInfo; - args_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_args; - args = (char *) &lv_remote_storage_vol_get_info_args; - memset (&lv_remote_storage_vol_get_info_args, 0, sizeof lv_remote_storage_vol_get_info_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_ret; - ret = (char *) &lv_remote_storage_vol_get_info_ret; - memset (&lv_remote_storage_vol_get_info_ret, 0, sizeof lv_remote_storage_vol_get_info_ret); - break; -case REMOTE_PROC_STORAGE_VOL_GET_PATH: - fn = (dispatch_fn) remoteDispatchStorageVolGetPath; - args_filter = (xdrproc_t) xdr_remote_storage_vol_get_path_args; - args = (char *) &lv_remote_storage_vol_get_path_args; - memset (&lv_remote_storage_vol_get_path_args, 0, sizeof lv_remote_storage_vol_get_path_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_path_ret; - ret = (char *) &lv_remote_storage_vol_get_path_ret; - memset (&lv_remote_storage_vol_get_path_ret, 0, sizeof lv_remote_storage_vol_get_path_ret); - break; -case REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY: - fn = (dispatch_fn) remoteDispatchStorageVolLookupByKey; - args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_args; - args = (char *) &lv_remote_storage_vol_lookup_by_key_args; - memset (&lv_remote_storage_vol_lookup_by_key_args, 0, sizeof lv_remote_storage_vol_lookup_by_key_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_ret; - ret = (char *) &lv_remote_storage_vol_lookup_by_key_ret; - memset (&lv_remote_storage_vol_lookup_by_key_ret, 0, sizeof lv_remote_storage_vol_lookup_by_key_ret); - break; -case REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME: - fn = (dispatch_fn) remoteDispatchStorageVolLookupByName; - args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_args; - args = (char *) &lv_remote_storage_vol_lookup_by_name_args; - memset (&lv_remote_storage_vol_lookup_by_name_args, 0, sizeof lv_remote_storage_vol_lookup_by_name_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_ret; - ret = (char *) &lv_remote_storage_vol_lookup_by_name_ret; - memset (&lv_remote_storage_vol_lookup_by_name_ret, 0, sizeof lv_remote_storage_vol_lookup_by_name_ret); - break; -case REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH: - fn = (dispatch_fn) remoteDispatchStorageVolLookupByPath; - args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_args; - args = (char *) &lv_remote_storage_vol_lookup_by_path_args; - memset (&lv_remote_storage_vol_lookup_by_path_args, 0, sizeof lv_remote_storage_vol_lookup_by_path_args); - ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_ret; - ret = (char *) &lv_remote_storage_vol_lookup_by_path_ret; - memset (&lv_remote_storage_vol_lookup_by_path_ret, 0, sizeof lv_remote_storage_vol_lookup_by_path_ret); - break; -case REMOTE_PROC_SUPPORTS_FEATURE: - fn = (dispatch_fn) remoteDispatchSupportsFeature; - args_filter = (xdrproc_t) xdr_remote_supports_feature_args; - args = (char *) &lv_remote_supports_feature_args; - memset (&lv_remote_supports_feature_args, 0, sizeof lv_remote_supports_feature_args); - ret_filter = (xdrproc_t) xdr_remote_supports_feature_ret; - ret = (char *) &lv_remote_supports_feature_ret; - memset (&lv_remote_supports_feature_ret, 0, sizeof lv_remote_supports_feature_ret); - break; diff --git a/qemud/remote_dispatch_ret.h b/qemud/remote_dispatch_ret.h new file mode 100644 --- /dev/null +++ b/qemud/remote_dispatch_ret.h @@ -0,0 +1,88 @@ +/* Automatically generated by remote_generate_stubs.pl. + * Do not edit this file. Any changes you make will be lost. + */ + + remote_get_type_ret val_remote_get_type_ret; + remote_get_version_ret val_remote_get_version_ret; + remote_get_max_vcpus_ret val_remote_get_max_vcpus_ret; + remote_node_get_info_ret val_remote_node_get_info_ret; + remote_get_capabilities_ret val_remote_get_capabilities_ret; + remote_domain_create_xml_ret val_remote_domain_create_xml_ret; + remote_domain_define_xml_ret val_remote_domain_define_xml_ret; + remote_domain_dump_xml_ret val_remote_domain_dump_xml_ret; + remote_domain_get_autostart_ret val_remote_domain_get_autostart_ret; + remote_domain_get_info_ret val_remote_domain_get_info_ret; + remote_domain_get_max_memory_ret val_remote_domain_get_max_memory_ret; + remote_domain_get_max_vcpus_ret val_remote_domain_get_max_vcpus_ret; + remote_domain_get_os_type_ret val_remote_domain_get_os_type_ret; + remote_domain_get_vcpus_ret val_remote_domain_get_vcpus_ret; + remote_list_defined_domains_ret val_remote_list_defined_domains_ret; + remote_domain_lookup_by_id_ret val_remote_domain_lookup_by_id_ret; + remote_domain_lookup_by_name_ret val_remote_domain_lookup_by_name_ret; + remote_domain_lookup_by_uuid_ret val_remote_domain_lookup_by_uuid_ret; + remote_num_of_defined_domains_ret val_remote_num_of_defined_domains_ret; + remote_list_defined_networks_ret val_remote_list_defined_networks_ret; + remote_list_domains_ret val_remote_list_domains_ret; + remote_list_networks_ret val_remote_list_networks_ret; + remote_network_create_xml_ret val_remote_network_create_xml_ret; + remote_network_define_xml_ret val_remote_network_define_xml_ret; + remote_network_dump_xml_ret val_remote_network_dump_xml_ret; + remote_network_get_autostart_ret val_remote_network_get_autostart_ret; + remote_network_get_bridge_name_ret val_remote_network_get_bridge_name_ret; + remote_network_lookup_by_name_ret val_remote_network_lookup_by_name_ret; + remote_network_lookup_by_uuid_ret val_remote_network_lookup_by_uuid_ret; + remote_num_of_defined_networks_ret val_remote_num_of_defined_networks_ret; + remote_num_of_domains_ret val_remote_num_of_domains_ret; + remote_num_of_networks_ret val_remote_num_of_networks_ret; + remote_domain_get_scheduler_type_ret val_remote_domain_get_scheduler_type_ret; + remote_domain_get_scheduler_parameters_ret val_remote_domain_get_scheduler_parameters_ret; + remote_get_hostname_ret val_remote_get_hostname_ret; + remote_supports_feature_ret val_remote_supports_feature_ret; + remote_domain_migrate_prepare_ret val_remote_domain_migrate_prepare_ret; + remote_domain_migrate_finish_ret val_remote_domain_migrate_finish_ret; + remote_domain_block_stats_ret val_remote_domain_block_stats_ret; + remote_domain_interface_stats_ret val_remote_domain_interface_stats_ret; + remote_auth_list_ret val_remote_auth_list_ret; + remote_auth_sasl_init_ret val_remote_auth_sasl_init_ret; + remote_auth_sasl_start_ret val_remote_auth_sasl_start_ret; + remote_auth_sasl_step_ret val_remote_auth_sasl_step_ret; + remote_auth_polkit_ret val_remote_auth_polkit_ret; + remote_num_of_storage_pools_ret val_remote_num_of_storage_pools_ret; + remote_list_storage_pools_ret val_remote_list_storage_pools_ret; + remote_num_of_defined_storage_pools_ret val_remote_num_of_defined_storage_pools_ret; + remote_list_defined_storage_pools_ret val_remote_list_defined_storage_pools_ret; + remote_find_storage_pool_sources_ret val_remote_find_storage_pool_sources_ret; + remote_storage_pool_create_xml_ret val_remote_storage_pool_create_xml_ret; + remote_storage_pool_define_xml_ret val_remote_storage_pool_define_xml_ret; + remote_storage_pool_lookup_by_name_ret val_remote_storage_pool_lookup_by_name_ret; + remote_storage_pool_lookup_by_uuid_ret val_remote_storage_pool_lookup_by_uuid_ret; + remote_storage_pool_lookup_by_volume_ret val_remote_storage_pool_lookup_by_volume_ret; + remote_storage_pool_get_info_ret val_remote_storage_pool_get_info_ret; + remote_storage_pool_dump_xml_ret val_remote_storage_pool_dump_xml_ret; + remote_storage_pool_get_autostart_ret val_remote_storage_pool_get_autostart_ret; + remote_storage_pool_num_of_volumes_ret val_remote_storage_pool_num_of_volumes_ret; + remote_storage_pool_list_volumes_ret val_remote_storage_pool_list_volumes_ret; + remote_storage_vol_create_xml_ret val_remote_storage_vol_create_xml_ret; + remote_storage_vol_lookup_by_name_ret val_remote_storage_vol_lookup_by_name_ret; + remote_storage_vol_lookup_by_key_ret val_remote_storage_vol_lookup_by_key_ret; + remote_storage_vol_lookup_by_path_ret val_remote_storage_vol_lookup_by_path_ret; + remote_storage_vol_get_info_ret val_remote_storage_vol_get_info_ret; + remote_storage_vol_dump_xml_ret val_remote_storage_vol_dump_xml_ret; + remote_storage_vol_get_path_ret val_remote_storage_vol_get_path_ret; + remote_node_get_cells_free_memory_ret val_remote_node_get_cells_free_memory_ret; + remote_node_get_free_memory_ret val_remote_node_get_free_memory_ret; + remote_domain_block_peek_ret val_remote_domain_block_peek_ret; + remote_domain_memory_peek_ret val_remote_domain_memory_peek_ret; + remote_domain_events_register_ret val_remote_domain_events_register_ret; + remote_domain_events_deregister_ret val_remote_domain_events_deregister_ret; + remote_domain_event_ret val_remote_domain_event_ret; + remote_domain_migrate_prepare2_ret val_remote_domain_migrate_prepare2_ret; + remote_domain_migrate_finish2_ret val_remote_domain_migrate_finish2_ret; + remote_get_uri_ret val_remote_get_uri_ret; + remote_node_num_of_devices_ret val_remote_node_num_of_devices_ret; + remote_node_list_devices_ret val_remote_node_list_devices_ret; + remote_node_device_lookup_by_name_ret val_remote_node_device_lookup_by_name_ret; + remote_node_device_dump_xml_ret val_remote_node_device_dump_xml_ret; + remote_node_device_get_parent_ret val_remote_node_device_get_parent_ret; + remote_node_device_num_of_caps_ret val_remote_node_device_num_of_caps_ret; + remote_node_device_list_caps_ret val_remote_node_device_list_caps_ret; diff --git a/qemud/remote_dispatch_table.h b/qemud/remote_dispatch_table.h new file mode 100644 --- /dev/null +++ b/qemud/remote_dispatch_table.h @@ -0,0 +1,594 @@ +/* Automatically generated by remote_generate_stubs.pl. + * Do not edit this file. Any changes you make will be lost. + */ + +{ /* (unused) => 0 */ + .fn = NULL, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* Open => 1 */ + .fn = (dispatch_fn) remoteDispatchOpen, + .args_filter = (xdrproc_t) xdr_remote_open_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* Close => 2 */ + .fn = (dispatch_fn) remoteDispatchClose, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* GetType => 3 */ + .fn = (dispatch_fn) remoteDispatchGetType, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_get_type_ret, +}, +{ /* GetVersion => 4 */ + .fn = (dispatch_fn) remoteDispatchGetVersion, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_get_version_ret, +}, +{ /* GetMaxVcpus => 5 */ + .fn = (dispatch_fn) remoteDispatchGetMaxVcpus, + .args_filter = (xdrproc_t) xdr_remote_get_max_vcpus_args, + .ret_filter = (xdrproc_t) xdr_remote_get_max_vcpus_ret, +}, +{ /* NodeGetInfo => 6 */ + .fn = (dispatch_fn) remoteDispatchNodeGetInfo, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_node_get_info_ret, +}, +{ /* GetCapabilities => 7 */ + .fn = (dispatch_fn) remoteDispatchGetCapabilities, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_get_capabilities_ret, +}, +{ /* DomainAttachDevice => 8 */ + .fn = (dispatch_fn) remoteDispatchDomainAttachDevice, + .args_filter = (xdrproc_t) xdr_remote_domain_attach_device_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainCreate => 9 */ + .fn = (dispatch_fn) remoteDispatchDomainCreate, + .args_filter = (xdrproc_t) xdr_remote_domain_create_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainCreateXml => 10 */ + .fn = (dispatch_fn) remoteDispatchDomainCreateXml, + .args_filter = (xdrproc_t) xdr_remote_domain_create_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_create_xml_ret, +}, +{ /* DomainDefineXml => 11 */ + .fn = (dispatch_fn) remoteDispatchDomainDefineXml, + .args_filter = (xdrproc_t) xdr_remote_domain_define_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_define_xml_ret, +}, +{ /* DomainDestroy => 12 */ + .fn = (dispatch_fn) remoteDispatchDomainDestroy, + .args_filter = (xdrproc_t) xdr_remote_domain_destroy_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainDetachDevice => 13 */ + .fn = (dispatch_fn) remoteDispatchDomainDetachDevice, + .args_filter = (xdrproc_t) xdr_remote_domain_detach_device_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainDumpXml => 14 */ + .fn = (dispatch_fn) remoteDispatchDomainDumpXml, + .args_filter = (xdrproc_t) xdr_remote_domain_dump_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_dump_xml_ret, +}, +{ /* DomainGetAutostart => 15 */ + .fn = (dispatch_fn) remoteDispatchDomainGetAutostart, + .args_filter = (xdrproc_t) xdr_remote_domain_get_autostart_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_autostart_ret, +}, +{ /* DomainGetInfo => 16 */ + .fn = (dispatch_fn) remoteDispatchDomainGetInfo, + .args_filter = (xdrproc_t) xdr_remote_domain_get_info_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_info_ret, +}, +{ /* DomainGetMaxMemory => 17 */ + .fn = (dispatch_fn) remoteDispatchDomainGetMaxMemory, + .args_filter = (xdrproc_t) xdr_remote_domain_get_max_memory_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_max_memory_ret, +}, +{ /* DomainGetMaxVcpus => 18 */ + .fn = (dispatch_fn) remoteDispatchDomainGetMaxVcpus, + .args_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret, +}, +{ /* DomainGetOsType => 19 */ + .fn = (dispatch_fn) remoteDispatchDomainGetOsType, + .args_filter = (xdrproc_t) xdr_remote_domain_get_os_type_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_os_type_ret, +}, +{ /* DomainGetVcpus => 20 */ + .fn = (dispatch_fn) remoteDispatchDomainGetVcpus, + .args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_ret, +}, +{ /* ListDefinedDomains => 21 */ + .fn = (dispatch_fn) remoteDispatchListDefinedDomains, + .args_filter = (xdrproc_t) xdr_remote_list_defined_domains_args, + .ret_filter = (xdrproc_t) xdr_remote_list_defined_domains_ret, +}, +{ /* DomainLookupById => 22 */ + .fn = (dispatch_fn) remoteDispatchDomainLookupById, + .args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_id_ret, +}, +{ /* DomainLookupByName => 23 */ + .fn = (dispatch_fn) remoteDispatchDomainLookupByName, + .args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_name_ret, +}, +{ /* DomainLookupByUuid => 24 */ + .fn = (dispatch_fn) remoteDispatchDomainLookupByUuid, + .args_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, +}, +{ /* NumOfDefinedDomains => 25 */ + .fn = (dispatch_fn) remoteDispatchNumOfDefinedDomains, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_defined_domains_ret, +}, +{ /* DomainPinVcpu => 26 */ + .fn = (dispatch_fn) remoteDispatchDomainPinVcpu, + .args_filter = (xdrproc_t) xdr_remote_domain_pin_vcpu_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainReboot => 27 */ + .fn = (dispatch_fn) remoteDispatchDomainReboot, + .args_filter = (xdrproc_t) xdr_remote_domain_reboot_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainResume => 28 */ + .fn = (dispatch_fn) remoteDispatchDomainResume, + .args_filter = (xdrproc_t) xdr_remote_domain_resume_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSetAutostart => 29 */ + .fn = (dispatch_fn) remoteDispatchDomainSetAutostart, + .args_filter = (xdrproc_t) xdr_remote_domain_set_autostart_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSetMaxMemory => 30 */ + .fn = (dispatch_fn) remoteDispatchDomainSetMaxMemory, + .args_filter = (xdrproc_t) xdr_remote_domain_set_max_memory_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSetMemory => 31 */ + .fn = (dispatch_fn) remoteDispatchDomainSetMemory, + .args_filter = (xdrproc_t) xdr_remote_domain_set_memory_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSetVcpus => 32 */ + .fn = (dispatch_fn) remoteDispatchDomainSetVcpus, + .args_filter = (xdrproc_t) xdr_remote_domain_set_vcpus_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainShutdown => 33 */ + .fn = (dispatch_fn) remoteDispatchDomainShutdown, + .args_filter = (xdrproc_t) xdr_remote_domain_shutdown_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSuspend => 34 */ + .fn = (dispatch_fn) remoteDispatchDomainSuspend, + .args_filter = (xdrproc_t) xdr_remote_domain_suspend_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainUndefine => 35 */ + .fn = (dispatch_fn) remoteDispatchDomainUndefine, + .args_filter = (xdrproc_t) xdr_remote_domain_undefine_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* ListDefinedNetworks => 36 */ + .fn = (dispatch_fn) remoteDispatchListDefinedNetworks, + .args_filter = (xdrproc_t) xdr_remote_list_defined_networks_args, + .ret_filter = (xdrproc_t) xdr_remote_list_defined_networks_ret, +}, +{ /* ListDomains => 37 */ + .fn = (dispatch_fn) remoteDispatchListDomains, + .args_filter = (xdrproc_t) xdr_remote_list_domains_args, + .ret_filter = (xdrproc_t) xdr_remote_list_domains_ret, +}, +{ /* ListNetworks => 38 */ + .fn = (dispatch_fn) remoteDispatchListNetworks, + .args_filter = (xdrproc_t) xdr_remote_list_networks_args, + .ret_filter = (xdrproc_t) xdr_remote_list_networks_ret, +}, +{ /* NetworkCreate => 39 */ + .fn = (dispatch_fn) remoteDispatchNetworkCreate, + .args_filter = (xdrproc_t) xdr_remote_network_create_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* NetworkCreateXml => 40 */ + .fn = (dispatch_fn) remoteDispatchNetworkCreateXml, + .args_filter = (xdrproc_t) xdr_remote_network_create_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_network_create_xml_ret, +}, +{ /* NetworkDefineXml => 41 */ + .fn = (dispatch_fn) remoteDispatchNetworkDefineXml, + .args_filter = (xdrproc_t) xdr_remote_network_define_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_network_define_xml_ret, +}, +{ /* NetworkDestroy => 42 */ + .fn = (dispatch_fn) remoteDispatchNetworkDestroy, + .args_filter = (xdrproc_t) xdr_remote_network_destroy_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* NetworkDumpXml => 43 */ + .fn = (dispatch_fn) remoteDispatchNetworkDumpXml, + .args_filter = (xdrproc_t) xdr_remote_network_dump_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_network_dump_xml_ret, +}, +{ /* NetworkGetAutostart => 44 */ + .fn = (dispatch_fn) remoteDispatchNetworkGetAutostart, + .args_filter = (xdrproc_t) xdr_remote_network_get_autostart_args, + .ret_filter = (xdrproc_t) xdr_remote_network_get_autostart_ret, +}, +{ /* NetworkGetBridgeName => 45 */ + .fn = (dispatch_fn) remoteDispatchNetworkGetBridgeName, + .args_filter = (xdrproc_t) xdr_remote_network_get_bridge_name_args, + .ret_filter = (xdrproc_t) xdr_remote_network_get_bridge_name_ret, +}, +{ /* NetworkLookupByName => 46 */ + .fn = (dispatch_fn) remoteDispatchNetworkLookupByName, + .args_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_args, + .ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_name_ret, +}, +{ /* NetworkLookupByUuid => 47 */ + .fn = (dispatch_fn) remoteDispatchNetworkLookupByUuid, + .args_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_args, + .ret_filter = (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret, +}, +{ /* NetworkSetAutostart => 48 */ + .fn = (dispatch_fn) remoteDispatchNetworkSetAutostart, + .args_filter = (xdrproc_t) xdr_remote_network_set_autostart_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* NetworkUndefine => 49 */ + .fn = (dispatch_fn) remoteDispatchNetworkUndefine, + .args_filter = (xdrproc_t) xdr_remote_network_undefine_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* NumOfDefinedNetworks => 50 */ + .fn = (dispatch_fn) remoteDispatchNumOfDefinedNetworks, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_defined_networks_ret, +}, +{ /* NumOfDomains => 51 */ + .fn = (dispatch_fn) remoteDispatchNumOfDomains, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_domains_ret, +}, +{ /* NumOfNetworks => 52 */ + .fn = (dispatch_fn) remoteDispatchNumOfNetworks, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_networks_ret, +}, +{ /* DomainCoreDump => 53 */ + .fn = (dispatch_fn) remoteDispatchDomainCoreDump, + .args_filter = (xdrproc_t) xdr_remote_domain_core_dump_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainRestore => 54 */ + .fn = (dispatch_fn) remoteDispatchDomainRestore, + .args_filter = (xdrproc_t) xdr_remote_domain_restore_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainSave => 55 */ + .fn = (dispatch_fn) remoteDispatchDomainSave, + .args_filter = (xdrproc_t) xdr_remote_domain_save_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainGetSchedulerType => 56 */ + .fn = (dispatch_fn) remoteDispatchDomainGetSchedulerType, + .args_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_type_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret, +}, +{ /* DomainGetSchedulerParameters => 57 */ + .fn = (dispatch_fn) remoteDispatchDomainGetSchedulerParameters, + .args_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, +}, +{ /* DomainSetSchedulerParameters => 58 */ + .fn = (dispatch_fn) remoteDispatchDomainSetSchedulerParameters, + .args_filter = (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* GetHostname => 59 */ + .fn = (dispatch_fn) remoteDispatchGetHostname, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_get_hostname_ret, +}, +{ /* SupportsFeature => 60 */ + .fn = (dispatch_fn) remoteDispatchSupportsFeature, + .args_filter = (xdrproc_t) xdr_remote_supports_feature_args, + .ret_filter = (xdrproc_t) xdr_remote_supports_feature_ret, +}, +{ /* DomainMigratePrepare => 61 */ + .fn = (dispatch_fn) remoteDispatchDomainMigratePrepare, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare_ret, +}, +{ /* DomainMigratePerform => 62 */ + .fn = (dispatch_fn) remoteDispatchDomainMigratePerform, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_perform_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* DomainMigrateFinish => 63 */ + .fn = (dispatch_fn) remoteDispatchDomainMigrateFinish, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish_ret, +}, +{ /* DomainBlockStats => 64 */ + .fn = (dispatch_fn) remoteDispatchDomainBlockStats, + .args_filter = (xdrproc_t) xdr_remote_domain_block_stats_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_block_stats_ret, +}, +{ /* DomainInterfaceStats => 65 */ + .fn = (dispatch_fn) remoteDispatchDomainInterfaceStats, + .args_filter = (xdrproc_t) xdr_remote_domain_interface_stats_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_interface_stats_ret, +}, +{ /* AuthList => 66 */ + .fn = (dispatch_fn) remoteDispatchAuthList, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_auth_list_ret, +}, +{ /* AuthSaslInit => 67 */ + .fn = (dispatch_fn) remoteDispatchAuthSaslInit, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_auth_sasl_init_ret, +}, +{ /* AuthSaslStart => 68 */ + .fn = (dispatch_fn) remoteDispatchAuthSaslStart, + .args_filter = (xdrproc_t) xdr_remote_auth_sasl_start_args, + .ret_filter = (xdrproc_t) xdr_remote_auth_sasl_start_ret, +}, +{ /* AuthSaslStep => 69 */ + .fn = (dispatch_fn) remoteDispatchAuthSaslStep, + .args_filter = (xdrproc_t) xdr_remote_auth_sasl_step_args, + .ret_filter = (xdrproc_t) xdr_remote_auth_sasl_step_ret, +}, +{ /* AuthPolkit => 70 */ + .fn = (dispatch_fn) remoteDispatchAuthPolkit, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_auth_polkit_ret, +}, +{ /* NumOfStoragePools => 71 */ + .fn = (dispatch_fn) remoteDispatchNumOfStoragePools, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_storage_pools_ret, +}, +{ /* ListStoragePools => 72 */ + .fn = (dispatch_fn) remoteDispatchListStoragePools, + .args_filter = (xdrproc_t) xdr_remote_list_storage_pools_args, + .ret_filter = (xdrproc_t) xdr_remote_list_storage_pools_ret, +}, +{ /* NumOfDefinedStoragePools => 73 */ + .fn = (dispatch_fn) remoteDispatchNumOfDefinedStoragePools, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_defined_storage_pools_ret, +}, +{ /* ListDefinedStoragePools => 74 */ + .fn = (dispatch_fn) remoteDispatchListDefinedStoragePools, + .args_filter = (xdrproc_t) xdr_remote_list_defined_storage_pools_args, + .ret_filter = (xdrproc_t) xdr_remote_list_defined_storage_pools_ret, +}, +{ /* FindStoragePoolSources => 75 */ + .fn = (dispatch_fn) remoteDispatchFindStoragePoolSources, + .args_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_args, + .ret_filter = (xdrproc_t) xdr_remote_find_storage_pool_sources_ret, +}, +{ /* StoragePoolCreateXml => 76 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolCreateXml, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_create_xml_ret, +}, +{ /* StoragePoolDefineXml => 77 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolDefineXml, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_define_xml_ret, +}, +{ /* StoragePoolCreate => 78 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolCreate, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_create_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolBuild => 79 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolBuild, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_build_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolDestroy => 80 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolDestroy, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_destroy_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolDelete => 81 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolDelete, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_delete_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolUndefine => 82 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolUndefine, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_undefine_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolRefresh => 83 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolRefresh, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_refresh_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolLookupByName => 84 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolLookupByName, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret, +}, +{ /* StoragePoolLookupByUuid => 85 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolLookupByUuid, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret, +}, +{ /* StoragePoolLookupByVolume => 86 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolLookupByVolume, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_ret, +}, +{ /* StoragePoolGetInfo => 87 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolGetInfo, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_info_ret, +}, +{ /* StoragePoolDumpXml => 88 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolDumpXml, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret, +}, +{ /* StoragePoolGetAutostart => 89 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolGetAutostart, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_get_autostart_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_get_autostart_ret, +}, +{ /* StoragePoolSetAutostart => 90 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolSetAutostart, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_set_autostart_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StoragePoolNumOfVolumes => 91 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolNumOfVolumes, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_ret, +}, +{ /* StoragePoolListVolumes => 92 */ + .fn = (dispatch_fn) remoteDispatchStoragePoolListVolumes, + .args_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, +}, +{ /* StorageVolCreateXml => 93 */ + .fn = (dispatch_fn) remoteDispatchStorageVolCreateXml, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_ret, +}, +{ /* StorageVolDelete => 94 */ + .fn = (dispatch_fn) remoteDispatchStorageVolDelete, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_delete_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* StorageVolLookupByName => 95 */ + .fn = (dispatch_fn) remoteDispatchStorageVolLookupByName, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_ret, +}, +{ /* StorageVolLookupByKey => 96 */ + .fn = (dispatch_fn) remoteDispatchStorageVolLookupByKey, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_ret, +}, +{ /* StorageVolLookupByPath => 97 */ + .fn = (dispatch_fn) remoteDispatchStorageVolLookupByPath, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_ret, +}, +{ /* StorageVolGetInfo => 98 */ + .fn = (dispatch_fn) remoteDispatchStorageVolGetInfo, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_info_ret, +}, +{ /* StorageVolDumpXml => 99 */ + .fn = (dispatch_fn) remoteDispatchStorageVolDumpXml, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret, +}, +{ /* StorageVolGetPath => 100 */ + .fn = (dispatch_fn) remoteDispatchStorageVolGetPath, + .args_filter = (xdrproc_t) xdr_remote_storage_vol_get_path_args, + .ret_filter = (xdrproc_t) xdr_remote_storage_vol_get_path_ret, +}, +{ /* NodeGetCellsFreeMemory => 101 */ + .fn = (dispatch_fn) remoteDispatchNodeGetCellsFreeMemory, + .args_filter = (xdrproc_t) xdr_remote_node_get_cells_free_memory_args, + .ret_filter = (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, +}, +{ /* NodeGetFreeMemory => 102 */ + .fn = (dispatch_fn) remoteDispatchNodeGetFreeMemory, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_node_get_free_memory_ret, +}, +{ /* DomainBlockPeek => 103 */ + .fn = (dispatch_fn) remoteDispatchDomainBlockPeek, + .args_filter = (xdrproc_t) xdr_remote_domain_block_peek_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_block_peek_ret, +}, +{ /* DomainMemoryPeek => 104 */ + .fn = (dispatch_fn) remoteDispatchDomainMemoryPeek, + .args_filter = (xdrproc_t) xdr_remote_domain_memory_peek_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_memory_peek_ret, +}, +{ /* DomainEventsRegister => 105 */ + .fn = (dispatch_fn) remoteDispatchDomainEventsRegister, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_domain_events_register_ret, +}, +{ /* DomainEventsDeregister => 106 */ + .fn = (dispatch_fn) remoteDispatchDomainEventsDeregister, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_domain_events_deregister_ret, +}, +{ /* DomainEvent => 107 */ + .fn = (dispatch_fn) remoteDispatchDomainEvent, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_domain_event_ret, +}, +{ /* DomainMigratePrepare2 => 108 */ + .fn = (dispatch_fn) remoteDispatchDomainMigratePrepare2, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare2_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret, +}, +{ /* DomainMigrateFinish2 => 109 */ + .fn = (dispatch_fn) remoteDispatchDomainMigrateFinish2, + .args_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_args, + .ret_filter = (xdrproc_t) xdr_remote_domain_migrate_finish2_ret, +}, +{ /* GetUri => 110 */ + .fn = (dispatch_fn) remoteDispatchGetUri, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_get_uri_ret, +}, +{ /* NodeNumOfDevices => 111 */ + .fn = (dispatch_fn) remoteDispatchNodeNumOfDevices, + .args_filter = (xdrproc_t) xdr_remote_node_num_of_devices_args, + .ret_filter = (xdrproc_t) xdr_remote_node_num_of_devices_ret, +}, +{ /* NodeListDevices => 112 */ + .fn = (dispatch_fn) remoteDispatchNodeListDevices, + .args_filter = (xdrproc_t) xdr_remote_node_list_devices_args, + .ret_filter = (xdrproc_t) xdr_remote_node_list_devices_ret, +}, +{ /* NodeDeviceLookupByName => 113 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceLookupByName, + .args_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_args, + .ret_filter = (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, +}, +{ /* NodeDeviceDumpXml => 114 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceDumpXml, + .args_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_node_device_dump_xml_ret, +}, +{ /* NodeDeviceGetParent => 115 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceGetParent, + .args_filter = (xdrproc_t) xdr_remote_node_device_get_parent_args, + .ret_filter = (xdrproc_t) xdr_remote_node_device_get_parent_ret, +}, +{ /* NodeDeviceNumOfCaps => 116 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceNumOfCaps, + .args_filter = (xdrproc_t) xdr_remote_node_device_num_of_caps_args, + .ret_filter = (xdrproc_t) xdr_remote_node_device_num_of_caps_ret, +}, +{ /* NodeDeviceListCaps => 117 */ + .fn = (dispatch_fn) remoteDispatchNodeDeviceListCaps, + .args_filter = (xdrproc_t) xdr_remote_node_device_list_caps_args, + .ret_filter = (xdrproc_t) xdr_remote_node_device_list_caps_ret, +}, diff --git a/qemud/remote_generate_stubs.pl b/qemud/remote_generate_stubs.pl --- a/qemud/remote_generate_stubs.pl +++ b/qemud/remote_generate_stubs.pl @@ -12,8 +12,8 @@ use Getopt::Std; use Getopt::Std; # Command line options. -our ($opt_c, $opt_d, $opt_i, $opt_s, $opt_v, $opt_w); -getopts ('cdisvw'); +our ($opt_p, $opt_t, $opt_a, $opt_r, $opt_d); +getopts ('ptard'); # Convert name_of_call to NameOfCall. sub name_to_ProcName { @@ -25,7 +25,17 @@ sub name_to_ProcName { # Read the input file (usually remote_protocol.x) and form an # opinion about the name, args and return type of each RPC. -my ($name, $ProcName, %calls); +my ($name, $ProcName, $id, %calls, @calls); + +# REMOTE_PROC_CLOSE has no args or ret. +$calls{close} = { + name => "close", + ProcName => "Close", + UC_NAME => "CLOSE", + args => "void", + ret => "void", +}; + while (<>) { if (/^struct remote_(.*)_args/) { $name = $1; @@ -57,17 +67,14 @@ while (<>) { ret => "remote_${name}_ret" } } + } elsif (/^\s*REMOTE_PROC_(.*?)\s+=\s+(\d+),?$/) { + $name = lc $1; + $id = $2; + $ProcName = name_to_ProcName ($name); + + $calls[$id] = $calls{$name}; } } - -# REMOTE_PROC_CLOSE has no args or ret. -$calls{close} = { - name => "close", - ProcName => "Close", - UC_NAME => "CLOSE", - args => "void", - ret => "void", -}; #---------------------------------------------------------------------- # Output @@ -90,135 +97,59 @@ if ($opt_d) { } # Prototypes for dispatch functions ("remote_dispatch_prototypes.h"). -elsif ($opt_i) { +elsif ($opt_p) { my @keys = sort (keys %calls); foreach (@keys) { print "static int remoteDispatch$calls{$_}->{ProcName} (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, $calls{$_}->{args} *args, $calls{$_}->{ret} *ret);\n"; } } -# Local variables used inside remoteDispatchClientRequest -# ("remote_dispatch_localvars.h"). -elsif ($opt_v) { - my @values = values %calls; - foreach (@values) { - if ($_->{args} ne "void") { - print "$_->{args} lv_$_->{args};\n"; +# Union of all arg types +# ("remote_dispatch_args.h"). +elsif ($opt_a) { + for ($id = 0 ; $id <= $#calls ; $id++) { + if (defined $calls[$id] && + $calls[$id]->{args} ne "void") { + print " $calls[$id]->{args} val_$calls[$id]->{args};\n"; } - if ($_->{ret} ne "void") { - print "$_->{ret} lv_$_->{ret};\n"; + } +} + +# Union of all arg types +# ("remote_dispatch_ret.h"). +elsif ($opt_r) { + for ($id = 0 ; $id <= $#calls ; $id++) { + if (defined $calls[$id] && + $calls[$id]->{ret} ne "void") { + print " $calls[$id]->{ret} val_$calls[$id]->{ret};\n"; } } } # Inside the switch statement, prepare the 'fn', 'args_filter', etc -# ("remote_dispatch_proc_switch.h"). -elsif ($opt_w) { - my @keys = sort (keys %calls); - foreach (@keys) { - print "case REMOTE_PROC_$calls{$_}->{UC_NAME}:\n"; - print " fn = (dispatch_fn) remoteDispatch$calls{$_}->{ProcName};\n"; - if ($calls{$_}->{args} ne "void") { - print " args_filter = (xdrproc_t) xdr_$calls{$_}->{args};\n"; - print " args = (char *) &lv_$calls{$_}->{args};\n"; - print " memset (&lv_$calls{$_}->{args}, 0, sizeof lv_$calls{$_}->{args});\n" +# ("remote_dispatch_table.h"). +elsif ($opt_t) { + for ($id = 0 ; $id <= $#calls ; $id++) { + if (defined $calls[$id]) { + print "{ /* $calls[$id]->{ProcName} => $id */\n"; + print " .fn = (dispatch_fn) remoteDispatch$calls[$id]->{ProcName},\n"; + if ($calls[$id]->{args} ne "void") { + print " .args_filter = (xdrproc_t) xdr_$calls[$id]->{args},\n"; + } else { + print " .args_filter = (xdrproc_t) xdr_void,\n"; + } + if ($calls[$id]->{ret} ne "void") { + print " .ret_filter = (xdrproc_t) xdr_$calls[$id]->{ret},\n"; + } else { + print " .ret_filter = (xdrproc_t) xdr_void,\n"; + } + print "},\n"; + } else { + print "{ /* (unused) => $id */\n"; + print " .fn = NULL,\n"; + print " .args_filter = (xdrproc_t) xdr_void,\n"; + print " .ret_filter = (xdrproc_t) xdr_void,\n"; + print "},\n"; } - if ($calls{$_}->{ret} ne "void") { - print " ret_filter = (xdrproc_t) xdr_$calls{$_}->{ret};\n"; - print " ret = (char *) &lv_$calls{$_}->{ret};\n"; - print " memset (&lv_$calls{$_}->{ret}, 0, sizeof lv_$calls{$_}->{ret});\n" - } - print " break;\n"; } } - -# Generate client stubs - just used to generate the first -# version of the stubs in remote_internal.c. They need -# hand-hacking afterwards. -elsif ($opt_c) { - my @keys = sort (keys %calls); - - foreach (@keys) { - my $args = $calls{$_}->{args}; - my $argsvoid = $args eq "void"; - my $ret = $calls{$_}->{ret}; - my $retvoid = $ret eq "void"; - - print "static @@\n"; - print "remote$calls{$_}->{ProcName} (@@)\n"; - print "{\n"; - if (!$argsvoid) { - print " $args args;\n"; - } - if (!$retvoid) { - print " $ret ret;\n"; - } - print " GET_PRIVATE (conn, @@);\n"; - print "\n"; - if (!$argsvoid) { - print " @@\n"; - print "\n"; - } - if (!$retvoid) { - print " memset (&ret, 0, sizeof ret);\n"; - } - print " if (call (conn, priv, 0, REMOTE_PROC_$calls{$_}->{UC_NAME},\n"; - print " (xdrproc_t) xdr_$args, (char *) "; - if ($argsvoid) { - print "NULL"; - } else { - print "&args"; - } - print ",\n"; - print " (xdrproc_t) xdr_$ret, (char *) "; - if ($retvoid) { - print "NULL"; - } else { - print "&ret"; - } - print ") == -1)\n"; - print " return -1;\n"; - print "\n @@\n"; - print "}\n\n"; - } -} - -# Generate server stubs - just used to generate the first -# version of the stubs in remote.c. They need hand-hacking -# afterwards. -elsif ($opt_s) { - my @keys = sort (keys %calls); - - foreach (@keys) { - my $args = $calls{$_}->{args}; - my $argsvoid = $args eq "void"; - my $ret = $calls{$_}->{ret}; - my $retvoid = $ret eq "void"; - - print "static int\n"; - print "remoteDispatch$calls{$_}->{ProcName} (struct qemud_server *server,\n"; - print " struct qemud_client *client,\n"; - print " remote_message_header *req,\n"; - print " remote_get_max_vcpus_args *args,\n"; - print " remote_get_max_vcpus_ret *ret)\n"; - print "{\n"; - if (!$argsvoid || !$retvoid) { - print " @@\n"; - } - print " CHECK_CONN;\n"; - print "\n"; - if (!$argsvoid) { - print " @@\n"; - print "\n"; - } - print " @@ = vir$calls{$_}->{ProcName} (@@);\n"; - print " if (@@) return -1;\n"; - print "\n"; - if (!$retvoid) { - print " @@\n"; - print "\n"; - } - print " return 0;\n"; - print "}\n\n"; - } -} -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:13:00AM +0000, Daniel P. Berrange wrote:
This refactors the libvirtd RPC call dispatcher code to be driven off a table lookup, rather than a giant switch. This dramatically reduces the stack usage of this dispatcher and makes the code more efficient, since GCC wasn't optimizing away the switch into a table lookup.
There's not been any change since last time i posted this really.
+1 it's mostly unreadable anyway :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This replaces the linked list of 'struct qemud_client' instances with an array instead, allowing easy fine grained per-client locking qemud.c | 43 ++++++++++++++++++++++++------------------- qemud.h | 4 +--- 2 files changed, 25 insertions(+), 22 deletions(-) Daniel diff --git a/qemud/qemud.c b/qemud/qemud.c --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -1151,6 +1151,12 @@ static int qemudDispatchServer(struct qe return -1; } + if (VIR_REALLOC_N(server->clients, server->nclients+1) < 0) { + qemudLog(QEMUD_ERR, "%s", _("Out of memory allocating clients")); + close(fd); + return -1; + } + /* Disable Nagle. Unix sockets will ignore this. */ setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start, sizeof no_slow_start); @@ -1231,9 +1237,7 @@ static int qemudDispatchServer(struct qe } } - client->next = server->clients; - server->clients = client; - server->nclients++; + server->clients[server->nclients++] = client; return 0; @@ -1248,19 +1252,19 @@ static int qemudDispatchServer(struct qe static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud_client *client) { - struct qemud_client *tmp = server->clients; - struct qemud_client *prev = NULL; - while (tmp) { - if (tmp == client) { - if (prev == NULL) - server->clients = client->next; - else - prev->next = client->next; - server->nclients--; + int i, n = -1; + for (i = 0 ; i < server->nclients ; i++) { + if (server->clients[i] == client) { + n = i; break; } - prev = tmp; - tmp = tmp->next; + } + if (n != -1) { + if (n < (server->nclients-1)) + memmove(server->clients + n, + server->clients + n + 1, + server->nclients - (n + 1)); + server->nclients--; } virEventRemoveHandleImpl(client->watch); @@ -1629,13 +1633,14 @@ static void static void qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { struct qemud_server *server = (struct qemud_server *)opaque; - struct qemud_client *client = server->clients; + struct qemud_client *client = NULL; + int i; - while (client) { - if (client->watch == watch) + for (i = 0 ; i < server->nclients ; i++) { + if (server->clients[i]->watch == watch) { + client = server->clients[i]; break; - - client = client->next; + } } if (!client) diff --git a/qemud/qemud.h b/qemud/qemud.h --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -133,8 +133,6 @@ struct qemud_client { /* back-pointer to our server */ struct qemud_server *server; - - struct qemud_client *next; }; #define QEMUD_CLIENT_MAGIC 0x7788aaee @@ -155,7 +153,7 @@ struct qemud_server { int nsockets; struct qemud_socket *sockets; int nclients; - struct qemud_client *clients; + struct qemud_client **clients; int sigread; char logDir[PATH_MAX]; unsigned int shutdown : 1; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:14:04AM +0000, Daniel P. Berrange wrote:
This replaces the linked list of 'struct qemud_client' instances with an array instead, allowing easy fine grained per-client locking
+1 I'm still a bit afraid of those memmove scattered around the array code, and would prefer set of macros to add/remove from the array, reviewed once, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

The current RPC handler methods have two possible return codes, -1 and -2, both indicate that an error occurred, but one says that the error has been serialized onto the outgoing dispatch buffer already, the other says that the caller must do serialization. This unneccessarily complex and has a number of errors already, so this patch makes the RPC handler responsible for all error serialization. qemud/qemud.c | 12 qemud/qemud.h | 5 qemud/remote.c | 1710 +++++++++++++++++++------------------ qemud/remote_dispatch_prototypes.h | 234 ++--- qemud/remote_generate_stubs.pl | 2 src/domain_conf.c | 8 6 files changed, 1049 insertions(+), 922 deletions(-) Daniel diff --git a/qemud/qemud.c b/qemud/qemud.c --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -1396,13 +1396,12 @@ static int qemudClientRead(struct qemud_ static void qemudDispatchClientRead(struct qemud_server *server, struct qemud_client *client) { - + unsigned int len; /*qemudDebug ("qemudDispatchClientRead: mode = %d", client->mode);*/ switch (client->mode) { case QEMUD_MODE_RX_HEADER: { XDR x; - unsigned int len; if (qemudClientRead(server, client) < 0) return; /* Error, or blocking */ @@ -1453,7 +1452,14 @@ static void qemudDispatchClientRead(stru if (client->bufferOffset < client->bufferLength) return; /* Not read enough */ - remoteDispatchClientRequest (server, client); + if ((len = remoteDispatchClientRequest (server, client)) == 0) + qemudDispatchClientFailure(server, client); + + /* Set up the output buffer. */ + client->mode = QEMUD_MODE_TX_PACKET; + client->bufferLength = len; + client->bufferOffset = 0; + if (qemudRegisterClientEvent(server, client, 1) < 0) qemudDispatchClientFailure(server, client); diff --git a/qemud/qemud.h b/qemud/qemud.h --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -177,8 +177,9 @@ void qemudLog(int priority, const char * #define qemudDebug(fmt, ...) do {} while(0) #endif -void remoteDispatchClientRequest (struct qemud_server *server, - struct qemud_client *client); +unsigned int +remoteDispatchClientRequest (struct qemud_server *server, + struct qemud_client *client); void qemudDispatchClientWrite(struct qemud_server *server, struct qemud_client *client); diff --git a/qemud/remote.c b/qemud/remote.c --- a/qemud/remote.c +++ b/qemud/remote.c @@ -55,10 +55,9 @@ #define REMOTE_DEBUG(fmt,...) qemudDebug("REMOTE: " fmt, __VA_ARGS__) -static void remoteDispatchError (struct qemud_client *client, - remote_message_header *req, - const char *fmt, ...) - ATTRIBUTE_FORMAT(printf, 3, 4); +static void remoteDispatchFormatError (remote_error *rerr, + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 2, 3); static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain); static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network); static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool); @@ -82,7 +81,7 @@ typedef union { typedef int (*dispatch_fn) (struct qemud_server *server, struct qemud_client *client, - remote_message_header *req, + remote_error *err, dispatch_args *args, dispatch_ret *ret); @@ -103,59 +102,151 @@ remoteDispatchDomainEventSend (struct qe int event, int detail); + +/* Convert a libvirt virError object into wire format */ +static void +remoteDispatchCopyError (remote_error *rerr, + virErrorPtr verr) +{ + rerr->code = verr->code; + rerr->domain = verr->domain; + rerr->message = verr->message ? malloc(sizeof(char*)) : NULL; + if (rerr->message) *rerr->message = strdup(verr->message); + rerr->level = verr->level; + rerr->str1 = verr->str1 ? malloc(sizeof(char*)) : NULL; + if (rerr->str1) *rerr->str1 = strdup(verr->str1); + rerr->str2 = verr->str2 ? malloc(sizeof(char*)) : NULL; + if (rerr->str2) *rerr->str2 = strdup(verr->str2); + rerr->str3 = verr->str3 ? malloc(sizeof(char*)) : NULL; + if (rerr->str3) *rerr->str3 = strdup(verr->str3); + rerr->int1 = verr->int1; + rerr->int2 = verr->int2; +} + + +/* A set of helpers for sending back errors to client + in various ways .... */ + +static void +remoteDispatchStringError (remote_error *rerr, + int code, const char *msg) +{ + virError verr; + + memset(&verr, 0, sizeof verr); + + /* Construct the dummy libvirt virError. */ + verr.code = code; + verr.domain = VIR_FROM_REMOTE; + verr.message = (char *)msg; + verr.level = VIR_ERR_ERROR; + verr.str1 = (char *)msg; + + remoteDispatchCopyError(rerr, &verr); +} + +static void +remoteDispatchAuthError (remote_error *rerr) +{ + remoteDispatchStringError (rerr, VIR_ERR_AUTH_FAILED, "authentication failed"); +} + +static void +remoteDispatchFormatError (remote_error *rerr, + const char *fmt, ...) +{ + va_list args; + char msgbuf[1024]; + char *msg = msgbuf; + + va_start (args, fmt); + vsnprintf (msgbuf, sizeof msgbuf, fmt, args); + va_end (args); + + remoteDispatchStringError (rerr, VIR_ERR_RPC, msg); +} + +static void +remoteDispatchGenericError (remote_error *rerr) +{ + remoteDispatchStringError(rerr, + VIR_ERR_INTERNAL_ERROR, + "library function returned error but did not set virterror"); +} + +static void +remoteDispatchOOMError (remote_error *rerr) +{ + remoteDispatchStringError(rerr, + VIR_ERR_NO_MEMORY, + NULL); +} + +static void +remoteDispatchConnError (remote_error *rerr, + virConnectPtr conn) +{ + virErrorPtr verr; + + if (conn) + verr = virConnGetLastError(conn); + else + verr = virGetLastError(); + if (verr) + remoteDispatchCopyError(rerr, verr); + else + remoteDispatchGenericError(rerr); +} + + /* This function gets called from qemud when it detects an incoming * remote protocol message. At this point, client->buffer contains * the full call message (including length word which we skip). */ -void +unsigned int remoteDispatchClientRequest (struct qemud_server *server, struct qemud_client *client) { XDR xdr; remote_message_header req, rep; + remote_error rerr; dispatch_args args; dispatch_ret ret; const dispatch_data *data = NULL; - int rv, len; + int rv = -1, len; memset(&args, 0, sizeof args); memset(&ret, 0, sizeof ret); + memset(&rerr, 0, sizeof rerr); /* Parse the header. */ xdrmem_create (&xdr, client->buffer, client->bufferLength, XDR_DECODE); - if (!xdr_remote_message_header (&xdr, &req)) { - remoteDispatchError (client, NULL, "%s", _("xdr_remote_message_header")); - xdr_destroy (&xdr); - return; - } + if (!xdr_remote_message_header (&xdr, &req)) + goto fatal_error; /* Check version, etc. */ if (req.prog != REMOTE_PROGRAM) { - remoteDispatchError (client, &req, - _("program mismatch (actual %x, expected %x)"), - req.prog, REMOTE_PROGRAM); - xdr_destroy (&xdr); - return; + remoteDispatchFormatError (&rerr, + _("program mismatch (actual %x, expected %x)"), + req.prog, REMOTE_PROGRAM); + goto rpc_error; } if (req.vers != REMOTE_PROTOCOL_VERSION) { - remoteDispatchError (client, &req, - _("version mismatch (actual %x, expected %x)"), - req.vers, REMOTE_PROTOCOL_VERSION); - xdr_destroy (&xdr); - return; + remoteDispatchFormatError (&rerr, + _("version mismatch (actual %x, expected %x)"), + req.vers, REMOTE_PROTOCOL_VERSION); + goto rpc_error; } if (req.direction != REMOTE_CALL) { - remoteDispatchError (client, &req, _("direction (%d) != REMOTE_CALL"), - (int) req.direction); - xdr_destroy (&xdr); - return; + remoteDispatchFormatError (&rerr, _("direction (%d) != REMOTE_CALL"), + (int) req.direction); + goto rpc_error; } if (req.status != REMOTE_OK) { - remoteDispatchError (client, &req, _("status (%d) != REMOTE_OK"), - (int) req.status); - xdr_destroy (&xdr); - return; + remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"), + (int) req.status); + goto rpc_error; } /* If client is marked as needing auth, don't allow any RPC ops, @@ -168,47 +259,35 @@ remoteDispatchClientRequest (struct qemu req.proc != REMOTE_PROC_AUTH_SASL_STEP && req.proc != REMOTE_PROC_AUTH_POLKIT ) { - remoteDispatchError (client, &req, "%s", _("authentication required")); - xdr_destroy (&xdr); - return; + /* Explicitly *NOT* calling remoteDispatchAuthError() because + we want back-compatability with libvirt clients which don't + support the VIR_ERR_AUTH_FAILED error code */ + remoteDispatchFormatError (&rerr, "%s", _("authentication required")); + goto rpc_error; } } if (req.proc >= ARRAY_CARDINALITY(dispatch_table) || dispatch_table[req.proc].fn == NULL) { - remoteDispatchError (client, &req, _("unknown procedure: %d"), - req.proc); - xdr_destroy (&xdr); - return; + remoteDispatchFormatError (&rerr, _("unknown procedure: %d"), + req.proc); + goto rpc_error; } data = &(dispatch_table[req.proc]); /* De-serialize args off the wire */ if (!((data->args_filter)(&xdr, &args))) { - remoteDispatchError (client, &req, "%s", _("parse args failed")); - xdr_destroy (&xdr); - } - + remoteDispatchFormatError (&rerr, "%s", _("parse args failed")); + goto rpc_error; + } + + /* Call function. */ + rv = (data->fn)(server, client, &rerr, &args, &ret); + xdr_free (data->args_filter, (char*)&args); + +rpc_error: xdr_destroy (&xdr); - - /* Call function. */ - rv = (data->fn)(server, client, &req, &args, &ret); - xdr_free (data->args_filter, (char*)&args); - - /* Dispatch function must return -2, -1 or 0. Anything else is - * an internal error. - */ - if (rv < -2 || rv > 0) { - remoteDispatchError (client, &req, - _("internal error - dispatch function returned invalid code %d"), rv); - return; - } - - /* Dispatch error? If so then the function has already set up the - * return buffer, so just return immediately. - */ - if (rv == -2) return; /* Return header. */ rep.prog = req.prog; @@ -216,217 +295,51 @@ remoteDispatchClientRequest (struct qemu rep.proc = req.proc; rep.direction = REMOTE_REPLY; rep.serial = req.serial; - rep.status = rv == 0 ? REMOTE_OK : REMOTE_ERROR; + rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK; /* Serialise the return header. */ xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE); len = 0; /* We'll come back and write this later. */ if (!xdr_int (&xdr, &len)) { - remoteDispatchError (client, &req, "%s", _("dummy length")); - xdr_destroy (&xdr); if (rv == 0) xdr_free (data->ret_filter, (char*)&ret); - return; + goto fatal_error; } if (!xdr_remote_message_header (&xdr, &rep)) { - remoteDispatchError (client, &req, "%s", _("serialise reply header")); - xdr_destroy (&xdr); if (rv == 0) xdr_free (data->ret_filter, (char*)&ret); - return; + goto fatal_error; } /* If OK, serialise return structure, if error serialise error. */ - if (rv == 0) { - if (!((data->ret_filter) (&xdr, &ret))) { - remoteDispatchError (client, &req, "%s", _("serialise return struct")); - xdr_destroy (&xdr); - return; - } + if (rv >= 0) { + if (!((data->ret_filter) (&xdr, &ret))) + goto fatal_error; xdr_free (data->ret_filter, (char*)&ret); } else /* error */ { - virErrorPtr verr; - remote_error error; - remote_nonnull_domain dom; - remote_nonnull_network net; - - verr = client->conn - ? virConnGetLastError (client->conn) - : virGetLastError (); - - if (verr) { - error.code = verr->code; - error.domain = verr->domain; - error.message = verr->message ? &verr->message : NULL; - error.level = verr->level; - if (verr->dom) { - dom.name = verr->dom->name; - memcpy (dom.uuid, verr->dom->uuid, VIR_UUID_BUFLEN); - dom.id = verr->dom->id; - } - error.dom = verr->dom ? &dom : NULL; - error.str1 = verr->str1 ? &verr->str1 : NULL; - error.str2 = verr->str2 ? &verr->str2 : NULL; - error.str3 = verr->str3 ? &verr->str3 : NULL; - error.int1 = verr->int1; - error.int2 = verr->int2; - if (verr->net) { - net.name = verr->net->name; - memcpy (net.uuid, verr->net->uuid, VIR_UUID_BUFLEN); - } - error.net = verr->net ? &net : NULL; - } else { - /* Error was NULL so synthesize an error. */ - char msgbuf[] = "remoteDispatchClientRequest: internal error: library function returned error but did not set virterror"; - char *msg = msgbuf; - - error.code = VIR_ERR_RPC; - error.domain = VIR_FROM_REMOTE; - error.message = &msg; - error.level = VIR_ERR_ERROR; - error.dom = NULL; - error.str1 = &msg; - error.str2 = NULL; - error.str3 = NULL; - error.int1 = 0; - error.int2 = 0; - error.net = NULL; - } - - if (!xdr_remote_error (&xdr, &error)) { - remoteDispatchError (client, &req, "%s", _("serialise return error")); - xdr_destroy (&xdr); - return; - } + /* Error was NULL so synthesize an error. */ + if (rerr.code == 0) + remoteDispatchGenericError(&rerr); + if (!xdr_remote_error (&xdr, &rerr)) + goto fatal_error; } /* Write the length word. */ len = xdr_getpos (&xdr); - if (xdr_setpos (&xdr, 0) == 0) { - remoteDispatchError (client, &req, "%s", _("xdr_setpos")); - xdr_destroy (&xdr); - return; - } - - if (!xdr_int (&xdr, &len)) { - remoteDispatchError (client, &req, "%s", _("serialise return length")); - xdr_destroy (&xdr); - return; - } + if (xdr_setpos (&xdr, 0) == 0) + goto fatal_error; + + if (!xdr_int (&xdr, &len)) + goto fatal_error; xdr_destroy (&xdr); - - /* Set up the output buffer. */ - client->mode = QEMUD_MODE_TX_PACKET; - client->bufferLength = len; - client->bufferOffset = 0; -} - -/* An error occurred during the dispatching process itself (ie. not - * an error from the function being called). We return an error - * reply. - */ -static void -remoteDispatchSendError (struct qemud_client *client, - remote_message_header *req, - int code, const char *msg) -{ - remote_message_header rep; - remote_error error; - XDR xdr; - int len; - - /* Future versions of the protocol may use different vers or prog. Try - * our hardest to send back a message that such clients could see. - */ - if (req) { - rep.prog = req->prog; - rep.vers = req->vers; - rep.proc = req->proc; - rep.direction = REMOTE_REPLY; - rep.serial = req->serial; - rep.status = REMOTE_ERROR; - } else { - rep.prog = REMOTE_PROGRAM; - rep.vers = REMOTE_PROTOCOL_VERSION; - rep.proc = REMOTE_PROC_OPEN; - rep.direction = REMOTE_REPLY; - rep.serial = 1; - rep.status = REMOTE_ERROR; - } - - /* Construct the error. */ - error.code = code; - error.domain = VIR_FROM_REMOTE; - error.message = (char**)&msg; - error.level = VIR_ERR_ERROR; - error.dom = NULL; - error.str1 = (char**)&msg; - error.str2 = NULL; - error.str3 = NULL; - error.int1 = 0; - error.int2 = 0; - error.net = NULL; - - /* Serialise the return header and error. */ - xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE); - - len = 0; /* We'll come back and write this later. */ - if (!xdr_int (&xdr, &len)) { - xdr_destroy (&xdr); - return; - } - - if (!xdr_remote_message_header (&xdr, &rep)) { - xdr_destroy (&xdr); - return; - } - - if (!xdr_remote_error (&xdr, &error)) { - xdr_destroy (&xdr); - return; - } - - len = xdr_getpos (&xdr); - if (xdr_setpos (&xdr, 0) == 0) { - xdr_destroy (&xdr); - return; - } - - if (!xdr_int (&xdr, &len)) { - xdr_destroy (&xdr); - return; - } - + return len; + +fatal_error: + /* Seriously bad stuff happened, so we'll kill off this client + and not send back any RPC error */ xdr_destroy (&xdr); - - /* Send it. */ - client->mode = QEMUD_MODE_TX_PACKET; - client->bufferLength = len; - client->bufferOffset = 0; -} - -static void -remoteDispatchFailAuth (struct qemud_client *client, - remote_message_header *req) -{ - remoteDispatchSendError (client, req, VIR_ERR_AUTH_FAILED, "authentication failed"); -} - -static void -remoteDispatchError (struct qemud_client *client, - remote_message_header *req, - const char *fmt, ...) -{ - va_list args; - char msgbuf[1024]; - char *msg = msgbuf; - - va_start (args, fmt); - vsnprintf (msgbuf, sizeof msgbuf, fmt, args); - va_end (args); - - remoteDispatchSendError (client, req, VIR_ERR_RPC, msg); + return 0; } int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED, @@ -450,7 +363,8 @@ int remoteRelayDomainEvent (virConnectPt static int remoteDispatchOpen (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, remote_message_header *req, + struct qemud_client *client, + remote_error *rerr, struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED) { const char *name; @@ -458,8 +372,8 @@ remoteDispatchOpen (struct qemud_server /* Already opened? */ if (client->conn) { - remoteDispatchError (client, req, "%s", _("connection already open")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("connection already open")); + return -1; } name = args->name ? *args->name : NULL; @@ -475,60 +389,76 @@ remoteDispatchOpen (struct qemud_server ? virConnectOpenReadOnly (name) : virConnectOpen (name); - return client->conn ? 0 : -1; -} - -#define CHECK_CONN(client) \ - if (!client->conn) { \ - remoteDispatchError (client, req, "%s", _("connection not open")); \ - return -2; \ + if (client->conn == NULL) { + remoteDispatchConnError(rerr, NULL); + return -1; + } + + return 0; +} + +#define CHECK_CONN(client) \ + if (!client->conn) { \ + remoteDispatchFormatError (rerr, "%s", _("connection not open")); \ + return -1; \ } static int remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, remote_message_header *req, + struct qemud_client *client, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { - int rv; - CHECK_CONN(client); - - rv = virConnectClose (client->conn); - if (rv == 0) client->conn = NULL; - - return rv; + CHECK_CONN(client); + + if (virConnectClose (client->conn) < 0) { + remoteDispatchConnError(rerr, NULL); + return -1; + } + + return 0; } static int remoteDispatchSupportsFeature (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, remote_message_header *req, + struct qemud_client *client, + remote_error *rerr, remote_supports_feature_args *args, remote_supports_feature_ret *ret) { CHECK_CONN(client); ret->supported = virDrvSupportsFeature (client->conn, args->feature); - if (ret->supported == -1) return -1; + + if (ret->supported == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } static int remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, remote_message_header *req, + struct qemud_client *client, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret) { const char *type; CHECK_CONN(client); type = virConnectGetType (client->conn); - if (type == NULL) return -1; + if (type == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } /* We have to strdup because remoteDispatchClientRequest will * free this string after it's been serialised. */ ret->type = strdup (type); if (!ret->type) { - remoteDispatchError (client, req, "%s", _("out of memory in strdup")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("out of memory in strdup")); + return -1; } return 0; @@ -537,15 +467,17 @@ static int static int remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_version_ret *ret) { unsigned long hvVer; CHECK_CONN(client); - if (virConnectGetVersion (client->conn, &hvVer) == -1) - return -1; + if (virConnectGetVersion (client->conn, &hvVer) == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } ret->hv_ver = hvVer; return 0; @@ -554,7 +486,7 @@ static int static int remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_hostname_ret *ret) { @@ -562,7 +494,10 @@ remoteDispatchGetHostname (struct qemud_ CHECK_CONN(client); hostname = virConnectGetHostname (client->conn); - if (hostname == NULL) return -1; + if (hostname == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } ret->hostname = hostname; return 0; @@ -571,7 +506,7 @@ static int static int remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_uri_ret *ret) { @@ -579,7 +514,10 @@ remoteDispatchGetUri (struct qemud_serve CHECK_CONN(client); uri = virConnectGetURI (client->conn); - if (uri == NULL) return -1; + if (uri == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } ret->uri = uri; return 0; @@ -588,7 +526,7 @@ static int static int remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret) { @@ -597,7 +535,10 @@ remoteDispatchGetMaxVcpus (struct qemud_ type = args->type ? *args->type : NULL; ret->max_vcpus = virConnectGetMaxVcpus (client->conn, type); - if (ret->max_vcpus == -1) return -1; + if (ret->max_vcpus == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -605,15 +546,17 @@ static int static int remoteDispatchNodeGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_node_get_info_ret *ret) { virNodeInfo info; CHECK_CONN(client); - if (virNodeGetInfo (client->conn, &info) == -1) - return -1; + if (virNodeGetInfo (client->conn, &info) == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } memcpy (ret->model, info.model, sizeof ret->model); ret->memory = info.memory; @@ -630,7 +573,7 @@ static int static int remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_capabilities_ret *ret) { @@ -638,7 +581,10 @@ remoteDispatchGetCapabilities (struct qe CHECK_CONN(client); caps = virConnectGetCapabilities (client->conn); - if (caps == NULL) return -1; + if (caps == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } ret->capabilities = caps; return 0; @@ -647,22 +593,22 @@ static int static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret) { CHECK_CONN(client); if (args->maxCells > REMOTE_NODE_MAX_CELLS) { - remoteDispatchError (client, req, - "%s", _("maxCells > REMOTE_NODE_MAX_CELLS")); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxCells > REMOTE_NODE_MAX_CELLS")); + return -1; } /* Allocate return buffer. */ if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } ret->freeMems.freeMems_len = virNodeGetCellsFreeMemory(client->conn, @@ -671,6 +617,7 @@ remoteDispatchNodeGetCellsFreeMemory (st args->maxCells); if (ret->freeMems.freeMems_len == 0) { VIR_FREE(ret->freeMems.freeMems_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -681,7 +628,7 @@ static int static int remoteDispatchNodeGetFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_node_get_free_memory_ret *ret) { @@ -689,8 +636,10 @@ remoteDispatchNodeGetFreeMemory (struct CHECK_CONN(client); freeMem = virNodeGetFreeMemory(client->conn); - if (freeMem == 0) return -1; - + if (freeMem == 0) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } ret->freeMem = freeMem; return 0; } @@ -699,7 +648,7 @@ static int static int remoteDispatchDomainGetSchedulerType (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret) { @@ -710,13 +659,14 @@ remoteDispatchDomainGetSchedulerType (st dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } type = virDomainGetSchedulerType (dom, &nparams); if (type == NULL) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -729,7 +679,7 @@ static int static int remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret) { @@ -741,25 +691,26 @@ remoteDispatchDomainGetSchedulerParamete nparams = args->nparams; if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) { - remoteDispatchError (client, req, "%s", _("nparams too large")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("nparams too large")); + return -1; } if (VIR_ALLOC_N(params, nparams) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { VIR_FREE(params); - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } r = virDomainGetSchedulerParameters (dom, params, &nparams); if (r == -1) { virDomainFree(dom); VIR_FREE(params); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -789,7 +740,7 @@ remoteDispatchDomainGetSchedulerParamete case VIR_DOMAIN_SCHED_FIELD_BOOLEAN: ret->params.params_val[i].value.remote_sched_param_value_u.b = params[i].value.b; break; default: - remoteDispatchError (client, req, "%s", _("unknown type")); + remoteDispatchFormatError (rerr, "%s", _("unknown type")); goto cleanup; } } @@ -799,19 +750,19 @@ remoteDispatchDomainGetSchedulerParamete return 0; oom: - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); + remoteDispatchOOMError(rerr); cleanup: virDomainFree(dom); for (i = 0 ; i < nparams ; i++) VIR_FREE(ret->params.params_val[i].field); VIR_FREE(params); - return -2; + return -1; } static int remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_set_scheduler_parameters_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -823,12 +774,12 @@ remoteDispatchDomainSetSchedulerParamete nparams = args->params.params_len; if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) { - remoteDispatchError (client, req, "%s", _("nparams too large")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("nparams too large")); + return -1; } if (VIR_ALLOC_N(params, nparams)) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } /* Deserialise parameters. */ @@ -856,14 +807,17 @@ remoteDispatchDomainSetSchedulerParamete dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { VIR_FREE(params); - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } r = virDomainSetSchedulerParameters (dom, params, nparams); virDomainFree(dom); VIR_FREE(params); - if (r == -1) return -1; + if (r == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -871,7 +825,7 @@ static int static int remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret) { @@ -882,13 +836,14 @@ remoteDispatchDomainBlockStats (struct q dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } path = args->path; if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) { virDomainFree (dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree (dom); @@ -905,7 +860,7 @@ static int static int remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret) { @@ -916,13 +871,14 @@ remoteDispatchDomainInterfaceStats (stru dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } path = args->path; if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1) { virDomainFree (dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree (dom); @@ -942,7 +898,7 @@ static int static int remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret) { @@ -955,8 +911,8 @@ remoteDispatchDomainBlockPeek (struct qe dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } path = args->path; offset = args->offset; @@ -965,22 +921,23 @@ remoteDispatchDomainBlockPeek (struct qe if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) { virDomainFree (dom); - remoteDispatchError (client, req, - "%s", _("size > maximum buffer size")); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("size > maximum buffer size")); + return -1; } ret->buffer.buffer_len = size; if (VIR_ALLOC_N(ret->buffer.buffer_val, size) < 0) { virDomainFree (dom); - remoteDispatchError (client, req, "%s", strerror (errno)); - return -2; + remoteDispatchFormatError (rerr, "%s", strerror (errno)); + return -1; } if (virDomainBlockPeek (dom, path, offset, size, ret->buffer.buffer_val, flags) == -1) { /* free (ret->buffer.buffer_val); - caller frees */ virDomainFree (dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree (dom); @@ -991,7 +948,7 @@ static int static int remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_memory_peek_args *args, remote_domain_memory_peek_ret *ret) { @@ -1003,31 +960,32 @@ remoteDispatchDomainMemoryPeek (struct q dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } offset = args->offset; size = args->size; flags = args->flags; if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) { - remoteDispatchError (client, req, - "%s", _("size > maximum buffer size")); - virDomainFree (dom); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("size > maximum buffer size")); + virDomainFree (dom); + return -1; } ret->buffer.buffer_len = size; if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) { - remoteDispatchError (client, req, "%s", strerror (errno)); - virDomainFree (dom); - return -2; + remoteDispatchFormatError (rerr, "%s", strerror (errno)); + virDomainFree (dom); + return -1; } if (virDomainMemoryPeek (dom, offset, size, ret->buffer.buffer_val, flags) == -1) { /* free (ret->buffer.buffer_val); - caller frees */ virDomainFree (dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree (dom); @@ -1038,7 +996,7 @@ static int static int remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_attach_device_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1047,12 +1005,13 @@ remoteDispatchDomainAttachDevice (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainAttachDevice (dom, args->xml) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1062,7 +1021,7 @@ static int static int remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_create_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1071,12 +1030,13 @@ remoteDispatchDomainCreate (struct qemud dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainCreate (dom) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1086,7 +1046,7 @@ static int static int remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_create_xml_args *args, remote_domain_create_xml_ret *ret) { @@ -1094,7 +1054,10 @@ remoteDispatchDomainCreateXml (struct qe CHECK_CONN(client); dom = virDomainCreateXML (client->conn, args->xml_desc, args->flags); - if (dom == NULL) return -1; + if (dom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->dom, dom); virDomainFree(dom); @@ -1105,7 +1068,7 @@ static int static int remoteDispatchDomainDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_define_xml_args *args, remote_domain_define_xml_ret *ret) { @@ -1113,7 +1076,10 @@ remoteDispatchDomainDefineXml (struct qe CHECK_CONN(client); dom = virDomainDefineXML (client->conn, args->xml); - if (dom == NULL) return -1; + if (dom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->dom, dom); virDomainFree(dom); @@ -1124,7 +1090,7 @@ static int static int remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_destroy_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1133,12 +1099,13 @@ remoteDispatchDomainDestroy (struct qemu dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainDestroy (dom) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1148,7 +1115,7 @@ static int static int remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_detach_device_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1157,12 +1124,13 @@ remoteDispatchDomainDetachDevice (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainDetachDevice (dom, args->xml) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -1173,7 +1141,7 @@ static int static int remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_dump_xml_args *args, remote_domain_dump_xml_ret *ret) { @@ -1182,15 +1150,16 @@ remoteDispatchDomainDumpXml (struct qemu dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->xml = virDomainGetXMLDesc (dom, args->flags); if (!ret->xml) { - virDomainFree(dom); - return -1; + virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); + return -1; } virDomainFree(dom); return 0; @@ -1199,7 +1168,7 @@ static int static int remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_autostart_args *args, remote_domain_get_autostart_ret *ret) { @@ -1208,12 +1177,13 @@ remoteDispatchDomainGetAutostart (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainGetAutostart (dom, &ret->autostart) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1223,7 +1193,7 @@ static int static int remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_info_args *args, remote_domain_get_info_ret *ret) { @@ -1233,12 +1203,13 @@ remoteDispatchDomainGetInfo (struct qemu dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainGetInfo (dom, &info) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -1256,7 +1227,7 @@ static int static int remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_max_memory_args *args, remote_domain_get_max_memory_ret *ret) { @@ -1265,13 +1236,14 @@ remoteDispatchDomainGetMaxMemory (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } ret->memory = virDomainGetMaxMemory (dom); if (ret->memory == 0) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1281,7 +1253,7 @@ static int static int remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_max_vcpus_args *args, remote_domain_get_max_vcpus_ret *ret) { @@ -1290,13 +1262,14 @@ remoteDispatchDomainGetMaxVcpus (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } ret->num = virDomainGetMaxVcpus (dom); if (ret->num == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1306,7 +1279,7 @@ static int static int remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret) { @@ -1315,15 +1288,16 @@ remoteDispatchDomainGetOsType (struct qe dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this */ ret->type = virDomainGetOSType (dom); if (ret->type == NULL) { - virDomainFree(dom); - return -1; + virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); + return -1; } virDomainFree(dom); return 0; @@ -1332,7 +1306,7 @@ static int static int remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret) { @@ -1344,20 +1318,20 @@ remoteDispatchDomainGetVcpus (struct qem dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (args->maxinfo > REMOTE_VCPUINFO_MAX) { virDomainFree(dom); - remoteDispatchError (client, req, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX")); + return -1; } if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) { virDomainFree(dom); - remoteDispatchError (client, req, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX")); + return -1; } /* Allocate buffers to take the results. */ @@ -1373,6 +1347,7 @@ remoteDispatchDomainGetVcpus (struct qem VIR_FREE(info); VIR_FREE(cpumaps); virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -1403,14 +1378,14 @@ oom: VIR_FREE(info); VIR_FREE(cpumaps); virDomainFree(dom); - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } static int remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_migrate_prepare_args *args, remote_domain_migrate_prepare_ret *ret) { @@ -1427,8 +1402,8 @@ remoteDispatchDomainMigratePrepare (stru /* Wacky world of XDR ... */ if (VIR_ALLOC(uri_out) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } r = virDomainMigratePrepare (client->conn, &cookie, &cookielen, @@ -1436,6 +1411,7 @@ remoteDispatchDomainMigratePrepare (stru args->flags, dname, args->resource); if (r == -1) { VIR_FREE(uri_out); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -1457,7 +1433,7 @@ static int static int remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_migrate_perform_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1468,8 +1444,8 @@ remoteDispatchDomainMigratePerform (stru dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } dname = args->dname == NULL ? NULL : *args->dname; @@ -1480,7 +1456,10 @@ remoteDispatchDomainMigratePerform (stru args->uri, args->flags, dname, args->resource); virDomainFree (dom); - if (r == -1) return -1; + if (r == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -1488,7 +1467,7 @@ static int static int remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_migrate_finish_args *args, remote_domain_migrate_finish_ret *ret) { @@ -1500,7 +1479,10 @@ remoteDispatchDomainMigrateFinish (struc args->cookie.cookie_len, args->uri, args->flags); - if (ddom == NULL) return -1; + if (ddom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->ddom, ddom); virDomainFree (ddom); @@ -1510,7 +1492,7 @@ static int static int remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_migrate_prepare2_args *args, remote_domain_migrate_prepare2_ret *ret) { @@ -1527,15 +1509,18 @@ remoteDispatchDomainMigratePrepare2 (str /* Wacky world of XDR ... */ if (VIR_ALLOC(uri_out) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } r = virDomainMigratePrepare2 (client->conn, &cookie, &cookielen, uri_in, uri_out, args->flags, dname, args->resource, args->dom_xml); - if (r == -1) return -1; + if (r == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } /* remoteDispatchClientRequest will free cookie, uri_out and * the string if there is one. @@ -1550,7 +1535,7 @@ static int static int remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret) { @@ -1563,7 +1548,10 @@ remoteDispatchDomainMigrateFinish2 (stru args->uri, args->flags, args->retcode); - if (ddom == NULL) return -1; + if (ddom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->ddom, ddom); @@ -1573,22 +1561,22 @@ static int static int remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_list_defined_domains_args *args, remote_list_defined_domains_ret *ret) { CHECK_CONN(client); if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -1596,6 +1584,7 @@ remoteDispatchListDefinedDomains (struct ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -1605,7 +1594,7 @@ static int static int remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret) { @@ -1613,7 +1602,10 @@ remoteDispatchDomainLookupById (struct q CHECK_CONN(client); dom = virDomainLookupByID (client->conn, args->id); - if (dom == NULL) return -1; + if (dom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->dom, dom); virDomainFree(dom); @@ -1623,7 +1615,7 @@ static int static int remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret) { @@ -1631,7 +1623,10 @@ remoteDispatchDomainLookupByName (struct CHECK_CONN(client); dom = virDomainLookupByName (client->conn, args->name); - if (dom == NULL) return -1; + if (dom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->dom, dom); virDomainFree(dom); @@ -1641,7 +1636,7 @@ static int static int remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret) { @@ -1649,7 +1644,10 @@ remoteDispatchDomainLookupByUuid (struct CHECK_CONN(client); dom = virDomainLookupByUUID (client->conn, (unsigned char *) args->uuid); - if (dom == NULL) return -1; + if (dom == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_domain (&ret->dom, dom); virDomainFree(dom); @@ -1659,14 +1657,17 @@ static int static int remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_defined_domains_ret *ret) { CHECK_CONN(client); ret->num = virConnectNumOfDefinedDomains (client->conn); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -1674,7 +1675,7 @@ static int static int remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_pin_vcpu_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1684,14 +1685,14 @@ remoteDispatchDomainPinVcpu (struct qemu dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) { virDomainFree(dom); - remoteDispatchError (client, req, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX")); - return -2; + remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX")); + return -1; } rv = virDomainPinVcpu (dom, args->vcpu, @@ -1699,6 +1700,7 @@ remoteDispatchDomainPinVcpu (struct qemu args->cpumap.cpumap_len); if (rv == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1708,7 +1710,7 @@ static int static int remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_reboot_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1717,12 +1719,13 @@ remoteDispatchDomainReboot (struct qemud dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainReboot (dom, args->flags) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1732,14 +1735,16 @@ static int static int remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_restore_args *args, void *ret ATTRIBUTE_UNUSED) { CHECK_CONN(client); - if (virDomainRestore (client->conn, args->from) == -1) - return -1; + if (virDomainRestore (client->conn, args->from) == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -1747,7 +1752,7 @@ static int static int remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_resume_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1756,12 +1761,13 @@ remoteDispatchDomainResume (struct qemud dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainResume (dom) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1771,7 +1777,7 @@ static int static int remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_save_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1780,12 +1786,13 @@ remoteDispatchDomainSave (struct qemud_s dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainSave (dom, args->to) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1795,7 +1802,7 @@ static int static int remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_core_dump_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1804,12 +1811,13 @@ remoteDispatchDomainCoreDump (struct qem dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainCoreDump (dom, args->to, args->flags) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1819,7 +1827,7 @@ static int static int remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_set_autostart_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1828,12 +1836,13 @@ remoteDispatchDomainSetAutostart (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainSetAutostart (dom, args->autostart) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1843,7 +1852,7 @@ static int static int remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_set_max_memory_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1852,12 +1861,13 @@ remoteDispatchDomainSetMaxMemory (struct dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainSetMaxMemory (dom, args->memory) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1867,7 +1877,7 @@ static int static int remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_set_memory_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1876,12 +1886,13 @@ remoteDispatchDomainSetMemory (struct qe dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainSetMemory (dom, args->memory) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1891,7 +1902,7 @@ static int static int remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_set_vcpus_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1900,12 +1911,13 @@ remoteDispatchDomainSetVcpus (struct qem dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainSetVcpus (dom, args->nvcpus) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1915,7 +1927,7 @@ static int static int remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_shutdown_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1924,12 +1936,13 @@ remoteDispatchDomainShutdown (struct qem dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainShutdown (dom) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1939,7 +1952,7 @@ static int static int remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_suspend_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1948,12 +1961,13 @@ remoteDispatchDomainSuspend (struct qemu dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainSuspend (dom) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1963,7 +1977,7 @@ static int static int remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_domain_undefine_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -1972,12 +1986,13 @@ remoteDispatchDomainUndefine (struct qem dom = get_nonnull_domain (client->conn, args->dom); if (dom == NULL) { - remoteDispatchError (client, req, "%s", _("domain not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virDomainUndefine (dom) == -1) { virDomainFree(dom); + remoteDispatchConnError(rerr, client->conn); return -1; } virDomainFree(dom); @@ -1987,22 +2002,22 @@ static int static int remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_list_defined_networks_args *args, remote_list_defined_networks_ret *ret) { CHECK_CONN(client); if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -2010,6 +2025,7 @@ remoteDispatchListDefinedNetworks (struc ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -2019,28 +2035,29 @@ static int static int remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_list_domains_args *args, remote_list_domains_ret *ret) { CHECK_CONN(client); if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX")); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX")); + return -1; } /* Allocate return buffer. */ if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } ret->ids.ids_len = virConnectListDomains (client->conn, ret->ids.ids_val, args->maxids); if (ret->ids.ids_len == -1) { VIR_FREE(ret->ids.ids_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -2050,22 +2067,22 @@ static int static int remoteDispatchListNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_list_networks_args *args, remote_list_networks_ret *ret) { CHECK_CONN(client); if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -2073,6 +2090,7 @@ remoteDispatchListNetworks (struct qemud ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_len); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -2082,7 +2100,7 @@ static int static int remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_create_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -2091,12 +2109,13 @@ remoteDispatchNetworkCreate (struct qemu net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virNetworkCreate (net) == -1) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2106,7 +2125,7 @@ static int static int remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret) { @@ -2114,7 +2133,10 @@ remoteDispatchNetworkCreateXml (struct q CHECK_CONN(client); net = virNetworkCreateXML (client->conn, args->xml); - if (net == NULL) return -1; + if (net == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_network (&ret->net, net); virNetworkFree(net); @@ -2124,7 +2146,7 @@ static int static int remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_define_xml_args *args, remote_network_define_xml_ret *ret) { @@ -2132,7 +2154,10 @@ remoteDispatchNetworkDefineXml (struct q CHECK_CONN(client); net = virNetworkDefineXML (client->conn, args->xml); - if (net == NULL) return -1; + if (net == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_network (&ret->net, net); virNetworkFree(net); @@ -2142,7 +2167,7 @@ static int static int remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_destroy_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -2151,12 +2176,13 @@ remoteDispatchNetworkDestroy (struct qem net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virNetworkDestroy (net) == -1) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2166,7 +2192,7 @@ static int static int remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_dump_xml_args *args, remote_network_dump_xml_ret *ret) { @@ -2175,14 +2201,15 @@ remoteDispatchNetworkDumpXml (struct qem net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->xml = virNetworkGetXMLDesc (net, args->flags); if (!ret->xml) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2192,7 +2219,7 @@ static int static int remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_get_autostart_args *args, remote_network_get_autostart_ret *ret) { @@ -2201,12 +2228,13 @@ remoteDispatchNetworkGetAutostart (struc net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virNetworkGetAutostart (net, &ret->autostart) == -1) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2216,7 +2244,7 @@ static int static int remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_get_bridge_name_args *args, remote_network_get_bridge_name_ret *ret) { @@ -2225,14 +2253,15 @@ remoteDispatchNetworkGetBridgeName (stru net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->name = virNetworkGetBridgeName (net); if (!ret->name) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2242,7 +2271,7 @@ static int static int remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret) { @@ -2250,7 +2279,10 @@ remoteDispatchNetworkLookupByName (struc CHECK_CONN(client); net = virNetworkLookupByName (client->conn, args->name); - if (net == NULL) return -1; + if (net == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_network (&ret->net, net); virNetworkFree(net); @@ -2260,7 +2292,7 @@ static int static int remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_lookup_by_uuid_args *args, remote_network_lookup_by_uuid_ret *ret) { @@ -2268,7 +2300,10 @@ remoteDispatchNetworkLookupByUuid (struc CHECK_CONN(client); net = virNetworkLookupByUUID (client->conn, (unsigned char *) args->uuid); - if (net == NULL) return -1; + if (net == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_network (&ret->net, net); virNetworkFree(net); @@ -2278,7 +2313,7 @@ static int static int remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_set_autostart_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -2287,12 +2322,13 @@ remoteDispatchNetworkSetAutostart (struc net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virNetworkSetAutostart (net, args->autostart) == -1) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2302,7 +2338,7 @@ static int static int remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_network_undefine_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -2311,12 +2347,13 @@ remoteDispatchNetworkUndefine (struct qe net = get_nonnull_network (client->conn, args->net); if (net == NULL) { - remoteDispatchError (client, req, "%s", _("network not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virNetworkUndefine (net) == -1) { virNetworkFree(net); + remoteDispatchConnError(rerr, client->conn); return -1; } virNetworkFree(net); @@ -2326,14 +2363,17 @@ static int static int remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_defined_networks_ret *ret) { CHECK_CONN(client); ret->num = virConnectNumOfDefinedNetworks (client->conn); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -2341,14 +2381,17 @@ static int static int remoteDispatchNumOfDomains (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_domains_ret *ret) { CHECK_CONN(client); ret->num = virConnectNumOfDomains (client->conn); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -2356,14 +2399,17 @@ static int static int remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_networks_ret *ret) { CHECK_CONN(client); ret->num = virConnectNumOfNetworks (client->conn); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -2372,14 +2418,14 @@ static int static int remoteDispatchAuthList (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req ATTRIBUTE_UNUSED, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_list_ret *ret) { ret->types.types_len = 1; if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } ret->types.types_val[0] = client->auth; return 0; @@ -2390,8 +2436,7 @@ remoteDispatchAuthList (struct qemud_ser /* * NB, keep in sync with similar method in src/remote_internal.c */ -static char *addrToString(struct qemud_client *client, - remote_message_header *req, +static char *addrToString(remote_error *rerr, struct sockaddr_storage *sa, socklen_t salen) { char host[1024], port[20]; char *addr; @@ -2401,14 +2446,14 @@ static char *addrToString(struct qemud_c host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - remoteDispatchError(client, req, - _("Cannot resolve address %d: %s"), - err, gai_strerror(err)); + remoteDispatchFormatError(rerr, + _("Cannot resolve address %d: %s"), + err, gai_strerror(err)); return NULL; } if (VIR_ALLOC_N(addr, strlen(host) + 1 + strlen(port) + 1) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); + remoteDispatchOOMError(rerr); return NULL; } @@ -2428,7 +2473,7 @@ static int static int remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_sasl_init_ret *ret) { @@ -2443,33 +2488,33 @@ remoteDispatchAuthSaslInit (struct qemud if (client->auth != REMOTE_AUTH_SASL || client->saslconn != NULL) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid SASL init request")); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } /* Get local address in form IPADDR:PORT */ salen = sizeof(sa); if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) { - remoteDispatchError(client, req, - _("failed to get sock address %d (%s)"), - errno, strerror(errno)); - return -2; - } - if ((localAddr = addrToString(client, req, &sa, salen)) == NULL) { - return -2; + remoteDispatchFormatError(rerr, + _("failed to get sock address %d (%s)"), + errno, strerror(errno)); + return -1; + } + if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) { + return -1; } /* Get remote address in form IPADDR:PORT */ salen = sizeof(sa); if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) { - remoteDispatchError(client, req, _("failed to get peer address %d (%s)"), - errno, strerror(errno)); + remoteDispatchFormatError(rerr, _("failed to get peer address %d (%s)"), + errno, strerror(errno)); VIR_FREE(localAddr); - return -2; - } - if ((remoteAddr = addrToString(client, req, &sa, salen)) == NULL) { + return -1; + } + if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) { VIR_FREE(localAddr); - return -2; + return -1; } err = sasl_server_new("libvirt", @@ -2485,9 +2530,9 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("sasl context setup failed %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchFailAuth(client, req); - client->saslconn = NULL; - return -2; + remoteDispatchAuthError(rerr); + client->saslconn = NULL; + return -1; } /* Inform SASL that we've got an external SSF layer from TLS */ @@ -2498,10 +2543,10 @@ remoteDispatchAuthSaslInit (struct qemud cipher = gnutls_cipher_get(client->tlssession); if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) { qemudLog(QEMUD_ERR, "%s", _("cannot TLS get cipher size")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; - return -2; + return -1; } ssf *= 8; /* tls key size is bytes, sasl wants bits */ @@ -2509,10 +2554,10 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot set SASL external SSF %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; - return -2; + return -1; } } @@ -2538,10 +2583,10 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot set SASL security props %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchFailAuth(client, req); - sasl_dispose(&client->saslconn); - client->saslconn = NULL; - return -2; + remoteDispatchAuthError(rerr); + sasl_dispose(&client->saslconn); + client->saslconn = NULL; + return -1; } err = sasl_listmech(client->saslconn, @@ -2555,19 +2600,19 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot list SASL mechanisms %d (%s)"), err, sasl_errdetail(client->saslconn)); - remoteDispatchFailAuth(client, req); - sasl_dispose(&client->saslconn); - client->saslconn = NULL; - return -2; + remoteDispatchAuthError(rerr); + sasl_dispose(&client->saslconn); + client->saslconn = NULL; + return -1; } REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist); ret->mechlist = strdup(mechlist); if (!ret->mechlist) { qemudLog(QEMUD_ERR, "%s", _("cannot allocate mechlist")); - remoteDispatchFailAuth(client, req); - sasl_dispose(&client->saslconn); - client->saslconn = NULL; - return -2; + remoteDispatchAuthError(rerr); + sasl_dispose(&client->saslconn); + client->saslconn = NULL; + return -1; } return 0; @@ -2578,7 +2623,7 @@ remoteDispatchAuthSaslInit (struct qemud * got what we asked for */ static int remoteSASLCheckSSF (struct qemud_client *client, - remote_message_header *req) { + remote_error *rerr) { const void *val; int err, ssf; @@ -2590,7 +2635,7 @@ remoteSASLCheckSSF (struct qemud_client if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot query SASL ssf on connection %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; return -1; @@ -2599,7 +2644,7 @@ remoteSASLCheckSSF (struct qemud_client REMOTE_DEBUG("negotiated an SSF of %d", ssf); if (ssf < 56) { /* 56 is good for Kerberos */ qemudLog(QEMUD_ERR, _("negotiated SSF %d was not strong enough"), ssf); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; return -1; @@ -2620,7 +2665,7 @@ static int static int remoteSASLCheckAccess (struct qemud_server *server, struct qemud_client *client, - remote_message_header *req) { + remote_error *rerr) { const void *val; int err; char **wildcards; @@ -2630,14 +2675,14 @@ remoteSASLCheckAccess (struct qemud_serv qemudLog(QEMUD_ERR, _("cannot query SASL username on connection %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; return -1; } if (val == NULL) { qemudLog(QEMUD_ERR, "%s", _("no client username was found")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; return -1; @@ -2647,7 +2692,7 @@ remoteSASLCheckAccess (struct qemud_serv client->saslUsername = strdup((const char*)val); if (client->saslUsername == NULL) { qemudLog(QEMUD_ERR, "%s", _("out of memory copying username")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; return -1; @@ -2667,7 +2712,7 @@ remoteSASLCheckAccess (struct qemud_serv /* Denied */ qemudLog(QEMUD_ERR, _("SASL client %s not allowed in whitelist"), client->saslUsername); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; return -1; @@ -2680,7 +2725,7 @@ static int static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret) { @@ -2692,8 +2737,8 @@ remoteDispatchAuthSaslStart (struct qemu if (client->auth != REMOTE_AUTH_SASL || client->saslconn == NULL) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid SASL start request")); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } REMOTE_DEBUG("Using SASL mechanism %s. Data %d bytes, nil: %d", @@ -2711,23 +2756,23 @@ remoteDispatchAuthSaslStart (struct qemu err, sasl_errdetail(client->saslconn)); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) { qemudLog(QEMUD_ERR, _("sasl start reply data too long %d"), serveroutlen); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } /* NB, distinction of NULL vs "" is *critical* in SASL */ if (serverout) { if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } memcpy(ret->data.data_val, serverout, serveroutlen); } else { @@ -2740,12 +2785,12 @@ remoteDispatchAuthSaslStart (struct qemu if (err == SASL_CONTINUE) { ret->complete = 0; } else { - if (remoteSASLCheckSSF(client, req) < 0) - return -2; + if (remoteSASLCheckSSF(client, rerr) < 0) + return -1; /* Check username whitelist ACL */ - if (remoteSASLCheckAccess(server, client, req) < 0) - return -2; + if (remoteSASLCheckAccess(server, client, rerr) < 0) + return -1; REMOTE_DEBUG("Authentication successful %d", client->fd); ret->complete = 1; @@ -2759,7 +2804,7 @@ static int static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret) { @@ -2771,8 +2816,8 @@ remoteDispatchAuthSaslStep (struct qemud if (client->auth != REMOTE_AUTH_SASL || client->saslconn == NULL) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid SASL start request")); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } REMOTE_DEBUG("Using SASL Data %d bytes, nil: %d", @@ -2789,8 +2834,8 @@ remoteDispatchAuthSaslStep (struct qemud err, sasl_errdetail(client->saslconn)); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) { @@ -2798,15 +2843,15 @@ remoteDispatchAuthSaslStep (struct qemud serveroutlen); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } /* NB, distinction of NULL vs "" is *critical* in SASL */ if (serverout) { if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } memcpy(ret->data.data_val, serverout, serveroutlen); } else { @@ -2819,12 +2864,12 @@ remoteDispatchAuthSaslStep (struct qemud if (err == SASL_CONTINUE) { ret->complete = 0; } else { - if (remoteSASLCheckSSF(client, req) < 0) - return -2; + if (remoteSASLCheckSSF(client, rerr) < 0) + return -1; /* Check username whitelist ACL */ - if (remoteSASLCheckAccess(server, client, req) < 0) - return -2; + if (remoteSASLCheckAccess(server, client, rerr) < 0) + return -1; REMOTE_DEBUG("Authentication successful %d", client->fd); ret->complete = 1; @@ -2839,36 +2884,36 @@ static int static int remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED) { qemudLog(QEMUD_ERR, "%s", _("client tried unsupported SASL init request")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); return -1; } static int remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED, remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED) { qemudLog(QEMUD_ERR, "%s", _("client tried unsupported SASL start request")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); return -1; } static int remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED, remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED) { qemudLog(QEMUD_ERR, "%s", _("client tried unsupported SASL step request")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); return -1; } #endif /* HAVE_SASL */ @@ -2878,7 +2923,7 @@ static int static int remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_polkit_ret *ret) { @@ -2898,14 +2943,14 @@ remoteDispatchAuthPolkit (struct qemud_s if (client->auth != REMOTE_AUTH_POLKIT) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid PolicyKit init request")); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) { qemudLog(QEMUD_ERR, "%s", _("cannot get peer socket identity")); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } qemudLog(QEMUD_INFO, _("Checking PID %d running as %d"), @@ -2916,16 +2961,16 @@ remoteDispatchAuthPolkit (struct qemud_s qemudLog(QEMUD_ERR, _("Failed to lookup policy kit caller: %s"), err.message); dbus_error_free(&err); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } if (!(pkaction = polkit_action_new())) { qemudLog(QEMUD_ERR, _("Failed to create polkit action %s\n"), strerror(errno)); polkit_caller_unref(pkcaller); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } polkit_action_set_action_id(pkaction, action); @@ -2939,8 +2984,8 @@ remoteDispatchAuthPolkit (struct qemud_s polkit_caller_unref(pkcaller); polkit_action_unref(pkaction); dbus_error_free(&err); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } #if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED @@ -2954,8 +2999,8 @@ remoteDispatchAuthPolkit (struct qemud_s _("Policy kit failed to check authorization %d %s"), polkit_error_get_error_code(pkerr), polkit_error_get_error_message(pkerr)); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } #else pkresult = polkit_context_can_caller_do_action(pkcontext, @@ -2971,8 +3016,8 @@ remoteDispatchAuthPolkit (struct qemud_s " result: %s\n"), action, callerPid, callerUid, polkit_result_to_string_representation(pkresult)); - remoteDispatchFailAuth(client, req); - return -2; + remoteDispatchAuthError(rerr); + return -1; } qemudLog(QEMUD_INFO, _("Policy allowed action %s from pid %d, uid %d, result %s"), @@ -2988,14 +3033,14 @@ remoteDispatchAuthPolkit (struct qemud_s static int remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_message_header *req, - void *args ATTRIBUTE_UNUSED, - remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED) + struct qemud_client *client, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED) { qemudLog(QEMUD_ERR, "%s", _("client tried unsupported PolicyKit init request")); - remoteDispatchFailAuth(client, req); + remoteDispatchAuthError(rerr); return -1; } #endif /* HAVE_POLKIT */ @@ -3009,22 +3054,22 @@ static int static int remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_list_defined_storage_pools_args *args, remote_list_defined_storage_pools_ret *ret) { CHECK_CONN(client); if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -3032,6 +3077,7 @@ remoteDispatchListDefinedStoragePools (s ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -3041,22 +3087,22 @@ static int static int remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_list_storage_pools_args *args, remote_list_storage_pools_ret *ret) { CHECK_CONN(client); if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -3064,6 +3110,7 @@ remoteDispatchListStoragePools (struct q ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -3073,7 +3120,7 @@ static int static int remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_find_storage_pool_sources_args *args, remote_find_storage_pool_sources_ret *ret) { @@ -3084,8 +3131,10 @@ remoteDispatchFindStoragePoolSources (st args->type, args->srcSpec ? *args->srcSpec : NULL, args->flags); - if (ret->xml == NULL) - return -1; + if (ret->xml == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -3094,7 +3143,7 @@ static int static int remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_create_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3103,12 +3152,13 @@ remoteDispatchStoragePoolCreate (struct pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolCreate (pool, args->flags) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3118,7 +3168,7 @@ static int static int remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret) { @@ -3126,7 +3176,10 @@ remoteDispatchStoragePoolCreateXml (stru CHECK_CONN(client); pool = virStoragePoolCreateXML (client->conn, args->xml, args->flags); - if (pool == NULL) return -1; + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_pool (&ret->pool, pool); virStoragePoolFree(pool); @@ -3136,7 +3189,7 @@ static int static int remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_define_xml_args *args, remote_storage_pool_define_xml_ret *ret) { @@ -3144,7 +3197,10 @@ remoteDispatchStoragePoolDefineXml (stru CHECK_CONN(client); pool = virStoragePoolDefineXML (client->conn, args->xml, args->flags); - if (pool == NULL) return -1; + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_pool (&ret->pool, pool); virStoragePoolFree(pool); @@ -3153,22 +3209,23 @@ remoteDispatchStoragePoolDefineXml (stru static int remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_message_header *req, - remote_storage_pool_build_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + struct qemud_client *client, + remote_error *rerr, + remote_storage_pool_build_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virStoragePoolPtr pool; + CHECK_CONN(client); + + pool = get_nonnull_storage_pool (client->conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolBuild (pool, args->flags) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3179,7 +3236,7 @@ static int static int remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_destroy_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3188,12 +3245,13 @@ remoteDispatchStoragePoolDestroy (struct pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolDestroy (pool) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3203,7 +3261,7 @@ static int static int remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_delete_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3212,12 +3270,13 @@ remoteDispatchStoragePoolDelete (struct pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolDelete (pool, args->flags) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3227,7 +3286,7 @@ static int static int remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_refresh_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3236,12 +3295,13 @@ remoteDispatchStoragePoolRefresh (struct pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolRefresh (pool, args->flags) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3251,7 +3311,7 @@ static int static int remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_get_info_args *args, remote_storage_pool_get_info_ret *ret) { @@ -3261,12 +3321,13 @@ remoteDispatchStoragePoolGetInfo (struct pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolGetInfo (pool, &info) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -3283,7 +3344,7 @@ static int static int remoteDispatchStoragePoolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_dump_xml_args *args, remote_storage_pool_dump_xml_ret *ret) { @@ -3292,14 +3353,15 @@ remoteDispatchStoragePoolDumpXml (struct pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->xml = virStoragePoolGetXMLDesc (pool, args->flags); if (!ret->xml) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3309,7 +3371,7 @@ static int static int remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_get_autostart_args *args, remote_storage_pool_get_autostart_ret *ret) { @@ -3318,12 +3380,13 @@ remoteDispatchStoragePoolGetAutostart (s pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3334,7 +3397,7 @@ static int static int remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret) { @@ -3342,7 +3405,10 @@ remoteDispatchStoragePoolLookupByName (s CHECK_CONN(client); pool = virStoragePoolLookupByName (client->conn, args->name); - if (pool == NULL) return -1; + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_pool (&ret->pool, pool); virStoragePoolFree(pool); @@ -3352,7 +3418,7 @@ static int static int remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_lookup_by_uuid_args *args, remote_storage_pool_lookup_by_uuid_ret *ret) { @@ -3360,7 +3426,10 @@ remoteDispatchStoragePoolLookupByUuid (s CHECK_CONN(client); pool = virStoragePoolLookupByUUID (client->conn, (unsigned char *) args->uuid); - if (pool == NULL) return -1; + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_pool (&ret->pool, pool); virStoragePoolFree(pool); @@ -3370,7 +3439,7 @@ static int static int remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_lookup_by_volume_args *args, remote_storage_pool_lookup_by_volume_ret *ret) { @@ -3379,10 +3448,17 @@ remoteDispatchStoragePoolLookupByVolume CHECK_CONN(client); vol = get_nonnull_storage_vol (client->conn, args->vol); + if (vol == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } pool = virStoragePoolLookupByVolume (vol); virStorageVolFree(vol); - if (pool == NULL) return -1; + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_pool (&ret->pool, pool); virStoragePoolFree(pool); @@ -3392,7 +3468,7 @@ static int static int remoteDispatchStoragePoolSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_set_autostart_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3401,12 +3477,13 @@ remoteDispatchStoragePoolSetAutostart (s pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolSetAutostart (pool, args->autostart) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3416,7 +3493,7 @@ static int static int remoteDispatchStoragePoolUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_undefine_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3425,12 +3502,13 @@ remoteDispatchStoragePoolUndefine (struc pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStoragePoolUndefine (pool) == -1) { virStoragePoolFree(pool); + remoteDispatchConnError(rerr, client->conn); return -1; } virStoragePoolFree(pool); @@ -3440,14 +3518,17 @@ static int static int remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_storage_pools_ret *ret) { CHECK_CONN(client); ret->num = virConnectNumOfStoragePools (client->conn); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -3455,14 +3536,17 @@ static int static int remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_defined_storage_pools_ret *ret) { CHECK_CONN(client); ret->num = virConnectNumOfDefinedStoragePools (client->conn); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -3470,7 +3554,7 @@ static int static int remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_list_volumes_args *args, remote_storage_pool_list_volumes_ret *ret) { @@ -3478,22 +3562,22 @@ remoteDispatchStoragePoolListVolumes (st CHECK_CONN(client); if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX")); - return -2; - } - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - virStoragePoolFree(pool); - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX")); + return -1; + } + + pool = get_nonnull_storage_pool (client->conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + virStoragePoolFree(pool); + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -3502,6 +3586,7 @@ remoteDispatchStoragePoolListVolumes (st virStoragePoolFree(pool); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -3512,7 +3597,7 @@ static int static int remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_pool_num_of_volumes_args *args, remote_storage_pool_num_of_volumes_ret *ret) { @@ -3521,13 +3606,16 @@ remoteDispatchStoragePoolNumOfVolumes (s pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } ret->num = virStoragePoolNumOfVolumes (pool); virStoragePoolFree(pool); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -3542,7 +3630,7 @@ static int static int remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret) { @@ -3552,13 +3640,16 @@ remoteDispatchStorageVolCreateXml (struc pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } vol = virStorageVolCreateXML (pool, args->xml, args->flags); virStoragePoolFree(pool); - if (vol == NULL) return -1; + if (vol == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_vol (&ret->vol, vol); virStorageVolFree(vol); @@ -3569,7 +3660,7 @@ static int static int remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_delete_args *args, void *ret ATTRIBUTE_UNUSED) { @@ -3578,12 +3669,13 @@ remoteDispatchStorageVolDelete (struct q vol = get_nonnull_storage_vol (client->conn, args->vol); if (vol == NULL) { - remoteDispatchError (client, req, "%s", _("storage_vol not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStorageVolDelete (vol, args->flags) == -1) { virStorageVolFree(vol); + remoteDispatchConnError(rerr, client->conn); return -1; } virStorageVolFree(vol); @@ -3593,7 +3685,7 @@ static int static int remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_get_info_args *args, remote_storage_vol_get_info_ret *ret) { @@ -3603,12 +3695,13 @@ remoteDispatchStorageVolGetInfo (struct vol = get_nonnull_storage_vol (client->conn, args->vol); if (vol == NULL) { - remoteDispatchError (client, req, "%s", _("storage_vol not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } if (virStorageVolGetInfo (vol, &info) == -1) { virStorageVolFree(vol); + remoteDispatchConnError(rerr, client->conn); return -1; } @@ -3624,7 +3717,7 @@ static int static int remoteDispatchStorageVolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_dump_xml_args *args, remote_storage_vol_dump_xml_ret *ret) { @@ -3633,14 +3726,15 @@ remoteDispatchStorageVolDumpXml (struct vol = get_nonnull_storage_vol (client->conn, args->vol); if (vol == NULL) { - remoteDispatchError (client, req, "%s", _("storage_vol not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->xml = virStorageVolGetXMLDesc (vol, args->flags); if (!ret->xml) { virStorageVolFree(vol); + remoteDispatchConnError(rerr, client->conn); return -1; } virStorageVolFree(vol); @@ -3651,7 +3745,7 @@ static int static int remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_get_path_args *args, remote_storage_vol_get_path_ret *ret) { @@ -3660,14 +3754,15 @@ remoteDispatchStorageVolGetPath (struct vol = get_nonnull_storage_vol (client->conn, args->vol); if (vol == NULL) { - remoteDispatchError (client, req, "%s", _("storage_vol not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->name = virStorageVolGetPath (vol); if (!ret->name) { virStorageVolFree(vol); + remoteDispatchConnError(rerr, client->conn); return -1; } virStorageVolFree(vol); @@ -3678,7 +3773,7 @@ static int static int remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_lookup_by_name_args *args, remote_storage_vol_lookup_by_name_ret *ret) { @@ -3688,13 +3783,16 @@ remoteDispatchStorageVolLookupByName (st pool = get_nonnull_storage_pool (client->conn, args->pool); if (pool == NULL) { - remoteDispatchError (client, req, "%s", _("storage_pool not found")); - return -2; + remoteDispatchConnError(rerr, client->conn); + return -1; } vol = virStorageVolLookupByName (pool, args->name); virStoragePoolFree(pool); - if (vol == NULL) return -1; + if (vol == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_vol (&ret->vol, vol); virStorageVolFree(vol); @@ -3704,7 +3802,7 @@ static int static int remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_lookup_by_key_args *args, remote_storage_vol_lookup_by_key_ret *ret) { @@ -3712,7 +3810,10 @@ remoteDispatchStorageVolLookupByKey (str CHECK_CONN(client); vol = virStorageVolLookupByKey (client->conn, args->key); - if (vol == NULL) return -1; + if (vol == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_vol (&ret->vol, vol); virStorageVolFree(vol); @@ -3723,7 +3824,7 @@ static int static int remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_storage_vol_lookup_by_path_args *args, remote_storage_vol_lookup_by_path_ret *ret) { @@ -3731,7 +3832,10 @@ remoteDispatchStorageVolLookupByPath (st CHECK_CONN(client); vol = virStorageVolLookupByPath (client->conn, args->path); - if (vol == NULL) return -1; + if (vol == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_storage_vol (&ret->vol, vol); virStorageVolFree(vol); @@ -3746,7 +3850,7 @@ static int static int remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_num_of_devices_args *args, remote_node_num_of_devices_ret *ret) { @@ -3755,7 +3859,10 @@ remoteDispatchNodeNumOfDevices (struct q ret->num = virNodeNumOfDevices (client->conn, args->cap ? *args->cap : NULL, args->flags); - if (ret->num == -1) return -1; + if (ret->num == -1) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } return 0; } @@ -3764,22 +3871,22 @@ static int static int remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_list_devices_args *args, remote_node_list_devices_ret *ret) { CHECK_CONN(client); if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError(rerr, + "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = @@ -3787,6 +3894,7 @@ remoteDispatchNodeListDevices (struct qe args->cap ? *args->cap : NULL, ret->names.names_val, args->maxnames, args->flags); if (ret->names.names_len == -1) { + remoteDispatchConnError(rerr, client->conn); VIR_FREE(ret->names.names_val); return -1; } @@ -3798,7 +3906,7 @@ static int static int remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_device_lookup_by_name_args *args, remote_node_device_lookup_by_name_ret *ret) { @@ -3807,7 +3915,10 @@ remoteDispatchNodeDeviceLookupByName (st CHECK_CONN(client); dev = virNodeDeviceLookupByName (client->conn, args->name); - if (dev == NULL) return -1; + if (dev == NULL) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } make_nonnull_node_device (&ret->dev, dev); virNodeDeviceFree(dev); @@ -3818,7 +3929,7 @@ static int static int remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_device_dump_xml_args *args, remote_node_device_dump_xml_ret *ret) { @@ -3827,13 +3938,14 @@ remoteDispatchNodeDeviceDumpXml (struct dev = virNodeDeviceLookupByName(client->conn, args->name); if (dev == NULL) { - remoteDispatchError (client, req, "%s", _("node_device not found")); - return -2; + remoteDispatchFormatError(rerr, "%s", _("node_device not found")); + return -1; } /* remoteDispatchClientRequest will free this. */ ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags); if (!ret->xml) { + remoteDispatchConnError(rerr, client->conn); virNodeDeviceFree(dev); return -1; } @@ -3845,7 +3957,7 @@ static int static int remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_device_get_parent_args *args, remote_node_device_get_parent_ret *ret) { @@ -3855,8 +3967,8 @@ remoteDispatchNodeDeviceGetParent (struc dev = virNodeDeviceLookupByName(client->conn, args->name); if (dev == NULL) { - remoteDispatchError (client, req, "%s", _("node_device not found")); - return -2; + remoteDispatchFormatError(rerr, "%s", _("node_device not found")); + return -1; } parent = virNodeDeviceGetParent(dev); @@ -3867,13 +3979,13 @@ remoteDispatchNodeDeviceGetParent (struc /* remoteDispatchClientRequest will free this. */ char **parent_p; if (VIR_ALLOC(parent_p) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } *parent_p = strdup(parent); if (*parent_p == NULL) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchOOMError(rerr); + return -1; } ret->parent = parent_p; } @@ -3886,7 +3998,7 @@ static int static int remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_device_num_of_caps_args *args, remote_node_device_num_of_caps_ret *ret) { @@ -3895,11 +4007,15 @@ remoteDispatchNodeDeviceNumOfCaps (struc dev = virNodeDeviceLookupByName(client->conn, args->name); if (dev == NULL) { - remoteDispatchError (client, req, "%s", _("node_device not found")); - return -2; + remoteDispatchFormatError(rerr, "%s", _("node_device not found")); + return -1; } ret->num = virNodeDeviceNumOfCaps(dev); + if (ret->num < 0) { + remoteDispatchConnError(rerr, client->conn); + return -1; + } virNodeDeviceFree(dev); return 0; @@ -3909,7 +4025,7 @@ static int static int remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req, + remote_error *rerr, remote_node_device_list_caps_args *args, remote_node_device_list_caps_ret *ret) { @@ -3918,26 +4034,27 @@ remoteDispatchNodeDeviceListCaps (struct dev = virNodeDeviceLookupByName(client->conn, args->name); if (dev == NULL) { - remoteDispatchError (client, req, "%s", _("node_device not found")); - return -2; + remoteDispatchFormatError(rerr, "%s", _("node_device not found")); + return -1; } if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { - remoteDispatchError (client, req, - "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); - return -2; - } - - /* Allocate return buffer. */ - if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { - remoteDispatchSendError(client, req, VIR_ERR_NO_MEMORY, NULL); - return -2; + remoteDispatchFormatError(rerr, + "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; } ret->names.names_len = virNodeDeviceListCaps (dev, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { + remoteDispatchConnError(rerr, client->conn); VIR_FREE(ret->names.names_val); return -1; } @@ -3952,7 +4069,7 @@ static int static int remoteDispatchDomainEvent (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, - remote_message_header *req ATTRIBUTE_UNUSED, + remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, remote_domain_event_ret *ret ATTRIBUTE_UNUSED) { @@ -3960,7 +4077,8 @@ remoteDispatchDomainEvent (struct qemud_ * This does not make sense, as this should not be intiated * from the client side in generated code. */ - return -1; + remoteDispatchFormatError(rerr, "%s", _("unexpected async event method call")); + return -1; } /*************************** @@ -3969,7 +4087,7 @@ static int static int remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req ATTRIBUTE_UNUSED, + remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, remote_domain_events_register_ret *ret ATTRIBUTE_UNUSED) { @@ -3987,7 +4105,7 @@ static int static int remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client, - remote_message_header *req ATTRIBUTE_UNUSED, + remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, remote_domain_events_deregister_ret *ret ATTRIBUTE_UNUSED) { @@ -4013,10 +4131,8 @@ remoteDispatchDomainEventSend (struct qe int len; remote_domain_event_ret data; - if(!client) { - remoteDispatchError (client, NULL, "%s", _("Invalid Client")); - return; - } + if (!client) + return; rep.prog = REMOTE_PROGRAM; rep.vers = REMOTE_PROTOCOL_VERSION; @@ -4030,7 +4146,7 @@ remoteDispatchDomainEventSend (struct qe len = 0; /* We'll come back and write this later. */ if (!xdr_int (&xdr, &len)) { - remoteDispatchError (client, NULL, "%s", _("xdr_int failed (1)")); + /*remoteDispatchError (client, NULL, "%s", _("xdr_int failed (1)"));*/ xdr_destroy (&xdr); return; } @@ -4046,20 +4162,20 @@ remoteDispatchDomainEventSend (struct qe data.detail = detail; if (!xdr_remote_domain_event_ret(&xdr, &data)) { - remoteDispatchError (client, NULL, "%s", _("serialise return struct")); + /*remoteDispatchError (client, NULL, "%s", _("serialise return struct"));*/ xdr_destroy (&xdr); return; } len = xdr_getpos (&xdr); if (xdr_setpos (&xdr, 0) == 0) { - remoteDispatchError (client, NULL, "%s", _("xdr_setpos failed")); + /*remoteDispatchError (client, NULL, "%s", _("xdr_setpos failed"));*/ xdr_destroy (&xdr); return; } if (!xdr_int (&xdr, &len)) { - remoteDispatchError (client, NULL, "%s", _("xdr_int failed (2)")); + /*remoteDispatchError (client, NULL, "%s", _("xdr_int failed (2)"));*/ xdr_destroy (&xdr); return; } diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h --- a/qemud/remote_dispatch_prototypes.h +++ b/qemud/remote_dispatch_prototypes.h @@ -2,120 +2,120 @@ * Do not edit this file. Any changes you make will be lost. */ -static int remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_list_ret *ret); -static int remoteDispatchAuthPolkit (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_polkit_ret *ret); -static int remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_auth_sasl_init_ret *ret); -static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret); -static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret); -static int remoteDispatchClose (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, void *ret); -static int remoteDispatchDomainAttachDevice (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_attach_device_args *args, void *ret); -static int remoteDispatchDomainBlockPeek (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret); -static int remoteDispatchDomainBlockStats (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret); -static int remoteDispatchDomainCoreDump (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_core_dump_args *args, void *ret); -static int remoteDispatchDomainCreate (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_create_args *args, void *ret); -static int remoteDispatchDomainCreateXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_create_xml_args *args, remote_domain_create_xml_ret *ret); -static int remoteDispatchDomainDefineXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_define_xml_args *args, remote_domain_define_xml_ret *ret); -static int remoteDispatchDomainDestroy (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_destroy_args *args, void *ret); -static int remoteDispatchDomainDetachDevice (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_detach_device_args *args, void *ret); -static int remoteDispatchDomainDumpXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_dump_xml_args *args, remote_domain_dump_xml_ret *ret); -static int remoteDispatchDomainEvent (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_domain_event_ret *ret); -static int remoteDispatchDomainEventsDeregister (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_domain_events_deregister_ret *ret); -static int remoteDispatchDomainEventsRegister (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_domain_events_register_ret *ret); -static int remoteDispatchDomainGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_autostart_args *args, remote_domain_get_autostart_ret *ret); -static int remoteDispatchDomainGetInfo (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_info_args *args, remote_domain_get_info_ret *ret); -static int remoteDispatchDomainGetMaxMemory (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_max_memory_args *args, remote_domain_get_max_memory_ret *ret); -static int remoteDispatchDomainGetMaxVcpus (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_max_vcpus_args *args, remote_domain_get_max_vcpus_ret *ret); -static int remoteDispatchDomainGetOsType (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret); -static int remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret); -static int remoteDispatchDomainGetSchedulerType (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret); -static int remoteDispatchDomainGetVcpus (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret); -static int remoteDispatchDomainInterfaceStats (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret); -static int remoteDispatchDomainLookupById (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret); -static int remoteDispatchDomainLookupByName (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret); -static int remoteDispatchDomainLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret); -static int remoteDispatchDomainMemoryPeek (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_memory_peek_args *args, remote_domain_memory_peek_ret *ret); -static int remoteDispatchDomainMigrateFinish (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_migrate_finish_args *args, remote_domain_migrate_finish_ret *ret); -static int remoteDispatchDomainMigrateFinish2 (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret); -static int remoteDispatchDomainMigratePerform (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_migrate_perform_args *args, void *ret); -static int remoteDispatchDomainMigratePrepare (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_migrate_prepare_args *args, remote_domain_migrate_prepare_ret *ret); -static int remoteDispatchDomainMigratePrepare2 (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_migrate_prepare2_args *args, remote_domain_migrate_prepare2_ret *ret); -static int remoteDispatchDomainPinVcpu (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_pin_vcpu_args *args, void *ret); -static int remoteDispatchDomainReboot (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_reboot_args *args, void *ret); -static int remoteDispatchDomainRestore (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_restore_args *args, void *ret); -static int remoteDispatchDomainResume (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_resume_args *args, void *ret); -static int remoteDispatchDomainSave (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_save_args *args, void *ret); -static int remoteDispatchDomainSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_set_autostart_args *args, void *ret); -static int remoteDispatchDomainSetMaxMemory (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_set_max_memory_args *args, void *ret); -static int remoteDispatchDomainSetMemory (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_set_memory_args *args, void *ret); -static int remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_set_scheduler_parameters_args *args, void *ret); -static int remoteDispatchDomainSetVcpus (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_set_vcpus_args *args, void *ret); -static int remoteDispatchDomainShutdown (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_shutdown_args *args, void *ret); -static int remoteDispatchDomainSuspend (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_suspend_args *args, void *ret); -static int remoteDispatchDomainUndefine (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_domain_undefine_args *args, void *ret); -static int remoteDispatchFindStoragePoolSources (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_find_storage_pool_sources_args *args, remote_find_storage_pool_sources_ret *ret); -static int remoteDispatchGetCapabilities (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_get_capabilities_ret *ret); -static int remoteDispatchGetHostname (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_get_hostname_ret *ret); -static int remoteDispatchGetMaxVcpus (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret); -static int remoteDispatchGetType (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_get_type_ret *ret); -static int remoteDispatchGetUri (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_get_uri_ret *ret); -static int remoteDispatchGetVersion (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_get_version_ret *ret); -static int remoteDispatchListDefinedDomains (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_list_defined_domains_args *args, remote_list_defined_domains_ret *ret); -static int remoteDispatchListDefinedNetworks (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_list_defined_networks_args *args, remote_list_defined_networks_ret *ret); -static int remoteDispatchListDefinedStoragePools (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_list_defined_storage_pools_args *args, remote_list_defined_storage_pools_ret *ret); -static int remoteDispatchListDomains (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_list_domains_args *args, remote_list_domains_ret *ret); -static int remoteDispatchListNetworks (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_list_networks_args *args, remote_list_networks_ret *ret); -static int remoteDispatchListStoragePools (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_list_storage_pools_args *args, remote_list_storage_pools_ret *ret); -static int remoteDispatchNetworkCreate (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_create_args *args, void *ret); -static int remoteDispatchNetworkCreateXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret); -static int remoteDispatchNetworkDefineXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_define_xml_args *args, remote_network_define_xml_ret *ret); -static int remoteDispatchNetworkDestroy (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_destroy_args *args, void *ret); -static int remoteDispatchNetworkDumpXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_dump_xml_args *args, remote_network_dump_xml_ret *ret); -static int remoteDispatchNetworkGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_get_autostart_args *args, remote_network_get_autostart_ret *ret); -static int remoteDispatchNetworkGetBridgeName (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_get_bridge_name_args *args, remote_network_get_bridge_name_ret *ret); -static int remoteDispatchNetworkLookupByName (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret); -static int remoteDispatchNetworkLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_lookup_by_uuid_args *args, remote_network_lookup_by_uuid_ret *ret); -static int remoteDispatchNetworkSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_set_autostart_args *args, void *ret); -static int remoteDispatchNetworkUndefine (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_network_undefine_args *args, void *ret); -static int remoteDispatchNodeDeviceDumpXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_device_dump_xml_args *args, remote_node_device_dump_xml_ret *ret); -static int remoteDispatchNodeDeviceGetParent (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_device_get_parent_args *args, remote_node_device_get_parent_ret *ret); -static int remoteDispatchNodeDeviceListCaps (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_device_list_caps_args *args, remote_node_device_list_caps_ret *ret); -static int remoteDispatchNodeDeviceLookupByName (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_device_lookup_by_name_args *args, remote_node_device_lookup_by_name_ret *ret); -static int remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_device_num_of_caps_args *args, remote_node_device_num_of_caps_ret *ret); -static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret); -static int remoteDispatchNodeGetFreeMemory (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_node_get_free_memory_ret *ret); -static int remoteDispatchNodeGetInfo (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_node_get_info_ret *ret); -static int remoteDispatchNodeListDevices (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_list_devices_args *args, remote_node_list_devices_ret *ret); -static int remoteDispatchNodeNumOfDevices (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_node_num_of_devices_args *args, remote_node_num_of_devices_ret *ret); -static int remoteDispatchNumOfDefinedDomains (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_num_of_defined_domains_ret *ret); -static int remoteDispatchNumOfDefinedNetworks (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_num_of_defined_networks_ret *ret); -static int remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_num_of_defined_storage_pools_ret *ret); -static int remoteDispatchNumOfDomains (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_num_of_domains_ret *ret); -static int remoteDispatchNumOfNetworks (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_num_of_networks_ret *ret); -static int remoteDispatchNumOfStoragePools (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, void *args, remote_num_of_storage_pools_ret *ret); -static int remoteDispatchOpen (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_open_args *args, void *ret); -static int remoteDispatchStoragePoolBuild (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_build_args *args, void *ret); -static int remoteDispatchStoragePoolCreate (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_create_args *args, void *ret); -static int remoteDispatchStoragePoolCreateXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret); -static int remoteDispatchStoragePoolDefineXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_define_xml_args *args, remote_storage_pool_define_xml_ret *ret); -static int remoteDispatchStoragePoolDelete (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_delete_args *args, void *ret); -static int remoteDispatchStoragePoolDestroy (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_destroy_args *args, void *ret); -static int remoteDispatchStoragePoolDumpXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_dump_xml_args *args, remote_storage_pool_dump_xml_ret *ret); -static int remoteDispatchStoragePoolGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_get_autostart_args *args, remote_storage_pool_get_autostart_ret *ret); -static int remoteDispatchStoragePoolGetInfo (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_get_info_args *args, remote_storage_pool_get_info_ret *ret); -static int remoteDispatchStoragePoolListVolumes (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_list_volumes_args *args, remote_storage_pool_list_volumes_ret *ret); -static int remoteDispatchStoragePoolLookupByName (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret); -static int remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_lookup_by_uuid_args *args, remote_storage_pool_lookup_by_uuid_ret *ret); -static int remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_lookup_by_volume_args *args, remote_storage_pool_lookup_by_volume_ret *ret); -static int remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_num_of_volumes_args *args, remote_storage_pool_num_of_volumes_ret *ret); -static int remoteDispatchStoragePoolRefresh (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_refresh_args *args, void *ret); -static int remoteDispatchStoragePoolSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_set_autostart_args *args, void *ret); -static int remoteDispatchStoragePoolUndefine (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_pool_undefine_args *args, void *ret); -static int remoteDispatchStorageVolCreateXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret); -static int remoteDispatchStorageVolDelete (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_delete_args *args, void *ret); -static int remoteDispatchStorageVolDumpXml (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_dump_xml_args *args, remote_storage_vol_dump_xml_ret *ret); -static int remoteDispatchStorageVolGetInfo (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_get_info_args *args, remote_storage_vol_get_info_ret *ret); -static int remoteDispatchStorageVolGetPath (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_get_path_args *args, remote_storage_vol_get_path_ret *ret); -static int remoteDispatchStorageVolLookupByKey (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_lookup_by_key_args *args, remote_storage_vol_lookup_by_key_ret *ret); -static int remoteDispatchStorageVolLookupByName (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_lookup_by_name_args *args, remote_storage_vol_lookup_by_name_ret *ret); -static int remoteDispatchStorageVolLookupByPath (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_storage_vol_lookup_by_path_args *args, remote_storage_vol_lookup_by_path_ret *ret); -static int remoteDispatchSupportsFeature (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, remote_supports_feature_args *args, remote_supports_feature_ret *ret); +static int remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_auth_list_ret *ret); +static int remoteDispatchAuthPolkit (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_auth_polkit_ret *ret); +static int remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_auth_sasl_init_ret *ret); +static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret); +static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret); +static int remoteDispatchClose (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, void *ret); +static int remoteDispatchDomainAttachDevice (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_attach_device_args *args, void *ret); +static int remoteDispatchDomainBlockPeek (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret); +static int remoteDispatchDomainBlockStats (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret); +static int remoteDispatchDomainCoreDump (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_core_dump_args *args, void *ret); +static int remoteDispatchDomainCreate (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_create_args *args, void *ret); +static int remoteDispatchDomainCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_create_xml_args *args, remote_domain_create_xml_ret *ret); +static int remoteDispatchDomainDefineXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_define_xml_args *args, remote_domain_define_xml_ret *ret); +static int remoteDispatchDomainDestroy (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_destroy_args *args, void *ret); +static int remoteDispatchDomainDetachDevice (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_detach_device_args *args, void *ret); +static int remoteDispatchDomainDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_dump_xml_args *args, remote_domain_dump_xml_ret *ret); +static int remoteDispatchDomainEvent (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_domain_event_ret *ret); +static int remoteDispatchDomainEventsDeregister (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_domain_events_deregister_ret *ret); +static int remoteDispatchDomainEventsRegister (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_domain_events_register_ret *ret); +static int remoteDispatchDomainGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_autostart_args *args, remote_domain_get_autostart_ret *ret); +static int remoteDispatchDomainGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_info_args *args, remote_domain_get_info_ret *ret); +static int remoteDispatchDomainGetMaxMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_max_memory_args *args, remote_domain_get_max_memory_ret *ret); +static int remoteDispatchDomainGetMaxVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_max_vcpus_args *args, remote_domain_get_max_vcpus_ret *ret); +static int remoteDispatchDomainGetOsType (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret); +static int remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret); +static int remoteDispatchDomainGetSchedulerType (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret); +static int remoteDispatchDomainGetVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret); +static int remoteDispatchDomainInterfaceStats (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret); +static int remoteDispatchDomainLookupById (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret); +static int remoteDispatchDomainLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret); +static int remoteDispatchDomainLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret); +static int remoteDispatchDomainMemoryPeek (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_memory_peek_args *args, remote_domain_memory_peek_ret *ret); +static int remoteDispatchDomainMigrateFinish (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_finish_args *args, remote_domain_migrate_finish_ret *ret); +static int remoteDispatchDomainMigrateFinish2 (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret); +static int remoteDispatchDomainMigratePerform (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_perform_args *args, void *ret); +static int remoteDispatchDomainMigratePrepare (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_prepare_args *args, remote_domain_migrate_prepare_ret *ret); +static int remoteDispatchDomainMigratePrepare2 (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_prepare2_args *args, remote_domain_migrate_prepare2_ret *ret); +static int remoteDispatchDomainPinVcpu (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_pin_vcpu_args *args, void *ret); +static int remoteDispatchDomainReboot (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_reboot_args *args, void *ret); +static int remoteDispatchDomainRestore (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_restore_args *args, void *ret); +static int remoteDispatchDomainResume (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_resume_args *args, void *ret); +static int remoteDispatchDomainSave (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_save_args *args, void *ret); +static int remoteDispatchDomainSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_autostart_args *args, void *ret); +static int remoteDispatchDomainSetMaxMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_max_memory_args *args, void *ret); +static int remoteDispatchDomainSetMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_memory_args *args, void *ret); +static int remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_scheduler_parameters_args *args, void *ret); +static int remoteDispatchDomainSetVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_vcpus_args *args, void *ret); +static int remoteDispatchDomainShutdown (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_shutdown_args *args, void *ret); +static int remoteDispatchDomainSuspend (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_suspend_args *args, void *ret); +static int remoteDispatchDomainUndefine (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_undefine_args *args, void *ret); +static int remoteDispatchFindStoragePoolSources (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_find_storage_pool_sources_args *args, remote_find_storage_pool_sources_ret *ret); +static int remoteDispatchGetCapabilities (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_capabilities_ret *ret); +static int remoteDispatchGetHostname (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_hostname_ret *ret); +static int remoteDispatchGetMaxVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret); +static int remoteDispatchGetType (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_type_ret *ret); +static int remoteDispatchGetUri (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_uri_ret *ret); +static int remoteDispatchGetVersion (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_version_ret *ret); +static int remoteDispatchListDefinedDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_defined_domains_args *args, remote_list_defined_domains_ret *ret); +static int remoteDispatchListDefinedNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_defined_networks_args *args, remote_list_defined_networks_ret *ret); +static int remoteDispatchListDefinedStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_defined_storage_pools_args *args, remote_list_defined_storage_pools_ret *ret); +static int remoteDispatchListDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_domains_args *args, remote_list_domains_ret *ret); +static int remoteDispatchListNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_networks_args *args, remote_list_networks_ret *ret); +static int remoteDispatchListStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_storage_pools_args *args, remote_list_storage_pools_ret *ret); +static int remoteDispatchNetworkCreate (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_create_args *args, void *ret); +static int remoteDispatchNetworkCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret); +static int remoteDispatchNetworkDefineXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_define_xml_args *args, remote_network_define_xml_ret *ret); +static int remoteDispatchNetworkDestroy (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_destroy_args *args, void *ret); +static int remoteDispatchNetworkDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_dump_xml_args *args, remote_network_dump_xml_ret *ret); +static int remoteDispatchNetworkGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_get_autostart_args *args, remote_network_get_autostart_ret *ret); +static int remoteDispatchNetworkGetBridgeName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_get_bridge_name_args *args, remote_network_get_bridge_name_ret *ret); +static int remoteDispatchNetworkLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret); +static int remoteDispatchNetworkLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_lookup_by_uuid_args *args, remote_network_lookup_by_uuid_ret *ret); +static int remoteDispatchNetworkSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_set_autostart_args *args, void *ret); +static int remoteDispatchNetworkUndefine (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_undefine_args *args, void *ret); +static int remoteDispatchNodeDeviceDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_dump_xml_args *args, remote_node_device_dump_xml_ret *ret); +static int remoteDispatchNodeDeviceGetParent (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_get_parent_args *args, remote_node_device_get_parent_ret *ret); +static int remoteDispatchNodeDeviceListCaps (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_list_caps_args *args, remote_node_device_list_caps_ret *ret); +static int remoteDispatchNodeDeviceLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_lookup_by_name_args *args, remote_node_device_lookup_by_name_ret *ret); +static int remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_num_of_caps_args *args, remote_node_device_num_of_caps_ret *ret); +static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret); +static int remoteDispatchNodeGetFreeMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_node_get_free_memory_ret *ret); +static int remoteDispatchNodeGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_node_get_info_ret *ret); +static int remoteDispatchNodeListDevices (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_list_devices_args *args, remote_node_list_devices_ret *ret); +static int remoteDispatchNodeNumOfDevices (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_num_of_devices_args *args, remote_node_num_of_devices_ret *ret); +static int remoteDispatchNumOfDefinedDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_defined_domains_ret *ret); +static int remoteDispatchNumOfDefinedNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_defined_networks_ret *ret); +static int remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_defined_storage_pools_ret *ret); +static int remoteDispatchNumOfDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_domains_ret *ret); +static int remoteDispatchNumOfNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_networks_ret *ret); +static int remoteDispatchNumOfStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_storage_pools_ret *ret); +static int remoteDispatchOpen (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_open_args *args, void *ret); +static int remoteDispatchStoragePoolBuild (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_build_args *args, void *ret); +static int remoteDispatchStoragePoolCreate (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_create_args *args, void *ret); +static int remoteDispatchStoragePoolCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret); +static int remoteDispatchStoragePoolDefineXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_define_xml_args *args, remote_storage_pool_define_xml_ret *ret); +static int remoteDispatchStoragePoolDelete (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_delete_args *args, void *ret); +static int remoteDispatchStoragePoolDestroy (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_destroy_args *args, void *ret); +static int remoteDispatchStoragePoolDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_dump_xml_args *args, remote_storage_pool_dump_xml_ret *ret); +static int remoteDispatchStoragePoolGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_get_autostart_args *args, remote_storage_pool_get_autostart_ret *ret); +static int remoteDispatchStoragePoolGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_get_info_args *args, remote_storage_pool_get_info_ret *ret); +static int remoteDispatchStoragePoolListVolumes (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_list_volumes_args *args, remote_storage_pool_list_volumes_ret *ret); +static int remoteDispatchStoragePoolLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret); +static int remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_lookup_by_uuid_args *args, remote_storage_pool_lookup_by_uuid_ret *ret); +static int remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_lookup_by_volume_args *args, remote_storage_pool_lookup_by_volume_ret *ret); +static int remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_num_of_volumes_args *args, remote_storage_pool_num_of_volumes_ret *ret); +static int remoteDispatchStoragePoolRefresh (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_refresh_args *args, void *ret); +static int remoteDispatchStoragePoolSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_set_autostart_args *args, void *ret); +static int remoteDispatchStoragePoolUndefine (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_undefine_args *args, void *ret); +static int remoteDispatchStorageVolCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret); +static int remoteDispatchStorageVolDelete (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_delete_args *args, void *ret); +static int remoteDispatchStorageVolDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_dump_xml_args *args, remote_storage_vol_dump_xml_ret *ret); +static int remoteDispatchStorageVolGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_get_info_args *args, remote_storage_vol_get_info_ret *ret); +static int remoteDispatchStorageVolGetPath (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_get_path_args *args, remote_storage_vol_get_path_ret *ret); +static int remoteDispatchStorageVolLookupByKey (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_lookup_by_key_args *args, remote_storage_vol_lookup_by_key_ret *ret); +static int remoteDispatchStorageVolLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_lookup_by_name_args *args, remote_storage_vol_lookup_by_name_ret *ret); +static int remoteDispatchStorageVolLookupByPath (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_lookup_by_path_args *args, remote_storage_vol_lookup_by_path_ret *ret); +static int remoteDispatchSupportsFeature (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_supports_feature_args *args, remote_supports_feature_ret *ret); diff --git a/qemud/remote_generate_stubs.pl b/qemud/remote_generate_stubs.pl --- a/qemud/remote_generate_stubs.pl +++ b/qemud/remote_generate_stubs.pl @@ -100,7 +100,7 @@ elsif ($opt_p) { elsif ($opt_p) { my @keys = sort (keys %calls); foreach (@keys) { - print "static int remoteDispatch$calls{$_}->{ProcName} (struct qemud_server *server, struct qemud_client *client, remote_message_header *req, $calls{$_}->{args} *args, $calls{$_}->{ret} *ret);\n"; + print "static int remoteDispatch$calls{$_}->{ProcName} (struct qemud_server *server, struct qemud_client *client, remote_error *err, $calls{$_}->{args} *args, $calls{$_}->{ret} *ret);\n"; } } diff --git a/src/domain_conf.c b/src/domain_conf.c --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -498,8 +498,12 @@ void virDomainRemoveInactive(virDomainOb memmove(doms->objs + i, doms->objs + i + 1, sizeof(*(doms->objs)) * (doms->count - (i + 1))); - if (VIR_REALLOC_N(doms->objs, doms->count - 1) < 0) { - ; /* Failure to reduce memory allocation isn't fatal */ + if (doms->count > 1) { + if (VIR_REALLOC_N(doms->objs, doms->count - 1) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + } else { + VIR_FREE(doms->objs); } doms->count--; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:16:29AM +0000, Daniel P. Berrange wrote:
The current RPC handler methods have two possible return codes, -1 and -2, both indicate that an error occurred, but one says that the error has been serialized onto the outgoing dispatch buffer already, the other says that the caller must do serialization. This unneccessarily complex and has a number of errors already, so this patch makes the RPC handler responsible for all error serialization.
I tried to have a glance though the code, it's a bit hard but it seems most of it is kind of similar once the old error routine is changed everything seems to result from it, including change in parameters, so +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch makes the event loop in the libvirtd daemon thread safe, and re-entrant. This allows one thread to add/remove/update timers/file handle watches while other thread is doing the poll. This sometimes requires that we wakeup the main thread to make it see changes to the poll FD list. We use the traditional self-pipe trick for this task. event.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- event.h | 14 +++++ qemud.c | 10 +++ qemud.h | 3 + 4 files changed, 167 insertions(+), 28 deletions(-) Daniel diff --git a/qemud/event.c b/qemud/event.c --- a/qemud/event.c +++ b/qemud/event.c @@ -28,12 +28,16 @@ #include <poll.h> #include <sys/time.h> #include <errno.h> +#include <unistd.h> #include "qemud.h" #include "event.h" #include "memory.h" +#include "util.h" #define EVENT_DEBUG(fmt, ...) qemudDebug("EVENT: " fmt, __VA_ARGS__) + +static int virEventInterruptLocked(void); /* State for a single file handle being monitored */ struct virEventHandle { @@ -63,6 +67,9 @@ struct virEventTimeout { /* State for the main event loop */ struct virEventLoop { + pthread_mutex_t lock; + pthread_t leader; + int wakeupfd[2]; int handlesCount; int handlesAlloc; struct virEventHandle *handles; @@ -80,6 +87,16 @@ static int nextWatch = 0; /* Unique ID for the next timer to be registered */ static int nextTimer = 0; +static void virEventLock(void) +{ + pthread_mutex_lock(&eventLoop.lock); +} + +static void virEventUnlock(void) +{ + pthread_mutex_unlock(&eventLoop.lock); +} + /* * Register a callback for monitoring file handle events. * NB, it *must* be safe to call this from within a callback @@ -89,17 +106,23 @@ int virEventAddHandleImpl(int fd, int ev virEventHandleCallback cb, void *opaque, virFreeCallback ff) { + int watch; EVENT_DEBUG("Add handle %d %d %p %p", fd, events, cb, opaque); + virEventLock(); if (eventLoop.handlesCount == eventLoop.handlesAlloc) { EVENT_DEBUG("Used %d handle slots, adding %d more", eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT); if (VIR_REALLOC_N(eventLoop.handles, - (eventLoop.handlesAlloc + EVENT_ALLOC_EXTENT)) < 0) + (eventLoop.handlesAlloc + EVENT_ALLOC_EXTENT)) < 0) { + virEventUnlock(); return -1; + } eventLoop.handlesAlloc += EVENT_ALLOC_EXTENT; } - eventLoop.handles[eventLoop.handlesCount].watch = nextWatch++; + watch = nextWatch++; + + eventLoop.handles[eventLoop.handlesCount].watch = watch; eventLoop.handles[eventLoop.handlesCount].fd = fd; eventLoop.handles[eventLoop.handlesCount].events = virEventHandleTypeToPollEvent(events); @@ -110,11 +133,15 @@ int virEventAddHandleImpl(int fd, int ev eventLoop.handlesCount++; - return nextWatch-1; + virEventInterruptLocked(); + virEventUnlock(); + + return watch; } void virEventUpdateHandleImpl(int watch, int events) { int i; + virEventLock(); for (i = 0 ; i < eventLoop.handlesCount ; i++) { if (eventLoop.handles[i].watch == watch) { eventLoop.handles[i].events = @@ -122,6 +149,8 @@ void virEventUpdateHandleImpl(int watch, break; } } + virEventInterruptLocked(); + virEventUnlock(); } /* @@ -133,6 +162,7 @@ int virEventRemoveHandleImpl(int watch) int virEventRemoveHandleImpl(int watch) { int i; EVENT_DEBUG("Remove handle %d", watch); + virEventLock(); for (i = 0 ; i < eventLoop.handlesCount ; i++) { if (eventLoop.handles[i].deleted) continue; @@ -140,9 +170,12 @@ int virEventRemoveHandleImpl(int watch) if (eventLoop.handles[i].watch == watch) { EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd); eventLoop.handles[i].deleted = 1; + virEventUnlock(); return 0; } } + virEventInterruptLocked(); + virEventUnlock(); return -1; } @@ -157,17 +190,21 @@ int virEventAddTimeoutImpl(int frequency void *opaque, virFreeCallback ff) { struct timeval now; + int ret; EVENT_DEBUG("Adding timer %d with %d ms freq", nextTimer, frequency); if (gettimeofday(&now, NULL) < 0) { return -1; } + virEventLock(); if (eventLoop.timeoutsCount == eventLoop.timeoutsAlloc) { EVENT_DEBUG("Used %d timeout slots, adding %d more", eventLoop.timeoutsAlloc, EVENT_ALLOC_EXTENT); if (VIR_REALLOC_N(eventLoop.timeouts, - (eventLoop.timeoutsAlloc + EVENT_ALLOC_EXTENT)) < 0) + (eventLoop.timeoutsAlloc + EVENT_ALLOC_EXTENT)) < 0) { + virEventUnlock(); return -1; + } eventLoop.timeoutsAlloc += EVENT_ALLOC_EXTENT; } @@ -183,8 +220,10 @@ int virEventAddTimeoutImpl(int frequency (((unsigned long long)now.tv_usec)/1000) : 0; eventLoop.timeoutsCount++; - - return nextTimer-1; + ret = nextTimer-1; + virEventInterruptLocked(); + virEventUnlock(); + return ret; } void virEventUpdateTimeoutImpl(int timer, int frequency) { @@ -195,6 +234,7 @@ void virEventUpdateTimeoutImpl(int timer return; } + virEventLock(); for (i = 0 ; i < eventLoop.timeoutsCount ; i++) { if (eventLoop.timeouts[i].timer == timer) { eventLoop.timeouts[i].frequency = frequency; @@ -205,6 +245,8 @@ void virEventUpdateTimeoutImpl(int timer break; } } + virEventInterruptLocked(); + virEventUnlock(); } /* @@ -216,15 +258,19 @@ int virEventRemoveTimeoutImpl(int timer) int virEventRemoveTimeoutImpl(int timer) { int i; EVENT_DEBUG("Remove timer %d", timer); + virEventLock(); for (i = 0 ; i < eventLoop.timeoutsCount ; i++) { if (eventLoop.timeouts[i].deleted) continue; if (eventLoop.timeouts[i].timer == timer) { eventLoop.timeouts[i].deleted = 1; + virEventUnlock(); return 0; } } + virEventInterruptLocked(); + virEventUnlock(); return -1; } @@ -336,10 +382,15 @@ static int virEventDispatchTimeouts(void continue; if (eventLoop.timeouts[i].expiresAt <= now) { - (eventLoop.timeouts[i].cb)(eventLoop.timeouts[i].timer, - eventLoop.timeouts[i].opaque); + virEventTimeoutCallback cb = eventLoop.timeouts[i].cb; + int timer = eventLoop.timeouts[i].timer; + void *opaque = eventLoop.timeouts[i].opaque; eventLoop.timeouts[i].expiresAt = now + eventLoop.timeouts[i].frequency; + + virEventUnlock(); + (cb)(timer, opaque); + virEventLock(); } } return 0; @@ -356,28 +407,25 @@ static int virEventDispatchTimeouts(void * * Returns 0 upon success, -1 if an error occurred */ -static int virEventDispatchHandles(struct pollfd *fds) { +static int virEventDispatchHandles(int nfds, struct pollfd *fds) { int i; - virEventHandleType hEvents; - /* Save this now - it may be changed during dispatch */ - int nhandles = eventLoop.handlesCount; - for (i = 0 ; i < nhandles ; i++) { + for (i = 0 ; i < nfds ; i++) { if (eventLoop.handles[i].deleted) { EVENT_DEBUG("Skip deleted %d", eventLoop.handles[i].fd); continue; } if (fds[i].revents) { - hEvents = virPollEventToEventHandleType(fds[i].revents); - EVENT_DEBUG("Dispatch %d %d %d %p", - eventLoop.handles[i].watch, - fds[i].fd, fds[i].revents, - eventLoop.handles[i].opaque); - (eventLoop.handles[i].cb)(eventLoop.handles[i].watch, - fds[i].fd, - hEvents, - eventLoop.handles[i].opaque); + virEventHandleCallback cb = eventLoop.handles[i].cb; + void *opaque = eventLoop.handles[i].opaque; + int hEvents = virPollEventToEventHandleType(fds[i].revents); + EVENT_DEBUG("Dispatch %d %d %p", fds[i].fd, + fds[i].revents, eventLoop.handles[i].opaque); + virEventUnlock(); + (cb)(eventLoop.handles[i].watch, + fds[i].fd, hEvents, opaque); + virEventLock(); } } @@ -472,13 +520,20 @@ int virEventRunOnce(void) { struct pollfd *fds; int ret, timeout, nfds; - if ((nfds = virEventMakePollFDs(&fds)) < 0) + virEventLock(); + eventLoop.leader = pthread_self(); + if ((nfds = virEventMakePollFDs(&fds)) < 0) { + virEventUnlock(); return -1; + } if (virEventCalculateTimeout(&timeout) < 0) { VIR_FREE(fds); + virEventUnlock(); return -1; } + + virEventUnlock(); retry: EVENT_DEBUG("Poll on %d handles %p timeout %d", nfds, fds, timeout); @@ -491,25 +546,86 @@ int virEventRunOnce(void) { VIR_FREE(fds); return -1; } + + virEventLock(); if (virEventDispatchTimeouts() < 0) { VIR_FREE(fds); + virEventUnlock(); return -1; } if (ret > 0 && - virEventDispatchHandles(fds) < 0) { + virEventDispatchHandles(nfds, fds) < 0) { VIR_FREE(fds); + virEventUnlock(); return -1; } VIR_FREE(fds); - if (virEventCleanupTimeouts() < 0) + if (virEventCleanupTimeouts() < 0) { + virEventUnlock(); + return -1; + } + + if (virEventCleanupHandles() < 0) { + virEventUnlock(); + return -1; + } + + eventLoop.leader = 0; + virEventUnlock(); + return 0; +} + +static void virEventHandleWakeup(int watch ATTRIBUTE_UNUSED, + int fd, + int events ATTRIBUTE_UNUSED, + void *opaque ATTRIBUTE_UNUSED) +{ + char c; + virEventLock(); + saferead(fd, &c, sizeof(c)); + virEventUnlock(); +} + +int virEventInit(void) +{ + if (pthread_mutex_init(&eventLoop.lock, NULL) != 0) return -1; - if (virEventCleanupHandles() < 0) + if (pipe(eventLoop.wakeupfd) < 0 || + qemudSetNonBlock(eventLoop.wakeupfd[0]) < 0 || + qemudSetNonBlock(eventLoop.wakeupfd[1]) < 0 || + qemudSetCloseExec(eventLoop.wakeupfd[0]) < 0 || + qemudSetCloseExec(eventLoop.wakeupfd[1]) < 0) + return -1; + + if (virEventAddHandleImpl(eventLoop.wakeupfd[0], + VIR_EVENT_HANDLE_READABLE, + virEventHandleWakeup, NULL, NULL) < 0) return -1; return 0; +} + +static int virEventInterruptLocked(void) +{ + char c = '\0'; + if (pthread_self() == eventLoop.leader) + return 0; + + if (safewrite(eventLoop.wakeupfd[1], &c, sizeof(c)) != sizeof(c)) + return -1; + return 0; +} + +int virEventInterrupt(void) +{ + int ret; + virEventLock(); + ret = virEventInterruptLocked(); + virEventUnlock(); + return ret; } int diff --git a/qemud/event.h b/qemud/event.h --- a/qemud/event.h +++ b/qemud/event.h @@ -101,6 +101,13 @@ int virEventRemoveTimeoutImpl(int timer) int virEventRemoveTimeoutImpl(int timer); /** + * virEventInit: Initialize the event loop + * + * returns -1 if initialization failed + */ +int virEventInit(void); + +/** * virEventRunOnce: run a single iteration of the event loop. * * Blocks the caller until at least one file handle has an @@ -116,5 +123,12 @@ virPollEventToEventHandleType(int events virPollEventToEventHandleType(int events); +/** + * virEventInterrupt: wakeup any thread waiting in poll() + * + * return -1 if wakup failed + */ +int virEventInterrupt(void); + #endif /* __VIRTD_EVENT_H__ */ diff --git a/qemud/qemud.c b/qemud/qemud.c --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -296,7 +296,7 @@ qemudDispatchSignalEvent(int watch ATTRI server->shutdown = 1; } -static int qemudSetCloseExec(int fd) { +int qemudSetCloseExec(int fd) { int flags; if ((flags = fcntl(fd, F_GETFD)) < 0) goto error; @@ -311,7 +311,7 @@ static int qemudSetCloseExec(int fd) { } -static int qemudSetNonBlock(int fd) { +int qemudSetNonBlock(int fd) { int flags; if ((flags = fcntl(fd, F_GETFL)) < 0) goto error; @@ -752,6 +752,12 @@ static struct qemud_server *qemudInitial } server->sigread = sigread; + + if (virEventInit() < 0) { + qemudLog(QEMUD_ERR, "%s", _("Failed to initialize event system")); + VIR_FREE(server); + return NULL; + } virInitialize(); diff --git a/qemud/qemud.h b/qemud/qemud.h --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -177,6 +177,9 @@ void qemudLog(int priority, const char * #define qemudDebug(fmt, ...) do {} while(0) #endif +int qemudSetCloseExec(int fd); +int qemudSetNonBlock(int fd); + unsigned int remoteDispatchClientRequest (struct qemud_server *server, struct qemud_client *client); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

Is patch 24/25 missing? I tried git branch thread-safe b726fa0fa5a91eee0af2f996c784d13593cd7616 git checkout thread-safe git am --interactive /home/bguthro/.thunderbird/tiloddj9.default/Mail/Local\ Folders/thread-safe and got through most of these, but it seemed to fail on patch 25: ... Applying PATCH: 22/28: Refactor libvirtd RPC call dispatcher Applying PATCH: 23/28: Replace client linked list with array Applying PATCH: 25/28: Thread safety for libvirtd event loop .dotest/patch:372: trailing whitespace. * .dotest/patch:388: trailing whitespace. * return -1 if wakup failed error: patch failed: qemud/qemud.h:177 error: qemud/qemud.h: patch does not apply Patch failed at 0024. When you have resolved this problem run "git-am --resolved".

please disregard this email...user error. Ben Guthro wrote on 12/01/2008 10:06 AM:
Is patch 24/25 missing?
I tried git branch thread-safe b726fa0fa5a91eee0af2f996c784d13593cd7616 git checkout thread-safe git am --interactive /home/bguthro/.thunderbird/tiloddj9.default/Mail/Local\ Folders/thread-safe
and got through most of these, but it seemed to fail on patch 25:
... Applying PATCH: 22/28: Refactor libvirtd RPC call dispatcher Applying PATCH: 23/28: Replace client linked list with array Applying PATCH: 25/28: Thread safety for libvirtd event loop .dotest/patch:372: trailing whitespace. * .dotest/patch:388: trailing whitespace. * return -1 if wakup failed error: patch failed: qemud/qemud.h:177 error: qemud/qemud.h: patch does not apply Patch failed at 0024. When you have resolved this problem run "git-am --resolved".

On Mon, Dec 01, 2008 at 12:18:24AM +0000, Daniel P. Berrange wrote:
This patch makes the event loop in the libvirtd daemon thread safe, and re-entrant. This allows one thread to add/remove/update timers/file handle watches while other thread is doing the poll. This sometimes requires that we wakeup the main thread to make it see changes to the poll FD list. We use the traditional self-pipe trick for this task. [...] -static int virEventDispatchHandles(struct pollfd *fds) { +static int virEventDispatchHandles(int nfds, struct pollfd *fds) { int i; - virEventHandleType hEvents; - /* Save this now - it may be changed during dispatch */ - int nhandles = eventLoop.handlesCount;
- for (i = 0 ; i < nhandles ; i++) { + for (i = 0 ; i < nfds ; i++) { if (eventLoop.handles[i].deleted) { EVENT_DEBUG("Skip deleted %d", eventLoop.handles[i].fd); continue; }
if (fds[i].revents) { - hEvents = virPollEventToEventHandleType(fds[i].revents); - EVENT_DEBUG("Dispatch %d %d %d %p", - eventLoop.handles[i].watch, - fds[i].fd, fds[i].revents, - eventLoop.handles[i].opaque); - (eventLoop.handles[i].cb)(eventLoop.handles[i].watch, - fds[i].fd, - hEvents, - eventLoop.handles[i].opaque); + virEventHandleCallback cb = eventLoop.handles[i].cb; + void *opaque = eventLoop.handles[i].opaque; + int hEvents = virPollEventToEventHandleType(fds[i].revents); + EVENT_DEBUG("Dispatch %d %d %p", fds[i].fd, + fds[i].revents, eventLoop.handles[i].opaque); + virEventUnlock(); + (cb)(eventLoop.handles[i].watch, + fds[i].fd, hEvents, opaque); + virEventLock(); } }
Hum, if this routine assume we enter it with the event lock and keep it though its lifetime except when dispatching, then I guess it's worth a comment, right ? Is there only one thread which can access or unregister fds, or do we have another lock in place ? Looks okay, but it's far from trivial, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Dec 03, 2008 at 03:48:05PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:18:24AM +0000, Daniel P. Berrange wrote:
This patch makes the event loop in the libvirtd daemon thread safe, and re-entrant. This allows one thread to add/remove/update timers/file handle watches while other thread is doing the poll. This sometimes requires that we wakeup the main thread to make it see changes to the poll FD list. We use the traditional self-pipe trick for this task. [...] -static int virEventDispatchHandles(struct pollfd *fds) { +static int virEventDispatchHandles(int nfds, struct pollfd *fds) { int i; - virEventHandleType hEvents; - /* Save this now - it may be changed during dispatch */ - int nhandles = eventLoop.handlesCount;
- for (i = 0 ; i < nhandles ; i++) { + for (i = 0 ; i < nfds ; i++) { if (eventLoop.handles[i].deleted) { EVENT_DEBUG("Skip deleted %d", eventLoop.handles[i].fd); continue; }
if (fds[i].revents) { - hEvents = virPollEventToEventHandleType(fds[i].revents); - EVENT_DEBUG("Dispatch %d %d %d %p", - eventLoop.handles[i].watch, - fds[i].fd, fds[i].revents, - eventLoop.handles[i].opaque); - (eventLoop.handles[i].cb)(eventLoop.handles[i].watch, - fds[i].fd, - hEvents, - eventLoop.handles[i].opaque); + virEventHandleCallback cb = eventLoop.handles[i].cb; + void *opaque = eventLoop.handles[i].opaque; + int hEvents = virPollEventToEventHandleType(fds[i].revents); + EVENT_DEBUG("Dispatch %d %d %p", fds[i].fd, + fds[i].revents, eventLoop.handles[i].opaque); + virEventUnlock(); + (cb)(eventLoop.handles[i].watch, + fds[i].fd, hEvents, opaque); + virEventLock(); } }
Hum, if this routine assume we enter it with the event lock and keep it though its lifetime except when dispatching, then I guess it's worth a comment, right ? Is there only one thread which can access or unregister fds, or do we have another lock in place ?
The virEventRemoveHandle / RemoveTimeout functions will take the lock, but then merely set the flag eventLoop.handles[i].deleted = 1; This ensures that if another thread is currently in virEventDispatchHandles doing the callback, it won't have the list of handles modified behind its back. Later on, the virEventCleanupHandles() will actually free the memory for all handles with the 'deleted' flag set to 1 when it knows no callbacks are being processed. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch makes the libvirtd daemon itself use mutliple threads. Each individual client is still serialized, but mutliple clients can now be handled in parallel. This introduces a pool of worker threads to handle RPC call processing, while the main thread just runs the event loop and handles network I/O. THREADING.txt | 63 + qemud.c | 231 ++++- qemud.h | 22 remote.c | 1759 ++++++++++++++++++++++--------------------- remote_dispatch_prototypes.h | 936 ++++++++++++++++++++-- remote_generate_stubs.pl | 8 6 files changed, 2004 insertions(+), 1015 deletions(-) Daniel diff --git a/qemud/THREADING.txt b/qemud/THREADING.txt new file mode 100644 --- /dev/null +++ b/qemud/THREADING.txt @@ -0,0 +1,63 @@ + + Threading: the RULES. + ==================== + +If you don't understand this, don't touch the code. Ask for +further advice / explanation on the mailing list first. + + - the top level lock is on 'struct qemud_server'. This must be + held before acquiring any other lock + + - Each 'struct qemud_client' object has a lock. The server lock + must be held before acquiring it. Once the client lock is acquired + the server lock can (optionally) be dropped. + + - The event loop has its own self-contained lock. You can ignore + this as a caller of virEvent APIs. + + +The server lock is only needed / used once the daemon has entered +its main loop, which is the qemudRunLoop() . The initial thread +acquires the lock upon entering this method. + +It immediatelty spawns 'n' worker threads, whose main loop is +the qemudWorker() method. The workers will immediately try to +acquire the server lock, and thus block since its held by the +initial thread. + +When the initial thread enters the poll() call, it drops the +server lock. The worker locks now each wakeup, acquire the +server lock and go into a condition wait on the 'job' condition +variable. The workers are now all 'primed' for incoming RPC +calls. + + + +A file descriptor event now occurrs, causing the initial thread +to exit poll(). It invokes the registered callback associated +with the file descriptors on which the event occurrs. The callbacks +are required to immediately acquire the server lock. + +If the callback is dealing with a client event, it will then +acquire the client lock, and drop the server lock. + +The callback will now handle the I/O event, reading or writing +a RPC message. Once a complete RPC message has been read the +client is marked as being in state QEMUD_MODE_WAIT_DISPATCH, +and the 'job' condition variable is signaled. The callback +now drops the client lock and goes back into the poll() loop +waiting for more I/O events. + +Meanwhile one of the worker threads wakes up from its condition +variable sleep, holding the server lock. It now searches for a +client in state QEMUD_MODE_WAIT_DISPATCH. If it doesn't find +one, it goes back to sleep. If it does find one, then it calls +into the remoteDispatchClientRequest() method de-serialize the +incoming message into an XDR object and invoke the helper method +for the associated RPC call. + +While the helper method is executing, no locks are held on either +the client or server, but the ref count on the 'struct qemud_client' +object is incremented to ensure its not deleted. The helper can +now safely invoke the neccessary libvirt API call. + diff --git a/qemud/qemud.c b/qemud/qemud.c --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -263,9 +263,12 @@ qemudDispatchSignalEvent(int watch ATTRI siginfo_t siginfo; int ret; + pthread_mutex_lock(&server->lock); + if (saferead(server->sigread, &siginfo, sizeof(siginfo)) != sizeof(siginfo)) { qemudLog(QEMUD_ERR, _("Failed to read from signal pipe: %s"), strerror(errno)); + pthread_mutex_unlock(&server->lock); return; } @@ -294,6 +297,8 @@ qemudDispatchSignalEvent(int watch ATTRI if (ret != 0) server->shutdown = 1; + + pthread_mutex_unlock(&server->lock); } int qemudSetCloseExec(int fd) { @@ -748,6 +753,11 @@ static struct qemud_server *qemudInitial if (VIR_ALLOC(server) < 0) { qemudLog(QEMUD_ERR, "%s", _("Failed to allocate struct qemud_server")); + return NULL; + } + + if (pthread_mutex_init(&server->lock, NULL) != 0) { + VIR_FREE(server); return NULL; } @@ -1175,6 +1185,9 @@ static int qemudDispatchServer(struct qe if (VIR_ALLOC(client) < 0) goto cleanup; + if (pthread_mutex_init(&client->lock, NULL) != 0) + goto cleanup; + client->magic = QEMUD_CLIENT_MAGIC; client->fd = fd; client->readonly = sock->readonly; @@ -1248,31 +1261,23 @@ static int qemudDispatchServer(struct qe return 0; cleanup: - if (client->tlssession) gnutls_deinit (client->tlssession); + if (client && + client->tlssession) gnutls_deinit (client->tlssession); close (fd); free (client); return -1; } - - -static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud_client *client) { - int i, n = -1; - for (i = 0 ; i < server->nclients ; i++) { - if (server->clients[i] == client) { - n = i; - break; - } - } - if (n != -1) { - if (n < (server->nclients-1)) - memmove(server->clients + n, - server->clients + n + 1, - server->nclients - (n + 1)); - server->nclients--; - } - +/* + * You must hold lock for at least the client + * We don't free stuff here, merely disconnect the client's + * network socket & resources. + * We keep the libvirt connection open until any async + * jobs have finished, then clean it up elsehwere + */ +static void qemudDispatchClientFailure(struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client) { virEventRemoveHandleImpl(client->watch); /* Deregister event delivery callback */ @@ -1281,18 +1286,63 @@ static void qemudDispatchClientFailure(s virConnectDomainEventDeregister(client->conn, remoteRelayDomainEvent); } - if (client->conn) - virConnectClose(client->conn); - #if HAVE_SASL if (client->saslconn) sasl_dispose(&client->saslconn); free(client->saslUsername); #endif if (client->tlssession) gnutls_deinit (client->tlssession); close(client->fd); - free(client); + client->fd = -1; } + +/* Caller must hold server lock */ +static struct qemud_client *qemudPendingJob(struct qemud_server *server) +{ + int i; + for (i = 0 ; i < server->nclients ; i++) { + pthread_mutex_lock(&server->clients[i]->lock); + if (server->clients[i]->mode == QEMUD_MODE_WAIT_DISPATCH) { + /* Delibrately don't unlock client - caller wants the lock */ + return server->clients[i]; + } + pthread_mutex_unlock(&server->clients[i]->lock); + } + return NULL; +} + +static void *qemudWorker(void *data) +{ + struct qemud_server *server = data; + + while (1) { + struct qemud_client *client; + int len; + pthread_mutex_lock(&server->lock); + while ((client = qemudPendingJob(server)) == NULL) + pthread_cond_wait(&server->job, &server->lock); + pthread_mutex_unlock(&server->lock); + + /* We own a locked client now... */ + client->mode = QEMUD_MODE_IN_DISPATCH; + client->refs++; + + if ((len = remoteDispatchClientRequest (server, client)) == 0) + qemudDispatchClientFailure(server, client); + + /* Set up the output buffer. */ + client->mode = QEMUD_MODE_TX_PACKET; + client->bufferLength = len; + client->bufferOffset = 0; + + if (qemudRegisterClientEvent(server, client, 1) < 0) + qemudDispatchClientFailure(server, client); + + client->refs--; + pthread_mutex_unlock(&client->lock); + pthread_mutex_unlock(&server->lock); + } +} static int qemudClientReadBuf(struct qemud_server *server, @@ -1458,16 +1508,11 @@ static void qemudDispatchClientRead(stru if (client->bufferOffset < client->bufferLength) return; /* Not read enough */ - if ((len = remoteDispatchClientRequest (server, client)) == 0) + client->mode = QEMUD_MODE_WAIT_DISPATCH; + if (qemudRegisterClientEvent(server, client, 1) < 0) qemudDispatchClientFailure(server, client); - /* Set up the output buffer. */ - client->mode = QEMUD_MODE_TX_PACKET; - client->bufferLength = len; - client->bufferOffset = 0; - - if (qemudRegisterClientEvent(server, client, 1) < 0) - qemudDispatchClientFailure(server, client); + pthread_cond_signal(&server->job); break; } @@ -1600,13 +1645,17 @@ qemudDispatchClientWrite(struct qemud_se return; if (client->bufferOffset == client->bufferLength) { - /* Done writing, switch back to receive */ - client->mode = QEMUD_MODE_RX_HEADER; - client->bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN; - client->bufferOffset = 0; + if (client->closing) { + qemudDispatchClientFailure (server, client); + } else { + /* Done writing, switch back to receive */ + client->mode = QEMUD_MODE_RX_HEADER; + client->bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN; + client->bufferOffset = 0; - if (qemudRegisterClientEvent (server, client, 1) < 0) - qemudDispatchClientFailure (server, client); + if (qemudRegisterClientEvent (server, client, 1) < 0) + qemudDispatchClientFailure (server, client); + } } /* Still writing */ break; @@ -1648,6 +1697,8 @@ qemudDispatchClientEvent(int watch, int struct qemud_client *client = NULL; int i; + pthread_mutex_lock(&server->lock); + for (i = 0 ; i < server->nclients ; i++) { if (server->clients[i]->watch == watch) { client = server->clients[i]; @@ -1655,8 +1706,13 @@ qemudDispatchClientEvent(int watch, int } } - if (!client) + if (!client) { + pthread_mutex_unlock(&server->lock); return; + } + + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); if (client->fd != fd) return; @@ -1667,11 +1723,12 @@ qemudDispatchClientEvent(int watch, int qemudDispatchClientRead(server, client); else qemudDispatchClientFailure(server, client); + pthread_mutex_unlock(&client->lock); } static int qemudRegisterClientEvent(struct qemud_server *server, struct qemud_client *client, - int removeFirst) { + int update) { int mode; switch (client->mode) { case QEMUD_MODE_TLS_HANDSHAKE: @@ -1690,20 +1747,23 @@ static int qemudRegisterClientEvent(stru mode = VIR_EVENT_HANDLE_WRITABLE; break; + case QEMUD_MODE_WAIT_DISPATCH: + mode = 0; + break; + default: return -1; } - if (removeFirst) - if (virEventRemoveHandleImpl(client->watch) < 0) + if (update) { + virEventUpdateHandleImpl(client->watch, mode); + } else { + if ((client->watch = virEventAddHandleImpl(client->fd, + mode, + qemudDispatchClientEvent, + server, NULL)) < 0) return -1; - - if ((client->watch = virEventAddHandleImpl(client->fd, - mode | VIR_EVENT_HANDLE_ERROR | - VIR_EVENT_HANDLE_HANGUP, - qemudDispatchClientEvent, - server, NULL)) < 0) - return -1; + } return 0; } @@ -1711,7 +1771,11 @@ static void static void qemudDispatchServerEvent(int watch, int fd, int events, void *opaque) { struct qemud_server *server = (struct qemud_server *)opaque; - struct qemud_socket *sock = server->sockets; + struct qemud_socket *sock; + + pthread_mutex_lock(&server->lock); + + sock = server->sockets; while (sock) { if (sock->watch == watch) @@ -1720,14 +1784,10 @@ qemudDispatchServerEvent(int watch, int sock = sock->next; } - if (!sock) - return; + if (sock && sock->fd == fd && events) + qemudDispatchServer(server, sock); - if (sock->fd != fd) - return; - - if (events) - qemudDispatchServer(server, sock); + pthread_mutex_unlock(&server->lock); } @@ -1761,6 +1821,26 @@ static void qemudInactiveTimer(int timer static int qemudRunLoop(struct qemud_server *server) { int timerid = -1; + int ret = -1, i; + + pthread_mutex_lock(&server->lock); + + server->nworkers = 10; + if (VIR_ALLOC_N(server->workers, server->nworkers) < 0) { + qemudLog(QEMUD_ERR, "%s", _("Failed to allocate workers")); + return -1; + } + + for (i = 0 ; i < server->nworkers ; i++) { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, 1); + + pthread_create(&server->workers[i], + &attr, + qemudWorker, + server); + } for (;;) { /* A shutdown timeout is specified, so check @@ -1774,8 +1854,31 @@ static int qemudRunLoop(struct qemud_ser qemudDebug("Scheduling shutdown timer %d", timerid); } + pthread_mutex_unlock(&server->lock); if (qemudOneLoop() < 0) break; + pthread_mutex_lock(&server->lock); + + reprocess: + for (i = 0 ; i < server->nclients ; i++) { + int inactive; + pthread_mutex_lock(&server->clients[i]->lock); + inactive = server->clients[i]->fd == -1 + && server->clients[i]->refs == 0; + pthread_mutex_unlock(&server->clients[i]->lock); + if (inactive) { + if (server->clients[i]->conn) + virConnectClose(server->clients[i]->conn); + VIR_FREE(server->clients[i]); + server->nclients--; + if (i < server->nclients) { + memmove(server->clients + i, + server->clients + i + 1, + server->nclients - i); + goto reprocess; + } + } + } /* Unregister any timeout that's active, since we * just had an event processed @@ -1786,11 +1889,21 @@ static int qemudRunLoop(struct qemud_ser timerid = -1; } - if (server->shutdown) - return 0; + if (server->shutdown) { + ret = 0; + break; + } } - return -1; + for (i = 0 ; i < server->nworkers ; i++) { + pthread_t thread = server->workers[i]; + pthread_mutex_unlock(&server->lock); + pthread_join(thread, NULL); + pthread_mutex_lock(&server->lock); + } + + pthread_mutex_unlock(&server->lock); + return ret; } static void qemudCleanup(struct qemud_server *server) { diff --git a/qemud/qemud.h b/qemud/qemud.h --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -72,10 +72,12 @@ typedef enum { enum qemud_mode { - QEMUD_MODE_RX_HEADER, - QEMUD_MODE_RX_PAYLOAD, - QEMUD_MODE_TX_PACKET, - QEMUD_MODE_TLS_HANDSHAKE, + QEMUD_MODE_RX_HEADER, /* Receiving the fixed length RPC header data */ + QEMUD_MODE_RX_PAYLOAD, /* Receiving the variable length RPC payload data */ + QEMUD_MODE_WAIT_DISPATCH, /* Message received, waiting for worker to process */ + QEMUD_MODE_IN_DISPATCH, /* RPC call being processed */ + QEMUD_MODE_TX_PACKET, /* Transmitting reply to RPC call */ + QEMUD_MODE_TLS_HANDSHAKE, /* Performing TLS handshake */ }; /* Whether we're passing reads & writes through a sasl SSF */ @@ -93,11 +95,14 @@ enum qemud_sock_type { /* Stores the per-client connection state */ struct qemud_client { + PTHREAD_MUTEX_T(lock); + int magic; int fd; int watch; - int readonly; + int readonly:1; + int closing:1; enum qemud_mode mode; struct sockaddr_storage addr; @@ -130,6 +135,7 @@ struct qemud_client { * called, it will be set back to NULL if that succeeds. */ virConnectPtr conn; + int refs; /* back-pointer to our server */ struct qemud_server *server; @@ -150,10 +156,16 @@ struct qemud_socket { /* Main server state */ struct qemud_server { + pthread_mutex_t lock; + pthread_cond_t job; + + int nworkers; + pthread_t *workers; int nsockets; struct qemud_socket *sockets; int nclients; struct qemud_client **clients; + int sigread; char logDir[PATH_MAX]; unsigned int shutdown : 1; diff --git a/qemud/remote.c b/qemud/remote.c --- a/qemud/remote.c +++ b/qemud/remote.c @@ -79,8 +79,22 @@ typedef union { } dispatch_ret; +/** + * When the RPC handler is called: + * + * - Server object is unlocked + * - Client object is unlocked + * + * Both must be locked before use. Server lock must + * be held before attempting to lock client. + * + * Without any locking, it is safe to use: + * + * 'conn', 'rerr', 'args and 'ret' + */ typedef int (*dispatch_fn) (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn, remote_error *err, dispatch_args *args, dispatch_ret *ret); @@ -202,6 +216,9 @@ remoteDispatchConnError (remote_error *r /* This function gets called from qemud when it detects an incoming * remote protocol message. At this point, client->buffer contains * the full call message (including length word which we skip). + * + * Server object is unlocked + * Client object is locked */ unsigned int remoteDispatchClientRequest (struct qemud_server *server, @@ -214,6 +231,7 @@ remoteDispatchClientRequest (struct qemu dispatch_ret ret; const dispatch_data *data = NULL; int rv = -1, len; + virConnectPtr conn = NULL; memset(&args, 0, sizeof args); memset(&ret, 0, sizeof ret); @@ -283,7 +301,25 @@ remoteDispatchClientRequest (struct qemu } /* Call function. */ - rv = (data->fn)(server, client, &rerr, &args, &ret); + conn = client->conn; + pthread_mutex_unlock(&client->lock); + + /* + * When the RPC handler is called: + * + * - Server object is unlocked + * - Client object is unlocked + * + * Without locking, it is safe to use: + * + * 'conn', 'rerr', 'args and 'ret' + */ + rv = (data->fn)(server, client, conn, &rerr, &args, &ret); + + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); + xdr_free (data->args_filter, (char*)&args); rpc_error: @@ -362,19 +398,24 @@ int remoteRelayDomainEvent (virConnectPt /*----- Functions. -----*/ static int -remoteDispatchOpen (struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchOpen (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn, remote_error *rerr, struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED) { const char *name; - int flags; + int flags, rc; /* Already opened? */ - if (client->conn) { + if (conn) { remoteDispatchFormatError (rerr, "%s", _("connection already open")); return -1; } + + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); name = args->name ? *args->name : NULL; @@ -389,12 +430,12 @@ remoteDispatchOpen (struct qemud_server ? virConnectOpenReadOnly (name) : virConnectOpen (name); - if (client->conn == NULL) { + if (client->conn == NULL) remoteDispatchConnError(rerr, NULL); - return -1; - } - - return 0; + + rc = client->conn ? 0 : -1; + pthread_mutex_unlock(&client->lock); + return rc; } #define CHECK_CONN(client) \ @@ -405,32 +446,32 @@ remoteDispatchOpen (struct qemud_server static int remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_error *rerr, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn ATTRIBUTE_UNUSED, + remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED) { - CHECK_CONN(client); - - if (virConnectClose (client->conn) < 0) { - remoteDispatchConnError(rerr, NULL); - return -1; - } - + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); + + client->closing = 1; + + pthread_mutex_unlock(&client->lock); return 0; } static int remoteDispatchSupportsFeature (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_supports_feature_args *args, remote_supports_feature_ret *ret) { - CHECK_CONN(client); - - ret->supported = virDrvSupportsFeature (client->conn, args->feature); + ret->supported = virDrvSupportsFeature (conn, args->feature); if (ret->supported == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -439,16 +480,16 @@ remoteDispatchSupportsFeature (struct qe static int remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret) { const char *type; - CHECK_CONN(client); - - type = virConnectGetType (client->conn); + + type = virConnectGetType (conn); if (type == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -466,16 +507,16 @@ remoteDispatchGetType (struct qemud_serv static int remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_version_ret *ret) { unsigned long hvVer; - CHECK_CONN(client); - - if (virConnectGetVersion (client->conn, &hvVer) == -1) { - remoteDispatchConnError(rerr, client->conn); + + if (virConnectGetVersion (conn, &hvVer) == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -485,17 +526,17 @@ remoteDispatchGetVersion (struct qemud_s static int remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_hostname_ret *ret) { char *hostname; - CHECK_CONN(client); - - hostname = virConnectGetHostname (client->conn); + + hostname = virConnectGetHostname (conn); if (hostname == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -505,7 +546,8 @@ remoteDispatchGetHostname (struct qemud_ static int remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_uri_ret *ret) @@ -513,9 +555,9 @@ remoteDispatchGetUri (struct qemud_serve char *uri; CHECK_CONN(client); - uri = virConnectGetURI (client->conn); + uri = virConnectGetURI (conn); if (uri == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -525,18 +567,18 @@ remoteDispatchGetUri (struct qemud_serve static int remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret) { char *type; - CHECK_CONN(client); type = args->type ? *args->type : NULL; - ret->max_vcpus = virConnectGetMaxVcpus (client->conn, type); + ret->max_vcpus = virConnectGetMaxVcpus (conn, type); if (ret->max_vcpus == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -545,16 +587,16 @@ remoteDispatchGetMaxVcpus (struct qemud_ static int remoteDispatchNodeGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_node_get_info_ret *ret) { virNodeInfo info; - CHECK_CONN(client); - - if (virNodeGetInfo (client->conn, &info) == -1) { - remoteDispatchConnError(rerr, client->conn); + + if (virNodeGetInfo (conn, &info) == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -572,17 +614,17 @@ remoteDispatchNodeGetInfo (struct qemud_ static int remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_get_capabilities_ret *ret) { char *caps; - CHECK_CONN(client); - - caps = virConnectGetCapabilities (client->conn); + + caps = virConnectGetCapabilities (conn); if (caps == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -592,12 +634,12 @@ remoteDispatchGetCapabilities (struct qe static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret) { - CHECK_CONN(client); if (args->maxCells > REMOTE_NODE_MAX_CELLS) { remoteDispatchFormatError (rerr, @@ -611,13 +653,13 @@ remoteDispatchNodeGetCellsFreeMemory (st return -1; } - ret->freeMems.freeMems_len = virNodeGetCellsFreeMemory(client->conn, + ret->freeMems.freeMems_len = virNodeGetCellsFreeMemory(conn, (unsigned long long *)ret->freeMems.freeMems_val, args->startCell, args->maxCells); if (ret->freeMems.freeMems_len == 0) { VIR_FREE(ret->freeMems.freeMems_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -627,17 +669,17 @@ remoteDispatchNodeGetCellsFreeMemory (st static int remoteDispatchNodeGetFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_node_get_free_memory_ret *ret) { unsigned long long freeMem; - CHECK_CONN(client); - - freeMem = virNodeGetFreeMemory(client->conn); + + freeMem = virNodeGetFreeMemory(conn); if (freeMem == 0) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } ret->freeMem = freeMem; @@ -647,7 +689,8 @@ remoteDispatchNodeGetFreeMemory (struct static int remoteDispatchDomainGetSchedulerType (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret) @@ -655,18 +698,17 @@ remoteDispatchDomainGetSchedulerType (st virDomainPtr dom; char *type; int nparams; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } type = virDomainGetSchedulerType (dom, &nparams); if (type == NULL) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -678,7 +720,8 @@ remoteDispatchDomainGetSchedulerType (st static int remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret) @@ -686,7 +729,6 @@ remoteDispatchDomainGetSchedulerParamete virDomainPtr dom; virSchedParameterPtr params; int i, r, nparams; - CHECK_CONN(client); nparams = args->nparams; @@ -699,10 +741,10 @@ remoteDispatchDomainGetSchedulerParamete return -1; } - dom = get_nonnull_domain (client->conn, args->dom); + dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { VIR_FREE(params); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -710,7 +752,7 @@ remoteDispatchDomainGetSchedulerParamete if (r == -1) { virDomainFree(dom); VIR_FREE(params); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -761,7 +803,8 @@ cleanup: static int remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_set_scheduler_parameters_args *args, void *ret ATTRIBUTE_UNUSED) @@ -769,7 +812,6 @@ remoteDispatchDomainSetSchedulerParamete virDomainPtr dom; int i, r, nparams; virSchedParameterPtr params; - CHECK_CONN(client); nparams = args->params.params_len; @@ -804,10 +846,10 @@ remoteDispatchDomainSetSchedulerParamete } } - dom = get_nonnull_domain (client->conn, args->dom); + dom = get_nonnull_domain (conn, args->dom); if (dom == NULL) { VIR_FREE(params); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -815,7 +857,7 @@ remoteDispatchDomainSetSchedulerParamete virDomainFree(dom); VIR_FREE(params); if (r == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -824,7 +866,8 @@ remoteDispatchDomainSetSchedulerParamete static int remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret) @@ -832,18 +875,17 @@ remoteDispatchDomainBlockStats (struct q virDomainPtr dom; char *path; struct _virDomainBlockStats stats; - CHECK_CONN (client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } path = args->path; if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) { virDomainFree (dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree (dom); @@ -859,7 +901,8 @@ remoteDispatchDomainBlockStats (struct q static int remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret) @@ -867,18 +910,17 @@ remoteDispatchDomainInterfaceStats (stru virDomainPtr dom; char *path; struct _virDomainInterfaceStats stats; - CHECK_CONN (client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } path = args->path; if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1) { virDomainFree (dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree (dom); @@ -897,7 +939,8 @@ remoteDispatchDomainInterfaceStats (stru static int remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret) @@ -907,11 +950,10 @@ remoteDispatchDomainBlockPeek (struct qe unsigned long long offset; size_t size; unsigned int flags; - CHECK_CONN (client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } path = args->path; @@ -937,7 +979,7 @@ remoteDispatchDomainBlockPeek (struct qe ret->buffer.buffer_val, flags) == -1) { /* free (ret->buffer.buffer_val); - caller frees */ virDomainFree (dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree (dom); @@ -947,7 +989,8 @@ remoteDispatchDomainBlockPeek (struct qe static int remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_memory_peek_args *args, remote_domain_memory_peek_ret *ret) @@ -956,11 +999,10 @@ remoteDispatchDomainMemoryPeek (struct q unsigned long long offset; size_t size; unsigned int flags; - CHECK_CONN (client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } offset = args->offset; @@ -985,7 +1027,7 @@ remoteDispatchDomainMemoryPeek (struct q ret->buffer.buffer_val, flags) == -1) { /* free (ret->buffer.buffer_val); - caller frees */ virDomainFree (dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree (dom); @@ -995,23 +1037,23 @@ remoteDispatchDomainMemoryPeek (struct q static int remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_attach_device_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainAttachDevice (dom, args->xml) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1020,23 +1062,23 @@ remoteDispatchDomainAttachDevice (struct static int remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_create_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainCreate (dom) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1045,17 +1087,17 @@ remoteDispatchDomainCreate (struct qemud static int remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_error *rerr, - remote_domain_create_xml_args *args, - remote_domain_create_xml_ret *ret) -{ - virDomainPtr dom; - CHECK_CONN(client); - - dom = virDomainCreateXML (client->conn, args->xml_desc, args->flags); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_domain_create_xml_args *args, + remote_domain_create_xml_ret *ret) +{ + virDomainPtr dom; + + dom = virDomainCreateXML (conn, args->xml_desc, args->flags); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1067,17 +1109,17 @@ remoteDispatchDomainCreateXml (struct qe static int remoteDispatchDomainDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_define_xml_args *args, remote_domain_define_xml_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = virDomainDefineXML (client->conn, args->xml); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = virDomainDefineXML (conn, args->xml); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1089,23 +1131,23 @@ remoteDispatchDomainDefineXml (struct qe static int remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_destroy_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainDestroy (dom) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1114,23 +1156,23 @@ remoteDispatchDomainDestroy (struct qemu static int remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_detach_device_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainDetachDevice (dom, args->xml) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -1140,17 +1182,17 @@ remoteDispatchDomainDetachDevice (struct static int remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_dump_xml_args *args, remote_domain_dump_xml_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1158,7 +1200,7 @@ remoteDispatchDomainDumpXml (struct qemu ret->xml = virDomainGetXMLDesc (dom, args->flags); if (!ret->xml) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1167,23 +1209,23 @@ remoteDispatchDomainDumpXml (struct qemu static int remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_autostart_args *args, remote_domain_get_autostart_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainGetAutostart (dom, &ret->autostart) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1192,24 +1234,24 @@ remoteDispatchDomainGetAutostart (struct static int remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_info_args *args, remote_domain_get_info_ret *ret) { virDomainPtr dom; virDomainInfo info; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainGetInfo (dom, &info) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -1226,24 +1268,24 @@ remoteDispatchDomainGetInfo (struct qemu static int remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_max_memory_args *args, remote_domain_get_max_memory_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } ret->memory = virDomainGetMaxMemory (dom); if (ret->memory == 0) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1252,24 +1294,24 @@ remoteDispatchDomainGetMaxMemory (struct static int remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_max_vcpus_args *args, remote_domain_get_max_vcpus_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } ret->num = virDomainGetMaxVcpus (dom); if (ret->num == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1278,17 +1320,17 @@ remoteDispatchDomainGetMaxVcpus (struct static int remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1296,7 +1338,7 @@ remoteDispatchDomainGetOsType (struct qe ret->type = virDomainGetOSType (dom); if (ret->type == NULL) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1305,7 +1347,8 @@ remoteDispatchDomainGetOsType (struct qe static int remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret) @@ -1314,11 +1357,10 @@ remoteDispatchDomainGetVcpus (struct qem virVcpuInfoPtr info = NULL; unsigned char *cpumaps = NULL; int info_len, i; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1347,7 +1389,7 @@ remoteDispatchDomainGetVcpus (struct qem VIR_FREE(info); VIR_FREE(cpumaps); virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -1384,10 +1426,119 @@ oom: static int remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_migrate_prepare_args *args, remote_domain_migrate_prepare_ret *ret) +{ + int r; + char *cookie = NULL; + int cookielen = 0; + char *uri_in; + char **uri_out; + char *dname; + + uri_in = args->uri_in == NULL ? NULL : *args->uri_in; + dname = args->dname == NULL ? NULL : *args->dname; + + /* Wacky world of XDR ... */ + if (VIR_ALLOC(uri_out) < 0) { + remoteDispatchOOMError(rerr); + return -1; + } + + r = virDomainMigratePrepare (conn, &cookie, &cookielen, + uri_in, uri_out, + args->flags, dname, args->resource); + if (r == -1) { + VIR_FREE(uri_out); + remoteDispatchConnError(rerr, conn); + return -1; + } + + /* remoteDispatchClientRequest will free cookie, uri_out and + * the string if there is one. + */ + ret->cookie.cookie_len = cookielen; + ret->cookie.cookie_val = cookie; + if (*uri_out == NULL) { + ret->uri_out = NULL; + VIR_FREE(uri_out); + } else { + ret->uri_out = uri_out; + } + + return 0; +} + +static int +remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_domain_migrate_perform_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + int r; + virDomainPtr dom; + char *dname; + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + dname = args->dname == NULL ? NULL : *args->dname; + + r = virDomainMigratePerform (dom, + args->cookie.cookie_val, + args->cookie.cookie_len, + args->uri, + args->flags, dname, args->resource); + virDomainFree (dom); + if (r == -1) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + return 0; +} + +static int +remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_domain_migrate_finish_args *args, + remote_domain_migrate_finish_ret *ret) +{ + virDomainPtr ddom; + CHECK_CONN (client); + + ddom = virDomainMigrateFinish (conn, args->dname, + args->cookie.cookie_val, + args->cookie.cookie_len, + args->uri, + args->flags); + if (ddom == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + make_nonnull_domain (&ret->ddom, ddom); + virDomainFree (ddom); + return 0; +} + +static int +remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_domain_migrate_prepare2_args *args, + remote_domain_migrate_prepare2_ret *ret) { int r; char *cookie = NULL; @@ -1406,119 +1557,12 @@ remoteDispatchDomainMigratePrepare (stru return -1; } - r = virDomainMigratePrepare (client->conn, &cookie, &cookielen, - uri_in, uri_out, - args->flags, dname, args->resource); - if (r == -1) { - VIR_FREE(uri_out); - remoteDispatchConnError(rerr, client->conn); - return -1; - } - - /* remoteDispatchClientRequest will free cookie, uri_out and - * the string if there is one. - */ - ret->cookie.cookie_len = cookielen; - ret->cookie.cookie_val = cookie; - if (*uri_out == NULL) { - ret->uri_out = NULL; - VIR_FREE(uri_out); - } else { - ret->uri_out = uri_out; - } - - return 0; -} - -static int -remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_error *rerr, - remote_domain_migrate_perform_args *args, - void *ret ATTRIBUTE_UNUSED) -{ - int r; - virDomainPtr dom; - char *dname; - CHECK_CONN (client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); - return -1; - } - - dname = args->dname == NULL ? NULL : *args->dname; - - r = virDomainMigratePerform (dom, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags, dname, args->resource); - virDomainFree (dom); - if (r == -1) { - remoteDispatchConnError(rerr, client->conn); - return -1; - } - - return 0; -} - -static int -remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_error *rerr, - remote_domain_migrate_finish_args *args, - remote_domain_migrate_finish_ret *ret) -{ - virDomainPtr ddom; - CHECK_CONN (client); - - ddom = virDomainMigrateFinish (client->conn, args->dname, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags); - if (ddom == NULL) { - remoteDispatchConnError(rerr, client->conn); - return -1; - } - - make_nonnull_domain (&ret->ddom, ddom); - virDomainFree (ddom); - return 0; -} - -static int -remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, - remote_error *rerr, - remote_domain_migrate_prepare2_args *args, - remote_domain_migrate_prepare2_ret *ret) -{ - int r; - char *cookie = NULL; - int cookielen = 0; - char *uri_in; - char **uri_out; - char *dname; - CHECK_CONN (client); - - uri_in = args->uri_in == NULL ? NULL : *args->uri_in; - dname = args->dname == NULL ? NULL : *args->dname; - - /* Wacky world of XDR ... */ - if (VIR_ALLOC(uri_out) < 0) { - remoteDispatchOOMError(rerr); - return -1; - } - - r = virDomainMigratePrepare2 (client->conn, &cookie, &cookielen, + r = virDomainMigratePrepare2 (conn, &cookie, &cookielen, uri_in, uri_out, args->flags, dname, args->resource, args->dom_xml); if (r == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -1534,7 +1578,8 @@ remoteDispatchDomainMigratePrepare2 (str static int remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret) @@ -1542,14 +1587,14 @@ remoteDispatchDomainMigrateFinish2 (stru virDomainPtr ddom; CHECK_CONN (client); - ddom = virDomainMigrateFinish2 (client->conn, args->dname, + ddom = virDomainMigrateFinish2 (conn, args->dname, args->cookie.cookie_val, args->cookie.cookie_len, args->uri, args->flags, args->retcode); if (ddom == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -1560,12 +1605,12 @@ remoteDispatchDomainMigrateFinish2 (stru static int remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_list_defined_domains_args *args, remote_list_defined_domains_ret *ret) { - CHECK_CONN(client); if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -1580,11 +1625,11 @@ remoteDispatchListDefinedDomains (struct } ret->names.names_len = - virConnectListDefinedDomains (client->conn, + virConnectListDefinedDomains (conn, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -1593,17 +1638,17 @@ remoteDispatchListDefinedDomains (struct static int remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = virDomainLookupByID (client->conn, args->id); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = virDomainLookupByID (conn, args->id); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1614,17 +1659,17 @@ remoteDispatchDomainLookupById (struct q static int remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = virDomainLookupByName (client->conn, args->name); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = virDomainLookupByName (conn, args->name); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1635,17 +1680,17 @@ remoteDispatchDomainLookupByName (struct static int remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret) { virDomainPtr dom; - CHECK_CONN(client); - - dom = virDomainLookupByUUID (client->conn, (unsigned char *) args->uuid); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = virDomainLookupByUUID (conn, (unsigned char *) args->uuid); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1656,16 +1701,16 @@ remoteDispatchDomainLookupByUuid (struct static int remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_defined_domains_ret *ret) { - CHECK_CONN(client); - - ret->num = virConnectNumOfDefinedDomains (client->conn); - if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + + ret->num = virConnectNumOfDefinedDomains (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1674,18 +1719,18 @@ remoteDispatchNumOfDefinedDomains (struc static int remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_pin_vcpu_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; int rv; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1700,7 +1745,7 @@ remoteDispatchDomainPinVcpu (struct qemu args->cpumap.cpumap_len); if (rv == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1709,23 +1754,23 @@ remoteDispatchDomainPinVcpu (struct qemu static int remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_reboot_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainReboot (dom, args->flags) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1734,15 +1779,15 @@ remoteDispatchDomainReboot (struct qemud static int remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_restore_args *args, void *ret ATTRIBUTE_UNUSED) { - CHECK_CONN(client); - - if (virDomainRestore (client->conn, args->from) == -1) { - remoteDispatchConnError(rerr, client->conn); + + if (virDomainRestore (conn, args->from) == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -1751,23 +1796,23 @@ remoteDispatchDomainRestore (struct qemu static int remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_resume_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainResume (dom) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1776,23 +1821,23 @@ remoteDispatchDomainResume (struct qemud static int remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_save_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainSave (dom, args->to) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1801,23 +1846,23 @@ remoteDispatchDomainSave (struct qemud_s static int remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_core_dump_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainCoreDump (dom, args->to, args->flags) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1826,23 +1871,23 @@ remoteDispatchDomainCoreDump (struct qem static int remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_set_autostart_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainSetAutostart (dom, args->autostart) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1851,23 +1896,23 @@ remoteDispatchDomainSetAutostart (struct static int remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_set_max_memory_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainSetMaxMemory (dom, args->memory) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1876,23 +1921,23 @@ remoteDispatchDomainSetMaxMemory (struct static int remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_set_memory_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainSetMemory (dom, args->memory) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1901,23 +1946,23 @@ remoteDispatchDomainSetMemory (struct qe static int remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_set_vcpus_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainSetVcpus (dom, args->nvcpus) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1926,23 +1971,23 @@ remoteDispatchDomainSetVcpus (struct qem static int remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_shutdown_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainShutdown (dom) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1951,23 +1996,23 @@ remoteDispatchDomainShutdown (struct qem static int remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_suspend_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainSuspend (dom) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -1976,23 +2021,23 @@ remoteDispatchDomainSuspend (struct qemu static int remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_domain_undefine_args *args, void *ret ATTRIBUTE_UNUSED) { virDomainPtr dom; - CHECK_CONN(client); - - dom = get_nonnull_domain (client->conn, args->dom); - if (dom == NULL) { - remoteDispatchConnError(rerr, client->conn); + + dom = get_nonnull_domain (conn, args->dom); + if (dom == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virDomainUndefine (dom) == -1) { virDomainFree(dom); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virDomainFree(dom); @@ -2001,12 +2046,12 @@ remoteDispatchDomainUndefine (struct qem static int remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_list_defined_networks_args *args, remote_list_defined_networks_ret *ret) { - CHECK_CONN(client); if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -2021,11 +2066,11 @@ remoteDispatchListDefinedNetworks (struc } ret->names.names_len = - virConnectListDefinedNetworks (client->conn, + virConnectListDefinedNetworks (conn, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -2034,12 +2079,12 @@ remoteDispatchListDefinedNetworks (struc static int remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_list_domains_args *args, remote_list_domains_ret *ret) { - CHECK_CONN(client); if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -2053,11 +2098,11 @@ remoteDispatchListDomains (struct qemud_ return -1; } - ret->ids.ids_len = virConnectListDomains (client->conn, + ret->ids.ids_len = virConnectListDomains (conn, ret->ids.ids_val, args->maxids); if (ret->ids.ids_len == -1) { VIR_FREE(ret->ids.ids_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -2066,12 +2111,12 @@ remoteDispatchListDomains (struct qemud_ static int remoteDispatchListNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_list_networks_args *args, remote_list_networks_ret *ret) { - CHECK_CONN(client); if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -2086,11 +2131,11 @@ remoteDispatchListNetworks (struct qemud } ret->names.names_len = - virConnectListNetworks (client->conn, + virConnectListNetworks (conn, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_len); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -2099,23 +2144,23 @@ remoteDispatchListNetworks (struct qemud static int remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_create_args *args, void *ret ATTRIBUTE_UNUSED) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virNetworkCreate (net) == -1) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2124,17 +2169,17 @@ remoteDispatchNetworkCreate (struct qemu static int remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = virNetworkCreateXML (client->conn, args->xml); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = virNetworkCreateXML (conn, args->xml); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2145,17 +2190,17 @@ remoteDispatchNetworkCreateXml (struct q static int remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_define_xml_args *args, remote_network_define_xml_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = virNetworkDefineXML (client->conn, args->xml); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = virNetworkDefineXML (conn, args->xml); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2166,23 +2211,23 @@ remoteDispatchNetworkDefineXml (struct q static int remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_destroy_args *args, void *ret ATTRIBUTE_UNUSED) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virNetworkDestroy (net) == -1) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2191,17 +2236,17 @@ remoteDispatchNetworkDestroy (struct qem static int remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_dump_xml_args *args, remote_network_dump_xml_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2209,7 +2254,7 @@ remoteDispatchNetworkDumpXml (struct qem ret->xml = virNetworkGetXMLDesc (net, args->flags); if (!ret->xml) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2218,23 +2263,23 @@ remoteDispatchNetworkDumpXml (struct qem static int remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_get_autostart_args *args, remote_network_get_autostart_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virNetworkGetAutostart (net, &ret->autostart) == -1) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2243,17 +2288,17 @@ remoteDispatchNetworkGetAutostart (struc static int remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_get_bridge_name_args *args, remote_network_get_bridge_name_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2261,7 +2306,7 @@ remoteDispatchNetworkGetBridgeName (stru ret->name = virNetworkGetBridgeName (net); if (!ret->name) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2270,17 +2315,17 @@ remoteDispatchNetworkGetBridgeName (stru static int remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = virNetworkLookupByName (client->conn, args->name); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = virNetworkLookupByName (conn, args->name); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2291,17 +2336,17 @@ remoteDispatchNetworkLookupByName (struc static int remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_lookup_by_uuid_args *args, remote_network_lookup_by_uuid_ret *ret) { virNetworkPtr net; - CHECK_CONN(client); - - net = virNetworkLookupByUUID (client->conn, (unsigned char *) args->uuid); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = virNetworkLookupByUUID (conn, (unsigned char *) args->uuid); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2312,23 +2357,23 @@ remoteDispatchNetworkLookupByUuid (struc static int remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_set_autostart_args *args, void *ret ATTRIBUTE_UNUSED) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virNetworkSetAutostart (net, args->autostart) == -1) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2337,23 +2382,23 @@ remoteDispatchNetworkSetAutostart (struc static int remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_network_undefine_args *args, void *ret ATTRIBUTE_UNUSED) { virNetworkPtr net; - CHECK_CONN(client); - - net = get_nonnull_network (client->conn, args->net); - if (net == NULL) { - remoteDispatchConnError(rerr, client->conn); + + net = get_nonnull_network (conn, args->net); + if (net == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virNetworkUndefine (net) == -1) { virNetworkFree(net); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virNetworkFree(net); @@ -2362,16 +2407,16 @@ remoteDispatchNetworkUndefine (struct qe static int remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_defined_networks_ret *ret) { - CHECK_CONN(client); - - ret->num = virConnectNumOfDefinedNetworks (client->conn); - if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + + ret->num = virConnectNumOfDefinedNetworks (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2380,16 +2425,16 @@ remoteDispatchNumOfDefinedNetworks (stru static int remoteDispatchNumOfDomains (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_domains_ret *ret) { - CHECK_CONN(client); - - ret->num = virConnectNumOfDomains (client->conn); - if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + + ret->num = virConnectNumOfDomains (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -2398,26 +2443,27 @@ remoteDispatchNumOfDomains (struct qemud static int remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_networks_ret *ret) { - CHECK_CONN(client); - - ret->num = virConnectNumOfNetworks (client->conn); - if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); - return -1; - } - - return 0; -} - - -static int -remoteDispatchAuthList (struct qemud_server *server ATTRIBUTE_UNUSED, + + ret->num = virConnectNumOfNetworks (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + return 0; +} + + +static int +remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_list_ret *ret) @@ -2427,7 +2473,12 @@ remoteDispatchAuthList (struct qemud_ser remoteDispatchOOMError(rerr); return -1; } + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); ret->types.types_val[0] = client->auth; + pthread_mutex_unlock(&client->lock); + return 0; } @@ -2471,8 +2522,9 @@ static char *addrToString(remote_error * * XXX callbacks for stuff like password verification ? */ static int -remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_sasl_init_ret *ret) @@ -2483,13 +2535,16 @@ remoteDispatchAuthSaslInit (struct qemud struct sockaddr_storage sa; socklen_t salen; char *localAddr, *remoteAddr; + + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); REMOTE_DEBUG("Initialize SASL auth %d", client->fd); if (client->auth != REMOTE_AUTH_SASL || client->saslconn != NULL) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid SASL init request")); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } /* Get local address in form IPADDR:PORT */ @@ -2498,10 +2553,10 @@ remoteDispatchAuthSaslInit (struct qemud remoteDispatchFormatError(rerr, _("failed to get sock address %d (%s)"), errno, strerror(errno)); - return -1; + goto error; } if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) { - return -1; + goto error; } /* Get remote address in form IPADDR:PORT */ @@ -2510,11 +2565,11 @@ remoteDispatchAuthSaslInit (struct qemud remoteDispatchFormatError(rerr, _("failed to get peer address %d (%s)"), errno, strerror(errno)); VIR_FREE(localAddr); - return -1; + goto error; } if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) { VIR_FREE(localAddr); - return -1; + goto error; } err = sasl_server_new("libvirt", @@ -2530,9 +2585,8 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("sasl context setup failed %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchAuthError(rerr); - client->saslconn = NULL; - return -1; + client->saslconn = NULL; + goto authfail; } /* Inform SASL that we've got an external SSF layer from TLS */ @@ -2543,10 +2597,9 @@ remoteDispatchAuthSaslInit (struct qemud cipher = gnutls_cipher_get(client->tlssession); if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) { qemudLog(QEMUD_ERR, "%s", _("cannot TLS get cipher size")); - remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; - return -1; + goto authfail; } ssf *= 8; /* tls key size is bytes, sasl wants bits */ @@ -2554,10 +2607,9 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot set SASL external SSF %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchAuthError(rerr); sasl_dispose(&client->saslconn); client->saslconn = NULL; - return -1; + goto authfail; } } @@ -2583,10 +2635,9 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot set SASL security props %d (%s)"), err, sasl_errstring(err, NULL, NULL)); - remoteDispatchAuthError(rerr); - sasl_dispose(&client->saslconn); - client->saslconn = NULL; - return -1; + sasl_dispose(&client->saslconn); + client->saslconn = NULL; + goto authfail; } err = sasl_listmech(client->saslconn, @@ -2600,22 +2651,27 @@ remoteDispatchAuthSaslInit (struct qemud if (err != SASL_OK) { qemudLog(QEMUD_ERR, _("cannot list SASL mechanisms %d (%s)"), err, sasl_errdetail(client->saslconn)); - remoteDispatchAuthError(rerr); - sasl_dispose(&client->saslconn); - client->saslconn = NULL; - return -1; + sasl_dispose(&client->saslconn); + client->saslconn = NULL; + goto authfail; } REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist); ret->mechlist = strdup(mechlist); if (!ret->mechlist) { qemudLog(QEMUD_ERR, "%s", _("cannot allocate mechlist")); - remoteDispatchAuthError(rerr); - sasl_dispose(&client->saslconn); - client->saslconn = NULL; - return -1; - } - - return 0; + sasl_dispose(&client->saslconn); + client->saslconn = NULL; + goto authfail; + } + + pthread_mutex_unlock(&client->lock); + return 0; + +authfail: + remoteDispatchAuthError(rerr); +error: + pthread_mutex_unlock(&client->lock); + return -1; } @@ -2725,6 +2781,7 @@ static int static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret) @@ -2732,13 +2789,16 @@ remoteDispatchAuthSaslStart (struct qemu const char *serverout; unsigned int serveroutlen; int err; + + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); REMOTE_DEBUG("Start SASL auth %d", client->fd); if (client->auth != REMOTE_AUTH_SASL || client->saslconn == NULL) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid SASL start request")); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } REMOTE_DEBUG("Using SASL mechanism %s. Data %d bytes, nil: %d", @@ -2756,23 +2816,21 @@ remoteDispatchAuthSaslStart (struct qemu err, sasl_errdetail(client->saslconn)); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) { qemudLog(QEMUD_ERR, _("sasl start reply data too long %d"), serveroutlen); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } /* NB, distinction of NULL vs "" is *critical* in SASL */ if (serverout) { if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) { remoteDispatchOOMError(rerr); - return -1; + goto error; } memcpy(ret->data.data_val, serverout, serveroutlen); } else { @@ -2786,24 +2844,32 @@ remoteDispatchAuthSaslStart (struct qemu ret->complete = 0; } else { if (remoteSASLCheckSSF(client, rerr) < 0) - return -1; + goto error; /* Check username whitelist ACL */ if (remoteSASLCheckAccess(server, client, rerr) < 0) - return -1; + goto error; REMOTE_DEBUG("Authentication successful %d", client->fd); ret->complete = 1; client->auth = REMOTE_AUTH_NONE; } - return 0; + pthread_mutex_unlock(&client->lock); + return 0; + +authfail: + remoteDispatchAuthError(rerr); +error: + pthread_mutex_unlock(&client->lock); + return -1; } static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret) @@ -2811,13 +2877,16 @@ remoteDispatchAuthSaslStep (struct qemud const char *serverout; unsigned int serveroutlen; int err; + + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); REMOTE_DEBUG("Step SASL auth %d", client->fd); if (client->auth != REMOTE_AUTH_SASL || client->saslconn == NULL) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid SASL start request")); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } REMOTE_DEBUG("Using SASL Data %d bytes, nil: %d", @@ -2834,8 +2903,7 @@ remoteDispatchAuthSaslStep (struct qemud err, sasl_errdetail(client->saslconn)); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) { @@ -2843,15 +2911,14 @@ remoteDispatchAuthSaslStep (struct qemud serveroutlen); sasl_dispose(&client->saslconn); client->saslconn = NULL; - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } /* NB, distinction of NULL vs "" is *critical* in SASL */ if (serverout) { if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) { remoteDispatchOOMError(rerr); - return -1; + goto error; } memcpy(ret->data.data_val, serverout, serveroutlen); } else { @@ -2865,25 +2932,33 @@ remoteDispatchAuthSaslStep (struct qemud ret->complete = 0; } else { if (remoteSASLCheckSSF(client, rerr) < 0) - return -1; + goto error; /* Check username whitelist ACL */ if (remoteSASLCheckAccess(server, client, rerr) < 0) - return -1; + goto error; REMOTE_DEBUG("Authentication successful %d", client->fd); ret->complete = 1; client->auth = REMOTE_AUTH_NONE; } - return 0; + pthread_mutex_unlock(&client->lock); + return 0; + +authfail: + remoteDispatchAuthError(rerr); +error: + pthread_mutex_unlock(&client->lock); + return -1; } #else /* HAVE_SASL */ static int remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED) @@ -2895,7 +2970,8 @@ remoteDispatchAuthSaslInit (struct qemud static int remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED, remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED) @@ -2907,7 +2983,8 @@ remoteDispatchAuthSaslStart (struct qemu static int remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED, remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED) @@ -2921,8 +2998,9 @@ remoteDispatchAuthSaslStep (struct qemud #if HAVE_POLKIT static int -remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED, +remoteDispatchAuthPolkit (struct qemud_server *server, struct qemud_client *client, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_polkit_ret *ret) @@ -2935,7 +3013,13 @@ remoteDispatchAuthPolkit (struct qemud_s PolKitError *pkerr = NULL; PolKitResult pkresult; DBusError err; - const char *action = client->readonly ? + const char *action; + + pthread_mutex_lock(&server->lock); + pthread_mutex_lock(&client->lock); + pthread_mutex_unlock(&server->lock); + + action = client->readonly ? "org.libvirt.unix.monitor" : "org.libvirt.unix.manage"; @@ -2943,14 +3027,12 @@ remoteDispatchAuthPolkit (struct qemud_s if (client->auth != REMOTE_AUTH_POLKIT) { qemudLog(QEMUD_ERR, "%s", _("client tried invalid PolicyKit init request")); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) { qemudLog(QEMUD_ERR, "%s", _("cannot get peer socket identity")); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } qemudLog(QEMUD_INFO, _("Checking PID %d running as %d"), @@ -2961,16 +3043,14 @@ remoteDispatchAuthPolkit (struct qemud_s qemudLog(QEMUD_ERR, _("Failed to lookup policy kit caller: %s"), err.message); dbus_error_free(&err); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } if (!(pkaction = polkit_action_new())) { qemudLog(QEMUD_ERR, _("Failed to create polkit action %s\n"), strerror(errno)); polkit_caller_unref(pkcaller); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } polkit_action_set_action_id(pkaction, action); @@ -2984,8 +3064,7 @@ remoteDispatchAuthPolkit (struct qemud_s polkit_caller_unref(pkcaller); polkit_action_unref(pkaction); dbus_error_free(&err); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } #if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED @@ -2999,8 +3078,7 @@ remoteDispatchAuthPolkit (struct qemud_s _("Policy kit failed to check authorization %d %s"), polkit_error_get_error_code(pkerr), polkit_error_get_error_message(pkerr)); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } #else pkresult = polkit_context_can_caller_do_action(pkcontext, @@ -3016,8 +3094,7 @@ remoteDispatchAuthPolkit (struct qemud_s " result: %s\n"), action, callerPid, callerUid, polkit_result_to_string_representation(pkresult)); - remoteDispatchAuthError(rerr); - return -1; + goto authfail; } qemudLog(QEMUD_INFO, _("Policy allowed action %s from pid %d, uid %d, result %s"), @@ -3026,14 +3103,21 @@ remoteDispatchAuthPolkit (struct qemud_s ret->complete = 1; client->auth = REMOTE_AUTH_NONE; - return 0; + pthread_mutex_unlock(&client->lock); + return 0; + +authfail: + remoteDispatchAuthError(rerr); + pthread_mutex_unlock(&client->lock); + return -1; } #else /* HAVE_POLKIT */ static int remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED) @@ -3053,12 +3137,12 @@ remoteDispatchAuthPolkit (struct qemud_s static int remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_list_defined_storage_pools_args *args, remote_list_defined_storage_pools_ret *ret) { - CHECK_CONN(client); if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -3073,11 +3157,11 @@ remoteDispatchListDefinedStoragePools (s } ret->names.names_len = - virConnectListDefinedStoragePools (client->conn, + virConnectListDefinedStoragePools (conn, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3086,12 +3170,12 @@ remoteDispatchListDefinedStoragePools (s static int remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_list_storage_pools_args *args, remote_list_storage_pools_ret *ret) { - CHECK_CONN(client); if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -3106,11 +3190,11 @@ remoteDispatchListStoragePools (struct q } ret->names.names_len = - virConnectListStoragePools (client->conn, + virConnectListStoragePools (conn, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3119,20 +3203,19 @@ remoteDispatchListStoragePools (struct q static int remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_find_storage_pool_sources_args *args, remote_find_storage_pool_sources_ret *ret) { - CHECK_CONN(client); - ret->xml = - virConnectFindStoragePoolSources (client->conn, + virConnectFindStoragePoolSources (conn, args->type, args->srcSpec ? *args->srcSpec : NULL, args->flags); if (ret->xml == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3142,23 +3225,23 @@ remoteDispatchFindStoragePoolSources (st static int remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_create_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolCreate (pool, args->flags) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3167,17 +3250,17 @@ remoteDispatchStoragePoolCreate (struct static int remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = virStoragePoolCreateXML (client->conn, args->xml, args->flags); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = virStoragePoolCreateXML (conn, args->xml, args->flags); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3188,17 +3271,17 @@ remoteDispatchStoragePoolCreateXml (stru static int remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_define_xml_args *args, remote_storage_pool_define_xml_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = virStoragePoolDefineXML (client->conn, args->xml, args->flags); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = virStoragePoolDefineXML (conn, args->xml, args->flags); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3209,23 +3292,23 @@ remoteDispatchStoragePoolDefineXml (stru static int remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_build_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolBuild (pool, args->flags) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3235,23 +3318,23 @@ remoteDispatchStoragePoolBuild (struct q static int remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_destroy_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolDestroy (pool) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3260,23 +3343,23 @@ remoteDispatchStoragePoolDestroy (struct static int remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_delete_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolDelete (pool, args->flags) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3285,23 +3368,23 @@ remoteDispatchStoragePoolDelete (struct static int remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_refresh_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolRefresh (pool, args->flags) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3310,24 +3393,24 @@ remoteDispatchStoragePoolRefresh (struct static int remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_get_info_args *args, remote_storage_pool_get_info_ret *ret) { virStoragePoolPtr pool; virStoragePoolInfo info; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolGetInfo (pool, &info) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3343,17 +3426,17 @@ remoteDispatchStoragePoolGetInfo (struct static int remoteDispatchStoragePoolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_dump_xml_args *args, remote_storage_pool_dump_xml_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3361,7 +3444,7 @@ remoteDispatchStoragePoolDumpXml (struct ret->xml = virStoragePoolGetXMLDesc (pool, args->flags); if (!ret->xml) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3370,23 +3453,23 @@ remoteDispatchStoragePoolDumpXml (struct static int remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_get_autostart_args *args, remote_storage_pool_get_autostart_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3396,17 +3479,17 @@ remoteDispatchStoragePoolGetAutostart (s static int remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = virStoragePoolLookupByName (client->conn, args->name); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = virStoragePoolLookupByName (conn, args->name); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3417,17 +3500,17 @@ remoteDispatchStoragePoolLookupByName (s static int remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_lookup_by_uuid_args *args, remote_storage_pool_lookup_by_uuid_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = virStoragePoolLookupByUUID (client->conn, (unsigned char *) args->uuid); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = virStoragePoolLookupByUUID (conn, (unsigned char *) args->uuid); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3438,25 +3521,25 @@ remoteDispatchStoragePoolLookupByUuid (s static int remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_lookup_by_volume_args *args, remote_storage_pool_lookup_by_volume_ret *ret) { virStoragePoolPtr pool; virStorageVolPtr vol; - CHECK_CONN(client); - - vol = get_nonnull_storage_vol (client->conn, args->vol); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = get_nonnull_storage_vol (conn, args->vol); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } pool = virStoragePoolLookupByVolume (vol); virStorageVolFree(vol); if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3467,23 +3550,23 @@ remoteDispatchStoragePoolLookupByVolume static int remoteDispatchStoragePoolSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_set_autostart_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolSetAutostart (pool, args->autostart) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3492,23 +3575,23 @@ remoteDispatchStoragePoolSetAutostart (s static int remoteDispatchStoragePoolUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_undefine_args *args, void *ret ATTRIBUTE_UNUSED) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStoragePoolUndefine (pool) == -1) { virStoragePoolFree(pool); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStoragePoolFree(pool); @@ -3517,16 +3600,16 @@ remoteDispatchStoragePoolUndefine (struc static int remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_storage_pools_ret *ret) { - CHECK_CONN(client); - - ret->num = virConnectNumOfStoragePools (client->conn); - if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + + ret->num = virConnectNumOfStoragePools (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3535,16 +3618,16 @@ remoteDispatchNumOfStoragePools (struct static int remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, void *args ATTRIBUTE_UNUSED, remote_num_of_defined_storage_pools_ret *ret) { - CHECK_CONN(client); - - ret->num = virConnectNumOfDefinedStoragePools (client->conn); - if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + + ret->num = virConnectNumOfDefinedStoragePools (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3553,13 +3636,13 @@ remoteDispatchNumOfDefinedStoragePools ( static int remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_list_volumes_args *args, remote_storage_pool_list_volumes_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { remoteDispatchFormatError (rerr, @@ -3567,9 +3650,9 @@ remoteDispatchStoragePoolListVolumes (st return -1; } - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3586,7 +3669,7 @@ remoteDispatchStoragePoolListVolumes (st virStoragePoolFree(pool); if (ret->names.names_len == -1) { VIR_FREE(ret->names.names_val); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3596,24 +3679,24 @@ remoteDispatchStoragePoolListVolumes (st static int remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_pool_num_of_volumes_args *args, remote_storage_pool_num_of_volumes_ret *ret) { virStoragePoolPtr pool; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } ret->num = virStoragePoolNumOfVolumes (pool); virStoragePoolFree(pool); if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3629,25 +3712,25 @@ remoteDispatchStoragePoolNumOfVolumes (s static int remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret) { virStoragePoolPtr pool; virStorageVolPtr vol; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } vol = virStorageVolCreateXML (pool, args->xml, args->flags); virStoragePoolFree(pool); if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3659,23 +3742,23 @@ remoteDispatchStorageVolCreateXml (struc static int remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_delete_args *args, void *ret ATTRIBUTE_UNUSED) { virStorageVolPtr vol; - CHECK_CONN(client); - - vol = get_nonnull_storage_vol (client->conn, args->vol); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = get_nonnull_storage_vol (conn, args->vol); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStorageVolDelete (vol, args->flags) == -1) { virStorageVolFree(vol); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStorageVolFree(vol); @@ -3684,24 +3767,24 @@ remoteDispatchStorageVolDelete (struct q static int remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_get_info_args *args, remote_storage_vol_get_info_ret *ret) { virStorageVolPtr vol; virStorageVolInfo info; - CHECK_CONN(client); - - vol = get_nonnull_storage_vol (client->conn, args->vol); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = get_nonnull_storage_vol (conn, args->vol); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } if (virStorageVolGetInfo (vol, &info) == -1) { virStorageVolFree(vol); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3716,17 +3799,17 @@ remoteDispatchStorageVolGetInfo (struct static int remoteDispatchStorageVolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_dump_xml_args *args, remote_storage_vol_dump_xml_ret *ret) { virStorageVolPtr vol; - CHECK_CONN(client); - - vol = get_nonnull_storage_vol (client->conn, args->vol); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = get_nonnull_storage_vol (conn, args->vol); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3734,7 +3817,7 @@ remoteDispatchStorageVolDumpXml (struct ret->xml = virStorageVolGetXMLDesc (vol, args->flags); if (!ret->xml) { virStorageVolFree(vol); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStorageVolFree(vol); @@ -3744,17 +3827,17 @@ remoteDispatchStorageVolDumpXml (struct static int remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_get_path_args *args, remote_storage_vol_get_path_ret *ret) { virStorageVolPtr vol; - CHECK_CONN(client); - - vol = get_nonnull_storage_vol (client->conn, args->vol); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = get_nonnull_storage_vol (conn, args->vol); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3762,7 +3845,7 @@ remoteDispatchStorageVolGetPath (struct ret->name = virStorageVolGetPath (vol); if (!ret->name) { virStorageVolFree(vol); - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } virStorageVolFree(vol); @@ -3772,25 +3855,25 @@ remoteDispatchStorageVolGetPath (struct static int remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_lookup_by_name_args *args, remote_storage_vol_lookup_by_name_ret *ret) { virStoragePoolPtr pool; virStorageVolPtr vol; - CHECK_CONN(client); - - pool = get_nonnull_storage_pool (client->conn, args->pool); - if (pool == NULL) { - remoteDispatchConnError(rerr, client->conn); + + pool = get_nonnull_storage_pool (conn, args->pool); + if (pool == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } vol = virStorageVolLookupByName (pool, args->name); virStoragePoolFree(pool); if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3801,17 +3884,17 @@ remoteDispatchStorageVolLookupByName (st static int remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_lookup_by_key_args *args, remote_storage_vol_lookup_by_key_ret *ret) { virStorageVolPtr vol; - CHECK_CONN(client); - - vol = virStorageVolLookupByKey (client->conn, args->key); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = virStorageVolLookupByKey (conn, args->key); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3823,17 +3906,17 @@ remoteDispatchStorageVolLookupByKey (str static int remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_storage_vol_lookup_by_path_args *args, remote_storage_vol_lookup_by_path_ret *ret) { virStorageVolPtr vol; - CHECK_CONN(client); - - vol = virStorageVolLookupByPath (client->conn, args->path); - if (vol == NULL) { - remoteDispatchConnError(rerr, client->conn); + + vol = virStorageVolLookupByPath (conn, args->path); + if (vol == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3849,18 +3932,19 @@ remoteDispatchStorageVolLookupByPath (st static int remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_num_of_devices_args *args, remote_node_num_of_devices_ret *ret) { CHECK_CONN(client); - ret->num = virNodeNumOfDevices (client->conn, + ret->num = virNodeNumOfDevices (conn, args->cap ? *args->cap : NULL, args->flags); if (ret->num == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -3870,7 +3954,8 @@ remoteDispatchNodeNumOfDevices (struct q static int remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_list_devices_args *args, remote_node_list_devices_ret *ret) @@ -3890,11 +3975,11 @@ remoteDispatchNodeListDevices (struct qe } ret->names.names_len = - virNodeListDevices (client->conn, + virNodeListDevices (conn, args->cap ? *args->cap : NULL, ret->names.names_val, args->maxnames, args->flags); if (ret->names.names_len == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); VIR_FREE(ret->names.names_val); return -1; } @@ -3905,7 +3990,8 @@ remoteDispatchNodeListDevices (struct qe static int remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_device_lookup_by_name_args *args, remote_node_device_lookup_by_name_ret *ret) @@ -3914,9 +4000,9 @@ remoteDispatchNodeDeviceLookupByName (st CHECK_CONN(client); - dev = virNodeDeviceLookupByName (client->conn, args->name); - if (dev == NULL) { - remoteDispatchConnError(rerr, client->conn); + dev = virNodeDeviceLookupByName (conn, args->name); + if (dev == NULL) { + remoteDispatchConnError(rerr, conn); return -1; } @@ -3928,7 +4014,8 @@ remoteDispatchNodeDeviceLookupByName (st static int remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_device_dump_xml_args *args, remote_node_device_dump_xml_ret *ret) @@ -3936,7 +4023,7 @@ remoteDispatchNodeDeviceDumpXml (struct virNodeDevicePtr dev; CHECK_CONN(client); - dev = virNodeDeviceLookupByName(client->conn, args->name); + dev = virNodeDeviceLookupByName(conn, args->name); if (dev == NULL) { remoteDispatchFormatError(rerr, "%s", _("node_device not found")); return -1; @@ -3945,7 +4032,7 @@ remoteDispatchNodeDeviceDumpXml (struct /* remoteDispatchClientRequest will free this. */ ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags); if (!ret->xml) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); virNodeDeviceFree(dev); return -1; } @@ -3956,7 +4043,8 @@ remoteDispatchNodeDeviceDumpXml (struct static int remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_device_get_parent_args *args, remote_node_device_get_parent_ret *ret) @@ -3965,7 +4053,7 @@ remoteDispatchNodeDeviceGetParent (struc const char *parent; CHECK_CONN(client); - dev = virNodeDeviceLookupByName(client->conn, args->name); + dev = virNodeDeviceLookupByName(conn, args->name); if (dev == NULL) { remoteDispatchFormatError(rerr, "%s", _("node_device not found")); return -1; @@ -3997,7 +4085,8 @@ remoteDispatchNodeDeviceGetParent (struc static int remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_device_num_of_caps_args *args, remote_node_device_num_of_caps_ret *ret) @@ -4005,7 +4094,7 @@ remoteDispatchNodeDeviceNumOfCaps (struc virNodeDevicePtr dev; CHECK_CONN(client); - dev = virNodeDeviceLookupByName(client->conn, args->name); + dev = virNodeDeviceLookupByName(conn, args->name); if (dev == NULL) { remoteDispatchFormatError(rerr, "%s", _("node_device not found")); return -1; @@ -4013,7 +4102,7 @@ remoteDispatchNodeDeviceNumOfCaps (struc ret->num = virNodeDeviceNumOfCaps(dev); if (ret->num < 0) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); return -1; } @@ -4024,7 +4113,8 @@ remoteDispatchNodeDeviceNumOfCaps (struc static int remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr, remote_node_device_list_caps_args *args, remote_node_device_list_caps_ret *ret) @@ -4032,7 +4122,7 @@ remoteDispatchNodeDeviceListCaps (struct virNodeDevicePtr dev; CHECK_CONN(client); - dev = virNodeDeviceLookupByName(client->conn, args->name); + dev = virNodeDeviceLookupByName(conn, args->name); if (dev == NULL) { remoteDispatchFormatError(rerr, "%s", _("node_device not found")); return -1; @@ -4054,7 +4144,7 @@ remoteDispatchNodeDeviceListCaps (struct virNodeDeviceListCaps (dev, ret->names.names_val, args->maxnames); if (ret->names.names_len == -1) { - remoteDispatchConnError(rerr, client->conn); + remoteDispatchConnError(rerr, conn); VIR_FREE(ret->names.names_val); return -1; } @@ -4069,6 +4159,7 @@ static int static int remoteDispatchDomainEvent (struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn ATTRIBUTE_UNUSED, remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, remote_domain_event_ret *ret ATTRIBUTE_UNUSED) @@ -4086,7 +4177,8 @@ remoteDispatchDomainEvent (struct qemud_ ***************************/ static int remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, remote_domain_events_register_ret *ret ATTRIBUTE_UNUSED) @@ -4095,7 +4187,7 @@ remoteDispatchDomainEventsRegister (stru /* Register event delivery callback */ REMOTE_DEBUG("%s","Registering to relay remote events"); - virConnectDomainEventRegister(client->conn, remoteRelayDomainEvent, client, NULL); + virConnectDomainEventRegister(conn, remoteRelayDomainEvent, client, NULL); if(ret) ret->cb_registered = 1; @@ -4104,7 +4196,8 @@ remoteDispatchDomainEventsRegister (stru static int remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED, - struct qemud_client *client, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, remote_error *rerr ATTRIBUTE_UNUSED, void *args ATTRIBUTE_UNUSED, remote_domain_events_deregister_ret *ret ATTRIBUTE_UNUSED) @@ -4113,7 +4206,7 @@ remoteDispatchDomainEventsDeregister (st /* Deregister event delivery callback */ REMOTE_DEBUG("%s","Deregistering to relay remote events"); - virConnectDomainEventDeregister(client->conn, remoteRelayDomainEvent); + virConnectDomainEventDeregister(conn, remoteRelayDomainEvent); if(ret) ret->cb_registered = 0; diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h --- a/qemud/remote_dispatch_prototypes.h +++ b/qemud/remote_dispatch_prototypes.h @@ -2,120 +2,822 @@ * Do not edit this file. Any changes you make will be lost. */ -static int remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_auth_list_ret *ret); -static int remoteDispatchAuthPolkit (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_auth_polkit_ret *ret); -static int remoteDispatchAuthSaslInit (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_auth_sasl_init_ret *ret); -static int remoteDispatchAuthSaslStart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_auth_sasl_start_args *args, remote_auth_sasl_start_ret *ret); -static int remoteDispatchAuthSaslStep (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_auth_sasl_step_args *args, remote_auth_sasl_step_ret *ret); -static int remoteDispatchClose (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, void *ret); -static int remoteDispatchDomainAttachDevice (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_attach_device_args *args, void *ret); -static int remoteDispatchDomainBlockPeek (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_block_peek_args *args, remote_domain_block_peek_ret *ret); -static int remoteDispatchDomainBlockStats (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_block_stats_args *args, remote_domain_block_stats_ret *ret); -static int remoteDispatchDomainCoreDump (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_core_dump_args *args, void *ret); -static int remoteDispatchDomainCreate (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_create_args *args, void *ret); -static int remoteDispatchDomainCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_create_xml_args *args, remote_domain_create_xml_ret *ret); -static int remoteDispatchDomainDefineXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_define_xml_args *args, remote_domain_define_xml_ret *ret); -static int remoteDispatchDomainDestroy (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_destroy_args *args, void *ret); -static int remoteDispatchDomainDetachDevice (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_detach_device_args *args, void *ret); -static int remoteDispatchDomainDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_dump_xml_args *args, remote_domain_dump_xml_ret *ret); -static int remoteDispatchDomainEvent (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_domain_event_ret *ret); -static int remoteDispatchDomainEventsDeregister (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_domain_events_deregister_ret *ret); -static int remoteDispatchDomainEventsRegister (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_domain_events_register_ret *ret); -static int remoteDispatchDomainGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_autostart_args *args, remote_domain_get_autostart_ret *ret); -static int remoteDispatchDomainGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_info_args *args, remote_domain_get_info_ret *ret); -static int remoteDispatchDomainGetMaxMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_max_memory_args *args, remote_domain_get_max_memory_ret *ret); -static int remoteDispatchDomainGetMaxVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_max_vcpus_args *args, remote_domain_get_max_vcpus_ret *ret); -static int remoteDispatchDomainGetOsType (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_os_type_args *args, remote_domain_get_os_type_ret *ret); -static int remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_scheduler_parameters_args *args, remote_domain_get_scheduler_parameters_ret *ret); -static int remoteDispatchDomainGetSchedulerType (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_scheduler_type_args *args, remote_domain_get_scheduler_type_ret *ret); -static int remoteDispatchDomainGetVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_get_vcpus_args *args, remote_domain_get_vcpus_ret *ret); -static int remoteDispatchDomainInterfaceStats (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_interface_stats_args *args, remote_domain_interface_stats_ret *ret); -static int remoteDispatchDomainLookupById (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_lookup_by_id_args *args, remote_domain_lookup_by_id_ret *ret); -static int remoteDispatchDomainLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_lookup_by_name_args *args, remote_domain_lookup_by_name_ret *ret); -static int remoteDispatchDomainLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_lookup_by_uuid_args *args, remote_domain_lookup_by_uuid_ret *ret); -static int remoteDispatchDomainMemoryPeek (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_memory_peek_args *args, remote_domain_memory_peek_ret *ret); -static int remoteDispatchDomainMigrateFinish (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_finish_args *args, remote_domain_migrate_finish_ret *ret); -static int remoteDispatchDomainMigrateFinish2 (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_finish2_args *args, remote_domain_migrate_finish2_ret *ret); -static int remoteDispatchDomainMigratePerform (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_perform_args *args, void *ret); -static int remoteDispatchDomainMigratePrepare (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_prepare_args *args, remote_domain_migrate_prepare_ret *ret); -static int remoteDispatchDomainMigratePrepare2 (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_migrate_prepare2_args *args, remote_domain_migrate_prepare2_ret *ret); -static int remoteDispatchDomainPinVcpu (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_pin_vcpu_args *args, void *ret); -static int remoteDispatchDomainReboot (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_reboot_args *args, void *ret); -static int remoteDispatchDomainRestore (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_restore_args *args, void *ret); -static int remoteDispatchDomainResume (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_resume_args *args, void *ret); -static int remoteDispatchDomainSave (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_save_args *args, void *ret); -static int remoteDispatchDomainSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_autostart_args *args, void *ret); -static int remoteDispatchDomainSetMaxMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_max_memory_args *args, void *ret); -static int remoteDispatchDomainSetMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_memory_args *args, void *ret); -static int remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_scheduler_parameters_args *args, void *ret); -static int remoteDispatchDomainSetVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_set_vcpus_args *args, void *ret); -static int remoteDispatchDomainShutdown (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_shutdown_args *args, void *ret); -static int remoteDispatchDomainSuspend (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_suspend_args *args, void *ret); -static int remoteDispatchDomainUndefine (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_domain_undefine_args *args, void *ret); -static int remoteDispatchFindStoragePoolSources (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_find_storage_pool_sources_args *args, remote_find_storage_pool_sources_ret *ret); -static int remoteDispatchGetCapabilities (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_capabilities_ret *ret); -static int remoteDispatchGetHostname (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_hostname_ret *ret); -static int remoteDispatchGetMaxVcpus (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret); -static int remoteDispatchGetType (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_type_ret *ret); -static int remoteDispatchGetUri (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_uri_ret *ret); -static int remoteDispatchGetVersion (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_get_version_ret *ret); -static int remoteDispatchListDefinedDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_defined_domains_args *args, remote_list_defined_domains_ret *ret); -static int remoteDispatchListDefinedNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_defined_networks_args *args, remote_list_defined_networks_ret *ret); -static int remoteDispatchListDefinedStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_defined_storage_pools_args *args, remote_list_defined_storage_pools_ret *ret); -static int remoteDispatchListDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_domains_args *args, remote_list_domains_ret *ret); -static int remoteDispatchListNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_networks_args *args, remote_list_networks_ret *ret); -static int remoteDispatchListStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_list_storage_pools_args *args, remote_list_storage_pools_ret *ret); -static int remoteDispatchNetworkCreate (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_create_args *args, void *ret); -static int remoteDispatchNetworkCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_create_xml_args *args, remote_network_create_xml_ret *ret); -static int remoteDispatchNetworkDefineXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_define_xml_args *args, remote_network_define_xml_ret *ret); -static int remoteDispatchNetworkDestroy (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_destroy_args *args, void *ret); -static int remoteDispatchNetworkDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_dump_xml_args *args, remote_network_dump_xml_ret *ret); -static int remoteDispatchNetworkGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_get_autostart_args *args, remote_network_get_autostart_ret *ret); -static int remoteDispatchNetworkGetBridgeName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_get_bridge_name_args *args, remote_network_get_bridge_name_ret *ret); -static int remoteDispatchNetworkLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_lookup_by_name_args *args, remote_network_lookup_by_name_ret *ret); -static int remoteDispatchNetworkLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_lookup_by_uuid_args *args, remote_network_lookup_by_uuid_ret *ret); -static int remoteDispatchNetworkSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_set_autostart_args *args, void *ret); -static int remoteDispatchNetworkUndefine (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_network_undefine_args *args, void *ret); -static int remoteDispatchNodeDeviceDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_dump_xml_args *args, remote_node_device_dump_xml_ret *ret); -static int remoteDispatchNodeDeviceGetParent (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_get_parent_args *args, remote_node_device_get_parent_ret *ret); -static int remoteDispatchNodeDeviceListCaps (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_list_caps_args *args, remote_node_device_list_caps_ret *ret); -static int remoteDispatchNodeDeviceLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_lookup_by_name_args *args, remote_node_device_lookup_by_name_ret *ret); -static int remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_device_num_of_caps_args *args, remote_node_device_num_of_caps_ret *ret); -static int remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_get_cells_free_memory_args *args, remote_node_get_cells_free_memory_ret *ret); -static int remoteDispatchNodeGetFreeMemory (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_node_get_free_memory_ret *ret); -static int remoteDispatchNodeGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_node_get_info_ret *ret); -static int remoteDispatchNodeListDevices (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_list_devices_args *args, remote_node_list_devices_ret *ret); -static int remoteDispatchNodeNumOfDevices (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_node_num_of_devices_args *args, remote_node_num_of_devices_ret *ret); -static int remoteDispatchNumOfDefinedDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_defined_domains_ret *ret); -static int remoteDispatchNumOfDefinedNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_defined_networks_ret *ret); -static int remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_defined_storage_pools_ret *ret); -static int remoteDispatchNumOfDomains (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_domains_ret *ret); -static int remoteDispatchNumOfNetworks (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_networks_ret *ret); -static int remoteDispatchNumOfStoragePools (struct qemud_server *server, struct qemud_client *client, remote_error *err, void *args, remote_num_of_storage_pools_ret *ret); -static int remoteDispatchOpen (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_open_args *args, void *ret); -static int remoteDispatchStoragePoolBuild (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_build_args *args, void *ret); -static int remoteDispatchStoragePoolCreate (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_create_args *args, void *ret); -static int remoteDispatchStoragePoolCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_create_xml_args *args, remote_storage_pool_create_xml_ret *ret); -static int remoteDispatchStoragePoolDefineXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_define_xml_args *args, remote_storage_pool_define_xml_ret *ret); -static int remoteDispatchStoragePoolDelete (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_delete_args *args, void *ret); -static int remoteDispatchStoragePoolDestroy (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_destroy_args *args, void *ret); -static int remoteDispatchStoragePoolDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_dump_xml_args *args, remote_storage_pool_dump_xml_ret *ret); -static int remoteDispatchStoragePoolGetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_get_autostart_args *args, remote_storage_pool_get_autostart_ret *ret); -static int remoteDispatchStoragePoolGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_get_info_args *args, remote_storage_pool_get_info_ret *ret); -static int remoteDispatchStoragePoolListVolumes (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_list_volumes_args *args, remote_storage_pool_list_volumes_ret *ret); -static int remoteDispatchStoragePoolLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_lookup_by_name_args *args, remote_storage_pool_lookup_by_name_ret *ret); -static int remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_lookup_by_uuid_args *args, remote_storage_pool_lookup_by_uuid_ret *ret); -static int remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_lookup_by_volume_args *args, remote_storage_pool_lookup_by_volume_ret *ret); -static int remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_num_of_volumes_args *args, remote_storage_pool_num_of_volumes_ret *ret); -static int remoteDispatchStoragePoolRefresh (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_refresh_args *args, void *ret); -static int remoteDispatchStoragePoolSetAutostart (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_set_autostart_args *args, void *ret); -static int remoteDispatchStoragePoolUndefine (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_pool_undefine_args *args, void *ret); -static int remoteDispatchStorageVolCreateXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_create_xml_args *args, remote_storage_vol_create_xml_ret *ret); -static int remoteDispatchStorageVolDelete (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_delete_args *args, void *ret); -static int remoteDispatchStorageVolDumpXml (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_dump_xml_args *args, remote_storage_vol_dump_xml_ret *ret); -static int remoteDispatchStorageVolGetInfo (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_get_info_args *args, remote_storage_vol_get_info_ret *ret); -static int remoteDispatchStorageVolGetPath (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_get_path_args *args, remote_storage_vol_get_path_ret *ret); -static int remoteDispatchStorageVolLookupByKey (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_lookup_by_key_args *args, remote_storage_vol_lookup_by_key_ret *ret); -static int remoteDispatchStorageVolLookupByName (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_lookup_by_name_args *args, remote_storage_vol_lookup_by_name_ret *ret); -static int remoteDispatchStorageVolLookupByPath (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_storage_vol_lookup_by_path_args *args, remote_storage_vol_lookup_by_path_ret *ret); -static int remoteDispatchSupportsFeature (struct qemud_server *server, struct qemud_client *client, remote_error *err, remote_supports_feature_args *args, remote_supports_feature_ret *ret); +static int remoteDispatchAuthList( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_auth_list_ret *ret); +static int remoteDispatchAuthPolkit( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_auth_polkit_ret *ret); +static int remoteDispatchAuthSaslInit( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_auth_sasl_init_ret *ret); +static int remoteDispatchAuthSaslStart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_auth_sasl_start_args *args, + remote_auth_sasl_start_ret *ret); +static int remoteDispatchAuthSaslStep( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_auth_sasl_step_args *args, + remote_auth_sasl_step_ret *ret); +static int remoteDispatchClose( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + void *ret); +static int remoteDispatchDomainAttachDevice( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_attach_device_args *args, + void *ret); +static int remoteDispatchDomainBlockPeek( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_block_peek_args *args, + remote_domain_block_peek_ret *ret); +static int remoteDispatchDomainBlockStats( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_block_stats_args *args, + remote_domain_block_stats_ret *ret); +static int remoteDispatchDomainCoreDump( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_core_dump_args *args, + void *ret); +static int remoteDispatchDomainCreate( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_create_args *args, + void *ret); +static int remoteDispatchDomainCreateXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_create_xml_args *args, + remote_domain_create_xml_ret *ret); +static int remoteDispatchDomainDefineXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_define_xml_args *args, + remote_domain_define_xml_ret *ret); +static int remoteDispatchDomainDestroy( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_destroy_args *args, + void *ret); +static int remoteDispatchDomainDetachDevice( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_detach_device_args *args, + void *ret); +static int remoteDispatchDomainDumpXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_dump_xml_args *args, + remote_domain_dump_xml_ret *ret); +static int remoteDispatchDomainEvent( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_domain_event_ret *ret); +static int remoteDispatchDomainEventsDeregister( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_domain_events_deregister_ret *ret); +static int remoteDispatchDomainEventsRegister( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_domain_events_register_ret *ret); +static int remoteDispatchDomainGetAutostart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_autostart_args *args, + remote_domain_get_autostart_ret *ret); +static int remoteDispatchDomainGetInfo( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_info_args *args, + remote_domain_get_info_ret *ret); +static int remoteDispatchDomainGetMaxMemory( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_max_memory_args *args, + remote_domain_get_max_memory_ret *ret); +static int remoteDispatchDomainGetMaxVcpus( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_max_vcpus_args *args, + remote_domain_get_max_vcpus_ret *ret); +static int remoteDispatchDomainGetOsType( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_os_type_args *args, + remote_domain_get_os_type_ret *ret); +static int remoteDispatchDomainGetSchedulerParameters( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_scheduler_parameters_args *args, + remote_domain_get_scheduler_parameters_ret *ret); +static int remoteDispatchDomainGetSchedulerType( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_scheduler_type_args *args, + remote_domain_get_scheduler_type_ret *ret); +static int remoteDispatchDomainGetVcpus( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_get_vcpus_args *args, + remote_domain_get_vcpus_ret *ret); +static int remoteDispatchDomainInterfaceStats( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_interface_stats_args *args, + remote_domain_interface_stats_ret *ret); +static int remoteDispatchDomainLookupById( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_lookup_by_id_args *args, + remote_domain_lookup_by_id_ret *ret); +static int remoteDispatchDomainLookupByName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_lookup_by_name_args *args, + remote_domain_lookup_by_name_ret *ret); +static int remoteDispatchDomainLookupByUuid( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_lookup_by_uuid_args *args, + remote_domain_lookup_by_uuid_ret *ret); +static int remoteDispatchDomainMemoryPeek( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_memory_peek_args *args, + remote_domain_memory_peek_ret *ret); +static int remoteDispatchDomainMigrateFinish( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_migrate_finish_args *args, + remote_domain_migrate_finish_ret *ret); +static int remoteDispatchDomainMigrateFinish2( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_migrate_finish2_args *args, + remote_domain_migrate_finish2_ret *ret); +static int remoteDispatchDomainMigratePerform( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_migrate_perform_args *args, + void *ret); +static int remoteDispatchDomainMigratePrepare( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_migrate_prepare_args *args, + remote_domain_migrate_prepare_ret *ret); +static int remoteDispatchDomainMigratePrepare2( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_migrate_prepare2_args *args, + remote_domain_migrate_prepare2_ret *ret); +static int remoteDispatchDomainPinVcpu( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_pin_vcpu_args *args, + void *ret); +static int remoteDispatchDomainReboot( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_reboot_args *args, + void *ret); +static int remoteDispatchDomainRestore( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_restore_args *args, + void *ret); +static int remoteDispatchDomainResume( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_resume_args *args, + void *ret); +static int remoteDispatchDomainSave( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_save_args *args, + void *ret); +static int remoteDispatchDomainSetAutostart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_set_autostart_args *args, + void *ret); +static int remoteDispatchDomainSetMaxMemory( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_set_max_memory_args *args, + void *ret); +static int remoteDispatchDomainSetMemory( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_set_memory_args *args, + void *ret); +static int remoteDispatchDomainSetSchedulerParameters( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_set_scheduler_parameters_args *args, + void *ret); +static int remoteDispatchDomainSetVcpus( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_set_vcpus_args *args, + void *ret); +static int remoteDispatchDomainShutdown( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_shutdown_args *args, + void *ret); +static int remoteDispatchDomainSuspend( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_suspend_args *args, + void *ret); +static int remoteDispatchDomainUndefine( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_domain_undefine_args *args, + void *ret); +static int remoteDispatchFindStoragePoolSources( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_find_storage_pool_sources_args *args, + remote_find_storage_pool_sources_ret *ret); +static int remoteDispatchGetCapabilities( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_get_capabilities_ret *ret); +static int remoteDispatchGetHostname( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_get_hostname_ret *ret); +static int remoteDispatchGetMaxVcpus( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_get_max_vcpus_args *args, + remote_get_max_vcpus_ret *ret); +static int remoteDispatchGetType( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_get_type_ret *ret); +static int remoteDispatchGetUri( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_get_uri_ret *ret); +static int remoteDispatchGetVersion( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_get_version_ret *ret); +static int remoteDispatchListDefinedDomains( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_defined_domains_args *args, + remote_list_defined_domains_ret *ret); +static int remoteDispatchListDefinedNetworks( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_defined_networks_args *args, + remote_list_defined_networks_ret *ret); +static int remoteDispatchListDefinedStoragePools( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_defined_storage_pools_args *args, + remote_list_defined_storage_pools_ret *ret); +static int remoteDispatchListDomains( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_domains_args *args, + remote_list_domains_ret *ret); +static int remoteDispatchListNetworks( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_networks_args *args, + remote_list_networks_ret *ret); +static int remoteDispatchListStoragePools( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_storage_pools_args *args, + remote_list_storage_pools_ret *ret); +static int remoteDispatchNetworkCreate( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_create_args *args, + void *ret); +static int remoteDispatchNetworkCreateXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_create_xml_args *args, + remote_network_create_xml_ret *ret); +static int remoteDispatchNetworkDefineXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_define_xml_args *args, + remote_network_define_xml_ret *ret); +static int remoteDispatchNetworkDestroy( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_destroy_args *args, + void *ret); +static int remoteDispatchNetworkDumpXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_dump_xml_args *args, + remote_network_dump_xml_ret *ret); +static int remoteDispatchNetworkGetAutostart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_get_autostart_args *args, + remote_network_get_autostart_ret *ret); +static int remoteDispatchNetworkGetBridgeName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_get_bridge_name_args *args, + remote_network_get_bridge_name_ret *ret); +static int remoteDispatchNetworkLookupByName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_lookup_by_name_args *args, + remote_network_lookup_by_name_ret *ret); +static int remoteDispatchNetworkLookupByUuid( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_lookup_by_uuid_args *args, + remote_network_lookup_by_uuid_ret *ret); +static int remoteDispatchNetworkSetAutostart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_set_autostart_args *args, + void *ret); +static int remoteDispatchNetworkUndefine( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_network_undefine_args *args, + void *ret); +static int remoteDispatchNodeDeviceDumpXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_device_dump_xml_args *args, + remote_node_device_dump_xml_ret *ret); +static int remoteDispatchNodeDeviceGetParent( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_device_get_parent_args *args, + remote_node_device_get_parent_ret *ret); +static int remoteDispatchNodeDeviceListCaps( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_device_list_caps_args *args, + remote_node_device_list_caps_ret *ret); +static int remoteDispatchNodeDeviceLookupByName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_device_lookup_by_name_args *args, + remote_node_device_lookup_by_name_ret *ret); +static int remoteDispatchNodeDeviceNumOfCaps( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_device_num_of_caps_args *args, + remote_node_device_num_of_caps_ret *ret); +static int remoteDispatchNodeGetCellsFreeMemory( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_get_cells_free_memory_args *args, + remote_node_get_cells_free_memory_ret *ret); +static int remoteDispatchNodeGetFreeMemory( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_node_get_free_memory_ret *ret); +static int remoteDispatchNodeGetInfo( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_node_get_info_ret *ret); +static int remoteDispatchNodeListDevices( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_list_devices_args *args, + remote_node_list_devices_ret *ret); +static int remoteDispatchNodeNumOfDevices( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_node_num_of_devices_args *args, + remote_node_num_of_devices_ret *ret); +static int remoteDispatchNumOfDefinedDomains( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_defined_domains_ret *ret); +static int remoteDispatchNumOfDefinedNetworks( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_defined_networks_ret *ret); +static int remoteDispatchNumOfDefinedStoragePools( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_defined_storage_pools_ret *ret); +static int remoteDispatchNumOfDomains( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_domains_ret *ret); +static int remoteDispatchNumOfNetworks( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_networks_ret *ret); +static int remoteDispatchNumOfStoragePools( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_storage_pools_ret *ret); +static int remoteDispatchOpen( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_open_args *args, + void *ret); +static int remoteDispatchStoragePoolBuild( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_build_args *args, + void *ret); +static int remoteDispatchStoragePoolCreate( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_create_args *args, + void *ret); +static int remoteDispatchStoragePoolCreateXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_create_xml_args *args, + remote_storage_pool_create_xml_ret *ret); +static int remoteDispatchStoragePoolDefineXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_define_xml_args *args, + remote_storage_pool_define_xml_ret *ret); +static int remoteDispatchStoragePoolDelete( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_delete_args *args, + void *ret); +static int remoteDispatchStoragePoolDestroy( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_destroy_args *args, + void *ret); +static int remoteDispatchStoragePoolDumpXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_dump_xml_args *args, + remote_storage_pool_dump_xml_ret *ret); +static int remoteDispatchStoragePoolGetAutostart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_get_autostart_args *args, + remote_storage_pool_get_autostart_ret *ret); +static int remoteDispatchStoragePoolGetInfo( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_get_info_args *args, + remote_storage_pool_get_info_ret *ret); +static int remoteDispatchStoragePoolListVolumes( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_list_volumes_args *args, + remote_storage_pool_list_volumes_ret *ret); +static int remoteDispatchStoragePoolLookupByName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_lookup_by_name_args *args, + remote_storage_pool_lookup_by_name_ret *ret); +static int remoteDispatchStoragePoolLookupByUuid( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_lookup_by_uuid_args *args, + remote_storage_pool_lookup_by_uuid_ret *ret); +static int remoteDispatchStoragePoolLookupByVolume( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_lookup_by_volume_args *args, + remote_storage_pool_lookup_by_volume_ret *ret); +static int remoteDispatchStoragePoolNumOfVolumes( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_num_of_volumes_args *args, + remote_storage_pool_num_of_volumes_ret *ret); +static int remoteDispatchStoragePoolRefresh( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_refresh_args *args, + void *ret); +static int remoteDispatchStoragePoolSetAutostart( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_set_autostart_args *args, + void *ret); +static int remoteDispatchStoragePoolUndefine( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_pool_undefine_args *args, + void *ret); +static int remoteDispatchStorageVolCreateXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_create_xml_args *args, + remote_storage_vol_create_xml_ret *ret); +static int remoteDispatchStorageVolDelete( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_delete_args *args, + void *ret); +static int remoteDispatchStorageVolDumpXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_dump_xml_args *args, + remote_storage_vol_dump_xml_ret *ret); +static int remoteDispatchStorageVolGetInfo( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_get_info_args *args, + remote_storage_vol_get_info_ret *ret); +static int remoteDispatchStorageVolGetPath( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_get_path_args *args, + remote_storage_vol_get_path_ret *ret); +static int remoteDispatchStorageVolLookupByKey( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_lookup_by_key_args *args, + remote_storage_vol_lookup_by_key_ret *ret); +static int remoteDispatchStorageVolLookupByName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_lookup_by_name_args *args, + remote_storage_vol_lookup_by_name_ret *ret); +static int remoteDispatchStorageVolLookupByPath( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_storage_vol_lookup_by_path_args *args, + remote_storage_vol_lookup_by_path_ret *ret); +static int remoteDispatchSupportsFeature( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_supports_feature_args *args, + remote_supports_feature_ret *ret); diff --git a/qemud/remote_generate_stubs.pl b/qemud/remote_generate_stubs.pl --- a/qemud/remote_generate_stubs.pl +++ b/qemud/remote_generate_stubs.pl @@ -100,7 +100,13 @@ elsif ($opt_p) { elsif ($opt_p) { my @keys = sort (keys %calls); foreach (@keys) { - print "static int remoteDispatch$calls{$_}->{ProcName} (struct qemud_server *server, struct qemud_client *client, remote_error *err, $calls{$_}->{args} *args, $calls{$_}->{ret} *ret);\n"; + print "static int remoteDispatch$calls{$_}->{ProcName}(\n"; + print " struct qemud_server *server, \n"; + print " struct qemud_client *client, \n"; + print " virConnectPtr conn, \n"; + print " remote_error *err, \n"; + print " $calls{$_}->{args} *args,\n"; + print " $calls{$_}->{ret} *ret);\n"; } } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:21:10AM +0000, Daniel P. Berrange wrote:
This patch makes the libvirtd daemon itself use mutliple threads. Each individual client is still serialized, but mutliple clients can now be handled in parallel. This introduces a pool of worker threads to handle RPC call processing, while the main thread just runs the event loop and handles network I/O.
okay, the whole point of the exercise :-)
diff --git a/qemud/THREADING.txt b/qemud/THREADING.txt new file mode 100644 --- /dev/null +++ b/qemud/THREADING.txt
good :-)
+ - The event loop has its own self-contained lock. You can ignore + this as a caller of virEvent APIs.
still worth explaining as this is rather complex [...] that patch is hard, really ! I tried to follow the quemu side of it and a bit of the network handling side. The problem is that the model is rather complex and the compiler can't help us if we made any mistake. And locking errors could go unnotified for ages before biting us. Still the best is probably to push this and try it as much as possible to assert the status, just the eyeball review will clearly not be sufficient. So +1 but we need much testing ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch extends the libvirtd configuration file to allow various thread related parameters to be tuned. It introduces a limit on the number of client connections allowed over TCP socket to prevent DOS attacks on the machine resources. It also adds a min/max worker thread pool size for handling RPC calls. libvirtd.aug | 6 ++++++ libvirtd.conf | 19 +++++++++++++++++++ qemud.c | 17 ++++++++++++++++- test_libvirtd.aug | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) Daniel diff --git a/qemud/libvirtd.aug b/qemud/libvirtd.aug --- a/qemud/libvirtd.aug +++ b/qemud/libvirtd.aug @@ -13,11 +13,13 @@ module Libvirtd = let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\"" let bool_val = store /0|1/ + let int_val = store /[0-9]+/ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ "" let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end let str_entry (kw:string) = [ key kw . value_sep . str_val ] let bool_entry (kw:string) = [ key kw . value_sep . bool_val ] + let int_entry (kw:string) = [ key kw . value_sep . int_val ] let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ] @@ -48,6 +50,9 @@ module Libvirtd = | str_array_entry "tls_allowed_dn_list" | str_array_entry "sasl_allowed_username_list" + let processing_entry = int_entry "min_workers" + | int_entry "max_workers" + | int_entry "max_clients" (* Each enty in the config is one of the following three ... *) let entry = network_entry @@ -55,6 +60,7 @@ module Libvirtd = | authentication_entry | certificate_entry | authorization_entry + | processing_entry let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ] let empty = [ label "#empty" . eol ] diff --git a/qemud/libvirtd.conf b/qemud/libvirtd.conf --- a/qemud/libvirtd.conf +++ b/qemud/libvirtd.conf @@ -225,3 +225,22 @@ #sasl_allowed_username_list = ["joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ] + +################################################################# +# +# Processing controls +# + +# The maximum number of concurrent client connections to allow +# over all sockets combined. +# max_clients = 20 + + +# The minimum limit sets the number of workers to start up +# initially. If the number of active clients exceeds this, +# then more threads are spawned, upto max_workers limit. +# Typically you'd want max_workers to equal maximum number +# of clients allowed +#min_workers = 5 +#max_workers = 20 + diff --git a/qemud/qemud.c b/qemud/qemud.c --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -129,6 +129,10 @@ static char *crl_file = (char *) ""; static gnutls_certificate_credentials_t x509_cred; static gnutls_dh_params_t dh_params; + +static int min_workers = 5; +static int max_workers = 20; +static int max_clients = 20; #define DH_BITS 1024 @@ -1167,6 +1171,12 @@ static int qemudDispatchServer(struct qe return -1; } + if (server->nclients >= max_clients) { + qemudLog(QEMUD_ERR, "%s", _("Too many active clients, dropping connection")); + close(fd); + return -1; + } + if (VIR_REALLOC_N(server->clients, server->nclients+1) < 0) { qemudLog(QEMUD_ERR, "%s", _("Out of memory allocating clients")); close(fd); @@ -1825,7 +1835,7 @@ static int qemudRunLoop(struct qemud_ser pthread_mutex_lock(&server->lock); - server->nworkers = 10; + server->nworkers = min_workers; if (VIR_ALLOC_N(server->workers, server->nworkers) < 0) { qemudLog(QEMUD_ERR, "%s", _("Failed to allocate workers")); return -1; @@ -2221,6 +2231,11 @@ remoteReadConfigFile (struct qemud_serve if (remoteReadSaslAllowedUsernameList (conf, server, filename) < 0) goto free_and_fail; + + + GET_CONF_INT (conf, filename, min_workers); + GET_CONF_INT (conf, filename, max_workers); + GET_CONF_INT (conf, filename, max_clients); virConfFree (conf); return 0; diff --git a/qemud/test_libvirtd.aug b/qemud/test_libvirtd.aug --- a/qemud/test_libvirtd.aug +++ b/qemud/test_libvirtd.aug @@ -227,6 +227,25 @@ sasl_allowed_username_list = [ \"joe@EXAMPLE.COM\", \"fred@EXAMPLE.COM\" ] + + +################################################################# +# +# Processing controls +# + +# The maximum number of concurrent client connections to allow +# over all sockets combined. +max_clients = 20 + + +# The minimum limit sets the number of workers to start up +# initially. If the number of active clients exceeds this, +# then more threads are spawned, upto max_workers limit. +# Typically you'd want max_workers to equal maximum number +# of clients allowed +min_workers = 5 +max_workers = 20 " test Libvirtd.lns get conf = @@ -461,3 +480,22 @@ sasl_allowed_username_list = [ { "1" = "joe@EXAMPLE.COM" } { "2" = "fred@EXAMPLE.COM" } } + { "#empty" } + { "#empty" } + { "#comment" = "################################################################"} + { "#comment" = ""} + { "#comment" = "Processing controls"} + { "#comment" = ""} + { "#empty" } + { "#comment" = "The maximum number of concurrent client connections to allow"} + { "#comment" = "over all sockets combined."} + { "max_clients" = "20" } + { "#empty" } + { "#empty" } + { "#comment" = "The minimum limit sets the number of workers to start up"} + { "#comment" = "initially. If the number of active clients exceeds this,"} + { "#comment" = "then more threads are spawned, upto max_workers limit."} + { "#comment" = "Typically you'd want max_workers to equal maximum number"} + { "#comment" = "of clients allowed"} + { "min_workers" = "5" } + { "max_workers" = "20" } -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:22:49AM +0000, Daniel P. Berrange wrote:
This patch extends the libvirtd configuration file to allow various thread related parameters to be tuned. It introduces a limit on the number of client connections allowed over TCP socket to prevent DOS attacks on the machine resources. It also adds a min/max worker thread pool size for handling RPC calls.
Ah back to simpler stuff :-) +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

The QEMU driver internal API for interacting with the monitor console takes a 'struct qemud_driver *' parameter. This is a problem because any access to this struct must be protected by a lock, but we do not want to hold the global driver lock for all monitor operations since it would destroy any hope of concurrency. Fortunately tracing down many levels of call reveals this parameter is totally unused, so this patch removes it from a tonne of internal APIs qemu_driver.c | 109 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 60 deletions(-) Daniel diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -136,8 +136,7 @@ static void qemudShutdownVMDaemon(virCon static int qemudDomainGetMaxVcpus(virDomainPtr dom); -static int qemudMonitorCommand (const struct qemud_driver *driver, - const virDomainObjPtr vm, +static int qemudMonitorCommand (const virDomainObjPtr vm, const char *cmd, char **reply); @@ -386,14 +385,12 @@ qemudShutdown(void) { /* Return -1 for error, 1 to continue reading and 0 for success */ typedef int qemudHandlerMonitorOutput(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, const char *output, int fd); static int qemudReadMonitorOutput(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, int fd, char *buf, @@ -452,7 +449,7 @@ qemudReadMonitorOutput(virConnectPtr con } else { got += ret; buf[got] = '\0'; - if ((ret = func(conn, driver, vm, buf, fd)) != 1) + if ((ret = func(conn, vm, buf, fd)) != 1) return ret; } } @@ -466,7 +463,6 @@ qemudReadMonitorOutput(virConnectPtr con static int qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED, - struct qemud_driver *driver ATTRIBUTE_UNUSED, virDomainObjPtr vm, const char *output, int fd) @@ -480,7 +476,6 @@ qemudCheckMonitorPrompt(virConnectPtr co } static int qemudOpenMonitor(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, const char *monitor) { int monfd; @@ -504,7 +499,7 @@ static int qemudOpenMonitor(virConnectPt } ret = qemudReadMonitorOutput(conn, - driver, vm, monfd, + vm, monfd, buf, sizeof(buf), qemudCheckMonitorPrompt, "monitor"); @@ -564,7 +559,6 @@ static int qemudExtractMonitorPath(virCo static int qemudFindCharDevicePTYs(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, const char *output, int fd ATTRIBUTE_UNUSED) @@ -603,7 +597,7 @@ qemudFindCharDevicePTYs(virConnectPtr co } /* Got them all, so now open the monitor console */ - ret = qemudOpenMonitor(conn, driver, vm, monitor); + ret = qemudOpenMonitor(conn, vm, monitor); cleanup: VIR_FREE(monitor); @@ -611,11 +605,10 @@ cleanup: } static int qemudWaitForMonitor(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm) { char buf[1024]; /* Plenty of space to get startup greeting */ int ret = qemudReadMonitorOutput(conn, - driver, vm, vm->stderr_fd, + vm, vm->stderr_fd, buf, sizeof(buf), qemudFindCharDevicePTYs, "console"); @@ -632,7 +625,6 @@ static int qemudWaitForMonitor(virConnec static int qemudDetectVcpuPIDs(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm) { char *qemucpus = NULL; char *line; @@ -656,7 +648,7 @@ qemudDetectVcpuPIDs(virConnectPtr conn, return 0; } - if (qemudMonitorCommand(driver, vm, "info cpus", &qemucpus) < 0) { + if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot run monitor command to fetch CPU thread info")); VIR_FREE(vm->vcpupids); @@ -732,7 +724,6 @@ error: static int qemudInitCpus(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, const char *migrateFrom) { char *info = NULL; @@ -772,7 +763,7 @@ qemudInitCpus(virConnectPtr conn, if (migrateFrom == NULL) { /* Allow the CPUS to start executing */ - if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { + if (qemudMonitorCommand(vm, "cont", &info) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resume operation failed")); return -1; @@ -999,9 +990,9 @@ static int qemudStartVMDaemon(virConnect VIR_EVENT_HANDLE_HANGUP, qemudDispatchVMEvent, driver, NULL)) < 0) || - (qemudWaitForMonitor(conn, driver, vm) < 0) || - (qemudDetectVcpuPIDs(conn, driver, vm) < 0) || - (qemudInitCpus(conn, driver, vm, migrateFrom) < 0)) { + (qemudWaitForMonitor(conn, vm) < 0) || + (qemudDetectVcpuPIDs(conn, vm) < 0) || + (qemudInitCpus(conn, vm, migrateFrom) < 0)) { qemudShutdownVMDaemon(conn, driver, vm); return -1; } @@ -1143,8 +1134,7 @@ cleanup: } static int -qemudMonitorCommand (const struct qemud_driver *driver ATTRIBUTE_UNUSED, - const virDomainObjPtr vm, +qemudMonitorCommand (const virDomainObjPtr vm, const char *cmd, char **reply) { int size = 0; @@ -1683,7 +1673,7 @@ static int qemudDomainSuspend(virDomainP goto cleanup; } if (vm->state != VIR_DOMAIN_PAUSED) { - if (qemudMonitorCommand(driver, vm, "stop", &info) < 0) { + if (qemudMonitorCommand(vm, "stop", &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("suspend operation failed")); goto cleanup; @@ -1732,7 +1722,7 @@ static int qemudDomainResume(virDomainPt goto cleanup; } if (vm->state == VIR_DOMAIN_PAUSED) { - if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { + if (qemudMonitorCommand(vm, "cont", &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("resume operation failed")); goto cleanup; @@ -1774,7 +1764,7 @@ static int qemudDomainShutdown(virDomain goto cleanup; } - if (qemudMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { + if (qemudMonitorCommand(vm, "system_powerdown", &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("shutdown operation failed")); goto cleanup; @@ -2171,7 +2161,7 @@ static int qemudDomainSave(virDomainPtr goto cleanup; } - if (qemudMonitorCommand(driver, vm, command, &info) < 0) { + if (qemudMonitorCommand(vm, command, &info) < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("migrate operation failed")); goto cleanup; @@ -2541,7 +2531,7 @@ static int qemudDomainRestore(virConnect /* If it was running before, resume it now. */ if (header.was_running) { char *info; - if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { + if (qemudMonitorCommand(vm, "cont", &info) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to resume domain")); goto cleanup; @@ -2821,7 +2811,6 @@ static char *qemudDiskDeviceName(const v } static int qemudDomainChangeEjectableMedia(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { @@ -2905,7 +2894,7 @@ static int qemudDomainChangeEjectableMed } VIR_FREE(devname); - if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { + if (qemudMonitorCommand(vm, cmd, &reply) < 0) { qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot change cdrom media")); VIR_FREE(cmd); @@ -2934,7 +2923,6 @@ static int qemudDomainChangeEjectableMed } static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { @@ -2971,7 +2959,7 @@ static int qemudDomainAttachPciDiskDevic return ret; } - if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { + if (qemudMonitorCommand(vm, cmd, &reply) < 0) { qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, _("cannot attach %s disk"), type); VIR_FREE(cmd); @@ -3006,7 +2994,6 @@ static int qemudDomainAttachPciDiskDevic } static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { @@ -3041,7 +3028,7 @@ static int qemudDomainAttachUsbMassstora return ret; } - if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { + if (qemudMonitorCommand(vm, cmd, &reply) < 0) { qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot attach usb disk")); VIR_FREE(cmd); @@ -3070,7 +3057,6 @@ static int qemudDomainAttachUsbMassstora } static int qemudDomainAttachHostDevice(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { @@ -3096,7 +3082,7 @@ static int qemudDomainAttachHostDevice(v return -1; } - if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { + if (qemudMonitorCommand(vm, cmd, &reply) < 0) { qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("cannot attach usb device")); VIR_FREE(cmd); @@ -3132,12 +3118,14 @@ static int qemudDomainAttachDevice(virDo qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - goto cleanup; - } - - if (!virDomainIsActive(vm)) { + qemuDriverUnlock(driver); + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + "%s", _("no domain with matching uuid")); + goto cleanup; + } + + if (!virDomainIsActive(vm)) { + qemuDriverUnlock(driver); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot attach device on inactive domain")); goto cleanup; @@ -3146,6 +3134,7 @@ static int qemudDomainAttachDevice(virDo dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml); + qemuDriverUnlock(driver); if (dev == NULL) goto cleanup; @@ -3154,14 +3143,14 @@ static int qemudDomainAttachDevice(virDo switch (dev->data.disk->device) { case VIR_DOMAIN_DISK_DEVICE_CDROM: case VIR_DOMAIN_DISK_DEVICE_FLOPPY: - ret = qemudDomainChangeEjectableMedia(dom->conn, driver, vm, dev); + ret = qemudDomainChangeEjectableMedia(dom->conn, vm, dev); break; case VIR_DOMAIN_DISK_DEVICE_DISK: if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { - ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, driver, vm, dev); + ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, vm, dev); } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - ret = qemudDomainAttachPciDiskDevice(dom->conn, driver, vm, dev); + ret = qemudDomainAttachPciDiskDevice(dom->conn, vm, dev); } break; default: @@ -3172,7 +3161,7 @@ static int qemudDomainAttachDevice(virDo } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { - ret = qemudDomainAttachHostDevice(dom->conn, driver, vm, dev); + ret = qemudDomainAttachHostDevice(dom->conn, vm, dev); } else { qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("this device type cannot be attached")); @@ -3183,12 +3172,10 @@ cleanup: virDomainDeviceDefFree(dev); if (vm) virDomainObjUnlock(vm); - qemuDriverUnlock(driver); return ret; } static int qemudDomainDetachPciDiskDevice(virConnectPtr conn, - struct qemud_driver *driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { int i, ret = -1; @@ -3222,7 +3209,7 @@ static int qemudDomainDetachPciDiskDevic goto cleanup; } - if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { + if (qemudMonitorCommand(vm, cmd, &reply) < 0) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("failed to execute detach disk %s command"), detach->dst); goto cleanup; @@ -3268,18 +3255,21 @@ static int qemudDomainDetachDevice(virDo qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); if (!vm) { - qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, - "%s", _("no domain with matching uuid")); - goto cleanup; - } - - if (!virDomainIsActive(vm)) { + qemuDriverUnlock(driver); + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + "%s", _("no domain with matching uuid")); + goto cleanup; + } + + if (!virDomainIsActive(vm)) { + qemuDriverUnlock(driver); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot attach device on inactive domain")); goto cleanup; } dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml); + qemuDriverUnlock(driver); if (dev == NULL) goto cleanup; @@ -3288,7 +3278,7 @@ static int qemudDomainDetachDevice(virDo dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK && (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)) - ret = qemudDomainDetachPciDiskDevice(dom->conn, driver, vm, dev); + ret = qemudDomainDetachPciDiskDevice(dom->conn, vm, dev); else qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", _("only SCSI or virtio disk device can be detached dynamically")); @@ -3297,7 +3287,6 @@ cleanup: virDomainDeviceDefFree(dev); if (vm) virDomainObjUnlock(vm); - qemuDriverUnlock(driver); return ret; } @@ -3444,7 +3433,7 @@ qemudDomainBlockStats (virDomainPtr dom, goto cleanup; len = strlen (qemu_dev_name); - if (qemudMonitorCommand (driver, vm, "info blockstats", &info) < 0) { + if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("'info blockstats' command failed")); goto cleanup; @@ -3710,7 +3699,7 @@ qemudDomainMemoryPeek (virDomainPtr dom, /* Issue the memsave command. */ snprintf (cmd, sizeof cmd, "memsave %llu %zi \"%s\"", offset, size, tmp); - if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) { + if (qemudMonitorCommand (vm, cmd, &info) < 0) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("'memsave' command failed")); goto cleanup; @@ -4028,7 +4017,7 @@ qemudDomainMigratePerform (virDomainPtr if (!(flags & VIR_MIGRATE_LIVE)) { /* Pause domain for non-live migration */ snprintf(cmd, sizeof cmd, "%s", "stop"); - qemudMonitorCommand (driver, vm, cmd, &info); + qemudMonitorCommand (vm, cmd, &info); DEBUG ("stop reply: %s", info); VIR_FREE(info); @@ -4043,7 +4032,7 @@ qemudDomainMigratePerform (virDomainPtr if (resource > 0) { /* Issue migrate_set_speed command. Don't worry if it fails. */ snprintf (cmd, sizeof cmd, "migrate_set_speed %lum", resource); - qemudMonitorCommand (driver, vm, cmd, &info); + qemudMonitorCommand (vm, cmd, &info); DEBUG ("migrate_set_speed reply: %s", info); VIR_FREE (info); @@ -4059,7 +4048,7 @@ qemudDomainMigratePerform (virDomainPtr snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri); VIR_FREE (safe_uri); - if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) { + if (qemudMonitorCommand (vm, cmd, &info) < 0) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("migrate operation failed")); goto cleanup; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:25:17AM +0000, Daniel P. Berrange wrote:
The QEMU driver internal API for interacting with the monitor console takes a 'struct qemud_driver *' parameter. This is a problem because any access to this struct must be protected by a lock, but we do not want to hold the global driver lock for all monitor operations since it would destroy any hope of concurrency. Fortunately tracing down many levels of call reveals this parameter is totally unused, so this patch removes it from a tonne of internal APIs
Okay, seems we're mostly just removing the driver parameter from most calls, rather simple, we're lucky :-) +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This is a diffstat summary for the combined series of 28 patches b/Makefile.maint | 1 b/qemud/Makefile.am | 24 b/qemud/THREADING.txt | 63 b/qemud/event.c | 168 + b/qemud/event.h | 14 b/qemud/libvirtd.aug | 6 b/qemud/libvirtd.conf | 19 b/qemud/qemud.c | 273 ++- b/qemud/qemud.h | 34 b/qemud/remote.c | 3030 ++++++++++++++++++----------------- b/qemud/remote_dispatch_args.h | 101 + b/qemud/remote_dispatch_prototypes.h | 936 +++++++++- b/qemud/remote_dispatch_ret.h | 88 + b/qemud/remote_dispatch_table.h | 594 ++++++ b/qemud/remote_generate_stubs.pl | 197 -- b/qemud/test_libvirtd.aug | 38 b/src/datatypes.c | 1 b/src/datatypes.h | 1 b/src/domain_conf.c | 56 b/src/domain_conf.h | 4 b/src/domain_event.c | 191 +- b/src/domain_event.h | 51 b/src/libvirt.c | 14 b/src/libvirt_sym.version.in | 25 b/src/lxc_conf.h | 2 b/src/lxc_driver.c | 453 +++-- b/src/network_conf.c | 54 b/src/network_conf.h | 5 b/src/network_driver.c | 439 +++-- b/src/node_device.c | 118 + b/src/node_device.h | 4 b/src/node_device_conf.c | 36 b/src/node_device_conf.h | 8 b/src/node_device_devkit.c | 41 b/src/node_device_hal.c | 166 + b/src/openvz_conf.h | 2 b/src/openvz_driver.c | 493 +++-- b/src/qemu_conf.h | 5 b/src/qemu_driver.c | 2321 +++++++++++++++----------- b/src/remote_internal.c | 93 - b/src/storage_conf.c | 44 b/src/storage_conf.h | 7 b/src/storage_driver.c | 860 ++++++--- b/src/test.c | 2016 +++++++++++++++++------ b/src/uml_conf.h | 2 b/src/uml_driver.c | 617 ++++--- b/src/xen_inotify.c | 135 - b/src/xen_unified.c | 30 b/src/xen_unified.h | 4 b/src/xs_internal.c | 56 b/tests/virsh-all | 1 qemud/remote_dispatch_localvars.h | 185 -- qemud/remote_dispatch_proc_switch.h | 898 ---------- 54 files changed, 9513 insertions(+), 5594 deletions(-) Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition, thanks ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Dec 03, 2008 at 04:18:21PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition,
I wrote some an OCaml program using CIL to check driver method exit paths and validate that all objects were left in an unlocked state. This found some real bugs ! So here's the incremental fixes for those diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -2128,7 +2128,7 @@ static int qemudDomainSave(virDomainPtr if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to write save header")); - return -1; + goto cleanup; } if (safewrite(fd, xml, header.xml_len) != header.xml_len) { diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -2393,7 +2393,7 @@ testStoragePoolCreate(virConnectPtr conn } if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) { - return NULL; + goto cleanup; } def = NULL; diff --git a/src/uml_driver.c b/src/uml_driver.c --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -251,6 +251,7 @@ reread: if (e->mask & IN_DELETE) { if (!virDomainIsActive(dom)) { + virDomainObjUnlock(dom); continue; } @@ -263,10 +264,12 @@ reread: dom->state = VIR_DOMAIN_SHUTOFF; } else if (e->mask & (IN_CREATE | IN_MODIFY)) { if (virDomainIsActive(dom)) { + virDomainObjUnlock(dom); continue; } if (umlReadPidFile(NULL, driver, dom) < 0) { + virDomainObjUnlock(dom); continue; } @@ -279,6 +282,7 @@ reread: if (umlIdentifyChrPTY(NULL, driver, dom) < 0) umlShutdownVMDaemon(NULL, driver, dom); } + virDomainObjUnlock(dom); } } Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Dec 03, 2008 at 06:52:32PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 04:18:21PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition,
I wrote some an OCaml program using CIL to check driver method exit paths and validate that all objects were left in an unlocked state. This found some real bugs !
So here's the incremental fixes for those [...]
Damn, I missed them :-) Is the CIL code too specific or too limited to share ? I must admit I looked for a bit on the CIL website and Rich details from his previous work on it: http://et.redhat.com/~rjones/cil-analysis-of-libvirt/ but the Ocaml language barrier somehow blocked me. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Dec 03, 2008 at 08:20:36PM +0100, Daniel Veillard wrote:
On Wed, Dec 03, 2008 at 06:52:32PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 04:18:21PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition,
I wrote some an OCaml program using CIL to check driver method exit paths and validate that all objects were left in an unlocked state. This found some real bugs !
So here's the incremental fixes for those [...]
Damn, I missed them :-)
Is the CIL code too specific or too limited to share ? I must admit I looked for a bit on the CIL website and Rich details from his previous work on it: http://et.redhat.com/~rjones/cil-analysis-of-libvirt/ but the Ocaml language barrier somehow blocked me.
I started off from Rich's example, and then bashed my head again a brick for 2 days and the attached file is the result :-) Basically CIL is able to parse the GCC intermediate files - the .i files generated from -save-temps. It can compute the control flow information - eg various paths from if/while/switch statements. There's a handy module called 'DataFlow' which traverses the graph and invokes an instance of what they call the 'ForwardsTransfer' module interface. This is what you implement todo your analysis on the code. I've tried to stuff a bunch of comments in my code to explain what I'm doing. The key thing is that I'm not attempting to solve the general problem of checking thread safety in arbitrary code. That would justbe insane & impossible. Instead I'm only trying to analyse the internal driver API entry points for each driver we have and so far just checking everything is unlocked upon exit. Its fairly easy to extend to track other rules we define. eg validate that you lock the 'qemud_driver *' object before locking the virDomainObjPtr instance. These libvirt specific rules I apply are what makes the analysis even remotely practical. I'll document this more fully & try and figure out how we can integrate it into our build system, but here's my quick notes on how I use it - Edit gnulib/lib/c-ctype.h, gnulib/lib/c-ctype.c, src/xmlrpc.c src/xmlrpc.h, src/cgroup.c and replace all references to the datatype 'bool' with 'char' CIL wants the compiler temporary files (eg -save-tmps) but thse include 'bool' data types, and it doesn't know how to handle them so I have to remove them by editing the source. - Run 'make distclean' and 'find -name *.i | xargs rm' - Run autogen.sh as normal - Run make CFLAGS="-save-temps -g -O0" - Install 'ocaml-devel', 'ocaml-cil-devel', 'ocaml-findlib' RPMS - Edit cilvirtflow.ml and find where it says '/home/berrange/....' and make that point to your libvirt directory. - Compile the program ocamlfind ocamlopt -package unix,str,cil -c cilvirtflow.ml ocamlfind ocamlopt -package unix,str,cil cilvirtflow.cmx -linkpkg -o cilvirtflow - Run the analysis ./cilvirtflow If all went to plan it should print out a huge report along the lines of this - this is without my fixes from a few minutes ago - showing the kind of info it gives for identifying bugs Function: qemuDriverLock - Total exit points with locked vars: 0 Function: qemuDriverUnlock - Total exit points with locked vars: 0 Function: qemudSetCloseExec - Total exit points with locked vars: 0 Function: qemudSetNonBlock - Total exit points with locked vars: 0 Function: qemudAutostartConfigs - Total exit points with locked vars: 0 Function: qemudStartup - Total exit points with locked vars: 0 Function: qemudNotifyLoadDomain - Total exit points with locked vars: 0 Function: qemudReload - Total exit points with locked vars: 0 Function: qemudActive - Total exit points with locked vars: 0 Function: qemudShutdown - Total exit points with locked vars: 0 Function: qemudReadMonitorOutput - Total exit points with locked vars: 0 Function: qemudCheckMonitorPrompt - Total exit points with locked vars: 0 Function: qemudOpenMonitor - Total exit points with locked vars: 0 Function: qemudExtractMonitorPath - Total exit points with locked vars: 0 Function: qemudFindCharDevicePTYs - Total exit points with locked vars: 0 Function: qemudWaitForMonitor - Total exit points with locked vars: 0 Function: qemudDetectVcpuPIDs - Total exit points with locked vars: 0 Function: qemudInitCpus - Total exit points with locked vars: 0 Function: qemudNextFreeVNCPort - Total exit points with locked vars: 0 Function: qemudStartVMDaemon - Total exit points with locked vars: 0 Function: qemudVMData - Total exit points with locked vars: 0 Function: qemudShutdownVMDaemon - Total exit points with locked vars: 0 Function: qemudDispatchVMEvent - Total exit points with locked vars: 0 Function: qemudMonitorCommand - Total exit points with locked vars: 0 Function: qemudProbe - Total exit points with locked vars: 0 Function: qemudOpen - Total exit points with locked vars: 0 Function: qemudClose - Total exit points with locked vars: 0 Function: qemudSupportsFeature - Total exit points with locked vars: 0 Function: qemudGetType - Total exit points with locked vars: 0 Function: qemudGetMaxVCPUs - Total exit points with locked vars: 0 Function: qemudGetNodeInfo - Total exit points with locked vars: 0 Function: qemudGetCapabilities - Total exit points with locked vars: 0 Function: qemudNodeGetCellsFreeMemory - Total exit points with locked vars: 0 Function: qemudNodeGetFreeMemory - Total exit points with locked vars: 0 Function: qemudGetProcessInfo - Total exit points with locked vars: 0 Function: qemudDomainLookupByID - Total exit points with locked vars: 0 Function: qemudDomainLookupByUUID - Total exit points with locked vars: 0 Function: qemudDomainLookupByName - Total exit points with locked vars: 0 Function: qemudGetVersion - Total exit points with locked vars: 0 Function: qemudGetHostname - Total exit points with locked vars: 0 Function: qemudListDomains - Total exit points with locked vars: 0 Function: qemudNumDomains - Total exit points with locked vars: 0 Function: qemudDomainCreate - Total exit points with locked vars: 0 Function: qemudDomainSuspend - Total exit points with locked vars: 0 Function: qemudDomainResume - Total exit points with locked vars: 0 Function: qemudDomainShutdown - Total exit points with locked vars: 0 Function: qemudDomainDestroy - Total exit points with locked vars: 0 Function: qemudDomainGetOSType - Total exit points with locked vars: 0 Function: qemudDomainGetMaxMemory - Total exit points with locked vars: 0 Function: qemudDomainSetMaxMemory - Total exit points with locked vars: 0 Function: qemudDomainSetMemory - Total exit points with locked vars: 0 Function: qemudDomainGetInfo - Total exit points with locked vars: 0 Function: qemudEscape - Total exit points with locked vars: 0 Function: qemudEscapeMonitorArg - Total exit points with locked vars: 0 Function: qemudEscapeShellArg - Total exit points with locked vars: 0 Function: qemudDomainSave - Total exit points with locked vars: 1 - Locked vars at exit #line 2131 "qemu_driver.c" return (-1); ^^^^^^^^^ >>>>Drivers < Var: driver 14905 >>>>Objects < Var: vm 14906 Function: qemudDomainSetVcpus - Total exit points with locked vars: 0 Function: qemudDomainPinVcpu - Total exit points with locked vars: 0 Function: qemudDomainGetVcpus - Total exit points with locked vars: 0 Function: qemudDomainGetMaxVcpus - Total exit points with locked vars: 0 Function: qemudDomainRestore - Total exit points with locked vars: 0 Function: qemudDomainDumpXML - Total exit points with locked vars: 0 Function: qemudListDefinedDomains - Total exit points with locked vars: 0 Function: qemudNumDefinedDomains - Total exit points with locked vars: 0 Function: qemudDomainStart - Total exit points with locked vars: 0 Function: qemudDomainDefine - Total exit points with locked vars: 0 Function: qemudDomainUndefine - Total exit points with locked vars: 0 Function: qemudDiskDeviceName - Total exit points with locked vars: 0 Function: qemudDomainChangeEjectableMedia - Total exit points with locked vars: 0 Function: qemudDomainAttachPciDiskDevice - Total exit points with locked vars: 0 Function: qemudDomainAttachUsbMassstorageDevice - Total exit points with locked vars: 0 Function: qemudDomainAttachHostDevice - Total exit points with locked vars: 0 Function: qemudDomainAttachDevice - Total exit points with locked vars: 0 Function: qemudDomainDetachPciDiskDevice - Total exit points with locked vars: 0 Function: qemudDomainDetachDevice - Total exit points with locked vars: 0 Function: qemudDomainGetAutostart - Total exit points with locked vars: 0 Function: qemudDomainSetAutostart - Total exit points with locked vars: 0 Function: qemudDomainBlockStats - Total exit points with locked vars: 0 Function: qemudDomainInterfaceStats - Total exit points with locked vars: 0 Function: qemudDomainBlockPeek - Total exit points with locked vars: 0 Function: qemudDomainMemoryPeek - Total exit points with locked vars: 0 Function: qemudDomainEventRegister - Total exit points with locked vars: 0 Function: qemudDomainEventDeregister - Total exit points with locked vars: 0 Function: qemuDomainEventDispatchFunc - Total exit points with locked vars: 1 - Locked vars at exit #line 3777 return; ^^^^^^^^^ >>>>Drivers < Var: driver 16606 >>>>Objects < Function: qemuDomainEventFlush - Total exit points with locked vars: 0 Function: qemuDomainEventQueue - Total exit points with locked vars: 0 Function: qemudDomainMigratePrepare2 - Total exit points with locked vars: 0 Function: qemudDomainMigratePerform - Total exit points with locked vars: 0 Function: qemudDomainMigrateFinish2 - Total exit points with locked vars: 0 Function: qemuRegister - Total exit points with locked vars: 0 Function: umlDriverLock - Total exit points with locked vars: 0 Function: umlDriverUnlock - Total exit points with locked vars: 0 Function: umlSetCloseExec - Total exit points with locked vars: 0 Function: umlAutostartConfigs - Total exit points with locked vars: 0 Function: umlIdentifyOneChrPTY - Total exit points with locked vars: 0 Function: umlIdentifyChrPTY - Total exit points with locked vars: 0 Function: umlInotifyEvent - Total exit points with locked vars: 3 - Locked vars at exit #line 232 "uml_driver.c" return; ^^^^^^^^^ >>>>Drivers < >>>>Objects < Var: dom 30814 - Locked vars at exit #line 239 return; ^^^^^^^^^ >>>>Drivers < >>>>Objects < Var: dom 30814 - Locked vars at exit #line 283 return; ^^^^^^^^^ >>>>Drivers < >>>>Objects < Var: dom 30814 Function: umlStartup - Total exit points with locked vars: 0 Function: umlReload - Total exit points with locked vars: 0 Function: umlActive - Total exit points with locked vars: 0 Function: umlShutdown - Total exit points with locked vars: 0 Function: umlReadPidFile - Total exit points with locked vars: 0 Function: umlMonitorAddress - Total exit points with locked vars: 0 Function: umlOpenMonitor - Total exit points with locked vars: 0 Function: umlMonitorCommand - Total exit points with locked vars: 0 Function: umlStartVMDaemon - Total exit points with locked vars: 0 Function: umlShutdownVMDaemon - Total exit points with locked vars: 0 Function: umlOpen - Total exit points with locked vars: 0 Function: umlClose - Total exit points with locked vars: 0 Function: umlGetType - Total exit points with locked vars: 0 Function: umlGetNodeInfo - Total exit points with locked vars: 0 Function: umlGetCapabilities - Total exit points with locked vars: 0 Function: umlNodeGetCellsFreeMemory - Total exit points with locked vars: 0 Function: umlNodeGetFreeMemory - Total exit points with locked vars: 0 Function: umlGetProcessInfo - Total exit points with locked vars: 0 Function: umlDomainLookupByID - Total exit points with locked vars: 0 Function: umlDomainLookupByUUID - Total exit points with locked vars: 0 Function: umlDomainLookupByName - Total exit points with locked vars: 0 Function: umlGetVersion - Total exit points with locked vars: 0 Function: umlGetHostname - Total exit points with locked vars: 0 Function: umlListDomains - Total exit points with locked vars: 0 Function: umlNumDomains - Total exit points with locked vars: 0 Function: umlDomainCreate - Total exit points with locked vars: 0 Function: umlDomainShutdown - Total exit points with locked vars: 0 Function: umlDomainDestroy - Total exit points with locked vars: 0 Function: umlDomainGetOSType - Total exit points with locked vars: 0 Function: umlDomainGetMaxMemory - Total exit points with locked vars: 0 Function: umlDomainSetMaxMemory - Total exit points with locked vars: 0 Function: umlDomainSetMemory - Total exit points with locked vars: 0 Function: umlDomainGetInfo - Total exit points with locked vars: 0 Function: umlDomainDumpXML - Total exit points with locked vars: 0 Function: umlListDefinedDomains - Total exit points with locked vars: 0 Function: umlNumDefinedDomains - Total exit points with locked vars: 0 Function: umlDomainStart - Total exit points with locked vars: 0 Function: umlDomainDefine - Total exit points with locked vars: 0 Function: umlDomainUndefine - Total exit points with locked vars: 0 Function: umlDomainGetAutostart - Total exit points with locked vars: 0 Function: umlDomainSetAutostart - Total exit points with locked vars: 0 Function: umlDomainBlockPeek - Total exit points with locked vars: 0 Function: umlRegister - Total exit points with locked vars: 0 Function: lxcDriverLock - Total exit points with locked vars: 0 Function: lxcDriverUnlock - Total exit points with locked vars: 0 Function: lxcProbe - Total exit points with locked vars: 0 Function: lxcOpen - Total exit points with locked vars: 0 Function: lxcClose - Total exit points with locked vars: 0 Function: lxcDomainLookupByID - Total exit points with locked vars: 0 Function: lxcDomainLookupByUUID - Total exit points with locked vars: 0 Function: lxcDomainLookupByName - Total exit points with locked vars: 0 Function: lxcListDomains - Total exit points with locked vars: 0 Function: lxcNumDomains - Total exit points with locked vars: 0 Function: lxcListDefinedDomains - Total exit points with locked vars: 0 Function: lxcNumDefinedDomains - Total exit points with locked vars: 0 Function: lxcDomainDefine - Total exit points with locked vars: 0 Function: lxcDomainUndefine - Total exit points with locked vars: 0 Function: lxcDomainGetInfo - Total exit points with locked vars: 0 Function: lxcGetOSType - Total exit points with locked vars: 0 Function: lxcDomainDumpXML - Total exit points with locked vars: 0 Function: lxcVMCleanup - Total exit points with locked vars: 0 Function: lxcSetupInterfaces - Total exit points with locked vars: 0 Function: lxcMonitorClient - Total exit points with locked vars: 0 Function: lxcVmTerminate - Total exit points with locked vars: 0 Function: lxcMonitorEvent - Total exit points with locked vars: 0 Function: lxcControllerStart - Total exit points with locked vars: 0 Function: lxcVmStart - Total exit points with locked vars: 0 Function: lxcDomainStart - Total exit points with locked vars: 0 Function: lxcDomainCreateAndStart - Total exit points with locked vars: 0 Function: lxcDomainShutdown - Total exit points with locked vars: 0 Function: lxcDomainDestroy - Total exit points with locked vars: 0 Function: lxcCheckNetNsSupport - Total exit points with locked vars: 0 Function: lxcStartup - Total exit points with locked vars: 0 Function: lxcShutdown - Total exit points with locked vars: 0 Function: lxcActive - Total exit points with locked vars: 0 Function: lxcVersion - Total exit points with locked vars: 0 Function: lxcGetSchedulerType - Total exit points with locked vars: 0 Function: lxcSetSchedulerParameters - Total exit points with locked vars: 0 Function: lxcGetSchedulerParameters - Total exit points with locked vars: 0 Function: lxcRegister - Total exit points with locked vars: 0 Function: openvzDriverLock - Total exit points with locked vars: 0 Function: openvzDriverUnlock - Total exit points with locked vars: 0 Function: openvzDomainDefineCmd - Total exit points with locked vars: 0 Function: openvzDomainLookupByID - Total exit points with locked vars: 0 Function: openvzGetVersion - Total exit points with locked vars: 0 Function: openvzGetOSType - Total exit points with locked vars: 0 Function: openvzDomainLookupByUUID - Total exit points with locked vars: 0 Function: openvzDomainLookupByName - Total exit points with locked vars: 0 Function: openvzDomainGetInfo - Total exit points with locked vars: 0 Function: openvzDomainDumpXML - Total exit points with locked vars: 0 Function: openvzSetProgramSentinal - Total exit points with locked vars: 0 Function: openvzDomainShutdown - Total exit points with locked vars: 0 Function: openvzDomainReboot - Total exit points with locked vars: 0 Function: openvzGenerateVethName - Total exit points with locked vars: 0 Function: openvzGenerateContainerVethName - Total exit points with locked vars: 0 Function: openvzDomainSetNetwork - Total exit points with locked vars: 0 Function: openvzDomainSetNetworkConfig - Total exit points with locked vars: 0 Function: openvzDomainDefineXML - Total exit points with locked vars: 0 Function: openvzDomainCreateXML - Total exit points with locked vars: 0 Function: openvzDomainCreate - Total exit points with locked vars: 0 Function: openvzDomainUndefine - Total exit points with locked vars: 0 Function: openvzDomainSetAutostart - Total exit points with locked vars: 0 Function: openvzDomainGetAutostart - Total exit points with locked vars: 0 Function: openvzGetMaxVCPUs - Total exit points with locked vars: 0 Function: openvzDomainGetMaxVcpus - Total exit points with locked vars: 0 Function: openvzDomainSetVcpus - Total exit points with locked vars: 0 Function: openvzProbe - Total exit points with locked vars: 0 Function: openvzOpen - Total exit points with locked vars: 0 Function: openvzClose - Total exit points with locked vars: 0 Function: openvzGetType - Total exit points with locked vars: 0 Function: openvzGetNodeInfo - Total exit points with locked vars: 0 Function: openvzGetCapabilities - Total exit points with locked vars: 0 Function: openvzListDomains - Total exit points with locked vars: 0 Function: openvzNumDomains - Total exit points with locked vars: 0 Function: openvzListDefinedDomains - Total exit points with locked vars: 0 Function: openvzGetProcessInfo - Total exit points with locked vars: 0 Function: openvzNumDefinedDomains - Total exit points with locked vars: 0 Function: openvzRegister - Total exit points with locked vars: 0 Function: testDriverLock - Total exit points with locked vars: 0 Function: testDriverUnlock - Total exit points with locked vars: 0 Function: testBuildCapabilities - Total exit points with locked vars: 0 Function: testOpenDefault - Total exit points with locked vars: 0 Function: testBuildFilename - Total exit points with locked vars: 0 Function: testOpenFromFile - Total exit points with locked vars: 0 Function: testOpen - Total exit points with locked vars: 0 Function: testClose - Total exit points with locked vars: 0 Function: testGetVersion - Total exit points with locked vars: 0 Function: testGetHostname - Total exit points with locked vars: 0 Function: testGetMaxVCPUs - Total exit points with locked vars: 0 Function: testNodeGetInfo - Total exit points with locked vars: 0 Function: testGetCapabilities - Total exit points with locked vars: 0 Function: testNumOfDomains - Total exit points with locked vars: 0 Function: testDomainCreateXML - Total exit points with locked vars: 0 Function: testLookupDomainByID - Total exit points with locked vars: 0 Function: testLookupDomainByUUID - Total exit points with locked vars: 0 Function: testLookupDomainByName - Total exit points with locked vars: 0 Function: testListDomains - Total exit points with locked vars: 0 Function: testDestroyDomain - Total exit points with locked vars: 0 Function: testResumeDomain - Total exit points with locked vars: 0 Function: testPauseDomain - Total exit points with locked vars: 0 Function: testShutdownDomain - Total exit points with locked vars: 0 Function: testRebootDomain - Total exit points with locked vars: 0 Function: testGetDomainInfo - Total exit points with locked vars: 0 Function: testDomainSave - Total exit points with locked vars: 0 Function: testDomainRestore - Total exit points with locked vars: 0 Function: testDomainCoreDump - Total exit points with locked vars: 0 Function: testGetOSType - Total exit points with locked vars: 0 Function: testGetMaxMemory - Total exit points with locked vars: 0 Function: testSetMaxMemory - Total exit points with locked vars: 0 Function: testSetMemory - Total exit points with locked vars: 0 Function: testSetVcpus - Total exit points with locked vars: 0 Function: testDomainDumpXML - Total exit points with locked vars: 0 Function: testNumOfDefinedDomains - Total exit points with locked vars: 0 Function: testListDefinedDomains - Total exit points with locked vars: 0 Function: testDomainDefineXML - Total exit points with locked vars: 0 Function: testNodeGetCellsFreeMemory - Total exit points with locked vars: 0 Function: testDomainCreate - Total exit points with locked vars: 0 Function: testDomainUndefine - Total exit points with locked vars: 0 Function: testDomainGetAutostart - Total exit points with locked vars: 0 Function: testDomainSetAutostart - Total exit points with locked vars: 0 Function: testDomainGetSchedulerType - Total exit points with locked vars: 0 Function: testDomainGetSchedulerParams - Total exit points with locked vars: 0 Function: testDomainSetSchedulerParams - Total exit points with locked vars: 0 Function: testOpenNetwork - Total exit points with locked vars: 0 Function: testCloseNetwork - Total exit points with locked vars: 0 Function: testLookupNetworkByUUID - Total exit points with locked vars: 0 Function: testLookupNetworkByName - Total exit points with locked vars: 0 Function: testNumNetworks - Total exit points with locked vars: 0 Function: testListNetworks - Total exit points with locked vars: 0 Function: testNumDefinedNetworks - Total exit points with locked vars: 0 Function: testListDefinedNetworks - Total exit points with locked vars: 0 Function: testNetworkCreate - Total exit points with locked vars: 0 Function: testNetworkDefine - Total exit points with locked vars: 0 Function: testNetworkUndefine - Total exit points with locked vars: 0 Function: testNetworkStart - Total exit points with locked vars: 0 Function: testNetworkDestroy - Total exit points with locked vars: 0 Function: testNetworkDumpXML - Total exit points with locked vars: 0 Function: testNetworkGetBridgeName - Total exit points with locked vars: 0 Function: testNetworkGetAutostart - Total exit points with locked vars: 0 Function: testNetworkSetAutostart - Total exit points with locked vars: 0 Function: testStoragePoolObjSetDefaults - Total exit points with locked vars: 0 Function: testStorageOpen - Total exit points with locked vars: 0 Function: testStorageClose - Total exit points with locked vars: 0 Function: testStoragePoolLookupByUUID - Total exit points with locked vars: 0 Function: testStoragePoolLookupByName - Total exit points with locked vars: 0 Function: testStoragePoolLookupByVolume - Total exit points with locked vars: 0 Function: testStorageNumPools - Total exit points with locked vars: 0 Function: testStorageListPools - Total exit points with locked vars: 0 Function: testStorageNumDefinedPools - Total exit points with locked vars: 0 Function: testStorageListDefinedPools - Total exit points with locked vars: 0 Function: testStoragePoolStart - Total exit points with locked vars: 0 Function: testStorageFindPoolSources - Total exit points with locked vars: 0 Function: testStoragePoolCreate - Total exit points with locked vars: 1 - Locked vars at exit #line 2396 "test.c" return ((virStoragePool *)((void *)0)); ^^^^^^^^^ >>>>Drivers < Var: privconn 73413 >>>>Objects < Function: testStoragePoolDefine - Total exit points with locked vars: 0 Function: testStoragePoolUndefine - Total exit points with locked vars: 0 Function: testStoragePoolBuild - Total exit points with locked vars: 0 Function: testStoragePoolDestroy - Total exit points with locked vars: 0 Function: testStoragePoolDelete - Total exit points with locked vars: 0 Function: testStoragePoolRefresh - Total exit points with locked vars: 0 Function: testStoragePoolGetInfo - Total exit points with locked vars: 0 Function: testStoragePoolDumpXML - Total exit points with locked vars: 0 Function: testStoragePoolGetAutostart - Total exit points with locked vars: 0 Function: testStoragePoolSetAutostart - Total exit points with locked vars: 0 Function: testStoragePoolNumVolumes - Total exit points with locked vars: 0 Function: testStoragePoolListVolumes - Total exit points with locked vars: 0 Function: testStorageVolumeLookupByName - Total exit points with locked vars: 0 Function: testStorageVolumeLookupByKey - Total exit points with locked vars: 0 Function: testStorageVolumeLookupByPath - Total exit points with locked vars: 0 Function: testStorageVolumeCreateXML - Total exit points with locked vars: 0 Function: testStorageVolumeDelete - Total exit points with locked vars: 0 Function: testStorageVolumeTypeForPool - Total exit points with locked vars: 0 Function: testStorageVolumeGetInfo - Total exit points with locked vars: 0 Function: testStorageVolumeGetXMLDesc - Total exit points with locked vars: 0 Function: testStorageVolumeGetPath - Total exit points with locked vars: 0 Function: testDevMonOpen - Total exit points with locked vars: 0 Function: testDevMonClose - Total exit points with locked vars: 0 Function: testRegister - Total exit points with locked vars: 0 Function: networkDriverLock - Total exit points with locked vars: 0 Function: networkDriverUnlock - Total exit points with locked vars: 0 Function: networkAutostartConfigs - Total exit points with locked vars: 0 Function: networkStartup - Total exit points with locked vars: 0 Function: networkReload - Total exit points with locked vars: 0 Function: networkActive - Total exit points with locked vars: 0 Function: networkShutdown - Total exit points with locked vars: 0 Function: networkBuildDnsmasqArgv - Total exit points with locked vars: 0 Function: networkAddMasqueradingIptablesRules - Total exit points with locked vars: 0 Function: networkAddRoutingIptablesRules - Total exit points with locked vars: 0 Function: networkAddIptablesRules - Total exit points with locked vars: 0 Function: networkRemoveIptablesRules - Total exit points with locked vars: 0 Function: networkEnableIpForwarding - Total exit points with locked vars: 0 Function: networkStartNetworkDaemon - Total exit points with locked vars: 0 Function: networkShutdownNetworkDaemon - Total exit points with locked vars: 0 Function: networkLookupByUUID - Total exit points with locked vars: 0 Function: networkLookupByName - Total exit points with locked vars: 0 Function: networkOpenNetwork - Total exit points with locked vars: 0 Function: networkCloseNetwork - Total exit points with locked vars: 0 Function: networkNumNetworks - Total exit points with locked vars: 0 Function: networkListNetworks - Total exit points with locked vars: 0 Function: networkNumDefinedNetworks - Total exit points with locked vars: 0 Function: networkListDefinedNetworks - Total exit points with locked vars: 0 Function: networkCreate - Total exit points with locked vars: 0 Function: networkDefine - Total exit points with locked vars: 0 Function: networkUndefine - Total exit points with locked vars: 0 Function: networkStart - Total exit points with locked vars: 0 Function: networkDestroy - Total exit points with locked vars: 0 Function: networkDumpXML - Total exit points with locked vars: 0 Function: networkGetBridgeName - Total exit points with locked vars: 0 Function: networkGetAutostart - Total exit points with locked vars: 0 Function: networkSetAutostart - Total exit points with locked vars: 0 Function: networkRegister - Total exit points with locked vars: 0 Function: nodeDeviceLock - Total exit points with locked vars: 0 Function: nodeDeviceUnlock - Total exit points with locked vars: 0 Function: nodeNumOfDevices - Total exit points with locked vars: 0 Function: nodeListDevices - Total exit points with locked vars: 0 Function: nodeDeviceLookupByName - Total exit points with locked vars: 0 Function: nodeDeviceDumpXML - Total exit points with locked vars: 0 Function: nodeDeviceGetParent - Total exit points with locked vars: 0 Function: nodeDeviceNumOfCaps - Total exit points with locked vars: 0 Function: nodeDeviceListCaps - Total exit points with locked vars: 0 Function: nodedevRegister - Total exit points with locked vars: 0 Function: nodeDeviceWatchFree - Total exit points with locked vars: 0 Function: storageDriverLock - Total exit points with locked vars: 0 Function: storageDriverUnlock - Total exit points with locked vars: 0 Function: storageDriverAutostart - Total exit points with locked vars: 0 Function: storageDriverStartup - Total exit points with locked vars: 0 Function: storageDriverReload - Total exit points with locked vars: 0 Function: storageDriverActive - Total exit points with locked vars: 0 Function: storageDriverShutdown - Total exit points with locked vars: 0 Function: storagePoolLookupByUUID - Total exit points with locked vars: 0 Function: storagePoolLookupByName - Total exit points with locked vars: 0 Function: storagePoolLookupByVolume - Total exit points with locked vars: 0 Function: storageOpen - Total exit points with locked vars: 0 Function: storageClose - Total exit points with locked vars: 0 Function: storageNumPools - Total exit points with locked vars: 0 Function: storageListPools - Total exit points with locked vars: 0 Function: storageNumDefinedPools - Total exit points with locked vars: 0 Function: storageListDefinedPools - Total exit points with locked vars: 0 Function: storageFindPoolSources - Total exit points with locked vars: 0 Function: storagePoolCreate - Total exit points with locked vars: 0 Function: storagePoolDefine - Total exit points with locked vars: 0 Function: storagePoolUndefine - Total exit points with locked vars: 0 Function: storagePoolStart - Total exit points with locked vars: 0 Function: storagePoolBuild - Total exit points with locked vars: 0 Function: storagePoolDestroy - Total exit points with locked vars: 0 Function: storagePoolDelete - Total exit points with locked vars: 0 Function: storagePoolRefresh - Total exit points with locked vars: 0 Function: storagePoolGetInfo - Total exit points with locked vars: 0 Function: storagePoolDumpXML - Total exit points with locked vars: 0 Function: storagePoolGetAutostart - Total exit points with locked vars: 0 Function: storagePoolSetAutostart - Total exit points with locked vars: 0 Function: storagePoolNumVolumes - Total exit points with locked vars: 0 Function: storagePoolListVolumes - Total exit points with locked vars: 0 Function: storageVolumeLookupByName - Total exit points with locked vars: 0 Function: storageVolumeLookupByKey - Total exit points with locked vars: 0 Function: storageVolumeLookupByPath - Total exit points with locked vars: 0 Function: storageVolumeCreateXML - Total exit points with locked vars: 0 Function: storageVolumeDelete - Total exit points with locked vars: 0 Function: storageVolumeGetInfo - Total exit points with locked vars: 0 Function: storageVolumeGetXMLDesc - Total exit points with locked vars: 0 Function: storageVolumeGetPath - Total exit points with locked vars: 0 Function: storageRegister - Total exit points with locked vars: 0 There was one false positive there qemuDomainEventDispatchFunc which is defined to expect a locked input & output, thus violating the assumptions in my program Oh, and it'll dump .dot files for the control flow graphs which you can view with 'dotty' Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Dec 03, 2008 at 07:44:02PM +0000, Daniel P. Berrange wrote:
Its fairly easy to extend to track other rules we define. eg validate that you lock the 'qemud_driver *' object before locking the virDomainObjPtr instance.
It can now also do - Check that you lock the driver before an object - Check that no objects are locked when locking the driver - Check for use of driver while unlocked - Check for use of objects while unlocked and takes into account access to global variables. eg, a report for the storage driver autostart bug DV identified earlier Function: storageDriverAutostart - Total exit points with locked vars: 0 - Total blocks with lock ordering mistakes: 7 - Object used while unlocked on #line 66 "storage_driver.c" tmp___5 = virStoragePoolObjIsActive(pool); - Object used while unlocked on #line 69 backend = virStorageBackendForType((pool->def)->type); - Object used while unlocked on #line 70 fprintf((FILE */* __restrict */)stderr, (char const */* __restrict */)"Missing backend %d", (pool->def)->type); - Object used while unlocked on #line 75 tmp___1 = (*(backend->startPool))((virConnect *)((void *)0), pool); - Object used while unlocked on #line 78 fprintf((FILE */* __restrict */)stderr, (char const */* __restrict */)"Failed to autostart storage pool \'%s\': %s", (pool->def)->name, tmp___0); - Object used while unlocked on #line 83 tmp___4 = (*(backend->refreshPool))((virConnect *)((void *)0), pool); - Object used while unlocked on #line 87 fprintf((FILE */* __restrict */)stderr, (char const */* __restrict */)"Failed to autostart storage pool \'%s\': %s", (pool->def)->name, tmp___3); Or a bugs I missed before Function: umlInotifyEvent - Total exit points with locked vars: 3 - Object locked while driver is unlocked on #line 246 dom = virDomainFindByName(& driver->domains, (char const *)name); Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

* Daniel P. Berrange (berrange@redhat.com) wrote:
(* * This is the list of all libvirt methods which return * pointers to locked objects *) let lockedObjMethods = [ "virDomainFindByID"; "virDomainFindByUUID"; "virDomainFindByName"; "virDomainAssignDef"; ...
All quite cool. Anyway to annotate the source so these tables don't get out of date?

On Wed, Dec 03, 2008 at 04:15:05PM -0800, Chris Wright wrote:
* Daniel P. Berrange (berrange@redhat.com) wrote:
(* * This is the list of all libvirt methods which return * pointers to locked objects *) let lockedObjMethods = [ "virDomainFindByID"; "virDomainFindByUUID"; "virDomainFindByName"; "virDomainAssignDef"; ...
All quite cool. Anyway to annotate the source so these tables don't get out of date?
We'd have to invent some annotation for parameters and return types to indicate whether they expect / return a locked object. Although actually thinking about it, in domain_conf.c, every single func which takes a virDomainObjPtr as a param expects it to be locked, and all which return such an object give it to you pre-locked. So I could just have it parse domain_conf.h and extract the list of APIs in that header. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Dec 03, 2008 at 11:57:54PM +0000, Daniel P. Berrange wrote:
let isLockableThingNull exp funcheck = match exp with | UnOp (op,exp,typ) -> ( match op with LNot -> ( match exp with Lval (lhost, off) -> ( match lhost with Var vi -> funcheck vi | _ -> false ) | _ -> false ) | _ -> false ) | _ -> false
I guess this is better written using a nested pattern, something like: let isLockableThingNull exp funcheck = match exp with | UnOp (LNot, Lval (Var vi, off), typ) when funcheck vi -> true | _ -> false
let isLockableObjectNull exp = isLockableThingNull exp isLockableObjectVar
let isLockableDriverNull exp = isLockableThingNull exp isLockableDriverVar
It doesn't really matter, but you can also hide subfunctions (and static variables) like this: let isLockableObjectNull, isLockableDriverNull = let isLockableThingNull exp funcheck = (* this function is hidden *) (* the definition above *) in let isLockableObjectNull exp = (* visible *) (* copy definition from above *) in let isLockableDriverNull exp = (* visible *) (* copy definition from above *) in isLockableObjectNull, isLockableDriverNull
module L = DF.ForwardsDataFlow(Locking)
CIL is kinda crazy isn't it :-(
let prefixes = [ "qem"; "uml"; "lxc"; "ope"; "tes"; "net"; "sto"; "nod" ] in if String.length name > 4 then let prefix = String.sub fundec.svar.vname 0 3 in
There's also a function String.starts_with. It's in extlib, so you need to compile with '-package extlib' and add 'open ExtString' at the top of the source file. Top marks for dealing with the sheer weirdness of CIL :-) Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my OCaml programming blog: http://camltastic.blogspot.com/ Fedora now supports 68 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora

On Wed, Dec 03, 2008 at 07:44:02PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 08:20:36PM +0100, Daniel Veillard wrote:
On Wed, Dec 03, 2008 at 06:52:32PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 04:18:21PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition,
I wrote some an OCaml program using CIL to check driver method exit paths and validate that all objects were left in an unlocked state. This found some real bugs !
So here's the incremental fixes for those [...]
Damn, I missed them :-)
Is the CIL code too specific or too limited to share ? I must admit I looked for a bit on the CIL website and Rich details from his previous work on it: http://et.redhat.com/~rjones/cil-analysis-of-libvirt/ but the Ocaml language barrier somehow blocked me.
I started off from Rich's example, and then bashed my head again a brick for 2 days and the attached file is the result :-)
All I can say is ... blimey. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my OCaml programming blog: http://camltastic.blogspot.com/ Fedora now supports 68 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora

On Wed, Dec 03, 2008 at 06:52:32PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 04:18:21PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition,
I wrote some an OCaml program using CIL to check driver method exit paths and validate that all objects were left in an unlocked state. This found some real bugs !
So here's the incremental fixes for those
I was having so much fun I wrote more checks for incorrect locking order and data access while unlocked, and improved existing detection. A bunch more bugs found and fixed ! lxc_driver.c | 23 +++++++++++++++++++---- network_driver.c | 3 --- qemu_driver.c | 28 +++++++++++++++++----------- storage_driver.c | 10 ++++++++-- test.c | 3 +-- uml_driver.c | 18 ++++++++++++++---- 6 files changed, 59 insertions(+), 26 deletions(-) Daniel diff --git a/src/lxc_driver.c b/src/lxc_driver.c --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -682,24 +682,32 @@ static void lxcMonitorEvent(int watch, virDomainObjPtr vm = NULL; unsigned int i; + lxcDriverLock(driver); for (i = 0 ; i < driver->domains.count ; i++) { + virDomainObjLock(driver->domains.objs[i]); if (driver->domains.objs[i]->monitorWatch == watch) { vm = driver->domains.objs[i]; break; } + virDomainObjUnlock(driver->domains.objs[i]); } if (!vm) { virEventRemoveHandle(watch); - return; + goto cleanup; } if (vm->monitor != fd) { virEventRemoveHandle(watch); - return; + goto cleanup; } if (lxcVmTerminate(NULL, driver, vm, SIGINT) < 0) virEventRemoveHandle(watch); + +cleanup: + if (vm) + virDomainObjUnlock(vm); + lxcDriverUnlock(driver); } @@ -1153,20 +1161,26 @@ static int lxcStartup(void) char *config = NULL; virDomainDefPtr tmp; int rc; - if ((vm->monitor = lxcMonitorClient(NULL, lxc_driver, vm)) < 0) + virDomainObjLock(vm); + if ((vm->monitor = lxcMonitorClient(NULL, lxc_driver, vm)) < 0) { + virDomainObjUnlock(vm); continue; + } /* Read pid from controller */ if ((rc = virFileReadPid(lxc_driver->stateDir, vm->def->name, &vm->pid)) != 0) { close(vm->monitor); vm->monitor = -1; + virDomainObjUnlock(vm); continue; } if ((config = virDomainConfigFile(NULL, lxc_driver->stateDir, - vm->def->name)) == NULL) + vm->def->name)) == NULL) { + virDomainObjUnlock(vm); continue; + } /* Try and load the live config */ tmp = virDomainDefParseFile(NULL, lxc_driver->caps, config); @@ -1184,6 +1198,7 @@ static int lxcStartup(void) close(vm->monitor); vm->monitor = -1; } + virDomainObjUnlock(vm); } lxcDriverUnlock(lxc_driver); diff --git a/src/network_driver.c b/src/network_driver.c --- a/src/network_driver.c +++ b/src/network_driver.c @@ -1005,7 +1005,6 @@ static virNetworkPtr networkCreate(virCo def = NULL; if (networkStartNetworkDaemon(conn, driver, network) < 0) { - virNetworkObjUnlock(network); virNetworkRemoveInactive(&driver->networks, network); network = NULL; @@ -1043,7 +1042,6 @@ static virNetworkPtr networkDefine(virCo driver->networkConfigDir, driver->networkAutostartDir, network) < 0) { - virNetworkObjUnlock(network); virNetworkRemoveInactive(&driver->networks, network); network = NULL; @@ -1083,7 +1081,6 @@ static int networkUndefine(virNetworkPtr if (virNetworkDeleteConfig(net->conn, network) < 0) goto cleanup; - virNetworkObjUnlock(network); virNetworkRemoveInactive(&driver->networks, network); network = NULL; diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -243,8 +243,7 @@ qemudStartup(void) { goto out_of_memory; if (qemudLoadDriverConfig(qemu_driver, driverConf) < 0) { - qemudShutdown(); - return -1; + goto error; } if (virDomainLoadAllConfigs(NULL, @@ -327,9 +326,13 @@ qemudActive(void) { return 0; qemuDriverLock(qemu_driver); - for (i = 0 ; i < qemu_driver->domains.count ; i++) - if (virDomainIsActive(qemu_driver->domains.objs[i])) + for (i = 0 ; i < qemu_driver->domains.count ; i++) { + virDomainObjPtr vm = qemu_driver->domains.objs[i]; + virDomainObjLock(vm); + if (virDomainIsActive(vm)) active = 1; + virDomainObjUnlock(vm); + } qemuDriverUnlock(qemu_driver); return active; @@ -1088,12 +1091,15 @@ qemudDispatchVMEvent(int watch, int fd, qemuDriverLock(driver); for (i = 0 ; i < driver->domains.count ; i++) { - if (virDomainIsActive(driver->domains.objs[i]) && - (driver->domains.objs[i]->stdout_watch == watch || - driver->domains.objs[i]->stderr_watch == watch)) { - vm = driver->domains.objs[i]; - break; - } + virDomainObjPtr tmpvm = driver->domains.objs[i]; + virDomainObjLock(vm); + if (virDomainIsActive(tmpvm) && + (tmpvm->stdout_watch == watch || + tmpvm->stderr_watch == watch)) { + vm = tmpvm; + break; + } + virDomainObjUnlock(vm); } if (!vm) @@ -2128,7 +2134,7 @@ static int qemudDomainSave(virDomainPtr if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to write save header")); - return -1; + goto cleanup; } if (safewrite(fd, xml, header.xml_len) != header.xml_len) { diff --git a/src/storage_driver.c b/src/storage_driver.c --- a/src/storage_driver.c +++ b/src/storage_driver.c @@ -62,13 +62,14 @@ storageDriverAutostart(virStorageDriverS for (i = 0 ; i < driver->pools.count ; i++) { virStoragePoolObjPtr pool = driver->pools.objs[i]; - + virStoragePoolObjLock(pool); if (pool->autostart && !virStoragePoolObjIsActive(pool)) { virStorageBackendPtr backend; if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { storageLog("Missing backend %d", pool->def->type); + virStoragePoolObjUnlock(pool); continue; } @@ -77,6 +78,7 @@ storageDriverAutostart(virStorageDriverS virErrorPtr err = virGetLastError(); storageLog("Failed to autostart storage pool '%s': %s", pool->def->name, err ? err->message : NULL); + virStoragePoolObjUnlock(pool); continue; } @@ -86,10 +88,12 @@ storageDriverAutostart(virStorageDriverS backend->stopPool(NULL, pool); storageLog("Failed to autostart storage pool '%s': %s", pool->def->name, err ? err->message : NULL); + virStoragePoolObjUnlock(pool); continue; } pool->active = 1; } + virStoragePoolObjUnlock(pool); } } @@ -237,11 +241,12 @@ storageDriverShutdown(void) { /* shutdown active pools */ for (i = 0 ; i < driverState->pools.count ; i++) { virStoragePoolObjPtr pool = driverState->pools.objs[i]; - + virStoragePoolObjLock(pool); if (virStoragePoolObjIsActive(pool)) { virStorageBackendPtr backend; if ((backend = virStorageBackendForType(pool->def->type)) == NULL) { storageLog("Missing backend"); + virStoragePoolObjUnlock(pool); continue; } @@ -253,6 +258,7 @@ storageDriverShutdown(void) { } virStoragePoolObjClearVols(pool); } + virStoragePoolObjUnlock(pool); } /* free inactive pools */ diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -1592,7 +1592,6 @@ static int testDomainUndefine(virDomainP } privdom->state = VIR_DOMAIN_SHUTOFF; - virDomainObjUnlock(privdom); virDomainRemoveInactive(&privconn->domains, privdom); privdom = NULL; @@ -2393,7 +2392,7 @@ testStoragePoolCreate(virConnectPtr conn } if (!(pool = virStoragePoolObjAssignDef(conn, &privconn->pools, def))) { - return NULL; + goto cleanup; } def = NULL; diff --git a/src/uml_driver.c b/src/uml_driver.c --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -215,28 +215,29 @@ umlInotifyEvent(int watch, struct uml_driver *driver = data; virDomainObjPtr dom; + umlDriverLock(driver); if (watch != driver->inotifyWatch) - return; + goto cleanup; reread: got = read(fd, buf, sizeof(buf)); if (got == -1) { if (errno == EINTR) goto reread; - return; + goto cleanup; } tmp = buf; while (got) { if (got < sizeof(struct inotify_event)) - return; /* bad */ + goto cleanup; /* bad */ e = (struct inotify_event *)tmp; tmp += sizeof(struct inotify_event); got -= sizeof(struct inotify_event); if (got < e->len) - return; + goto cleanup; tmp += e->len; got -= e->len; @@ -251,6 +252,7 @@ reread: if (e->mask & IN_DELETE) { if (!virDomainIsActive(dom)) { + virDomainObjUnlock(dom); continue; } @@ -263,10 +265,12 @@ reread: dom->state = VIR_DOMAIN_SHUTOFF; } else if (e->mask & (IN_CREATE | IN_MODIFY)) { if (virDomainIsActive(dom)) { + virDomainObjUnlock(dom); continue; } if (umlReadPidFile(NULL, driver, dom) < 0) { + virDomainObjUnlock(dom); continue; } @@ -279,7 +283,11 @@ reread: if (umlIdentifyChrPTY(NULL, driver, dom) < 0) umlShutdownVMDaemon(NULL, driver, dom); } + virDomainObjUnlock(dom); } + +cleanup: + umlDriverUnlock(driver); } /** @@ -465,8 +473,10 @@ umlShutdown(void) { /* shutdown active VMs */ for (i = 0 ; i < uml_driver->domains.count ; i++) { virDomainObjPtr dom = uml_driver->domains.objs[i]; + virDomainObjLock(dom); if (virDomainIsActive(dom)) umlShutdownVMDaemon(NULL, uml_driver, dom); + virDomainObjUnlock(dom); } virDomainObjListFree(¨_driver->domains); -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, Dec 03, 2008 at 11:52:45PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 06:52:32PM +0000, Daniel P. Berrange wrote:
On Wed, Dec 03, 2008 at 04:18:21PM +0100, Daniel Veillard wrote:
On Mon, Dec 01, 2008 at 12:26:48AM +0000, Daniel P. Berrange wrote:
This is a diffstat summary for the combined series of 28 patches
Okay, my take at this point is that those should be commited with the few fix found my manual examination, maybe extend the documentation a bit, and start testing it as much as prossible. Some locking debug facility might be a good addition,
I wrote some an OCaml program using CIL to check driver method exit paths and validate that all objects were left in an unlocked state. This found some real bugs !
So here's the incremental fixes for those
I was having so much fun I wrote more checks for incorrect locking order and data access while unlocked, and improved existing detection. A bunch more bugs found and fixed !
Sure ! All looks fine. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

"Daniel P. Berrange" <berrange@redhat.com> wrote:
The following huge series of patches adds thread safety for the libvirtd
Hi Dan, FYI, I've applied everything and have begun looking. I noticed while applying ("git am" complained) that #25 and 26 had trailing white space.

On Mon, Dec 01, 2008 at 11:08:36AM +0100, Jim Meyering wrote:
"Daniel P. Berrange" <berrange@redhat.com> wrote:
The following huge series of patches adds thread safety for the libvirtd
Hi Dan,
FYI, I've applied everything and have begun looking. I noticed while applying ("git am" complained) that #25 and 26 had trailing white space.
Thanks, I've fixed this up now. For some odd reason, on my Fedora 10 box, emacs has stopped activating my 'show trailing whitespace' macros Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

What git changeset does this queue apply against? I'm having a heck of a time getting it to apply cleanly with git-am. alternately: I know you work on occasion with mercurial. Is this an mq tree somewhere? Daniel P. Berrange wrote on 11/30/2008 06:14 PM:
The following huge series of patches adds thread safety for the libvirtd daemon and drivers, and makes the daemon multi-threaded in processing RPC calls. This enables multiple clients to be processed in parallel, without blocking each other. It does not change the thread rules for the virConnectPtr object though, so each individual client is still serialized.
There are two core places where we have to have synchronization in the threading model this patch series introduces
- The libvirt daemon code - A single global server lock (aka struct qemud_server) - One lock per client connection (aka struct qemud_client)
- The driver implementations - One lock per driver (aka QEMU, LXC, Test, UML, OpenVZ, Network, Storage, Node Devices) - One lock per primary object in a driver (virDomainObjPtr, virNetworkObjPtr, virStoragePoolObjPtr, virNodeDeviceObjptr instances)
For most cases, the big global server / driver locks are only held while obtaining one of the finer grained locks. This gives a fairly good level of concurrency for operations touching different objects. Once this core infrastructure is merged, it will be possible to iterate on impl of drivers to reduce the time locks are held - eg avoid holding a lock while talking to the QEMU monitor interface.
To try and make it easier to spot thread locking problems this series refactors alot of methods so that there is only a single return point where the unlock call can be placed, rather than multiple return point which increases the chances of missing an unlock call.
This touches a huge amount of code, so I'd like to get this all merged ASAP as it'll be really hard to keep it synced with ongoing changes.
Daniel

On Mon, Dec 01, 2008 at 11:07:47AM -0500, Ben Guthro wrote:
What git changeset does this queue apply against?
It was against CVS head as off Sunday evening.
I'm having a heck of a time getting it to apply cleanly with git-am.
alternately: I know you work on occasion with mercurial. Is this an mq tree somewhere?
This my current HG mirror http://hg.berrange.com/libraries/libvirt--devel And this is the MQ series http://berrange.com/~dan/libvirt-threading-2008-12-01/ Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Sun, Nov 30, 2008 at 11:14:37PM +0000, Daniel P. Berrange wrote:
The following huge series of patches adds thread safety for the libvirtd daemon and drivers, and makes the daemon multi-threaded in processing RPC calls. This enables multiple clients to be processed in parallel, without blocking each other. It does not change the thread rules for the virConnectPtr object though, so each individual client is still serialized.
This touches a huge amount of code, so I'd like to get this all merged ASAP as it'll be really hard to keep it synced with ongoing changes.
I've committed this whole series of patches + the fixes the various reviews suggested, plus the fixes CIL identified. Now for people to find all the real-world bugs it.... Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (7)
-
Ben Guthro
-
Chris Wright
-
Daniel P. Berrange
-
Daniel Veillard
-
Jim Meyering
-
Richard W.M. Jones
-
Ron Yorston