0a122b
From 4a1e019ac51460ce6329892cc99fc11d518d2eb2 Mon Sep 17 00:00:00 2001
0a122b
Message-Id: <4a1e019ac51460ce6329892cc99fc11d518d2eb2.1389014116.git.minovotn@redhat.com>
0a122b
In-Reply-To: <c8cc35838d42aa286242772d97e3a9be7bb786ba.1389014116.git.minovotn@redhat.com>
0a122b
References: <c8cc35838d42aa286242772d97e3a9be7bb786ba.1389014116.git.minovotn@redhat.com>
0a122b
From: Paolo Bonzini <pbonzini@redhat.com>
0a122b
Date: Mon, 9 Dec 2013 14:09:16 +0100
0a122b
Subject: [PATCH 28/50] block: make bdrv_co_do_write_zeroes stricter in
0a122b
 producing aligned requests
0a122b
0a122b
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
0a122b
Message-id: <1386598178-11845-31-git-send-email-pbonzini@redhat.com>
0a122b
Patchwork-id: 56067
0a122b
O-Subject: [RHEL 7.0 qemu-kvm PATCH 30/52] block: make bdrv_co_do_write_zeroes stricter in producing aligned requests
0a122b
Bugzilla: 1007815
0a122b
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
0a122b
RH-Acked-by: Fam Zheng <famz@redhat.com>
0a122b
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
0a122b
Right now, bdrv_co_do_write_zeroes will only try to align the
0a122b
beginning of the request.  However, it is simpler for many
0a122b
formats to expect the block layer to separate both the head *and*
0a122b
the tail.  This makes sure that the format's bdrv_co_write_zeroes
0a122b
function will be called with aligned sector_num and nb_sectors for
0a122b
the bulk of the request.
0a122b
0a122b
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
0a122b
Reviewed-by: Peter Lieven <pl@kamp.de>
0a122b
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
(cherry picked from commit b8d71c09f31a9cae248d167dddc75c66d5135ff2)
0a122b
---
0a122b
 block.c | 35 +++++++++++++++++++++++------------
0a122b
 1 file changed, 23 insertions(+), 12 deletions(-)
0a122b
0a122b
Signed-off-by: Michal Novotny <minovotn@redhat.com>
0a122b
---
0a122b
 block.c | 35 +++++++++++++++++++++++------------
0a122b
 1 file changed, 23 insertions(+), 12 deletions(-)
0a122b
0a122b
diff --git a/block.c b/block.c
0a122b
index c9e65b4..1ac1ab3 100644
0a122b
--- a/block.c
0a122b
+++ b/block.c
0a122b
@@ -2781,14 +2781,21 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
0a122b
     while (nb_sectors > 0 && !ret) {
0a122b
         int num = nb_sectors;
0a122b
 
0a122b
-        /* align request */
0a122b
-        if (bs->bl.write_zeroes_alignment &&
0a122b
-            num >= bs->bl.write_zeroes_alignment &&
0a122b
-            sector_num % bs->bl.write_zeroes_alignment) {
0a122b
-            if (num > bs->bl.write_zeroes_alignment) {
0a122b
+        /* Align request.  Block drivers can expect the "bulk" of the request
0a122b
+         * to be aligned.
0a122b
+         */
0a122b
+        if (bs->bl.write_zeroes_alignment
0a122b
+            && num > bs->bl.write_zeroes_alignment) {
0a122b
+            if (sector_num % bs->bl.write_zeroes_alignment != 0) {
0a122b
+                /* Make a small request up to the first aligned sector.  */
0a122b
                 num = bs->bl.write_zeroes_alignment;
0a122b
+                num -= sector_num % bs->bl.write_zeroes_alignment;
0a122b
+            } else if ((sector_num + num) % bs->bl.write_zeroes_alignment != 0) {
0a122b
+                /* Shorten the request to the last aligned sector.  num cannot
0a122b
+                 * underflow because num > bs->bl.write_zeroes_alignment.
0a122b
+                 */
0a122b
+                num -= (sector_num + num) % bs->bl.write_zeroes_alignment;
0a122b
             }
0a122b
-            num -= sector_num % bs->bl.write_zeroes_alignment;
0a122b
         }
0a122b
 
0a122b
         /* limit request size */
0a122b
@@ -2806,16 +2813,20 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
0a122b
             /* Fall back to bounce buffer if write zeroes is unsupported */
0a122b
             iov.iov_len = num * BDRV_SECTOR_SIZE;
0a122b
             if (iov.iov_base == NULL) {
0a122b
-                /* allocate bounce buffer only once and ensure that it
0a122b
-                 * is big enough for this and all future requests.
0a122b
-                 */
0a122b
-                size_t bufsize = num <= nb_sectors ? num : max_write_zeroes;
0a122b
-                iov.iov_base = qemu_blockalign(bs, bufsize * BDRV_SECTOR_SIZE);
0a122b
-                memset(iov.iov_base, 0, bufsize * BDRV_SECTOR_SIZE);
0a122b
+                iov.iov_base = qemu_blockalign(bs, num * BDRV_SECTOR_SIZE);
0a122b
+                memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE);
0a122b
             }
0a122b
             qemu_iovec_init_external(&qiov, &iov, 1);
0a122b
 
0a122b
             ret = drv->bdrv_co_writev(bs, sector_num, num, &qiov);
0a122b
+
0a122b
+            /* Keep bounce buffer around if it is big enough for all
0a122b
+             * all future requests.
0a122b
+             */
0a122b
+            if (num < max_write_zeroes) {
0a122b
+                qemu_vfree(iov.iov_base);
0a122b
+                iov.iov_base = NULL;
0a122b
+            }
0a122b
         }
0a122b
 
0a122b
         sector_num += num;
0a122b
-- 
0a122b
1.7.11.7
0a122b