Exemplo n.º 1
0
/**
 * virUnrefDomain:
 * @domain: the domain to unreference
 *
 * Unreference the domain. If the use count drops to zero, the structure is
 * actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefDomain(virDomainPtr domain) {
    int refs;

    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
        virLibConnError(VIR_ERR_INVALID_DOMAIN, "%s",
                        _("bad domain or no connection"));
        return -1;
    }
    virMutexLock(&domain->conn->lock);
    VIR_DEBUG("unref domain %p %s %d", domain, domain->name, domain->refs);
    domain->refs--;
    refs = domain->refs;
    if (refs == 0) {
        virReleaseDomain(domain);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&domain->conn->lock);
    return refs;
}
Exemplo n.º 2
0
/**
 * virUnrefSecret:
 * @secret: the secret to unreference
 *
 * Unreference the secret. If the use count drops to zero, the structure is
 * actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefSecret(virSecretPtr secret) {
    int refs;

    if (!VIR_IS_CONNECTED_SECRET(secret)) {
        virLibConnError(VIR_ERR_INVALID_SECRET, "%s",
                        _("bad secret or no connection"));
        return -1;
    }
    virMutexLock(&secret->conn->lock);
    VIR_DEBUG("unref secret %p %p %d", secret, secret->uuid, secret->refs);
    secret->refs--;
    refs = secret->refs;
    if (refs == 0) {
        virReleaseSecret(secret);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&secret->conn->lock);
    return refs;
}
Exemplo n.º 3
0
/**
 * virUnrefStoragePool:
 * @pool: the pool to unreference
 *
 * Unreference the pool. If the use count drops to zero, the structure is
 * actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefStoragePool(virStoragePoolPtr pool) {
    int refs;

    if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) {
        virLibConnError(VIR_ERR_INVALID_STORAGE_POOL,
                        _("bad storage pool or no connection"));
        return -1;
    }
    virMutexLock(&pool->conn->lock);
    VIR_DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs);
    pool->refs--;
    refs = pool->refs;
    if (refs == 0) {
        virReleaseStoragePool(pool);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&pool->conn->lock);
    return refs;
}
Exemplo n.º 4
0
/* Iterate over all file handles and dispatch any which
 * have pending events listed in the poll() data. Invoke
 * the user supplied callback for each handle which has
 * pending events
 *
 * This method must cope with new handles being registered
 * by a callback, and must skip any handles marked as deleted.
 *
 * Returns 0 upon success, -1 if an error occurred
 */
