Commit 170d3bd3 authored by Andrey Shinkevich's avatar Andrey Shinkevich Committed by Max Reitz
Browse files

block: include base when checking image chain for block allocation



This patch is used in the 'block/stream: introduce a bottom node'
that is following. Instead of the base node, the caller may pass
the node that has the base as its backing image to the function
bdrv_is_allocated_above() with a new parameter include_base = true
and get rid of the dependency on the base that may change during
commit/stream parallel jobs. Now, if the specified base is not
found in the backing image chain, the QEMU will abort.

Suggested-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: default avatarAndrey Shinkevich <andrey.shinkevich@virtuozzo.com>
Reviewed-by: default avatarVladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
Message-id: 1559152576-281803-2-git-send-email-andrey.shinkevich@virtuozzo.com
[mreitz: Squashed in the following as a rebase on conflicting patches:]
Message-id: e3cf99ae-62e9-8b6e-5a06-d3c8b9363b85@redhat.com
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
parent d24f8023
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ static int coroutine_fn commit_run(Job *job, Error **errp)
            break;
        }
        /* Copy if allocated above the base */
        ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base),
        ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base), false,
                                      offset, COMMIT_BUFFER_SIZE, &n);
        copy = (ret == 1);
        trace_commit_one_iteration(s, offset, n, ret);
+15 −6
Original line number Diff line number Diff line
@@ -2295,10 +2295,11 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
/*
 * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP]
 *
 * Return true if (a prefix of) the given range is allocated in any image
 * between BASE and TOP (inclusive).  BASE can be NULL to check if the given
 * offset is allocated in any image of the chain.  Return false otherwise,
 * or negative errno on failure.
 * Return 1 if (a prefix of) the given range is allocated in any image
 * between BASE and TOP (BASE is only included if include_base is set).
 * BASE can be NULL to check if the given offset is allocated in any
 * image of the chain.  Return 0 otherwise, or negative errno on
 * failure.
 *
 * 'pnum' is set to the number of bytes (including and immediately
 * following the specified offset) that are known to be in the same
@@ -2310,17 +2311,21 @@ int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
 */
int bdrv_is_allocated_above(BlockDriverState *top,
                            BlockDriverState *base,
                            int64_t offset, int64_t bytes, int64_t *pnum)
                            bool include_base, int64_t offset,
                            int64_t bytes, int64_t *pnum)
{
    BlockDriverState *intermediate;
    int ret;
    int64_t n = bytes;

    assert(base || !include_base);

    intermediate = top;
    while (intermediate && intermediate != base) {
    while (include_base || intermediate != base) {
        int64_t pnum_inter;
        int64_t size_inter;

        assert(intermediate);
        ret = bdrv_is_allocated(intermediate, offset, bytes, &pnum_inter);
        if (ret < 0) {
            return ret;
@@ -2339,6 +2344,10 @@ int bdrv_is_allocated_above(BlockDriverState *top,
            n = pnum_inter;
        }

        if (intermediate == base) {
            break;
        }

        intermediate = backing_bs(intermediate);
    }

+1 −1
Original line number Diff line number Diff line
@@ -808,7 +808,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s)
            return 0;
        }

        ret = bdrv_is_allocated_above(bs, base, offset, bytes, &count);
        ret = bdrv_is_allocated_above(bs, base, false, offset, bytes, &count);
        if (ret < 0) {
            return ret;
        }
+2 −1
Original line number Diff line number Diff line
@@ -2148,7 +2148,8 @@ static bool is_unallocated(BlockDriverState *bs, int64_t offset, int64_t bytes)
{
    int64_t nr;
    return !bytes ||
        (!bdrv_is_allocated_above(bs, NULL, offset, bytes, &nr) && nr == bytes);
        (!bdrv_is_allocated_above(bs, NULL, false, offset, bytes, &nr) &&
         nr == bytes);
}

static bool is_zero_cow(BlockDriverState *bs, QCowL2Meta *m)
+1 −1
Original line number Diff line number Diff line
@@ -275,7 +275,7 @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
    while (remaining_sectors > 0) {
        int64_t count;

        ret = bdrv_is_allocated_above(top->bs, base->bs,
        ret = bdrv_is_allocated_above(top->bs, base->bs, false,
                                      sector_num * BDRV_SECTOR_SIZE,
                                      remaining_sectors * BDRV_SECTOR_SIZE,
                                      &count);
Loading