+Wed Jan 21 18:10:12 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+
+ Make Xen driver threadsafe
+ * src/proxy_internal.c, src/xen_inotify.c, src/xen_internal.c,
+ src/xen_unified.c, src/xen_unified.h, src/xend_internal.c,
+ src/xm_internal.c, src/xs_internal.c, src/xs_internal.h: Add
+ mutex locking of shared state
+
Wed Jan 21 10:48:12 IST 2009 Mark McLoughlin <markmc@redhat.com>
If you un-install libvirt and re-install it, you get a warning
#define STANDALONE
-static int debug = 0;
+#define VIR_FROM_THIS VIR_FROM_PROXY
static int xenProxyClose(virConnectPtr conn);
static virDrvOpenStatus xenProxyOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags);
const char *proxyarg[2];
if (!proxyPath) {
- fprintf(stderr, "failed to find libvirt_proxy\n");
+ VIR_WARN0("failed to find libvirt_proxy\n");
return(-1);
}
- if (debug)
- fprintf(stderr, "Asking to launch %s\n", proxyPath);
+ VIR_DEBUG("Asking to launch %s\n", proxyPath);
proxyarg[0] = proxyPath;
proxyarg[1] = NULL;
if (virExec(NULL, proxyarg, NULL, NULL,
&pid, -1, NULL, NULL, VIR_EXEC_DAEMON) < 0)
- fprintf(stderr, "Failed to fork libvirt_proxy\n");
+ VIR_ERROR0("Failed to fork libvirt_proxy\n");
/*
* do a waitpid on the intermediate process to avoid zombies.
return (-1);
}
- if (debug > 0)
- fprintf(stderr, "connected to unix socket %s via %d\n", path, fd);
+ DEBUG("connected to unix socket %s via %d\n", path, fd);
return (fd);
}
/**
- * virProxyCloseClientSocket:
- * @fd: the file descriptor for the socket
+ * virProxyCloseSocket:
+ * @priv: the Xen proxy data
*
- * Close the socket from that client
+ * Close the socket from that client. The caller must
+ * hold the lock on 'priv' before calling
*
* Returns 0 in case of success and -1 in case of error
*/
static int
-virProxyCloseClientSocket(int fd) {
+virProxyCloseSocket(xenUnifiedPrivatePtr priv) {
int ret;
- if (fd < 0)
+ if (priv->proxy < 0)
return(-1);
- ret = close(fd);
+ ret = close(priv->proxy);
if (ret != 0)
- fprintf(stderr, _("Failed to close socket %d\n"), fd);
- else if (debug > 0)
- fprintf(stderr, "Closed socket %d\n", fd);
+ VIR_WARN(_("Failed to close socket %d\n"), priv->proxy);
+ else
+ VIR_DEBUG("Closed socket %d\n", priv->proxy);
+ priv->proxy = -1;
return(ret);
}
* @fd: the socket
* @buffer: the target memory area
* @len: the length in bytes
- * @quiet: quiet access
*
* Process a read from a client socket
*
* Returns the number of byte read or -1 in case of error.
*/
static int
-virProxyReadClientSocket(int fd, char *buffer, int len, int quiet) {
+virProxyReadClientSocket(int fd, char *buffer, int len) {
int ret;
if ((fd < 0) || (buffer == NULL) || (len < 0))
ret = read(fd, buffer, len);
if (ret < 0) {
if (errno == EINTR) {
- if (debug > 0)
- fprintf(stderr, "read socket %d interrupted\n", fd);
+ VIR_DEBUG("read socket %d interrupted\n", fd);
goto retry;
}
- if (!quiet)
- fprintf(stderr, _("Failed to read socket %d\n"), fd);
+ VIR_WARN("Failed to read socket %d\n", fd);
return(-1);
}
- if (debug)
- fprintf(stderr, "read %d bytes from socket %d\n",
- ret, fd);
+ VIR_DEBUG("read %d bytes from socket %d\n",
+ ret, fd);
return(ret);
}
ret = safewrite(fd, data, len);
if (ret < 0) {
- fprintf(stderr, _("Failed to write to socket %d\n"), fd);
+ VIR_WARN(_("Failed to write to socket %d\n"), fd);
return(-1);
}
- if (debug)
- fprintf(stderr, "wrote %d bytes to socket %d\n",
- len, fd);
+ VIR_DEBUG("wrote %d bytes to socket %d\n",
+ len, fd);
return(0);
}
return -1;
}
- /* Fail silently. */
- if (priv->proxy == -1)
- return -1;
-
- virProxyCloseClientSocket (priv->proxy);
- priv->proxy = -1;
+ xenUnifiedLock(priv);
+ virProxyCloseSocket (priv);
+ xenUnifiedUnlock(priv);
return 0;
}
return -1;
}
+ xenUnifiedLock(priv);
+
/* Fail silently. */
if (priv->proxy == -1)
- return -1;
+ goto error;
/*
* normal communication serial numbers are in 0..4095
request->serial = serial;
ret = virProxyWriteClientSocket(priv->proxy, (const char *) request,
request->len);
- if (ret < 0)
- return(-1);
+ if (ret < 0) {
+ if (!quiet)
+ virReportSystemError(conn, errno, "%s",
+ _("failed to write proxy request"));
+ goto error;
+ }
retry:
if (answer == NULL) {
/* read in situ */
ret = virProxyReadClientSocket(priv->proxy, (char *) request,
- sizeof(virProxyPacket), quiet);
- if (ret < 0)
- return(-1);
+ sizeof(virProxyPacket));
+ if (ret < 0) {
+ if (!quiet)
+ virReportSystemError(conn, errno, "%s",
+ _("failed to read proxy reply"));
+ goto error;
+ }
if (ret != sizeof(virProxyPacket)) {
- fprintf(stderr,
- _("Communication error with proxy: got %d bytes of %d\n"),
- ret, (int) sizeof(virProxyPacket));
- xenProxyClose(conn);
- return(-1);
+ virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Communication error with proxy: got %d bytes of %d\n"),
+ ret, (int) sizeof(virProxyPacket));
+ goto error;
}
res = request;
if (res->len != sizeof(virProxyPacket)) {
- fprintf(stderr,
- _("Communication error with proxy: expected %d bytes got %d\n"),
- (int) sizeof(virProxyPacket), res->len);
- xenProxyClose(conn);
- return(-1);
+ virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Communication error with proxy: expected %d bytes got %d\n"),
+ (int) sizeof(virProxyPacket), res->len);
+ goto error;
}
} else {
/* read in packet provided */
ret = virProxyReadClientSocket(priv->proxy, (char *) answer,
- sizeof(virProxyPacket), quiet);
- if (ret < 0)
- return(-1);
+ sizeof(virProxyPacket));
+ if (ret < 0) {
+ if (!quiet)
+ virReportSystemError(conn, errno, "%s",
+ _("failed to read proxy reply"));
+ goto error;
+ }
if (ret != sizeof(virProxyPacket)) {
- fprintf(stderr,
- _("Communication error with proxy: got %d bytes of %d\n"),
- ret, (int) sizeof(virProxyPacket));
- xenProxyClose(conn);
- return(-1);
+ virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Communication error with proxy: got %d bytes of %d\n"),
+ ret, (int) sizeof(virProxyPacket));
+ goto error;
}
res = (virProxyPacketPtr) answer;
if ((res->len < sizeof(virProxyPacket)) ||
(res->len > sizeof(virProxyFullPacket))) {
- fprintf(stderr,
- _("Communication error with proxy: got %d bytes packet\n"),
- res->len);
- xenProxyClose(conn);
- return(-1);
+ virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Communication error with proxy: got %d bytes packet\n"),
+ res->len);
+ goto error;
}
if (res->len > sizeof(virProxyPacket)) {
ret = virProxyReadClientSocket(priv->proxy,
(char *) &(answer->extra.arg[0]),
- res->len - ret, quiet);
+ res->len - ret);
if (ret != (int) (res->len - sizeof(virProxyPacket))) {
- fprintf(stderr,
- _("Communication error with proxy: got %d bytes of %d\n"),
- ret, (int) sizeof(virProxyPacket));
- xenProxyClose(conn);
- return(-1);
+ virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Communication error with proxy: got %d bytes of %d\n"),
+ ret, (int) sizeof(virProxyPacket));
+ goto error;
}
}
}
*/
if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
(res->len < sizeof(virProxyPacket))) {
- fprintf(stderr, "%s",
- _("Communication error with proxy: malformed packet\n"));
- xenProxyClose(conn);
- return(-1);
+ virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Communication error with proxy: malformed packet\n"));
+ goto error;
}
if (res->serial != serial) {
- TODO /* Asynchronous communication */
- fprintf(stderr, _("got asynchronous packet number %d\n"), res->serial);
+ VIR_WARN(_("got asynchronous packet number %d\n"), res->serial);
goto retry;
}
- return(0);
+
+ xenUnifiedUnlock(priv);
+ return 0;
+
+error:
+ virProxyCloseSocket(priv);
+ xenUnifiedUnlock(priv);
+ return -1;
}
/**
ret = xenProxyCommand(conn, &req, NULL, 1);
if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
virProxyError(NULL, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
- xenProxyClose(conn);
return(-1);
}
return(0);
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, NULL, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(-1);
}
*hvVer = req.data.larg;
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(-1);
}
nb = ans.data.arg;
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, NULL, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(-1);
}
return(req.data.arg);
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, NULL, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(0);
}
return(req.data.larg);
req.len = sizeof(req);
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(domain->conn);
return(-1);
}
if (ans.len != sizeof(virProxyPacket) + sizeof(virDomainInfo)) {
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(NULL);
}
if (ans.data.arg == -1) {
ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(NULL);
}
if (req.data.arg == -1) {
strcpy(&req.extra.str[0], name);
ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(NULL);
}
if (req.data.arg == -1) {
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(conn);
return(-1);
}
if (ans.data.arg == -1) {
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(conn);
return NULL;
}
if (ans.data.arg == -1)
req.len = sizeof(req);
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(domain->conn);
return(NULL);
}
if (ans.len <= sizeof(virProxyPacket)) {
req.len = sizeof(req);
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
if (ret < 0) {
- xenProxyClose(domain->conn);
return(NULL);
}
if ((ans.len == sizeof(virProxyPacket)) && (ans.data.arg < 0)) {
return;
}
+ xenUnifiedLock(priv);
+
reread:
got = read(fd, buf, sizeof(buf));
if (got == -1) {
if (errno == EINTR)
goto reread;
- return;
+ goto cleanup;
}
tmp = buf;
while (got) {
if (got < sizeof(struct inotify_event))
- return; /* bad */
+ goto cleanup; /* bad */
e = (struct inotify_event *)tmp;
tmp += sizeof(struct inotify_event);
got -= sizeof(struct inotify_event);
if (got < e->len)
- return;
+ goto cleanup;
tmp += e->len;
got -= e->len;
if (xenInotifyRemoveDomainConfigInfo(conn, fname) < 0 ) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Error adding file to config cache"));
- return;
+ goto cleanup;
}
} else if (e->mask & ( IN_CREATE | IN_CLOSE_WRITE | IN_MOVED_TO) ) {
virDomainEventPtr event;
if (xenInotifyAddDomainConfigInfo(conn, fname) < 0 ) {
virXenInotifyError(NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Error adding file to config cache"));
- return;
+ goto cleanup;
}
event = xenInotifyDomainEventFromFile(conn, fname,
}
}
+
+cleanup:
+ xenUnifiedUnlock(priv);
}
/**
DEBUG0("Failed to add inotify handle, disabling events");
}
- conn->refs++;
+ virConnectRef(conn);
return 0;
}
{
#ifdef __linux__
xenUnifiedPrivatePtr priv;
+ int ret;
priv = (xenUnifiedPrivatePtr) dom->conn->privateData;
- return xenLinuxDomainBlockStats (priv, dom, path, stats);
+ xenUnifiedLock(priv);
+ /* Need to lock because it hits the xenstore handle :-( */
+ ret = xenLinuxDomainBlockStats (priv, dom, path, stats);
+ xenUnifiedUnlock(priv);
+ return ret;
#else
virXenErrorFunc (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__,
"block statistics not supported on this platform",
if (XEN_GETDOMAININFO_DOMAIN(dominfo) != id)
return (NULL);
-
- if (!(name = xenStoreDomainGetName(conn, id)))
+ xenUnifiedLock(priv);
+ name = xenStoreDomainGetName(conn, id);
+ xenUnifiedUnlock(priv);
+ if (!name)
return (NULL);
ret = virGetDomain(conn, name, XEN_GETDOMAININFO_UUID(dominfo));
if (id == -1)
return (NULL);
- if (!(name = xenStoreDomainGetName(conn, id)))
+ xenUnifiedLock(priv);
+ name = xenStoreDomainGetName(conn, id);
+ xenUnifiedUnlock(priv);
+ if (!name)
return (NULL);
ret = virGetDomain(conn, name, uuid);
xen_op_v2_sys op_sys;
int i, j, ret;
xenUnifiedPrivatePtr priv;
- int nbNodeCells;
if (conn == NULL) {
virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
return -1;
}
- nbNodeCells = xenNbCells(conn);
- if (nbNodeCells < 0) {
+ priv = conn->privateData;
+
+ if (priv->nbNodeCells < 0) {
virXenErrorFunc (conn, VIR_ERR_XEN_CALL, __FUNCTION__,
"cannot determine actual number of cells",0);
return(-1);
}
- if ((maxCells < 1) || (startCell >= nbNodeCells)) {
+ if ((maxCells < 1) || (startCell >= priv->nbNodeCells)) {
virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
"invalid argument", 0);
return -1;
return -1;
}
- priv = (xenUnifiedPrivatePtr) conn->privateData;
if (priv->handle < 0) {
virXenErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
"priv->handle invalid", 0);
memset(&op_sys, 0, sizeof(op_sys));
op_sys.cmd = XEN_V2_OP_GETAVAILHEAP;
- for (i = startCell, j = 0;(i < nbNodeCells) && (j < maxCells);i++,j++) {
+ for (i = startCell, j = 0;(i < priv->nbNodeCells) && (j < maxCells);i++,j++) {
op_sys.u.availheap.node = i;
ret = xenHypervisorDoV2Sys(priv->handle, &op_sys);
if (ret < 0) {
unsigned char *cpumaps, int maplen);
/* The five Xen drivers below us. */
-static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
+static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
[XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
[XEN_UNIFIED_PROXY_OFFSET] = &xenProxyDriver,
[XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
-/*
- * Helper functions currently used in the NUMA code
- * Those variables should not be accessed directly but through helper
- * functions xenNbCells() and xenNbCpu() available to all Xen backends
- */
-static int nbNodeCells = -1;
-static int nbNodeCpus = -1;
-
/**
* xenNumaInit:
* @conn: pointer to the hypervisor connection
static void
xenNumaInit(virConnectPtr conn) {
virNodeInfo nodeInfo;
+ xenUnifiedPrivatePtr priv;
int ret;
ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
if (ret < 0)
return;
- nbNodeCells = nodeInfo.nodes;
- nbNodeCpus = nodeInfo.cpus;
-}
-/**
- * xenNbCells:
- * @conn: pointer to the hypervisor connection
- *
- * Number of NUMA cells present in the actual Node
- *
- * Returns the number of NUMA cells available on that Node
- */
-int xenNbCells(virConnectPtr conn) {
- if (nbNodeCells < 0)
- xenNumaInit(conn);
- return(nbNodeCells);
-}
+ priv = conn->privateData;
-/**
- * xenNbCpus:
- * @conn: pointer to the hypervisor connection
- *
- * Number of CPUs present in the actual Node
- *
- * Returns the number of CPUs available on that Node
- */
-int xenNbCpus(virConnectPtr conn) {
- if (nbNodeCpus < 0)
- xenNumaInit(conn);
- return(nbNodeCpus);
+ priv->nbNodeCells = nodeInfo.nodes;
+ priv->nbNodeCpus = nodeInfo.cpus;
}
+
/**
* xenDomainUsedCpus:
* @dom: the domain
xenDomainUsedCpus(virDomainPtr dom)
{
char *res = NULL;
- int nb_cpu, ncpus;
+ int ncpus;
int nb_vcpu;
char *cpulist = NULL;
unsigned char *cpumap = NULL;
int n, m;
virVcpuInfoPtr cpuinfo = NULL;
virNodeInfo nodeinfo;
+ xenUnifiedPrivatePtr priv;
if (!VIR_IS_CONNECTED_DOMAIN(dom))
return (NULL);
- nb_cpu = xenNbCpus(dom->conn);
- if (nb_cpu <= 0)
+ priv = dom->conn->privateData;
+
+ if (priv->nbNodeCpus <= 0)
return(NULL);
nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
if (nb_vcpu <= 0)
if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
return(NULL);
- if (VIR_ALLOC_N(cpulist, nb_cpu) < 0)
+ if (VIR_ALLOC_N(cpulist, priv->nbNodeCpus) < 0)
goto done;
if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
goto done;
if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
cpumap, cpumaplen)) >= 0) {
for (n = 0 ; n < ncpus ; n++) {
- for (m = 0 ; m < nb_cpu; m++) {
+ for (m = 0 ; m < priv->nbNodeCpus; m++) {
if ((cpulist[m] == 0) &&
(VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
cpulist[m] = 1;
nb++;
/* if all CPU are used just return NULL */
- if (nb == nb_cpu)
+ if (nb == priv->nbNodeCpus)
goto done;
}
}
}
- res = virDomainCpuSetFormat(dom->conn, cpulist, nb_cpu);
+ res = virDomainCpuSetFormat(dom->conn, cpulist, priv->nbNodeCpus);
}
done:
xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating private data");
return VIR_DRV_OPEN_ERROR;
}
- conn->privateData = priv;
+ if (virMutexInit(&priv->lock) < 0) {
+ xenUnifiedError (NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot initialise mutex"));
+ VIR_FREE(priv);
+ return VIR_DRV_OPEN_ERROR;
+ }
/* Allocate callback list */
if (VIR_ALLOC(cbList) < 0) {
xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating callback list");
+ virMutexDestroy(&priv->lock);
+ VIR_FREE(priv);
return VIR_DRV_OPEN_ERROR;
}
+ conn->privateData = priv;
+
priv->domainEventCallbacks = cbList;
priv->handle = -1;
}
}
+ xenNumaInit(conn);
+
if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
DEBUG0("Failed to make capabilities");
goto fail;
DEBUG0("Failed to activate a mandatory sub-driver");
for (i = 0 ; i < XEN_UNIFIED_NR_DRIVERS ; i++)
if (priv->opened[i]) drivers[i]->close(conn);
+ virMutexDestroy(&priv->lock);
VIR_FREE(priv);
+ conn->privateData = NULL;
return ret;
}
if (priv->opened[i] && drivers[i]->close)
(void) drivers[i]->close (conn);
- free (conn->privateData);
+ virMutexDestroy(&priv->lock);
+ VIR_FREE(conn->privateData);
conn->privateData = NULL;
return 0;
static char *
xenUnifiedGetCapabilities (virConnectPtr conn)
{
- GET_PRIVATE(conn);
- int i;
- char *ret;
+ xenUnifiedPrivatePtr priv = conn->privateData;
+ char *xml;
- for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
- if (priv->opened[i] && drivers[i]->getCapabilities) {
- ret = drivers[i]->getCapabilities (conn);
- if (ret) return ret;
- }
+ if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
+ virReportOOMError(conn);
+ return NULL;
+ }
- return NULL;
+ return xml;
}
static int
} else {
if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
char *cpus, *res;
+ xenUnifiedLock(priv);
cpus = xenDomainUsedCpus(dom);
+ xenUnifiedUnlock(priv);
res = xenDaemonDomainDumpXML(dom, flags, cpus);
VIR_FREE(cpus);
return(res);
void *opaque,
void (*freefunc)(void *))
{
+ GET_PRIVATE (conn);
+
int ret;
+ xenUnifiedLock(priv);
- GET_PRIVATE (conn);
if (priv->xsWatch == -1) {
xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+ xenUnifiedUnlock(priv);
return -1;
}
if (ret == 0)
conn->refs++;
+ xenUnifiedUnlock(priv);
return (ret);
}
{
int ret;
GET_PRIVATE (conn);
+ xenUnifiedLock(priv);
+
if (priv->xsWatch == -1) {
xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+ xenUnifiedUnlock(priv);
return -1;
}
- ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
- callback);
+ if (priv->domainEventDispatching)
+ ret = virDomainEventCallbackListMarkDelete(conn, priv->domainEventCallbacks,
+ callback);
+ else
+ ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
+ callback);
if (ret == 0)
virUnrefConnect(conn);
+
+ xenUnifiedUnlock(priv);
return ret;
}
return -1;
}
+static void
+xenUnifiedDomainEventDispatchFunc(virConnectPtr conn,
+ virDomainEventPtr event,
+ virConnectDomainEventCallback cb,
+ void *cbopaque,
+ void *opaque)
+{
+ xenUnifiedPrivatePtr priv = opaque;
+
+ /*
+ * Release the lock while the callback is running so that
+ * we're re-entrant safe for callback work - the callback
+ * may want to invoke other virt functions & we have already
+ * protected the one piece of state we have - the callback
+ * list
+ */
+ xenUnifiedUnlock(priv);
+ virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+ xenUnifiedLock(priv);
+}
+
/**
* xenUnifiedDomainEventDispatch:
+ * @priv: the connection to dispatch events on
+ * @event: the event to dispatch
*
* Dispatch domain events to registered callbacks
*
+ * The caller must hold the lock in 'priv' before invoking
+ *
*/
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
virDomainEventPtr event)
{
- if (!priv || !priv->domainEventCallbacks)
+ if (!priv)
return;
- virDomainEventDispatch(event,
- priv->domainEventCallbacks,
- virDomainEventDispatchDefaultFunc,
- NULL);
+ priv->domainEventDispatching = 1;
+
+ if (priv->domainEventCallbacks) {
+ virDomainEventDispatch(event,
+ priv->domainEventCallbacks,
+ xenUnifiedDomainEventDispatchFunc,
+ priv);
+
+ /* Purge any deleted callbacks */
+ virDomainEventCallbackListPurgeMarked(priv->domainEventCallbacks);
+ }
+
virDomainEventFree(event);
+
+ priv->domainEventDispatching = 0;
+}
+
+void xenUnifiedLock(xenUnifiedPrivatePtr priv)
+{
+ virMutexLock(&priv->lock);
+}
+
+void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
+{
+ virMutexUnlock(&priv->lock);
}
* low-level drivers access parts of this structure.
*/
struct _xenUnifiedPrivate {
+ virMutex lock;
+
+ /* These initial vars are initialized in Open method
+ * and readonly thereafter, so can be used without
+ * holding the lock
+ */
virCapsPtr caps;
int handle; /* Xen hypervisor handle */
struct sockaddr_un addr_un; /* the unix address */
struct sockaddr_in addr_in; /* the inet address */
- struct xs_handle *xshandle; /* handle to talk to the xenstore */
-
- int proxy; /* fd of proxy. */
-
/* Keep track of the drivers which opened. We keep a yes/no flag
* here for each driver, corresponding to the array drivers in
* xen_unified.c.
*/
int opened[XEN_UNIFIED_NR_DRIVERS];
+
+ /*
+ * Everything from this point onwards must be protected
+ * by the lock when used
+ */
+
+ struct xs_handle *xshandle; /* handle to talk to the xenstore */
+
+ int proxy; /* fd of proxy. */
+
+
/* A list of xenstore watches */
xenStoreWatchListPtr xsWatchList;
int xsWatch;
/* A list of active domain name/uuids */
xenUnifiedDomainInfoListPtr activeDomainList;
+ /* NUMA topology info cache */
+ int nbNodeCells;
+ int nbNodeCpus;
/* An list of callbacks */
virDomainEventCallbackListPtr domainEventCallbacks;
+ int domainEventDispatching;
/* Location of config files, either /etc
* or /var/lib/xen */
typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
-
-int xenNbCells(virConnectPtr conn);
-int xenNbCpus(virConnectPtr conn);
char *xenDomainUsedCpus(virDomainPtr dom);
void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
virDomainEventPtr event);
unsigned long xenUnifiedVersion(void);
+#ifndef PROXY
+void xenUnifiedLock(xenUnifiedPrivatePtr priv);
+void xenUnifiedUnlock(xenUnifiedPrivatePtr priv);
+#else
+#define xenUnifiedLock(p) do {} while(0)
+#define xenUnifiedUnlock(p) do {} while(0)
+#endif
+
#endif /* __VIR_XEN_UNIFIED_H__ */
int hvm,
int xendConfigVersion)
{
+#ifndef PROXY
+ xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
const char *tmp;
virDomainGraphicsDefPtr graphics = NULL;
if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
tmp[0] == '1') {
/* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
- int port = xenStoreDomainGetVNCPort(conn, def->id);
+ int port;
const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
+ xenUnifiedLock(priv);
+ port = xenStoreDomainGetVNCPort(conn, def->id);
+ xenUnifiedUnlock(priv);
+
if (VIR_ALLOC(graphics) < 0)
goto no_memory;
virDomainDefPtr def,
const struct sexpr *root)
{
+#ifndef PROXY
+ xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
virDomainGraphicsDefPtr graphics = NULL;
const struct sexpr *cur, *node;
const char *tmp;
!(graphics->data.sdl.xauth = strdup(xauth)))
goto no_memory;
} else {
- int port = xenStoreDomainGetVNCPort(conn, def->id);
- if (port == -1) {
- // Didn't find port entry in xenstore
- port = sexpr_int(node, "device/vfb/vncdisplay");
- }
+ int port;
const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");;
const char *keymap = sexpr_node(node, "device/vfb/keymap");
const char *unused = sexpr_node(node, "device/vfb/vncunused");
+ xenUnifiedLock(priv);
+ port = xenStoreDomainGetVNCPort(conn, def->id);
+ xenUnifiedUnlock(priv);
+
+ if (port == -1) {
+ // Didn't find port entry in xenstore
+ port = sexpr_int(node, "device/vfb/vncdisplay");
+ }
+
if ((unused && STREQ(unused, "1")) || port == -1) {
graphics->data.vnc.autoport = 1;
port = -1;
int xendConfigVersion,
const char *cpus)
{
+#ifndef PROXY
+ xenUnifiedPrivatePtr priv = conn->privateData;
+#endif
const char *tmp;
virDomainDefPtr def;
int hvm = 0;
goto error;
/* Character device config */
+ xenUnifiedLock(priv);
tty = xenStoreDomainGetConsolePath(conn, def->id);
+ xenUnifiedUnlock(priv);
if (hvm) {
tmp = sexpr_node(root, "domain/image/hvm/serial");
if (tmp && STRNEQ(tmp, "none")) {
char *ref,
int ref_len)
{
+ xenUnifiedPrivatePtr priv = domain->conn->privateData;
char *xref;
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
strcpy(class, "vbd");
if (dev->data.disk->dst == NULL)
return -1;
+ xenUnifiedLock(priv);
xref = xenStoreDomainGetDiskID(domain->conn, domain->id,
dev->data.disk->dst);
+ xenUnifiedUnlock(priv);
if (xref == NULL)
return -1;
strcpy(class, "vif");
+ xenUnifiedLock(priv);
xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
mac);
+ xenUnifiedUnlock(priv);
if (xref == NULL)
return -1;
return ret;
}
+
+/*
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
int
xenXMConfigCacheRemoveFile(virConnectPtr conn,
const char *filename)
}
+/*
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
int
xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename)
{
}
/* This method is called by various methods to scan /etc/xen
- (or whatever directory was set by LIBVIRT_XM_CONFIG_DIR
- environment variable) and process any domain configs. It
- has rate-limited so never rescans more frequently than
- once every X seconds */
+ * (or whatever directory was set by LIBVIRT_XM_CONFIG_DIR
+ * environment variable) and process any domain configs. It
+ * has rate-limited so never rescans more frequently than
+ * once every X seconds
+ *
+ * Caller must hold the lock on 'conn->privateData' before
+ * calling this funtion
+ */
int xenXMConfigCacheRefresh (virConnectPtr conn) {
xenUnifiedPrivatePtr priv = conn->privateData;
DIR *dh;
return (-1);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto error;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto error;
memset(info, 0, sizeof(virDomainInfo));
info->maxMem = entry->def->maxmem;
info->state = VIR_DOMAIN_SHUTOFF;
info->cpuTime = 0;
+ xenUnifiedUnlock(priv);
return (0);
+error:
+ xenUnifiedUnlock(priv);
+ return -1;
}
#define MAX_VFB 1024
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
+ char *ret = NULL;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
return (NULL);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (NULL);
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (NULL);
+ goto cleanup;
+
+ ret = virDomainDefFormat(domain->conn, entry->def, flags);
- return virDomainDefFormat(domain->conn, entry->def, flags);
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
}
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
+ int ret = -1;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
return (-1);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto cleanup;
entry->def->memory = memory;
if (entry->def->memory > entry->def->maxmem)
* in-memory representation of the config file. I say not!
*/
if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
- return (-1);
+ goto cleanup;
+ ret = 0;
- return (0);
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
}
/*
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
+ int ret = -1;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
return (-1);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto cleanup;
entry->def->maxmem = memory;
if (entry->def->memory > entry->def->maxmem)
* in-memory representation of the config file. I say not!
*/
if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
- return (-1);
+ goto cleanup;
+ ret = 0;
- return (0);
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
}
/*
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
+ unsigned long ret = 0;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
- return (-1);
+ return (0);
}
if (domain->id != -1)
- return (-1);
+ return (0);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto cleanup;
+
+ ret = entry->def->maxmem;
- return entry->def->maxmem;
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
}
/*
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
+ int ret = -1;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
return (-1);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto cleanup;
entry->def->vcpus = vcpus;
* in-memory representation of the config file. I say not!
*/
if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0)
- return (-1);
+ goto cleanup;
+ ret = 0;
- return (0);
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
}
/**
}
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) {
xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("virHashLookup"));
- return -1;
+ goto cleanup;
}
if (!(entry = virHashLookup(priv->configCache, filename))) {
xenXMError (domain->conn, VIR_ERR_INTERNAL_ERROR,
"%s", _("can't retrieve config file for domain"));
- return -1;
+ goto cleanup;
}
/* from bit map, build character string of mapped CPU numbers */
if (virBufferError(&mapbuf)) {
virReportOOMError(domain->conn);
- return -1;
+ goto cleanup;
}
mapstr = virBufferContentAndReset(&mapbuf);
cleanup:
VIR_FREE(mapstr);
VIR_FREE(cpuset);
+ xenUnifiedUnlock(priv);
return (ret);
}
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
- virDomainPtr ret;
+ virDomainPtr ret = NULL;
if (!VIR_IS_CONNECT(conn)) {
xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
}
priv = conn->privateData;
+ xenUnifiedLock(priv);
#ifndef WITH_XEN_INOTIFY
if (xenXMConfigCacheRefresh (conn) < 0)
- return (NULL);
+ goto cleanup;
#endif
if (!(filename = virHashLookup(priv->nameConfigMap, domname)))
- return (NULL);
+ goto cleanup;
- if (!(entry = virHashLookup(priv->configCache, filename))) {
- return (NULL);
- }
+ if (!(entry = virHashLookup(priv->configCache, filename)))
+ goto cleanup;
- if (!(ret = virGetDomain(conn, domname, entry->def->uuid))) {
- return (NULL);
- }
+ if (!(ret = virGetDomain(conn, domname, entry->def->uuid)))
+ goto cleanup;
/* Ensure its marked inactive, because may be cached
handle to a previously active domain */
ret->id = -1;
+cleanup:
+ xenUnifiedUnlock(priv);
return (ret);
}
const unsigned char *uuid) {
xenUnifiedPrivatePtr priv;
xenXMConfCachePtr entry;
- virDomainPtr ret;
+ virDomainPtr ret = NULL;
if (!VIR_IS_CONNECT(conn)) {
xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
}
priv = conn->privateData;
+ xenUnifiedLock(priv);
#ifndef WITH_XEN_INOTIFY
if (xenXMConfigCacheRefresh (conn) < 0)
- return (NULL);
+ goto cleanup;
#endif
- if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID, (const void *)uuid))) {
- return (NULL);
- }
+ if (!(entry = virHashSearch(priv->configCache, xenXMDomainSearchForUUID, (const void *)uuid)))
+ goto cleanup;
- if (!(ret = virGetDomain(conn, entry->def->name, uuid))) {
- return (NULL);
- }
+ if (!(ret = virGetDomain(conn, entry->def->name, uuid)))
+ goto cleanup;
/* Ensure its marked inactive, because may be cached
handle to a previously active domain */
ret->id = -1;
+cleanup:
+ xenUnifiedUnlock(priv);
return (ret);
}
*/
int xenXMDomainCreate(virDomainPtr domain) {
char *sexpr;
- int ret;
+ int ret = -1;
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
if (domain->id != -1)
return (-1);
+ xenUnifiedLock(priv);
+
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto error;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto error;
if (!(sexpr = xenDaemonFormatSxpr(domain->conn, entry->def, priv->xendConfigVersion))) {
xenXMError(domain->conn, VIR_ERR_XML_ERROR,
"%s", _("failed to build sexpr"));
- return (-1);
+ goto error;
}
ret = xenDaemonDomainCreateXML(domain->conn, sexpr);
VIR_FREE(sexpr);
- if (ret != 0) {
- return (-1);
- }
+ if (ret != 0)
+ goto error;
if ((ret = xenDaemonDomainLookupByName_ids(domain->conn, domain->name,
- entry->def->uuid)) < 0) {
- return (-1);
- }
+ entry->def->uuid)) < 0)
+ goto error;
domain->id = ret;
if ((ret = xend_wait_for_devices(domain->conn, domain->name)) < 0)
- goto cleanup;
+ goto error;
if ((ret = xenDaemonDomainResume(domain)) < 0)
- goto cleanup;
+ goto error;
+ xenUnifiedUnlock(priv);
return (0);
- cleanup:
+ error:
if (domain->id != -1) {
xenDaemonDomainDestroy(domain);
domain->id = -1;
}
+ xenUnifiedUnlock(priv);
return (-1);
}
if (conn->flags & VIR_CONNECT_RO)
return (NULL);
+ xenUnifiedLock(priv);
+
#ifndef WITH_XEN_INOTIFY
- if (xenXMConfigCacheRefresh (conn) < 0)
+ if (xenXMConfigCacheRefresh (conn) < 0) {
+ xenUnifiedUnlock(priv);
return (NULL);
+ }
#endif
if (!(def = virDomainDefParseString(conn, priv->caps, xml,
- VIR_DOMAIN_XML_INACTIVE)))
+ VIR_DOMAIN_XML_INACTIVE))) {
+ xenUnifiedLock(priv);
return (NULL);
+ }
if (virHashLookup(priv->nameConfigMap, def->name)) {
/* domain exists, we will overwrite it */
goto error;
}
- if (!(ret = virGetDomain(conn, def->name, def->uuid)))
- return NULL;
-
- ret->id = -1;
+ if ((ret = virGetDomain(conn, def->name, def->uuid)))
+ ret->id = -1;
+ xenUnifiedUnlock(priv);
return (ret);
error:
VIR_FREE(entry);
virDomainDefFree(def);
+ xenUnifiedUnlock(priv);
return (NULL);
}
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
+ int ret = -1;
+
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return (-1);
priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return (-1);
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return (-1);
+ goto cleanup;
if (unlink(entry->filename) < 0)
- return (-1);
+ goto cleanup;
/* Remove the name -> filename mapping */
if (virHashRemoveEntry(priv->nameConfigMap, domain->name, NULL) < 0)
- return(-1);
+ goto cleanup;
/* Remove the config record itself */
if (virHashRemoveEntry(priv->configCache, entry->filename, xenXMConfigFree) < 0)
- return (-1);
+ goto cleanup;
- return (0);
+ ret = 0;
+
+cleanup:
+ xenUnifiedUnlock(priv);
+ return ret;
}
struct xenXMListIteratorContext {
int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) {
xenUnifiedPrivatePtr priv;
struct xenXMListIteratorContext ctx;
+ int ret = -1;
if (!VIR_IS_CONNECT(conn)) {
xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
}
priv = conn->privateData;
+ xenUnifiedLock(priv);
#ifndef WITH_XEN_INOTIFY
if (xenXMConfigCacheRefresh (conn) < 0)
- return (-1);
+ goto cleanup;
#endif
if (maxnames > virHashSize(priv->configCache))
ctx.names = names;
virHashForEach(priv->nameConfigMap, xenXMListIterator, &ctx);
- return (ctx.count);
+ ret = ctx.count;
+
+#ifndef WITH_XEN_INOTIFY
+cleanup:
+#endif
+ xenUnifiedUnlock(priv);
+ return ret;
}
/*
*/
int xenXMNumOfDefinedDomains(virConnectPtr conn) {
xenUnifiedPrivatePtr priv;
+ int ret = -1;
if (!VIR_IS_CONNECT(conn)) {
xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
}
priv = conn->privateData;
+ xenUnifiedLock(priv);
#ifndef WITH_XEN_INOTIFY
if (xenXMConfigCacheRefresh (conn) < 0)
- return (-1);
+ goto cleanup;
#endif
- return virHashSize(priv->nameConfigMap);
+ ret = virHashSize(priv->nameConfigMap);
+
+#ifndef WITH_XEN_INOTIFY
+cleanup:
+#endif
+ xenUnifiedUnlock(priv);
+ return ret;
}
return -1;
}
- priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
-
if (domain->conn->flags & VIR_CONNECT_RO)
return -1;
if (domain->id != -1)
return -1;
+ priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+ xenUnifiedLock(priv);
+
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return -1;
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return -1;
+ goto cleanup;
def = entry->def;
if (!(dev = virDomainDeviceDefParse(domain->conn,
priv->caps,
entry->def,
xml, VIR_DOMAIN_XML_INACTIVE)))
- return -1;
+ goto cleanup;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
cleanup:
virDomainDeviceDefFree(dev);
-
+ xenUnifiedUnlock(priv);
return ret;
}
return -1;
}
- priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
if (domain->conn->flags & VIR_CONNECT_RO)
return -1;
if (domain->id != -1)
return -1;
+
+ priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
+ xenUnifiedLock(priv);
+
if (!(filename = virHashLookup(priv->nameConfigMap, domain->name)))
- return -1;
+ goto cleanup;
if (!(entry = virHashLookup(priv->configCache, filename)))
- return -1;
+ goto cleanup;
def = entry->def;
if (!(dev = virDomainDeviceDefParse(domain->conn,
priv->caps,
entry->def,
xml, VIR_DOMAIN_XML_INACTIVE)))
- return -1;
+ goto cleanup;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
cleanup:
virDomainDeviceDefFree(dev);
+ xenUnifiedUnlock(priv);
return (ret);
}
#include "xs_internal.h"
#include "xen_internal.h" /* for xenHypervisorCheckID */
-#ifdef __linux__
-#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
-#elif defined(__sun)
-#define XEN_HYPERVISOR_SOCKET "/dev/xen/privcmd"
-#else
-#error "unsupported platform"
-#endif
-
#ifndef PROXY
static char *xenStoreDomainGetOSType(virDomainPtr domain);
+static void xenStoreWatchEvent(int watch, int fd, int events, void *data);
+static void xenStoreWatchListFree(xenStoreWatchListPtr list);
struct xenUnifiedDriver xenStoreDriver = {
xenStoreOpen, /* open */
priv = (xenUnifiedPrivatePtr) conn->privateData;
+#ifndef PROXY
if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
DEBUG0("Warning, could not remove @introduceDomain watch");
/* not fatal */
xenStoreWatchListFree(priv->xsWatchList);
priv->xsWatchList = NULL;
-#ifndef PROXY
xenUnifiedDomainInfoListFree(priv->activeDomainList);
priv->activeDomainList = NULL;
#endif
{
char *tmp;
unsigned long ret = 0;
+ xenUnifiedPrivatePtr priv;
if (!VIR_IS_CONNECTED_DOMAIN(domain))
return (ret);
if (domain->id == -1)
return(-1);
+ priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
tmp = virDomainDoStoreQuery(domain->conn, domain->id, "memory/target");
if (tmp != NULL) {
ret = (unsigned long) atol(tmp);
- free(tmp);
+ VIR_FREE(tmp);
}
+ xenUnifiedUnlock(priv);
return(ret);
}
}
priv = (xenUnifiedPrivatePtr) conn->privateData;
+
+ xenUnifiedLock(priv);
if (priv->xshandle == NULL)
- return(-1);
+ goto error;
idlist = xs_directory (priv->xshandle, 0, "/local/domain", &num);
if (idlist == NULL)
- return(-1);
+ goto error;
for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
id = strtol(idlist[i], &endptr, 10);
ids[ret++] = (int) id;
}
free(idlist);
+ xenUnifiedUnlock(priv);
return(ret);
+
+error:
+ xenUnifiedUnlock(priv);
+ return -1;
}
/**
int
xenStoreDomainShutdown(virDomainPtr domain)
{
+ int ret;
+ xenUnifiedPrivatePtr priv;
+
if ((domain == NULL) || (domain->conn == NULL)) {
virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
* this is very hackish, the domU kernel probes for a special
* node in the xenstore and launch the shutdown command if found.
*/
- return(virDomainDoStoreWrite(domain, "control/shutdown", "poweroff"));
+ priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
+ ret = virDomainDoStoreWrite(domain, "control/shutdown", "poweroff");
+ xenUnifiedUnlock(priv);
+ return ret;
}
/**
int
xenStoreDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
{
+ int ret;
+ xenUnifiedPrivatePtr priv;
+
if ((domain == NULL) || (domain->conn == NULL)) {
virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
* this is very hackish, the domU kernel probes for a special
* node in the xenstore and launch the shutdown command if found.
*/
- return(virDomainDoStoreWrite(domain, "control/shutdown", "reboot"));
+ priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
+ ret = virDomainDoStoreWrite(domain, "control/shutdown", "reboot");
+ xenUnifiedUnlock(priv);
+ return ret;
}
/*
vm = virDomainGetVM(domain);
if (vm) {
+ xenUnifiedPrivatePtr priv = domain->conn->privateData;
+ xenUnifiedLock(priv);
str = virDomainGetVMInfo(domain, vm, "image/ostype");
- free(vm);
+ xenUnifiedUnlock(priv);
+ VIR_FREE(vm);
}
return (str);
* Return the port number on which the domain is listening for VNC
* connections.
*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
* Returns the port number, -1 in case of error
*/
int xenStoreDomainGetVNCPort(virConnectPtr conn, int domid) {
* Returns the path to the serial console. It is the callers
* responsibilty to free() the return string. Returns NULL
* on error
+ *
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
*/
char * xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
return virDomainDoStoreQuery(conn, domid, "console/tty");
*
* Get the type of domain operation system.
*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
* Returns the new string or NULL in case of error, the string must be
* freed by the caller.
*/
* Get the reference (i.e. the string number) for the device on that domain
* which uses the given mac address
*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
* Returns the new string or NULL in case of error, the string must be
* freed by the caller.
*/
* Get the reference (i.e. the string number) for the device on that domain
* which uses the given virtual block device name
*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ *
* Returns the new string or NULL in case of error, the string must be
* freed by the caller.
*/
return (NULL);
}
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
char *xenStoreDomainGetName(virConnectPtr conn,
int id) {
char prop[200];
}
#ifndef PROXY
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
int xenStoreDomainGetUUID(virConnectPtr conn,
int id,
unsigned char *uuid) {
return ret;
}
-#endif //PROXY
-void xenStoreWatchListFree(xenStoreWatchListPtr list)
+static void
+xenStoreWatchListFree(xenStoreWatchListPtr list)
{
int i;
for (i=0; i<list->count; i++) {
VIR_FREE(list);
}
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
int xenStoreAddWatch(virConnectPtr conn,
const char *path,
const char *token,
return xs_watch(priv->xshandle, watch->path, watch->token);
}
+/*
+ * The caller must hold the lock on the privateData
+ * associated with the 'conn' parameter.
+ */
int xenStoreRemoveWatch(virConnectPtr conn,
const char *path,
const char *token)
; /* Failure to reduce memory allocation isn't fatal */
}
list->count--;
-#ifndef PROXY
virUnrefConnect(conn);
-#endif
return 0;
}
}
return -1;
}
-xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
- const char *path,
- const char *token)
+static xenStoreWatchPtr
+xenStoreFindWatch(xenStoreWatchListPtr list,
+ const char *path,
+ const char *token)
{
int i;
for (i = 0 ; i < list->count ; i++)
return NULL;
}
-void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
- int fd ATTRIBUTE_UNUSED,
- int events ATTRIBUTE_UNUSED,
- void *data)
+static void
+xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
+ int fd ATTRIBUTE_UNUSED,
+ int events ATTRIBUTE_UNUSED,
+ void *data)
{
char **event;
char *path;
virConnectPtr conn = data;
xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
if(!priv) return;
- if(!priv->xshandle) return;
+
+ xenUnifiedLock(priv);
+
+ if(!priv->xshandle)
+ goto cleanup;
event = xs_read_watch(priv->xshandle, &stringCount);
if (!event)
- return;
+ goto cleanup;
path = event[XS_WATCH_PATH];
token = event[XS_WATCH_TOKEN];
if( sw )
sw->cb(conn, path, token, sw->opaque);
VIR_FREE(event);
+
+cleanup:
+ xenUnifiedUnlock(priv);
}
-#ifndef PROXY
-/* The domain callback for the @introduceDomain watch */
+
+/*
+ * The domain callback for the @introduceDomain watch
+ *
+ * The lock on 'priv' is held when calling this
+ */
int xenStoreDomainIntroduced(virConnectPtr conn,
const char *path ATTRIBUTE_UNUSED,
const char *token ATTRIBUTE_UNUSED,
return 0;
}
-/* The domain callback for the @destroyDomain watch */
+/*
+ * The domain callback for the @destroyDomain watch
+ *
+ * The lock on 'priv' is held when calling this
+ */
int xenStoreDomainReleased(virConnectPtr conn,
const char *path ATTRIBUTE_UNUSED,
const char *token ATTRIBUTE_UNUSED,
typedef xenStoreWatchList *xenStoreWatchListPtr;
-void xenStoreWatchListFree(xenStoreWatchListPtr head);
-
int xenStoreAddWatch(virConnectPtr conn,
const char *path,
const char *token,
int xenStoreRemoveWatch(virConnectPtr conn,
const char *path,
const char *token);
-xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
- const char *path,
- const char *token);
-
-void xenStoreWatchEvent(int watch, int fd, int events, void *data);
/* domain events */
int xenStoreDomainIntroduced(virConnectPtr conn,