static int virEventPollDispatchHandles(int nfds, struct pollfd *fds) {
    int i, n;
    VIR_DEBUG("Dispatch %d", nfds);

    /* NB, use nfds not eventLoop.handlesCount, because new
     * fds might be added on end of list, and they're not
     * in the fds array we've got */
    for (i = 0, n = 0; n < nfds && i < eventLoop.handlesCount; n++) {
        while ((eventLoop.handles[i].fd != fds[n].fd ||
                eventLoop.handles[i].events == 0) &&
               i < eventLoop.handlesCount) {
            i++;
        }
        if (i == eventLoop.handlesCount)
            break;

        VIR_DEBUG("i=%d w=%d", i, eventLoop.handles[i].watch);
        if (eventLoop.handles[i].deleted) {
            EVENT_DEBUG("Skip deleted n=%d w=%d f=%d", i,
                        eventLoop.handles[i].watch, eventLoop.handles[i].fd);
            continue;
        }

        if (fds[n].revents) {
            virEventHandleCallback cb = eventLoop.handles[i].cb;
            int watch = eventLoop.handles[i].watch;
            void *opaque = eventLoop.handles[i].opaque;
            int hEvents = virEventPollFromNativeEvents(fds[n].revents);
            PROBE(EVENT_POLL_DISPATCH_HANDLE,
                  "watch=%d events=%d",
                  watch, hEvents);
            virMutexUnlock(&eventLoop.lock);
            (cb)(watch, fds[n].fd, hEvents, opaque);
            virMutexLock(&eventLoop.lock);
        }
    }

    return 0;
}
Exemplo n.º 5
0
int virThreadLocalInit(virThreadLocalPtr l,
                       virThreadLocalCleanup c)
{
    if ((l->key = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
        errno = ESRCH;
        return -1;
    }
    TlsSetValue(l->key, NULL);

    if (c) {
        virMutexLock(&virThreadLocalLock);
        if (VIR_REALLOC_N(virThreadLocalList,
                          virThreadLocalCount + 1) < 0)
            return -1;
        virThreadLocalList[virThreadLocalCount].key = l->key;
        virThreadLocalList[virThreadLocalCount].cleanup = c;
        virThreadLocalCount++;
        virMutexUnlock(&virThreadLocalLock);
    }

    return 0;
}
Exemplo n.º 6
0
int virNetClientStreamQueuePacket(virNetClientStreamPtr st,
                                  virNetMessagePtr msg)
{
    int ret = -1;
    size_t need;

    virMutexLock(&st->lock);
    need = msg->bufferLength - msg->bufferOffset;
    if (need) {
        size_t avail = st->incomingLength - st->incomingOffset;
        if (need > avail) {
            size_t extra = need - avail;
            if (VIR_REALLOC_N(st->incoming,
                              st->incomingLength + extra) < 0) {
                VIR_DEBUG("Out of memory handling stream data");
                goto cleanup;
            }
            st->incomingLength += extra;
        }

        memcpy(st->incoming + st->incomingOffset,
               msg->buffer + msg->bufferOffset,
               msg->bufferLength - msg->bufferOffset);
        st->incomingOffset += (msg->bufferLength - msg->bufferOffset);
    } else {
        st->incomingEOF = true;
    }

    VIR_DEBUG("Stream incoming data offset %zu length %zu EOF %d",
              st->incomingOffset, st->incomingLength,
              st->incomingEOF);
    virNetClientStreamEventTimerUpdate(st);

    ret = 0;

cleanup:
    virMutexUnlock(&st->lock);
    return ret;
}
Exemplo n.º 7
0
/*
 * Register a callback for monitoring file handle events.
 * NB, it *must* be safe to call this from within a callback
 * For this reason we only ever append to existing list.
 */
int virEventPollAddHandle(int fd, int events,
                          virEventHandleCallback cb,
                          void *opaque,
                          virFreeCallback ff)
{
    int watch;
    virMutexLock(&eventLoop.lock);
    if (eventLoop.handlesCount == eventLoop.handlesAlloc) {
        EVENT_DEBUG("Used %zu handle slots, adding at least %d more",
                    eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT);
        if (VIR_RESIZE_N(eventLoop.handles, eventLoop.handlesAlloc,
                         eventLoop.handlesCount, EVENT_ALLOC_EXTENT) < 0) {
            virMutexUnlock(&eventLoop.lock);
            return -1;
        }
    }

    watch = nextWatch++;

    eventLoop.handles[eventLoop.handlesCount].watch = watch;
    eventLoop.handles[eventLoop.handlesCount].fd = fd;
    eventLoop.handles[eventLoop.handlesCount].events =
                                         virEventPollToNativeEvents(events);
    eventLoop.handles[eventLoop.handlesCount].cb = cb;
    eventLoop.handles[eventLoop.handlesCount].ff = ff;
    eventLoop.handles[eventLoop.handlesCount].opaque = opaque;
    eventLoop.handles[eventLoop.handlesCount].deleted = 0;

    eventLoop.handlesCount++;

    virEventPollInterruptLocked();

    PROBE(EVENT_POLL_ADD_HANDLE,
          "watch=%d fd=%d events=%d cb=%p opaque=%p ff=%p",
          watch, fd, events, cb, opaque, ff);
    virMutexUnlock(&eventLoop.lock);

    return watch;
}
Exemplo n.º 8
0
/**
 * virUnrefNetwork:
 * @network: the network to unreference
 *
 * Unreference the network. If the use count drops to zero, the structure is
 * actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefNetwork(virNetworkPtr network) {
    int refs;

    if (!VIR_IS_CONNECTED_NETWORK(network)) {
        virLibConnError(VIR_ERR_INVALID_NETWORK,
                        _("bad network or no connection"));
        return -1;
    }
    virMutexLock(&network->conn->lock);
    VIR_DEBUG("unref network %p %s %d", network, network->name, network->refs);
    network->refs--;
    refs = network->refs;
    if (refs == 0) {
        virReleaseNetwork(network);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&network->conn->lock);
    return refs;
}
Exemplo n.º 9
0
/**
 * virUnrefStorageVol:
 * @vol: the vol to unreference
 *
 * Unreference the vol. If the use count drops to zero, the structure is
 * actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefStorageVol(virStorageVolPtr vol) {
    int refs;

    if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) {
        virLibConnError(VIR_ERR_INVALID_STORAGE_VOL,
                        _("bad storage volume or no connection"));
        return -1;
    }
    virMutexLock(&vol->conn->lock);
    VIR_DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs);
    vol->refs--;
    refs = vol->refs;
    if (refs == 0) {
        virReleaseStorageVol(vol);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&vol->conn->lock);
    return refs;
}
Exemplo n.º 10
0
/**
 * virUnrefInterface:
 * @interface: the interface to unreference
 *
 * Unreference the interface. If the use count drops to zero, the structure is
 * actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefInterface(virInterfacePtr iface) {
    int refs;

    if (!VIR_IS_CONNECTED_INTERFACE(iface)) {
        virLibConnError(VIR_ERR_INVALID_INTERFACE,
                        _("bad interface or no connection"));
        return -1;
    }
    virMutexLock(&iface->conn->lock);
    VIR_DEBUG("unref interface %p %s %d", iface, iface->name, iface->refs);
    iface->refs--;
    refs = iface->refs;
    if (refs == 0) {
        virReleaseInterface(iface);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&iface->conn->lock);
    return refs;
}
Exemplo n.º 11
0
virDomainSnapshotPtr
virGetDomainSnapshot(virDomainPtr domain, const char *name)
{
    virDomainSnapshotPtr ret = NULL;

    if (!VIR_IS_DOMAIN(domain)) {
        virLibConnError(VIR_ERR_INVALID_DOMAIN, _("bad domain"));
        return NULL;
    }
    virCheckNonNullArgReturn(name, NULL);

    virMutexLock(&domain->conn->lock);

    if (VIR_ALLOC(ret) < 0) {
        virMutexUnlock(&domain->conn->lock);
        virReportOOMError();
        goto error;
    }
    ret->name = strdup(name);
    if (ret->name == NULL) {
        virMutexUnlock(&domain->conn->lock);
        virReportOOMError();
        goto error;
    }
    ret->magic = VIR_SNAPSHOT_MAGIC;
    ret->domain = domain;

    domain->refs++;
    ret->refs++;
    virMutexUnlock(&domain->conn->lock);
    return ret;

 error:
    if (ret != NULL) {
        VIR_FREE(ret->name);
        VIR_FREE(ret);
    }
    return NULL;
}
Exemplo n.º 12
0
void virEventPollUpdateHandle(int watch, int events) {
    int i;
    PROBE(EVENT_POLL_UPDATE_HANDLE,
          "watch=%d events=%d",
          watch, events);

    if (watch <= 0) {
        VIR_WARN("Ignoring invalid update watch %d", watch);
        return;
    }

    virMutexLock(&eventLoop.lock);
    for (i = 0 ; i < eventLoop.handlesCount ; i++) {
        if (eventLoop.handles[i].watch == watch) {
            eventLoop.handles[i].events =
                    virEventPollToNativeEvents(events);
            virEventPollInterruptLocked();
            break;
        }
    }
    virMutexUnlock(&eventLoop.lock);
}
Exemplo n.º 13
0
int virNetClientStreamEventUpdateCallback(virNetClientStreamPtr st,
                                          int events)
{
    int ret = -1;

    virMutexLock(&st->lock);
    if (!st->cb) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("no stream callback registered"));
        goto cleanup;
    }

    st->cbEvents = events;

    virNetClientStreamEventTimerUpdate(st);

    ret = 0;

cleanup:
    virMutexUnlock(&st->lock);
    return ret;
}
Exemplo n.º 14
0
/**
 * virGetNodeDevice:
 * @conn: the hypervisor connection
 * @name: device name (unique on node)
 *
 * Lookup if the device is already registered for that connection,
 * if yes return a new pointer to it, if no allocate a new structure,
 * and register it in the table. In any case a corresponding call to
 * virUnrefNodeDevice() is needed to not leak data.
 *
 * Returns a pointer to the node device, or NULL in case of failure
 */
virNodeDevicePtr
virGetNodeDevice(virConnectPtr conn, const char *name)
{
    virNodeDevicePtr ret = NULL;

    if (!VIR_IS_CONNECT(conn)) {
        virLibConnError(VIR_ERR_INVALID_CONN, _("no connection"));
        return NULL;
    }
    virCheckNonNullArgReturn(name, NULL);

    virMutexLock(&conn->lock);

    if (VIR_ALLOC(ret) < 0) {
        virMutexUnlock(&conn->lock);
        virReportOOMError();
        goto error;
    }
    ret->magic = VIR_NODE_DEVICE_MAGIC;
    ret->conn = conn;
    ret->name = strdup(name);
    if (ret->name == NULL) {
        virMutexUnlock(&conn->lock);
        virReportOOMError();
        goto error;
    }

    conn->refs++;
    ret->refs++;
    virMutexUnlock(&conn->lock);
    return ret;

error:
    if (ret != NULL) {
        VIR_FREE(ret->name);
        VIR_FREE(ret);
    }
    return NULL;
}
Exemplo n.º 15
0
int virNetClientStreamEventAddCallback(virNetClientStreamPtr st,
                                       int events,
                                       virNetClientStreamEventCallback cb,
                                       void *opaque,
                                       virFreeCallback ff)
{
    int ret = -1;

    virMutexLock(&st->lock);
    if (st->cb) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("multiple stream callbacks not supported"));
        goto cleanup;
    }

    st->refs++;
    if ((st->cbTimer =
         virEventAddTimeout(-1,
                            virNetClientStreamEventTimer,
                            st,
                            virNetClientStreamEventTimerFree)) < 0) {
        st->refs--;
        goto cleanup;
    }

    st->cb = cb;
    st->cbOpaque = opaque;
    st->cbFree = ff;
    st->cbEvents = events;

    virNetClientStreamEventTimerUpdate(st);

    ret = 0;

