Make xen driver threadsafe

This commit is contained in:
Daniel P. Berrange 2009-01-21 18:11:14 +00:00
parent 20921cc284
commit e52d74e536
10 changed files with 558 additions and 307 deletions

View File

@ -1,3 +1,11 @@
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

View File

@ -33,7 +33,7 @@
#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);
@ -149,19 +149,18 @@ virProxyForkServer(void)
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.
@ -226,32 +225,33 @@ retry:
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);
}
@ -260,14 +260,13 @@ virProxyCloseClientSocket(int fd) {
* @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))
@ -277,17 +276,14 @@ retry:
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",
VIR_DEBUG("read %d bytes from socket %d\n",
ret, fd);
return(ret);
}
@ -309,11 +305,10 @@ virProxyWriteClientSocket(int fd, const char *data, int len) {
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",
VIR_DEBUG("wrote %d bytes to socket %d\n",
len, fd);
return(0);
@ -347,12 +342,9 @@ xenProxyClose(virConnectPtr conn)
return -1;
}
/* Fail silently. */
if (priv->proxy == -1)
return -1;
virProxyCloseClientSocket (priv->proxy);
priv->proxy = -1;
xenUnifiedLock(priv);
virProxyCloseSocket (priv);
xenUnifiedUnlock(priv);
return 0;
}
@ -376,9 +368,11 @@ xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
return -1;
}
xenUnifiedLock(priv);
/* Fail silently. */
if (priv->proxy == -1)
return -1;
goto error;
/*
* normal communication serial numbers are in 0..4095
@ -390,62 +384,69 @@ xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
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,
virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
_("Communication error with proxy: got %d bytes of %d\n"),
ret, (int) sizeof(virProxyPacket));
xenProxyClose(conn);
return(-1);
goto error;
}
res = request;
if (res->len != sizeof(virProxyPacket)) {
fprintf(stderr,
virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
_("Communication error with proxy: expected %d bytes got %d\n"),
(int) sizeof(virProxyPacket), res->len);
xenProxyClose(conn);
return(-1);
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,
virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
_("Communication error with proxy: got %d bytes of %d\n"),
ret, (int) sizeof(virProxyPacket));
xenProxyClose(conn);
return(-1);
goto error;
}
res = (virProxyPacketPtr) answer;
if ((res->len < sizeof(virProxyPacket)) ||
(res->len > sizeof(virProxyFullPacket))) {
fprintf(stderr,
virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
_("Communication error with proxy: got %d bytes packet\n"),
res->len);
xenProxyClose(conn);
return(-1);
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,
virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
_("Communication error with proxy: got %d bytes of %d\n"),
ret, (int) sizeof(virProxyPacket));
xenProxyClose(conn);
return(-1);
goto error;
}
}
}
@ -454,17 +455,22 @@ retry:
*/
if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
(res->len < sizeof(virProxyPacket))) {
fprintf(stderr, "%s",
virProxyError(conn, VIR_ERR_INTERNAL_ERROR,
_("Communication error with proxy: malformed packet\n"));
xenProxyClose(conn);
return(-1);
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;
}
/**
@ -507,7 +513,6 @@ xenProxyOpen(virConnectPtr conn,
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);
@ -549,7 +554,6 @@ xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer)
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, NULL, 0);
if (ret < 0) {
xenProxyClose(conn);
return(-1);
}
*hvVer = req.data.larg;
@ -587,7 +591,6 @@ xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
xenProxyClose(conn);
return(-1);
}
nb = ans.data.arg;
@ -627,7 +630,6 @@ xenProxyNumOfDomains(virConnectPtr conn)
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, NULL, 0);
if (ret < 0) {
xenProxyClose(conn);
return(-1);
}
return(req.data.arg);
@ -659,7 +661,6 @@ xenProxyDomainGetDomMaxMemory(virConnectPtr conn, int id)
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, NULL, 0);
if (ret < 0) {
xenProxyClose(conn);
return(0);
}
return(req.data.larg);
@ -724,7 +725,6 @@ xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
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)) {
@ -769,7 +769,6 @@ xenProxyLookupByID(virConnectPtr conn, int id)
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
xenProxyClose(conn);
return(NULL);
}
if (ans.data.arg == -1) {
@ -814,7 +813,6 @@ xenProxyLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
ret = xenProxyCommand(conn, (virProxyPacketPtr) &req, &req, 0);
if (ret < 0) {
xenProxyClose(conn);
return(NULL);
}
if (req.data.arg == -1) {
@ -861,7 +859,6 @@ xenProxyLookupByName(virConnectPtr conn, const char *name)
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) {
@ -901,7 +898,6 @@ xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
xenProxyClose(conn);
return(-1);
}
if (ans.data.arg == -1) {
@ -941,7 +937,6 @@ xenProxyGetCapabilities (virConnectPtr conn)
req.len = sizeof(req);
ret = xenProxyCommand(conn, &req, &ans, 0);
if (ret < 0) {
xenProxyClose(conn);
return NULL;
}
if (ans.data.arg == -1)
@ -995,7 +990,6 @@ xenProxyDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
req.len = sizeof(req);
ret = xenProxyCommand(domain->conn, &req, &ans, 0);
if (ret < 0) {
xenProxyClose(domain->conn);
return(NULL);
}
if (ans.len <= sizeof(virProxyPacket)) {
@ -1044,7 +1038,6 @@ xenProxyDomainGetOSType(virDomainPtr domain)
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)) {

View File

@ -298,25 +298,27 @@ xenInotifyEvent(int watch ATTRIBUTE_UNUSED,
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;
@ -340,14 +342,14 @@ reread:
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,
@ -363,6 +365,9 @@ reread:
}
}
cleanup:
xenUnifiedUnlock(priv);
}
/**
@ -458,7 +463,7 @@ xenInotifyOpen(virConnectPtr conn ATTRIBUTE_UNUSED,
DEBUG0("Failed to add inotify handle, disabling events");
}
conn->refs++;
virConnectRef(conn);
return 0;
}

View File

@ -1337,9 +1337,14 @@ xenHypervisorDomainBlockStats (virDomainPtr dom,
{
#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",
@ -2756,8 +2761,10 @@ xenHypervisorLookupDomainByID(virConnectPtr conn,
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));
@ -2824,7 +2831,10 @@ xenHypervisorLookupDomainByUUID(virConnectPtr conn,
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);
@ -3057,7 +3067,6 @@ xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *free
xen_op_v2_sys op_sys;
int i, j, ret;
xenUnifiedPrivatePtr priv;
int nbNodeCells;
if (conn == NULL) {
virXenErrorFunc (conn, VIR_ERR_INVALID_ARG, __FUNCTION__,
@ -3065,14 +3074,15 @@ xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *free
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;
@ -3087,7 +3097,6 @@ xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *free
return -1;
}
priv = (xenUnifiedPrivatePtr) conn->privateData;
if (priv->handle < 0) {
virXenErrorFunc (conn, VIR_ERR_INTERNAL_ERROR, __FUNCTION__,
"priv->handle invalid", 0);
@ -3097,7 +3106,7 @@ xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *free
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) {

View File

@ -56,7 +56,7 @@ xenUnifiedDomainGetVcpus (virDomainPtr dom,
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,
@ -71,14 +71,6 @@ static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
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
@ -90,42 +82,19 @@ static int nbNodeCpus = -1;
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;
priv = conn->privateData;
priv->nbNodeCells = nodeInfo.nodes;
priv->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);
}
/**
* 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);
}
/**
* xenDomainUsedCpus:
@ -141,7 +110,7 @@ char *
xenDomainUsedCpus(virDomainPtr dom)
{
char *res = NULL;
int nb_cpu, ncpus;
int ncpus;
int nb_vcpu;
char *cpulist = NULL;
unsigned char *cpumap = NULL;
@ -150,12 +119,14 @@ xenDomainUsedCpus(virDomainPtr dom)
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)
@ -163,7 +134,7 @@ xenDomainUsedCpus(virDomainPtr dom)
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;
@ -175,19 +146,19 @@ xenDomainUsedCpus(virDomainPtr dom)
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:
@ -267,13 +238,22 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
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;
@ -344,6 +324,8 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
}
}
xenNumaInit(conn);
if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
DEBUG0("Failed to make capabilities");
goto fail;
@ -368,7 +350,9 @@ clean:
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;
}
@ -388,7 +372,8 @@ xenUnifiedClose (virConnectPtr conn)
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;
@ -497,17 +482,15 @@ xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
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
@ -1019,7 +1002,9 @@ xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
} 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);
@ -1362,11 +1347,14 @@ xenUnifiedDomainEventRegister (virConnectPtr conn,
void *opaque,
void (*freefunc)(void *))
{
int ret;
GET_PRIVATE (conn);
int ret;
xenUnifiedLock(priv);
if (priv->xsWatch == -1) {
xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
xenUnifiedUnlock(priv);
return -1;
}
@ -1376,6 +1364,7 @@ xenUnifiedDomainEventRegister (virConnectPtr conn,
if (ret == 0)
conn->refs++;
xenUnifiedUnlock(priv);
return (ret);
}
@ -1385,16 +1374,25 @@ xenUnifiedDomainEventDeregister (virConnectPtr conn,
{
int ret;
GET_PRIVATE (conn);
xenUnifiedLock(priv);
if (priv->xsWatch == -1) {
xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
xenUnifiedUnlock(priv);
return -1;
}
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;
}
@ -1585,21 +1583,66 @@ xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
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;
priv->domainEventDispatching = 1;
if (priv->domainEventCallbacks) {
virDomainEventDispatch(event,
priv->domainEventCallbacks,
virDomainEventDispatchDefaultFunc,
NULL);
virDomainEventFree(event);
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);
}

View File

@ -131,6 +131,12 @@ typedef xenUnifiedDomainInfoList *xenUnifiedDomainInfoListPtr;
* 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 */
@ -144,25 +150,36 @@ struct _xenUnifiedPrivate {
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 */
@ -188,9 +205,6 @@ struct _xenUnifiedPrivate {
typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
int xenNbCells(virConnectPtr conn);
int xenNbCpus(virConnectPtr conn);
char *xenDomainUsedCpus(virDomainPtr dom);
void xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr info);
@ -204,4 +218,12 @@ void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
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__ */

View File

@ -1941,18 +1941,25 @@ xenDaemonParseSxprGraphicsOld(virConnectPtr conn,
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;
@ -2017,6 +2024,9 @@ xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
virDomainDefPtr def,
const struct sexpr *root)
{
#ifndef PROXY
xenUnifiedPrivatePtr priv = conn->privateData;
#endif
virDomainGraphicsDefPtr graphics = NULL;
const struct sexpr *cur, *node;
const char *tmp;
@ -2048,16 +2058,21 @@ xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
!(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;
@ -2114,6 +2129,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
int xendConfigVersion,
const char *cpus)
{
#ifndef PROXY
xenUnifiedPrivatePtr priv = conn->privateData;
#endif
const char *tmp;
virDomainDefPtr def;
int hvm = 0;
@ -2333,7 +2351,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
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")) {
@ -5442,14 +5462,17 @@ virDomainXMLDevID(virDomainPtr domain,
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;
@ -5465,8 +5488,10 @@ virDomainXMLDevID(virDomainPtr domain,
strcpy(class, "vif");
xenUnifiedLock(priv);
xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
mac);
xenUnifiedUnlock(priv);
if (xref == NULL)
return -1;

View File

@ -347,6 +347,11 @@ xenXMConfigSaveFile(virConnectPtr conn, const char *filename, virDomainDefPtr de
return ret;
}
/*
* Caller must hold the lock on 'conn->privateData' before
* calling this funtion
*/
int
xenXMConfigCacheRemoveFile(virConnectPtr conn,
const char *filename)
@ -367,6 +372,10 @@ xenXMConfigCacheRemoveFile(virConnectPtr conn,
}
/*
* Caller must hold the lock on 'conn->privateData' before
* calling this funtion
*/
int
xenXMConfigCacheAddFile(virConnectPtr conn, const char *filename)
{
@ -460,10 +469,14 @@ 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;
@ -621,12 +634,13 @@ int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) {
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;
@ -635,8 +649,12 @@ int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) {
info->state = VIR_DOMAIN_SHUTOFF;
info->cpuTime = 0;
xenUnifiedUnlock(priv);
return (0);
error:
xenUnifiedUnlock(priv);
return -1;
}
#define MAX_VFB 1024
@ -1293,6 +1311,7 @@ char *xenXMDomainDumpXML(virDomainPtr domain, int flags) {
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,
@ -1303,14 +1322,19 @@ char *xenXMDomainDumpXML(virDomainPtr domain, int flags) {
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;
return virDomainDefFormat(domain->conn, entry->def, flags);
ret = virDomainDefFormat(domain->conn, entry->def, flags);
cleanup:
xenUnifiedUnlock(priv);
return ret;
}
@ -1321,6 +1345,7 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) {
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,
@ -1335,12 +1360,13 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) {
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)
@ -1350,9 +1376,12 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) {
* 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;
}
/*
@ -1362,6 +1391,7 @@ int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
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,
@ -1374,12 +1404,13 @@ int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
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)
@ -1389,9 +1420,12 @@ int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
* 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;
}
/*
@ -1401,24 +1435,30 @@ unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain) {
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;
return entry->def->maxmem;
ret = entry->def->maxmem;
cleanup:
xenUnifiedUnlock(priv);
return ret;
}
/*
@ -1428,6 +1468,7 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
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,
@ -1440,12 +1481,13 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
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;
@ -1453,9 +1495,12 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int 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;
}
/**
@ -1501,15 +1546,16 @@ int xenXMDomainPinVcpu(virDomainPtr domain,
}
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 */
@ -1527,7 +1573,7 @@ int xenXMDomainPinVcpu(virDomainPtr domain,
if (virBufferError(&mapbuf)) {
virReportOOMError(domain->conn);
return -1;
goto cleanup;
}
mapstr = virBufferContentAndReset(&mapbuf);
@ -1554,6 +1600,7 @@ int xenXMDomainPinVcpu(virDomainPtr domain,
cleanup:
VIR_FREE(mapstr);
VIR_FREE(cpuset);
xenUnifiedUnlock(priv);
return (ret);
}
@ -1564,7 +1611,7 @@ virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname) {
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
virDomainPtr ret;
virDomainPtr ret = NULL;
if (!VIR_IS_CONNECT(conn)) {
xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@ -1576,27 +1623,28 @@ virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname) {
}
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);
}
@ -1621,7 +1669,7 @@ virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
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__);
@ -1633,24 +1681,25 @@ virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
}
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);
}
@ -1660,7 +1709,7 @@ virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
*/
int xenXMDomainCreate(virDomainPtr domain) {
char *sexpr;
int ret;
int ret = -1;
xenUnifiedPrivatePtr priv;
const char *filename;
xenXMConfCachePtr entry;
@ -1670,43 +1719,45 @@ int xenXMDomainCreate(virDomainPtr domain) {
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);
}
@ -2290,14 +2341,20 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) {
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 */
@ -2375,16 +2432,16 @@ virDomainPtr xenXMDomainDefineXML(virConnectPtr conn, const char *xml) {
goto error;
}
if (!(ret = virGetDomain(conn, def->name, def->uuid)))
return NULL;
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);
}
@ -2395,6 +2452,8 @@ int xenXMDomainUndefine(virDomainPtr domain) {
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__);
@ -2407,25 +2466,30 @@ int xenXMDomainUndefine(virDomainPtr domain) {
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 {
@ -2459,6 +2523,7 @@ static void xenXMListIterator(const void *payload ATTRIBUTE_UNUSED, const char *
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__);
@ -2466,10 +2531,11 @@ int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames
}
priv = conn->privateData;
xenUnifiedLock(priv);
#ifndef WITH_XEN_INOTIFY
if (xenXMConfigCacheRefresh (conn) < 0)
return (-1);
goto cleanup;
#endif
if (maxnames > virHashSize(priv->configCache))
@ -2481,7 +2547,13 @@ int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames
ctx.names = names;
virHashForEach(priv->nameConfigMap, xenXMListIterator, &ctx);
return (ctx.count);
ret = ctx.count;
#ifndef WITH_XEN_INOTIFY
cleanup:
#endif
xenUnifiedUnlock(priv);
return ret;
}
/*
@ -2490,6 +2562,7 @@ int xenXMListDefinedDomains(virConnectPtr conn, char **const names, int maxnames
*/
int xenXMNumOfDefinedDomains(virConnectPtr conn) {
xenUnifiedPrivatePtr priv;
int ret = -1;
if (!VIR_IS_CONNECT(conn)) {
xenXMError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@ -2497,13 +2570,20 @@ int xenXMNumOfDefinedDomains(virConnectPtr conn) {
}
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;
}
@ -2532,24 +2612,25 @@ xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) {
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:
@ -2592,7 +2673,7 @@ xenXMDomainAttachDevice(virDomainPtr domain, const char *xml) {
cleanup:
virDomainDeviceDefFree(dev);
xenUnifiedUnlock(priv);
return ret;
}
@ -2622,23 +2703,26 @@ xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
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:
@ -2690,6 +2774,7 @@ xenXMDomainDetachDevice(virDomainPtr domain, const char *xml) {
cleanup:
virDomainDeviceDefFree(dev);
xenUnifiedUnlock(priv);
return (ret);
}

View File

@ -37,16 +37,10 @@
#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 */
@ -374,6 +368,7 @@ xenStoreClose(virConnectPtr conn)
priv = (xenUnifiedPrivatePtr) conn->privateData;
#ifndef PROXY
if (xenStoreRemoveWatch(conn, "@introduceDomain", "introduceDomain") < 0) {
DEBUG0("Warning, could not remove @introduceDomain watch");
/* not fatal */
@ -386,7 +381,6 @@ xenStoreClose(virConnectPtr conn)
xenStoreWatchListFree(priv->xsWatchList);
priv->xsWatchList = NULL;
#ifndef PROXY
xenUnifiedDomainInfoListFree(priv->activeDomainList);
priv->activeDomainList = NULL;
#endif
@ -518,17 +512,21 @@ xenStoreDomainGetMaxMemory(virDomainPtr domain)
{
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);
}
@ -591,12 +589,14 @@ xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
}
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);
@ -611,7 +611,12 @@ xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
ids[ret++] = (int) id;
}
free(idlist);
xenUnifiedUnlock(priv);
return(ret);
error:
xenUnifiedUnlock(priv);
return -1;
}
/**
@ -696,6 +701,9 @@ done:
int
xenStoreDomainShutdown(virDomainPtr domain)
{
int ret;
xenUnifiedPrivatePtr priv;
if ((domain == NULL) || (domain->conn == NULL)) {
virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
@ -707,7 +715,11 @@ xenStoreDomainShutdown(virDomainPtr domain)
* 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;
}
/**
@ -724,6 +736,9 @@ xenStoreDomainShutdown(virDomainPtr domain)
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__);
@ -735,7 +750,11 @@ xenStoreDomainReboot(virDomainPtr domain, unsigned int flags ATTRIBUTE_UNUSED)
* 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;
}
/*
@ -759,8 +778,11 @@ xenStoreDomainGetOSType(virDomainPtr domain) {
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);
@ -775,6 +797,9 @@ xenStoreDomainGetOSType(virDomainPtr domain) {
* 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) {
@ -803,6 +828,9 @@ 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");
@ -816,6 +844,9 @@ char * xenStoreDomainGetConsolePath(virConnectPtr conn, int domid) {
*
* 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.
*/
@ -860,6 +891,9 @@ xenStoreDomainGetOSTypeID(virConnectPtr conn, int id) {
* 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.
*/
@ -912,6 +946,9 @@ xenStoreDomainGetNetworkID(virConnectPtr conn, int id, const char *mac) {
* 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.
*/
@ -975,6 +1012,10 @@ xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev) {
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];
@ -991,6 +1032,10 @@ char *xenStoreDomainGetName(virConnectPtr conn,
}
#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) {
@ -1017,9 +1062,9 @@ int xenStoreDomainGetUUID(virConnectPtr conn,
return ret;
}
#endif //PROXY
void xenStoreWatchListFree(xenStoreWatchListPtr list)
static void
xenStoreWatchListFree(xenStoreWatchListPtr list)
{
int i;
for (i=0; i<list->count; i++) {
@ -1030,6 +1075,10 @@ void xenStoreWatchListFree(xenStoreWatchListPtr list)
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,
@ -1082,6 +1131,10 @@ int xenStoreAddWatch(virConnectPtr conn,
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)
@ -1124,16 +1177,15 @@ int xenStoreRemoveWatch(virConnectPtr conn,
; /* Failure to reduce memory allocation isn't fatal */
}
list->count--;
#ifndef PROXY
virUnrefConnect(conn);
#endif
return 0;
}
}
return -1;
}
xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
static xenStoreWatchPtr
xenStoreFindWatch(xenStoreWatchListPtr list,
const char *path,
const char *token)
{
@ -1146,7 +1198,8 @@ xenStoreWatchPtr xenStoreFindWatch(xenStoreWatchListPtr list,
return NULL;
}
void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
static void
xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
int fd ATTRIBUTE_UNUSED,
int events ATTRIBUTE_UNUSED,
void *data)
@ -1160,11 +1213,15 @@ void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
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];
@ -1173,10 +1230,17 @@ void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED,
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,
@ -1251,7 +1315,11 @@ retry:
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,

View File

@ -78,8 +78,6 @@ typedef struct _xenStoreWatchList xenStoreWatchList;
typedef xenStoreWatchList *xenStoreWatchListPtr;
void xenStoreWatchListFree(xenStoreWatchListPtr head);
int xenStoreAddWatch(virConnectPtr conn,
const char *path,
const char *token,
@ -88,11 +86,6 @@ int xenStoreAddWatch(virConnectPtr conn,
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,