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

Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging



Block layer patches

# gpg: Signature made Mon 09 Jan 2017 13:43:44 GMT
# gpg:                using RSA key 0x7F09B272C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
# Primary key fingerprint: DC3D EB15 9A9A F95D 3D74  56FE 7F09 B272 C88F 2FD6

* remotes/kevin/tags/for-upstream:
  block: Rename raw-{posix,win32} to file-*.c
  block: Rename raw_bsd to raw-format.c
  blkverify: Implement bdrv_co_preadv/pwritev/flush
  blkdebug: Implement bdrv_co_preadv/pwritev/flush
  quorum: Clean up quorum_aio_get()
  quorum: Inline quorum_fifo_aio_cb()
  quorum: Implement .bdrv_co_preadv/pwritev()
  quorum: Avoid bdrv_aio_writev() for rewrites
  quorum: Inline quorum_aio_cb()
  quorum: Do cleanup in caller coroutine
  quorum: Implement .bdrv_co_readv/writev
  quorum: Remove s from quorum_aio_get() arguments
  coroutine: Introduce qemu_coroutine_enter_if_inactive()
  qemu-img: fix in-flight count for qemu-img bench

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 8305f9bd c1bb86cd
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -1718,9 +1718,9 @@ L: qemu-block@nongnu.org
S: Supported
F: block/linux-aio.c
F: include/block/raw-aio.h
F: block/raw-posix.c
F: block/raw-win32.c
F: block/raw_bsd.c
F: block/raw-format.c
F: block/file-posix.c
F: block/file-win32.c
F: block/win32-aio.c

qcow2
+3 −3
Original line number Diff line number Diff line
block-obj-y += raw_bsd.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o
@@ -6,8 +6,8 @@ block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
block-obj-y += quorum.o
block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o
block-obj-y += block-backend.o snapshot.o qapi.o
block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
block-obj-$(CONFIG_POSIX) += raw-posix.o
block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
block-obj-$(CONFIG_POSIX) += file-posix.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
block-obj-y += null.o mirror.o commit.o io.o
block-obj-y += throttle-groups.o
+40 −46
Original line number Diff line number Diff line
@@ -58,10 +58,6 @@ typedef struct BlkdebugSuspendedReq {
    QLIST_ENTRY(BlkdebugSuspendedReq) next;
} BlkdebugSuspendedReq;

static const AIOCBInfo blkdebug_aiocb_info = {
    .aiocb_size    = sizeof(BlkdebugAIOCB),
};

enum {
    ACTION_INJECT_ERROR,
    ACTION_SET_STATE,
@@ -77,7 +73,7 @@ typedef struct BlkdebugRule {
            int error;
            int immediately;
            int once;
            int64_t sector;
            int64_t offset;
        } inject;
        struct {
            int new_state;
@@ -174,6 +170,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
    const char* event_name;
    BlkdebugEvent event;
    struct BlkdebugRule *rule;
    int64_t sector;

    /* Find the right event for the rule */
    event_name = qemu_opt_get(opts, "event");
@@ -200,7 +197,9 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
        rule->options.inject.once  = qemu_opt_get_bool(opts, "once", 0);
        rule->options.inject.immediately =
            qemu_opt_get_bool(opts, "immediately", 0);
        rule->options.inject.sector = qemu_opt_get_number(opts, "sector", -1);
        sector = qemu_opt_get_number(opts, "sector", -1);
        rule->options.inject.offset =
            sector == -1 ? -1 : sector * BDRV_SECTOR_SIZE;
        break;

    case ACTION_SET_STATE:
@@ -408,17 +407,14 @@ out:

static void error_callback_bh(void *opaque)
{
    struct BlkdebugAIOCB *acb = opaque;
    acb->common.cb(acb->common.opaque, acb->ret);
    qemu_aio_unref(acb);
    Coroutine *co = opaque;
    qemu_coroutine_enter(co);
}

static BlockAIOCB *inject_error(BlockDriverState *bs,
    BlockCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
static int inject_error(BlockDriverState *bs, BlkdebugRule *rule)
{
    BDRVBlkdebugState *s = bs->opaque;
    int error = rule->options.inject.error;
    struct BlkdebugAIOCB *acb;
    bool immediately = rule->options.inject.immediately;

    if (rule->options.inject.once) {
@@ -426,81 +422,79 @@ static BlockAIOCB *inject_error(BlockDriverState *bs,
        remove_rule(rule);
    }

    if (immediately) {
        return NULL;
    if (!immediately) {
        aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), error_callback_bh,
                                qemu_coroutine_self());
        qemu_coroutine_yield();
    }

    acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
    acb->ret = -error;

    aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), error_callback_bh, acb);

