When making the request shorter, use bl.request_alignment as the alignment. This partially fixes iotests 154 and 271 with qcow2.
Signed-off-by: Fiona Ebner <[email protected]> --- block/io.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/block/io.c b/block/io.c index 233b2617ea..d92b30bce5 100644 --- a/block/io.c +++ b/block/io.c @@ -2162,6 +2162,7 @@ bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, int ret = 0; bool padding; BdrvRequestPadding pad; + uint64_t total_length = bs->total_sectors * BDRV_SECTOR_SIZE; /* This flag doesn't make sense for padding or zero writes */ flags &= ~BDRV_REQ_REGISTERED_BUF; @@ -2177,10 +2178,21 @@ bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, int64_t aligned_offset = offset & ~(align - 1); int64_t write_bytes = pad.merge_reads ? pad.buf_len : align; - qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); - ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes, - align, &local_qiov, 0, - flags & ~BDRV_REQ_ZERO_WRITE); + if (total_length >= aligned_offset + write_bytes) { + qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); + ret = bdrv_aligned_pwritev(child, req, aligned_offset, + write_bytes, align, &local_qiov, 0, + flags & ~BDRV_REQ_ZERO_WRITE); + } else { + write_bytes = total_length - aligned_offset; + qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); + ret = bdrv_aligned_pwritev(child, req, aligned_offset, + write_bytes, + bs->bl.request_alignment, + &local_qiov, 0, + flags & ~BDRV_REQ_ZERO_WRITE); + } + if (ret < 0 || pad.merge_reads) { /* Error or all work is done */ goto out; @@ -2205,12 +2217,20 @@ bdrv_co_do_zero_pwritev(BdrvChild *child, int64_t offset, int64_t bytes, assert(!bytes || (offset & (align - 1)) == 0); if (bytes) { - assert(align == pad.tail + bytes); + if (total_length >= offset + align) { + assert(align == pad.tail + bytes); - qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); - ret = bdrv_aligned_pwritev(child, req, offset, align, align, - &local_qiov, 0, - flags & ~BDRV_REQ_ZERO_WRITE); + qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); + ret = bdrv_aligned_pwritev(child, req, offset, align, align, + &local_qiov, 0, + flags & ~BDRV_REQ_ZERO_WRITE); + } else { + int64_t write_bytes = total_length - offset; + qemu_iovec_init_buf(&local_qiov, pad.tail_buf, write_bytes); + ret = bdrv_aligned_pwritev(child, req, offset, write_bytes, + bs->bl.request_alignment, &local_qiov, 0, + flags & ~BDRV_REQ_ZERO_WRITE); + } } out: -- 2.47.3
