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



Reply via email to