cleanup:
    virMutexUnlock(&st->lock);
    return ret;
}
Exemplo n.º 16
0
ssize_t virNetSASLSessionEncode(virNetSASLSessionPtr sasl,
                                const char *input,
                                size_t inputLen,
                                const char **output,
                                size_t *outputlen)
{
    unsigned inlen = inputLen;
    unsigned outlen = 0;
    int err;
    ssize_t ret = -1;

    virMutexLock(&sasl->lock);
    if (inputLen > sasl->maxbufsize) {
        virReportSystemError(EINVAL,
                             _("SASL data length %zu too long, max %zu"),
                             inputLen, sasl->maxbufsize);
        goto cleanup;
    }

    err = sasl_encode(sasl->conn,
                      input,
                      inlen,
                      output,
                      &outlen);
    *outputlen = outlen;

    if (err != SASL_OK) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("failed to encode SASL data: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        goto cleanup;
    }
    ret = 0;

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}
Exemplo n.º 17
0
int
virUnrefDomainSnapshot(virDomainSnapshotPtr snapshot)
{
    int refs;

    if (!VIR_IS_DOMAIN_SNAPSHOT(snapshot)) {
        virLibConnError(VIR_ERR_INVALID_DOMAIN_SNAPSHOT, _("not a snapshot"));
        return -1;
    }

    virMutexLock(&snapshot->domain->conn->lock);
    VIR_DEBUG("unref snapshot %p %s %d", snapshot, snapshot->name, snapshot->refs);
    snapshot->refs--;
    refs = snapshot->refs;
    if (refs == 0) {
        virReleaseDomainSnapshot(snapshot);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&snapshot->domain->conn->lock);
    return refs;
}
Exemplo n.º 18
0
/**
 * virConnectDispose:
 * @conn: the hypervisor connection to release
 *
 * Unconditionally release all memory associated with a connection.
 * The conn.lock mutex must be held prior to calling this, and will
 * be released prior to this returning. The connection obj must not
 * be used once this method returns.
 */
