Commit f68419ee 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 Thu 12 May 2016 14:37:05 BST using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream: (69 commits)
  qemu-iotests: iotests: fail hard if not run via "check"
  block: enable testing of LUKS driver with block I/O tests
  block: add support for encryption secrets in block I/O tests
  block: add support for --image-opts in block I/O tests
  qemu-io: Add 'write -z -u' to test MAY_UNMAP flag
  qemu-io: Add 'write -f' to test FUA flag
  qemu-io: Allow unaligned access by default
  qemu-io: Use bool for command line flags
  qemu-io: Make 'open' subcommand more like command line
  qemu-io: Add missing option documentation
  qmp: add monitor command to add/remove a child
  quorum: implement bdrv_add_child() and bdrv_del_child()
  Add new block driver interface to add/delete a BDS's child
  qemu-img: check block status of backing file when converting.
  iotests: fix the redirection order in 083
  block: Inactivate all children
  block: Drop superfluous invalidating bs->file from drivers
  block: Invalidate all children
  nbd: Simplify client FUA handling
  block: Honor BDRV_REQ_FUA during write_zeroes
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e4f70d63 efc2645f
Loading
Loading
Loading
Loading
+103 −24
Original line number Diff line number Diff line
@@ -218,8 +218,6 @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, char *dest, size_t sz,

void bdrv_register(BlockDriver *bdrv)
{
    bdrv_setup_io_funcs(bdrv);

    QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
}

@@ -1176,7 +1174,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
    return child;
}

static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
                             BlockDriverState *child_bs,
                             const char *child_name,
                             const BdrvChildRole *child_role)
@@ -2261,7 +2259,6 @@ static void swap_feature_fields(BlockDriverState *bs_top,

    assert(!bs_new->throttle_state);
    if (bs_top->throttle_state) {
        assert(bs_top->io_limits_enabled);
        bdrv_io_limits_enable(bs_new, throttle_group_get_name(bs_top));
        bdrv_io_limits_disable(bs_top);
    }
@@ -3201,6 +3198,7 @@ void bdrv_init_with_whitelist(void)

void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
{
    BdrvChild *child;
    Error *local_err = NULL;
    int ret;

@@ -3215,14 +3213,21 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)

    if (bs->drv->bdrv_invalidate_cache) {
        bs->drv->bdrv_invalidate_cache(bs, &local_err);
    } else if (bs->file) {
        bdrv_invalidate_cache(bs->file->bs, &local_err);
        if (local_err) {
            bs->open_flags |= BDRV_O_INACTIVE;
            error_propagate(errp, local_err);
            return;
        }
    }

    QLIST_FOREACH(child, &bs->children, next) {
        bdrv_invalidate_cache(child->bs, &local_err);
        if (local_err) {
            bs->open_flags |= BDRV_O_INACTIVE;
            error_propagate(errp, local_err);
            return;
        }
    }

    ret = refresh_total_sectors(bs, bs->total_sectors);
    if (ret < 0) {
@@ -3250,38 +3255,63 @@ void bdrv_invalidate_cache_all(Error **errp)
    }
}

static int bdrv_inactivate(BlockDriverState *bs)
static int bdrv_inactivate_recurse(BlockDriverState *bs,
                                   bool setting_flag)
{
    BdrvChild *child;
    int ret;

    if (bs->drv->bdrv_inactivate) {
    if (!setting_flag && bs->drv->bdrv_inactivate) {
        ret = bs->drv->bdrv_inactivate(bs);
        if (ret < 0) {
            return ret;
        }
    }

    QLIST_FOREACH(child, &bs->children, next) {
        ret = bdrv_inactivate_recurse(child->bs, setting_flag);
        if (ret < 0) {
            return ret;
        }
    }

    if (setting_flag) {
        bs->open_flags |= BDRV_O_INACTIVE;
    }
    return 0;
}

int bdrv_inactivate_all(void)
{
    BlockDriverState *bs = NULL;
    int ret;
    int ret = 0;
    int pass;

    while ((bs = bdrv_next(bs)) != NULL) {
        AioContext *aio_context = bdrv_get_aio_context(bs);
        aio_context_acquire(bdrv_get_aio_context(bs));
    }

        aio_context_acquire(aio_context);
        ret = bdrv_inactivate(bs);
        aio_context_release(aio_context);
    /* We do two passes of inactivation. The first pass calls to drivers'
     * .bdrv_inactivate callbacks recursively so all cache is flushed to disk;
     * the second pass sets the BDRV_O_INACTIVE flag so that no further write
     * is allowed. */
    for (pass = 0; pass < 2; pass++) {
        bs = NULL;
        while ((bs = bdrv_next(bs)) != NULL) {
            ret = bdrv_inactivate_recurse(bs, pass);
            if (ret < 0) {
            return ret;
                goto out;
            }
        }
    }

    return 0;
out:
    bs = NULL;
    while ((bs = bdrv_next(bs)) != NULL) {
        aio_context_release(bdrv_get_aio_context(bs));
    }

    return ret;
}

/**************************************************************/
@@ -3981,3 +4011,52 @@ void bdrv_refresh_filename(BlockDriverState *bs)
        QDECREF(json);
    }
}

