Commit 0f01b9fd authored by Peter Maydell's avatar Peter Maydell
Browse files

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



Block layer patches:

- Active mirror (blockdev-mirror copy-mode=write-blocking)
- bdrv_drain_*() fixes and test cases
- Fix crash with scsi-hd and drive_del

# gpg: Signature made Mon 18 Jun 2018 17:44:10 BST
# gpg:                using RSA key 7F09B272C88F2FD6
# 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: (35 commits)
  iotests: Add test for active mirroring
  block/mirror: Add copy mode QAPI interface
  block/mirror: Add active mirroring
  job: Add job_progress_increase_remaining()
  block/mirror: Add MirrorBDSOpaque
  block/dirty-bitmap: Add bdrv_dirty_iter_next_area
  test-hbitmap: Add non-advancing iter_next tests
  hbitmap: Add @advance param to hbitmap_iter_next()
  block: Generalize should_update_child() rule
  block/mirror: Use source as a BdrvChild
  block/mirror: Wait for in-flight op conflicts
  block/mirror: Use CoQueue to wait on in-flight ops
  block/mirror: Convert to coroutines
  block/mirror: Pull out mirror_perform()
  block: fix QEMU crash with scsi-hd and drive_del
  test-bdrv-drain: Test graph changes in drain_all section
  block: Allow graph changes in bdrv_drain_all_begin/end sections
  block: ignore_bds_parents parameter for drain functions
  block: Move bdrv_drain_all_begin() out of coroutine context
  block: Allow AIO_WAIT_WHILE with NULL ctx
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents a01fba46 4c790afe
Loading
Loading
Loading
Loading
+80 −16
Original line number Diff line number Diff line
@@ -333,6 +333,10 @@ BlockDriverState *bdrv_new(void)

    qemu_co_queue_init(&bs->flush_queue);

    for (i = 0; i < bdrv_drain_all_count; i++) {
        bdrv_drained_begin(bs);
    }

    QTAILQ_INSERT_TAIL(&all_bdrv_states, bs, bs_list);

    return bs;
@@ -818,7 +822,13 @@ static char *bdrv_child_get_parent_desc(BdrvChild *c)
static void bdrv_child_cb_drained_begin(BdrvChild *child)
{
    BlockDriverState *bs = child->opaque;
    bdrv_drained_begin(bs);
    bdrv_do_drained_begin_quiesce(bs, NULL, false);
}

static bool bdrv_child_cb_drained_poll(BdrvChild *child)
{
    BlockDriverState *bs = child->opaque;
    return bdrv_drain_poll(bs, false, NULL, false);
}

static void bdrv_child_cb_drained_end(BdrvChild *child)
@@ -902,9 +912,11 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
}

const BdrvChildRole child_file = {
    .parent_is_bds   = true,
    .get_parent_desc = bdrv_child_get_parent_desc,
    .inherit_options = bdrv_inherited_options,
    .drained_begin   = bdrv_child_cb_drained_begin,
    .drained_poll    = bdrv_child_cb_drained_poll,
    .drained_end     = bdrv_child_cb_drained_end,
    .attach          = bdrv_child_cb_attach,
    .detach          = bdrv_child_cb_detach,
@@ -926,9 +938,11 @@ static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options,
}

const BdrvChildRole child_format = {
    .parent_is_bds   = true,
    .get_parent_desc = bdrv_child_get_parent_desc,
    .inherit_options = bdrv_inherited_fmt_options,
    .drained_begin   = bdrv_child_cb_drained_begin,
    .drained_poll    = bdrv_child_cb_drained_poll,
    .drained_end     = bdrv_child_cb_drained_end,
    .attach          = bdrv_child_cb_attach,
    .detach          = bdrv_child_cb_detach,
@@ -1043,11 +1057,13 @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
}