static void
virConnectDispose(void *obj)
{
    virConnectPtr conn = obj;

    if (conn->networkDriver)
        conn->networkDriver->networkClose(conn);
    if (conn->interfaceDriver)
        conn->interfaceDriver->interfaceClose(conn);
    if (conn->storageDriver)
        conn->storageDriver->storageClose(conn);
    if (conn->nodeDeviceDriver)
        conn->nodeDeviceDriver->nodeDeviceClose(conn);
    if (conn->secretDriver)
        conn->secretDriver->secretClose(conn);
    if (conn->nwfilterDriver)
        conn->nwfilterDriver->nwfilterClose(conn);
    if (conn->driver)
        conn->driver->connectClose(conn);

    virMutexLock(&conn->lock);

    virResetError(&conn->err);

    virURIFree(conn->uri);

    if (conn->closeCallback) {
        virObjectLock(conn->closeCallback);
        conn->closeCallback->callback = NULL;
        virObjectUnlock(conn->closeCallback);

        virObjectUnref(conn->closeCallback);
    }

    virMutexUnlock(&conn->lock);
    virMutexDestroy(&conn->lock);
}
Exemplo n.º 19
0
/*
 * Iterate over all timers and determine if any have expired.
 * Invoke the user supplied callback for each timer whose
 * expiry time is met, and schedule the next timeout. Does
 * not try to 'catch up' on time if the actual expiry time
 * was later than the requested time.
 *
 * This method must cope with new timers being registered
 * by a callback, and must skip any timers marked as deleted.
 *
 * Returns 0 upon success, -1 if an error occurred
 */
