xen_driver.c 51.5 KB
Newer Older
1
/*
2
 * xen_driver.c: Unified Xen driver.
3
 *
4
 * Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
5 6 7 8 9 10
 *
 * See COPYING.LIB for the License of this software
 *
 * Richard W.M. Jones <rjones@redhat.com>
 */

11
#include <config.h>
12

13 14 15 16 17 18 19 20 21 22 23
/* Note:
 *
 * This driver provides a unified interface to the five
 * separate underlying Xen drivers (xen_internal, proxy_internal,
 * xend_internal, xs_internal and xm_internal).  Historically
 * the body of libvirt.c handled the five Xen drivers,
 * and contained Xen-specific code.
 */

#include <stdint.h>
#include <unistd.h>
24
#include <string.h>
25
#include <errno.h>
26 27
#include <sys/types.h>
#include <xen/dom0_ops.h>
28
#include <libxml/uri.h>
29

30
#include "virterror_internal.h"
31
#include "logging.h"
32
#include "datatypes.h"
33
#include "xen_driver.h"
34

35
#include "xen_hypervisor.h"
36 37 38 39
#include "proxy_internal.h"
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
40 41 42
#if WITH_XEN_INOTIFY
#include "xen_inotify.h"
#endif
43
#include "xml.h"
44
#include "util.h"
45
#include "memory.h"
46 47
#include "node_device_conf.h"
#include "pci.h"
48

49 50
#define VIR_FROM_THIS VIR_FROM_XEN

51 52
static int
xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
53 54 55 56 57 58
static int
xenUnifiedDomainGetMaxVcpus (virDomainPtr dom);
static int
xenUnifiedDomainGetVcpus (virDomainPtr dom,
                          virVcpuInfoPtr info, int maxinfo,
                          unsigned char *cpumaps, int maplen);
59

60
/* The five Xen drivers below us. */
D
Daniel P. Berrange 已提交
61
static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
62 63 64 65 66
    [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
    [XEN_UNIFIED_PROXY_OFFSET] = &xenProxyDriver,
    [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
    [XEN_UNIFIED_XS_OFFSET] = &xenStoreDriver,
    [XEN_UNIFIED_XM_OFFSET] = &xenXMDriver,
67 68 69
#if WITH_XEN_INOTIFY
    [XEN_UNIFIED_INOTIFY_OFFSET] = &xenInotifyDriver,
#endif
70 71
};

J
John Levon 已提交
72 73
static int inside_daemon;

74
#define xenUnifiedError(conn, code, fmt...)                                  \
75
        virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__,           \
76
                               __FUNCTION__, __LINE__, fmt)
77

78 79 80 81 82
/**
 * xenNumaInit:
 * @conn: pointer to the hypervisor connection
 *
 * Initializer for previous variables. We currently assume that
R
Richard W.M. Jones 已提交
83
 * the number of physical CPU and the number of NUMA cell is fixed
84 85 86 87 88
 * until reboot which might be false in future Xen implementations.
 */
static void
xenNumaInit(virConnectPtr conn) {
    virNodeInfo nodeInfo;
D
Daniel P. Berrange 已提交
89
    xenUnifiedPrivatePtr priv;
90 91 92 93 94 95
    int ret;

    ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
    if (ret < 0)
        return;

D
Daniel P. Berrange 已提交
96
    priv = conn->privateData;
97

D
Daniel P. Berrange 已提交
98 99
    priv->nbNodeCells = nodeInfo.nodes;
    priv->nbNodeCpus = nodeInfo.cpus;
100 101
}

D
Daniel P. Berrange 已提交
102

103 104 105 106 107 108 109 110 111 112 113 114 115 116
/**
 * xenDomainUsedCpus:
 * @dom: the domain
 *
 * Analyze which set of CPUs are used by the domain and
 * return a string providing the ranges.
 *
 * Returns the string which needs to be freed by the caller or
 *         NULL if the domain uses all CPU or in case of error.
 */
char *
xenDomainUsedCpus(virDomainPtr dom)
{
    char *res = NULL;
D
Daniel P. Berrange 已提交
117
    int ncpus;
118 119 120 121 122 123 124 125
    int nb_vcpu;
    char *cpulist = NULL;
    unsigned char *cpumap = NULL;
    size_t cpumaplen;
    int nb = 0;
    int n, m;
    virVcpuInfoPtr cpuinfo = NULL;
    virNodeInfo nodeinfo;
D
Daniel P. Berrange 已提交
126
    xenUnifiedPrivatePtr priv;
127 128 129 130

    if (!VIR_IS_CONNECTED_DOMAIN(dom))
        return (NULL);

D
Daniel P. Berrange 已提交
131 132 133
    priv = dom->conn->privateData;

    if (priv->nbNodeCpus <= 0)
134 135 136 137 138 139 140
        return(NULL);
    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
    if (nb_vcpu <= 0)
        return(NULL);
    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
        return(NULL);

D
Daniel P. Berrange 已提交
141
    if (VIR_ALLOC_N(cpulist, priv->nbNodeCpus) < 0)
142
        goto done;
143
    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
144 145
        goto done;
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
146 147
    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0)
148 149 150 151
        goto done;

    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
                                          cpumap, cpumaplen)) >= 0) {
152
        for (n = 0 ; n < ncpus ; n++) {
D
Daniel P. Berrange 已提交
153
            for (m = 0 ; m < priv->nbNodeCpus; m++) {
154 155 156 157 158
                if ((cpulist[m] == 0) &&
                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
                    cpulist[m] = 1;
                    nb++;
                    /* if all CPU are used just return NULL */
D
Daniel P. Berrange 已提交
159
                    if (nb == priv->nbNodeCpus)
160 161 162 163 164
                        goto done;

                }
            }
        }
D
Daniel P. Berrange 已提交
165
        res = virDomainCpuSetFormat(dom->conn, cpulist, priv->nbNodeCpus);
166 167 168
    }

done:
169 170 171
    VIR_FREE(cpulist);
    VIR_FREE(cpumap);
    VIR_FREE(cpuinfo);
172 173 174
    return(res);
}

J
John Levon 已提交
175 176 177
#ifdef WITH_LIBVIRTD

static int
178
xenInitialize (int privileged ATTRIBUTE_UNUSED)
J
John Levon 已提交
179 180 181 182 183 184 185 186 187 188 189
{
    inside_daemon = 1;
    return 0;
}

static virStateDriver state_driver = {
    .initialize = xenInitialize,
};

#endif

190 191 192 193 194 195 196 197 198 199 200
/*----- Dispatch functions. -----*/

