Commit 9adc1cb4 authored by Max Reitz's avatar Max Reitz
Browse files

mirror: Only mirror granularity-aligned chunks



In write-blocking mode, all writes to the top node directly go to the
target.  We must only mirror chunks of data that are aligned to the
job's granularity, because that is how the dirty bitmap works.
Therefore, the request alignment for writes must be the job's
granularity (in write-blocking mode).

Unfortunately, this forces all reads and writes to have the same
granularity (we only need this alignment for writes to the target, not
the source), but that is something to be fixed another time.

Cc: qemu-stable@nongnu.org
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
Message-id: 20190805153308.2657-1-mreitz@redhat.com
Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Fixes: d06107ad
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
parent 8a9cb864
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -1481,6 +1481,15 @@ static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
    *nshared = BLK_PERM_ALL;
}

static void bdrv_mirror_top_refresh_limits(BlockDriverState *bs, Error **errp)
{
    MirrorBDSOpaque *s = bs->opaque;

    if (s && s->job && s->job->copy_mode == MIRROR_COPY_MODE_WRITE_BLOCKING) {
        bs->bl.request_alignment = s->job->granularity;
    }
}

/* Dummy node that provides consistent read to its users without requiring it
 * from its backing file and that allows writes on the backing file chain. */
static BlockDriver bdrv_mirror_top = {
@@ -1493,6 +1502,7 @@ static BlockDriver bdrv_mirror_top = {
    .bdrv_co_block_status       = bdrv_co_block_status_from_backing,
    .bdrv_refresh_filename      = bdrv_mirror_top_refresh_filename,
    .bdrv_child_perm            = bdrv_mirror_top_child_perm,
    .bdrv_refresh_limits        = bdrv_mirror_top_refresh_limits,
};

static BlockJob *mirror_start_job(
@@ -1637,6 +1647,25 @@ static BlockJob *mirror_start_job(
        s->should_complete = true;
    }

    /*
     * Must be called before we start tracking writes, but after
     *
     *     ((MirrorBlockJob *)
     *         ((MirrorBDSOpaque *)
     *             mirror_top_bs->opaque
     *         )->job
     *     )->copy_mode
     *
     * has the correct value.
     * (We start tracking writes as of the following
     * bdrv_create_dirty_bitmap() call.)
     */
    bdrv_refresh_limits(mirror_top_bs, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        goto fail;
    }

    s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
    if (!s->dirty_bitmap) {
        goto fail;