static int virEventPollDispatchTimeouts(void)
{
    unsigned long long now;
    int i;
    /* Save this now - it may be changed during dispatch */
    int ntimeouts = eventLoop.timeoutsCount;
    VIR_DEBUG("Dispatch %d", ntimeouts);

    if (virTimeMillisNow(&now) < 0)
        return -1;

    for (i = 0 ; i < ntimeouts ; i++) {
        if (eventLoop.timeouts[i].deleted || eventLoop.timeouts[i].frequency < 0)
            continue;

        /* Add 20ms fuzz so we don't pointlessly spin doing
         * <10ms sleeps, particularly on kernels with low HZ
         * it is fine that a timer expires 20ms earlier than
         * requested
         */
        if (eventLoop.timeouts[i].expiresAt <= (now+20)) {
            virEventTimeoutCallback cb = eventLoop.timeouts[i].cb;
            int timer = eventLoop.timeouts[i].timer;
            void *opaque = eventLoop.timeouts[i].opaque;
            eventLoop.timeouts[i].expiresAt =
                now + eventLoop.timeouts[i].frequency;

            PROBE(EVENT_POLL_DISPATCH_TIMEOUT,
                  "timer=%d",
                  timer);
            virMutexUnlock(&eventLoop.lock);
            (cb)(timer, opaque);
            virMutexLock(&eventLoop.lock);
        }
    }
    return 0;
}
Exemplo n.º 20
0
/**
 * virReleaseConnect:
 * @conn: the hypervisor connection to release
 *
 * Unconditionally release all memory associated with a connection.
 * The conn.lock mutex must be held prior to calling this, and will
 * be released prior to this returning. The connection obj must not
 * be used once this method returns.
 */
static void
virReleaseConnect(virConnectPtr conn) {
    VIR_DEBUG("release connection %p", conn);

    /* make sure to release the connection lock before we call the
     * close callbacks, otherwise we will deadlock if an error
     * is raised by any of the callbacks */
    virMutexUnlock(&conn->lock);

    if (conn->networkDriver)
        conn->networkDriver->close(conn);
    if (conn->interfaceDriver)
        conn->interfaceDriver->close(conn);
    if (conn->storageDriver)
        conn->storageDriver->close(conn);
    if (conn->deviceMonitor)
        conn->deviceMonitor->close(conn);
    if (conn->secretDriver)
        conn->secretDriver->close(conn);
    if (conn->nwfilterDriver)
        conn->nwfilterDriver->close(conn);
    if (conn->driver)
        conn->driver->close(conn);

    virMutexLock(&conn->lock);

    if (conn->closeFreeCallback)
        conn->closeFreeCallback(conn->closeOpaque);

    virResetError(&conn->err);

    virURIFree(conn->uri);

    virMutexUnlock(&conn->lock);
    virMutexDestroy(&conn->lock);
    VIR_FREE(conn);
}
Exemplo n.º 21
0
/**
 * virUnrefNWFilter:
 * @nwfilter: the nwfilter to unreference
 *
 * Unreference the networkf itler. If the use count drops to zero, the
 * structure is actually freed.
 *
 * Returns the reference count or -1 in case of failure.
 */
