20.11.2019 17:03, Kevin Wolf wrote:
> When extending the size of an image that has a backing file larger than
> its old size, make sure that the backing file data doesn't become
> visible in the guest, but the added area is properly zeroed out.
>
> The old behaviour made a difference in 'block_resize' (where showing the
> backing file data from an old snapshot rather than zeros is
> questionable) as well as in commit block jobs (both from active and
> intermediate nodes) and HMP 'commit', where committing to a short
> backing file would incorrectly omit writing zeroes for unallocated
> blocks on the top layer after the EOF of the short backing file.
>
> Signed-off-by: Kevin Wolf <[email protected]>
> ---
> block/io.c | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/block/io.c b/block/io.c
> index 003f4ea38c..8683f7a4bd 100644
> --- a/block/io.c
> +++ b/block/io.c
> @@ -3382,6 +3382,31 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child,
> int64_t offset, bool exact,
> goto out;
> }
>
> + /*
> + * If the image has a backing file that is large enough that it would
> + * provide data for the new area, we cannot leave it unallocated because
> + * then the backing file content would become visible. Instead, zero-fill
> + * the area where backing file and new area overlap.
> + */
Should we mention that, still, we don't care if user for some reason will change
backing file in future?
> + if (new_bytes && bs->backing && prealloc == PREALLOC_MODE_OFF) {
> + int64_t backing_len;
> +
> + backing_len = bdrv_getlength(backing_bs(bs));
> + if (backing_len < 0) {
> + ret = backing_len;
> + goto out;
> + }
> +
> + if (backing_len > old_size) {
> + ret = bdrv_co_do_pwrite_zeroes(bs, old_size,
> + MIN(new_bytes, backing_len -
> old_size),
> + BDRV_REQ_ZERO_WRITE |
> BDRV_REQ_MAY_UNMAP);
two over-80 lines
> + if (ret < 0) {
> + goto out;
> + }
> + }
> + }
should we improve "off" mode specification in qapi?
> +
> ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
> if (ret < 0) {
> error_setg_errno(errp, -ret, "Could not refresh total sector
> count");
>
Hmm. is it correct to call write_zeroes before refresh_total_sectors?
Note that qcow2_co_pwrite_zeroes rely on bs->total_sectors...
--
Best regards,
Vladimir