/*
 * Hot add/remove a BDS's child. So the user can take a child offline when
 * it is broken and take a new child online
 */
void bdrv_add_child(BlockDriverState *parent_bs, BlockDriverState *child_bs,
                    Error **errp)
{

    if (!parent_bs->drv || !parent_bs->drv->bdrv_add_child) {
        error_setg(errp, "The node %s does not support adding a child",
                   bdrv_get_device_or_node_name(parent_bs));
        return;
    }

    if (!QLIST_EMPTY(&child_bs->parents)) {
        error_setg(errp, "The node %s already has a parent",
                   child_bs->node_name);
        return;
    }

    parent_bs->drv->bdrv_add_child(parent_bs, child_bs, errp);
}

void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
{
    BdrvChild *tmp;

    if (!parent_bs->drv || !parent_bs->drv->bdrv_del_child) {
        error_setg(errp, "The node %s does not support removing a child",
                   bdrv_get_device_or_node_name(parent_bs));
        return;
    }

    QLIST_FOREACH(tmp, &parent_bs->children, next) {
        if (tmp == child) {
            break;
        }
    }

    if (!tmp) {
        error_setg(errp, "The node %s does not have a child named %s",
                   bdrv_get_device_or_node_name(parent_bs),
                   bdrv_get_device_or_node_name(child->bs));
        return;
    }

    parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
}
+34 −80
Original line number Diff line number Diff line
/*
 * QEMU Block backends
 *
 * Copyright (C) 2014 Red Hat, Inc.
 * Copyright (C) 2014-2016 Red Hat, Inc.
 *
 * Authors:
 *  Markus Armbruster <armbru@redhat.com>,
@@ -692,7 +692,7 @@ static int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
        return ret;
    }

    return bdrv_co_do_preadv(blk_bs(blk), offset, bytes, qiov, flags);
    return bdrv_co_preadv(blk_bs(blk), offset, bytes, qiov, flags);
}

static int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
@@ -710,7 +710,7 @@ static int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
        flags |= BDRV_REQ_FUA;
    }

    return bdrv_co_do_pwritev(blk_bs(blk), offset, bytes, qiov, flags);
    return bdrv_co_pwritev(blk_bs(blk), offset, bytes, qiov, flags);
}

typedef struct BlkRwCo {
@@ -772,54 +772,27 @@ static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
    return rwco.ret;
}

static int blk_rw(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
                  int nb_sectors, CoroutineEntry co_entry,
                  BdrvRequestFlags flags)
{
    if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
        return -EINVAL;
    }

    return blk_prw(blk, sector_num << BDRV_SECTOR_BITS, buf,
                   nb_sectors << BDRV_SECTOR_BITS, co_entry, flags);
}

int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
             int nb_sectors)
{
    return blk_rw(blk, sector_num, buf, nb_sectors, blk_read_entry, 0);
}

int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
                         int nb_sectors)
int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf,
                          int count)
{
    BlockDriverState *bs = blk_bs(blk);
    bool enabled;
    int ret;

    ret = blk_check_request(blk, sector_num, nb_sectors);
    ret = blk_check_byte_request(blk, offset, count);
    if (ret < 0) {
        return ret;
    }

    enabled = bs->io_limits_enabled;
    bs->io_limits_enabled = false;
    ret = blk_read(blk, sector_num, buf, nb_sectors);
    bs->io_limits_enabled = enabled;
    bdrv_no_throttling_begin(bs);
    ret = blk_pread(blk, offset, buf, count);
    bdrv_no_throttling_end(bs);
    return ret;
}

int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf,
              int nb_sectors)
{
    return blk_rw(blk, sector_num, (uint8_t*) buf, nb_sectors,
                  blk_write_entry, 0);
}

int blk_write_zeroes(BlockBackend *blk, int64_t sector_num,
                     int nb_sectors, BdrvRequestFlags flags)
int blk_write_zeroes(BlockBackend *blk, int64_t offset,
                     int count, BdrvRequestFlags flags)
{
    return blk_rw(blk, sector_num, NULL, nb_sectors, blk_write_entry,
    return blk_prw(blk, offset, NULL, count, blk_write_entry,
                   flags | BDRV_REQ_ZERO_WRITE);
}

@@ -932,18 +905,12 @@ static void blk_aio_write_entry(void *opaque)
    blk_aio_complete(acb);
}

BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num,
                                 int nb_sectors, BdrvRequestFlags flags,
BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t offset,
                                 int count, BdrvRequestFlags flags,
                                 BlockCompletionFunc *cb, void *opaque)
{
    if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
        return blk_abort_aio_request(blk, cb, opaque, -EINVAL);
    }

    return blk_aio_prwv(blk, sector_num << BDRV_SECTOR_BITS,
                        nb_sectors << BDRV_SECTOR_BITS, NULL,
                        blk_aio_write_entry, flags | BDRV_REQ_ZERO_WRITE,
                        cb, opaque);
    return blk_aio_prwv(blk, offset, count, NULL, blk_aio_write_entry,
                        flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
}

int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
@@ -955,9 +922,11 @@ int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
    return count;
}

int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count)
int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count,
               BdrvRequestFlags flags)
{
    int ret = blk_prw(blk, offset, (void*) buf, count, blk_write_entry, 0);
    int ret = blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
                      flags);
    if (ret < 0) {
        return ret;
    }
@@ -991,30 +960,20 @@ int64_t blk_nb_sectors(BlockBackend *blk)
    return bdrv_nb_sectors(blk_bs(blk));
}

BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num,
                          QEMUIOVector *iov, int nb_sectors,
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
                           QEMUIOVector *qiov, BdrvRequestFlags flags,
                           BlockCompletionFunc *cb, void *opaque)
{
    if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
        return blk_abort_aio_request(blk, cb, opaque, -EINVAL);
    return blk_aio_prwv(blk, offset, qiov->size, qiov,
                        blk_aio_read_entry, flags, cb, opaque);
}

    assert(nb_sectors << BDRV_SECTOR_BITS == iov->size);
    return blk_aio_prwv(blk, sector_num << BDRV_SECTOR_BITS, iov->size, iov,
                        blk_aio_read_entry, 0, cb, opaque);
}

BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
                           QEMUIOVector *iov, int nb_sectors,
BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
                            QEMUIOVector *qiov, BdrvRequestFlags flags,
                            BlockCompletionFunc *cb, void *opaque)
{
    if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
        return blk_abort_aio_request(blk, cb, opaque, -EINVAL);
    }

    assert(nb_sectors << BDRV_SECTOR_BITS == iov->size);
    return blk_aio_prwv(blk, sector_num << BDRV_SECTOR_BITS, iov->size, iov,
                        blk_aio_write_entry, 0, cb, opaque);
    return blk_aio_prwv(blk, offset, qiov->size, qiov,
                        blk_aio_write_entry, flags, cb, opaque);
}

BlockAIOCB *blk_aio_flush(BlockBackend *blk,
@@ -1444,15 +1403,10 @@ void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
    return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
}

int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t sector_num,
                                     int nb_sectors, BdrvRequestFlags flags)
int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t offset,
                                     int count, BdrvRequestFlags flags)
{
    if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
        return -EINVAL;
    }

    return blk_co_pwritev(blk, sector_num << BDRV_SECTOR_BITS,
                          nb_sectors << BDRV_SECTOR_BITS, NULL,
    return blk_co_pwritev(blk, offset, count, NULL,
                          flags | BDRV_REQ_ZERO_WRITE);
}

+33 −18
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
    int ret;

    bs->read_only = 1; // no write support yet
    bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */

    ret = bdrv_pread(bs->file->bs, 0, &bochs, sizeof(bochs));
    if (ret < 0) {
@@ -221,38 +222,52 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
    return bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
}