int
virUnrefNWFilter(virNWFilterPtr nwfilter)
{
    int refs;

    if (!VIR_IS_CONNECTED_NWFILTER(nwfilter)) {
        virLibConnError(VIR_ERR_INVALID_NWFILTER,
                        _("bad nwfilter or no connection"));
        return -1;
    }
    virMutexLock(&nwfilter->conn->lock);
    VIR_DEBUG("unref nwfilter %p %s %d", nwfilter, nwfilter->name,
              nwfilter->refs);
    nwfilter->refs--;
    refs = nwfilter->refs;
    if (refs == 0) {
        virReleaseNWFilter(nwfilter);
        /* Already unlocked mutex */
        return 0;
    }

    virMutexUnlock(&nwfilter->conn->lock);
    return refs;
}
Exemplo n.º 22
0
void virEventPollUpdateTimeout(int timer, int frequency)
{
    unsigned long long now;
    int i;
    bool found = false;
    PROBE(EVENT_POLL_UPDATE_TIMEOUT,
          "timer=%d frequency=%d",
          timer, frequency);

    if (timer <= 0) {
        VIR_WARN("Ignoring invalid update timer %d", timer);
        return;
    }

    if (virTimeMillisNow(&now) < 0) {
        return;
    }

    virMutexLock(&eventLoop.lock);
    for (i = 0; i < eventLoop.timeoutsCount; i++) {
        if (eventLoop.timeouts[i].timer == timer) {
            eventLoop.timeouts[i].frequency = frequency;
            eventLoop.timeouts[i].expiresAt =
                frequency >= 0 ? frequency + now : 0;
            VIR_DEBUG("Set timer freq=%d expires=%llu", frequency,
                      eventLoop.timeouts[i].expiresAt);
            virEventPollInterruptLocked();
            found = true;
            break;
        }
    }
    virMutexUnlock(&eventLoop.lock);

    if (!found)
        VIR_WARN("Got update for non-existent timer %d", timer);
}
Exemplo n.º 23
0
void virThreadPoolFree(virThreadPoolPtr pool)
{
    virThreadPoolJobPtr job;
    bool priority = false;

    if (!pool)
        return;

    virMutexLock(&pool->mutex);
    pool->quit = true;
    if (pool->nWorkers > 0)
        virCondBroadcast(&pool->cond);
    if (pool->nPrioWorkers > 0) {
        priority = true;
        virCondBroadcast(&pool->prioCond);
    }

    while (pool->nWorkers > 0 || pool->nPrioWorkers > 0)
        ignore_value(virCondWait(&pool->quit_cond, &pool->mutex));

    while ((job = pool->jobList.head)) {
        pool->jobList.head = pool->jobList.head->next;
        VIR_FREE(job);
    }

    VIR_FREE(pool->workers);
    virMutexUnlock(&pool->mutex);
    virMutexDestroy(&pool->mutex);
    virCondDestroy(&pool->quit_cond);
    virCondDestroy(&pool->cond);
    if (priority) {
        VIR_FREE(pool->prioWorkers);
        virCondDestroy(&pool->prioCond);
    }
    VIR_FREE(pool);
}
static int virFDStreamRemoveCallback(virStreamPtr stream)
{
    struct virFDStreamData *fdst = stream->privateData;
    int ret = -1;

    if (!fdst) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("stream is not open"));
        return -1;
    }

    virMutexLock(&fdst->lock);
    if (fdst->watch == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("stream does not have a callback registered"));
        goto cleanup;
    }

    virEventRemoveHandle(fdst->watch);
    if (fdst->dispatching)
        fdst->cbRemoved = true;
    else if (fdst->ff)
        (fdst->ff)(fdst->opaque);

    fdst->watch = 0;
    fdst->ff = NULL;
    fdst->cb = NULL;
    fdst->events = 0;
    fdst->opaque = NULL;

    ret = 0;

 cleanup:
    virMutexUnlock(&fdst->lock);
    return ret;
}
Exemplo n.º 25
0
/**
 * virObjectEventStateLock:
 * @state: the event state object
 *
 * Lock event state before calling functions from object_event_private.h.
 */