const BdrvChildRole child_backing = {
    .parent_is_bds   = true,
    .get_parent_desc = bdrv_child_get_parent_desc,
    .attach          = bdrv_backing_attach,
    .detach          = bdrv_backing_detach,
    .inherit_options = bdrv_backing_options,
    .drained_begin   = bdrv_child_cb_drained_begin,
    .drained_poll    = bdrv_child_cb_drained_poll,
    .drained_end     = bdrv_child_cb_drained_end,
    .inactivate      = bdrv_child_cb_inactivate,
    .update_filename = bdrv_backing_update_filename,
@@ -1152,7 +1168,7 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
                            int open_flags, Error **errp)
{
    Error *local_err = NULL;
    int ret;
    int i, ret;

    bdrv_assign_node_name(bs, node_name, &local_err);
    if (local_err) {
@@ -1200,6 +1216,12 @@ static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
    assert(bdrv_min_mem_align(bs) != 0);
    assert(is_power_of_2(bs->bl.request_alignment));

    for (i = 0; i < bs->quiesce_counter; i++) {
        if (drv->bdrv_co_drain_begin) {
            drv->bdrv_co_drain_begin(bs);
        }
    }

    return 0;
open_failed:
    bs->drv = NULL;
@@ -2021,7 +2043,12 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
            child->role->detach(child);
        }
        if (old_bs->quiesce_counter && child->role->drained_end) {
            for (i = 0; i < old_bs->quiesce_counter; i++) {
            int num = old_bs->quiesce_counter;
            if (child->role->parent_is_bds) {
                num -= bdrv_drain_all_count;
            }
            assert(num >= 0);
            for (i = 0; i < num; i++) {
                child->role->drained_end(child);
            }
        }
@@ -2033,7 +2060,12 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
    if (new_bs) {
        QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
        if (new_bs->quiesce_counter && child->role->drained_begin) {
            for (i = 0; i < new_bs->quiesce_counter; i++) {
            int num = new_bs->quiesce_counter;
            if (child->role->parent_is_bds) {
                num -= bdrv_drain_all_count;
            }
            assert(num >= 0);
            for (i = 0; i < num; i++) {
                child->role->drained_begin(child);
            }
        }
@@ -3395,16 +3427,39 @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
        return false;
    }

    if (c->role == &child_backing) {
        /* If @from is a backing file of @to, ignore the child to avoid
         * creating a loop. We only want to change the pointer of other
         * parents. */
    /* If the child @c belongs to the BDS @to, replacing the current
     * c->bs by @to would mean to create a loop.
     *
     * Such a case occurs when appending a BDS to a backing chain.
     * For instance, imagine the following chain:
     *
     *   guest device -> node A -> further backing chain...
     *
     * Now we create a new BDS B which we want to put on top of this
     * chain, so we first attach A as its backing node:
     *
     *                   node B
     *                     |
     *                     v
     *   guest device -> node A -> further backing chain...
     *
     * Finally we want to replace A by B.  When doing that, we want to
     * replace all pointers to A by pointers to B -- except for the
     * pointer from B because (1) that would create a loop, and (2)
     * that pointer should simply stay intact:
     *
     *   guest device -> node B
     *                     |
     *                     v
     *                   node A -> further backing chain...
     *
     * In general, when replacing a node A (c->bs) by a node B (@to),
     * if A is a child of B, that means we cannot replace A by B there
     * because that would create a loop.  Silently detaching A from B
     * is also not really an option.  So overall just leaving A in
     * place there is the most sensible choice. */
    QLIST_FOREACH(to_c, &to->children, next) {
        if (to_c == c) {
                break;
            }
        }
        if (to_c) {
            return false;
        }
    }
@@ -3430,6 +3485,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,

    /* Put all parents into @list and calculate their cumulative permissions */
    QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
        assert(c->bs == from);
        if (!should_update_child(c, to)) {
            continue;
        }
@@ -4037,6 +4093,14 @@ BlockDriverState *bdrv_next_node(BlockDriverState *bs)
    return QTAILQ_NEXT(bs, node_list);
}

BlockDriverState *bdrv_next_all_states(BlockDriverState *bs)
{
    if (!bs) {
        return QTAILQ_FIRST(&all_bdrv_states);
    }
    return QTAILQ_NEXT(bs, bs_list);
}

const char *bdrv_get_node_name(const BlockDriverState *bs)
{
    return bs->node_name;
@@ -4948,7 +5012,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
    AioContext *ctx = bdrv_get_aio_context(bs);

    aio_disable_external(ctx);
    bdrv_parent_drained_begin(bs, NULL);
    bdrv_parent_drained_begin(bs, NULL, false);
    bdrv_drain(bs); /* ensure there are no in-flight requests */

    while (aio_poll(ctx, false)) {
@@ -4962,7 +5026,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
     */
    aio_context_acquire(new_context);
    bdrv_attach_aio_context(bs, new_context);
    bdrv_parent_drained_end(bs, NULL);
    bdrv_parent_drained_end(bs, NULL, false);
    aio_enable_external(ctx);
    aio_context_release(new_context);
}
+1 −1
Original line number Diff line number Diff line
@@ -354,7 +354,7 @@ static int coroutine_fn backup_run_incremental(BackupBlockJob *job)
    HBitmapIter hbi;

    hbitmap_iter_init(&hbi, job->copy_bitmap, 0);
    while ((cluster = hbitmap_iter_next(&hbi)) != -1) {
    while ((cluster = hbitmap_iter_next(&hbi, true)) != -1) {
        do {
            if (yield_and_check(job)) {
                return 0;
+5 −0
Original line number Diff line number Diff line
@@ -767,6 +767,11 @@ void blk_remove_bs(BlockBackend *blk)

    blk_update_root_state(blk);

    /* bdrv_root_unref_child() will cause blk->root to become stale and may
     * switch to a completion coroutine later on. Let's drain all I/O here
     * to avoid that and a potential QEMU crash.
     */
    blk_drain(blk);
    bdrv_root_unref_child(blk->root);
    blk->root = NULL;
}
+56 −1
Original line number Diff line number Diff line
@@ -519,7 +519,62 @@ void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter)

int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter)
{
    return hbitmap_iter_next(&iter->hbi);
    return hbitmap_iter_next(&iter->hbi, true);
}

/**
 * Return the next consecutively dirty area in the dirty bitmap
 * belonging to the given iterator @iter.
 *
 * @max_offset: Maximum value that may be returned for
 *              *offset + *bytes
 * @offset:     Will contain the start offset of the next dirty area
 * @bytes:      Will contain the length of the next dirty area
 *
 * Returns: True if a dirty area could be found before max_offset
 *          (which means that *offset and *bytes then contain valid
 *          values), false otherwise.
 *
 * Note that @iter is never advanced if false is returned.  If an area
 * is found (which means that true is returned), it will be advanced
 * past that area.
 */
bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset,
                               uint64_t *offset, int *bytes)
{
    uint32_t granularity = bdrv_dirty_bitmap_granularity(iter->bitmap);
    uint64_t gran_max_offset;
    int64_t ret;
    int size;

    if (max_offset == iter->bitmap->size) {
        /* If max_offset points to the image end, round it up by the
         * bitmap granularity */
        gran_max_offset = ROUND_UP(max_offset, granularity);
    } else {
        gran_max_offset = max_offset;
    }

    ret = hbitmap_iter_next(&iter->hbi, false);
    if (ret < 0 || ret + granularity > gran_max_offset) {
        return false;
    }

    *offset = ret;
    size = 0;

    assert(granularity <= INT_MAX);

    do {
        /* Advance iterator */
        ret = hbitmap_iter_next(&iter->hbi, true);
        size += granularity;
    } while (ret + granularity <= gran_max_offset &&
             hbitmap_iter_next(&iter->hbi, false) == ret + granularity &&
             size <= INT_MAX - granularity);

    *bytes = MIN(size, max_offset - *offset);
    return true;
}

/* Called within bdrv_dirty_bitmap_lock..unlock */
+210 −122

File changed.

Preview size limit exceeded, changes collapsed.

Loading