예제 #1
0
static void test_notify(void)
{
    g_assert(!aio_poll(ctx, false));
    aio_notify(ctx);
    g_assert(!aio_poll(ctx, true));
    g_assert(!aio_poll(ctx, false));
}
예제 #2
0
파일: test-aio.c 프로젝트: AmesianX/panda
static void test_acquire(void)
{
    QemuThread thread;
    AcquireTestData data;

    /* Dummy event notifier ensures aio_poll() will block */
    event_notifier_init(&data.notifier, false);
    set_event_notifier(ctx, &data.notifier, dummy_notifier_read);
    g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */

    qemu_mutex_init(&data.start_lock);
    qemu_mutex_lock(&data.start_lock);
    data.thread_acquired = false;

    qemu_thread_create(&thread, "test_acquire_thread",
                       test_acquire_thread,
                       &data, QEMU_THREAD_JOINABLE);

    /* Block in aio_poll(), let other thread kick us and acquire context */
    aio_context_acquire(ctx);
    qemu_mutex_unlock(&data.start_lock); /* let the thread run */
    g_assert(aio_poll(ctx, true));
    g_assert(!data.thread_acquired);
    aio_context_release(ctx);

    qemu_thread_join(&thread);
    set_event_notifier(ctx, &data.notifier, NULL);
    event_notifier_cleanup(&data.notifier);

    g_assert(data.thread_acquired);
}
예제 #3
0
static void test_flush(void)
{
    g_assert(!aio_poll(ctx, false));
    aio_notify(ctx);
    aio_flush(ctx);
    g_assert(!aio_poll(ctx, false));
}
예제 #4
0
파일: iothread.c 프로젝트: pfliu/qemu
static void *iothread_run(void *opaque)
{
    IOThread *iothread = opaque;

    rcu_register_thread();

    my_iothread = iothread;
    qemu_mutex_lock(&iothread->init_done_lock);
    iothread->thread_id = qemu_get_thread_id();
    qemu_cond_signal(&iothread->init_done_cond);
    qemu_mutex_unlock(&iothread->init_done_lock);

    while (iothread->running) {
        aio_poll(iothread->ctx, true);

        if (atomic_read(&iothread->worker_context)) {
            GMainLoop *loop;

            g_main_context_push_thread_default(iothread->worker_context);
            iothread->main_loop =
                g_main_loop_new(iothread->worker_context, TRUE);
            loop = iothread->main_loop;

            g_main_loop_run(iothread->main_loop);
            iothread->main_loop = NULL;
            g_main_loop_unref(loop);

            g_main_context_pop_thread_default(iothread->worker_context);
        }
    }

    rcu_unregister_thread();
    return NULL;
}
예제 #5
0
파일: iothread.c 프로젝트: 01org/qemu-lite
static void *iothread_run(void *opaque)
{
    IOThread *iothread = opaque;
    bool blocking;

    rcu_register_thread();

    qemu_mutex_lock(&iothread->init_done_lock);
    iothread->thread_id = qemu_get_thread_id();
    qemu_cond_signal(&iothread->init_done_cond);
    qemu_mutex_unlock(&iothread->init_done_lock);

    while (!iothread->stopping) {
        aio_context_acquire(iothread->ctx);
        blocking = true;
        while (!iothread->stopping && aio_poll(iothread->ctx, blocking)) {
            /* Progress was made, keep going */
            blocking = false;
        }
        aio_context_release(iothread->ctx);
    }

    rcu_unregister_thread();
    return NULL;
}
예제 #6
0
static void test_pair_jobs_fail_cancel_race(void)
{
    BlockJob *job1;
    BlockJob *job2;
    BlockJobTxn *txn;
    int result1 = -EINPROGRESS;
    int result2 = -EINPROGRESS;

    txn = block_job_txn_new();
    job1 = test_block_job_start(1, true, -ECANCELED, &result1, txn);
    job2 = test_block_job_start(2, false, 0, &result2, txn);
    block_job_start(job1);
    block_job_start(job2);

    block_job_cancel(job1, false);

    /* Now make job2 finish before the main loop kicks jobs.  This simulates
     * the race between a pending kick and another job completing.
     */
    block_job_enter(job2);
    block_job_enter(job2);

    while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
        aio_poll(qemu_get_aio_context(), true);
    }

    g_assert_cmpint(result1, ==, -ECANCELED);
    g_assert_cmpint(result2, ==, -ECANCELED);

    block_job_txn_unref(txn);
}
예제 #7
0
파일: blockjob.c 프로젝트: jansonzhou/qemu
static int block_job_finish_sync(BlockJob *job,
                                 void (*finish)(BlockJob *, Error **errp),
                                 Error **errp)
{
    struct BlockFinishData data;
    BlockDriverState *bs = job->bs;
    Error *local_err = NULL;

    assert(bs->job == job);

    /* Set up our own callback to store the result and chain to
     * the original callback.
     */
    data.job = job;
    data.cb = job->cb;
    data.opaque = job->opaque;
    data.ret = -EINPROGRESS;
    job->cb = block_job_finish_cb;
    job->opaque = &data;
    finish(job, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return -EBUSY;
    }
    while (data.ret == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(bs), true);
    }
    return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
}
예제 #8
0
static void qemu_archipelago_aio_cancel(BlockDriverAIOCB *blockacb)
{
    ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) blockacb;
    aio_cb->cancelled = true;
    while (aio_cb->status == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(aio_cb->common.bs), true);
    }
    qemu_aio_release(aio_cb);
}
예제 #9
0
static gboolean
aio_ctx_dispatch(GSource     *source,
                 GSourceFunc  callback,
                 gpointer     user_data)
{
    AioContext *ctx = (AioContext *) source;

    assert(callback == NULL);
    aio_poll(ctx, false);
    return true;
}
예제 #10
0
int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset)
{
    int ret = -EINPROGRESS;

    qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(s->bs), true);
    }

    return ret;
}
예제 #11
0
파일: rbd.c 프로젝트: Arch-Linux-MIPS/qemu
/*
 * Cancel aio. Since we don't reference acb in a non qemu threads,
 * it is safe to access it here.
 */