/* These dispatch functions follow the model used historically
 * by libvirt.c -- trying each low-level Xen driver in turn
 * until one succeeds.  However since we know what low-level
 * drivers can perform which functions, it is probably better
 * in future to optimise these dispatch functions to just call
 * the single function (or small number of appropriate functions)
 * in the low level drivers directly.
 */

201
static int
202 203 204 205
xenUnifiedProbe (void)
{
#ifdef __linux__
    if (virFileExists("/proc/xen"))
206
        return 1;
207
#endif
208
#ifdef __sun
209 210 211
    FILE *fh;

    if (fh = fopen("/dev/xen/domcaps", "r")) {
212
        fclose(fh);
213
        return 1;
214 215
    }
#endif
216
    return 0;
217 218
}

219
static virDrvOpenStatus
220
xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
221
{
222
    int i, ret = VIR_DRV_OPEN_DECLINED;
223
    xenUnifiedPrivatePtr priv;
224
    virDomainEventCallbackListPtr cbList;
225

J
John Levon 已提交
226 227 228 229 230 231 232 233 234
#ifdef __sun
    /*
     * Only the libvirtd instance can open this driver.
     * Everything else falls back to the remote driver.
     */
    if (!inside_daemon)
        return VIR_DRV_OPEN_DECLINED;
#endif

235 236 237 238 239 240
    if (conn->uri == NULL) {
        if (!xenUnifiedProbe())
            return VIR_DRV_OPEN_DECLINED;

        conn->uri = xmlParseURI("xen:///");
        if (!conn->uri) {
J
Jim Meyering 已提交
241
            virReportOOMError (NULL);
242 243
            return VIR_DRV_OPEN_ERROR;
        }
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
    } else {
        if (conn->uri->scheme) {
            /* Decline any scheme which isn't "xen://" or "http://". */
            if (STRCASENEQ(conn->uri->scheme, "xen") &&
                STRCASENEQ(conn->uri->scheme, "http"))
                return VIR_DRV_OPEN_DECLINED;


            /* Return an error if the path isn't '' or '/' */
            if (conn->uri->path &&
                STRNEQ(conn->uri->path, "") &&
                STRNEQ(conn->uri->path, "/")) {
                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
                                _("unexpected Xen URI path '%s', try xen:///"),
                                conn->uri->path);
                return VIR_DRV_OPEN_ERROR;
            }
261

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
            /* Decline any xen:// URI with a server specified, allowing remote
             * driver to handle, but keep any http:/// URIs */
            if (STRCASEEQ(conn->uri->scheme, "xen") &&
                conn->uri->server)
                return VIR_DRV_OPEN_DECLINED;
        } else {
            /* Special case URI for Xen driver only:
             *
             * Treat a plain path as a Xen UNIX socket path, and give
             * error unless path is absolute
             */
            if (!conn->uri->path || conn->uri->path[0] != '/') {
                xenUnifiedError(NULL, VIR_ERR_INTERNAL_ERROR,
                                _("unexpected Xen URI path '%s', try ///var/lib/xen/xend-socket"),
                                NULLSTR(conn->uri->path));
                return VIR_DRV_OPEN_ERROR;
            }
        }
    }
281

282 283
    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */
284 285

    /* Allocate per-connection private data. */
286
    if (VIR_ALLOC(priv) < 0) {
J
Jim Meyering 已提交
287
        virReportOOMError (NULL);
288 289
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
290 291
    if (virMutexInit(&priv->lock) < 0) {
        xenUnifiedError (NULL, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
292
                         "%s", _("cannot initialise mutex"));
D
Daniel P. Berrange 已提交
293 294 295
        VIR_FREE(priv);
        return VIR_DRV_OPEN_ERROR;
    }
296

297 298
    /* Allocate callback list */
    if (VIR_ALLOC(cbList) < 0) {
J
Jim Meyering 已提交
299
        virReportOOMError (NULL);
D
Daniel P. Berrange 已提交
300 301
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
302 303
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
304 305
    conn->privateData = priv;

306 307
    priv->domainEventCallbacks = cbList;

308 309 310 311 312 313
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;
    priv->proxy = -1;


J
John Levon 已提交
314 315
    /* Hypervisor is only run with privilege & required to succeed */
    if (xenHavePrivilege()) {
316
        DEBUG0("Trying hypervisor sub-driver");
317
        if (drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->open(conn, auth, flags) ==
318 319 320
            VIR_DRV_OPEN_SUCCESS) {
            DEBUG0("Activated hypervisor sub-driver");
            priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] = 1;
321
        }
322
    }
323

J
John Levon 已提交
324
    /* XenD is required to succeed if privileged.
325
     * If it fails as non-root, then the proxy driver may take over
326 327
     */
    DEBUG0("Trying XenD sub-driver");
328
    if (drivers[XEN_UNIFIED_XEND_OFFSET]->open(conn, auth, flags) ==
329 330 331 332 333 334 335 336
        VIR_DRV_OPEN_SUCCESS) {
        DEBUG0("Activated XenD sub-driver");
        priv->opened[XEN_UNIFIED_XEND_OFFSET] = 1;

        /* XenD is active, so try the xm & xs drivers too, both requird to
         * succeed if root, optional otherwise */
        if (priv->xendConfigVersion <= 2) {
            DEBUG0("Trying XM sub-driver");
337
            if (drivers[XEN_UNIFIED_XM_OFFSET]->open(conn, auth, flags) ==
338 339 340 341 342 343
                VIR_DRV_OPEN_SUCCESS) {
                DEBUG0("Activated XM sub-driver");
                priv->opened[XEN_UNIFIED_XM_OFFSET] = 1;
            }
        }
        DEBUG0("Trying XS sub-driver");
344
        if (drivers[XEN_UNIFIED_XS_OFFSET]->open(conn, auth, flags) ==
345 346 347 348
            VIR_DRV_OPEN_SUCCESS) {
            DEBUG0("Activated XS sub-driver");
            priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
        } else {
J
John Levon 已提交
349 350
            if (xenHavePrivilege())
                goto fail; /* XS is mandatory when privileged */
351 352
        }
    } else {
J
John Levon 已提交
353 354
        if (xenHavePrivilege()) {
            goto fail; /* XenD is mandatory when privileged */
355 356 357
        } else {
#if WITH_PROXY
            DEBUG0("Trying proxy sub-driver");
358
            if (drivers[XEN_UNIFIED_PROXY_OFFSET]->open(conn, auth, flags) ==
359 360 361 362 363 364 365 366
                VIR_DRV_OPEN_SUCCESS) {
                DEBUG0("Activated proxy sub-driver");
                priv->opened[XEN_UNIFIED_PROXY_OFFSET] = 1;
            } else {
                goto fail; /* Proxy is mandatory if XenD failed */
            }
#else
            DEBUG0("Handing off for remote driver");
367 368
            ret = VIR_DRV_OPEN_DECLINED; /* Let remote_driver try instead */
            goto clean;
369
#endif
370
        }
371 372
    }

D
Daniel P. Berrange 已提交
373 374
    xenNumaInit(conn);

375
    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
376 377 378 379
        DEBUG0("Failed to make capabilities");
        goto fail;
    }

