From 2dafe60e9ab72cd3c212ef57daf0450390beb332 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 13 Jul 2015 03:27:19 +0200 Subject: [PATCH 01/58] block: Add bdrv_get_block_status_above Message-id: <1436758047-4639-2-git-send-email-famz@redhat.com> Patchwork-id: 66959 O-Subject: [RHEL-7.2 qemu-kvm-rhev PATCH 1/9] block: Add bdrv_get_block_status_above Bugzilla: 1242316 RH-Acked-by: Jeffrey Cody RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Paolo Bonzini Like bdrv_is_allocated_above, this function follows the backing chain until seeing BDRV_BLOCK_ALLOCATED. Base is not included. Reimplement bdrv_is_allocated on top. [Initialized bdrv_co_get_block_status_above() ret to 0 to silence mingw64 compiler warning about the unitialized variable. assert(bs != base) prevents that case but I suppose the program could be compiled with -DNDEBUG. --Stefan] Signed-off-by: Fam Zheng Signed-off-by: Stefan Hajnoczi (cherry picked from commit ba3f0e2545c365ebe1dbddb0e53058710d41881e) Signed-off-by: Fam Zheng Signed-off-by: Miroslav Rezanina --- block.c | 56 +++++++++++++++++++++++++++++++++++++++++---------- include/block/block.h | 4 ++++ 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/block.c b/block.c index d49599b..0b92ecb 100644 --- a/block.c +++ b/block.c @@ -4254,28 +4254,54 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, return ret; } -/* Coroutine wrapper for bdrv_get_block_status() */ -static void coroutine_fn bdrv_get_block_status_co_entry(void *opaque) +static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + int64_t sector_num, + int nb_sectors, + int *pnum) +{ + BlockDriverState *p; + int64_t ret = 0; + + assert(bs != base); + for (p = bs; p != base; p = p->backing_hd) { + ret = bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum); + if (ret < 0 || ret & BDRV_BLOCK_ALLOCATED) { + break; + } + /* [sector_num, pnum] unallocated on this layer, which could be only + * the first part of [sector_num, nb_sectors]. */ + nb_sectors = MIN(nb_sectors, *pnum); + } + return ret; +} + +/* Coroutine wrapper for bdrv_get_block_status_above() */ +static void coroutine_fn bdrv_get_block_status_above_co_entry(void *opaque) { BdrvCoGetBlockStatusData *data = opaque; - BlockDriverState *bs = data->bs; - data->ret = bdrv_co_get_block_status(bs, data->sector_num, data->nb_sectors, - data->pnum); + data->ret = bdrv_co_get_block_status_above(data->bs, data->base, + data->sector_num, + data->nb_sectors, + data->pnum); data->done = true; } /* - * Synchronous wrapper around bdrv_co_get_block_status(). + * Synchronous wrapper around bdrv_co_get_block_status_above(). * - * See bdrv_co_get_block_status() for details. + * See bdrv_co_get_block_status_above() for details. */ -int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int *pnum) +int64_t bdrv_get_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + int64_t sector_num, + int nb_sectors, int *pnum) { Coroutine *co; BdrvCoGetBlockStatusData data = { .bs = bs, + .base = base, .sector_num = sector_num, .nb_sectors = nb_sectors, .pnum = pnum, @@ -4284,11 +4310,11 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, if (qemu_in_coroutine()) { /* Fast-path if already in coroutine context */ - bdrv_get_block_status_co_entry(&data); + bdrv_get_block_status_above_co_entry(&data); } else { AioContext *aio_context = bdrv_get_aio_context(bs); - co = qemu_coroutine_create(bdrv_get_block_status_co_entry); + co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry); qemu_coroutine_enter(co, &data); while (!data.done) { aio_poll(aio_context, true); @@ -4297,6 +4323,14 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, return data.ret; } +int64_t bdrv_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) +{ + return bdrv_get_block_status_above(bs, bs->backing_hd, + sector_num, nb_sectors, pnum); +} + int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { diff --git a/include/block/block.h b/include/block/block.h index 4c57d63..98c6703 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -361,6 +361,10 @@ bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs); bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs); int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); +int64_t bdrv_get_block_status_above(BlockDriverState *bs, + BlockDriverState *base, + int64_t sector_num, + int nb_sectors, int *pnum); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum); int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, -- 1.8.3.1