    return &acb->common;
    return -error;
}

static BlockAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
    BlockCompletionFunc *cb, void *opaque)
static int coroutine_fn
blkdebug_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                   QEMUIOVector *qiov, int flags)
{
    BDRVBlkdebugState *s = bs->opaque;
    BlkdebugRule *rule = NULL;

    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
        if (rule->options.inject.sector == -1 ||
            (rule->options.inject.sector >= sector_num &&
             rule->options.inject.sector < sector_num + nb_sectors)) {
        uint64_t inject_offset = rule->options.inject.offset;

        if (inject_offset == -1 ||
            (inject_offset >= offset && inject_offset < offset + bytes))
        {
            break;
        }
    }

    if (rule && rule->options.inject.error) {
        return inject_error(bs, cb, opaque, rule);
        return inject_error(bs, rule);
    }

    return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors,
                          cb, opaque);
    return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
}

static BlockAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
    BlockCompletionFunc *cb, void *opaque)
static int coroutine_fn
blkdebug_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                    QEMUIOVector *qiov, int flags)
{
    BDRVBlkdebugState *s = bs->opaque;
    BlkdebugRule *rule = NULL;

    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
        if (rule->options.inject.sector == -1 ||
            (rule->options.inject.sector >= sector_num &&
             rule->options.inject.sector < sector_num + nb_sectors)) {
        uint64_t inject_offset = rule->options.inject.offset;

        if (inject_offset == -1 ||
            (inject_offset >= offset && inject_offset < offset + bytes))
        {
            break;
        }
    }

    if (rule && rule->options.inject.error) {
        return inject_error(bs, cb, opaque, rule);
        return inject_error(bs, rule);
    }

    return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
                           cb, opaque);
    return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
}

static BlockAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
    BlockCompletionFunc *cb, void *opaque)
static int blkdebug_co_flush(BlockDriverState *bs)
{
    BDRVBlkdebugState *s = bs->opaque;
    BlkdebugRule *rule = NULL;

    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
        if (rule->options.inject.sector == -1) {
        if (rule->options.inject.offset == -1) {
            break;
        }
    }

    if (rule && rule->options.inject.error) {
        return inject_error(bs, cb, opaque, rule);
        return inject_error(bs, rule);
    }

    return bdrv_aio_flush(bs->file->bs, cb, opaque);
    return bdrv_co_flush(bs->file->bs);
}