380
#if WITH_XEN_INOTIFY
381 382 383 384 385 386 387
    if (xenHavePrivilege()) {
        DEBUG0("Trying Xen inotify sub-driver");
        if (drivers[XEN_UNIFIED_INOTIFY_OFFSET]->open(conn, auth, flags) ==
            VIR_DRV_OPEN_SUCCESS) {
            DEBUG0("Activated Xen inotify sub-driver");
            priv->opened[XEN_UNIFIED_INOTIFY_OFFSET] = 1;
        }
388 389 390
    }
#endif

391
    return VIR_DRV_OPEN_SUCCESS;
392

393 394
fail:
    ret = VIR_DRV_OPEN_ERROR;
395
#ifndef WITH_PROXY
396
clean:
397
#endif
398 399 400
    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);
D
Daniel P. Berrange 已提交
401
    virMutexDestroy(&priv->lock);
402
    VIR_FREE(priv);
D
Daniel P. Berrange 已提交
403
    conn->privateData = NULL;
D
Daniel Veillard 已提交
404
    return ret;
405 406
}

407 408 409
#define GET_PRIVATE(conn) \
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) (conn)->privateData

410 411 412
static int
xenUnifiedClose (virConnectPtr conn)
{
413
    GET_PRIVATE(conn);
414
    int i;
415

416
    virCapabilitiesFree(priv->caps);
417 418
    virDomainEventCallbackListFree(priv->domainEventCallbacks);

419 420
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->close)
421
            (void) drivers[i]->close (conn);
422

D
Daniel P. Berrange 已提交
423 424
    virMutexDestroy(&priv->lock);
    VIR_FREE(conn->privateData);
425

426
    return 0;
427 428
}

429 430 431 432 433 434 435 436 437 438 439

#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
                    ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +   \
                    (DOM0_INTERFACE_VERSION & 0xFFFF))

unsigned long xenUnifiedVersion(void)
{
    return HV_VERSION;
}


440 441 442
static const char *
xenUnifiedType (virConnectPtr conn)
{
443
    GET_PRIVATE(conn);
444
    int i;
445

446
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
447 448
        if (priv->opened[i])
            return "Xen";
449

450
    return NULL;
451 452
}

453 454 455 456 457
/* Which features are supported by this driver? */
static int
xenUnifiedSupportsFeature (virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
{
    switch (feature) {
458 459 460 461 462
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
        return 1;
    default:
        return 0;
463 464 465
    }
}

466
static int
467
xenUnifiedGetVersion (virConnectPtr conn, unsigned long *hvVer)
468
{
469
    GET_PRIVATE(conn);
470
    int i;
471

472 473 474
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->version &&
475 476
            drivers[i]->version (conn, hvVer) == 0)
            return 0;
477

478
    return -1;
479 480
}

481 482 483 484 485 486
/* NB: Even if connected to the proxy, we're still on the
 * same machine.
 */
static char *
xenUnifiedGetHostname (virConnectPtr conn)
{
487
    char *result;
488

489 490
    result = virGetHostname();
    if (result == NULL) {
491 492
        virReportSystemError(conn, errno,
                             "%s", _("cannot lookup hostname"));
493 494
        return NULL;
    }
495 496
    /* Caller frees this string. */
    return result;
497 498
}

499 500 501
static int
xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type)
{
502
    GET_PRIVATE(conn);
503

504 505 506 507
    if (type && STRCASENEQ (type, "Xen")) {
        xenUnifiedError (conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
        return -1;
    }
508

509 510 511 512 513 514
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorGetMaxVcpus (conn, type);
    else {
        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
        return -1;
    }
515 516 517 518 519
}

static int
xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
{
520
    GET_PRIVATE(conn);
521
    int i;
522

523 524 525
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->nodeGetInfo &&
526 527
            drivers[i]->nodeGetInfo (conn, info) == 0)
            return 0;
528

529
    return -1;
530 531 532 533 534
}

static char *
xenUnifiedGetCapabilities (virConnectPtr conn)
{
D
Daniel P. Berrange 已提交
535 536
    xenUnifiedPrivatePtr priv = conn->privateData;
    char *xml;
537

D
Daniel P. Berrange 已提交
538 539 540 541
    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
        virReportOOMError(conn);
        return NULL;
    }
542

D
Daniel P. Berrange 已提交
543
    return xml;
544 545 546 547 548
}

