[libvirt] PATCH 0/5: connection cloning support (WIP)

This series is a work-in-progress set of patches implementing connection cloning. The idea is that if you want to use a connection form multiple threads, you could do virConnectPtr copy = virConnectClone(conn) and use 'copy' from the other thread. This avoids the problem of having to make all the virError handling stuff thread-local whic is the blocker for allowing real mutlti-thread access to a single virConnectPtr object. I believe this cloning support should be sufficient for the Java bindings need to use a thread for its event loop. The idea being that if you wanted to use an event loop in a background thread, you'd create a cloned object for use event loop triggered callbacks like domain events notifications. I'd still like to do some experiments later making the single virConnectPtr fully thread safe, but that'll take a little more time. I'm hoping this cloning will address the Java needs right now... 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 :|

In common with my previous patches todo the same in test driver, this patch removes use of GET_PRIVATE() macros for accessing the remote driver state. In also removes the the 'magic' parameter in struct private_data. It wasn't really providing any significant level of protection since every struct private_data instance is owned by a virConnectPtr object which already has a magic field that's checked for sanity by libvirt.c. diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -86,14 +86,9 @@ #include "util.h" #include "event.h" -/* Per-connection private data. */ -#define MAGIC 999 /* private_data->magic if OK */ -#define DEAD 998 /* private_data->magic if dead/closed */ - static int inside_daemon = 0; struct private_data { - int magic; /* Should be MAGIC or DEAD. */ int sock; /* Socket. */ int watch; /* File handle watch */ pid_t pid; /* PID of tunnel process */ @@ -118,39 +113,6 @@ struct private_data { /* Timer for flushing domainEvents queue */ int eventFlushTimer; }; - -#define GET_PRIVATE(conn,retcode) \ - struct private_data *priv = (struct private_data *) (conn)->privateData; \ - if (!priv || priv->magic != MAGIC) { \ - error (conn, VIR_ERR_INVALID_ARG, \ - _("tried to use a closed or uninitialised handle")); \ - return (retcode); \ - } - -#define GET_NETWORK_PRIVATE(conn,retcode) \ - struct private_data *priv = (struct private_data *) (conn)->networkPrivateData; \ - if (!priv || priv->magic != MAGIC) { \ - error (conn, VIR_ERR_INVALID_ARG, \ - _("tried to use a closed or uninitialised handle")); \ - return (retcode); \ - } - -#define GET_STORAGE_PRIVATE(conn,retcode) \ - struct private_data *priv = (struct private_data *) (conn)->storagePrivateData; \ - if (!priv || priv->magic != MAGIC) { \ - error (conn, VIR_ERR_INVALID_ARG, \ - "tried to use a closed or uninitialised handle"); \ - return (retcode); \ - } - -#define GET_DEVMON_PRIVATE(conn,retcode) \ - struct private_data *priv = (struct private_data *) (conn)->devMonPrivateData; \ - if (!priv || priv->magic != MAGIC) { \ - error (conn, VIR_ERR_INVALID_ARG, \ - _("tried to use a closed or uninitialised handle")); \ - return (retcode); \ - } - enum { REMOTE_CALL_IN_OPEN = 1, @@ -917,14 +879,12 @@ remoteOpen (virConnectPtr conn, } } - priv->magic = DEAD; priv->sock = -1; ret = doRemoteOpen(conn, priv, auth, rflags); if (ret != VIR_DRV_OPEN_SUCCESS) { conn->privateData = NULL; VIR_FREE(priv); } else { - priv->magic = MAGIC; conn->privateData = priv; } return ret; @@ -1268,9 +1228,6 @@ doRemoteClose (virConnectPtr conn, struc /* See comment for remoteType. */ free (priv->type); - /* Free private data. */ - priv->magic = DEAD; - /* Free callback list */ virDomainEventCallbackListFree(priv->callbackList); @@ -1284,10 +1241,10 @@ remoteClose (virConnectPtr conn) remoteClose (virConnectPtr conn) { int ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; ret = doRemoteClose(conn, priv); - free (priv); + VIR_FREE (priv); conn->privateData = NULL; return ret; @@ -1298,7 +1255,7 @@ remoteSupportsFeature (virConnectPtr con { remote_supports_feature_args args; remote_supports_feature_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; /* VIR_DRV_FEATURE_REMOTE* features are handled directly. */ if (feature == VIR_DRV_FEATURE_REMOTE) return 1; @@ -1326,7 +1283,7 @@ remoteType (virConnectPtr conn) remoteType (virConnectPtr conn) { remote_get_type_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; /* Cached? */ if (priv->type) return priv->type; @@ -1345,7 +1302,7 @@ remoteGetVersion (virConnectPtr conn, un remoteGetVersion (virConnectPtr conn, unsigned long *hvVer) { remote_get_version_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_VERSION, @@ -1361,7 +1318,7 @@ remoteGetHostname (virConnectPtr conn) remoteGetHostname (virConnectPtr conn) { remote_get_hostname_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_HOSTNAME, @@ -1378,7 +1335,7 @@ remoteGetMaxVcpus (virConnectPtr conn, c { remote_get_max_vcpus_args args; remote_get_max_vcpus_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); args.type = type == NULL ? NULL : (char **) &type; @@ -1394,7 +1351,7 @@ remoteNodeGetInfo (virConnectPtr conn, v remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info) { remote_node_get_info_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_INFO, @@ -1418,7 +1375,7 @@ remoteGetCapabilities (virConnectPtr con remoteGetCapabilities (virConnectPtr conn) { remote_get_capabilities_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_CAPABILITIES, @@ -1439,7 +1396,7 @@ remoteNodeGetCellsFreeMemory(virConnectP remote_node_get_cells_free_memory_args args; remote_node_get_cells_free_memory_ret ret; int i; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; if (maxCells > REMOTE_NODE_MAX_CELLS) { errorf (conn, VIR_ERR_RPC, @@ -1470,7 +1427,7 @@ remoteNodeGetFreeMemory (virConnectPtr c remoteNodeGetFreeMemory (virConnectPtr conn) { remote_node_get_free_memory_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY, @@ -1488,7 +1445,7 @@ remoteListDomains (virConnectPtr conn, i int i; remote_list_domains_args args; remote_list_domains_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; if (maxids > REMOTE_DOMAIN_ID_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -1524,7 +1481,7 @@ remoteNumOfDomains (virConnectPtr conn) remoteNumOfDomains (virConnectPtr conn) { remote_num_of_domains_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DOMAINS, @@ -1543,7 +1500,7 @@ remoteDomainCreateXML (virConnectPtr con virDomainPtr dom; remote_domain_create_xml_args args; remote_domain_create_xml_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; args.xml_desc = (char *) xmlDesc; args.flags = flags; @@ -1566,7 +1523,7 @@ remoteDomainLookupByID (virConnectPtr co virDomainPtr dom; remote_domain_lookup_by_id_args args; remote_domain_lookup_by_id_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; args.id = id; @@ -1588,7 +1545,7 @@ remoteDomainLookupByUUID (virConnectPtr virDomainPtr dom; remote_domain_lookup_by_uuid_args args; remote_domain_lookup_by_uuid_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); @@ -1609,7 +1566,7 @@ remoteDomainLookupByName (virConnectPtr virDomainPtr dom; remote_domain_lookup_by_name_args args; remote_domain_lookup_by_name_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; args.name = (char *) name; @@ -1629,7 +1586,7 @@ remoteDomainSuspend (virDomainPtr domain remoteDomainSuspend (virDomainPtr domain) { remote_domain_suspend_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1645,7 +1602,7 @@ remoteDomainResume (virDomainPtr domain) remoteDomainResume (virDomainPtr domain) { remote_domain_resume_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1661,7 +1618,7 @@ remoteDomainShutdown (virDomainPtr domai remoteDomainShutdown (virDomainPtr domain) { remote_domain_shutdown_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1677,7 +1634,7 @@ remoteDomainReboot (virDomainPtr domain, remoteDomainReboot (virDomainPtr domain, unsigned int flags) { remote_domain_reboot_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.flags = flags; @@ -1694,7 +1651,7 @@ remoteDomainDestroy (virDomainPtr domain remoteDomainDestroy (virDomainPtr domain) { remote_domain_destroy_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1711,7 +1668,7 @@ remoteDomainGetOSType (virDomainPtr doma { remote_domain_get_os_type_args args; remote_domain_get_os_type_ret ret; - GET_PRIVATE (domain->conn, NULL); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1730,7 +1687,7 @@ remoteDomainGetMaxMemory (virDomainPtr d { remote_domain_get_max_memory_args args; remote_domain_get_max_memory_ret ret; - GET_PRIVATE (domain->conn, 0); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1747,7 +1704,7 @@ remoteDomainSetMaxMemory (virDomainPtr d remoteDomainSetMaxMemory (virDomainPtr domain, unsigned long memory) { remote_domain_set_max_memory_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.memory = memory; @@ -1764,7 +1721,7 @@ remoteDomainSetMemory (virDomainPtr doma remoteDomainSetMemory (virDomainPtr domain, unsigned long memory) { remote_domain_set_memory_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.memory = memory; @@ -1782,7 +1739,7 @@ remoteDomainGetInfo (virDomainPtr domain { remote_domain_get_info_args args; remote_domain_get_info_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1805,7 +1762,7 @@ remoteDomainSave (virDomainPtr domain, c remoteDomainSave (virDomainPtr domain, const char *to) { remote_domain_save_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.to = (char *) to; @@ -1822,7 +1779,7 @@ remoteDomainRestore (virConnectPtr conn, remoteDomainRestore (virConnectPtr conn, const char *from) { remote_domain_restore_args args; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; args.from = (char *) from; @@ -1838,7 +1795,7 @@ remoteDomainCoreDump (virDomainPtr domai remoteDomainCoreDump (virDomainPtr domain, const char *to, int flags) { remote_domain_core_dump_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.to = (char *) to; @@ -1856,7 +1813,7 @@ remoteDomainSetVcpus (virDomainPtr domai remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) { remote_domain_set_vcpus_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.nvcpus = nvcpus; @@ -1876,7 +1833,7 @@ remoteDomainPinVcpu (virDomainPtr domain int maplen) { remote_domain_pin_vcpu_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; if (maplen > REMOTE_CPUMAP_MAX) { errorf (domain->conn, VIR_ERR_RPC, @@ -1908,7 +1865,7 @@ remoteDomainGetVcpus (virDomainPtr domai int i; remote_domain_get_vcpus_args args; remote_domain_get_vcpus_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; if (maxinfo > REMOTE_VCPUINFO_MAX) { errorf (domain->conn, VIR_ERR_RPC, @@ -1970,7 +1927,7 @@ remoteDomainGetMaxVcpus (virDomainPtr do { remote_domain_get_max_vcpus_args args; remote_domain_get_max_vcpus_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -1988,7 +1945,7 @@ remoteDomainDumpXML (virDomainPtr domain { remote_domain_dump_xml_args args; remote_domain_dump_xml_ret ret; - GET_PRIVATE (domain->conn, NULL); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.flags = flags; @@ -2012,7 +1969,7 @@ remoteDomainMigratePrepare (virConnectPt { remote_domain_migrate_prepare_args args; remote_domain_migrate_prepare_ret ret; - GET_PRIVATE (dconn, -1); + struct private_data *priv = dconn->privateData; args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in; args.flags = flags; @@ -2045,7 +2002,7 @@ remoteDomainMigratePerform (virDomainPtr unsigned long resource) { remote_domain_migrate_perform_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.cookie.cookie_len = cookielen; @@ -2074,7 +2031,7 @@ remoteDomainMigrateFinish (virConnectPtr virDomainPtr ddom; remote_domain_migrate_finish_args args; remote_domain_migrate_finish_ret ret; - GET_PRIVATE (dconn, NULL); + struct private_data *priv = dconn->privateData; args.dname = (char *) dname; args.cookie.cookie_len = cookielen; @@ -2104,7 +2061,7 @@ remoteDomainMigratePrepare2 (virConnectP { remote_domain_migrate_prepare2_args args; remote_domain_migrate_prepare2_ret ret; - GET_PRIVATE (dconn, -1); + struct private_data *priv = dconn->privateData; args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in; args.flags = flags; @@ -2140,7 +2097,7 @@ remoteDomainMigrateFinish2 (virConnectPt virDomainPtr ddom; remote_domain_migrate_finish2_args args; remote_domain_migrate_finish2_ret ret; - GET_PRIVATE (dconn, NULL); + struct private_data *priv = dconn->privateData; args.dname = (char *) dname; args.cookie.cookie_len = cookielen; @@ -2167,7 +2124,7 @@ remoteListDefinedDomains (virConnectPtr int i; remote_list_defined_domains_args args; remote_list_defined_domains_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; if (maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -2208,7 +2165,7 @@ remoteNumOfDefinedDomains (virConnectPtr remoteNumOfDefinedDomains (virConnectPtr conn) { remote_num_of_defined_domains_ret ret; - GET_PRIVATE (conn, -1); + struct private_data *priv = conn->privateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_DOMAINS, @@ -2223,7 +2180,7 @@ remoteDomainCreate (virDomainPtr domain) remoteDomainCreate (virDomainPtr domain) { remote_domain_create_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -2241,7 +2198,7 @@ remoteDomainDefineXML (virConnectPtr con virDomainPtr dom; remote_domain_define_xml_args args; remote_domain_define_xml_ret ret; - GET_PRIVATE (conn, NULL); + struct private_data *priv = conn->privateData; args.xml = (char *) xml; @@ -2261,7 +2218,7 @@ remoteDomainUndefine (virDomainPtr domai remoteDomainUndefine (virDomainPtr domain) { remote_domain_undefine_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -2277,7 +2234,7 @@ remoteDomainAttachDevice (virDomainPtr d remoteDomainAttachDevice (virDomainPtr domain, const char *xml) { remote_domain_attach_device_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.xml = (char *) xml; @@ -2294,7 +2251,7 @@ remoteDomainDetachDevice (virDomainPtr d remoteDomainDetachDevice (virDomainPtr domain, const char *xml) { remote_domain_detach_device_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.xml = (char *) xml; @@ -2312,7 +2269,7 @@ remoteDomainGetAutostart (virDomainPtr d { remote_domain_get_autostart_args args; remote_domain_get_autostart_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -2330,7 +2287,7 @@ remoteDomainSetAutostart (virDomainPtr d remoteDomainSetAutostart (virDomainPtr domain, int autostart) { remote_domain_set_autostart_args args; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.autostart = autostart; @@ -2348,7 +2305,7 @@ remoteDomainGetSchedulerType (virDomainP { remote_domain_get_scheduler_type_args args; remote_domain_get_scheduler_type_ret ret; - GET_PRIVATE (domain->conn, NULL); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -2371,7 +2328,7 @@ remoteDomainGetSchedulerParameters (virD remote_domain_get_scheduler_parameters_args args; remote_domain_get_scheduler_parameters_ret ret; int i; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.nparams = *nparams; @@ -2431,7 +2388,7 @@ remoteDomainSetSchedulerParameters (virD { remote_domain_set_scheduler_parameters_args args; int i, do_error; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -2489,7 +2446,7 @@ remoteDomainBlockStats (virDomainPtr dom { remote_domain_block_stats_args args; remote_domain_block_stats_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.path = (char *) path; @@ -2516,7 +2473,7 @@ remoteDomainInterfaceStats (virDomainPtr { remote_domain_interface_stats_args args; remote_domain_interface_stats_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); args.path = (char *) path; @@ -2551,7 +2508,7 @@ remoteDomainBlockPeek (virDomainPtr doma { remote_domain_block_peek_args args; remote_domain_block_peek_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) { errorf (domain->conn, VIR_ERR_RPC, @@ -2596,7 +2553,7 @@ remoteDomainMemoryPeek (virDomainPtr dom { remote_domain_memory_peek_args args; remote_domain_memory_peek_ret ret; - GET_PRIVATE (domain->conn, -1); + struct private_data *priv = domain->conn->privateData; if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) { errorf (domain->conn, VIR_ERR_RPC, @@ -2666,14 +2623,12 @@ remoteNetworkOpen (virConnectPtr conn, rflags |= VIR_DRV_OPEN_REMOTE_RO; rflags |= VIR_DRV_OPEN_REMOTE_UNIX; - priv->magic = DEAD; priv->sock = -1; ret = doRemoteOpen(conn, priv, auth, rflags); if (ret != VIR_DRV_OPEN_SUCCESS) { conn->networkPrivateData = NULL; VIR_FREE(priv); } else { - priv->magic = MAGIC; priv->localUses = 1; conn->networkPrivateData = priv; } @@ -2685,7 +2640,8 @@ remoteNetworkClose (virConnectPtr conn) remoteNetworkClose (virConnectPtr conn) { int ret = 0; - GET_NETWORK_PRIVATE (conn, -1); + struct private_data *priv = conn->networkPrivateData; + if (priv->localUses) { priv->localUses--; if (!priv->localUses) { @@ -2701,7 +2657,7 @@ remoteNumOfNetworks (virConnectPtr conn) remoteNumOfNetworks (virConnectPtr conn) { remote_num_of_networks_ret ret; - GET_NETWORK_PRIVATE (conn, -1); + struct private_data *priv = conn->networkPrivateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS, @@ -2718,7 +2674,7 @@ remoteListNetworks (virConnectPtr conn, int i; remote_list_networks_args args; remote_list_networks_ret ret; - GET_NETWORK_PRIVATE (conn, -1); + struct private_data *priv = conn->networkPrivateData; if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -2759,7 +2715,7 @@ remoteNumOfDefinedNetworks (virConnectPt remoteNumOfDefinedNetworks (virConnectPtr conn) { remote_num_of_defined_networks_ret ret; - GET_NETWORK_PRIVATE (conn, -1); + struct private_data *priv = conn->networkPrivateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS, @@ -2777,7 +2733,7 @@ remoteListDefinedNetworks (virConnectPtr int i; remote_list_defined_networks_args args; remote_list_defined_networks_ret ret; - GET_NETWORK_PRIVATE (conn, -1); + struct private_data *priv = conn->networkPrivateData; if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -2821,7 +2777,7 @@ remoteNetworkLookupByUUID (virConnectPtr virNetworkPtr net; remote_network_lookup_by_uuid_args args; remote_network_lookup_by_uuid_ret ret; - GET_NETWORK_PRIVATE (conn, NULL); + struct private_data *priv = conn->networkPrivateData; memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); @@ -2844,7 +2800,7 @@ remoteNetworkLookupByName (virConnectPtr virNetworkPtr net; remote_network_lookup_by_name_args args; remote_network_lookup_by_name_ret ret; - GET_NETWORK_PRIVATE (conn, NULL); + struct private_data *priv = conn->networkPrivateData; args.name = (char *) name; @@ -2866,7 +2822,7 @@ remoteNetworkCreateXML (virConnectPtr co virNetworkPtr net; remote_network_create_xml_args args; remote_network_create_xml_ret ret; - GET_NETWORK_PRIVATE (conn, NULL); + struct private_data *priv = conn->networkPrivateData; args.xml = (char *) xmlDesc; @@ -2888,7 +2844,7 @@ remoteNetworkDefineXML (virConnectPtr co virNetworkPtr net; remote_network_define_xml_args args; remote_network_define_xml_ret ret; - GET_NETWORK_PRIVATE (conn, NULL); + struct private_data *priv = conn->networkPrivateData; args.xml = (char *) xml; @@ -2908,7 +2864,7 @@ remoteNetworkUndefine (virNetworkPtr net remoteNetworkUndefine (virNetworkPtr network) { remote_network_undefine_args args; - GET_NETWORK_PRIVATE (network->conn, -1); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); @@ -2924,7 +2880,7 @@ remoteNetworkCreate (virNetworkPtr netwo remoteNetworkCreate (virNetworkPtr network) { remote_network_create_args args; - GET_NETWORK_PRIVATE (network->conn, -1); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); @@ -2940,7 +2896,7 @@ remoteNetworkDestroy (virNetworkPtr netw remoteNetworkDestroy (virNetworkPtr network) { remote_network_destroy_args args; - GET_NETWORK_PRIVATE (network->conn, -1); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); @@ -2957,7 +2913,7 @@ remoteNetworkDumpXML (virNetworkPtr netw { remote_network_dump_xml_args args; remote_network_dump_xml_ret ret; - GET_NETWORK_PRIVATE (network->conn, NULL); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); args.flags = flags; @@ -2977,7 +2933,7 @@ remoteNetworkGetBridgeName (virNetworkPt { remote_network_get_bridge_name_args args; remote_network_get_bridge_name_ret ret; - GET_NETWORK_PRIVATE (network->conn, NULL); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); @@ -2996,7 +2952,7 @@ remoteNetworkGetAutostart (virNetworkPtr { remote_network_get_autostart_args args; remote_network_get_autostart_ret ret; - GET_NETWORK_PRIVATE (network->conn, -1); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); @@ -3015,7 +2971,7 @@ remoteNetworkSetAutostart (virNetworkPtr remoteNetworkSetAutostart (virNetworkPtr network, int autostart) { remote_network_set_autostart_args args; - GET_NETWORK_PRIVATE (network->conn, -1); + struct private_data *priv = network->conn->networkPrivateData; make_nonnull_network (&args.net, network); args.autostart = autostart; @@ -3071,14 +3027,12 @@ remoteStorageOpen (virConnectPtr conn, rflags |= VIR_DRV_OPEN_REMOTE_RO; rflags |= VIR_DRV_OPEN_REMOTE_UNIX; - priv->magic = DEAD; priv->sock = -1; ret = doRemoteOpen(conn, priv, auth, rflags); if (ret != VIR_DRV_OPEN_SUCCESS) { conn->storagePrivateData = NULL; VIR_FREE(priv); } else { - priv->magic = MAGIC; priv->localUses = 1; conn->storagePrivateData = priv; } @@ -3090,7 +3044,8 @@ remoteStorageClose (virConnectPtr conn) remoteStorageClose (virConnectPtr conn) { int ret = 0; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->storagePrivateData; + if (priv->localUses) { priv->localUses--; if (!priv->localUses) { @@ -3106,7 +3061,7 @@ remoteNumOfStoragePools (virConnectPtr c remoteNumOfStoragePools (virConnectPtr conn) { remote_num_of_storage_pools_ret ret; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->storagePrivateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_STORAGE_POOLS, @@ -3123,7 +3078,7 @@ remoteListStoragePools (virConnectPtr co int i; remote_list_storage_pools_args args; remote_list_storage_pools_ret ret; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->storagePrivateData; if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many storage pools requested")); @@ -3160,7 +3115,7 @@ remoteNumOfDefinedStoragePools (virConne remoteNumOfDefinedStoragePools (virConnectPtr conn) { remote_num_of_defined_storage_pools_ret ret; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->storagePrivateData; memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS, @@ -3178,7 +3133,7 @@ remoteListDefinedStoragePools (virConnec int i; remote_list_defined_storage_pools_args args; remote_list_defined_storage_pools_ret ret; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->storagePrivateData; if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many storage pools requested")); @@ -3219,7 +3174,7 @@ remoteFindStoragePoolSources (virConnect { remote_find_storage_pool_sources_args args; remote_find_storage_pool_sources_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; const char *emptyString = ""; char *retval; @@ -3259,7 +3214,7 @@ remoteStoragePoolLookupByUUID (virConnec virStoragePoolPtr pool; remote_storage_pool_lookup_by_uuid_args args; remote_storage_pool_lookup_by_uuid_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); @@ -3282,7 +3237,7 @@ remoteStoragePoolLookupByName (virConnec virStoragePoolPtr pool; remote_storage_pool_lookup_by_name_args args; remote_storage_pool_lookup_by_name_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; args.name = (char *) name; @@ -3304,7 +3259,7 @@ remoteStoragePoolLookupByVolume (virStor virStoragePoolPtr pool; remote_storage_pool_lookup_by_volume_args args; remote_storage_pool_lookup_by_volume_ret ret; - GET_STORAGE_PRIVATE (vol->conn, NULL); + struct private_data *priv = vol->conn->storagePrivateData; make_nonnull_storage_vol (&args.vol, vol); @@ -3327,7 +3282,7 @@ remoteStoragePoolCreateXML (virConnectPt virStoragePoolPtr pool; remote_storage_pool_create_xml_args args; remote_storage_pool_create_xml_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; args.xml = (char *) xmlDesc; args.flags = flags; @@ -3350,7 +3305,7 @@ remoteStoragePoolDefineXML (virConnectPt virStoragePoolPtr pool; remote_storage_pool_define_xml_args args; remote_storage_pool_define_xml_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; args.xml = (char *) xml; args.flags = flags; @@ -3371,7 +3326,7 @@ remoteStoragePoolUndefine (virStoragePoo remoteStoragePoolUndefine (virStoragePoolPtr pool) { remote_storage_pool_undefine_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); @@ -3387,7 +3342,7 @@ remoteStoragePoolCreate (virStoragePoolP remoteStoragePoolCreate (virStoragePoolPtr pool, unsigned int flags) { remote_storage_pool_create_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3405,7 +3360,7 @@ remoteStoragePoolBuild (virStoragePoolPt unsigned int flags) { remote_storage_pool_build_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3422,7 +3377,7 @@ remoteStoragePoolDestroy (virStoragePool remoteStoragePoolDestroy (virStoragePoolPtr pool) { remote_storage_pool_destroy_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); @@ -3439,7 +3394,7 @@ remoteStoragePoolDelete (virStoragePoolP unsigned int flags) { remote_storage_pool_delete_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3457,7 +3412,7 @@ remoteStoragePoolRefresh (virStoragePool unsigned int flags) { remote_storage_pool_refresh_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3475,7 +3430,7 @@ remoteStoragePoolGetInfo (virStoragePool { remote_storage_pool_get_info_args args; remote_storage_pool_get_info_ret ret; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); @@ -3499,7 +3454,7 @@ remoteStoragePoolDumpXML (virStoragePool { remote_storage_pool_dump_xml_args args; remote_storage_pool_dump_xml_ret ret; - GET_STORAGE_PRIVATE (pool->conn, NULL); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3519,7 +3474,7 @@ remoteStoragePoolGetAutostart (virStorag { remote_storage_pool_get_autostart_args args; remote_storage_pool_get_autostart_ret ret; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); @@ -3538,7 +3493,7 @@ remoteStoragePoolSetAutostart (virStorag remoteStoragePoolSetAutostart (virStoragePoolPtr pool, int autostart) { remote_storage_pool_set_autostart_args args; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.autostart = autostart; @@ -3557,7 +3512,7 @@ remoteStoragePoolNumOfVolumes (virStorag { remote_storage_pool_num_of_volumes_args args; remote_storage_pool_num_of_volumes_ret ret; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool(&args.pool, pool); @@ -3576,7 +3531,7 @@ remoteStoragePoolListVolumes (virStorage int i; remote_storage_pool_list_volumes_args args; remote_storage_pool_list_volumes_ret ret; - GET_STORAGE_PRIVATE (pool->conn, -1); + struct private_data *priv = pool->conn->storagePrivateData; if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { error (pool->conn, VIR_ERR_RPC, _("too many storage volumes requested")); @@ -3619,7 +3574,7 @@ remoteStorageVolLookupByName (virStorage virStorageVolPtr vol; remote_storage_vol_lookup_by_name_args args; remote_storage_vol_lookup_by_name_ret ret; - GET_STORAGE_PRIVATE (pool->conn, NULL); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool(&args.pool, pool); args.name = (char *) name; @@ -3643,7 +3598,7 @@ remoteStorageVolLookupByKey (virConnectP virStorageVolPtr vol; remote_storage_vol_lookup_by_key_args args; remote_storage_vol_lookup_by_key_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; args.key = (char *) key; @@ -3666,7 +3621,7 @@ remoteStorageVolLookupByPath (virConnect virStorageVolPtr vol; remote_storage_vol_lookup_by_path_args args; remote_storage_vol_lookup_by_path_ret ret; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->storagePrivateData; args.path = (char *) path; @@ -3689,7 +3644,7 @@ remoteStorageVolCreateXML (virStoragePoo virStorageVolPtr vol; remote_storage_vol_create_xml_args args; remote_storage_vol_create_xml_ret ret; - GET_STORAGE_PRIVATE (pool->conn, NULL); + struct private_data *priv = pool->conn->storagePrivateData; make_nonnull_storage_pool (&args.pool, pool); args.xml = (char *) xmlDesc; @@ -3712,7 +3667,7 @@ remoteStorageVolDelete (virStorageVolPtr unsigned int flags) { remote_storage_vol_delete_args args; - GET_STORAGE_PRIVATE (vol->conn, -1); + struct private_data *priv = vol->conn->storagePrivateData; make_nonnull_storage_vol (&args.vol, vol); args.flags = flags; @@ -3730,7 +3685,7 @@ remoteStorageVolGetInfo (virStorageVolPt { remote_storage_vol_get_info_args args; remote_storage_vol_get_info_ret ret; - GET_STORAGE_PRIVATE (vol->conn, -1); + struct private_data *priv = vol->conn->storagePrivateData; make_nonnull_storage_vol (&args.vol, vol); @@ -3753,7 +3708,7 @@ remoteStorageVolDumpXML (virStorageVolPt { remote_storage_vol_dump_xml_args args; remote_storage_vol_dump_xml_ret ret; - GET_STORAGE_PRIVATE (vol->conn, NULL); + struct private_data *priv = vol->conn->storagePrivateData; make_nonnull_storage_vol (&args.vol, vol); args.flags = flags; @@ -3773,7 +3728,7 @@ remoteStorageVolGetPath (virStorageVolPt { remote_storage_vol_get_path_args args; remote_storage_vol_get_path_ret ret; - GET_NETWORK_PRIVATE (vol->conn, NULL); + struct private_data *priv = vol->conn->storagePrivateData; make_nonnull_storage_vol (&args.vol, vol); @@ -3813,7 +3768,8 @@ static int remoteDevMonClose(virConnectP static int remoteDevMonClose(virConnectPtr conn) { int ret = 0; - GET_DEVMON_PRIVATE (conn, -1); + struct private_data *priv = conn->devMonPrivateData; + if (priv->localUses) { priv->localUses--; if (!priv->localUses) { @@ -3831,7 +3787,7 @@ static int remoteNodeNumOfDevices(virCon { remote_node_num_of_devices_args args; remote_node_num_of_devices_ret ret; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->devMonPrivateData; args.cap = cap ? (char **)&cap : NULL; args.flags = flags; @@ -3855,7 +3811,7 @@ static int remoteNodeListDevices(virConn int i; remote_node_list_devices_args args; remote_node_list_devices_ret ret; - GET_STORAGE_PRIVATE (conn, -1); + struct private_data *priv = conn->devMonPrivateData; if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many device names requested")); @@ -3897,7 +3853,7 @@ static virNodeDevicePtr remoteNodeDevice remote_node_device_lookup_by_name_args args; remote_node_device_lookup_by_name_ret ret; virNodeDevicePtr dev; - GET_STORAGE_PRIVATE (conn, NULL); + struct private_data *priv = conn->devMonPrivateData; args.name = (char *)name; @@ -3919,7 +3875,7 @@ static char *remoteNodeDeviceDumpXML(vir { remote_node_device_dump_xml_args args; remote_node_device_dump_xml_ret ret; - GET_STORAGE_PRIVATE (dev->conn, NULL); + struct private_data *priv = dev->conn->devMonPrivateData; args.name = dev->name; args.flags = flags; @@ -3938,7 +3894,7 @@ static char *remoteNodeDeviceGetParent(v { remote_node_device_get_parent_args args; remote_node_device_get_parent_ret ret; - GET_STORAGE_PRIVATE (dev->conn, NULL); + struct private_data *priv = dev->conn->devMonPrivateData; args.name = dev->name; @@ -3956,7 +3912,7 @@ static int remoteNodeDeviceNumOfCaps(vir { remote_node_device_num_of_caps_args args; remote_node_device_num_of_caps_ret ret; - GET_STORAGE_PRIVATE (dev->conn, -1); + struct private_data *priv = dev->conn->devMonPrivateData; args.name = dev->name; @@ -3976,7 +3932,7 @@ static int remoteNodeDeviceListCaps(virN int i; remote_node_device_list_caps_args args; remote_node_device_list_caps_ret ret; - GET_STORAGE_PRIVATE (dev->conn, -1); + struct private_data *priv = dev->conn->devMonPrivateData; if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { error (dev->conn, VIR_ERR_RPC, _("too many capability names requested")); 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 merges all exit paths in the remote driver APIs so we more or less always have a single exit path in every method. NB we don't quite follow the HACKING guideline of naming cleanup paths 'cleanup', since we will need two possible cleanup points in some methods. So I've got a slightly different pattern cleanup: ....release data we allocated, typically free'ing the XDR object done: return ret; } In the next patch, the 'done' label will also unlock the driver. diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -1253,12 +1253,16 @@ static int static int remoteSupportsFeature (virConnectPtr conn, int feature) { + int rv = -1; remote_supports_feature_args args; remote_supports_feature_ret ret; struct private_data *priv = conn->privateData; /* VIR_DRV_FEATURE_REMOTE* features are handled directly. */ - if (feature == VIR_DRV_FEATURE_REMOTE) return 1; + if (feature == VIR_DRV_FEATURE_REMOTE) { + rv = 1; + goto done; + } args.feature = feature; @@ -1266,9 +1270,12 @@ remoteSupportsFeature (virConnectPtr con if (call (conn, priv, 0, REMOTE_PROC_SUPPORTS_FEATURE, (xdrproc_t) xdr_remote_supports_feature_args, (char *) &args, (xdrproc_t) xdr_remote_supports_feature_ret, (char *) &ret) == -1) - return -1; - - return ret.supported; + goto done; + + rv = ret.supported; + +done: + return rv; } /* Unfortunately this function is defined to return a static string. @@ -1282,25 +1289,33 @@ static const char * static const char * remoteType (virConnectPtr conn) { + char *rv = NULL; remote_get_type_ret ret; struct private_data *priv = conn->privateData; /* Cached? */ - if (priv->type) return priv->type; + if (priv->type) { + rv = priv->type; + goto done; + } memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_TYPE, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_get_type_ret, (char *) &ret) == -1) - return NULL; + goto done; /* Stash. */ - return priv->type = ret.type; + rv = priv->type = ret.type; + +done: + return rv; } static int remoteGetVersion (virConnectPtr conn, unsigned long *hvVer) { + int rv = -1; remote_get_version_ret ret; struct private_data *priv = conn->privateData; @@ -1308,15 +1323,19 @@ remoteGetVersion (virConnectPtr conn, un if (call (conn, priv, 0, REMOTE_PROC_GET_VERSION, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_get_version_ret, (char *) &ret) == -1) - return -1; + goto done; if (hvVer) *hvVer = ret.hv_ver; - return 0; + rv = 0; + +done: + return rv; } static char * remoteGetHostname (virConnectPtr conn) { + char *rv = NULL; remote_get_hostname_ret ret; struct private_data *priv = conn->privateData; @@ -1324,15 +1343,19 @@ remoteGetHostname (virConnectPtr conn) if (call (conn, priv, 0, REMOTE_PROC_GET_HOSTNAME, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_get_hostname_ret, (char *) &ret) == -1) - return NULL; + goto done; /* Caller frees this. */ - return ret.hostname; + rv = ret.hostname; + +done: + return rv; } static int remoteGetMaxVcpus (virConnectPtr conn, const char *type) { + int rv = -1; remote_get_max_vcpus_args args; remote_get_max_vcpus_ret ret; struct private_data *priv = conn->privateData; @@ -1342,14 +1365,18 @@ remoteGetMaxVcpus (virConnectPtr conn, c if (call (conn, priv, 0, REMOTE_PROC_GET_MAX_VCPUS, (xdrproc_t) xdr_remote_get_max_vcpus_args, (char *) &args, (xdrproc_t) xdr_remote_get_max_vcpus_ret, (char *) &ret) == -1) - return -1; - - return ret.max_vcpus; + goto done; + + rv = ret.max_vcpus; + +done: + return rv; } static int remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info) { + int rv = -1; remote_node_get_info_ret ret; struct private_data *priv = conn->privateData; @@ -1357,7 +1384,7 @@ remoteNodeGetInfo (virConnectPtr conn, v if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_INFO, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_node_get_info_ret, (char *) &ret) == -1) - return -1; + goto done; strncpy (info->model, ret.model, 32); info->model[31] = '\0'; @@ -1368,12 +1395,16 @@ remoteNodeGetInfo (virConnectPtr conn, v info->sockets = ret.sockets; info->cores = ret.cores; info->threads = ret.threads; - return 0; + rv = 0; + +done: + return rv; } static char * remoteGetCapabilities (virConnectPtr conn) { + char *rv = NULL; remote_get_capabilities_ret ret; struct private_data *priv = conn->privateData; @@ -1381,10 +1412,13 @@ remoteGetCapabilities (virConnectPtr con if (call (conn, priv, 0, REMOTE_PROC_GET_CAPABILITIES, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_get_capabilities_ret, (char *)&ret) == -1) - return NULL; + goto done; /* Caller frees this. */ - return ret.capabilities; + rv = ret.capabilities; + +done: + return rv; } static int @@ -1393,6 +1427,7 @@ remoteNodeGetCellsFreeMemory(virConnectP int startCell, int maxCells) { + int rv = -1; remote_node_get_cells_free_memory_args args; remote_node_get_cells_free_memory_ret ret; int i; @@ -1403,7 +1438,7 @@ remoteNodeGetCellsFreeMemory(virConnectP _("too many NUMA cells: %d > %d"), maxCells, REMOTE_NODE_MAX_CELLS); - return -1; + goto done; } args.startCell = startCell; @@ -1413,19 +1448,23 @@ remoteNodeGetCellsFreeMemory(virConnectP if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY, (xdrproc_t) xdr_remote_node_get_cells_free_memory_args, (char *)&args, (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *)&ret) == -1) - return -1; + goto done; for (i = 0 ; i < ret.freeMems.freeMems_len ; i++) freeMems[i] = ret.freeMems.freeMems_val[i]; xdr_free((xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *) &ret); - return ret.freeMems.freeMems_len; + rv = ret.freeMems.freeMems_len; + +done: + return rv; } static unsigned long long remoteNodeGetFreeMemory (virConnectPtr conn) { + unsigned long long rv = 0; /* 0 is error value this special function*/ remote_node_get_free_memory_ret ret; struct private_data *priv = conn->privateData; @@ -1433,15 +1472,19 @@ remoteNodeGetFreeMemory (virConnectPtr c if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_remote_node_get_free_memory_ret, (char *)&ret) == -1) - return 0; - - return ret.freeMem; + goto done; + + rv = ret.freeMem; + +done: + return rv; } static int remoteListDomains (virConnectPtr conn, int *ids, int maxids) { + int rv = -1; int i; remote_list_domains_args args; remote_list_domains_ret ret; @@ -1451,7 +1494,7 @@ remoteListDomains (virConnectPtr conn, i errorf (conn, VIR_ERR_RPC, _("too many remote domain IDs: %d > %d"), maxids, REMOTE_DOMAIN_ID_LIST_MAX); - return -1; + goto done; } args.maxids = maxids; @@ -1459,27 +1502,31 @@ remoteListDomains (virConnectPtr conn, i if (call (conn, priv, 0, REMOTE_PROC_LIST_DOMAINS, (xdrproc_t) xdr_remote_list_domains_args, (char *) &args, (xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.ids.ids_len > maxids) { errorf (conn, VIR_ERR_RPC, _("too many remote domain IDs: %d > %d"), ret.ids.ids_len, maxids); - xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret); - return -1; + goto cleanup; } for (i = 0; i < ret.ids.ids_len; ++i) ids[i] = ret.ids.ids_val[i]; + rv = ret.ids.ids_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret); - return ret.ids.ids_len; +done: + return rv; } static int remoteNumOfDomains (virConnectPtr conn) { + int rv = -1; remote_num_of_domains_ret ret; struct private_data *priv = conn->privateData; @@ -1487,9 +1534,12 @@ remoteNumOfDomains (virConnectPtr conn) if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DOMAINS, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_num_of_domains_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static virDomainPtr @@ -1497,7 +1547,7 @@ remoteDomainCreateXML (virConnectPtr con const char *xmlDesc, unsigned int flags) { - virDomainPtr dom; + virDomainPtr dom = NULL; remote_domain_create_xml_args args; remote_domain_create_xml_ret ret; struct private_data *priv = conn->privateData; @@ -1509,18 +1559,19 @@ remoteDomainCreateXML (virConnectPtr con if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_XML, (xdrproc_t) xdr_remote_domain_create_xml_args, (char *) &args, (xdrproc_t) xdr_remote_domain_create_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; dom = get_nonnull_domain (conn, ret.dom); xdr_free ((xdrproc_t) &xdr_remote_domain_create_xml_ret, (char *) &ret); +done: return dom; } static virDomainPtr remoteDomainLookupByID (virConnectPtr conn, int id) { - virDomainPtr dom; + virDomainPtr dom = NULL; remote_domain_lookup_by_id_args args; remote_domain_lookup_by_id_ret ret; struct private_data *priv = conn->privateData; @@ -1531,18 +1582,19 @@ remoteDomainLookupByID (virConnectPtr co if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_ID, (xdrproc_t) xdr_remote_domain_lookup_by_id_args, (char *) &args, (xdrproc_t) xdr_remote_domain_lookup_by_id_ret, (char *) &ret) == -1) - return NULL; + goto done; dom = get_nonnull_domain (conn, ret.dom); xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_id_ret, (char *) &ret); +done: return dom; } static virDomainPtr remoteDomainLookupByUUID (virConnectPtr conn, const unsigned char *uuid) { - virDomainPtr dom; + virDomainPtr dom = NULL; remote_domain_lookup_by_uuid_args args; remote_domain_lookup_by_uuid_ret ret; struct private_data *priv = conn->privateData; @@ -1553,17 +1605,19 @@ remoteDomainLookupByUUID (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID, (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args, (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret) == -1) - return NULL; + goto done; dom = get_nonnull_domain (conn, ret.dom); xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret); + +done: return dom; } static virDomainPtr remoteDomainLookupByName (virConnectPtr conn, const char *name) { - virDomainPtr dom; + virDomainPtr dom = NULL; remote_domain_lookup_by_name_args args; remote_domain_lookup_by_name_ret ret; struct private_data *priv = conn->privateData; @@ -1574,17 +1628,19 @@ remoteDomainLookupByName (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME, (xdrproc_t) xdr_remote_domain_lookup_by_name_args, (char *) &args, (xdrproc_t) xdr_remote_domain_lookup_by_name_ret, (char *) &ret) == -1) - return NULL; + goto done; dom = get_nonnull_domain (conn, ret.dom); xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_name_ret, (char *) &ret); +done: return dom; } static int remoteDomainSuspend (virDomainPtr domain) { + int rv = -1; remote_domain_suspend_args args; struct private_data *priv = domain->conn->privateData; @@ -1593,14 +1649,18 @@ remoteDomainSuspend (virDomainPtr domain if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SUSPEND, (xdrproc_t) xdr_remote_domain_suspend_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainResume (virDomainPtr domain) { + int rv = -1; remote_domain_resume_args args; struct private_data *priv = domain->conn->privateData; @@ -1609,14 +1669,18 @@ remoteDomainResume (virDomainPtr domain) if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_RESUME, (xdrproc_t) xdr_remote_domain_resume_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainShutdown (virDomainPtr domain) { + int rv = -1; remote_domain_shutdown_args args; struct private_data *priv = domain->conn->privateData; @@ -1625,14 +1689,18 @@ remoteDomainShutdown (virDomainPtr domai if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SHUTDOWN, (xdrproc_t) xdr_remote_domain_shutdown_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainReboot (virDomainPtr domain, unsigned int flags) { + int rv = -1; remote_domain_reboot_args args; struct private_data *priv = domain->conn->privateData; @@ -1642,14 +1710,18 @@ remoteDomainReboot (virDomainPtr domain, if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REBOOT, (xdrproc_t) xdr_remote_domain_reboot_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainDestroy (virDomainPtr domain) { + int rv = -1; remote_domain_destroy_args args; struct private_data *priv = domain->conn->privateData; @@ -1658,14 +1730,18 @@ remoteDomainDestroy (virDomainPtr domain if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DESTROY, (xdrproc_t) xdr_remote_domain_destroy_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static char * remoteDomainGetOSType (virDomainPtr domain) { + char *rv = NULL; remote_domain_get_os_type_args args; remote_domain_get_os_type_ret ret; struct private_data *priv = domain->conn->privateData; @@ -1676,15 +1752,19 @@ remoteDomainGetOSType (virDomainPtr doma if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_OS_TYPE, (xdrproc_t) xdr_remote_domain_get_os_type_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_os_type_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.type; + goto done; + + /* Caller frees. */ + rv = ret.type; + +done: + return rv; } static unsigned long remoteDomainGetMaxMemory (virDomainPtr domain) { + unsigned long rv = 0; remote_domain_get_max_memory_args args; remote_domain_get_max_memory_ret ret; struct private_data *priv = domain->conn->privateData; @@ -1695,14 +1775,18 @@ remoteDomainGetMaxMemory (virDomainPtr d if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_MEMORY, (xdrproc_t) xdr_remote_domain_get_max_memory_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_max_memory_ret, (char *) &ret) == -1) - return 0; - - return ret.memory; + goto done; + + rv = ret.memory; + +done: + return rv; } static int remoteDomainSetMaxMemory (virDomainPtr domain, unsigned long memory) { + int rv = -1; remote_domain_set_max_memory_args args; struct private_data *priv = domain->conn->privateData; @@ -1712,14 +1796,18 @@ remoteDomainSetMaxMemory (virDomainPtr d if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MAX_MEMORY, (xdrproc_t) xdr_remote_domain_set_max_memory_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainSetMemory (virDomainPtr domain, unsigned long memory) { + int rv = -1; remote_domain_set_memory_args args; struct private_data *priv = domain->conn->privateData; @@ -1729,14 +1817,18 @@ remoteDomainSetMemory (virDomainPtr doma if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY, (xdrproc_t) xdr_remote_domain_set_memory_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info) { + int rv = -1; remote_domain_get_info_args args; remote_domain_get_info_ret ret; struct private_data *priv = domain->conn->privateData; @@ -1747,7 +1839,7 @@ remoteDomainGetInfo (virDomainPtr domain if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INFO, (xdrproc_t) xdr_remote_domain_get_info_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_info_ret, (char *) &ret) == -1) - return -1; + goto done; info->state = ret.state; info->maxMem = ret.max_mem; @@ -1755,12 +1847,16 @@ remoteDomainGetInfo (virDomainPtr domain info->nrVirtCpu = ret.nr_virt_cpu; info->cpuTime = ret.cpu_time; - return 0; + rv = 0; + +done: + return rv; } static int remoteDomainSave (virDomainPtr domain, const char *to) { + int rv = -1; remote_domain_save_args args; struct private_data *priv = domain->conn->privateData; @@ -1770,14 +1866,18 @@ remoteDomainSave (virDomainPtr domain, c if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE, (xdrproc_t) xdr_remote_domain_save_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainRestore (virConnectPtr conn, const char *from) { + int rv = -1; remote_domain_restore_args args; struct private_data *priv = conn->privateData; @@ -1786,14 +1886,18 @@ remoteDomainRestore (virConnectPtr conn, if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_RESTORE, (xdrproc_t) xdr_remote_domain_restore_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainCoreDump (virDomainPtr domain, const char *to, int flags) { + int rv = -1; remote_domain_core_dump_args args; struct private_data *priv = domain->conn->privateData; @@ -1804,14 +1908,18 @@ remoteDomainCoreDump (virDomainPtr domai if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CORE_DUMP, (xdrproc_t) xdr_remote_domain_core_dump_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus) { + int rv = -1; remote_domain_set_vcpus_args args; struct private_data *priv = domain->conn->privateData; @@ -1821,9 +1929,12 @@ remoteDomainSetVcpus (virDomainPtr domai if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS, (xdrproc_t) xdr_remote_domain_set_vcpus_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int @@ -1832,6 +1943,7 @@ remoteDomainPinVcpu (virDomainPtr domain unsigned char *cpumap, int maplen) { + int rv = -1; remote_domain_pin_vcpu_args args; struct private_data *priv = domain->conn->privateData; @@ -1839,7 +1951,7 @@ remoteDomainPinVcpu (virDomainPtr domain errorf (domain->conn, VIR_ERR_RPC, _("map length greater than maximum: %d > %d"), maplen, REMOTE_CPUMAP_MAX); - return -1; + goto done; } make_nonnull_domain (&args.dom, domain); @@ -1850,9 +1962,12 @@ remoteDomainPinVcpu (virDomainPtr domain if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU, (xdrproc_t) xdr_remote_domain_pin_vcpu_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int @@ -1862,6 +1977,7 @@ remoteDomainGetVcpus (virDomainPtr domai unsigned char *cpumaps, int maplen) { + int rv = -1; int i; remote_domain_get_vcpus_args args; remote_domain_get_vcpus_ret ret; @@ -1871,13 +1987,13 @@ remoteDomainGetVcpus (virDomainPtr domai errorf (domain->conn, VIR_ERR_RPC, _("vCPU count exceeds maximum: %d > %d"), maxinfo, REMOTE_VCPUINFO_MAX); - return -1; + goto done; } if (maxinfo * maplen > REMOTE_CPUMAPS_MAX) { errorf (domain->conn, VIR_ERR_RPC, _("vCPU map buffer length exceeds maximum: %d > %d"), maxinfo * maplen, REMOTE_CPUMAPS_MAX); - return -1; + goto done; } make_nonnull_domain (&args.dom, domain); @@ -1888,21 +2004,19 @@ remoteDomainGetVcpus (virDomainPtr domai if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS, (xdrproc_t) xdr_remote_domain_get_vcpus_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.info.info_len > maxinfo) { errorf (domain->conn, VIR_ERR_RPC, _("host reports too many vCPUs: %d > %d"), ret.info.info_len, maxinfo); - xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret); - return -1; + goto cleanup; } if (ret.cpumaps.cpumaps_len > maxinfo * maplen) { errorf (domain->conn, VIR_ERR_RPC, _("host reports map buffer length exceeds maximum: %d > %d"), ret.cpumaps.cpumaps_len, maxinfo * maplen); - xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret); - return -1; + goto cleanup; } memset (info, 0, sizeof (virVcpuInfo) * maxinfo); @@ -1918,13 +2032,19 @@ remoteDomainGetVcpus (virDomainPtr domai for (i = 0; i < ret.cpumaps.cpumaps_len; ++i) cpumaps[i] = ret.cpumaps.cpumaps_val[i]; + rv = ret.info.info_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret); - return ret.info.info_len; + +done: + return rv; } static int remoteDomainGetMaxVcpus (virDomainPtr domain) { + int rv = -1; remote_domain_get_max_vcpus_args args; remote_domain_get_max_vcpus_ret ret; struct private_data *priv = domain->conn->privateData; @@ -1935,14 +2055,18 @@ remoteDomainGetMaxVcpus (virDomainPtr do if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_VCPUS, (xdrproc_t) xdr_remote_domain_get_max_vcpus_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static char * remoteDomainDumpXML (virDomainPtr domain, int flags) { + char *rv = NULL; remote_domain_dump_xml_args args; remote_domain_dump_xml_ret ret; struct private_data *priv = domain->conn->privateData; @@ -1954,10 +2078,13 @@ remoteDomainDumpXML (virDomainPtr domain if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DUMP_XML, (xdrproc_t) xdr_remote_domain_dump_xml_args, (char *) &args, (xdrproc_t) xdr_remote_domain_dump_xml_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.xml; + goto done; + + /* Caller frees. */ + rv = ret.xml; + +done: + return rv; } static int @@ -1967,6 +2094,7 @@ remoteDomainMigratePrepare (virConnectPt unsigned long flags, const char *dname, unsigned long resource) { + int rv = -1; remote_domain_migrate_prepare_args args; remote_domain_migrate_prepare_ret ret; struct private_data *priv = dconn->privateData; @@ -1980,7 +2108,7 @@ remoteDomainMigratePrepare (virConnectPt if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE, (xdrproc_t) xdr_remote_domain_migrate_prepare_args, (char *) &args, (xdrproc_t) xdr_remote_domain_migrate_prepare_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.cookie.cookie_len > 0) { *cookie = ret.cookie.cookie_val; /* Caller frees. */ @@ -1989,7 +2117,10 @@ remoteDomainMigratePrepare (virConnectPt if (ret.uri_out) *uri_out = *ret.uri_out; /* Caller frees. */ - return 0; + rv = 0; + +done: + return rv; } static int @@ -2001,6 +2132,7 @@ remoteDomainMigratePerform (virDomainPtr const char *dname, unsigned long resource) { + int rv = -1; remote_domain_migrate_perform_args args; struct private_data *priv = domain->conn->privateData; @@ -2015,9 +2147,12 @@ remoteDomainMigratePerform (virDomainPtr if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM, (xdrproc_t) xdr_remote_domain_migrate_perform_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static virDomainPtr @@ -2028,7 +2163,7 @@ remoteDomainMigrateFinish (virConnectPtr const char *uri, unsigned long flags) { - virDomainPtr ddom; + virDomainPtr ddom = NULL; remote_domain_migrate_finish_args args; remote_domain_migrate_finish_ret ret; struct private_data *priv = dconn->privateData; @@ -2043,11 +2178,12 @@ remoteDomainMigrateFinish (virConnectPtr if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH, (xdrproc_t) xdr_remote_domain_migrate_finish_args, (char *) &args, (xdrproc_t) xdr_remote_domain_migrate_finish_ret, (char *) &ret) == -1) - return NULL; + goto done; ddom = get_nonnull_domain (dconn, ret.ddom); xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish_ret, (char *) &ret); +done: return ddom; } @@ -2059,6 +2195,7 @@ remoteDomainMigratePrepare2 (virConnectP unsigned long resource, const char *dom_xml) { + int rv = -1; remote_domain_migrate_prepare2_args args; remote_domain_migrate_prepare2_ret ret; struct private_data *priv = dconn->privateData; @@ -2073,7 +2210,7 @@ remoteDomainMigratePrepare2 (virConnectP if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2, (xdrproc_t) xdr_remote_domain_migrate_prepare2_args, (char *) &args, (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.cookie.cookie_len > 0) { *cookie = ret.cookie.cookie_val; /* Caller frees. */ @@ -2082,7 +2219,10 @@ remoteDomainMigratePrepare2 (virConnectP if (ret.uri_out) *uri_out = *ret.uri_out; /* Caller frees. */ - return 0; + rv = 0; + +done: + return rv; } static virDomainPtr @@ -2094,7 +2234,7 @@ remoteDomainMigrateFinish2 (virConnectPt unsigned long flags, int retcode) { - virDomainPtr ddom; + virDomainPtr ddom = NULL; remote_domain_migrate_finish2_args args; remote_domain_migrate_finish2_ret ret; struct private_data *priv = dconn->privateData; @@ -2110,17 +2250,19 @@ remoteDomainMigrateFinish2 (virConnectPt if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH2, (xdrproc_t) xdr_remote_domain_migrate_finish2_args, (char *) &args, (xdrproc_t) xdr_remote_domain_migrate_finish2_ret, (char *) &ret) == -1) - return NULL; + goto done; ddom = get_nonnull_domain (dconn, ret.ddom); xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish2_ret, (char *) &ret); +done: return ddom; } static int remoteListDefinedDomains (virConnectPtr conn, char **const names, int maxnames) { + int rv = -1; int i; remote_list_defined_domains_args args; remote_list_defined_domains_ret ret; @@ -2130,7 +2272,7 @@ remoteListDefinedDomains (virConnectPtr errorf (conn, VIR_ERR_RPC, _("too many remote domain names: %d > %d"), maxnames, REMOTE_DOMAIN_NAME_LIST_MAX); - return -1; + goto done; } args.maxnames = maxnames; @@ -2138,32 +2280,36 @@ remoteListDefinedDomains (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_DOMAINS, (xdrproc_t) xdr_remote_list_defined_domains_args, (char *) &args, (xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { errorf (conn, VIR_ERR_RPC, _("too many remote domain names: %d > %d"), ret.names.names_len, maxnames); - xdr_free ((xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } static int remoteNumOfDefinedDomains (virConnectPtr conn) { + int rv = -1; remote_num_of_defined_domains_ret ret; struct private_data *priv = conn->privateData; @@ -2171,14 +2317,18 @@ remoteNumOfDefinedDomains (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_DOMAINS, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_num_of_defined_domains_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteDomainCreate (virDomainPtr domain) { + int rv = -1; remote_domain_create_args args; struct private_data *priv = domain->conn->privateData; @@ -2187,15 +2337,18 @@ remoteDomainCreate (virDomainPtr domain) if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE, (xdrproc_t) xdr_remote_domain_create_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static virDomainPtr remoteDomainDefineXML (virConnectPtr conn, const char *xml) { - virDomainPtr dom; + virDomainPtr dom = NULL; remote_domain_define_xml_args args; remote_domain_define_xml_ret ret; struct private_data *priv = conn->privateData; @@ -2206,17 +2359,19 @@ remoteDomainDefineXML (virConnectPtr con if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_DEFINE_XML, (xdrproc_t) xdr_remote_domain_define_xml_args, (char *) &args, (xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; dom = get_nonnull_domain (conn, ret.dom); xdr_free ((xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret); +done: return dom; } static int remoteDomainUndefine (virDomainPtr domain) { + int rv = -1; remote_domain_undefine_args args; struct private_data *priv = domain->conn->privateData; @@ -2225,14 +2380,18 @@ remoteDomainUndefine (virDomainPtr domai if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_UNDEFINE, (xdrproc_t) xdr_remote_domain_undefine_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainAttachDevice (virDomainPtr domain, const char *xml) { + int rv = -1; remote_domain_attach_device_args args; struct private_data *priv = domain->conn->privateData; @@ -2242,14 +2401,18 @@ remoteDomainAttachDevice (virDomainPtr d if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE, (xdrproc_t) xdr_remote_domain_attach_device_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainDetachDevice (virDomainPtr domain, const char *xml) { + int rv = -1; remote_domain_detach_device_args args; struct private_data *priv = domain->conn->privateData; @@ -2259,14 +2422,18 @@ remoteDomainDetachDevice (virDomainPtr d if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE, (xdrproc_t) xdr_remote_domain_detach_device_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainGetAutostart (virDomainPtr domain, int *autostart) { + int rv = -1; remote_domain_get_autostart_args args; remote_domain_get_autostart_ret ret; struct private_data *priv = domain->conn->privateData; @@ -2277,15 +2444,19 @@ remoteDomainGetAutostart (virDomainPtr d if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_AUTOSTART, (xdrproc_t) xdr_remote_domain_get_autostart_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_autostart_ret, (char *) &ret) == -1) - return -1; + goto done; if (autostart) *autostart = ret.autostart; - return 0; + rv = 0; + +done: + return rv; } static int remoteDomainSetAutostart (virDomainPtr domain, int autostart) { + int rv = -1; remote_domain_set_autostart_args args; struct private_data *priv = domain->conn->privateData; @@ -2295,14 +2466,18 @@ remoteDomainSetAutostart (virDomainPtr d if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_AUTOSTART, (xdrproc_t) xdr_remote_domain_set_autostart_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static char * remoteDomainGetSchedulerType (virDomainPtr domain, int *nparams) { + char *rv = NULL; remote_domain_get_scheduler_type_args args; remote_domain_get_scheduler_type_ret ret; struct private_data *priv = domain->conn->privateData; @@ -2313,21 +2488,25 @@ remoteDomainGetSchedulerType (virDomainP if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE, (xdrproc_t) xdr_remote_domain_get_scheduler_type_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret, (char *) &ret) == -1) - return NULL; + goto done; if (nparams) *nparams = ret.nparams; /* Caller frees this. */ - return ret.type; + rv = ret.type; + +done: + return rv; } static int remoteDomainGetSchedulerParameters (virDomainPtr domain, virSchedParameterPtr params, int *nparams) { + int rv = -1; remote_domain_get_scheduler_parameters_args args; remote_domain_get_scheduler_parameters_ret ret; - int i; + int i = -1; struct private_data *priv = domain->conn->privateData; make_nonnull_domain (&args.dom, domain); @@ -2337,16 +2516,15 @@ remoteDomainGetSchedulerParameters (virD if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS, (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_args, (char *) &args, (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, (char *) &ret) == -1) - return -1; + goto done; /* Check the length of the returned list carefully. */ if (ret.params.params_len > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX || ret.params.params_len > *nparams) { - xdr_free ((xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, (char *) &ret); error (domain->conn, VIR_ERR_RPC, _("remoteDomainGetSchedulerParameters: " "returned number of parameters exceeds limit")); - return -1; + goto cleanup; } *nparams = ret.params.params_len; @@ -2370,22 +2548,31 @@ remoteDomainGetSchedulerParameters (virD case VIR_DOMAIN_SCHED_FIELD_BOOLEAN: params[i].value.b = ret.params.params_val[i].value.remote_sched_param_value_u.b; break; default: - xdr_free ((xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, (char *) &ret); error (domain->conn, VIR_ERR_RPC, _("remoteDomainGetSchedulerParameters: " "unknown parameter type")); - return -1; - } - } - + goto cleanup; + } + } + + rv = 0; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, (char *) &ret); - return 0; + if (rv != 0) { + for ( ; i >= 0 ; i--) + VIR_FREE(params[i].field); + } + +done: + return rv; } static int remoteDomainSetSchedulerParameters (virDomainPtr domain, virSchedParameterPtr params, int nparams) { + int rv = -1; remote_domain_set_scheduler_parameters_args args; int i, do_error; struct private_data *priv = domain->conn->privateData; @@ -2396,7 +2583,7 @@ remoteDomainSetSchedulerParameters (virD args.params.params_len = nparams; if (VIR_ALLOC_N(args.params.params_val, nparams) < 0) { error (domain->conn, VIR_ERR_RPC, _("out of memory allocating array")); - return -1; + goto done; } do_error = 0; @@ -2429,21 +2616,25 @@ remoteDomainSetSchedulerParameters (virD if (do_error) { xdr_free ((xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args, (char *) &args); - return -1; + goto done; } if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS, (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteDomainBlockStats (virDomainPtr domain, const char *path, struct _virDomainBlockStats *stats) { + int rv = -1; remote_domain_block_stats_args args; remote_domain_block_stats_ret ret; struct private_data *priv = domain->conn->privateData; @@ -2456,7 +2647,7 @@ remoteDomainBlockStats (virDomainPtr dom (xdrproc_t) xdr_remote_domain_block_stats_args, (char *) &args, (xdrproc_t) xdr_remote_domain_block_stats_ret, (char *) &ret) == -1) - return -1; + goto done; stats->rd_req = ret.rd_req; stats->rd_bytes = ret.rd_bytes; @@ -2464,13 +2655,17 @@ remoteDomainBlockStats (virDomainPtr dom stats->wr_bytes = ret.wr_bytes; stats->errs = ret.errs; - return 0; + rv = 0; + +done: + return rv; } static int remoteDomainInterfaceStats (virDomainPtr domain, const char *path, struct _virDomainInterfaceStats *stats) { + int rv = -1; remote_domain_interface_stats_args args; remote_domain_interface_stats_ret ret; struct private_data *priv = domain->conn->privateData; @@ -2484,7 +2679,7 @@ remoteDomainInterfaceStats (virDomainPtr (char *) &args, (xdrproc_t) xdr_remote_domain_interface_stats_ret, (char *) &ret) == -1) - return -1; + goto done; stats->rx_bytes = ret.rx_bytes; stats->rx_packets = ret.rx_packets; @@ -2495,7 +2690,10 @@ remoteDomainInterfaceStats (virDomainPtr stats->tx_errs = ret.tx_errs; stats->tx_drop = ret.tx_drop; - return 0; + rv = 0; + +done: + return rv; } static int @@ -2506,6 +2704,7 @@ remoteDomainBlockPeek (virDomainPtr doma void *buffer, unsigned int flags) { + int rv = -1; remote_domain_block_peek_args args; remote_domain_block_peek_ret ret; struct private_data *priv = domain->conn->privateData; @@ -2514,7 +2713,7 @@ remoteDomainBlockPeek (virDomainPtr doma errorf (domain->conn, VIR_ERR_RPC, _("block peek request too large for remote protocol, %zi > %d"), size, REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX); - return -1; + goto done; } make_nonnull_domain (&args.dom, domain); @@ -2529,19 +2728,22 @@ remoteDomainBlockPeek (virDomainPtr doma (char *) &args, (xdrproc_t) xdr_remote_domain_block_peek_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.buffer.buffer_len != size) { - errorf (domain->conn, VIR_ERR_RPC, - "%s", _("returned buffer is not same size as requested")); - free (ret.buffer.buffer_val); - return -1; + errorf (domain->conn, VIR_ERR_RPC, + "%s", _("returned buffer is not same size as requested")); + goto cleanup; } memcpy (buffer, ret.buffer.buffer_val, size); + rv = 0; + +cleanup: free (ret.buffer.buffer_val); - return 0; +done: + return rv; } static int @@ -2551,6 +2753,7 @@ remoteDomainMemoryPeek (virDomainPtr dom void *buffer, unsigned int flags) { + int rv = -1; remote_domain_memory_peek_args args; remote_domain_memory_peek_ret ret; struct private_data *priv = domain->conn->privateData; @@ -2559,7 +2762,7 @@ remoteDomainMemoryPeek (virDomainPtr dom errorf (domain->conn, VIR_ERR_RPC, _("memory peek request too large for remote protocol, %zi > %d"), size, REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX); - return -1; + goto done; } make_nonnull_domain (&args.dom, domain); @@ -2573,19 +2776,22 @@ remoteDomainMemoryPeek (virDomainPtr dom (char *) &args, (xdrproc_t) xdr_remote_domain_memory_peek_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.buffer.buffer_len != size) { - errorf (domain->conn, VIR_ERR_RPC, - "%s", _("returned buffer is not same size as requested")); - free (ret.buffer.buffer_val); - return -1; + errorf (domain->conn, VIR_ERR_RPC, + "%s", _("returned buffer is not same size as requested")); + goto cleanup; } memcpy (buffer, ret.buffer.buffer_val, size); + rv = 0; + +cleanup: free (ret.buffer.buffer_val); - return 0; +done: + return rv; } /*----------------------------------------------------------------------*/ @@ -2639,23 +2845,24 @@ static int static int remoteNetworkClose (virConnectPtr conn) { - int ret = 0; + int rv = 0; struct private_data *priv = conn->networkPrivateData; if (priv->localUses) { priv->localUses--; if (!priv->localUses) { - ret = doRemoteClose(conn, priv); + rv = doRemoteClose(conn, priv); VIR_FREE(priv); conn->networkPrivateData = NULL; } } - return ret; + return rv; } static int remoteNumOfNetworks (virConnectPtr conn) { + int rv = -1; remote_num_of_networks_ret ret; struct private_data *priv = conn->networkPrivateData; @@ -2663,14 +2870,18 @@ remoteNumOfNetworks (virConnectPtr conn) if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_num_of_networks_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteListNetworks (virConnectPtr conn, char **const names, int maxnames) { + int rv = -1; int i; remote_list_networks_args args; remote_list_networks_ret ret; @@ -2680,7 +2891,7 @@ remoteListNetworks (virConnectPtr conn, errorf (conn, VIR_ERR_RPC, _("too many remote networks: %d > %d"), maxnames, REMOTE_NETWORK_NAME_LIST_MAX); - return -1; + goto done; } args.maxnames = maxnames; @@ -2688,32 +2899,36 @@ remoteListNetworks (virConnectPtr conn, if (call (conn, priv, 0, REMOTE_PROC_LIST_NETWORKS, (xdrproc_t) xdr_remote_list_networks_args, (char *) &args, (xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { errorf (conn, VIR_ERR_RPC, _("too many remote networks: %d > %d"), ret.names.names_len, maxnames); - xdr_free ((xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } static int remoteNumOfDefinedNetworks (virConnectPtr conn) { + int rv = -1; remote_num_of_defined_networks_ret ret; struct private_data *priv = conn->networkPrivateData; @@ -2721,15 +2936,19 @@ remoteNumOfDefinedNetworks (virConnectPt if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_num_of_defined_networks_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteListDefinedNetworks (virConnectPtr conn, char **const names, int maxnames) { + int rv = -1; int i; remote_list_defined_networks_args args; remote_list_defined_networks_ret ret; @@ -2739,7 +2958,7 @@ remoteListDefinedNetworks (virConnectPtr errorf (conn, VIR_ERR_RPC, _("too many remote networks: %d > %d"), maxnames, REMOTE_NETWORK_NAME_LIST_MAX); - return -1; + goto done; } args.maxnames = maxnames; @@ -2747,34 +2966,37 @@ remoteListDefinedNetworks (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_NETWORKS, (xdrproc_t) xdr_remote_list_defined_networks_args, (char *) &args, (xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { errorf (conn, VIR_ERR_RPC, _("too many remote networks: %d > %d"), ret.names.names_len, maxnames); - xdr_free ((xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } static virNetworkPtr remoteNetworkLookupByUUID (virConnectPtr conn, const unsigned char *uuid) { - virNetworkPtr net; + virNetworkPtr net = NULL; remote_network_lookup_by_uuid_args args; remote_network_lookup_by_uuid_ret ret; struct private_data *priv = conn->networkPrivateData; @@ -2785,11 +3007,12 @@ remoteNetworkLookupByUUID (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_UUID, (xdrproc_t) xdr_remote_network_lookup_by_uuid_args, (char *) &args, (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret, (char *) &ret) == -1) - return NULL; + goto done; net = get_nonnull_network (conn, ret.net); xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_uuid_ret, (char *) &ret); +done: return net; } @@ -2797,7 +3020,7 @@ remoteNetworkLookupByName (virConnectPtr remoteNetworkLookupByName (virConnectPtr conn, const char *name) { - virNetworkPtr net; + virNetworkPtr net = NULL; remote_network_lookup_by_name_args args; remote_network_lookup_by_name_ret ret; struct private_data *priv = conn->networkPrivateData; @@ -2808,18 +3031,19 @@ remoteNetworkLookupByName (virConnectPtr if (call (conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_NAME, (xdrproc_t) xdr_remote_network_lookup_by_name_args, (char *) &args, (xdrproc_t) xdr_remote_network_lookup_by_name_ret, (char *) &ret) == -1) - return NULL; + goto done; net = get_nonnull_network (conn, ret.net); xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_name_ret, (char *) &ret); +done: return net; } static virNetworkPtr remoteNetworkCreateXML (virConnectPtr conn, const char *xmlDesc) { - virNetworkPtr net; + virNetworkPtr net = NULL; remote_network_create_xml_args args; remote_network_create_xml_ret ret; struct private_data *priv = conn->networkPrivateData; @@ -2830,18 +3054,19 @@ remoteNetworkCreateXML (virConnectPtr co if (call (conn, priv, 0, REMOTE_PROC_NETWORK_CREATE_XML, (xdrproc_t) xdr_remote_network_create_xml_args, (char *) &args, (xdrproc_t) xdr_remote_network_create_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; net = get_nonnull_network (conn, ret.net); xdr_free ((xdrproc_t) &xdr_remote_network_create_xml_ret, (char *) &ret); +done: return net; } static virNetworkPtr remoteNetworkDefineXML (virConnectPtr conn, const char *xml) { - virNetworkPtr net; + virNetworkPtr net = NULL; remote_network_define_xml_args args; remote_network_define_xml_ret ret; struct private_data *priv = conn->networkPrivateData; @@ -2852,17 +3077,19 @@ remoteNetworkDefineXML (virConnectPtr co if (call (conn, priv, 0, REMOTE_PROC_NETWORK_DEFINE_XML, (xdrproc_t) xdr_remote_network_define_xml_args, (char *) &args, (xdrproc_t) xdr_remote_network_define_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; net = get_nonnull_network (conn, ret.net); xdr_free ((xdrproc_t) &xdr_remote_network_define_xml_ret, (char *) &ret); +done: return net; } static int remoteNetworkUndefine (virNetworkPtr network) { + int rv = -1; remote_network_undefine_args args; struct private_data *priv = network->conn->networkPrivateData; @@ -2871,14 +3098,18 @@ remoteNetworkUndefine (virNetworkPtr net if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_UNDEFINE, (xdrproc_t) xdr_remote_network_undefine_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteNetworkCreate (virNetworkPtr network) { + int rv = -1; remote_network_create_args args; struct private_data *priv = network->conn->networkPrivateData; @@ -2887,14 +3118,18 @@ remoteNetworkCreate (virNetworkPtr netwo if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_CREATE, (xdrproc_t) xdr_remote_network_create_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteNetworkDestroy (virNetworkPtr network) { + int rv = -1; remote_network_destroy_args args; struct private_data *priv = network->conn->networkPrivateData; @@ -2903,14 +3138,18 @@ remoteNetworkDestroy (virNetworkPtr netw if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_DESTROY, (xdrproc_t) xdr_remote_network_destroy_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static char * remoteNetworkDumpXML (virNetworkPtr network, int flags) { + char *rv = NULL; remote_network_dump_xml_args args; remote_network_dump_xml_ret ret; struct private_data *priv = network->conn->networkPrivateData; @@ -2922,15 +3161,19 @@ remoteNetworkDumpXML (virNetworkPtr netw if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_DUMP_XML, (xdrproc_t) xdr_remote_network_dump_xml_args, (char *) &args, (xdrproc_t) xdr_remote_network_dump_xml_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.xml; + goto done; + + /* Caller frees. */ + rv = ret.xml; + +done: + return rv; } static char * remoteNetworkGetBridgeName (virNetworkPtr network) { + char *rv = NULL; remote_network_get_bridge_name_args args; remote_network_get_bridge_name_ret ret; struct private_data *priv = network->conn->networkPrivateData; @@ -2941,15 +3184,19 @@ remoteNetworkGetBridgeName (virNetworkPt if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_GET_BRIDGE_NAME, (xdrproc_t) xdr_remote_network_get_bridge_name_args, (char *) &args, (xdrproc_t) xdr_remote_network_get_bridge_name_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.name; + goto done; + + /* Caller frees. */ + rv = ret.name; + +done: + return rv; } static int remoteNetworkGetAutostart (virNetworkPtr network, int *autostart) { + int rv = -1; remote_network_get_autostart_args args; remote_network_get_autostart_ret ret; struct private_data *priv = network->conn->networkPrivateData; @@ -2960,16 +3207,20 @@ remoteNetworkGetAutostart (virNetworkPtr if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_GET_AUTOSTART, (xdrproc_t) xdr_remote_network_get_autostart_args, (char *) &args, (xdrproc_t) xdr_remote_network_get_autostart_ret, (char *) &ret) == -1) - return -1; + goto done; if (autostart) *autostart = ret.autostart; - return 0; + rv = 0; + +done: + return rv; } static int remoteNetworkSetAutostart (virNetworkPtr network, int autostart) { + int rv = -1; remote_network_set_autostart_args args; struct private_data *priv = network->conn->networkPrivateData; @@ -2979,9 +3230,12 @@ remoteNetworkSetAutostart (virNetworkPtr if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_SET_AUTOSTART, (xdrproc_t) xdr_remote_network_set_autostart_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } @@ -3054,12 +3308,14 @@ remoteStorageClose (virConnectPtr conn) conn->storagePrivateData = NULL; } } + return ret; } static int remoteNumOfStoragePools (virConnectPtr conn) { + int rv = -1; remote_num_of_storage_pools_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3067,14 +3323,18 @@ remoteNumOfStoragePools (virConnectPtr c if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_STORAGE_POOLS, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_num_of_storage_pools_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteListStoragePools (virConnectPtr conn, char **const names, int maxnames) { + int rv = -1; int i; remote_list_storage_pools_args args; remote_list_storage_pools_ret ret; @@ -3082,7 +3342,7 @@ remoteListStoragePools (virConnectPtr co if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many storage pools requested")); - return -1; + goto done; } args.maxnames = maxnames; @@ -3090,30 +3350,34 @@ remoteListStoragePools (virConnectPtr co if (call (conn, priv, 0, REMOTE_PROC_LIST_STORAGE_POOLS, (xdrproc_t) xdr_remote_list_storage_pools_args, (char *) &args, (xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { error (conn, VIR_ERR_RPC, _("too many storage pools received")); - xdr_free ((xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } static int remoteNumOfDefinedStoragePools (virConnectPtr conn) { + int rv = -1; remote_num_of_defined_storage_pools_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3121,15 +3385,19 @@ remoteNumOfDefinedStoragePools (virConne if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_remote_num_of_defined_storage_pools_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteListDefinedStoragePools (virConnectPtr conn, char **const names, int maxnames) { + int rv = -1; int i; remote_list_defined_storage_pools_args args; remote_list_defined_storage_pools_ret ret; @@ -3137,7 +3405,7 @@ remoteListDefinedStoragePools (virConnec if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many storage pools requested")); - return -1; + goto done; } args.maxnames = maxnames; @@ -3145,25 +3413,28 @@ remoteListDefinedStoragePools (virConnec if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS, (xdrproc_t) xdr_remote_list_defined_storage_pools_args, (char *) &args, (xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { error (conn, VIR_ERR_RPC, _("too many storage pools received")); - xdr_free ((xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } static char * @@ -3172,11 +3443,11 @@ remoteFindStoragePoolSources (virConnect const char *srcSpec, unsigned int flags) { + char *rv = NULL; remote_find_storage_pool_sources_args args; remote_find_storage_pool_sources_ret ret; struct private_data *priv = conn->storagePrivateData; const char *emptyString = ""; - char *retval; args.type = (char*)type; /* @@ -3197,21 +3468,22 @@ remoteFindStoragePoolSources (virConnect if (call (conn, priv, 0, REMOTE_PROC_FIND_STORAGE_POOL_SOURCES, (xdrproc_t) xdr_remote_find_storage_pool_sources_args, (char *) &args, (xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret) == -1) - return NULL; - - retval = ret.xml; + goto done; + + rv = ret.xml; ret.xml = NULL; /* To stop xdr_free free'ing it */ xdr_free ((xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret); - return retval; +done: + return rv; } static virStoragePoolPtr remoteStoragePoolLookupByUUID (virConnectPtr conn, const unsigned char *uuid) { - virStoragePoolPtr pool; + virStoragePoolPtr pool = NULL; remote_storage_pool_lookup_by_uuid_args args; remote_storage_pool_lookup_by_uuid_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3222,11 +3494,12 @@ remoteStoragePoolLookupByUUID (virConnec if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID, (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret) == -1) - return NULL; + goto done; pool = get_nonnull_storage_pool (conn, ret.pool); xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret); +done: return pool; } @@ -3234,7 +3507,7 @@ remoteStoragePoolLookupByName (virConnec remoteStoragePoolLookupByName (virConnectPtr conn, const char *name) { - virStoragePoolPtr pool; + virStoragePoolPtr pool = NULL; remote_storage_pool_lookup_by_name_args args; remote_storage_pool_lookup_by_name_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3245,18 +3518,19 @@ remoteStoragePoolLookupByName (virConnec if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME, (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret) == -1) - return NULL; + goto done; pool = get_nonnull_storage_pool (conn, ret.pool); xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret); +done: return pool; } static virStoragePoolPtr remoteStoragePoolLookupByVolume (virStorageVolPtr vol) { - virStoragePoolPtr pool; + virStoragePoolPtr pool = NULL; remote_storage_pool_lookup_by_volume_args args; remote_storage_pool_lookup_by_volume_ret ret; struct private_data *priv = vol->conn->storagePrivateData; @@ -3267,11 +3541,12 @@ remoteStoragePoolLookupByVolume (virStor if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME, (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret) == -1) - return NULL; + goto done; pool = get_nonnull_storage_pool (vol->conn, ret.pool); xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret); +done: return pool; } @@ -3279,7 +3554,7 @@ static virStoragePoolPtr static virStoragePoolPtr remoteStoragePoolCreateXML (virConnectPtr conn, const char *xmlDesc, unsigned int flags) { - virStoragePoolPtr pool; + virStoragePoolPtr pool = NULL; remote_storage_pool_create_xml_args args; remote_storage_pool_create_xml_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3291,18 +3566,19 @@ remoteStoragePoolCreateXML (virConnectPt if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE_XML, (xdrproc_t) xdr_remote_storage_pool_create_xml_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_create_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; pool = get_nonnull_storage_pool (conn, ret.pool); xdr_free ((xdrproc_t) &xdr_remote_storage_pool_create_xml_ret, (char *) &ret); +done: return pool; } static virStoragePoolPtr remoteStoragePoolDefineXML (virConnectPtr conn, const char *xml, unsigned int flags) { - virStoragePoolPtr pool; + virStoragePoolPtr pool = NULL; remote_storage_pool_define_xml_args args; remote_storage_pool_define_xml_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3314,17 +3590,19 @@ remoteStoragePoolDefineXML (virConnectPt if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DEFINE_XML, (xdrproc_t) xdr_remote_storage_pool_define_xml_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_define_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; pool = get_nonnull_storage_pool (conn, ret.pool); xdr_free ((xdrproc_t) &xdr_remote_storage_pool_define_xml_ret, (char *) &ret); +done: return pool; } static int remoteStoragePoolUndefine (virStoragePoolPtr pool) { + int rv = -1; remote_storage_pool_undefine_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3333,14 +3611,18 @@ remoteStoragePoolUndefine (virStoragePoo if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_UNDEFINE, (xdrproc_t) xdr_remote_storage_pool_undefine_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolCreate (virStoragePoolPtr pool, unsigned int flags) { + int rv = -1; remote_storage_pool_create_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3350,15 +3632,19 @@ remoteStoragePoolCreate (virStoragePoolP if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE, (xdrproc_t) xdr_remote_storage_pool_create_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolBuild (virStoragePoolPtr pool, unsigned int flags) { + int rv = -1; remote_storage_pool_build_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3368,14 +3654,18 @@ remoteStoragePoolBuild (virStoragePoolPt if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_BUILD, (xdrproc_t) xdr_remote_storage_pool_build_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolDestroy (virStoragePoolPtr pool) { + int rv = -1; remote_storage_pool_destroy_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3384,15 +3674,19 @@ remoteStoragePoolDestroy (virStoragePool if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DESTROY, (xdrproc_t) xdr_remote_storage_pool_destroy_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolDelete (virStoragePoolPtr pool, unsigned int flags) { + int rv = -1; remote_storage_pool_delete_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3402,15 +3696,19 @@ remoteStoragePoolDelete (virStoragePoolP if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DELETE, (xdrproc_t) xdr_remote_storage_pool_delete_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolRefresh (virStoragePoolPtr pool, unsigned int flags) { + int rv = -1; remote_storage_pool_refresh_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3420,14 +3718,18 @@ remoteStoragePoolRefresh (virStoragePool if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_REFRESH, (xdrproc_t) xdr_remote_storage_pool_refresh_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolGetInfo (virStoragePoolPtr pool, virStoragePoolInfoPtr info) { + int rv = -1; remote_storage_pool_get_info_args args; remote_storage_pool_get_info_ret ret; struct private_data *priv = pool->conn->storagePrivateData; @@ -3438,20 +3740,24 @@ remoteStoragePoolGetInfo (virStoragePool if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_INFO, (xdrproc_t) xdr_remote_storage_pool_get_info_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_get_info_ret, (char *) &ret) == -1) - return -1; + goto done; info->state = ret.state; info->capacity = ret.capacity; info->allocation = ret.allocation; info->available = ret.available; - return 0; + rv = 0; + +done: + return rv; } static char * remoteStoragePoolDumpXML (virStoragePoolPtr pool, unsigned int flags) { + char *rv = NULL; remote_storage_pool_dump_xml_args args; remote_storage_pool_dump_xml_ret ret; struct private_data *priv = pool->conn->storagePrivateData; @@ -3463,15 +3769,19 @@ remoteStoragePoolDumpXML (virStoragePool if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DUMP_XML, (xdrproc_t) xdr_remote_storage_pool_dump_xml_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.xml; + goto done; + + /* Caller frees. */ + rv = ret.xml; + +done: + return rv; } static int remoteStoragePoolGetAutostart (virStoragePoolPtr pool, int *autostart) { + int rv = -1; remote_storage_pool_get_autostart_args args; remote_storage_pool_get_autostart_ret ret; struct private_data *priv = pool->conn->storagePrivateData; @@ -3482,16 +3792,20 @@ remoteStoragePoolGetAutostart (virStorag if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART, (xdrproc_t) xdr_remote_storage_pool_get_autostart_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_get_autostart_ret, (char *) &ret) == -1) - return -1; + goto done; if (autostart) *autostart = ret.autostart; - return 0; + rv = 0; + +done: + return rv; } static int remoteStoragePoolSetAutostart (virStoragePoolPtr pool, int autostart) { + int rv = -1; remote_storage_pool_set_autostart_args args; struct private_data *priv = pool->conn->storagePrivateData; @@ -3501,15 +3815,19 @@ remoteStoragePoolSetAutostart (virStorag if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART, (xdrproc_t) xdr_remote_storage_pool_set_autostart_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStoragePoolNumOfVolumes (virStoragePoolPtr pool) { + int rv = -1; remote_storage_pool_num_of_volumes_args args; remote_storage_pool_num_of_volumes_ret ret; struct private_data *priv = pool->conn->storagePrivateData; @@ -3520,14 +3838,18 @@ remoteStoragePoolNumOfVolumes (virStorag if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES, (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteStoragePoolListVolumes (virStoragePoolPtr pool, char **const names, int maxnames) { + int rv = -1; int i; remote_storage_pool_list_volumes_args args; remote_storage_pool_list_volumes_ret ret; @@ -3535,7 +3857,7 @@ remoteStoragePoolListVolumes (virStorage if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { error (pool->conn, VIR_ERR_RPC, _("too many storage volumes requested")); - return -1; + goto done; } args.maxnames = maxnames; make_nonnull_storage_pool(&args.pool, pool); @@ -3544,25 +3866,28 @@ remoteStoragePoolListVolumes (virStorage if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES, (xdrproc_t) xdr_remote_storage_pool_list_volumes_args, (char *) &args, (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { error (pool->conn, VIR_ERR_RPC, _("too many storage volumes received")); - xdr_free ((xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } @@ -3571,7 +3896,7 @@ remoteStorageVolLookupByName (virStorage remoteStorageVolLookupByName (virStoragePoolPtr pool, const char *name) { - virStorageVolPtr vol; + virStorageVolPtr vol = NULL; remote_storage_vol_lookup_by_name_args args; remote_storage_vol_lookup_by_name_ret ret; struct private_data *priv = pool->conn->storagePrivateData; @@ -3583,11 +3908,12 @@ remoteStorageVolLookupByName (virStorage if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME, (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret) == -1) - return NULL; + goto done; vol = get_nonnull_storage_vol (pool->conn, ret.vol); xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret); +done: return vol; } @@ -3595,7 +3921,7 @@ remoteStorageVolLookupByKey (virConnectP remoteStorageVolLookupByKey (virConnectPtr conn, const char *key) { - virStorageVolPtr vol; + virStorageVolPtr vol = NULL; remote_storage_vol_lookup_by_key_args args; remote_storage_vol_lookup_by_key_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3606,11 +3932,12 @@ remoteStorageVolLookupByKey (virConnectP if (call (conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY, (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret) == -1) - return NULL; + goto done; vol = get_nonnull_storage_vol (conn, ret.vol); xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret); +done: return vol; } @@ -3618,7 +3945,7 @@ remoteStorageVolLookupByPath (virConnect remoteStorageVolLookupByPath (virConnectPtr conn, const char *path) { - virStorageVolPtr vol; + virStorageVolPtr vol = NULL; remote_storage_vol_lookup_by_path_args args; remote_storage_vol_lookup_by_path_ret ret; struct private_data *priv = conn->storagePrivateData; @@ -3629,11 +3956,12 @@ remoteStorageVolLookupByPath (virConnect if (call (conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH, (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret) == -1) - return NULL; + goto done; vol = get_nonnull_storage_vol (conn, ret.vol); xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret); +done: return vol; } @@ -3641,7 +3969,7 @@ remoteStorageVolCreateXML (virStoragePoo remoteStorageVolCreateXML (virStoragePoolPtr pool, const char *xmlDesc, unsigned int flags) { - virStorageVolPtr vol; + virStorageVolPtr vol = NULL; remote_storage_vol_create_xml_args args; remote_storage_vol_create_xml_ret ret; struct private_data *priv = pool->conn->storagePrivateData; @@ -3654,11 +3982,12 @@ remoteStorageVolCreateXML (virStoragePoo if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML, (xdrproc_t) xdr_remote_storage_vol_create_xml_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_create_xml_ret, (char *) &ret) == -1) - return NULL; + goto done; vol = get_nonnull_storage_vol (pool->conn, ret.vol); xdr_free ((xdrproc_t) &xdr_remote_storage_vol_create_xml_ret, (char *) &ret); +done: return vol; } @@ -3666,6 +3995,7 @@ remoteStorageVolDelete (virStorageVolPtr remoteStorageVolDelete (virStorageVolPtr vol, unsigned int flags) { + int rv = -1; remote_storage_vol_delete_args args; struct private_data *priv = vol->conn->storagePrivateData; @@ -3675,14 +4005,18 @@ remoteStorageVolDelete (virStorageVolPtr if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DELETE, (xdrproc_t) xdr_remote_storage_vol_delete_args, (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - - return 0; + goto done; + + rv = 0; + +done: + return rv; } static int remoteStorageVolGetInfo (virStorageVolPtr vol, virStorageVolInfoPtr info) { + int rv = -1; remote_storage_vol_get_info_args args; remote_storage_vol_get_info_ret ret; struct private_data *priv = vol->conn->storagePrivateData; @@ -3693,19 +4027,23 @@ remoteStorageVolGetInfo (virStorageVolPt if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO, (xdrproc_t) xdr_remote_storage_vol_get_info_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_get_info_ret, (char *) &ret) == -1) - return -1; + goto done; info->type = ret.type; info->capacity = ret.capacity; info->allocation = ret.allocation; - return 0; + rv = 0; + +done: + return rv; } static char * remoteStorageVolDumpXML (virStorageVolPtr vol, unsigned int flags) { + char *rv = NULL; remote_storage_vol_dump_xml_args args; remote_storage_vol_dump_xml_ret ret; struct private_data *priv = vol->conn->storagePrivateData; @@ -3717,15 +4055,19 @@ remoteStorageVolDumpXML (virStorageVolPt if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DUMP_XML, (xdrproc_t) xdr_remote_storage_vol_dump_xml_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.xml; + goto done; + + /* Caller frees. */ + rv = ret.xml; + +done: + return rv; } static char * remoteStorageVolGetPath (virStorageVolPtr vol) { + char *rv = NULL; remote_storage_vol_get_path_args args; remote_storage_vol_get_path_ret ret; struct private_data *priv = vol->conn->storagePrivateData; @@ -3736,10 +4078,13 @@ remoteStorageVolGetPath (virStorageVolPt if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_PATH, (xdrproc_t) xdr_remote_storage_vol_get_path_args, (char *) &args, (xdrproc_t) xdr_remote_storage_vol_get_path_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.name; + goto done; + + /* Caller frees. */ + rv = ret.name; + +done: + return rv; } @@ -3785,6 +4130,7 @@ static int remoteNodeNumOfDevices(virCon const char *cap, unsigned int flags) { + int rv = -1; remote_node_num_of_devices_args args; remote_node_num_of_devices_ret ret; struct private_data *priv = conn->devMonPrivateData; @@ -3796,9 +4142,12 @@ static int remoteNodeNumOfDevices(virCon if (call (conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES, (xdrproc_t) xdr_remote_node_num_of_devices_args, (char *) &args, (xdrproc_t) xdr_remote_node_num_of_devices_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } @@ -3808,6 +4157,7 @@ static int remoteNodeListDevices(virConn int maxnames, unsigned int flags) { + int rv = -1; int i; remote_node_list_devices_args args; remote_node_list_devices_ret ret; @@ -3815,7 +4165,7 @@ static int remoteNodeListDevices(virConn if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many device names requested")); - return -1; + goto done; } args.cap = cap ? (char **)&cap : NULL; args.maxnames = maxnames; @@ -3825,25 +4175,28 @@ static int remoteNodeListDevices(virConn if (call (conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES, (xdrproc_t) xdr_remote_node_list_devices_args, (char *) &args, (xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { error (conn, VIR_ERR_RPC, _("too many device names received")); - xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } @@ -3852,7 +4205,7 @@ static virNodeDevicePtr remoteNodeDevice { remote_node_device_lookup_by_name_args args; remote_node_device_lookup_by_name_ret ret; - virNodeDevicePtr dev; + virNodeDevicePtr dev = NULL; struct private_data *priv = conn->devMonPrivateData; args.name = (char *)name; @@ -3861,18 +4214,20 @@ static virNodeDevicePtr remoteNodeDevice if (call (conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME, (xdrproc_t) xdr_remote_node_device_lookup_by_name_args, (char *) &args, (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret) == -1) - return NULL; + goto done; dev = get_nonnull_node_device(conn, ret.dev); xdr_free ((xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret); +done: return dev; } static char *remoteNodeDeviceDumpXML(virNodeDevicePtr dev, unsigned int flags) { + char *rv = NULL; remote_node_device_dump_xml_args args; remote_node_device_dump_xml_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; @@ -3884,14 +4239,18 @@ static char *remoteNodeDeviceDumpXML(vir if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DUMP_XML, (xdrproc_t) xdr_remote_node_device_dump_xml_args, (char *) &args, (xdrproc_t) xdr_remote_node_device_dump_xml_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.xml; + goto done; + + /* Caller frees. */ + rv = ret.xml; + +done: + return rv; } static char *remoteNodeDeviceGetParent(virNodeDevicePtr dev) { + char *rv = NULL; remote_node_device_get_parent_args args; remote_node_device_get_parent_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; @@ -3902,14 +4261,18 @@ static char *remoteNodeDeviceGetParent(v if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_GET_PARENT, (xdrproc_t) xdr_remote_node_device_get_parent_args, (char *) &args, (xdrproc_t) xdr_remote_node_device_get_parent_ret, (char *) &ret) == -1) - return NULL; - - /* Caller frees. */ - return ret.parent ? *ret.parent : NULL; + goto done; + + /* Caller frees. */ + rv = ret.parent ? *ret.parent : NULL; + +done: + return rv; } static int remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev) { + int rv = -1; remote_node_device_num_of_caps_args args; remote_node_device_num_of_caps_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; @@ -3920,15 +4283,19 @@ static int remoteNodeDeviceNumOfCaps(vir if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS, (xdrproc_t) xdr_remote_node_device_num_of_caps_args, (char *) &args, (xdrproc_t) xdr_remote_node_device_num_of_caps_ret, (char *) &ret) == -1) - return -1; - - return ret.num; + goto done; + + rv = ret.num; + +done: + return rv; } static int remoteNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) { + int rv = -1; int i; remote_node_device_list_caps_args args; remote_node_device_list_caps_ret ret; @@ -3936,7 +4303,7 @@ static int remoteNodeDeviceListCaps(virN if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { error (dev->conn, VIR_ERR_RPC, _("too many capability names requested")); - return -1; + goto done; } args.maxnames = maxnames; args.name = dev->name; @@ -3945,25 +4312,28 @@ static int remoteNodeDeviceListCaps(virN if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LIST_CAPS, (xdrproc_t) xdr_remote_node_device_list_caps_args, (char *) &args, (xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret) == -1) - return -1; + goto done; if (ret.names.names_len > maxnames) { error (dev->conn, VIR_ERR_RPC, _("too many capability names received")); - xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret); - return -1; - } - - /* This call is caller-frees (although that isn't clear from - * the documentation). However xdr_free will free up both the - * names and the list of pointers, so we have to strdup the - * names here. - */ - for (i = 0; i < ret.names.names_len; ++i) - names[i] = strdup (ret.names.names_val[i]); - + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret); - return ret.names.names_len; +done: + return rv; } @@ -4620,6 +4990,7 @@ remoteAuthSASL (virConnectPtr conn, stru remoteAuthFreeCredentials(cred, ncred); if (ret != 0 && saslconn) sasl_dispose(&saslconn); + return ret; } #endif /* HAVE_SASL */ @@ -4684,16 +5055,17 @@ static int remoteDomainEventRegister (vi void *opaque ATTRIBUTE_UNUSED, virFreeCallback freecb) { + int rv = -1; struct private_data *priv = conn->privateData; if (priv->eventFlushTimer < 0) { error (conn, VIR_ERR_NO_SUPPORT, _("no event support")); - return -1; + goto done; } if (virDomainEventCallbackListAdd(conn, priv->callbackList, callback, opaque, freecb) < 0) { error (conn, VIR_ERR_RPC, _("adding cb to list")); - return -1; + goto done; } if ( priv->callbackList->count == 1 ) { @@ -4701,21 +5073,25 @@ static int remoteDomainEventRegister (vi if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - } - - return 0; + goto done; + } + + rv = 0; + +done: + return rv; } static int remoteDomainEventDeregister (virConnectPtr conn, - void *callback ATTRIBUTE_UNUSED) -{ + void *callback ATTRIBUTE_UNUSED) +{ + int rv = -1; struct private_data *priv = conn->privateData; if (virDomainEventCallbackListRemove(conn, priv->callbackList, - callback) < 0) { + callback) < 0) { error (conn, VIR_ERR_RPC, _("removing cb fron list")); - return -1; + goto done; } if ( priv->callbackList->count == 0 ) { @@ -4723,10 +5099,13 @@ static int remoteDomainEventDeregister ( if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER, (xdrproc_t) xdr_void, (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL) == -1) - return -1; - } - - return 0; + goto done; + } + + rv = 0; + +done: + return rv; } /*----------------------------------------------------------------------*/ @@ -5524,22 +5903,22 @@ remoteDomainEventFired(int watch, DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); virEventRemoveHandle(watch); - return; + goto done; } if (fd != priv->sock) { virEventRemoveHandle(watch); - return; + goto done; } /* Read and deserialise length word. */ if (really_read (conn, priv, 0, buffer2, sizeof buffer2) == -1) - return; + goto done; xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE); if (!xdr_int (&xdr, &len)) { error (conn, VIR_ERR_RPC, _("xdr_int (length word, reply)")); - return; + goto done; } xdr_destroy (&xdr); @@ -5548,20 +5927,20 @@ remoteDomainEventFired(int watch, if (len < 0 || len > REMOTE_MESSAGE_MAX) { error (conn, VIR_ERR_RPC, _("packet received from server too large")); - return; + goto done; } /* Read reply header and what follows (either a ret or an error). */ if (really_read (conn, priv, 0, buffer, len) == -1) { error (conn, VIR_ERR_RPC, _("error reading buffer from memory")); - return; + goto done; } /* Deserialise reply header. */ xdrmem_create (&xdr, buffer, len, XDR_DECODE); if (!xdr_remote_message_header (&xdr, &hdr)) { error (conn, VIR_ERR_RPC, _("invalid header in event firing")); - return; + goto done; } if (hdr.proc == REMOTE_PROC_DOMAIN_EVENT && @@ -5572,6 +5951,9 @@ remoteDomainEventFired(int watch, DEBUG0("invalid proc in event firing"); error (conn, VIR_ERR_RPC, _("invalid proc in event firing")); } + +done: + return; } void 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 remote driver's internal 'struct private_data' object thread-safe. All the driver APIs will lock & unlock this data before accessing it. I'm also doing full reference counting on it now, because it will shortly be shareable across multiple virConnectPtr objects once virConnetClone is introduced. NB, although thread safe, it is not possible to parallelize API calls. This is because the call() method which actually does the RPC call will block on the socket read() waiting for the RPC reply. It holds the lock while doing this. So all threads are blocked for the duration of an RPC call. Safely lifting this restriction is in fact very very hard. I do have a plan for this which I call 'passing the buck'. More details to follow in a later patch for this once I actually have it working... Even then it won't be hugely useful since the libvirtd serializes all RPC calls from a single socket. But it will allow for receiving events promptly. I have of course validated this locking with Ocaml/CIL Daniel diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -89,6 +89,8 @@ static int inside_daemon = 0; static int inside_daemon = 0; struct private_data { + PTHREAD_MUTEX_T(lock); + int sock; /* Socket. */ int watch; /* File handle watch */ pid_t pid; /* PID of tunnel process */ @@ -119,6 +121,16 @@ enum { REMOTE_CALL_QUIET_MISSING_RPC = 2, }; + +static void remoteDriverLock(struct private_data *driver) +{ + pthread_mutex_lock(&driver->lock); +} + +static void remoteDriverUnlock(struct private_data *driver) +{ + pthread_mutex_unlock(&driver->lock); +} static int call (virConnectPtr conn, struct private_data *priv, int flags, int proc_nr, @@ -829,6 +841,10 @@ remoteOpen (virConnectPtr conn, return VIR_DRV_OPEN_ERROR; } + pthread_mutex_init(&priv->lock, NULL); + remoteDriverLock(priv); + priv->localUses = 1; + if (flags & VIR_CONNECT_RO) rflags |= VIR_DRV_OPEN_REMOTE_RO; @@ -883,9 +899,11 @@ remoteOpen (virConnectPtr conn, ret = doRemoteOpen(conn, priv, auth, rflags); if (ret != VIR_DRV_OPEN_SUCCESS) { conn->privateData = NULL; + remoteDriverUnlock(priv); VIR_FREE(priv); } else { conn->privateData = priv; + remoteDriverUnlock(priv); } return ret; } @@ -1240,12 +1258,19 @@ static int static int remoteClose (virConnectPtr conn) { - int ret; - struct private_data *priv = conn->privateData; - - ret = doRemoteClose(conn, priv); - VIR_FREE (priv); - conn->privateData = NULL; + int ret = 0; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + priv->localUses--; + if (!priv->localUses) { + ret = doRemoteClose(conn, priv); + conn->privateData = NULL; + remoteDriverUnlock(priv); + VIR_FREE (priv); + } + if (priv) + remoteDriverUnlock(priv); return ret; } @@ -1257,6 +1282,8 @@ remoteSupportsFeature (virConnectPtr con remote_supports_feature_args args; remote_supports_feature_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); /* VIR_DRV_FEATURE_REMOTE* features are handled directly. */ if (feature == VIR_DRV_FEATURE_REMOTE) { @@ -1275,6 +1302,7 @@ remoteSupportsFeature (virConnectPtr con rv = ret.supported; done: + remoteDriverUnlock(priv); return rv; } @@ -1293,6 +1321,8 @@ remoteType (virConnectPtr conn) remote_get_type_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + /* Cached? */ if (priv->type) { rv = priv->type; @@ -1309,6 +1339,7 @@ remoteType (virConnectPtr conn) rv = priv->type = ret.type; done: + remoteDriverUnlock(priv); return rv; } @@ -1319,6 +1350,8 @@ remoteGetVersion (virConnectPtr conn, un remote_get_version_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_VERSION, (xdrproc_t) xdr_void, (char *) NULL, @@ -1329,6 +1362,7 @@ remoteGetVersion (virConnectPtr conn, un rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1338,6 +1372,8 @@ remoteGetHostname (virConnectPtr conn) char *rv = NULL; remote_get_hostname_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_HOSTNAME, @@ -1349,6 +1385,7 @@ remoteGetHostname (virConnectPtr conn) rv = ret.hostname; done: + remoteDriverUnlock(priv); return rv; } @@ -1359,6 +1396,8 @@ remoteGetMaxVcpus (virConnectPtr conn, c remote_get_max_vcpus_args args; remote_get_max_vcpus_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); memset (&ret, 0, sizeof ret); args.type = type == NULL ? NULL : (char **) &type; @@ -1370,6 +1409,7 @@ remoteGetMaxVcpus (virConnectPtr conn, c rv = ret.max_vcpus; done: + remoteDriverUnlock(priv); return rv; } @@ -1379,6 +1419,8 @@ remoteNodeGetInfo (virConnectPtr conn, v int rv = -1; remote_node_get_info_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_INFO, @@ -1398,6 +1440,7 @@ remoteNodeGetInfo (virConnectPtr conn, v rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1407,6 +1450,8 @@ remoteGetCapabilities (virConnectPtr con char *rv = NULL; remote_get_capabilities_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_GET_CAPABILITIES, @@ -1418,6 +1463,7 @@ remoteGetCapabilities (virConnectPtr con rv = ret.capabilities; done: + remoteDriverUnlock(priv); return rv; } @@ -1433,6 +1479,8 @@ remoteNodeGetCellsFreeMemory(virConnectP int i; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + if (maxCells > REMOTE_NODE_MAX_CELLS) { errorf (conn, VIR_ERR_RPC, _("too many NUMA cells: %d > %d"), @@ -1458,6 +1506,7 @@ remoteNodeGetCellsFreeMemory(virConnectP rv = ret.freeMems.freeMems_len; done: + remoteDriverUnlock(priv); return rv; } @@ -1467,6 +1516,8 @@ remoteNodeGetFreeMemory (virConnectPtr c unsigned long long rv = 0; /* 0 is error value this special function*/ remote_node_get_free_memory_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY, @@ -1477,6 +1528,7 @@ remoteNodeGetFreeMemory (virConnectPtr c rv = ret.freeMem; done: + remoteDriverUnlock(priv); return rv; } @@ -1489,6 +1541,8 @@ remoteListDomains (virConnectPtr conn, i remote_list_domains_args args; remote_list_domains_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); if (maxids > REMOTE_DOMAIN_ID_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -1520,6 +1574,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -1530,6 +1585,8 @@ remoteNumOfDomains (virConnectPtr conn) remote_num_of_domains_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DOMAINS, (xdrproc_t) xdr_void, (char *) NULL, @@ -1539,6 +1596,7 @@ remoteNumOfDomains (virConnectPtr conn) rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -1552,6 +1610,8 @@ remoteDomainCreateXML (virConnectPtr con remote_domain_create_xml_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + args.xml_desc = (char *) xmlDesc; args.flags = flags; @@ -1565,6 +1625,7 @@ remoteDomainCreateXML (virConnectPtr con xdr_free ((xdrproc_t) &xdr_remote_domain_create_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return dom; } @@ -1576,6 +1637,8 @@ remoteDomainLookupByID (virConnectPtr co remote_domain_lookup_by_id_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + args.id = id; memset (&ret, 0, sizeof ret); @@ -1588,6 +1651,7 @@ remoteDomainLookupByID (virConnectPtr co xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_id_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return dom; } @@ -1599,6 +1663,8 @@ remoteDomainLookupByUUID (virConnectPtr remote_domain_lookup_by_uuid_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); memset (&ret, 0, sizeof ret); @@ -1611,6 +1677,7 @@ remoteDomainLookupByUUID (virConnectPtr xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return dom; } @@ -1622,6 +1689,8 @@ remoteDomainLookupByName (virConnectPtr remote_domain_lookup_by_name_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + args.name = (char *) name; memset (&ret, 0, sizeof ret); @@ -1634,6 +1703,7 @@ remoteDomainLookupByName (virConnectPtr xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_name_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return dom; } @@ -1643,6 +1713,8 @@ remoteDomainSuspend (virDomainPtr domain int rv = -1; remote_domain_suspend_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -1654,6 +1726,7 @@ remoteDomainSuspend (virDomainPtr domain rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1663,6 +1736,8 @@ remoteDomainResume (virDomainPtr domain) int rv = -1; remote_domain_resume_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -1674,6 +1749,7 @@ remoteDomainResume (virDomainPtr domain) rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1683,6 +1759,8 @@ remoteDomainShutdown (virDomainPtr domai int rv = -1; remote_domain_shutdown_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -1694,6 +1772,7 @@ remoteDomainShutdown (virDomainPtr domai rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1703,6 +1782,8 @@ remoteDomainReboot (virDomainPtr domain, int rv = -1; remote_domain_reboot_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.flags = flags; @@ -1715,6 +1796,7 @@ remoteDomainReboot (virDomainPtr domain, rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1724,6 +1806,8 @@ remoteDomainDestroy (virDomainPtr domain int rv = -1; remote_domain_destroy_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -1735,6 +1819,7 @@ remoteDomainDestroy (virDomainPtr domain rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1745,6 +1830,8 @@ remoteDomainGetOSType (virDomainPtr doma remote_domain_get_os_type_args args; remote_domain_get_os_type_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -1758,6 +1845,7 @@ remoteDomainGetOSType (virDomainPtr doma rv = ret.type; done: + remoteDriverUnlock(priv); return rv; } @@ -1769,6 +1857,8 @@ remoteDomainGetMaxMemory (virDomainPtr d remote_domain_get_max_memory_ret ret; struct private_data *priv = domain->conn->privateData; + remoteDriverLock(priv); + make_nonnull_domain (&args.dom, domain); memset (&ret, 0, sizeof ret); @@ -1780,6 +1870,7 @@ remoteDomainGetMaxMemory (virDomainPtr d rv = ret.memory; done: + remoteDriverUnlock(priv); return rv; } @@ -1789,6 +1880,8 @@ remoteDomainSetMaxMemory (virDomainPtr d int rv = -1; remote_domain_set_max_memory_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.memory = memory; @@ -1801,6 +1894,7 @@ remoteDomainSetMaxMemory (virDomainPtr d rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1810,6 +1904,8 @@ remoteDomainSetMemory (virDomainPtr doma int rv = -1; remote_domain_set_memory_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.memory = memory; @@ -1822,6 +1918,7 @@ remoteDomainSetMemory (virDomainPtr doma rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1832,6 +1929,8 @@ remoteDomainGetInfo (virDomainPtr domain remote_domain_get_info_args args; remote_domain_get_info_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -1850,6 +1949,7 @@ remoteDomainGetInfo (virDomainPtr domain rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1859,6 +1959,8 @@ remoteDomainSave (virDomainPtr domain, c int rv = -1; remote_domain_save_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.to = (char *) to; @@ -1871,6 +1973,7 @@ remoteDomainSave (virDomainPtr domain, c rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1880,6 +1983,8 @@ remoteDomainRestore (virConnectPtr conn, int rv = -1; remote_domain_restore_args args; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); args.from = (char *) from; @@ -1891,6 +1996,7 @@ remoteDomainRestore (virConnectPtr conn, rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1900,6 +2006,8 @@ remoteDomainCoreDump (virDomainPtr domai int rv = -1; remote_domain_core_dump_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.to = (char *) to; @@ -1913,6 +2021,7 @@ remoteDomainCoreDump (virDomainPtr domai rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1922,6 +2031,8 @@ remoteDomainSetVcpus (virDomainPtr domai int rv = -1; remote_domain_set_vcpus_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.nvcpus = nvcpus; @@ -1934,6 +2045,7 @@ remoteDomainSetVcpus (virDomainPtr domai rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1947,6 +2059,8 @@ remoteDomainPinVcpu (virDomainPtr domain remote_domain_pin_vcpu_args args; struct private_data *priv = domain->conn->privateData; + remoteDriverLock(priv); + if (maplen > REMOTE_CPUMAP_MAX) { errorf (domain->conn, VIR_ERR_RPC, _("map length greater than maximum: %d > %d"), @@ -1967,6 +2081,7 @@ remoteDomainPinVcpu (virDomainPtr domain rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -1983,6 +2098,8 @@ remoteDomainGetVcpus (virDomainPtr domai remote_domain_get_vcpus_ret ret; struct private_data *priv = domain->conn->privateData; + remoteDriverLock(priv); + if (maxinfo > REMOTE_VCPUINFO_MAX) { errorf (domain->conn, VIR_ERR_RPC, _("vCPU count exceeds maximum: %d > %d"), @@ -2038,6 +2155,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -2048,6 +2166,8 @@ remoteDomainGetMaxVcpus (virDomainPtr do remote_domain_get_max_vcpus_args args; remote_domain_get_max_vcpus_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -2060,6 +2180,7 @@ remoteDomainGetMaxVcpus (virDomainPtr do rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -2070,6 +2191,8 @@ remoteDomainDumpXML (virDomainPtr domain remote_domain_dump_xml_args args; remote_domain_dump_xml_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.flags = flags; @@ -2084,6 +2207,7 @@ remoteDomainDumpXML (virDomainPtr domain rv = ret.xml; done: + remoteDriverUnlock(priv); return rv; } @@ -2099,6 +2223,8 @@ remoteDomainMigratePrepare (virConnectPt remote_domain_migrate_prepare_ret ret; struct private_data *priv = dconn->privateData; + remoteDriverLock(priv); + args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in; args.flags = flags; args.dname = dname == NULL ? NULL : (char **) &dname; @@ -2120,6 +2246,7 @@ remoteDomainMigratePrepare (virConnectPt rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2136,6 +2263,8 @@ remoteDomainMigratePerform (virDomainPtr remote_domain_migrate_perform_args args; struct private_data *priv = domain->conn->privateData; + remoteDriverLock(priv); + make_nonnull_domain (&args.dom, domain); args.cookie.cookie_len = cookielen; args.cookie.cookie_val = (char *) cookie; @@ -2152,6 +2281,7 @@ remoteDomainMigratePerform (virDomainPtr rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2168,6 +2298,8 @@ remoteDomainMigrateFinish (virConnectPtr remote_domain_migrate_finish_ret ret; struct private_data *priv = dconn->privateData; + remoteDriverLock(priv); + args.dname = (char *) dname; args.cookie.cookie_len = cookielen; args.cookie.cookie_val = (char *) cookie; @@ -2184,6 +2316,7 @@ remoteDomainMigrateFinish (virConnectPtr xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return ddom; } @@ -2200,6 +2333,8 @@ remoteDomainMigratePrepare2 (virConnectP remote_domain_migrate_prepare2_ret ret; struct private_data *priv = dconn->privateData; + remoteDriverLock(priv); + args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in; args.flags = flags; args.dname = dname == NULL ? NULL : (char **) &dname; @@ -2222,6 +2357,7 @@ remoteDomainMigratePrepare2 (virConnectP rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2239,6 +2375,8 @@ remoteDomainMigrateFinish2 (virConnectPt remote_domain_migrate_finish2_ret ret; struct private_data *priv = dconn->privateData; + remoteDriverLock(priv); + args.dname = (char *) dname; args.cookie.cookie_len = cookielen; args.cookie.cookie_val = (char *) cookie; @@ -2256,6 +2394,7 @@ remoteDomainMigrateFinish2 (virConnectPt xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish2_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return ddom; } @@ -2267,6 +2406,8 @@ remoteListDefinedDomains (virConnectPtr remote_list_defined_domains_args args; remote_list_defined_domains_ret ret; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); if (maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -2303,6 +2444,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -2313,6 +2455,8 @@ remoteNumOfDefinedDomains (virConnectPtr remote_num_of_defined_domains_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_DOMAINS, (xdrproc_t) xdr_void, (char *) NULL, @@ -2322,6 +2466,7 @@ remoteNumOfDefinedDomains (virConnectPtr rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -2331,6 +2476,8 @@ remoteDomainCreate (virDomainPtr domain) int rv = -1; remote_domain_create_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -2342,6 +2489,7 @@ remoteDomainCreate (virDomainPtr domain) rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2353,6 +2501,8 @@ remoteDomainDefineXML (virConnectPtr con remote_domain_define_xml_ret ret; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + args.xml = (char *) xml; memset (&ret, 0, sizeof ret); @@ -2365,6 +2515,7 @@ remoteDomainDefineXML (virConnectPtr con xdr_free ((xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return dom; } @@ -2374,6 +2525,8 @@ remoteDomainUndefine (virDomainPtr domai int rv = -1; remote_domain_undefine_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -2385,6 +2538,7 @@ remoteDomainUndefine (virDomainPtr domai rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2394,6 +2548,8 @@ remoteDomainAttachDevice (virDomainPtr d int rv = -1; remote_domain_attach_device_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.xml = (char *) xml; @@ -2406,6 +2562,7 @@ remoteDomainAttachDevice (virDomainPtr d rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2415,6 +2572,8 @@ remoteDomainDetachDevice (virDomainPtr d int rv = -1; remote_domain_detach_device_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.xml = (char *) xml; @@ -2427,6 +2586,7 @@ remoteDomainDetachDevice (virDomainPtr d rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2437,6 +2597,8 @@ remoteDomainGetAutostart (virDomainPtr d remote_domain_get_autostart_args args; remote_domain_get_autostart_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -2450,6 +2612,7 @@ remoteDomainGetAutostart (virDomainPtr d rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2459,6 +2622,8 @@ remoteDomainSetAutostart (virDomainPtr d int rv = -1; remote_domain_set_autostart_args args; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.autostart = autostart; @@ -2471,6 +2636,7 @@ remoteDomainSetAutostart (virDomainPtr d rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2481,6 +2647,8 @@ remoteDomainGetSchedulerType (virDomainP remote_domain_get_scheduler_type_args args; remote_domain_get_scheduler_type_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -2496,6 +2664,7 @@ remoteDomainGetSchedulerType (virDomainP rv = ret.type; done: + remoteDriverUnlock(priv); return rv; } @@ -2508,6 +2677,8 @@ remoteDomainGetSchedulerParameters (virD remote_domain_get_scheduler_parameters_ret ret; int i = -1; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.nparams = *nparams; @@ -2565,6 +2736,7 @@ cleanup: } done: + remoteDriverUnlock(priv); return rv; } @@ -2576,6 +2748,8 @@ remoteDomainSetSchedulerParameters (virD remote_domain_set_scheduler_parameters_args args; int i, do_error; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); @@ -2627,6 +2801,7 @@ remoteDomainSetSchedulerParameters (virD rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2638,6 +2813,8 @@ remoteDomainBlockStats (virDomainPtr dom remote_domain_block_stats_args args; remote_domain_block_stats_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.path = (char *) path; @@ -2658,6 +2835,7 @@ remoteDomainBlockStats (virDomainPtr dom rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2669,6 +2847,8 @@ remoteDomainInterfaceStats (virDomainPtr remote_domain_interface_stats_args args; remote_domain_interface_stats_ret ret; struct private_data *priv = domain->conn->privateData; + + remoteDriverLock(priv); make_nonnull_domain (&args.dom, domain); args.path = (char *) path; @@ -2693,6 +2873,7 @@ remoteDomainInterfaceStats (virDomainPtr rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -2709,6 +2890,8 @@ remoteDomainBlockPeek (virDomainPtr doma remote_domain_block_peek_ret ret; struct private_data *priv = domain->conn->privateData; + remoteDriverLock(priv); + if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) { errorf (domain->conn, VIR_ERR_RPC, _("block peek request too large for remote protocol, %zi > %d"), @@ -2743,6 +2926,7 @@ cleanup: free (ret.buffer.buffer_val); done: + remoteDriverUnlock(priv); return rv; } @@ -2758,6 +2942,8 @@ remoteDomainMemoryPeek (virDomainPtr dom remote_domain_memory_peek_ret ret; struct private_data *priv = domain->conn->privateData; + remoteDriverLock(priv); + if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) { errorf (domain->conn, VIR_ERR_RPC, _("memory peek request too large for remote protocol, %zi > %d"), @@ -2791,6 +2977,7 @@ cleanup: free (ret.buffer.buffer_val); done: + remoteDriverUnlock(priv); return rv; } @@ -2807,11 +2994,17 @@ remoteNetworkOpen (virConnectPtr conn, if (conn && conn->driver && STREQ (conn->driver->name, "remote")) { - /* If we're here, the remote driver is already + struct private_data *priv; + + /* If we're here, the remote driver is already * in use due to a) a QEMU uri, or b) a remote * URI. So we can re-use existing connection */ - conn->networkPrivateData = conn->privateData; + priv = conn->privateData; + remoteDriverLock(priv); + priv->localUses++; + conn->networkPrivateData = priv; + remoteDriverUnlock(priv); return VIR_DRV_OPEN_SUCCESS; } else { /* Using a non-remote driver, so we need to open a @@ -2825,6 +3018,7 @@ remoteNetworkOpen (virConnectPtr conn, error (conn, VIR_ERR_NO_MEMORY, _("struct private_data")); return VIR_DRV_OPEN_ERROR; } + pthread_mutex_init(&priv->lock, NULL); if (flags & VIR_CONNECT_RO) rflags |= VIR_DRV_OPEN_REMOTE_RO; rflags |= VIR_DRV_OPEN_REMOTE_UNIX; @@ -2848,14 +3042,16 @@ remoteNetworkClose (virConnectPtr conn) int rv = 0; struct private_data *priv = conn->networkPrivateData; - if (priv->localUses) { - priv->localUses--; - if (!priv->localUses) { - rv = doRemoteClose(conn, priv); - VIR_FREE(priv); - conn->networkPrivateData = NULL; - } - } + remoteDriverLock(priv); + priv->localUses--; + if (!priv->localUses) { + rv = doRemoteClose(conn, priv); + conn->networkPrivateData = NULL; + remoteDriverUnlock(priv); + VIR_FREE(priv); + } + if (priv) + remoteDriverUnlock(priv); return rv; } @@ -2866,6 +3062,8 @@ remoteNumOfNetworks (virConnectPtr conn) remote_num_of_networks_ret ret; struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS, (xdrproc_t) xdr_void, (char *) NULL, @@ -2875,6 +3073,7 @@ remoteNumOfNetworks (virConnectPtr conn) rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -2886,6 +3085,8 @@ remoteListNetworks (virConnectPtr conn, remote_list_networks_args args; remote_list_networks_ret ret; struct private_data *priv = conn->networkPrivateData; + + remoteDriverLock(priv); if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -2922,6 +3123,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -2932,6 +3134,8 @@ remoteNumOfDefinedNetworks (virConnectPt remote_num_of_defined_networks_ret ret; struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS, (xdrproc_t) xdr_void, (char *) NULL, @@ -2941,6 +3145,7 @@ remoteNumOfDefinedNetworks (virConnectPt rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -2953,6 +3158,8 @@ remoteListDefinedNetworks (virConnectPtr remote_list_defined_networks_args args; remote_list_defined_networks_ret ret; struct private_data *priv = conn->networkPrivateData; + + remoteDriverLock(priv); if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) { errorf (conn, VIR_ERR_RPC, @@ -2989,6 +3196,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -3001,6 +3209,8 @@ remoteNetworkLookupByUUID (virConnectPtr remote_network_lookup_by_uuid_ret ret; struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); memset (&ret, 0, sizeof ret); @@ -3013,6 +3223,7 @@ remoteNetworkLookupByUUID (virConnectPtr xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_uuid_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return net; } @@ -3025,6 +3236,8 @@ remoteNetworkLookupByName (virConnectPtr remote_network_lookup_by_name_ret ret; struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + args.name = (char *) name; memset (&ret, 0, sizeof ret); @@ -3037,6 +3250,7 @@ remoteNetworkLookupByName (virConnectPtr xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_name_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return net; } @@ -3048,6 +3262,8 @@ remoteNetworkCreateXML (virConnectPtr co remote_network_create_xml_ret ret; struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + args.xml = (char *) xmlDesc; memset (&ret, 0, sizeof ret); @@ -3060,6 +3276,7 @@ remoteNetworkCreateXML (virConnectPtr co xdr_free ((xdrproc_t) &xdr_remote_network_create_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return net; } @@ -3071,6 +3288,8 @@ remoteNetworkDefineXML (virConnectPtr co remote_network_define_xml_ret ret; struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + args.xml = (char *) xml; memset (&ret, 0, sizeof ret); @@ -3083,6 +3302,7 @@ remoteNetworkDefineXML (virConnectPtr co xdr_free ((xdrproc_t) &xdr_remote_network_define_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return net; } @@ -3092,6 +3312,8 @@ remoteNetworkUndefine (virNetworkPtr net int rv = -1; remote_network_undefine_args args; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); @@ -3103,6 +3325,7 @@ remoteNetworkUndefine (virNetworkPtr net rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3112,6 +3335,8 @@ remoteNetworkCreate (virNetworkPtr netwo int rv = -1; remote_network_create_args args; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); @@ -3123,6 +3348,7 @@ remoteNetworkCreate (virNetworkPtr netwo rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3132,6 +3358,8 @@ remoteNetworkDestroy (virNetworkPtr netw int rv = -1; remote_network_destroy_args args; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); @@ -3143,6 +3371,7 @@ remoteNetworkDestroy (virNetworkPtr netw rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3153,6 +3382,8 @@ remoteNetworkDumpXML (virNetworkPtr netw remote_network_dump_xml_args args; remote_network_dump_xml_ret ret; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); args.flags = flags; @@ -3167,6 +3398,7 @@ remoteNetworkDumpXML (virNetworkPtr netw rv = ret.xml; done: + remoteDriverUnlock(priv); return rv; } @@ -3177,6 +3409,8 @@ remoteNetworkGetBridgeName (virNetworkPt remote_network_get_bridge_name_args args; remote_network_get_bridge_name_ret ret; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); @@ -3190,6 +3424,7 @@ remoteNetworkGetBridgeName (virNetworkPt rv = ret.name; done: + remoteDriverUnlock(priv); return rv; } @@ -3200,6 +3435,8 @@ remoteNetworkGetAutostart (virNetworkPtr remote_network_get_autostart_args args; remote_network_get_autostart_ret ret; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); @@ -3214,6 +3451,7 @@ remoteNetworkGetAutostart (virNetworkPtr rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3223,6 +3461,8 @@ remoteNetworkSetAutostart (virNetworkPtr int rv = -1; remote_network_set_autostart_args args; struct private_data *priv = network->conn->networkPrivateData; + + remoteDriverLock(priv); make_nonnull_network (&args.net, network); args.autostart = autostart; @@ -3235,6 +3475,7 @@ remoteNetworkSetAutostart (virNetworkPtr rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3254,16 +3495,23 @@ remoteStorageOpen (virConnectPtr conn, if (conn && conn->driver && STREQ (conn->driver->name, "remote")) { + struct private_data *priv = conn->privateData; /* If we're here, the remote driver is already * in use due to a) a QEMU uri, or b) a remote * URI. So we can re-use existing connection */ - conn->storagePrivateData = conn->privateData; + remoteDriverLock(priv); + priv->localUses++; + conn->storagePrivateData = priv; + remoteDriverUnlock(priv); return VIR_DRV_OPEN_SUCCESS; } else if (conn->networkDriver && STREQ (conn->networkDriver->name, "remote")) { - conn->storagePrivateData = conn->networkPrivateData; - ((struct private_data *)conn->storagePrivateData)->localUses++; + struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + conn->storagePrivateData = priv; + priv->localUses++; + remoteDriverUnlock(priv); return VIR_DRV_OPEN_SUCCESS; } else { /* Using a non-remote driver, so we need to open a @@ -3277,6 +3525,7 @@ remoteStorageOpen (virConnectPtr conn, error (NULL, VIR_ERR_NO_MEMORY, _("struct private_data")); return VIR_DRV_OPEN_ERROR; } + pthread_mutex_init(&priv->lock, NULL); if (flags & VIR_CONNECT_RO) rflags |= VIR_DRV_OPEN_REMOTE_RO; rflags |= VIR_DRV_OPEN_REMOTE_UNIX; @@ -3300,14 +3549,16 @@ remoteStorageClose (virConnectPtr conn) int ret = 0; struct private_data *priv = conn->storagePrivateData; - if (priv->localUses) { - priv->localUses--; - if (!priv->localUses) { - ret = doRemoteClose(conn, priv); - VIR_FREE(priv); - conn->storagePrivateData = NULL; - } - } + remoteDriverLock(priv); + priv->localUses--; + if (!priv->localUses) { + ret = doRemoteClose(conn, priv); + conn->storagePrivateData = NULL; + remoteDriverUnlock(priv); + VIR_FREE(priv); + } + if (priv) + remoteDriverUnlock(priv); return ret; } @@ -3319,6 +3570,8 @@ remoteNumOfStoragePools (virConnectPtr c remote_num_of_storage_pools_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_STORAGE_POOLS, (xdrproc_t) xdr_void, (char *) NULL, @@ -3328,6 +3581,7 @@ remoteNumOfStoragePools (virConnectPtr c rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -3339,6 +3593,8 @@ remoteListStoragePools (virConnectPtr co remote_list_storage_pools_args args; remote_list_storage_pools_ret ret; struct private_data *priv = conn->storagePrivateData; + + remoteDriverLock(priv); if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many storage pools requested")); @@ -3371,6 +3627,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -3381,6 +3638,8 @@ remoteNumOfDefinedStoragePools (virConne remote_num_of_defined_storage_pools_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + memset (&ret, 0, sizeof ret); if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS, (xdrproc_t) xdr_void, (char *) NULL, @@ -3390,6 +3649,7 @@ remoteNumOfDefinedStoragePools (virConne rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -3402,6 +3662,8 @@ remoteListDefinedStoragePools (virConnec remote_list_defined_storage_pools_args args; remote_list_defined_storage_pools_ret ret; struct private_data *priv = conn->storagePrivateData; + + remoteDriverLock(priv); if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many storage pools requested")); @@ -3434,6 +3696,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -3448,6 +3711,8 @@ remoteFindStoragePoolSources (virConnect remote_find_storage_pool_sources_ret ret; struct private_data *priv = conn->storagePrivateData; const char *emptyString = ""; + + remoteDriverLock(priv); args.type = (char*)type; /* @@ -3476,6 +3741,7 @@ remoteFindStoragePoolSources (virConnect xdr_free ((xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -3488,6 +3754,8 @@ remoteStoragePoolLookupByUUID (virConnec remote_storage_pool_lookup_by_uuid_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + memcpy (args.uuid, uuid, VIR_UUID_BUFLEN); memset (&ret, 0, sizeof ret); @@ -3500,6 +3768,7 @@ remoteStoragePoolLookupByUUID (virConnec xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return pool; } @@ -3512,6 +3781,8 @@ remoteStoragePoolLookupByName (virConnec remote_storage_pool_lookup_by_name_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + args.name = (char *) name; memset (&ret, 0, sizeof ret); @@ -3524,6 +3795,7 @@ remoteStoragePoolLookupByName (virConnec xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return pool; } @@ -3535,6 +3807,8 @@ remoteStoragePoolLookupByVolume (virStor remote_storage_pool_lookup_by_volume_ret ret; struct private_data *priv = vol->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_vol (&args.vol, vol); memset (&ret, 0, sizeof ret); @@ -3547,6 +3821,7 @@ remoteStoragePoolLookupByVolume (virStor xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return pool; } @@ -3559,6 +3834,8 @@ remoteStoragePoolCreateXML (virConnectPt remote_storage_pool_create_xml_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + args.xml = (char *) xmlDesc; args.flags = flags; @@ -3572,6 +3849,7 @@ remoteStoragePoolCreateXML (virConnectPt xdr_free ((xdrproc_t) &xdr_remote_storage_pool_create_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return pool; } @@ -3583,6 +3861,8 @@ remoteStoragePoolDefineXML (virConnectPt remote_storage_pool_define_xml_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + args.xml = (char *) xml; args.flags = flags; @@ -3596,6 +3876,7 @@ remoteStoragePoolDefineXML (virConnectPt xdr_free ((xdrproc_t) &xdr_remote_storage_pool_define_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return pool; } @@ -3605,6 +3886,8 @@ remoteStoragePoolUndefine (virStoragePoo int rv = -1; remote_storage_pool_undefine_args args; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); @@ -3616,6 +3899,7 @@ remoteStoragePoolUndefine (virStoragePoo rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3625,6 +3909,8 @@ remoteStoragePoolCreate (virStoragePoolP int rv = -1; remote_storage_pool_create_args args; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3637,6 +3923,7 @@ remoteStoragePoolCreate (virStoragePoolP rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3648,6 +3935,8 @@ remoteStoragePoolBuild (virStoragePoolPt remote_storage_pool_build_args args; struct private_data *priv = pool->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3659,6 +3948,7 @@ remoteStoragePoolBuild (virStoragePoolPt rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3668,6 +3958,8 @@ remoteStoragePoolDestroy (virStoragePool int rv = -1; remote_storage_pool_destroy_args args; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); @@ -3679,6 +3971,7 @@ remoteStoragePoolDestroy (virStoragePool rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3690,6 +3983,8 @@ remoteStoragePoolDelete (virStoragePoolP remote_storage_pool_delete_args args; struct private_data *priv = pool->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3701,6 +3996,7 @@ remoteStoragePoolDelete (virStoragePoolP rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3712,6 +4008,8 @@ remoteStoragePoolRefresh (virStoragePool remote_storage_pool_refresh_args args; struct private_data *priv = pool->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3723,6 +4021,7 @@ remoteStoragePoolRefresh (virStoragePool rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3733,6 +4032,8 @@ remoteStoragePoolGetInfo (virStoragePool remote_storage_pool_get_info_args args; remote_storage_pool_get_info_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); @@ -3750,6 +4051,7 @@ remoteStoragePoolGetInfo (virStoragePool rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3761,6 +4063,8 @@ remoteStoragePoolDumpXML (virStoragePool remote_storage_pool_dump_xml_args args; remote_storage_pool_dump_xml_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); args.flags = flags; @@ -3775,6 +4079,7 @@ remoteStoragePoolDumpXML (virStoragePool rv = ret.xml; done: + remoteDriverUnlock(priv); return rv; } @@ -3785,6 +4090,8 @@ remoteStoragePoolGetAutostart (virStorag remote_storage_pool_get_autostart_args args; remote_storage_pool_get_autostart_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); @@ -3799,6 +4106,7 @@ remoteStoragePoolGetAutostart (virStorag rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3808,6 +4116,8 @@ remoteStoragePoolSetAutostart (virStorag int rv = -1; remote_storage_pool_set_autostart_args args; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool (&args.pool, pool); args.autostart = autostart; @@ -3820,6 +4130,7 @@ remoteStoragePoolSetAutostart (virStorag rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -3831,6 +4142,8 @@ remoteStoragePoolNumOfVolumes (virStorag remote_storage_pool_num_of_volumes_args args; remote_storage_pool_num_of_volumes_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); make_nonnull_storage_pool(&args.pool, pool); @@ -3843,6 +4156,7 @@ remoteStoragePoolNumOfVolumes (virStorag rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -3854,6 +4168,8 @@ remoteStoragePoolListVolumes (virStorage remote_storage_pool_list_volumes_args args; remote_storage_pool_list_volumes_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + + remoteDriverLock(priv); if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) { error (pool->conn, VIR_ERR_RPC, _("too many storage volumes requested")); @@ -3887,6 +4203,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -3901,6 +4218,8 @@ remoteStorageVolLookupByName (virStorage remote_storage_vol_lookup_by_name_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_pool(&args.pool, pool); args.name = (char *) name; @@ -3914,6 +4233,7 @@ remoteStorageVolLookupByName (virStorage xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return vol; } @@ -3926,6 +4246,8 @@ remoteStorageVolLookupByKey (virConnectP remote_storage_vol_lookup_by_key_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + args.key = (char *) key; memset (&ret, 0, sizeof ret); @@ -3938,6 +4260,7 @@ remoteStorageVolLookupByKey (virConnectP xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return vol; } @@ -3950,6 +4273,8 @@ remoteStorageVolLookupByPath (virConnect remote_storage_vol_lookup_by_path_ret ret; struct private_data *priv = conn->storagePrivateData; + remoteDriverLock(priv); + args.path = (char *) path; memset (&ret, 0, sizeof ret); @@ -3962,6 +4287,7 @@ remoteStorageVolLookupByPath (virConnect xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return vol; } @@ -3974,6 +4300,8 @@ remoteStorageVolCreateXML (virStoragePoo remote_storage_vol_create_xml_ret ret; struct private_data *priv = pool->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_pool (&args.pool, pool); args.xml = (char *) xmlDesc; args.flags = flags; @@ -3988,6 +4316,7 @@ remoteStorageVolCreateXML (virStoragePoo xdr_free ((xdrproc_t) &xdr_remote_storage_vol_create_xml_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return vol; } @@ -3999,6 +4328,8 @@ remoteStorageVolDelete (virStorageVolPtr remote_storage_vol_delete_args args; struct private_data *priv = vol->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_vol (&args.vol, vol); args.flags = flags; @@ -4010,6 +4341,7 @@ remoteStorageVolDelete (virStorageVolPtr rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -4021,6 +4353,8 @@ remoteStorageVolGetInfo (virStorageVolPt remote_storage_vol_get_info_ret ret; struct private_data *priv = vol->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_vol (&args.vol, vol); memset (&ret, 0, sizeof ret); @@ -4036,6 +4370,7 @@ remoteStorageVolGetInfo (virStorageVolPt rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -4048,6 +4383,8 @@ remoteStorageVolDumpXML (virStorageVolPt remote_storage_vol_dump_xml_ret ret; struct private_data *priv = vol->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_vol (&args.vol, vol); args.flags = flags; @@ -4061,6 +4398,7 @@ remoteStorageVolDumpXML (virStorageVolPt rv = ret.xml; done: + remoteDriverUnlock(priv); return rv; } @@ -4072,6 +4410,8 @@ remoteStorageVolGetPath (virStorageVolPt remote_storage_vol_get_path_ret ret; struct private_data *priv = vol->conn->storagePrivateData; + remoteDriverLock(priv); + make_nonnull_storage_vol (&args.vol, vol); memset (&ret, 0, sizeof ret); @@ -4084,6 +4424,7 @@ remoteStorageVolGetPath (virStorageVolPt rv = ret.name; done: + remoteDriverUnlock(priv); return rv; } @@ -4095,19 +4436,58 @@ remoteDevMonOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { + if (inside_daemon) + return VIR_DRV_OPEN_DECLINED; + if (conn && conn->driver && STREQ (conn->driver->name, "remote")) { + struct private_data *priv = conn->privateData; /* If we're here, the remote driver is already * in use due to a) a QEMU uri, or b) a remote * URI. So we can re-use existing connection */ - conn->devMonPrivateData = conn->privateData; + remoteDriverLock(priv); + priv->localUses++; + conn->devMonPrivateData = priv; + remoteDriverUnlock(priv); return VIR_DRV_OPEN_SUCCESS; - } - - /* Decline open. Will fallback to appropriate local node driver. */ - return VIR_DRV_OPEN_DECLINED; + } else if (conn->networkDriver && + STREQ (conn->networkDriver->name, "remote")) { + struct private_data *priv = conn->networkPrivateData; + remoteDriverLock(priv); + conn->devMonPrivateData = priv; + priv->localUses++; + remoteDriverUnlock(priv); + return VIR_DRV_OPEN_SUCCESS; + } else { + /* Using a non-remote driver, so we need to open a + * new connection for network APIs, forcing it to + * use the UNIX transport. This handles Xen driver + * which doesn't have its own impl of the network APIs. + */ + struct private_data *priv; + int ret, rflags = 0; + if (VIR_ALLOC(priv) < 0) { + error (NULL, VIR_ERR_NO_MEMORY, _("struct private_data")); + return VIR_DRV_OPEN_ERROR; + } + pthread_mutex_init(&priv->lock, NULL); + if (flags & VIR_CONNECT_RO) + rflags |= VIR_DRV_OPEN_REMOTE_RO; + rflags |= VIR_DRV_OPEN_REMOTE_UNIX; + + priv->sock = -1; + ret = doRemoteOpen(conn, priv, auth, rflags); + if (ret != VIR_DRV_OPEN_SUCCESS) { + conn->devMonPrivateData = NULL; + VIR_FREE(priv); + } else { + priv->localUses = 1; + conn->devMonPrivateData = priv; + } + return ret; + } } static int remoteDevMonClose(virConnectPtr conn) @@ -4115,14 +4495,16 @@ static int remoteDevMonClose(virConnectP int ret = 0; struct private_data *priv = conn->devMonPrivateData; - if (priv->localUses) { - priv->localUses--; - if (!priv->localUses) { - ret = doRemoteClose(conn, priv); - VIR_FREE(priv); - conn->devMonPrivateData = NULL; - } - } + remoteDriverLock(priv); + priv->localUses--; + if (!priv->localUses) { + ret = doRemoteClose(conn, priv); + conn->devMonPrivateData = NULL; + remoteDriverUnlock(priv); + VIR_FREE(priv); + } + if (priv) + remoteDriverUnlock(priv); return ret; } @@ -4135,6 +4517,8 @@ static int remoteNodeNumOfDevices(virCon remote_node_num_of_devices_ret ret; struct private_data *priv = conn->devMonPrivateData; + remoteDriverLock(priv); + args.cap = cap ? (char **)&cap : NULL; args.flags = flags; @@ -4147,6 +4531,7 @@ static int remoteNodeNumOfDevices(virCon rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -4163,6 +4548,8 @@ static int remoteNodeListDevices(virConn remote_node_list_devices_ret ret; struct private_data *priv = conn->devMonPrivateData; + remoteDriverLock(priv); + if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) { error (conn, VIR_ERR_RPC, _("too many device names requested")); goto done; @@ -4196,6 +4583,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -4208,6 +4596,8 @@ static virNodeDevicePtr remoteNodeDevice virNodeDevicePtr dev = NULL; struct private_data *priv = conn->devMonPrivateData; + remoteDriverLock(priv); + args.name = (char *)name; memset (&ret, 0, sizeof ret); @@ -4221,6 +4611,7 @@ static virNodeDevicePtr remoteNodeDevice xdr_free ((xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return dev; } @@ -4232,6 +4623,8 @@ static char *remoteNodeDeviceDumpXML(vir remote_node_device_dump_xml_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; + remoteDriverLock(priv); + args.name = dev->name; args.flags = flags; @@ -4245,6 +4638,7 @@ static char *remoteNodeDeviceDumpXML(vir rv = ret.xml; done: + remoteDriverUnlock(priv); return rv; } @@ -4255,6 +4649,8 @@ static char *remoteNodeDeviceGetParent(v remote_node_device_get_parent_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; + remoteDriverLock(priv); + args.name = dev->name; memset (&ret, 0, sizeof ret); @@ -4267,6 +4663,7 @@ static char *remoteNodeDeviceGetParent(v rv = ret.parent ? *ret.parent : NULL; done: + remoteDriverUnlock(priv); return rv; } @@ -4277,6 +4674,8 @@ static int remoteNodeDeviceNumOfCaps(vir remote_node_device_num_of_caps_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; + remoteDriverLock(priv); + args.name = dev->name; memset (&ret, 0, sizeof ret); @@ -4288,6 +4687,7 @@ static int remoteNodeDeviceNumOfCaps(vir rv = ret.num; done: + remoteDriverUnlock(priv); return rv; } @@ -4301,6 +4701,8 @@ static int remoteNodeDeviceListCaps(virN remote_node_device_list_caps_ret ret; struct private_data *priv = dev->conn->devMonPrivateData; + remoteDriverLock(priv); + if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) { error (dev->conn, VIR_ERR_RPC, _("too many capability names requested")); goto done; @@ -4333,6 +4735,7 @@ cleanup: xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret); done: + remoteDriverUnlock(priv); return rv; } @@ -5058,6 +5461,8 @@ static int remoteDomainEventRegister (vi int rv = -1; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + if (priv->eventFlushTimer < 0) { error (conn, VIR_ERR_NO_SUPPORT, _("no event support")); goto done; @@ -5079,6 +5484,7 @@ static int remoteDomainEventRegister (vi rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -5087,6 +5493,8 @@ static int remoteDomainEventDeregister ( { int rv = -1; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); if (virDomainEventCallbackListRemove(conn, priv->callbackList, callback) < 0) { @@ -5105,6 +5513,7 @@ static int remoteDomainEventDeregister ( rv = 0; done: + remoteDriverUnlock(priv); return rv; } @@ -5897,6 +6306,8 @@ remoteDomainEventFired(int watch, virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; + remoteDriverLock(priv); + DEBUG("Event fired %d %d %d %X", watch, fd, event, event); if (event & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { @@ -5953,7 +6364,7 @@ remoteDomainEventFired(int watch, } done: - return; + remoteDriverUnlock(priv); } void @@ -5961,8 +6372,12 @@ remoteDomainEventQueueFlush(int timer AT { virConnectPtr conn = opaque; struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList, virDomainEventDispatchDefaultFunc, NULL); virEventUpdateTimeout(priv->eventFlushTimer, -1); -} + + remoteDriverUnlock(priv); +} -- |: 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 is a slightly incomplete attempt to add a new virConectClone operation to the public API. I includes the public API, the internal driver methods, and implementation for the test & remote drivers. Still todo is the Xen driver (needs thread-safety for Xen privte data access) and QEMU/LXC/OpenVZ/UML drivers (trivial, since they're already thread safe). The basic scheme of things is virConnectPtr conn = virConnectOpen(...some URI...) ....now I want to create a background thread... virConnectPtr copy = virConnectClone(conn); .... all done with thread.. virConnectClose(copy); virConnectClose(conn); ie, you must call virConnectClose as usual for all clones. The internal data will only be released once all copies are released. There is nothing special about the first original virConnectPtr - all clones are identical and indistinguishable. Daniel diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -396,6 +396,7 @@ virConnectPtr virConnectOpenAu virConnectPtr virConnectOpenAuth (const char *name, virConnectAuthPtr auth, int flags); +virConnectPtr virConnectClone (virConnectPtr conn); int virConnectClose (virConnectPtr conn); const char * virConnectGetType (virConnectPtr conn); int virConnectGetVersion (virConnectPtr conn, diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -396,6 +396,7 @@ virConnectPtr virConnectOpenAu virConnectPtr virConnectOpenAuth (const char *name, virConnectAuthPtr auth, int flags); +virConnectPtr virConnectClone (virConnectPtr conn); int virConnectClose (virConnectPtr conn); const char * virConnectGetType (virConnectPtr conn); int virConnectGetVersion (virConnectPtr conn, diff --git a/src/driver.h b/src/driver.h --- a/src/driver.h +++ b/src/driver.h @@ -74,6 +74,9 @@ typedef virDrvOpenStatus (*virDrvOpen) (virConnectPtr conn, virConnectAuthPtr auth, int flags); +typedef int + (*virDrvClone)(virConnectPtr conn, + virConnectPtr copied); typedef int (*virDrvClose) (virConnectPtr conn); typedef int @@ -329,6 +332,7 @@ struct _virDriver { int no; /* the number virDrvNo */ const char * name; /* the name of the driver */ virDrvOpen open; + virDrvClone clone; virDrvClose close; virDrvDrvSupportsFeature supports_feature; virDrvGetType type; @@ -448,6 +452,7 @@ struct _virNetworkDriver { struct _virNetworkDriver { const char * name; /* the name of the driver */ virDrvOpen open; + virDrvClone clone; virDrvClose close; virDrvNumOfNetworks numOfNetworks; virDrvListNetworks listNetworks; @@ -582,6 +587,7 @@ struct _virStorageDriver { struct _virStorageDriver { const char * name; /* the name of the driver */ virDrvOpen open; + virDrvClone clone; virDrvClose close; virDrvConnectNumOfStoragePools numOfPools; @@ -672,6 +678,7 @@ struct _virDeviceMonitor { struct _virDeviceMonitor { const char * name; /* the name of the driver */ virDrvOpen open; + virDrvClone clone; virDrvClose close; virDevMonNumOfDevices numOfDevices; virDevMonListDevices listDevices; diff --git a/src/libvirt.c b/src/libvirt.c --- a/src/libvirt.c +++ b/src/libvirt.c @@ -1033,6 +1033,79 @@ virConnectOpenAuth(const char *name, DEBUG("name=%s, auth=%p, flags=%d", name, auth, flags); return do_open (name, auth, flags); } + + +virConnectPtr +virConnectClone(virConnectPtr conn) +{ + virConnectPtr ret; + DEBUG("conn=%p", conn); + + ret = virGetConnect(); + if (ret == NULL) + return NULL; + + /* We are required to have clone support in + * every driver that's active for this to work + */ + if (!conn->driver->clone || + (conn->networkDriver && !conn->networkDriver->clone) || + (conn->storageDriver && !conn->storageDriver->clone) || + (conn->deviceMonitor && !conn->deviceMonitor->clone)) { + virLibConnError(NULL, VIR_ERR_NO_SUPPORT, + _("clone not supported for this driver")); + return NULL; + } + + /* + * Don't allow changing flags, because that could + * allow user to evade read-only restrictions + */ + ret->flags = conn->flags; + + ret->driver = conn->driver; + ret->networkDriver = conn->networkDriver; + ret->storageDriver = conn->storageDriver; + ret->deviceMonitor = conn->deviceMonitor; + + if (ret->driver->clone(conn, ret) < 0) + goto error; + if (ret->networkDriver && + ret->networkDriver->clone(conn, ret) < 0) + goto error; + if (ret->storageDriver && + ret->storageDriver->clone(conn, ret) < 0) + goto error; + if (ret->deviceMonitor && + ret->deviceMonitor->clone(conn, ret) < 0) + goto error; + + return ret; + +error: + if (ret->deviceMonitor && + ret->deviceMonitor->close && + ret->devMonPrivateData) + ret->deviceMonitor->close(ret); + + if (ret->storageDriver && + ret->storageDriver->close && + ret->storagePrivateData) + ret->storageDriver->close(ret); + + if (ret->networkDriver && + ret->networkDriver->close && + ret->networkPrivateData) + ret->networkDriver->close(ret); + + if (ret->privateData && + ret->driver->close) + ret->driver->close(ret); + + virUnrefConnect(ret); + return NULL; +} + /** * virConnectClose: 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 @@ -249,9 +249,12 @@ LIBVIRT_0.5.0 { } LIBVIRT_0.4.5; -/* no new entry point in 0.5.1 */ +LIBVIRT_0.5.2 { + global: + virConnectClone; +} LIBVIRT_0.5.0; + /* .... define new API here using predicted next version number .... */ - diff --git a/src/lxc_driver.c b/src/lxc_driver.c --- a/src/lxc_driver.c +++ b/src/lxc_driver.c @@ -1391,6 +1391,7 @@ static virDriver lxcDriver = { VIR_DRV_LXC, /* the number virDrvNo */ "LXC", /* the name of the driver */ lxcOpen, /* open */ + NULL, /* clone */ lxcClose, /* close */ NULL, /* supports_feature */ NULL, /* type */ diff --git a/src/network_driver.c b/src/network_driver.c --- a/src/network_driver.c +++ b/src/network_driver.c @@ -1275,6 +1275,7 @@ static virNetworkDriver networkDriver = static virNetworkDriver networkDriver = { "Network", networkOpenNetwork, /* open */ + NULL, /* clone */ networkCloseNetwork, /* close */ networkNumNetworks, /* numOfNetworks */ networkListNetworks, /* listNetworks */ diff --git a/src/openvz_driver.c b/src/openvz_driver.c --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -1247,6 +1247,7 @@ static virDriver openvzDriver = { VIR_DRV_OPENVZ, "OPENVZ", openvzOpen, /* open */ + NULL, /* clone */ openvzClose, /* close */ NULL, /* supports_feature */ openvzGetType, /* type */ diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -4149,6 +4149,7 @@ static virDriver qemuDriver = { VIR_DRV_QEMU, "QEMU", qemudOpen, /* open */ + NULL, /* clone */ qemudClose, /* close */ qemudSupportsFeature, /* supports_feature */ qemudGetType, /* type */ diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -1202,6 +1202,18 @@ verify_certificate (virConnectPtr conn A /*----------------------------------------------------------------------*/ +static int +remoteClone(virConnectPtr conn, virConnectPtr copied) +{ + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + priv->localUses++; + copied->privateData = priv; + remoteDriverUnlock(priv); + + return 0; +} static int doRemoteClose (virConnectPtr conn, struct private_data *priv) @@ -3037,6 +3049,19 @@ remoteNetworkOpen (virConnectPtr conn, } static int +remoteNetworkClone(virConnectPtr conn, virConnectPtr copied) +{ + struct private_data *priv = conn->networkPrivateData; + + remoteDriverLock(priv); + priv->localUses++; + copied->networkPrivateData = priv; + remoteDriverUnlock(priv); + + return 0; +} + +static int remoteNetworkClose (virConnectPtr conn) { int rv = 0; @@ -3542,6 +3567,20 @@ remoteStorageOpen (virConnectPtr conn, return ret; } } + +static int +remoteStorageClone(virConnectPtr conn, virConnectPtr copied) +{ + struct private_data *priv = conn->storagePrivateData; + + remoteDriverLock(priv); + priv->localUses++; + copied->storagePrivateData = priv; + remoteDriverUnlock(priv); + + return 0; +} + static int remoteStorageClose (virConnectPtr conn) @@ -4489,6 +4528,20 @@ remoteDevMonOpen(virConnectPtr conn, return ret; } } + +static int +remoteDevMonClone(virConnectPtr conn, virConnectPtr copied) +{ + struct private_data *priv = conn->devMonPrivateData; + + remoteDriverLock(priv); + priv->localUses++; + copied->devMonPrivateData = priv; + remoteDriverUnlock(priv); + + return 0; +} + static int remoteDevMonClose(virConnectPtr conn) { @@ -6065,6 +6118,7 @@ static virDriver driver = { .no = VIR_DRV_REMOTE, .name = "remote", .open = remoteOpen, + .clone = remoteClone, .close = remoteClose, .supports_feature = remoteSupportsFeature, .type = remoteType, @@ -6127,6 +6181,7 @@ static virNetworkDriver network_driver = static virNetworkDriver network_driver = { .name = "remote", .open = remoteNetworkOpen, + .clone = remoteNetworkClone, .close = remoteNetworkClose, .numOfNetworks = remoteNumOfNetworks, .listNetworks = remoteListNetworks, @@ -6148,6 +6203,7 @@ static virStorageDriver storage_driver = static virStorageDriver storage_driver = { .name = "remote", .open = remoteStorageOpen, + .clone = remoteStorageClone, .close = remoteStorageClose, .numOfPools = remoteNumOfStoragePools, .listPools = remoteListStoragePools, @@ -6185,6 +6241,7 @@ static virDeviceMonitor dev_monitor = { static virDeviceMonitor dev_monitor = { .name = "remote", .open = remoteDevMonOpen, + .clone = remoteDevMonClone, .close = remoteDevMonClose, .numOfDevices = remoteNodeNumOfDevices, .listDevices = remoteNodeListDevices, diff --git a/src/storage_driver.c b/src/storage_driver.c --- a/src/storage_driver.c +++ b/src/storage_driver.c @@ -1462,6 +1462,7 @@ static virStorageDriver storageDriver = static virStorageDriver storageDriver = { .name = "storage", .open = storageOpen, + .clone = NULL, .close = storageClose, .numOfPools = storageNumPools, .listPools = storageListPools, diff --git a/src/test.c b/src/test.c --- a/src/test.c +++ b/src/test.c @@ -59,6 +59,7 @@ typedef struct _testCell *testCellPtr; struct _testConn { PTHREAD_MUTEX_T(lock); + int refs; char path[PATH_MAX]; int nextDomID; @@ -214,6 +215,7 @@ static int testOpenDefault(virConnectPtr conn->privateData = privconn; pthread_mutex_init(&privconn->lock, NULL); testDriverLock(privconn); + privconn->refs = 1; if (gettimeofday(&tv, NULL) < 0) { testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day")); @@ -331,6 +333,7 @@ static int testOpenFromFile(virConnectPt conn->privateData = privconn; pthread_mutex_init(&privconn->lock, NULL); testDriverLock(privconn); + privconn->refs = 1; if (!(privconn->caps = testBuildCapabilities(conn))) goto error; @@ -627,18 +630,38 @@ static int testOpen(virConnectPtr conn, return (ret); } -static int testClose(virConnectPtr conn) +static int testClone(virConnectPtr conn, + virConnectPtr copied) { testConnPtr privconn = conn->privateData; testDriverLock(privconn); + privconn->refs++; + copied->privateData = conn->privateData; + testDriverUnlock(privconn); + return 0; +} + +static void testRelease(testConnPtr privconn) +{ virCapabilitiesFree(privconn->caps); virDomainObjListFree(&privconn->domains); virNetworkObjListFree(&privconn->networks); virStoragePoolObjListFree(&privconn->pools); testDriverUnlock(privconn); + VIR_FREE (privconn); +} - VIR_FREE (privconn); - conn->privateData = NULL; +static int testClose(virConnectPtr conn) +{ + testConnPtr privconn = conn->privateData; + testDriverLock(privconn); + privconn->refs--; + if (privconn->refs) { + testDriverUnlock(privconn); + } else { + testRelease(privconn); + conn->privateData = NULL; + } return 0; } @@ -1751,15 +1774,39 @@ static virDrvOpenStatus testOpenNetwork( static virDrvOpenStatus testOpenNetwork(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; if (STRNEQ(conn->driver->name, "Test")) return VIR_DRV_OPEN_DECLINED; - conn->networkPrivateData = conn->privateData; + testDriverLock(privconn); + privconn->refs++; + conn->networkPrivateData = privconn; + testDriverUnlock(privconn); + return VIR_DRV_OPEN_SUCCESS; } +static int testCloneNetwork(virConnectPtr conn, + virConnectPtr copied) +{ + testConnPtr privconn = conn->networkPrivateData; + testDriverLock(privconn); + privconn->refs++; + copied->networkPrivateData = conn->networkPrivateData; + testDriverUnlock(privconn); + return 0; +} + static int testCloseNetwork(virConnectPtr conn) { - conn->networkPrivateData = NULL; + testConnPtr privconn = conn->networkPrivateData; + testDriverLock(privconn); + privconn->refs--; + if (privconn->refs) { + testDriverUnlock(privconn); + } else { + testRelease(privconn); + conn->networkPrivateData = NULL; + } return 0; } @@ -2167,17 +2214,42 @@ static virDrvOpenStatus testStorageOpen( static virDrvOpenStatus testStorageOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; if (STRNEQ(conn->driver->name, "Test")) return VIR_DRV_OPEN_DECLINED; - conn->storagePrivateData = conn->privateData; + testDriverLock(privconn); + privconn->refs++; + conn->storagePrivateData = privconn; + testDriverUnlock(privconn); + return VIR_DRV_OPEN_SUCCESS; } -static int testStorageClose(virConnectPtr conn) { - conn->storagePrivateData = NULL; +static int testStorageClone(virConnectPtr conn, + virConnectPtr copied) +{ + testConnPtr privconn = conn->storagePrivateData; + testDriverLock(privconn); + privconn->refs++; + copied->storagePrivateData = conn->storagePrivateData; + testDriverUnlock(privconn); return 0; } + +static int testStorageClose(virConnectPtr conn) { + testConnPtr privconn = conn->storagePrivateData; + testDriverLock(privconn); + privconn->refs--; + if (privconn->refs) { + testDriverUnlock(privconn); + } else { + testRelease(privconn); + conn->storagePrivateData = NULL; + } + return 0; +} + static virStoragePoolPtr testStoragePoolLookupByUUID(virConnectPtr conn, @@ -3221,23 +3293,47 @@ static virDrvOpenStatus testDevMonOpen(v static virDrvOpenStatus testDevMonOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { + testConnPtr privconn = conn->privateData; if (STRNEQ(conn->driver->name, "Test")) return VIR_DRV_OPEN_DECLINED; - conn->devMonPrivateData = conn->privateData; + testDriverLock(privconn); + privconn->refs++; + conn->devMonPrivateData = privconn; + testDriverUnlock(privconn); + return VIR_DRV_OPEN_SUCCESS; } -static int testDevMonClose(virConnectPtr conn) { - conn->devMonPrivateData = NULL; +static int testDevMonClone(virConnectPtr conn, + virConnectPtr copied) +{ + testConnPtr privconn = conn->devMonPrivateData; + testDriverLock(privconn); + privconn->refs++; + copied->devMonPrivateData = conn->devMonPrivateData; + testDriverUnlock(privconn); return 0; } +static int testDevMonClose(virConnectPtr conn) { + testConnPtr privconn = conn->devMonPrivateData; + testDriverLock(privconn); + privconn->refs--; + if (privconn->refs) { + testDriverUnlock(privconn); + } else { + testRelease(privconn); + conn->devMonPrivateData = NULL; + } + return 0; +} static virDriver testDriver = { VIR_DRV_TEST, "Test", testOpen, /* open */ + testClone, /* clone */ testClose, /* close */ NULL, /* supports_feature */ NULL, /* type */ @@ -3301,6 +3397,7 @@ static virNetworkDriver testNetworkDrive static virNetworkDriver testNetworkDriver = { "Test", testOpenNetwork, /* open */ + testCloneNetwork, /* clone */ testCloseNetwork, /* close */ testNumNetworks, /* numOfNetworks */ testListNetworks, /* listNetworks */ @@ -3322,6 +3419,7 @@ static virStorageDriver testStorageDrive static virStorageDriver testStorageDriver = { .name = "Test", .open = testStorageOpen, + .clone = testStorageClone, .close = testStorageClose, .numOfPools = testStorageNumPools, @@ -3360,6 +3458,7 @@ static virDeviceMonitor testDevMonitor = static virDeviceMonitor testDevMonitor = { .name = "Test", .open = testDevMonOpen, + .clone = testDevMonClone, .close = testDevMonClose, }; diff --git a/src/uml_driver.c b/src/uml_driver.c --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -1812,6 +1812,7 @@ static virDriver umlDriver = { VIR_DRV_UML, "UML", umlOpen, /* open */ + NULL, /* clone */ umlClose, /* close */ NULL, /* supports_feature */ umlGetType, /* type */ diff --git a/src/xen_unified.c b/src/xen_unified.c --- a/src/xen_unified.c +++ b/src/xen_unified.c @@ -1399,6 +1399,7 @@ static virDriver xenUnifiedDriver = { .no = VIR_DRV_XEN_UNIFIED, .name = "Xen", .open = xenUnifiedOpen, + .clone = NULL, .close = xenUnifiedClose, .supports_feature = xenUnifiedSupportsFeature, .type = xenUnifiedType, -- |: 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 :|