static int bochs_read(BlockDriverState *bs, int64_t sector_num,
                    uint8_t *buf, int nb_sectors)
static int coroutine_fn
bochs_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                QEMUIOVector *qiov, int flags)
{
    BDRVBochsState *s = bs->opaque;
    uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
    int nb_sectors = bytes >> BDRV_SECTOR_BITS;
    uint64_t bytes_done = 0;
    QEMUIOVector local_qiov;
    int ret;

    assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
    assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);

    qemu_iovec_init(&local_qiov, qiov->niov);
    qemu_co_mutex_lock(&s->lock);

    while (nb_sectors > 0) {
        int64_t block_offset = seek_to_sector(bs, sector_num);
        if (block_offset < 0) {
            return block_offset;
        } else if (block_offset > 0) {
            ret = bdrv_pread(bs->file->bs, block_offset, buf, 512);
            ret = block_offset;
            goto fail;
        }

        qemu_iovec_reset(&local_qiov);
        qemu_iovec_concat(&local_qiov, qiov, bytes_done, 512);

        if (block_offset > 0) {
            ret = bdrv_co_preadv(bs->file->bs, block_offset, 512,
                                 &local_qiov, 0);
            if (ret < 0) {
                return ret;
                goto fail;
            }
        } else {
            memset(buf, 0, 512);
            qemu_iovec_memset(&local_qiov, 0, 0, 512);
        }
        nb_sectors--;
        sector_num++;
        buf += 512;
    }
    return 0;
        bytes_done += 512;
    }