static int
xenUnifiedListDomains (virConnectPtr conn, int *ids, int maxids)
{
549
    GET_PRIVATE(conn);
550
    int ret;
551

552 553 554 555 556
    /* Try xenstore. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
        ret = xenStoreListDomains (conn, ids, maxids);
        if (ret >= 0) return ret;
    }
557

558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
    /* Try HV. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorListDomains (conn, ids, maxids);
        if (ret >= 0) return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonListDomains (conn, ids, maxids);
        if (ret >= 0) return ret;
    }

    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyListDomains (conn, ids, maxids);
        if (ret >= 0) return ret;
    }
575
    return -1;
576 577 578 579 580
}

static int
xenUnifiedNumOfDomains (virConnectPtr conn)
{
581
    GET_PRIVATE(conn);
582
    int i, ret;
583

584 585
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->numOfDomains) {
586 587 588
            ret = drivers[i]->numOfDomains (conn);
            if (ret >= 0) return ret;
        }
589

590
    return -1;
591 592 593
}

static virDomainPtr
594 595
xenUnifiedDomainCreateXML (virConnectPtr conn,
                           const char *xmlDesc, unsigned int flags)
596
{
597
    GET_PRIVATE(conn);
598 599
    int i;
    virDomainPtr ret;
600

601
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
602 603
        if (priv->opened[i] && drivers[i]->domainCreateXML) {
            ret = drivers[i]->domainCreateXML (conn, xmlDesc, flags);
604 605
            if (ret) return ret;
        }
606

607
    return NULL;
608 609
}

610 611 612 613
/* Assumption made in underlying drivers:
 * If the domain is "not found" and there is no other error, then
 * the Lookup* functions return a NULL but do not set virterror.
 */
614 615 616
static virDomainPtr
xenUnifiedDomainLookupByID (virConnectPtr conn, int id)
{
617
    GET_PRIVATE(conn);
618
    virDomainPtr ret;
619

620 621 622 623 624
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
    virConnResetLastError (conn);

625 626 627 628 629 630 631
    /* Try hypervisor/xenstore combo. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorLookupDomainByID (conn, id);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

632 633 634 635 636 637 638 639 640 641 642 643 644
    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyLookupByID (conn, id);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonLookupByID (conn, id);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
645

646 647
    /* Not found. */
    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
648
    return NULL;
649 650 651 652
}

static virDomainPtr
xenUnifiedDomainLookupByUUID (virConnectPtr conn,
653
                              const unsigned char *uuid)
654
{
655
    GET_PRIVATE(conn);
656
    virDomainPtr ret;
657

658 659 660 661 662
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
    virConnResetLastError (conn);

663 664 665 666 667 668 669
    /* Try hypervisor/xenstore combo. */
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorLookupDomainByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

670 671 672 673 674 675 676 677 678 679 680 681 682
    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyLookupByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonLookupByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
683

684 685 686 687 688 689 690 691 692
    /* Try XM for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainLookupByUUID (conn, uuid);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Not found. */
    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
693
    return NULL;
694 695 696 697
}

static virDomainPtr
xenUnifiedDomainLookupByName (virConnectPtr conn,
698
                              const char *name)
699
{
700
    GET_PRIVATE(conn);
701
    virDomainPtr ret;
702

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
    /* Reset any connection-level errors in virterror first, in case
     * there is one hanging around from a previous call.
     */
    virConnResetLastError (conn);

    /* Try proxy. */
    if (priv->opened[XEN_UNIFIED_PROXY_OFFSET]) {
        ret = xenProxyLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xend. */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try xenstore for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
        ret = xenStoreLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }

    /* Try XM for inactive domains. */
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainLookupByName (conn, name);
        if (ret || conn->err.code != VIR_ERR_OK)
            return ret;
    }
735

736 737
    /* Not found. */
    xenUnifiedError (conn, VIR_ERR_NO_DOMAIN, __FUNCTION__);
738
    return NULL;
739 740 741 742 743
}

static int
xenUnifiedDomainSuspend (virDomainPtr dom)
{
744
    GET_PRIVATE(dom->conn);
745
    int i;
746

747 748 749
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
750
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
751
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
752
            priv->opened[i] &&
753 754 755
            drivers[i]->domainSuspend &&
            drivers[i]->domainSuspend (dom) == 0)
            return 0;
756

757 758 759
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSuspend (dom) == 0)
760
        return 0;
761

762
    return -1;
763 764 765 766 767
}

static int
xenUnifiedDomainResume (virDomainPtr dom)
{
768
    GET_PRIVATE(dom->conn);
769
    int i;
770

771 772 773
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
774
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
775
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
776
            priv->opened[i] &&
777 778 779
            drivers[i]->domainResume &&
            drivers[i]->domainResume (dom) == 0)
            return 0;
780

781 782 783
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainResume (dom) == 0)
784
        return 0;
785

786
    return -1;
787 788 789 790 791
}

static int
xenUnifiedDomainShutdown (virDomainPtr dom)
{
792
    GET_PRIVATE(dom->conn);
793
    int i;
794

795 796 797
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainShutdown &&
798 799
            drivers[i]->domainShutdown (dom) == 0)
            return 0;
800

801
    return -1;
802 803 804 805 806
}

static int
xenUnifiedDomainReboot (virDomainPtr dom, unsigned int flags)
{
807
    GET_PRIVATE(dom->conn);
808
    int i;
809

810 811 812
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainReboot &&
813 814
            drivers[i]->domainReboot (dom, flags) == 0)
            return 0;
815

816
    return -1;
817 818 819 820 821
}

static int
xenUnifiedDomainDestroy (virDomainPtr dom)
{
822
    GET_PRIVATE(dom->conn);
823
    int i;
824

825 826 827
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
828
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
829
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
830
            priv->opened[i] &&
831 832 833
            drivers[i]->domainDestroy &&
            drivers[i]->domainDestroy (dom) == 0)
            return 0;
834

835
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
836 837
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainDestroy (dom) == 0)
838
        return 0;
839

840
    return -1;
841 842 843 844 845
}

static char *
xenUnifiedDomainGetOSType (virDomainPtr dom)
{
846
    GET_PRIVATE(dom->conn);
847 848
    int i;
    char *ret;
849

850 851
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetOSType) {
852 853 854
            ret = drivers[i]->domainGetOSType (dom);
            if (ret) return ret;
        }
855

856
    return NULL;
857 858 859 860 861
}

static unsigned long
xenUnifiedDomainGetMaxMemory (virDomainPtr dom)
{
862
    GET_PRIVATE(dom->conn);
863 864
    int i;
    unsigned long ret;
865

866 867
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetMaxMemory) {
868 869 870
            ret = drivers[i]->domainGetMaxMemory (dom);
            if (ret != 0) return ret;
        }
871

872
    return 0;
873 874 875 876 877
}

static int
xenUnifiedDomainSetMaxMemory (virDomainPtr dom, unsigned long memory)
{
878
    GET_PRIVATE(dom->conn);
879
    int i;
880

881 882 883 884 885 886
    /* Prefer xend for setting max memory */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        if (xenDaemonDomainSetMaxMemory (dom, memory) == 0)
            return 0;
    }

887
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
888 889
        if (i != XEN_UNIFIED_XEND_OFFSET &&
            priv->opened[i] &&
890
            drivers[i]->domainSetMaxMemory &&
891 892
            drivers[i]->domainSetMaxMemory (dom, memory) == 0)
            return 0;
893

894
    return -1;
895 896 897 898 899
}

static int
xenUnifiedDomainSetMemory (virDomainPtr dom, unsigned long memory)
{
900
    GET_PRIVATE(dom->conn);
901
    int i;
902

903 904 905
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainSetMemory &&
906 907
            drivers[i]->domainSetMemory (dom, memory) == 0)
            return 0;
908

909
    return -1;
910 911 912 913 914
}

static int
xenUnifiedDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info)
{
915
    GET_PRIVATE(dom->conn);
916
    int i;
917

918 919 920
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainGetInfo &&
921 922
            drivers[i]->domainGetInfo (dom, info) == 0)
            return 0;
923

924
    return -1;
925 926 927 928 929
}

static int
xenUnifiedDomainSave (virDomainPtr dom, const char *to)
{
930
    GET_PRIVATE(dom->conn);
931
    int i;
932

933 934 935
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainSave &&
936 937
            drivers[i]->domainSave (dom, to) == 0)
            return 0;