static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
{
    RBDAIOCB *acb = (RBDAIOCB *) blockacb;
    acb->cancelled = 1;

    while (acb->status == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(acb->common.bs), true);
    }

    qemu_aio_release(acb);
}
예제 #12
0
int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
                            unsigned int n)
{
    int ret = -EINPROGRESS;

    qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(s->bs), true);
    }

    return ret;
}
예제 #13
0
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
{
    BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
    AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
    bool finished = false;

    /* Wait until request completes, invokes its callback, and frees itself */
    acb->finished = &finished;
    while (!finished) {
        aio_poll(aio_context, true);
    }
}
예제 #14
0
int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
                            unsigned int index, unsigned int n, bool flush)
{
    int ret = -EINPROGRESS;

    qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(s->bs), true);
    }

    return ret;
}
예제 #15
0
static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
{
    QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;

    /*
     * CancelIoEx is only supported in Vista and newer.  For now, just
     * wait for completion.
     */
    while (!HasOverlappedIoCompleted(&waiocb->ov)) {
        aio_poll(bdrv_get_aio_context(blockacb->bs), true);
    }
}
예제 #16
0
파일: qed.c 프로젝트: MauroZurita/qemu
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
{
    QEDAIOCB *acb = (QEDAIOCB *)blockacb;
    AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
    bool finished = false;

    /* Wait for the request to finish */
    acb->finished = &finished;
    while (!finished) {
        aio_poll(aio_context, true);
    }
}
예제 #17
0
int qed_read_l1_table_sync(BDRVQEDState *s)
{
    int ret = -EINPROGRESS;

    qed_read_table(s, s->header.l1_table_offset,
                   s->l1_table, qed_sync_cb, &ret);
    while (ret == -EINPROGRESS) {
        aio_poll(bdrv_get_aio_context(s->bs), true);
    }

    return ret;
}
예제 #18
0
파일: iothread.c 프로젝트: EternalKeel/qemu
static void *iothread_run(void *opaque)
{
    IOThread *iothread = opaque;

    rcu_register_thread();

    my_iothread = iothread;
    qemu_mutex_lock(&iothread->init_done_lock);
    iothread->thread_id = qemu_get_thread_id();
    qemu_cond_signal(&iothread->init_done_cond);
    qemu_mutex_unlock(&iothread->init_done_lock);

    while (!atomic_read(&iothread->stopping)) {
        aio_poll(iothread->ctx, true);
    }

    rcu_unregister_thread();
    return NULL;
}
예제 #19
0
static void test_single_job(int expected)
{
    BlockJob *job;
    BlockJobTxn *txn;
    int result = -EINPROGRESS;

    txn = block_job_txn_new();
    job = test_block_job_start(1, true, expected, &result, txn);
    block_job_start(job);

    if (expected == -ECANCELED) {
        block_job_cancel(job, false);
    }

    while (result == -EINPROGRESS) {
        aio_poll(qemu_get_aio_context(), true);
    }
    g_assert_cmpint(result, ==, expected);

    block_job_txn_unref(txn);
}
예제 #20
0
static void test_pair_jobs(int expected1, int expected2)
{
    BlockJob *job1;
    BlockJob *job2;
    BlockJobTxn *txn;
    int result1 = -EINPROGRESS;
    int result2 = -EINPROGRESS;

    txn = block_job_txn_new();
    job1 = test_block_job_start(1, true, expected1, &result1, txn);
    job2 = test_block_job_start(2, true, expected2, &result2, txn);
    block_job_start(job1);
    block_job_start(job2);

    /* Release our reference now to trigger as many nice
     * use-after-free bugs as possible.
     */
    block_job_txn_unref(txn);

    if (expected1 == -ECANCELED) {
        block_job_cancel(job1, false);
    }
    if (expected2 == -ECANCELED) {
        block_job_cancel(job2, false);
    }

    while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
        aio_poll(qemu_get_aio_context(), true);
    }

    /* Failure or cancellation of one job cancels the other job */
    if (expected1 != 0) {
        expected2 = -ECANCELED;
    } else if (expected2 != 0) {
        expected1 = -ECANCELED;
    }

    g_assert_cmpint(result1, ==, expected1);
    g_assert_cmpint(result2, ==, expected2);
}
예제 #21
0
static void test_pair_jobs(int expected1, int expected2)
{
    BlockJob *job1;
    BlockJob *job2;
    BlockJobTxn *txn;
    int result1 = -EINPROGRESS;
    int result2 = -EINPROGRESS;

    txn = block_job_txn_new();
    job1 = test_block_job_start(1, true, expected1, &result1);
    block_job_txn_add_job(txn, job1);
    job2 = test_block_job_start(2, true, expected2, &result2);
    block_job_txn_add_job(txn, job2);

    if (expected1 == -ECANCELED) {
        block_job_cancel(job1);
    }
    if (expected2 == -ECANCELED) {
        block_job_cancel(job2);
    }

    while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
        aio_poll(qemu_get_aio_context(), true);
    }

    /* Failure or cancellation of one job cancels the other job */
    if (expected1 != 0) {
        expected2 = -ECANCELED;
    } else if (expected2 != 0) {
        expected1 = -ECANCELED;
    }

    g_assert_cmpint(result1, ==, expected1);
    g_assert_cmpint(result2, ==, expected2);

    block_job_txn_unref(txn);
}
예제 #22
0
bool qemu_aio_wait(void)
{
    return aio_poll(qemu_aio_context, true);
}
예제 #23
0
파일: test-aio.c 프로젝트: AmesianX/panda
/* Wait until event notifier becomes inactive */
static void wait_until_inactive(EventNotifierTestData *data)
{
    while (data->active > 0) {
        aio_poll(ctx, true);
    }
}
예제 #24
0
파일: test-aio.c 프로젝트: AmesianX/panda
    qemu_thread_join(&thread);
    set_event_notifier(ctx, &data.notifier, NULL);
    event_notifier_cleanup(&data.notifier);

    g_assert(data.thread_acquired);
}

