Commit a098fbc0 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging



# gpg: Signature made Mon 18 Jul 2016 17:58:27 BST
# gpg:                using RSA key 0x9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/block-pull-request:
  MAINTAINERS: Add include/block/aio.h to block I/O path section
  virtio-blk: dataplane cleanup
  checkpatch: consider git extended headers valid patches
  aio-posix: remove useless parameter
  linux-aio: prevent submitting more than MAX_EVENTS
  aio_ctx_check: follow CODING_STYLE
  linux-aio: share one LinuxAioState within an AioContext
  spec/parallels: fix a mistake

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 3913d370 e1029ae2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1027,6 +1027,7 @@ F: async.c
F: aio-*.c
F: block/io.c
F: migration/block*
F: include/block/aio.h
T: git git://github.com/stefanha/qemu.git block

Block Jobs
+2 −1
Original line number Diff line number Diff line
@@ -485,12 +485,13 @@ bool aio_poll(AioContext *ctx, bool blocking)
    return progress;
}

void aio_context_setup(AioContext *ctx, Error **errp)
void aio_context_setup(AioContext *ctx)
{
#ifdef CONFIG_EPOLL_CREATE1
    assert(!ctx->epollfd);
    ctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
    if (ctx->epollfd == -1) {
        fprintf(stderr, "Failed to create epoll instance: %s", strerror(errno));
        ctx->epoll_available = false;
    } else {
        ctx->epoll_available = true;
+1 −1
Original line number Diff line number Diff line
@@ -371,6 +371,6 @@ bool aio_poll(AioContext *ctx, bool blocking)
    return progress;
}

void aio_context_setup(AioContext *ctx, Error **errp)
void aio_context_setup(AioContext *ctx)
{
}
+26 −7
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "block/thread-pool.h"
#include "qemu/main-loop.h"
#include "qemu/atomic.h"
#include "block/raw-aio.h"

/***********************************************************/
/* bottom halves (can be seen as timers which expire ASAP) */
@@ -242,6 +243,14 @@ aio_ctx_finalize(GSource *source)
    qemu_bh_delete(ctx->notify_dummy_bh);
    thread_pool_free(ctx->thread_pool);

#ifdef CONFIG_LINUX_AIO
    if (ctx->linux_aio) {
        laio_detach_aio_context(ctx->linux_aio, ctx);
        laio_cleanup(ctx->linux_aio);
        ctx->linux_aio = NULL;
    }
#endif

    qemu_mutex_lock(&ctx->bh_lock);
    while (ctx->first_bh) {
        QEMUBH *next = ctx->first_bh->next;
@@ -282,6 +291,17 @@ ThreadPool *aio_get_thread_pool(AioContext *ctx)
    return ctx->thread_pool;
}

#ifdef CONFIG_LINUX_AIO
LinuxAioState *aio_get_linux_aio(AioContext *ctx)
{
    if (!ctx->linux_aio) {
        ctx->linux_aio = laio_init();
        laio_attach_aio_context(ctx->linux_aio, ctx);
    }
    return ctx->linux_aio;
}
#endif

void aio_notify(AioContext *ctx)
{
    /* Write e.g. bh->scheduled before reading ctx->notify_me.  Pairs
@@ -327,14 +347,10 @@ AioContext *aio_context_new(Error **errp)
{
    int ret;
    AioContext *ctx;
    Error *local_err = NULL;

    ctx = (AioContext *) g_source_new(&aio_source_funcs, sizeof(AioContext));
    aio_context_setup(ctx, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        goto fail;
    }
    aio_context_setup(ctx);

    ret = event_notifier_init(&ctx->notifier, false);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Failed to initialize event notifier");
@@ -345,6 +361,9 @@ AioContext *aio_context_new(Error **errp)
                           false,
                           (EventNotifierHandler *)
                           event_notifier_dummy_cb);
#ifdef CONFIG_LINUX_AIO
    ctx->linux_aio = NULL;
#endif
    ctx->thread_pool = NULL;
    qemu_mutex_init(&ctx->bh_lock);
    rfifolock_init(&ctx->lock, aio_rfifolock_cb, ctx);
+22 −14
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@
 */
#define MAX_EVENTS 128

#define MAX_QUEUED_IO  128

struct qemu_laiocb {
    BlockAIOCB common;
    Coroutine *co;
@@ -44,12 +42,15 @@ struct qemu_laiocb {

typedef struct {
    int plugged;
    unsigned int n;
    unsigned int in_queue;
    unsigned int in_flight;
    bool blocked;
    QSIMPLEQ_HEAD(, qemu_laiocb) pending;
} LaioQueue;

struct LinuxAioState {
    AioContext *aio_context;

    io_context_t ctx;
    EventNotifier e;

@@ -129,6 +130,7 @@ static void qemu_laio_completion_bh(void *opaque)
            s->event_max = 0;
            return; /* no more events */
        }
        s->io_q.in_flight -= s->event_max;
    }

    /* Reschedule so nested event loops see currently pending completions */
@@ -190,7 +192,8 @@ static void ioq_init(LaioQueue *io_q)
{
    QSIMPLEQ_INIT(&io_q->pending);
    io_q->plugged = 0;
    io_q->n = 0;
    io_q->in_queue = 0;
    io_q->in_flight = 0;
    io_q->blocked = false;
}

@@ -198,14 +201,17 @@ static void ioq_submit(LinuxAioState *s)
{
    int ret, len;
    struct qemu_laiocb *aiocb;
    struct iocb *iocbs[MAX_QUEUED_IO];
    struct iocb *iocbs[MAX_EVENTS];
    QSIMPLEQ_HEAD(, qemu_laiocb) completed;

    do {
        if (s->io_q.in_flight >= MAX_EVENTS) {
            break;
        }
        len = 0;
        QSIMPLEQ_FOREACH(aiocb, &s->io_q.pending, next) {
            iocbs[len++] = &aiocb->iocb;
            if (len == MAX_QUEUED_IO) {
            if (s->io_q.in_flight + len >= MAX_EVENTS) {
                break;
            }
        }
@@ -218,24 +224,24 @@ static void ioq_submit(LinuxAioState *s)
            abort();
        }

        s->io_q.n -= ret;
        s->io_q.in_flight += ret;
        s->io_q.in_queue  -= ret;
        aiocb = container_of(iocbs[ret - 1], struct qemu_laiocb, iocb);
        QSIMPLEQ_SPLIT_AFTER(&s->io_q.pending, aiocb, next, &completed);
    } while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending));
    s->io_q.blocked = (s->io_q.n > 0);
    s->io_q.blocked = (s->io_q.in_queue > 0);
}

void laio_io_plug(BlockDriverState *bs, LinuxAioState *s)
{
    assert(!s->io_q.plugged);
    s->io_q.plugged = 1;
    s->io_q.plugged++;
}

void laio_io_unplug(BlockDriverState *bs, LinuxAioState *s)
{
    assert(s->io_q.plugged);
    s->io_q.plugged = 0;
    if (!s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
    if (--s->io_q.plugged == 0 &&
        !s->io_q.blocked && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
        ioq_submit(s);
    }
}
@@ -263,9 +269,10 @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
    io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));

    QSIMPLEQ_INSERT_TAIL(&s->io_q.pending, laiocb, next);
    s->io_q.n++;
    s->io_q.in_queue++;
    if (!s->io_q.blocked &&
        (!s->io_q.plugged || s->io_q.n >= MAX_QUEUED_IO)) {
        (!s->io_q.plugged ||
         s->io_q.in_flight + s->io_q.in_queue >= MAX_EVENTS)) {
        ioq_submit(s);
    }

@@ -325,6 +332,7 @@ void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)

void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context)
{
    s->aio_context = new_context;
    s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
    aio_set_event_notifier(new_context, &s->e, false,
                           qemu_laio_completion_cb);
Loading