This patch is part of the Fast Virtual Disk (FVD) proposal. See http://wiki.qemu.org/Features/FVD.
This patch adds FVD's implementation of the bdrv_is_allocated() interface. Signed-off-by: Chunqiang Tang <ct...@us.ibm.com> --- block/fvd-misc.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 67 insertions(+), 0 deletions(-) diff --git a/block/fvd-misc.c b/block/fvd-misc.c index 63ed168..766b62b 100644 --- a/block/fvd-misc.c +++ b/block/fvd-misc.c @@ -169,6 +169,73 @@ static int fvd_probe(const uint8_t * buf, int buf_size, const char *filename) static int fvd_is_allocated(BlockDriverState * bs, int64_t sector_num, int nb_sectors, int *pnum) { + BDRVFvdState *s = bs->opaque; + + if (s->prefetch_state == PREFETCH_STATE_FINISHED || + sector_num >= s->base_img_sectors || + !fresh_bitmap_show_sector_in_base_img(sector_num, s)) { + /* For the three cases that data may be saved in the FVD data file, we + * still need to check the underlying storage because those data could + * be holes in a sparse image, due to the optimization of "free write + * to zero-filled blocks". See Section 3.3.3 of the FVD-cow paper. + * This also covers the case of no base image. */ + + if (!s->table) { + return bdrv_is_allocated(s->fvd_data, s->data_offset + sector_num, + nb_sectors, pnum); + } + + /* Use the table to figure it out. */ + int64_t first_chunk = sector_num / s->chunk_size; + int64_t last_chunk = (sector_num + nb_sectors - 1) / s->chunk_size; + int allocated = !IS_EMPTY(s->table[first_chunk]); + int count; + + if (first_chunk == last_chunk) { + /* All data in one chunk. */ + *pnum = nb_sectors; + return allocated; + } + + /* Data in the first chunk. */ + count = s->chunk_size - (sector_num % s->chunk_size); + + /* Full chunks. */ + first_chunk++; + while (first_chunk < last_chunk) { + if ((allocated && IS_EMPTY(s->table[first_chunk])) + || (!allocated && !IS_EMPTY(s->table[first_chunk]))) { + *pnum = count; + return allocated; + } + + count += s->chunk_size; + first_chunk++; + } + + /* Data in the last chunk. */ + if ((allocated && !IS_EMPTY(s->table[last_chunk])) + || (!allocated && IS_EMPTY(s->table[last_chunk]))) { + int nb = (sector_num + nb_sectors) % s->chunk_size; + count += nb ? nb : s->chunk_size; + } + + *pnum = count; + return allocated; + } + + /* Use the FVD metadata to find out sectors in the base image. */ + int64_t end = sector_num + nb_sectors; + if (end > s->base_img_sectors) { + end = s->base_img_sectors; + } + + int64_t next = sector_num + 1; + while (next < end && fresh_bitmap_show_sector_in_base_img(next, s)) { + next++; + } + + *pnum = next - sector_num; return 0; } -- 1.7.0.4