@@ -752,9 +746,9 @@ static BlockDriver bdrv_blkdebug = {
    .bdrv_refresh_filename  = blkdebug_refresh_filename,
    .bdrv_refresh_limits    = blkdebug_refresh_limits,

    .bdrv_aio_readv         = blkdebug_aio_readv,
    .bdrv_aio_writev        = blkdebug_aio_writev,
    .bdrv_aio_flush         = blkdebug_aio_flush,
    .bdrv_co_preadv         = blkdebug_co_preadv,
    .bdrv_co_pwritev        = blkdebug_co_pwritev,
    .bdrv_co_flush_to_disk  = blkdebug_co_flush,

    .bdrv_debug_event           = blkdebug_debug_event,
    .bdrv_debug_breakpoint      = blkdebug_debug_breakpoint,
+96 −105
Original line number Diff line number Diff line
@@ -19,38 +19,36 @@ typedef struct {
    BdrvChild *test_file;
} BDRVBlkverifyState;

typedef struct BlkverifyAIOCB BlkverifyAIOCB;
struct BlkverifyAIOCB {
    BlockAIOCB common;
typedef struct BlkverifyRequest {
    Coroutine *co;
    BlockDriverState *bs;

    /* Request metadata */
    bool is_write;
    int64_t sector_num;
    int nb_sectors;
    uint64_t offset;
    uint64_t bytes;
    int flags;

    int ret;                    /* first completed request's result */
    unsigned int done;          /* completion counter */
    int (*request_fn)(BdrvChild *, int64_t, unsigned int, QEMUIOVector *,
                      BdrvRequestFlags);

    QEMUIOVector *qiov;         /* user I/O vector */
    QEMUIOVector raw_qiov;      /* cloned I/O vector for raw file */
    void *buf;                  /* buffer for raw file I/O */
    int ret;                    /* test image result */
    int raw_ret;                /* raw image result */

    void (*verify)(BlkverifyAIOCB *acb);
};
    unsigned int done;          /* completion counter */

static const AIOCBInfo blkverify_aiocb_info = {
    .aiocb_size         = sizeof(BlkverifyAIOCB),
};
    QEMUIOVector *qiov;         /* user I/O vector */
    QEMUIOVector *raw_qiov;     /* cloned I/O vector for raw file */
} BlkverifyRequest;

static void GCC_FMT_ATTR(2, 3) blkverify_err(BlkverifyAIOCB *acb,
static void GCC_FMT_ATTR(2, 3) blkverify_err(BlkverifyRequest *r,
                                             const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    fprintf(stderr, "blkverify: %s sector_num=%" PRId64 " nb_sectors=%d ",
            acb->is_write ? "write" : "read", acb->sector_num,
            acb->nb_sectors);
    fprintf(stderr, "blkverify: %s offset=%" PRId64 " bytes=%" PRId64 " ",
            r->is_write ? "write" : "read", r->offset, r->bytes);
    vfprintf(stderr, fmt, ap);
    fprintf(stderr, "\n");
    va_end(ap);
@@ -166,113 +164,106 @@ static int64_t blkverify_getlength(BlockDriverState *bs)
    return bdrv_getlength(s->test_file->bs);
}

static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
                                         int64_t sector_num, QEMUIOVector *qiov,
                                         int nb_sectors,
                                         BlockCompletionFunc *cb,
                                         void *opaque)
static void coroutine_fn blkverify_do_test_req(void *opaque)
{
    BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque);

    acb->is_write = is_write;
    acb->sector_num = sector_num;
    acb->nb_sectors = nb_sectors;
    acb->ret = -EINPROGRESS;
    acb->done = 0;
    acb->qiov = qiov;
    acb->buf = NULL;
    acb->verify = NULL;
    return acb;
    BlkverifyRequest *r = opaque;
    BDRVBlkverifyState *s = r->bs->opaque;

    r->ret = r->request_fn(s->test_file, r->offset, r->bytes, r->qiov,
                           r->flags);
    r->done++;
    qemu_coroutine_enter_if_inactive(r->co);
}

static void blkverify_aio_bh(void *opaque)
static void coroutine_fn blkverify_do_raw_req(void *opaque)
{
    BlkverifyAIOCB *acb = opaque;
    BlkverifyRequest *r = opaque;

    if (acb->buf) {
        qemu_iovec_destroy(&acb->raw_qiov);
        qemu_vfree(acb->buf);
    }
    acb->common.cb(acb->common.opaque, acb->ret);
    qemu_aio_unref(acb);
    r->raw_ret = r->request_fn(r->bs->file, r->offset, r->bytes, r->raw_qiov,
                               r->flags);
    r->done++;
    qemu_coroutine_enter_if_inactive(r->co);
}