938

939
    return -1;
940 941 942 943 944
}

static int
xenUnifiedDomainRestore (virConnectPtr conn, const char *from)
{
945
    GET_PRIVATE(conn);
946
    int i;
947

948 949 950
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainRestore &&
951 952
            drivers[i]->domainRestore (conn, from) == 0)
            return 0;
953

954
    return -1;
955 956 957 958 959
}

static int
xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags)
{
960
    GET_PRIVATE(dom->conn);
961
    int i;
962

963 964 965
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainCoreDump &&
966 967
            drivers[i]->domainCoreDump (dom, to, flags) == 0)
            return 0;
968

969
    return -1;
970 971 972 973 974
}

static int
xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus)
{
975
    GET_PRIVATE(dom->conn);
976
    int i;
977

978 979 980
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
981
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
982
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
983
            priv->opened[i] &&
984 985 986
            drivers[i]->domainSetVcpus &&
            drivers[i]->domainSetVcpus (dom, nvcpus) == 0)
            return 0;
987

988 989 990
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus &&
        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus (dom, nvcpus) == 0)
991
        return 0;
992

993
    return -1;
994 995 996 997
}

static int
xenUnifiedDomainPinVcpu (virDomainPtr dom, unsigned int vcpu,
998
                         unsigned char *cpumap, int maplen)
999
{
1000
    GET_PRIVATE(dom->conn);
1001
    int i;
1002

1003 1004 1005
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
            drivers[i]->domainPinVcpu &&
1006 1007
            drivers[i]->domainPinVcpu (dom, vcpu, cpumap, maplen) == 0)
            return 0;
1008

1009
    return -1;
1010 1011 1012 1013
}

static int
xenUnifiedDomainGetVcpus (virDomainPtr dom,
1014 1015
                          virVcpuInfoPtr info, int maxinfo,
                          unsigned char *cpumaps, int maplen)
1016
{
1017
    GET_PRIVATE(dom->conn);
1018
    int i, ret;
1019

1020 1021
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetVcpus) {
1022 1023 1024 1025
            ret = drivers[i]->domainGetVcpus (dom, info, maxinfo, cpumaps, maplen);
            if (ret > 0)
                return ret;
        }
1026
    return -1;
1027 1028 1029 1030 1031
}

static int
xenUnifiedDomainGetMaxVcpus (virDomainPtr dom)
{
1032
    GET_PRIVATE(dom->conn);
1033
    int i, ret;
1034

1035 1036
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) {
1037 1038 1039
            ret = drivers[i]->domainGetMaxVcpus (dom);
            if (ret != 0) return ret;
        }
1040

1041
    return -1;
1042 1043 1044 1045 1046
}

static char *
xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
{
1047
    GET_PRIVATE(dom->conn);
1048

1049 1050 1051 1052 1053 1054
    if (dom->id == -1 && priv->xendConfigVersion < 3 ) {
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainDumpXML(dom, flags);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            char *cpus, *res;
D
Daniel P. Berrange 已提交
1055
            xenUnifiedLock(priv);
1056
            cpus = xenDomainUsedCpus(dom);
D
Daniel P. Berrange 已提交
1057
            xenUnifiedUnlock(priv);
1058
            res = xenDaemonDomainDumpXML(dom, flags, cpus);
1059
            VIR_FREE(cpus);
1060
            return(res);
1061
        }
1062 1063
        if (priv->opened[XEN_UNIFIED_PROXY_OFFSET])
            return xenProxyDomainDumpXML(dom, flags);
1064
    }
1065

1066
    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
1067
    return NULL;
1068 1069
}

1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089

static char *
xenUnifiedDomainXMLFromNative(virConnectPtr conn,
                              const char *format,
                              const char *config,
                              unsigned int flags ATTRIBUTE_UNUSED)
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
    GET_PRIVATE(conn);

    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), format);
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1090
        conf = virConfReadMem(config, strlen(config), 0);
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
        if (!conf)
            goto cleanup;

        def = xenXMDomainConfigParse(conn, conf);
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
        def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion);
    }
    if (!def)
        goto cleanup;

    ret = virDomainDefFormat(conn, def, 0);

cleanup:
    virDomainDefFree(def);
    return ret;
}


#define MAX_CONFIG_SIZE (1024 * 65)
static char *
xenUnifiedDomainXMLToNative(virConnectPtr conn,
                            const char *format,
                            const char *xmlData,
                            unsigned int flags ATTRIBUTE_UNUSED)
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
    GET_PRIVATE(conn);

    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
        xenUnifiedError(conn, VIR_ERR_INVALID_ARG,
                        _("unsupported config type %s"), format);
        goto cleanup;
    }

    if (!(def = virDomainDefParseString(conn,
                                        priv->caps,
                                        xmlData,
                                        0)))
        goto cleanup;

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
        int len = MAX_CONFIG_SIZE;
        conf = xenXMDomainConfigFormat(conn, def);
        if (!conf)
            goto cleanup;

        if (VIR_ALLOC_N(ret, len) < 0) {
            virReportOOMError(conn);
            goto cleanup;
        }

        if (virConfWriteMem(ret, &len, conf) < 0) {
            VIR_FREE(ret);
            goto cleanup;
        }
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
        ret = xenDaemonFormatSxpr(conn, def, priv->xendConfigVersion);
    }

cleanup:
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
    return ret;
}