static void test_bh_schedule(void)
{
    BHTestData data = { .n = 0 };
    data.bh = aio_bh_new(ctx, bh_test_cb, &data);

    qemu_bh_schedule(data.bh);
    g_assert_cmpint(data.n, ==, 0);

    g_assert(aio_poll(ctx, true));
    g_assert_cmpint(data.n, ==, 1);

    g_assert(!aio_poll(ctx, false));
    g_assert_cmpint(data.n, ==, 1);
    qemu_bh_delete(data.bh);
}

static void test_bh_schedule10(void)
{
    BHTestData data = { .n = 0, .max = 10 };
    data.bh = aio_bh_new(ctx, bh_test_cb, &data);

    qemu_bh_schedule(data.bh);
    g_assert_cmpint(data.n, ==, 0);
예제 #25
0
파일: curl.c 프로젝트: Distrotech/qemu
static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
{
    CURLState *state = NULL;
    int i, j;

    do {
        for (i=0; i<CURL_NUM_STATES; i++) {
            for (j=0; j<CURL_NUM_ACB; j++)
                if (s->states[i].acb[j])
                    continue;
            if (s->states[i].in_use)
                continue;

            state = &s->states[i];
            state->in_use = 1;
            break;
        }
        if (!state) {
            aio_poll(bdrv_get_aio_context(bs), true);
        }
    } while(!state);

    if (!state->curl) {
        state->curl = curl_easy_init();
        if (!state->curl) {
            return NULL;
        }
        curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
        curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER,
                         (long) s->sslverify);
        if (s->cookie) {
            curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie);
        }
        curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout);
        curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
                         (void *)curl_read_cb);
        curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
        curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
        curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
        curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
        curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);

        /* Restrict supported protocols to avoid security issues in the more
         * obscure protocols.  For example, do not allow POP3/SMTP/IMAP see
         * CVE-2013-0249.
         *
         * Restricting protocols is only supported from 7.19.4 upwards.
         */
#if LIBCURL_VERSION_NUM >= 0x071304
        curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
        curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
#endif

#ifdef DEBUG_VERBOSE
        curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
#endif
    }

    state->s = s;

    return state;
}
예제 #26
0
/* Wait until there are no more BHs or AIO requests */
static void wait_for_aio(void)
{
    while (aio_poll(ctx, true)) {
        /* Do nothing */
    }
}