Commit 4c790afe authored by Kevin Wolf's avatar Kevin Wolf
Browse files

Merge remote-tracking branch 'mreitz/tags/pull-block-2018-06-18' into queue-block



Block patches:
- Active mirror (blockdev-mirror copy-mode=write-blocking)

# gpg: Signature made Mon Jun 18 17:08:19 2018 CEST
# gpg:                using RSA key F407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1  1829 F407 DB00 61D5 CF40

* mreitz/tags/pull-block-2018-06-18:
  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()

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
parents f45280cb e38da020
Loading
Loading
Loading
Loading
+34 −10
Original line number Diff line number Diff line
@@ -3427,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;
        }
    }
@@ -3462,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;
        }
+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;
+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 */
+486 −119

File changed.

Preview size limit exceeded, changes collapsed.

+8 −1
Original line number Diff line number Diff line
@@ -3586,6 +3586,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
                                   bool has_unmap, bool unmap,
                                   bool has_filter_node_name,
                                   const char *filter_node_name,
                                   bool has_copy_mode, MirrorCopyMode copy_mode,
                                   Error **errp)
{

@@ -3610,6 +3611,9 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
    if (!has_filter_node_name) {
        filter_node_name = NULL;
    }
    if (!has_copy_mode) {
        copy_mode = MIRROR_COPY_MODE_BACKGROUND;
    }

    if (granularity != 0 && (granularity < 512 || granularity > 1048576 * 64)) {
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "granularity",
@@ -3640,7 +3644,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
                 has_replaces ? replaces : NULL,
                 speed, granularity, buf_size, sync, backing_mode,
                 on_source_error, on_target_error, unmap, filter_node_name,
                 errp);
                 copy_mode, errp);
}

void qmp_drive_mirror(DriveMirror *arg, Error **errp)
@@ -3786,6 +3790,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
                           arg->has_on_target_error, arg->on_target_error,
                           arg->has_unmap, arg->unmap,
                           false, NULL,
                           arg->has_copy_mode, arg->copy_mode,
                           &local_err);
    bdrv_unref(target_bs);
    error_propagate(errp, local_err);
@@ -3806,6 +3811,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
                         BlockdevOnError on_target_error,
                         bool has_filter_node_name,
                         const char *filter_node_name,
                         bool has_copy_mode, MirrorCopyMode copy_mode,
                         Error **errp)
{
    BlockDriverState *bs;
@@ -3838,6 +3844,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
                           has_on_target_error, on_target_error,
                           true, true,
                           has_filter_node_name, filter_node_name,
                           has_copy_mode, copy_mode,
                           &local_err);
    error_propagate(errp, local_err);

Loading