If the event loop is being processed in a background thread, then while doing an RPC call, the event loop may get spurious wakeups due to the POLLIN condition being satisfied by the incoming RPC reply. This will cause the a-sync event handler to be unneccessarily run, and then block the entire event loop due to it waitinf on the mutex for the call() method to complete. Blocking the entire event loop is somewhat undesirable, so we turn off the FD watches while in a call() an re-enable them after. Daniel diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -753,9 +753,7 @@ doRemoteOpen (virConnectPtr conn, DEBUG0("Adding Handler for remote events"); /* Set up a callback to listen on the socket data */ if ((priv->watch = virEventAddHandle(priv->sock, - VIR_EVENT_HANDLE_READABLE | - VIR_EVENT_HANDLE_ERROR | - VIR_EVENT_HANDLE_HANGUP, + VIR_EVENT_HANDLE_READABLE, remoteDomainEventFired, conn, NULL)) < 0) { DEBUG0("virEventAddHandle failed: No addHandleImpl defined." @@ -5588,11 +5586,11 @@ static int really_read (virConnectPtr co * else Bad Things will happen in the XDR code. */ static int -call (virConnectPtr conn, struct private_data *priv, - int flags /* if we are in virConnectOpen */, - int proc_nr, - xdrproc_t args_filter, char *args, - xdrproc_t ret_filter, char *ret) +doCall (virConnectPtr conn, struct private_data *priv, + int flags /* if we are in virConnectOpen */, + int proc_nr, + xdrproc_t args_filter, char *args, + xdrproc_t ret_filter, char *ret) { char buffer[REMOTE_MESSAGE_MAX]; char buffer2[4]; @@ -5781,6 +5779,34 @@ retry_read: xdr_destroy (&xdr); return -1; } +} + + +static int +call (virConnectPtr conn, struct private_data *priv, + int flags /* if we are in virConnectOpen */, + int proc_nr, + xdrproc_t args_filter, char *args, + xdrproc_t ret_filter, char *ret) +{ + int rv; + /* + * Avoid needless wake-ups of the event loop in the + * case where this call is being made from a different + * thread than the event loop. These wake-ups would + * cause the event loop thread to be blocked on the + * mutex for the duration of the call + */ + if (priv->watch >= 0) + virEventUpdateHandle(priv->watch, 0); + + rv = doCall(conn, priv,flags, proc_nr, + args_filter, args, + ret_filter, ret); + + if (priv->watch >= 0) + virEventUpdateHandle(priv->watch, VIR_EVENT_HANDLE_READABLE); + return rv; } static int -- |: 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 is the final one for multi-threading in the remote driver. With the first 5 patches applied the remote driver is thread safe, but everything is still serialized, since the call() method which does the network I/O blocks until the reply is fully received, and holds the mutex while blocking. This is sub-optimal :-) We fundamentally only have a single network socket open, so we have to make sure only one thread is ever doing network I/O in each direction. The GNUTLS and SASL encryption state is also only safe to use from a single thread. This means we can't simply let the call() methods run in parallel. While one thread is waiting to receive it RPC reply message, there's no reason why the RPC requests from other threads can't be sent out on the wire. So called pipelining of requests. In fact, since we have a unique serial number for every request/reply there's no reason why replies need come back in the same order as they're sent. This provides optimal concurrency All the complexity starts off in the call() method. From the caller's point of view, this method takes an RPC request, sends it, waits for the reply message, and returns the data. ie it is blocking. The caller of call() is required to be holding the driver mutex. Upon entering the call() there are two possible scenarios - No thread is currently doing network I/O. - Another thread is doing network I/O In the first scenario, this thread takes immediate responsibilty for doing all network I/O until such time as its finished its own RPC call. This thread is said to be "holding the buck" In the second scenario, this thread delegates responsibility for doing I/O to the existing thread, and puts itself to sleep. Someone else is "holding the buck" While the thread holding the buck is waiting for its reply to arrive, it releases the driver mutex. This allows other threads to enter the call method and queue up their requests. Once the first thread has finished sending its initial request data, it will it start to send requests from other queued threads. It may even start to process other threads replies, and/or asynchronous events. Eventually its own reply will arrive. At this point the first thread is all done. There are again two possible scenarios for it to consider: - No other threads were sleeping waiting for it to finish - One or more threads were sleeping waiting for it to finish If no threads were waiting, it just returns, giving up the buck. If one or more threads were sleeping, then it picks the first sleeping thread and wakes it up. This is 'passing the buck'.
From the point of view of a sleeping thread, there are also two possible scenarios when it gets woken up
- It is being woken because the other thread has got its reply ready. - It is being woken because the other threadis passing it the buck In the first case, the thread being woken is done with its call and can just return from call() to its caller. In the second case, the thread being woken up is now "holding the buck' and has to take over responsibility for all network I/O, until its desired reply arrives To deal with all this 'buck passing', we need to keep various bits of state around about each thread's RPC call. This is done in the struct remote_thread_call. struct remote_thread_call { /* This indicated whether this call is being sent, being received, completed successfully, or failed with error */ int mode; /* The data being sent on the wire, the length, and progress */ /* 4 byte length, followed by RPC message headerbody */ char buffer[4 REMOTE_MESSAGE_MAX]; unsigned int bufferLength; unsigned int bufferOffset; /* The serial number & procedure number, so we can match up its reply when it arrives */ unsigned int serial; unsigned int proc_nr; /* The condition the thread sleeps on while another thread is holding the buck */ pthread_cond_t cond; /* Used to de-serialize the XDR object into the return values */ xdrproc_t ret_filter; /* Struct to hold the return values. Yes, evil XDR casts */ char *ret; /* If the 'mode' indicated an error, this stores it */ remote_error err; /* The next thread waiting to dispatch, if any */ struct remote_thread_call *next; }; As more and more threads arrie in the call() method, they're all queued up to have their requests processed in FIFO order for sake of fairness. Replies are processed in any order - whatever they arrive in, though the libvirtd daemon currently does strict FIFO ordering for replies. Since we need to release the mutex while waiting for I/O, we can no longer use blocking I/O on the socket. So its now put into non-blocking mode and then we use poll() to watch for readability / writability. We need the remote driver to work on Windows, but I'm hoping GNULIB's poll() function will work well enough for this not to be a problem Since this is a work in progress patch, there's quite a bit of debugging in it. I've also done a stupid modification to the 'virNodeGetInfo' impl for the QEMU driver to sleep for 5 seconds to demonstrate overlapping operations, and another stupid modification to virsh to spawn a thread that calls virNodeGetInfo in a loop. This just demonstrates I've got the hand-off between threads working in the RPC call() method. Obviously not to be comitted. Running virsh -c qemu:///system shows the two threads working in lock-step. In this case the background thread has started its virNodeGetInfo call and then I typed 'list' in the foreground thread DEBUG: libvirt.c: virConnectClone (conn=0x72e110) DEBUG: libvirt.c: virNodeGetInfo (conn=0x72fb40, info=0x7f5ee6025030) DEBUG: remote_internal.c: call (Doing call 6 (nil)) Welcome to lt-virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit DEBUG: remote_internal.c: call (We have the buck 6 0x7380f0 0x7380f0) ^ at this point the BG thread is waiting for its reply... virsh # list DEBUG: libvirt.c: virConnectNumOfDomains (conn=0x72e110) DEBUG: remote_internal.c: call (Doing call 51 0x7380f0) DEBUG: remote_internal.c: call (Going to sleep 51 0x7380f0 0x7910b0) ^ And thanks to us typing 'list', a new call is triggerd. We can see it putting itself to sleep since the bg thread has the buck DEBUG: remote_internal.c: processCallRecv (Do 4 0) DEBUG: remote_internal.c: processCallRecvLen (Got length, now need 188 total (184 more)) DEBUG: remote_internal.c: processCallRecv (Do 188 4) DEBUG: remote_internal.c: processCallRecv (Do 0 0) ^ Here we see the first thread has got the reply it wanted DEBUG: remote_internal.c: processCalls (Giving up the buck 6 0x7380f0 0x7910b0) ^ So its decided to give up the buck DEBUG: remote_internal.c: processCalls (Passing the buck to 51 0x7910b0) ^ And noticed another thread was waiting, so passed it the buck DEBUG: remote_internal.c: call (All done with our call 6 0x7910b0 0x7380f0) 2 1 1 8119572 DEBUG: remote_internal.c: call (Wokeup from sleep 51 0x7910b0 0x7910b0) DEBUG: remote_internal.c: call (We have the buck 51 0x7910b0 0x7910b0) ^ The second thread has now woken up and got the buck. Its requests has already been sent onto the wire by the first thread, so now it merely waits for its reply DEBUG: remote_internal.c: processCallRecv (Do 4 0) DEBUG: remote_internal.c: processCallRecvLen (Got length, now need 32 total (28 more)) DEBUG: remote_internal.c: processCallRecv (Do 32 4) DEBUG: remote_internal.c: processCallRecv (Do 0 0) ^ Which is has now got. DEBUG: remote_internal.c: processCalls (Giving up the buck 51 0x7910b0 (nil)) DEBUG: remote_internal.c: call (All done with our call 51 (nil) 0x7910b0) ^ The second thread now gives up the buck, and there's no one waiting who wants it Id Name State ---------------------------------- virsh # 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 @@ -586,6 +586,7 @@ LIBVIRT_PRIVATE_@VERSION@ { virEventAddHandle; virEventRemoveHandle; virExec; + virSetNonBlock; virFormatMacAddr; virParseMacAddr; virFileDeletePid; diff --git a/src/qemu_driver.c b/src/qemu_driver.c --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -1338,6 +1338,7 @@ static int qemudGetMaxVCPUs(virConnectPt static int qemudGetNodeInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { + sleep(5); return virNodeInfoPopulate(conn, nodeinfo); } diff --git a/src/remote_internal.c b/src/remote_internal.c --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -67,6 +67,8 @@ #include <libxml/uri.h> #include <netdb.h> + +#include <poll.h> /* AI_ADDRCONFIG is missing on some systems. */ #ifndef AI_ADDRCONFIG @@ -88,6 +90,37 @@ static int inside_daemon = 0; +struct remote_thread_call; + + +enum { + REMOTE_MODE_WAIT_TX, + REMOTE_MODE_WAIT_RX, + REMOTE_MODE_COMPLETE, + REMOTE_MODE_ERROR, +}; + +struct remote_thread_call { + int mode; + + /* 4 byte length, followed by RPC message header+body */ + char buffer[4 + REMOTE_MESSAGE_MAX]; + unsigned int bufferLength; + unsigned int bufferOffset; + + unsigned int serial; + unsigned int proc_nr; + + pthread_cond_t cond; + + xdrproc_t ret_filter; + char *ret; + + remote_error err; + + struct remote_thread_call *next; +}; + struct private_data { PTHREAD_MUTEX_T(lock); @@ -101,12 +134,24 @@ struct private_data { int localUses; /* Ref count for private data */ char *hostname; /* Original hostname */ FILE *debugLog; /* Debug remote protocol */ + #if HAVE_SASL sasl_conn_t *saslconn; /* SASL context */ + const char *saslDecoded; unsigned int saslDecodedLength; unsigned int saslDecodedOffset; -#endif + + const char *saslEncoded; + unsigned int saslEncodedLength; + unsigned int saslEncodedOffset; +#endif + + /* 4 byte length, followed by RPC message header+body */ + char buffer[4 + REMOTE_MESSAGE_MAX]; + unsigned int bufferLength; + unsigned int bufferOffset; + /* The list of domain event callbacks */ virDomainEventCallbackListPtr callbackList; /* The queue of domain events generated @@ -114,6 +159,9 @@ struct private_data { virDomainEventQueuePtr domainEvents; /* Timer for flushing domainEvents queue */ int eventFlushTimer; + + /* List of threads currently doing dispatch */ + struct remote_thread_call *waitDispatch; }; enum { @@ -160,7 +208,6 @@ static void make_nonnull_storage_pool (r static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src); static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src); void remoteDomainEventFired(int watch, int fd, int event, void *data); -static void remoteDomainProcessEvent(virConnectPtr conn, XDR *xdr); static void remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr); void remoteDomainEventQueueFlush(int timer, void *opaque); /*----------------------------------------------------------------------*/ @@ -695,6 +742,13 @@ doRemoteOpen (virConnectPtr conn, } /* switch (transport) */ + if (virSetNonBlock(priv->sock) < 0) { + errorf (conn, VIR_ERR_SYSTEM_ERROR, + _("unable to make socket non-blocking %s"), + strerror(errno)); + goto failed; + } + /* Try and authenticate with server */ if (remoteAuthenticate(conn, priv, 1, auth, authtype) == -1) @@ -767,6 +821,7 @@ doRemoteOpen (virConnectPtr conn, DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. " "continuing without events."); virEventRemoveHandle(priv->watch); + priv->watch = -1; } } /* Successful. */ @@ -842,6 +897,7 @@ remoteOpen (virConnectPtr conn, pthread_mutex_init(&priv->lock, NULL); remoteDriverLock(priv); priv->localUses = 1; + priv->watch = -1; if (flags & VIR_CONNECT_RO) rflags |= VIR_DRV_OPEN_REMOTE_RO; @@ -1226,6 +1282,7 @@ doRemoteClose (virConnectPtr conn, struc virEventRemoveTimeout(priv->eventFlushTimer); /* Remove handle for remote events */ virEventRemoveHandle(priv->watch); + priv->watch = -1; } /* Close socket. */ @@ -5570,12 +5627,616 @@ done: /*----------------------------------------------------------------------*/ -static int really_write (virConnectPtr conn, struct private_data *priv, - int in_open, char *bytes, int len); -static int really_read (virConnectPtr conn, struct private_data *priv, - int in_open, char *bytes, int len); - -/* This function performs a remote procedure call to procedure PROC_NR. + +static struct remote_thread_call * +prepareCall(virConnectPtr conn, + struct private_data *priv, + int flags, + int proc_nr, + xdrproc_t args_filter, char *args, + xdrproc_t ret_filter, char *ret) +{ + XDR xdr; + struct remote_message_header hdr; + struct remote_thread_call *rv; + + if (VIR_ALLOC(rv) < 0) + return NULL; + + /* Get a unique serial number for this message. */ + rv->serial = priv->counter++; + rv->proc_nr = proc_nr; + rv->ret_filter = ret_filter; + rv->ret = ret; + + pthread_cond_init(&rv->cond, NULL); + + hdr.prog = REMOTE_PROGRAM; + hdr.vers = REMOTE_PROTOCOL_VERSION; + hdr.proc = proc_nr; + hdr.direction = REMOTE_CALL; + hdr.serial = rv->serial; + hdr.status = REMOTE_OK; + + /* Serialise header followed by args. */ + xdrmem_create (&xdr, rv->buffer+4, REMOTE_MESSAGE_MAX, XDR_ENCODE); + if (!xdr_remote_message_header (&xdr, &hdr)) { + error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + VIR_ERR_RPC, _("xdr_remote_message_header failed")); + goto error; + } + + if (!(*args_filter) (&xdr, args)) { + error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, + _("marshalling args")); + goto error; + } + + /* Get the length stored in buffer. */ + rv->bufferLength = xdr_getpos (&xdr); + xdr_destroy (&xdr); + + /* Length must include the length word itself (always encoded in + * 4 bytes as per RFC 4506). + */ + rv->bufferLength += 4; + + /* Encode the length word. */ + xdrmem_create (&xdr, rv->buffer, 4, XDR_ENCODE); + if (!xdr_int (&xdr, (int *)&rv->bufferLength)) { + error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, + _("xdr_int (length word)")); + goto error; + } + xdr_destroy (&xdr); + + return rv; + +error: + VIR_FREE(ret); + return NULL; +} + + + +static int +processCallWrite(virConnectPtr conn, + struct private_data *priv, + int in_open /* if we are in virConnectOpen */, + const char *bytes, int len) +{ + int ret; + + if (priv->uses_tls) { + tls_resend: + ret = gnutls_record_send (priv->session, bytes, len); + if (ret < 0) { + if (ret == GNUTLS_E_INTERRUPTED) + goto tls_resend; + if (ret == GNUTLS_E_AGAIN) + return 0; + + error (in_open ? NULL : conn, + VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret)); + return -1; + } + } else { + resend: + ret = send (priv->sock, bytes, len, 0); + if (ret == -1) { + if (errno == EINTR) + goto resend; + if (errno == EAGAIN) + return 0; + + error (in_open ? NULL : conn, + VIR_ERR_SYSTEM_ERROR, strerror (errno)); + return -1; + + } + } + + return ret; +} + + +static int +processCallRead(virConnectPtr conn, + struct private_data *priv, + int in_open /* if we are in virConnectOpen */, + char *bytes, int len) +{ + int ret; + + if (priv->uses_tls) { + tls_resend: + ret = gnutls_record_recv (priv->session, bytes, len); + if (ret < 0) { + if (ret == GNUTLS_E_INTERRUPTED) + goto tls_resend; + if (ret == GNUTLS_E_AGAIN) + return 0; + + error (in_open ? NULL : conn, + VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret)); + return -1; + } + } else { + resend: + ret = recv (priv->sock, bytes, len, 0); + if (ret == -1) { + if (errno == EINTR) + goto resend; + if (errno == EAGAIN) + return 0; + + error (in_open ? NULL : conn, + VIR_ERR_SYSTEM_ERROR, strerror (errno)); + return -1; + + } + } + + return ret; +} + + +static int +processCallSendOne(virConnectPtr conn, + struct private_data *priv, + int in_open, + struct remote_thread_call *thecall) +{ +#if HAVE_SASL + if (priv->saslconn) { + const char *output; + unsigned int outputlen; + int err, ret; + + if (!priv->saslEncoded) { + err = sasl_encode(priv->saslconn, + thecall->buffer + thecall->bufferOffset, + thecall->bufferLength - thecall->bufferOffset, + &output, &outputlen); + if (err != SASL_OK) { + return -1; + } + priv->saslEncoded = output; + priv->saslEncodedLength = outputlen; + priv->saslEncodedOffset = 0; + + thecall->bufferOffset = thecall->bufferLength; + } + + ret = processCallWrite(conn, priv, in_open, + priv->saslEncoded + priv->saslEncodedOffset, + priv->saslEncodedLength - priv->saslEncodedOffset); + if (ret < 0) + return ret; + priv->saslEncodedOffset += ret; + + if (priv->saslEncodedOffset == priv->saslEncodedLength) { + priv->saslEncoded = NULL; + priv->saslEncodedOffset = priv->saslEncodedLength = 0; + thecall->mode = REMOTE_MODE_WAIT_RX; + } + } else { +#endif + int ret; + ret = processCallWrite(conn, priv, in_open, + thecall->buffer + thecall->bufferOffset, + thecall->bufferLength - thecall->bufferOffset); + if (ret < 0) + return ret; + thecall->bufferOffset += ret; + + if (thecall->bufferOffset == thecall->bufferLength) { + thecall->bufferOffset = thecall->bufferLength = 0; + thecall->mode = REMOTE_MODE_WAIT_RX; + } +#if HAVE_SASL + } +#endif + return 0; +} + + +static int +processCallSend(virConnectPtr conn, struct private_data *priv, + int in_open) { + struct remote_thread_call *thecall = priv->waitDispatch; + + while (thecall && + thecall->mode != REMOTE_MODE_WAIT_TX) + thecall = thecall->next; + + if (!thecall) + return -1; /* Shouldn't happen, but you never know... */ + + while (thecall) { + int ret = processCallSendOne(conn, priv, in_open, thecall); + if (ret < 0) + return ret; + + if (thecall->mode == REMOTE_MODE_WAIT_TX) + return 0; /* Blocking write, to back to event loop */ + + thecall = thecall->next; + } + + return 0; /* No more calls to send, all done */ +} + +static int +processCallRecvSome(virConnectPtr conn, struct private_data *priv, + int in_open) { + unsigned int wantData; + + /* Start by reading length word */ + if (priv->bufferLength == 0) + priv->bufferLength = 4; + + wantData = priv->bufferLength - priv->bufferOffset; + +#if HAVE_SASL + if (priv->saslconn) { + if (priv->saslDecoded == NULL) { + char encoded[8192]; + unsigned int encodedLen = sizeof(encoded); + int ret, err; + ret = processCallRead(conn, priv, in_open, + encoded, encodedLen); + if (ret < 0) + return -1; + if (ret == 0) + return 0; + + err = sasl_decode(priv->saslconn, encoded, ret, + &priv->saslDecoded, &priv->saslDecodedLength); + if (ret != SASL_OK) + return -1; + priv->saslDecodedOffset = 0; + } + + if ((priv->saslDecodedLength - priv->saslDecodedOffset) < wantData) + wantData = (priv->saslDecodedLength - priv->saslDecodedOffset); + + memcpy(priv->buffer + priv->bufferOffset, + priv->saslDecoded + priv->saslDecodedOffset, + wantData); + priv->saslDecodedOffset += wantData; + priv->bufferOffset += wantData; + if (priv->saslDecodedOffset == priv->saslDecodedLength) { + priv->saslDecodedLength = priv->saslDecodedLength = 0; + priv->saslDecoded = NULL; + } + + return wantData; + } else { +#endif + int ret; + + ret = processCallRead(conn, priv, in_open, + priv->buffer + priv->bufferOffset, + wantData); + if (ret < 0) + return -1; + if (ret == 0) + return 0; + + priv->bufferOffset += ret; + + return ret; +#if HAVE_SASL + } +#endif +} + + +static void +processCallAsyncEvent(virConnectPtr conn, struct private_data *priv, + int in_open, + remote_message_header *hdr, + XDR *xdr) { + /* An async message has come in while we were waiting for the + * response. Process it to pull it off the wire, and try again + */ + DEBUG0("Encountered an event while waiting for a response"); + + if (in_open) { + DEBUG("Ignoring bogus event %d received while in open", hdr->proc); + return; + } + + if (hdr->proc == REMOTE_PROC_DOMAIN_EVENT) { + remoteDomainQueueEvent(conn, xdr); + virEventUpdateTimeout(priv->eventFlushTimer, 0); + } else { + DEBUG("Unexpected event proc %d", hdr->proc); + } +} + +static int +processCallRecvLen(virConnectPtr conn, struct private_data *priv, + int in_open) { + XDR xdr; + int len; + + xdrmem_create (&xdr, priv->buffer, priv->bufferLength, XDR_DECODE); + if (!xdr_int (&xdr, &len)) { + error (in_open ? NULL : conn, + VIR_ERR_RPC, _("xdr_int (length word, reply)")); + return -1; + } + xdr_destroy (&xdr); + + /* Length includes length word - adjust to real length to read. */ + len -= 4; + + if (len < 0 || len > REMOTE_MESSAGE_MAX) { + error (in_open ? NULL : conn, + VIR_ERR_RPC, _("packet received from server too large")); + return -1; + } + + /* Extend our declared buffer length and carry + on reading the header + payload */ + priv->bufferLength += len; + DEBUG("Got length, now need %d total (%d more)", priv->bufferLength, len); + return 0; +} + + +static int +processCallRecvMsg(virConnectPtr conn, struct private_data *priv, + int in_open) { + XDR xdr; + struct remote_message_header hdr; + int len = priv->bufferLength - 4; + struct remote_thread_call *thecall; + + /* Deserialise reply header. */ + xdrmem_create (&xdr, priv->buffer + 4, len, XDR_DECODE); + if (!xdr_remote_message_header (&xdr, &hdr)) { + error (in_open ? NULL : conn, + VIR_ERR_RPC, _("invalid header in reply")); + return -1; + } + + /* Check program, version, etc. are what we expect. */ + if (hdr.prog != REMOTE_PROGRAM) { + virRaiseError (in_open ? NULL : conn, + NULL, NULL, VIR_FROM_REMOTE, + VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, + _("unknown program (received %x, expected %x)"), + hdr.prog, REMOTE_PROGRAM); + return -1; + } + if (hdr.vers != REMOTE_PROTOCOL_VERSION) { + virRaiseError (in_open ? NULL : conn, + NULL, NULL, VIR_FROM_REMOTE, + VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, + _("unknown protocol version (received %x, expected %x)"), + hdr.vers, REMOTE_PROTOCOL_VERSION); + return -1; + } + + /* Async events from server need special handling */ + if (hdr.direction == REMOTE_MESSAGE) { + processCallAsyncEvent(conn, priv, in_open, + &hdr, &xdr); + xdr_destroy(&xdr); + return 0; + } + + if (hdr.direction != REMOTE_REPLY) { + virRaiseError (in_open ? NULL : conn, + NULL, NULL, VIR_FROM_REMOTE, + VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, + _("got unexpected RPC call %d from server"), + hdr.proc); + xdr_destroy(&xdr); + return -1; + } + + /* Ok, definitely got an RPC reply now find + out who's been waiting for it */ + + thecall = priv->waitDispatch; + while (thecall && + thecall->serial != hdr.serial) + thecall = thecall->next; + + if (!thecall) { + virRaiseError (in_open ? NULL : conn, + NULL, NULL, VIR_FROM_REMOTE, + VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, + _("no call waiting for reply with serial %d"), + hdr.serial); + xdr_destroy(&xdr); + return -1; + } + + if (hdr.proc != thecall->proc_nr) { + virRaiseError (in_open ? NULL : conn, + NULL, NULL, VIR_FROM_REMOTE, + VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, + _("unknown procedure (received %x, expected %x)"), + hdr.proc, thecall->proc_nr); + xdr_destroy (&xdr); + return -1; + } + + /* Status is either REMOTE_OK (meaning that what follows is a ret + * structure), or REMOTE_ERROR (and what follows is a remote_error + * structure). + */ + switch (hdr.status) { + case REMOTE_OK: + if (!(*thecall->ret_filter) (&xdr, thecall->ret)) { + error (in_open ? NULL : conn, VIR_ERR_RPC, + _("unmarshalling ret")); + return -1; + } + thecall->mode = REMOTE_MODE_COMPLETE; + xdr_destroy (&xdr); + return 0; + + case REMOTE_ERROR: + memset (&thecall->err, 0, sizeof thecall->err); + if (!xdr_remote_error (&xdr, &thecall->err)) { + error (in_open ? NULL : conn, + VIR_ERR_RPC, _("unmarshalling remote_error")); + return -1; + } + xdr_destroy (&xdr); + thecall->mode = REMOTE_MODE_ERROR; + return 0; + + default: + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, + _("unknown status (received %x)"), + hdr.status); + xdr_destroy (&xdr); + return -1; + } +} + + +static int +processCallRecv(virConnectPtr conn, struct private_data *priv, + int in_open) { + int ret; + + /* Read as much data as is available, until we get + * EGAIN + */ + for (;;) { + DEBUG("Do %d %d", priv->bufferLength, priv->bufferOffset); + ret = processCallRecvSome(conn, priv, in_open); + + if (ret < 0) + return -1; + if (ret == 0) + return 0; /* Blocking on read */ + + /* Check for completion of our goal */ + if (priv->bufferOffset == priv->bufferLength) { + if (priv->bufferOffset == 4) { + ret = processCallRecvLen(conn, priv, in_open); + } else { + ret = processCallRecvMsg(conn, priv, in_open); + priv->bufferOffset = priv->bufferLength = 0; + } + if (ret < 0) + return -1; + } + } +} + +/* + * Process all calls pending dispatch/receive until we + * get a reply to our own call. Then quit and pass the buck + * to someone else. + */ +static int +processCalls(virConnectPtr conn, + struct private_data *priv, + int in_open, + struct remote_thread_call *thiscall) +{ + struct pollfd fds[1]; + int ret; + + /* XXX add wakeup pipe */ + + /* XXX weeeeeeeendows hate, perhaps gnulib poll() will work ? */ + + fds[0].fd = priv->sock; + + for (;;) { + struct remote_thread_call *tmp = priv->waitDispatch; + struct remote_thread_call *prev; + + fds[0].events = fds[0].revents = 0; + while (tmp) { + if (tmp->mode == REMOTE_MODE_WAIT_RX) + fds[0].events |= POLLIN; + if (tmp->mode == REMOTE_MODE_WAIT_TX) + fds[0].events |= POLLOUT; + + tmp = tmp->next; + } + + /* Release lock while poll'ing so other threads + * can stuff themselves on the queue */ + remoteDriverUnlock(priv); + ret = poll(fds, ARRAY_CARDINALITY(fds), -1); + remoteDriverLock(priv); + + if (ret < 0) { + if (errno == EAGAIN) + continue; + ;/* XXX damn */ + } + + if (fds[0].revents & POLLOUT) + processCallSend(conn, priv, in_open); + + if (fds[0].revents & POLLIN) + processCallRecv(conn, priv, in_open); + + /* XXX poll hup/err */ + + /* Iterate through waiting threads and if + * any are complete then tell 'em to wakeup + */ + tmp = priv->waitDispatch; + prev = NULL; + while (tmp) { + if (tmp != thiscall && + (tmp->mode == REMOTE_MODE_COMPLETE || + tmp->mode == REMOTE_MODE_ERROR)) { + /* Take them out of the list */ + if (prev) + prev->next = tmp->next; + else + priv->waitDispatch = tmp->next; + + /* And wake them up.... + * ...they won't actually wakeup until + * we release our mutex a short while + * later... + */ + DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch); + pthread_cond_signal(&tmp->cond); + } + prev = tmp; + tmp = tmp->next; + } + + /* Now see if *we* are done */ + if (thiscall->mode == REMOTE_MODE_COMPLETE || + thiscall->mode == REMOTE_MODE_ERROR) { + /* We're at head of the list already, so + * remove us + */ + priv->waitDispatch = thiscall->next; + DEBUG("Giving up the buck %d %p %p", thiscall->proc_nr, thiscall, priv->waitDispatch); + /* See if someone else is still waiting + * and if so, then pass the buck ! */ + if (priv->waitDispatch) { + DEBUG("Passing the buck to %d %p", priv->waitDispatch->proc_nr, priv->waitDispatch); + pthread_cond_signal(&priv->waitDispatch->cond); + } + return 0; + } + } +} + +/* + * This function performs a remote procedure call to procedure PROC_NR. * * NB. This does not free the args structure (not desirable, since you * often want this allocated on the stack or else it contains strings @@ -5584,204 +6245,29 @@ static int really_read (virConnectPtr co * * NB(2). Make sure to memset (&ret, 0, sizeof ret) before calling, * else Bad Things will happen in the XDR code. - */ -static int -doCall (virConnectPtr conn, struct private_data *priv, - int flags /* if we are in virConnectOpen */, - int proc_nr, - xdrproc_t args_filter, char *args, - xdrproc_t ret_filter, char *ret) -{ - char buffer[REMOTE_MESSAGE_MAX]; - char buffer2[4]; - struct remote_message_header hdr; - XDR xdr; - int len; - struct remote_error rerror; - - /* Get a unique serial number for this message. */ - int serial = priv->counter++; - - hdr.prog = REMOTE_PROGRAM; - hdr.vers = REMOTE_PROTOCOL_VERSION; - hdr.proc = proc_nr; - hdr.direction = REMOTE_CALL; - hdr.serial = serial; - hdr.status = REMOTE_OK; - - /* Serialise header followed by args. */ - xdrmem_create (&xdr, buffer, sizeof buffer, XDR_ENCODE); - if (!xdr_remote_message_header (&xdr, &hdr)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - VIR_ERR_RPC, _("xdr_remote_message_header failed")); - return -1; - } - - if (!(*args_filter) (&xdr, args)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, - _("marshalling args")); - return -1; - } - - /* Get the length stored in buffer. */ - len = xdr_getpos (&xdr); - xdr_destroy (&xdr); - - /* Length must include the length word itself (always encoded in - * 4 bytes as per RFC 4506). - */ - len += 4; - - /* Encode the length word. */ - xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_ENCODE); - if (!xdr_int (&xdr, &len)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, - _("xdr_int (length word)")); - return -1; - } - xdr_destroy (&xdr); - - /* Send length word followed by header+args. */ - if (really_write (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer2, sizeof buffer2) == -1 || - really_write (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer, len-4) == -1) - return -1; - -retry_read: - /* Read and deserialise length word. */ - if (really_read (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer2, sizeof buffer2) == -1) - return -1; - - xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE); - if (!xdr_int (&xdr, &len)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - VIR_ERR_RPC, _("xdr_int (length word, reply)")); - return -1; - } - xdr_destroy (&xdr); - - /* Length includes length word - adjust to real length to read. */ - len -= 4; - - if (len < 0 || len > REMOTE_MESSAGE_MAX) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - VIR_ERR_RPC, _("packet received from server too large")); - return -1; - } - - /* Read reply header and what follows (either a ret or an error). */ - if (really_read (conn, priv, flags & REMOTE_CALL_IN_OPEN, buffer, len) == -1) - return -1; - - /* Deserialise reply header. */ - xdrmem_create (&xdr, buffer, len, XDR_DECODE); - if (!xdr_remote_message_header (&xdr, &hdr)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - VIR_ERR_RPC, _("invalid header in reply")); - return -1; - } - - /* Check program, version, etc. are what we expect. */ - if (hdr.prog != REMOTE_PROGRAM) { - virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - NULL, NULL, VIR_FROM_REMOTE, - VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, - _("unknown program (received %x, expected %x)"), - hdr.prog, REMOTE_PROGRAM); - return -1; - } - if (hdr.vers != REMOTE_PROTOCOL_VERSION) { - virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - NULL, NULL, VIR_FROM_REMOTE, - VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, - _("unknown protocol version (received %x, expected %x)"), - hdr.vers, REMOTE_PROTOCOL_VERSION); - return -1; - } - - if (hdr.proc == REMOTE_PROC_DOMAIN_EVENT && - hdr.direction == REMOTE_MESSAGE) { - /* An async message has come in while we were waiting for the - * response. Process it to pull it off the wire, and try again - */ - DEBUG0("Encountered an event while waiting for a response"); - - remoteDomainQueueEvent(conn, &xdr); - virEventUpdateTimeout(priv->eventFlushTimer, 0); - - DEBUG0("Retrying read"); - xdr_destroy (&xdr); - goto retry_read; - } - if (hdr.proc != proc_nr) { - virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - NULL, NULL, VIR_FROM_REMOTE, - VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, - _("unknown procedure (received %x, expected %x)"), - hdr.proc, proc_nr); - return -1; - } - if (hdr.direction != REMOTE_REPLY) { - virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - NULL, NULL, VIR_FROM_REMOTE, - VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, - _("unknown direction (received %x, expected %x)"), - hdr.direction, REMOTE_REPLY); - return -1; - } - if (hdr.serial != serial) { - virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, - VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, - _("unknown serial (received %x, expected %x)"), - hdr.serial, serial); - return -1; - } - - /* Status is either REMOTE_OK (meaning that what follows is a ret - * structure), or REMOTE_ERROR (and what follows is a remote_error - * structure). - */ - switch (hdr.status) { - case REMOTE_OK: - if (!(*ret_filter) (&xdr, ret)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, VIR_ERR_RPC, - _("unmarshalling ret")); - return -1; - } - xdr_destroy (&xdr); - return 0; - - case REMOTE_ERROR: - memset (&rerror, 0, sizeof rerror); - if (!xdr_remote_error (&xdr, &rerror)) { - error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, - VIR_ERR_RPC, _("unmarshalling remote_error")); - return -1; - } - xdr_destroy (&xdr); - /* See if caller asked us to keep quiet about missing RPCs - * eg for interop with older servers */ - if (flags & REMOTE_CALL_QUIET_MISSING_RPC && - rerror.domain == VIR_FROM_REMOTE && - rerror.code == VIR_ERR_RPC && - rerror.level == VIR_ERR_ERROR && - STRPREFIX(*rerror.message, "unknown procedure")) { - return -2; - } - server_error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, &rerror); - xdr_free ((xdrproc_t) xdr_remote_error, (char *) &rerror); - return -1; - - default: - virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, - VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, - _("unknown status (received %x)"), - hdr.status); - xdr_destroy (&xdr); - return -1; - } -} - - + * + * NB(3) You must have the private_data lock before calling this + * + * NB(4) This is very complicated. Due to connection cloning, multiple + * threads can want to use the socket at once. Obviously only one of + * them can. So if someone's using the socket, other threads are put + * to sleep on condition variables. THe existing thread may completely + * send & receive their RPC call/reply while they're asleep. Or it + * may only get around to dealing with sending the call. Or it may + * get around to neither. So upon waking up from slumber, the other + * thread may or may not have more work todo. + * + * We call this dance 'passing the buck' + * + * http://en.wikipedia.org/wiki/Passing_the_buck + * + * "Buck passing or passing the buck is the action of transferring + * responsibility or blame unto another person. It is also used as + * a strategy in power politics when the actions of one country/ + * nation are blamed on another, providing an opportunity for war." + * + * NB(5) Don't Panic! + */ static int call (virConnectPtr conn, struct private_data *priv, int flags /* if we are in virConnectOpen */, @@ -5790,6 +6276,66 @@ call (virConnectPtr conn, struct private xdrproc_t ret_filter, char *ret) { int rv; + struct remote_thread_call *thiscall; + + DEBUG("Doing call %d %p", proc_nr, priv->waitDispatch); + thiscall = prepareCall(conn, priv, flags, proc_nr, + args_filter, args, + ret_filter, ret); + + if (!thiscall) { + error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + VIR_ERR_NO_MEMORY, NULL); + return -1; + } + + /* Check to see if another thread is dispatching */ + if (priv->waitDispatch) { + /* Stick ourselves on the end of the wait queue */ + struct remote_thread_call *tmp = priv->waitDispatch; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + tmp->next = thiscall; + else + priv->waitDispatch = thiscall; + + DEBUG("Going to sleep %d %p %p", proc_nr, priv->waitDispatch, thiscall); + /* Go to sleep while other thread is working... */ + pthread_cond_wait(&thiscall->cond, &priv->lock); + + DEBUG("Wokeup from sleep %d %p %p", proc_nr, priv->waitDispatch, thiscall); + /* Two reasons we can be woken up + * 1. Other thread has got our reply ready for us + * 2. Other thread is all done, and its out turn to + * be the dispatcher to finish waiting for + * out reply + */ + if (thiscall->mode == REMOTE_MODE_COMPLETE || + thiscall->mode == REMOTE_MODE_ERROR) { + /* + * We avoided catching the buck and our reply is ready ! + * We've already had 'thiscall' removed from the list + * so just need to (maybe) handle errors & free it + */ + goto cleanup; + } + + /* Grr, someone passed the buck onto us ... */ + + } else { + /* We're first to catch the buck */ + priv->waitDispatch = thiscall; + } + + DEBUG("We have the buck %d %p %p", proc_nr, priv->waitDispatch, thiscall); + /* + * The buck stops here! + * + * At this point we're about to own the dispatch + * process... + */ + /* * Avoid needless wake-ups of the event loop in the * case where this call is being made from a different @@ -5800,209 +6346,147 @@ call (virConnectPtr conn, struct private if (priv->watch >= 0) virEventUpdateHandle(priv->watch, 0); - rv = doCall(conn, priv,flags, proc_nr, - args_filter, args, - ret_filter, ret); + rv = processCalls(conn, priv, + flags & REMOTE_CALL_IN_OPEN ? 1 : 0, + thiscall); if (priv->watch >= 0) virEventUpdateHandle(priv->watch, VIR_EVENT_HANDLE_READABLE); - return rv; -} - -static int -really_write_buf (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - const char *bytes, int len) -{ - const char *p; - int err; - - p = bytes; - if (priv->uses_tls) { - do { - err = gnutls_record_send (priv->session, p, len); - if (err < 0) { - if (err == GNUTLS_E_INTERRUPTED || err == GNUTLS_E_AGAIN) - continue; - error (in_open ? NULL : conn, - VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err)); - return -1; - } - len -= err; - p += err; - } - while (len > 0); - } else { - do { - err = send (priv->sock, p, len, 0); - if (err == -1) { - if (errno == EINTR || errno == EAGAIN) - continue; - error (in_open ? NULL : conn, - VIR_ERR_SYSTEM_ERROR, strerror (errno)); - return -1; - } - len -= err; - p += err; - } - while (len > 0); - } - - return 0; -} - -static int -really_write_plain (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ - return really_write_buf(conn, priv, in_open, bytes, len); -} - -#if HAVE_SASL -static int -really_write_sasl (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ - const char *output; - unsigned int outputlen; - int err; - - err = sasl_encode(priv->saslconn, bytes, len, &output, &outputlen); - if (err != SASL_OK) { - return -1; - } - - return really_write_buf(conn, priv, in_open, output, outputlen); -} -#endif - -static int -really_write (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ -#if HAVE_SASL - if (priv->saslconn) - return really_write_sasl(conn, priv, in_open, bytes, len); - else -#endif - return really_write_plain(conn, priv, in_open, bytes, len); -} - -static int -really_read_buf (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ - int err; - - if (priv->uses_tls) { - tlsreread: - err = gnutls_record_recv (priv->session, bytes, len); - if (err < 0) { - if (err == GNUTLS_E_INTERRUPTED) - goto tlsreread; - error (in_open ? NULL : conn, - VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err)); - return -1; - } - if (err == 0) { - error (in_open ? NULL : conn, - VIR_ERR_RPC, _("socket closed unexpectedly")); - return -1; - } - return err; - } else { - reread: - err = recv (priv->sock, bytes, len, 0); - if (err == -1) { - if (errno == EINTR) - goto reread; - error (in_open ? NULL : conn, - VIR_ERR_SYSTEM_ERROR, strerror (errno)); - return -1; - } - if (err == 0) { - error (in_open ? NULL : conn, - VIR_ERR_RPC, _("socket closed unexpectedly")); - return -1; - } - return err; - } - - return 0; -} - -static int -really_read_plain (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ - do { - int ret = really_read_buf (conn, priv, in_open, bytes, len); - if (ret < 0) - return -1; - - len -= ret; - bytes += ret; - } while (len > 0); - - return 0; -} - -#if HAVE_SASL -static int -really_read_sasl (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ - do { - int want, got; - if (priv->saslDecoded == NULL) { - char encoded[8192]; - int encodedLen = sizeof(encoded); - int err, ret; - ret = really_read_buf (conn, priv, in_open, encoded, encodedLen); - if (ret < 0) - return -1; - - err = sasl_decode(priv->saslconn, encoded, ret, - &priv->saslDecoded, &priv->saslDecodedLength); - } - - got = priv->saslDecodedLength - priv->saslDecodedOffset; - want = len; - if (want > got) - want = got; - - memcpy(bytes, priv->saslDecoded + priv->saslDecodedOffset, want); - priv->saslDecodedOffset += want; - if (priv->saslDecodedOffset == priv->saslDecodedLength) { - priv->saslDecoded = NULL; - priv->saslDecodedOffset = priv->saslDecodedLength = 0; - } - bytes += want; - len -= want; - } while (len > 0); - - return 0; -} -#endif - -static int -really_read (virConnectPtr conn, struct private_data *priv, - int in_open /* if we are in virConnectOpen */, - char *bytes, int len) -{ -#if HAVE_SASL - if (priv->saslconn) - return really_read_sasl (conn, priv, in_open, bytes, len); - else -#endif - return really_read_plain (conn, priv, in_open, bytes, len); -} + + if (rv < 0) { + VIR_FREE(thiscall); + return -1; + } + +cleanup: + DEBUG("All done with our call %d %p %p", proc_nr, priv->waitDispatch, thiscall); + if (thiscall->mode == REMOTE_MODE_ERROR) { + /* See if caller asked us to keep quiet about missing RPCs + * eg for interop with older servers */ + if (flags & REMOTE_CALL_QUIET_MISSING_RPC && + thiscall->err.domain == VIR_FROM_REMOTE && + thiscall->err.code == VIR_ERR_RPC && + thiscall->err.level == VIR_ERR_ERROR && + STRPREFIX(*thiscall->err.message, "unknown procedure")) { + rv = -2; + } else { + server_error (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + &thiscall->err); + rv = -1; + } + } else { + rv = 0; + } + VIR_FREE(thiscall); + return rv; +} + + +/** + * remoteDomainReadEvent + * + * Read the event data off the wire + */ +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 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 +remoteDomainQueueEvent(virConnectPtr conn, XDR *xdr) +{ + 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: + * + * The callback for monitoring the remote socket + * for event data + */ +void +remoteDomainEventFired(int watch, + int fd, + int event, + void *opaque) +{ + virConnectPtr conn = opaque; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + /* This should be impossible, but it doesn't hurt to check */ + if (priv->waitDispatch) + goto done; + + DEBUG("Event fired %d %d %d %X", watch, fd, event, event); + + if (event & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { + DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " + "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); + virEventRemoveHandle(watch); + priv->watch = -1; + goto done; + } + + if (fd != priv->sock) { + virEventRemoveHandle(watch); + priv->watch = -1; + goto done; + } + + if (processCallRecv(conn, priv, 0) < 0) + DEBUG0("Something went wrong during async message processing"); + +done: + remoteDriverUnlock(priv); +} + +void +remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) +{ + virConnectPtr conn = opaque; + struct private_data *priv = conn->privateData; + + remoteDriverLock(priv); + + virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList, + virDomainEventDispatchDefaultFunc, NULL); + virEventUpdateTimeout(priv->eventFlushTimer, -1); + + remoteDriverUnlock(priv); +} + /* For errors internal to this library. */ static void @@ -6306,161 +6790,3 @@ remoteRegister (void) return 0; } -/** - * remoteDomainReadEvent - * - * Read the event data off the wire - */ -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 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) -{ - 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) -{ - 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: - * - * The callback for monitoring the remote socket - * for event data - */ -void -remoteDomainEventFired(int watch, - int fd, - int event, - void *opaque) -{ - char buffer[REMOTE_MESSAGE_MAX]; - char buffer2[4]; - struct remote_message_header hdr; - XDR xdr; - int len; - - virConnectPtr conn = opaque; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - DEBUG("Event fired %d %d %d %X", watch, fd, event, event); - - if (event & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) { - DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or " - "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__); - virEventRemoveHandle(watch); - goto done; - } - - if (fd != priv->sock) { - virEventRemoveHandle(watch); - goto done; - } - - /* Read and deserialise length word. */ - if (really_read (conn, priv, 0, buffer2, sizeof buffer2) == -1) - goto done; - - xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE); - if (!xdr_int (&xdr, &len)) { - error (conn, VIR_ERR_RPC, _("xdr_int (length word, reply)")); - goto done; - } - xdr_destroy (&xdr); - - /* Length includes length word - adjust to real length to read. */ - len -= 4; - - if (len < 0 || len > REMOTE_MESSAGE_MAX) { - error (conn, VIR_ERR_RPC, _("packet received from server too large")); - goto done; - } - - /* Read reply header and what follows (either a ret or an error). */ - if (really_read (conn, priv, 0, buffer, len) == -1) { - error (conn, VIR_ERR_RPC, _("error reading buffer from memory")); - goto done; - } - - /* Deserialise reply header. */ - xdrmem_create (&xdr, buffer, len, XDR_DECODE); - if (!xdr_remote_message_header (&xdr, &hdr)) { - error (conn, VIR_ERR_RPC, _("invalid header in event firing")); - goto done; - } - - if (hdr.proc == REMOTE_PROC_DOMAIN_EVENT && - hdr.direction == REMOTE_MESSAGE) { - DEBUG0("Encountered an async event"); - remoteDomainProcessEvent(conn, &xdr); - } else { - DEBUG0("invalid proc in event firing"); - error (conn, VIR_ERR_RPC, _("invalid proc in event firing")); - } - -done: - remoteDriverUnlock(priv); -} - -void -remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque) -{ - virConnectPtr conn = opaque; - struct private_data *priv = conn->privateData; - - remoteDriverLock(priv); - - virDomainEventQueueDispatch(priv->domainEvents, priv->callbackList, - virDomainEventDispatchDefaultFunc, NULL); - virEventUpdateTimeout(priv->eventFlushTimer, -1); - - remoteDriverUnlock(priv); -} diff --git a/src/util.c b/src/util.c --- a/src/util.c +++ b/src/util.c @@ -167,7 +167,7 @@ static int virSetCloseExec(int fd) { return 0; } -static int virSetNonBlock(int fd) { +int virSetNonBlock(int fd) { int flags; if ((flags = fcntl(fd, F_GETFL)) < 0) return -1; diff --git a/src/util.h b/src/util.h --- a/src/util.h +++ b/src/util.h @@ -36,6 +36,8 @@ enum { VIR_EXEC_NONBLOCK = (1 << 0), VIR_EXEC_DAEMON = (1 << 1), }; + +int virSetNonBlock(int fd); int virExec(virConnectPtr conn, const char *const*argv, diff --git a/src/virsh.c b/src/virsh.c --- a/src/virsh.c +++ b/src/virsh.c @@ -6572,12 +6572,27 @@ _vshStrdup(vshControl *ctl, const char * return NULL; } +static +void *evil(void *data) +{ + virConnectPtr conn = data; + + while (1) { + virNodeInfo ni; + virNodeGetInfo(conn, &ni); + fprintf(stderr, "BG %d %d %d %lu\n", ni.cores, ni.threads, ni.nodes, ni.memory); + sleep(2); + } +} + /* * Initialize connection. */ static int vshInit(vshControl *ctl) { + pthread_t t; + virConnectPtr cloned; if (ctl->conn) return FALSE; @@ -6590,6 +6605,9 @@ vshInit(vshControl *ctl) virConnectAuthPtrDefault, ctl->readonly ? VIR_CONNECT_RO : 0); + + cloned = virConnectClone(ctl->conn); + pthread_create(&t, NULL, evil, cloned); /* This is not necessarily fatal. All the individual commands check * vshConnectionUsability, except ones which don't need a connection -- |: 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 09, 2008 at 12:08:51PM +0000, Daniel P. Berrange wrote:
This series is a work-in-progress set of patches implementing connection cloning. The idea is that if you want to use a connection form multiple threads, you could do
virConnectPtr copy = virConnectClone(conn)
and use 'copy' from the other thread. This avoids the problem of having to make all the virError handling stuff thread-local whic is the blocker for allowing real mutlti-thread access to a single virConnectPtr object.
I believe this cloning support should be sufficient for the Java bindings need to use a thread for its event loop. The idea being that if you wanted to use an event loop in a background thread, you'd create a cloned object for use event loop triggered callbacks like domain events notifications.
I'd still like to do some experiments later making the single virConnectPtr fully thread safe, but that'll take a little more time. I'm hoping this cloning will address the Java needs right now...
Interesting approach, one more possibility of handling things like long-lasting operations, this could be generally useful even beyond just the Java bindings. 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/
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard