Commit b89d92f3 authored by Stefan Hajnoczi's avatar Stefan Hajnoczi
Browse files

block: add aio_wait_bh_oneshot()



Sometimes it's necessary for the main loop thread to run a BH in an
IOThread and wait for its completion.  This primitive is useful during
startup/shutdown to synchronize and avoid race conditions.

Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarFam Zheng <famz@redhat.com>
Acked-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Message-id: 20180307144205.20619-2-stefanha@redhat.com
Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parent 12c1c7d7
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -113,4 +113,17 @@ typedef struct {
 */
void aio_wait_kick(AioWait *wait);

/**
 * aio_wait_bh_oneshot:
 * @ctx: the aio context
 * @cb: the BH callback function
 * @opaque: user data for the BH callback function
 *
 * Run a BH in @ctx and wait for it to complete.
 *
 * Must be called from the main loop thread with @ctx acquired exactly once.
 * Note that main loop event processing may occur.
 */
void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);

#endif /* QEMU_AIO_WAIT */
+31 −0
Original line number Diff line number Diff line
@@ -38,3 +38,34 @@ void aio_wait_kick(AioWait *wait)
        aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL);
    }
}

typedef struct {
    AioWait wait;
    bool done;
    QEMUBHFunc *cb;
    void *opaque;
} AioWaitBHData;

/* Context: BH in IOThread */
static void aio_wait_bh(void *opaque)
{
    AioWaitBHData *data = opaque;

    data->cb(data->opaque);

    data->done = true;
    aio_wait_kick(&data->wait);
}

void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
{
    AioWaitBHData data = {
        .cb = cb,
        .opaque = opaque,
    };

    assert(qemu_get_current_aio_context() == qemu_get_aio_context());

    aio_bh_schedule_oneshot(ctx, aio_wait_bh, &data);
    AIO_WAIT_WHILE(&data.wait, ctx, !data.done);
}