1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
static int
xenUnifiedDomainMigratePrepare (virConnectPtr dconn,
                                char **cookie,
                                int *cookielen,
                                const char *uri_in,
                                char **uri_out,
                                unsigned long flags,
                                const char *dname,
                                unsigned long resource)
{
    GET_PRIVATE(dconn);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainMigratePrepare (dconn, cookie, cookielen,
                                              uri_in, uri_out,
                                              flags, dname, resource);

    xenUnifiedError (dconn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

static int
xenUnifiedDomainMigratePerform (virDomainPtr dom,
                                const char *cookie,
                                int cookielen,
                                const char *uri,
                                unsigned long flags,
                                const char *dname,
                                unsigned long resource)
{
    GET_PRIVATE(dom->conn);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainMigratePerform (dom, cookie, cookielen, uri,
                                              flags, dname, resource);

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

static virDomainPtr
xenUnifiedDomainMigrateFinish (virConnectPtr dconn,
                               const char *dname,
                               const char *cookie ATTRIBUTE_UNUSED,
                               int cookielen ATTRIBUTE_UNUSED,
                               const char *uri ATTRIBUTE_UNUSED,
                               unsigned long flags ATTRIBUTE_UNUSED)
{
    return xenUnifiedDomainLookupByName (dconn, dname);
}

1212 1213
static int
xenUnifiedListDefinedDomains (virConnectPtr conn, char **const names,
1214
                              int maxnames)
1215
{
1216
    GET_PRIVATE(conn);
1217 1218
    int i;
    int ret;
1219

1220 1221
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->listDefinedDomains) {
1222 1223 1224
            ret = drivers[i]->listDefinedDomains (conn, names, maxnames);
            if (ret >= 0) return ret;
        }
1225

1226
    return -1;
1227 1228 1229 1230 1231
}

static int
xenUnifiedNumOfDefinedDomains (virConnectPtr conn)
{
1232
    GET_PRIVATE(conn);
1233 1234
    int i;
    int ret;
1235

1236 1237
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->numOfDefinedDomains) {
1238 1239 1240
            ret = drivers[i]->numOfDefinedDomains (conn);
            if (ret >= 0) return ret;
        }
1241

1242
    return -1;
1243 1244 1245 1246 1247
}

static int
xenUnifiedDomainCreate (virDomainPtr dom)
{
1248
    GET_PRIVATE(dom->conn);
1249
    int i;
1250

1251 1252
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainCreate &&
1253 1254
            drivers[i]->domainCreate (dom) == 0)
            return 0;
1255

1256
    return -1;
1257 1258 1259 1260 1261
}

static virDomainPtr
xenUnifiedDomainDefineXML (virConnectPtr conn, const char *xml)
{
1262
    GET_PRIVATE(conn);
1263 1264
    int i;
    virDomainPtr ret;
1265

1266 1267
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainDefineXML) {
1268 1269 1270
            ret = drivers[i]->domainDefineXML (conn, xml);
            if (ret) return ret;
        }
1271

1272
    return NULL;
1273 1274 1275 1276 1277
}

static int
xenUnifiedDomainUndefine (virDomainPtr dom)
{
1278
    GET_PRIVATE(dom->conn);
1279
    int i;
1280

1281 1282
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainUndefine &&
1283 1284
            drivers[i]->domainUndefine (dom) == 0)
            return 0;
1285

1286
    return -1;
1287 1288 1289
}

static int
1290
xenUnifiedDomainAttachDevice (virDomainPtr dom, const char *xml)
1291
{
1292
    GET_PRIVATE(dom->conn);
1293
    int i;
1294

1295 1296
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainAttachDevice &&
1297 1298
            drivers[i]->domainAttachDevice (dom, xml) == 0)
            return 0;
1299

1300
    return -1;
1301 1302 1303
}

static int
1304
xenUnifiedDomainDetachDevice (virDomainPtr dom, const char *xml)
1305
{
1306
    GET_PRIVATE(dom->conn);
1307
    int i;
1308

1309 1310
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] && drivers[i]->domainDetachDevice &&
1311 1312
            drivers[i]->domainDetachDevice (dom, xml) == 0)
            return 0;
1313

1314
    return -1;
1315 1316
}

1317 1318 1319 1320 1321
static int
xenUnifiedDomainGetAutostart (virDomainPtr dom, int *autostart)
{
    GET_PRIVATE(dom->conn);

1322 1323 1324 1325 1326 1327 1328
    if (priv->xendConfigVersion < 3) {
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainGetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainGetAutostart(dom, autostart);
    }
1329

1330
    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
1331 1332 1333 1334 1335 1336 1337 1338
    return -1;
}

static int
xenUnifiedDomainSetAutostart (virDomainPtr dom, int autostart)
{
    GET_PRIVATE(dom->conn);

1339 1340 1341 1342 1343 1344 1345
    if (priv->xendConfigVersion < 3) {
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainSetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainSetAutostart(dom, autostart);
    }
1346

1347
    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
1348 1349 1350
    return -1;
}

1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
static char *
xenUnifiedDomainGetSchedulerType (virDomainPtr dom, int *nparams)
{
    GET_PRIVATE(dom->conn);
    int i;
    char *schedulertype;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
        if (priv->opened[i] && drivers[i]->domainGetSchedulerType) {
            schedulertype = drivers[i]->domainGetSchedulerType (dom, nparams);
1361 1362
            if (schedulertype != NULL)
                return(schedulertype);
1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
        }
    }
    return(NULL);
}

static int
xenUnifiedDomainGetSchedulerParameters (virDomainPtr dom,
                    virSchedParameterPtr params, int *nparams)
{
    GET_PRIVATE(dom->conn);
    int i, ret;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
        if (priv->opened[i] && drivers[i]->domainGetSchedulerParameters) {
           ret = drivers[i]->domainGetSchedulerParameters(dom, params, nparams);
1378 1379 1380
           if (ret == 0)
               return(0);
        }
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
    }
    return(-1);
}

static int
xenUnifiedDomainSetSchedulerParameters (virDomainPtr dom,
                    virSchedParameterPtr params, int nparams)
{
    GET_PRIVATE(dom->conn);
    int i, ret;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
        if (priv->opened[i] && drivers[i]->domainSetSchedulerParameters) {
           ret = drivers[i]->domainSetSchedulerParameters(dom, params, nparams);
1395 1396 1397
           if (ret == 0)
               return 0;
        }
1398 1399 1400 1401 1402
    }

    return(-1);
}

