block: bdrv_has_zero_init

This fixes the problem that qemu-img's use of no_zero_init only considered the
no_zero_init flag of the format driver, but not of the underlying protocols.

Between the raw/file split and this fix, converting to host devices is broken.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Kevin Wolf 2010-04-14 17:30:35 +02:00
parent 66f82ceed6
commit f2feebbd93
3 changed files with 18 additions and 2 deletions

13
block.c
View File

@ -1282,6 +1282,19 @@ void bdrv_flush_all(void)
} }
} }
int bdrv_has_zero_init(BlockDriverState *bs)
{
assert(bs->drv);
if (bs->drv->no_zero_init) {
return 0;
} else if (bs->file) {
return bdrv_has_zero_init(bs->file);
}
return 1;
}
/* /*
* Returns true iff the specified sector is present in the disk image. Drivers * Returns true iff the specified sector is present in the disk image. Drivers
* not implementing the functionality are assumed to not support backing files, * not implementing the functionality are assumed to not support backing files,

View File

@ -122,6 +122,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
void bdrv_flush(BlockDriverState *bs); void bdrv_flush(BlockDriverState *bs);
void bdrv_flush_all(void); void bdrv_flush_all(void);
int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
int *pnum); int *pnum);

View File

@ -732,6 +732,8 @@ static int img_convert(int argc, char **argv)
/* signal EOF to align */ /* signal EOF to align */
bdrv_write_compressed(out_bs, 0, NULL, 0); bdrv_write_compressed(out_bs, 0, NULL, 0);
} else { } else {
int has_zero_init = bdrv_has_zero_init(out_bs);
sector_num = 0; // total number of sectors converted so far sector_num = 0; // total number of sectors converted so far
for(;;) { for(;;) {
nb_sectors = total_sectors - sector_num; nb_sectors = total_sectors - sector_num;
@ -755,7 +757,7 @@ static int img_convert(int argc, char **argv)
if (n > bs_offset + bs_sectors - sector_num) if (n > bs_offset + bs_sectors - sector_num)
n = bs_offset + bs_sectors - sector_num; n = bs_offset + bs_sectors - sector_num;
if (!drv->no_zero_init) { if (has_zero_init) {
/* If the output image is being created as a copy on write image, /* If the output image is being created as a copy on write image,
assume that sectors which are unallocated in the input image assume that sectors which are unallocated in the input image
are present in both the output's and input's base images (no are present in both the output's and input's base images (no
@ -788,7 +790,7 @@ static int img_convert(int argc, char **argv)
If the output is to a host device, we also write out If the output is to a host device, we also write out
sectors that are entirely 0, since whatever data was sectors that are entirely 0, since whatever data was
already there is garbage, not 0s. */ already there is garbage, not 0s. */
if (drv->no_zero_init || out_baseimg || if (!has_zero_init || out_baseimg ||
is_allocated_sectors(buf1, n, &n1)) { is_allocated_sectors(buf1, n, &n1)) {
if (bdrv_write(out_bs, sector_num, buf1, n1) < 0) if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
error("error while writing"); error("error while writing");