static coroutine_fn int bochs_co_read(BlockDriverState *bs, int64_t sector_num,
                                      uint8_t *buf, int nb_sectors)
{
    int ret;
    BDRVBochsState *s = bs->opaque;
    qemu_co_mutex_lock(&s->lock);
    ret = bochs_read(bs, sector_num, buf, nb_sectors);
    ret = 0;
fail:
    qemu_co_mutex_unlock(&s->lock);
    qemu_iovec_destroy(&local_qiov);

    return ret;
}

@@ -267,7 +282,7 @@ static BlockDriver bdrv_bochs = {
    .instance_size	= sizeof(BDRVBochsState),
    .bdrv_probe		= bochs_probe,
    .bdrv_open		= bochs_open,
    .bdrv_read          = bochs_co_read,
    .bdrv_co_preadv = bochs_co_preadv,
    .bdrv_close		= bochs_close,
};

+22 −16
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
    int ret;

    bs->read_only = 1;
    bs->request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O supported */

    /* read header */
    ret = bdrv_pread(bs->file->bs, 128, &s->block_size, 4);
@@ -229,33 +230,38 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
    return 0;
}

static int cloop_read(BlockDriverState *bs, int64_t sector_num,
                    uint8_t *buf, int nb_sectors)
static int coroutine_fn
cloop_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
                QEMUIOVector *qiov, int flags)
{
    BDRVCloopState *s = bs->opaque;
    int i;
    uint64_t sector_num = offset >> BDRV_SECTOR_BITS;
    int nb_sectors = bytes >> BDRV_SECTOR_BITS;
    int ret, i;

    assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
    assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);

    qemu_co_mutex_lock(&s->lock);

    for (i = 0; i < nb_sectors; i++) {
        void *data;
        uint32_t sector_offset_in_block =
            ((sector_num + i) % s->sectors_per_block),
            block_num = (sector_num + i) / s->sectors_per_block;
        if (cloop_read_block(bs, block_num) != 0) {
            return -1;
        }
        memcpy(buf + i * 512,
            s->uncompressed_block + sector_offset_in_block * 512, 512);
            ret = -EIO;
            goto fail;
        }
    return 0;

        data = s->uncompressed_block + sector_offset_in_block * 512;
        qemu_iovec_from_buf(qiov, i * 512, data, 512);
    }

static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
                                      uint8_t *buf, int nb_sectors)
{
    int ret;
    BDRVCloopState *s = bs->opaque;
    qemu_co_mutex_lock(&s->lock);
    ret = cloop_read(bs, sector_num, buf, nb_sectors);
    ret = 0;
fail:
    qemu_co_mutex_unlock(&s->lock);

    return ret;
}

@@ -273,7 +279,7 @@ static BlockDriver bdrv_cloop = {
    .instance_size  = sizeof(BDRVCloopState),
    .bdrv_probe     = cloop_probe,
    .bdrv_open      = cloop_open,
    .bdrv_read      = cloop_co_read,
    .bdrv_co_preadv = cloop_co_preadv,
    .bdrv_close     = cloop_close,
};

+1 −1
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
    struct BlockCryptoCreateData *data = opaque;
    ssize_t ret;

    ret = blk_pwrite(data->blk, offset, buf, buflen);
    ret = blk_pwrite(data->blk, offset, buf, buflen, 0);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Could not write encryption header");
        return ret;
Loading