static void blkverify_aio_cb(void *opaque, int ret)
static int coroutine_fn
blkverify_co_prwv(BlockDriverState *bs, BlkverifyRequest *r, uint64_t offset,
                  uint64_t bytes, QEMUIOVector *qiov, QEMUIOVector *raw_qiov,
                  int flags, bool is_write)
{
    BlkverifyAIOCB *acb = opaque;
    Coroutine *co_a, *co_b;

    *r = (BlkverifyRequest) {
        .co         = qemu_coroutine_self(),
        .bs         = bs,
        .offset     = offset,
        .bytes      = bytes,
        .qiov       = qiov,
        .raw_qiov   = raw_qiov,
        .flags      = flags,
        .is_write   = is_write,
        .request_fn = is_write ? bdrv_co_pwritev : bdrv_co_preadv,
    };

    switch (++acb->done) {
    case 1:
        acb->ret = ret;
        break;
    co_a = qemu_coroutine_create(blkverify_do_test_req, r);
    co_b = qemu_coroutine_create(blkverify_do_raw_req, r);

    case 2:
        if (acb->ret != ret) {
            blkverify_err(acb, "return value mismatch %d != %d", acb->ret, ret);
        }
    qemu_coroutine_enter(co_a);
    qemu_coroutine_enter(co_b);

        if (acb->verify) {
            acb->verify(acb);
    while (r->done < 2) {
        qemu_coroutine_yield();
    }

        aio_bh_schedule_oneshot(bdrv_get_aio_context(acb->common.bs),
                                blkverify_aio_bh, acb);
        break;
    if (r->ret != r->raw_ret) {
        blkverify_err(r, "return value mismatch %d != %d", r->ret, r->raw_ret);
    }

    return r->ret;
}

static void blkverify_verify_readv(BlkverifyAIOCB *acb)
static int coroutine_fn
blkverify_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                    QEMUIOVector *qiov, int flags)
{
    ssize_t offset = qemu_iovec_compare(acb->qiov, &acb->raw_qiov);
    if (offset != -1) {
        blkverify_err(acb, "contents mismatch in sector %" PRId64,
                      acb->sector_num + (int64_t)(offset / BDRV_SECTOR_SIZE));
    }
    BlkverifyRequest r;
    QEMUIOVector raw_qiov;
    void *buf;
    ssize_t cmp_offset;
    int ret;

    buf = qemu_blockalign(bs->file->bs, qiov->size);
    qemu_iovec_init(&raw_qiov, qiov->niov);
    qemu_iovec_clone(&raw_qiov, qiov, buf);

    ret = blkverify_co_prwv(bs, &r, offset, bytes, qiov, &raw_qiov, flags,
                            false);

    cmp_offset = qemu_iovec_compare(qiov, &raw_qiov);
    if (cmp_offset != -1) {
        blkverify_err(&r, "contents mismatch at offset %" PRId64,
                      offset + cmp_offset);
    }

static BlockAIOCB *blkverify_aio_readv(BlockDriverState *bs,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
        BlockCompletionFunc *cb, void *opaque)
{
    BDRVBlkverifyState *s = bs->opaque;
    BlkverifyAIOCB *acb = blkverify_aio_get(bs, false, sector_num, qiov,
                                            nb_sectors, cb, opaque);

    acb->verify = blkverify_verify_readv;
    acb->buf = qemu_blockalign(bs->file->bs, qiov->size);
    qemu_iovec_init(&acb->raw_qiov, acb->qiov->niov);
    qemu_iovec_clone(&acb->raw_qiov, qiov, acb->buf);

    bdrv_aio_readv(s->test_file, sector_num, qiov, nb_sectors,
                   blkverify_aio_cb, acb);
    bdrv_aio_readv(bs->file, sector_num, &acb->raw_qiov, nb_sectors,
                   blkverify_aio_cb, acb);
    return &acb->common;
    qemu_iovec_destroy(&raw_qiov);
    qemu_vfree(buf);

    return ret;
}

static BlockAIOCB *blkverify_aio_writev(BlockDriverState *bs,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
        BlockCompletionFunc *cb, void *opaque)
static int coroutine_fn
blkverify_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                     QEMUIOVector *qiov, int flags)
{
    BDRVBlkverifyState *s = bs->opaque;
    BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
                                            nb_sectors, cb, opaque);

    bdrv_aio_writev(s->test_file, sector_num, qiov, nb_sectors,
                    blkverify_aio_cb, acb);
    bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors,
                    blkverify_aio_cb, acb);
    return &acb->common;
    BlkverifyRequest r;
    return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true);
}

static BlockAIOCB *blkverify_aio_flush(BlockDriverState *bs,
                                       BlockCompletionFunc *cb,
                                       void *opaque)
static int blkverify_co_flush(BlockDriverState *bs)
{
    BDRVBlkverifyState *s = bs->opaque;

    /* Only flush test file, the raw file is not important */
    return bdrv_aio_flush(s->test_file->bs, cb, opaque);
    return bdrv_co_flush(s->test_file->bs);
}

static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
@@ -332,9 +323,9 @@ static BlockDriver bdrv_blkverify = {
    .bdrv_getlength                   = blkverify_getlength,
    .bdrv_refresh_filename            = blkverify_refresh_filename,

    .bdrv_aio_readv                   = blkverify_aio_readv,
    .bdrv_aio_writev                  = blkverify_aio_writev,
    .bdrv_aio_flush                   = blkverify_aio_flush,
    .bdrv_co_preadv                   = blkverify_co_preadv,
    .bdrv_co_pwritev                  = blkverify_co_pwritev,
    .bdrv_co_flush                    = blkverify_co_flush,

    .is_filter                        = true,
    .bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter,
+0 −0

File moved.

Loading