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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list