static void
virObjectEventStateLock(virObjectEventStatePtr state)
{
    virMutexLock(&state->lock);
}
Exemplo n.º 26
0
void
bhyveDriverLock(bhyveConnPtr driver)
{
    virMutexLock(&driver->lock);
}
Exemplo n.º 27
0
/*
 * Callback that gets invoked when a stream becomes writable/readable
 */
static void
daemonStreamEvent(virStreamPtr st, int events, void *opaque)
{
    virNetServerClientPtr client = opaque;
    daemonClientStream *stream;
    daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);

    virMutexLock(&priv->lock);

    stream = priv->streams;
    while (stream) {
        if (stream->st == st)
            break;
        stream = stream->next;
    }

    if (!stream) {
        VIR_WARN("event for client=%p stream st=%p, but missing stream state", client, st);
        virStreamEventRemoveCallback(st);
        goto cleanup;
    }

    VIR_DEBUG("st=%p events=%d EOF=%d closed=%d", st, events, stream->recvEOF, stream->closed);

    if (!stream->closed &&
        (events & VIR_STREAM_EVENT_WRITABLE)) {
        if (daemonStreamHandleWrite(client, stream) < 0) {
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
    }

    if (!stream->closed && !stream->recvEOF &&
        (events & (VIR_STREAM_EVENT_READABLE))) {
        events = events & ~(VIR_STREAM_EVENT_READABLE);
        if (daemonStreamHandleRead(client, stream) < 0) {
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
        /* If we detected EOF during read processing,
         * then clear hangup/error conditions, since
         * we want the client to see the EOF message
         * we just sent them
         */
        if (stream->recvEOF)
            events = events & ~(VIR_STREAM_EVENT_HANGUP |
                                VIR_STREAM_EVENT_ERROR);
    }

    /* If we have a completion/abort message, always process it */
    if (stream->rx) {
        virNetMessagePtr msg = stream->rx;
        switch (msg->header.status) {
        case VIR_NET_CONTINUE:
            /* nada */
            break;
        case VIR_NET_OK:
            virNetMessageQueueServe(&stream->rx);
            if (daemonStreamHandleFinish(client, stream, msg) < 0) {
                virNetMessageFree(msg);
                daemonRemoveClientStream(client, stream);
                virNetServerClientClose(client);
                goto cleanup;
            }
            break;
        case VIR_NET_ERROR:
        default:
            virNetMessageQueueServe(&stream->rx);
            if (daemonStreamHandleAbort(client, stream, msg) < 0) {
                virNetMessageFree(msg);
                daemonRemoveClientStream(client, stream);
                virNetServerClientClose(client);
                goto cleanup;
            }
            break;
        }
    }


    /* If we got HANGUP, we need to only send an empty
     * packet so the client sees an EOF and cleans up
     */
    if (!stream->closed && !stream->recvEOF &&
        (events & VIR_STREAM_EVENT_HANGUP)) {
        virNetMessagePtr msg;
        events &= ~(VIR_STREAM_EVENT_HANGUP);
        stream->tx = 0;
        stream->recvEOF = 1;
        if (!(msg = virNetMessageNew(false))) {
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
        msg->cb = daemonStreamMessageFinished;
        msg->opaque = stream;
        stream->refs++;
        if (virNetServerProgramSendStreamData(remoteProgram,
                                              client,
                                              msg,
                                              stream->procedure,
                                              stream->serial,
                                              "", 0) < 0) {
            virNetMessageFree(msg);
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
    }

    if (!stream->closed &&
        (events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) {
        int ret;
        virNetMessagePtr msg;
        virNetMessageError rerr;

        memset(&rerr, 0, sizeof(rerr));
        stream->closed = 1;
        virStreamEventRemoveCallback(stream->st);
        virStreamAbort(stream->st);
        if (events & VIR_STREAM_EVENT_HANGUP)
            virReportError(VIR_ERR_RPC,
                           "%s", _("stream had unexpected termination"));
        else
            virReportError(VIR_ERR_RPC,
                           "%s", _("stream had I/O failure"));

        msg = virNetMessageNew(false);
        if (!msg) {
            ret = -1;
        } else {
            ret = virNetServerProgramSendStreamError(remoteProgram,
                                                     client,
                                                     msg,
                                                     &rerr,
                                                     stream->procedure,
                                                     stream->serial);
        }
        daemonRemoveClientStream(client, stream);
        if (ret < 0)
            virNetServerClientClose(client);
        goto cleanup;
    }

    if (stream->closed) {
        daemonRemoveClientStream(client, stream);
    } else {
        daemonStreamUpdateEvents(stream);
    }

cleanup:
    virMutexUnlock(&priv->lock);
}
Exemplo n.º 28
0
void
virNWFilterObjLock(virNWFilterObjPtr obj)
{
    virMutexLock(&obj->lock);
}
static int
virFDStreamCloseInt(virStreamPtr st, bool streamAbort)
{
    struct virFDStreamData *fdst;
    virStreamEventCallback cb;
    void *opaque;
    int ret;

    VIR_DEBUG("st=%p", st);

    if (!st || !(fdst = st->privateData) || fdst->abortCallbackDispatching)
        return 0;

    virMutexLock(&fdst->lock);

    /* aborting the stream, ensure the callback is called if it's
     * registered for stream error event */
    if (streamAbort &&
        fdst->cb &&
        (fdst->events & (VIR_STREAM_EVENT_READABLE |
                         VIR_STREAM_EVENT_WRITABLE))) {
        /* don't enter this function accidentally from the callback again */
        if (fdst->abortCallbackCalled) {
            virMutexUnlock(&fdst->lock);
            return 0;
        }

        fdst->abortCallbackCalled = true;
        fdst->abortCallbackDispatching = true;

        /* cache the pointers */
        cb = fdst->cb;
        opaque = fdst->opaque;
        virMutexUnlock(&fdst->lock);

        /* call failure callback, poll reports nothing on closed fd */
        (cb)(st, VIR_STREAM_EVENT_ERROR, opaque);

        virMutexLock(&fdst->lock);
        fdst->abortCallbackDispatching = false;
    }

    /* mutex locked */
    ret = VIR_CLOSE(fdst->fd);
    if (fdst->cmd) {
        char buf[1024];
        ssize_t len;
        int status;
        if ((len = saferead(fdst->errfd, buf, sizeof(buf)-1)) < 0)
            buf[0] = '\0';
        else
            buf[len] = '\0';

        virCommandRawStatus(fdst->cmd);
        if (virCommandWait(fdst->cmd, &status) < 0) {
            ret = -1;
        } else if (status != 0) {
            if (buf[0] == '\0') {
                if (WIFEXITED(status)) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("I/O helper exited with status %d"),
                                   WEXITSTATUS(status));
                } else {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("I/O helper exited abnormally"));
                }
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               buf);
            }
            ret = -1;
        }
        virCommandFree(fdst->cmd);
        fdst->cmd = NULL;
    }

    if (VIR_CLOSE(fdst->errfd) < 0)
        VIR_DEBUG("ignoring failed close on fd %d", fdst->errfd);

    st->privateData = NULL;

    /* call the internal stream closing callback */
    if (fdst->icbCb) {
        /* the mutex is not accessible anymore, as private data is null */
        (fdst->icbCb)(st, fdst->icbOpaque);
        if (fdst->icbFreeOpaque)
            (fdst->icbFreeOpaque)(fdst->icbOpaque);
    }

    if (fdst->dispatching) {
        fdst->closed = true;
        virMutexUnlock(&fdst->lock);
    } else {
        virMutexUnlock(&fdst->lock);
        virMutexDestroy(&fdst->lock);
        VIR_FREE(fdst);
    }

    return ret;
}
Exemplo n.º 30
0
static void nwfilterDriverLock(virNWFilterDriverStatePtr driver)
{
    virMutexLock(&driver->lock);
}