1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
static int
xenUnifiedDomainBlockStats (virDomainPtr dom, const char *path,
                            struct _virDomainBlockStats *stats)
{
    GET_PRIVATE (dom->conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorDomainBlockStats (dom, path, stats);

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

static int
xenUnifiedDomainInterfaceStats (virDomainPtr dom, const char *path,
                                struct _virDomainInterfaceStats *stats)
{
    GET_PRIVATE (dom->conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        return xenHypervisorDomainInterfaceStats (dom, path, stats);

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

R
Richard W.M. Jones 已提交
1429 1430 1431
static int
xenUnifiedDomainBlockPeek (virDomainPtr dom, const char *path,
                           unsigned long long offset, size_t size,
1432
                           void *buffer, unsigned int flags ATTRIBUTE_UNUSED)
R
Richard W.M. Jones 已提交
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
{
    int r;
    GET_PRIVATE (dom->conn);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        r = xenDaemonDomainBlockPeek (dom, path, offset, size, buffer);
        if (r != -2) return r;
        /* r == -2 means declined, so fall through to XM driver ... */
    }

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        if (xenXMDomainBlockPeek (dom, path, offset, size, buffer) == 0)
            return 0;
    }

    xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

1452 1453 1454 1455 1456 1457 1458
static int
xenUnifiedNodeGetCellsFreeMemory (virConnectPtr conn, unsigned long long *freeMems,
                                  int startCell, int maxCells)
{
    GET_PRIVATE (conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
1459
        return xenHypervisorNodeGetCellsFreeMemory (conn, freeMems,
1460 1461 1462 1463 1464 1465
                                                    startCell, maxCells);

    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return -1;
}

1466 1467 1468 1469 1470 1471 1472 1473
static unsigned long long
xenUnifiedNodeGetFreeMemory (virConnectPtr conn)
{
    unsigned long long freeMem = 0;
    int ret;
    GET_PRIVATE (conn);

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
1474
        ret = xenHypervisorNodeGetCellsFreeMemory (conn, &freeMem,
1475
                                                    -1, 1);
1476 1477 1478
        if (ret != 1)
            return (0);
        return(freeMem);
1479 1480 1481 1482 1483 1484
    }

    xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
    return(0);
}

1485 1486
static int
xenUnifiedDomainEventRegister (virConnectPtr conn,
1487
                               virConnectDomainEventCallback callback,
1488 1489 1490
                               void *opaque,
                               void (*freefunc)(void *))
{
D
Daniel P. Berrange 已提交
1491 1492
    GET_PRIVATE (conn);

1493
    int ret;
D
Daniel P. Berrange 已提交
1494
    xenUnifiedLock(priv);
1495

1496 1497
    if (priv->xsWatch == -1) {
        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1498
        xenUnifiedUnlock(priv);
1499 1500 1501
        return -1;
    }

1502 1503 1504
    ret = virDomainEventCallbackListAdd(conn, priv->domainEventCallbacks,
                                        callback, opaque, freefunc);

D
Daniel P. Berrange 已提交
1505
    xenUnifiedUnlock(priv);
1506
    return (ret);
1507 1508 1509 1510
}

static int
xenUnifiedDomainEventDeregister (virConnectPtr conn,
1511
                                 virConnectDomainEventCallback callback)
1512 1513 1514
{
    int ret;
    GET_PRIVATE (conn);
D
Daniel P. Berrange 已提交
1515 1516
    xenUnifiedLock(priv);

1517 1518
    if (priv->xsWatch == -1) {
        xenUnifiedError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1519
        xenUnifiedUnlock(priv);
1520 1521 1522
        return -1;
    }

D
Daniel P. Berrange 已提交
1523 1524 1525 1526 1527 1528
    if (priv->domainEventDispatching)
        ret = virDomainEventCallbackListMarkDelete(conn, priv->domainEventCallbacks,
                                                   callback);
    else
        ret = virDomainEventCallbackListRemove(conn, priv->domainEventCallbacks,
                                               callback);
1529

D
Daniel P. Berrange 已提交
1530
    xenUnifiedUnlock(priv);
1531 1532 1533
    return ret;
}

1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550

static int
xenUnifiedNodeDeviceGetPciInfo (virNodeDevicePtr dev,
                           unsigned *domain,
                           unsigned *bus,
                           unsigned *slot,
                           unsigned *function)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

    xml = virNodeDeviceGetXMLDesc(dev, 0);
    if (!xml)
        goto out;

1551
    def = virNodeDeviceDefParseString(dev->conn, xml, EXISTING_DEVICE);
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640
    if (!def)
        goto out;

    cap = def->caps;
    while (cap) {
        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
            *domain   = cap->data.pci_dev.domain;
            *bus      = cap->data.pci_dev.bus;
            *slot     = cap->data.pci_dev.slot;
            *function = cap->data.pci_dev.function;
            break;
        }

        cap = cap->next;
    }

    if (!cap) {
        xenUnifiedError(dev->conn, VIR_ERR_INVALID_ARG,
                        _("device %s is not a PCI device"), dev->name);
        goto out;
    }

    ret = 0;
out:
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
xenUnifiedNodeDeviceDettach (virNodeDevicePtr dev)
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
    if (!pci)
        return -1;

    if (pciDettachDevice(dev->conn, pci) < 0)
        goto out;

    ret = 0;
out:
    pciFreeDevice(dev->conn, pci);
    return ret;
}

static int
xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev)
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
    if (!pci)
        return -1;

    if (pciReAttachDevice(dev->conn, pci) < 0)
        goto out;

    ret = 0;
out:
    pciFreeDevice(dev->conn, pci);
    return ret;
}

static int
xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
{
    pciDevice *pci;
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

    pci = pciGetDevice(dev->conn, domain, bus, slot, function);
    if (!pci)
        return -1;

1641
    if (pciResetDevice(dev->conn, pci, NULL) < 0)
1642 1643 1644 1645 1646 1647 1648 1649 1650
        goto out;

    ret = 0;
out:
    pciFreeDevice(dev->conn, pci);
    return ret;
}


1651 1652 1653 1654
/*----- Register with libvirt.c, and initialise Xen drivers. -----*/

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
    VIR_DRV_XEN_UNIFIED,
    "Xen",
    xenUnifiedOpen, /* open */
    xenUnifiedClose, /* close */
    xenUnifiedSupportsFeature, /* supports_feature */
    xenUnifiedType, /* type */
    xenUnifiedGetVersion, /* version */
    xenUnifiedGetHostname, /* getHostname */
    xenUnifiedGetMaxVcpus, /* getMaxVcpus */
    xenUnifiedNodeGetInfo, /* nodeGetInfo */
    xenUnifiedGetCapabilities, /* getCapabilities */
    xenUnifiedListDomains, /* listDomains */
    xenUnifiedNumOfDomains, /* numOfDomains */
    xenUnifiedDomainCreateXML, /* domainCreateXML */
    xenUnifiedDomainLookupByID, /* domainLookupByID */
    xenUnifiedDomainLookupByUUID, /* domainLookupByUUID */
    xenUnifiedDomainLookupByName, /* domainLookupByName */
    xenUnifiedDomainSuspend, /* domainSuspend */
    xenUnifiedDomainResume, /* domainResume */
    xenUnifiedDomainShutdown, /* domainShutdown */
    xenUnifiedDomainReboot, /* domainReboot */
    xenUnifiedDomainDestroy, /* domainDestroy */
    xenUnifiedDomainGetOSType, /* domainGetOSType */
    xenUnifiedDomainGetMaxMemory, /* domainGetMaxMemory */
    xenUnifiedDomainSetMaxMemory, /* domainSetMaxMemory */
    xenUnifiedDomainSetMemory, /* domainSetMemory */
    xenUnifiedDomainGetInfo, /* domainGetInfo */
    xenUnifiedDomainSave, /* domainSave */
    xenUnifiedDomainRestore, /* domainRestore */
    xenUnifiedDomainCoreDump, /* domainCoreDump */
    xenUnifiedDomainSetVcpus, /* domainSetVcpus */
    xenUnifiedDomainPinVcpu, /* domainPinVcpu */
    xenUnifiedDomainGetVcpus, /* domainGetVcpus */
    xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */
    NULL, /* domainGetSecurityLabel */
    NULL, /* nodeGetSecurityModel */
    xenUnifiedDomainDumpXML, /* domainDumpXML */
1692 1693
    xenUnifiedDomainXMLFromNative, /* domainXMLFromNative */
    xenUnifiedDomainXMLToNative, /* domainXMLToNative */
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
    xenUnifiedListDefinedDomains, /* listDefinedDomains */
    xenUnifiedNumOfDefinedDomains, /* numOfDefinedDomains */
    xenUnifiedDomainCreate, /* domainCreate */
    xenUnifiedDomainDefineXML, /* domainDefineXML */
    xenUnifiedDomainUndefine, /* domainUndefine */
    xenUnifiedDomainAttachDevice, /* domainAttachDevice */
    xenUnifiedDomainDetachDevice, /* domainDetachDevice */
    xenUnifiedDomainGetAutostart, /* domainGetAutostart */
    xenUnifiedDomainSetAutostart, /* domainSetAutostart */
    xenUnifiedDomainGetSchedulerType, /* domainGetSchedulerType */
    xenUnifiedDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
    xenUnifiedDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
    xenUnifiedDomainMigratePrepare, /* domainMigratePrepare */
    xenUnifiedDomainMigratePerform, /* domainMigratePerform */
    xenUnifiedDomainMigrateFinish, /* domainMigrateFinish */
    xenUnifiedDomainBlockStats, /* domainBlockStats */
    xenUnifiedDomainInterfaceStats, /* domainInterfaceStats */
    xenUnifiedDomainBlockPeek, /* domainBlockPeek */
    NULL, /* domainMemoryPeek */
    xenUnifiedNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    xenUnifiedNodeGetFreeMemory, /* getFreeMemory */
    xenUnifiedDomainEventRegister, /* domainEventRegister */
    xenUnifiedDomainEventDeregister, /* domainEventDeregister */
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
1719 1720 1721
    xenUnifiedNodeDeviceDettach, /* nodeDeviceDettach */
    xenUnifiedNodeDeviceReAttach, /* nodeDeviceReAttach */
    xenUnifiedNodeDeviceReset, /* nodeDeviceReset */
C
Chris Lalancette 已提交
1722
    NULL, /* domainMigratePrepareTunnel */
1723 1724
};

1725
/**
1726
 * xenRegister:
1727 1728 1729 1730 1731
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
1732
int
1733
xenRegister (void)
1734
{
1735 1736
    /* Ignore failures here. */
    (void) xenHypervisorInit ();
1737

J
John Levon 已提交
1738 1739 1740 1741
#ifdef WITH_LIBVIRTD
    if (virRegisterStateDriver (&state_driver) == -1) return -1;
#endif

1742
    return virRegisterDriver (&xenUnifiedDriver);
1743 1744
}

1745 1746 1747 1748 1749 1750 1751 1752 1753
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
    int i;
J
John Levon 已提交
1754 1755 1756 1757

    if (list == NULL)
        return;

1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
    for (i=0; i<list->count; i++) {
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
    VIR_FREE(list);
}

/**
 * xenUnifiedAddDomainInfo:
 *
 * Add name and uuid to the domain info list
 *
 * Returns: 0 on success, -1 on failure
 */
int
xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
                        int id, char *name,
                        unsigned char *uuid)
{
    xenUnifiedDomainInfoPtr info;
    int n;

    /* check if we already have this callback on our list */
    for (n=0; n < list->count; n++) {
        if (STREQ(list->doms[n]->name, name) &&
            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
            DEBUG0("WARNING: dom already tracked");
            return -1;
        }
    }

    if (VIR_ALLOC(info) < 0)
        goto memory_error;
    if (!(info->name = strdup(name)))
        goto memory_error;

    memcpy(info->uuid, uuid, VIR_UUID_BUFLEN);
    info->id = id;

    /* Make space on list */
    n = list->count;
    if (VIR_REALLOC_N(list->doms, n + 1) < 0) {
        goto memory_error;
    }

    list->doms[n] = info;
    list->count++;
    return 0;
memory_error:
J
Jim Meyering 已提交
1807
    virReportOOMError (NULL);
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852
    if (info)
        VIR_FREE(info->name);
    VIR_FREE(info);
    return -1;
}

/**
 * xenUnifiedRemoveDomainInfo:
 *
 * Removes name and uuid to the domain info list
 *
 * Returns: 0 on success, -1 on failure
 */
int
xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
                           int id, char *name,
                           unsigned char *uuid)
{
    int i;
    for (i = 0 ; i < list->count ; i++) {
        if( list->doms[i]->id == id &&
            STREQ(list->doms[i]->name, name) &&
            !memcmp(list->doms[i]->uuid, uuid, VIR_UUID_BUFLEN)) {

            VIR_FREE(list->doms[i]->name);
            VIR_FREE(list->doms[i]);

            if (i < (list->count - 1))
                memmove(list->doms + i,
                        list->doms + i + 1,
                        sizeof(*(list->doms)) *
                                (list->count - (i + 1)));

            if (VIR_REALLOC_N(list->doms,
                              list->count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            list->count--;

            return 0;
        }
    }
    return -1;
}

D
Daniel P. Berrange 已提交
1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
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);
}

1874 1875
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
1876 1877
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
1878 1879 1880
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
1881 1882
 * The caller must hold the lock in 'priv' before invoking
 *
1883 1884
 */
void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv,
1885
                                    virDomainEventPtr event)
1886
{
D
Daniel P. Berrange 已提交
1887
    if (!priv)
1888
        return;
1889

D
Daniel P. Berrange 已提交
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
    priv->domainEventDispatching = 1;

    if (priv->domainEventCallbacks) {
        virDomainEventDispatch(event,
                               priv->domainEventCallbacks,
                               xenUnifiedDomainEventDispatchFunc,
                               priv);

        /* Purge any deleted callbacks */
        virDomainEventCallbackListPurgeMarked(priv->domainEventCallbacks);
    }

1902
    virDomainEventFree(event);
D
Daniel P. Berrange 已提交
1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914

    priv->domainEventDispatching = 0;
}

void xenUnifiedLock(xenUnifiedPrivatePtr priv)
{
    virMutexLock(&priv->lock);
}

void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
{
    virMutexUnlock(&priv->lock);
1915
}