26ba25
From d4702dc3b114f30be96a1a2b9fe4f7f05fef1fc0 Mon Sep 17 00:00:00 2001
26ba25
From: Fam Zheng <famz@redhat.com>
26ba25
Date: Wed, 4 Jul 2018 07:56:31 +0200
26ba25
Subject: [PATCH 176/268] qemu-img: Convert with copy offloading
26ba25
26ba25
RH-Author: Fam Zheng <famz@redhat.com>
26ba25
Message-id: <20180629061153.12687-11-famz@redhat.com>
26ba25
Patchwork-id: 81158
26ba25
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH v2 10/13] qemu-img: Convert with copy offloading
26ba25
Bugzilla: 1482537
26ba25
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
26ba25
RH-Acked-by: Max Reitz <mreitz@redhat.com>
26ba25
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
26ba25
26ba25
The new blk_co_copy_range interface offers a more efficient way in the
26ba25
case of network based storage. Make use of it to allow faster convert
26ba25
operation.
26ba25
26ba25
Since copy offloading cannot do zero detection ('-S') and compression
26ba25
(-c), only try it when these options are not used.
26ba25
26ba25
Signed-off-by: Fam Zheng <famz@redhat.com>
26ba25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26ba25
Message-id: 20180601092648.24614-11-famz@redhat.com
26ba25
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
26ba25
(cherry picked from commit ee5306d0923377439776e8a30b9fd2de34b5cbfb)
26ba25
Signed-off-by: Fam Zheng <famz@redhat.com>
26ba25
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
26ba25
---
26ba25
 qemu-img.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
26ba25
 1 file changed, 48 insertions(+), 2 deletions(-)
26ba25
26ba25
diff --git a/qemu-img.c b/qemu-img.c
26ba25
index 9fc8e66..b2ef54e 100644
26ba25
--- a/qemu-img.c
26ba25
+++ b/qemu-img.c
26ba25
@@ -1561,6 +1561,7 @@ typedef struct ImgConvertState {
26ba25
     bool target_has_backing;
26ba25
     int64_t target_backing_sectors; /* negative if unknown */
26ba25
     bool wr_in_order;
26ba25
+    bool copy_range;
26ba25
     int min_sparse;
26ba25
     size_t cluster_sectors;
26ba25
     size_t buf_sectors;
26ba25
@@ -1765,6 +1766,37 @@ static int coroutine_fn convert_co_write(ImgConvertState *s, int64_t sector_num,
26ba25
     return 0;
26ba25
 }
26ba25
 
26ba25
+static int coroutine_fn convert_co_copy_range(ImgConvertState *s, int64_t sector_num,
26ba25
+                                              int nb_sectors)
26ba25
+{
26ba25
+    int n, ret;
26ba25
+
26ba25
+    while (nb_sectors > 0) {
26ba25
+        BlockBackend *blk;
26ba25
+        int src_cur;
26ba25
+        int64_t bs_sectors, src_cur_offset;
26ba25
+        int64_t offset;
26ba25
+
26ba25
+        convert_select_part(s, sector_num, &src_cur, &src_cur_offset);
26ba25
+        offset = (sector_num - src_cur_offset) << BDRV_SECTOR_BITS;
26ba25
+        blk = s->src[src_cur];
26ba25
+        bs_sectors = s->src_sectors[src_cur];
26ba25
+
26ba25
+        n = MIN(nb_sectors, bs_sectors - (sector_num - src_cur_offset));
26ba25
+
26ba25
+        ret = blk_co_copy_range(blk, offset, s->target,
26ba25
+                                sector_num << BDRV_SECTOR_BITS,
26ba25
+                                n << BDRV_SECTOR_BITS, 0);
26ba25
+        if (ret < 0) {
26ba25
+            return ret;
26ba25
+        }
26ba25
+
26ba25
+        sector_num += n;
26ba25
+        nb_sectors -= n;
26ba25
+    }
26ba25
+    return 0;
26ba25
+}
26ba25
+
26ba25
 static void coroutine_fn convert_co_do_copy(void *opaque)
26ba25
 {
26ba25
     ImgConvertState *s = opaque;
26ba25
@@ -1787,6 +1819,7 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
26ba25
         int n;
26ba25
         int64_t sector_num;
26ba25
         enum ImgConvertBlockStatus status;
26ba25
+        bool copy_range;
26ba25
 
26ba25
         qemu_co_mutex_lock(&s->lock);
26ba25
         if (s->ret != -EINPROGRESS || s->sector_num >= s->total_sectors) {
26ba25
@@ -1816,7 +1849,9 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
26ba25
                                         s->allocated_sectors, 0);
26ba25
         }
26ba25
 
26ba25
-        if (status == BLK_DATA) {
26ba25
+retry:
26ba25
+        copy_range = s->copy_range && s->status == BLK_DATA;
26ba25
+        if (status == BLK_DATA && !copy_range) {
26ba25
             ret = convert_co_read(s, sector_num, n, buf);
26ba25
             if (ret < 0) {
26ba25
                 error_report("error while reading sector %" PRId64
26ba25
@@ -1838,7 +1873,15 @@ static void coroutine_fn convert_co_do_copy(void *opaque)
26ba25
         }
26ba25
 
26ba25
         if (s->ret == -EINPROGRESS) {
26ba25
-            ret = convert_co_write(s, sector_num, n, buf, status);
26ba25
+            if (copy_range) {
26ba25
+                ret = convert_co_copy_range(s, sector_num, n);
26ba25
+                if (ret) {
26ba25
+                    s->copy_range = false;
26ba25
+                    goto retry;
26ba25
+                }
26ba25
+            } else {
26ba25
+                ret = convert_co_write(s, sector_num, n, buf, status);
26ba25
+            }
26ba25
             if (ret < 0) {
26ba25
                 error_report("error while writing sector %" PRId64
26ba25
                              ": %s", sector_num, strerror(-ret));
26ba25
@@ -1961,6 +2004,7 @@ static int img_convert(int argc, char **argv)
26ba25
     ImgConvertState s = (ImgConvertState) {
26ba25
         /* Need at least 4k of zeros for sparse detection */
26ba25
         .min_sparse         = 8,
26ba25
+        .copy_range         = true,
26ba25
         .buf_sectors        = IO_BUF_SIZE / BDRV_SECTOR_SIZE,
26ba25
         .wr_in_order        = true,
26ba25
         .num_coroutines     = 8,
26ba25
@@ -2001,6 +2045,7 @@ static int img_convert(int argc, char **argv)
26ba25
             break;
26ba25
         case 'c':
26ba25
             s.compressed = true;
26ba25
+            s.copy_range = false;
26ba25
             break;
26ba25
         case 'o':
26ba25
             if (!is_valid_option_list(optarg)) {
26ba25
@@ -2042,6 +2087,7 @@ static int img_convert(int argc, char **argv)
26ba25
             }
26ba25
 
26ba25
             s.min_sparse = sval / BDRV_SECTOR_SIZE;
26ba25
+            s.copy_range = false;
26ba25
             break;
26ba25
         }
26ba25
         case 'p':
26ba25
-- 
26ba25
1.8.3.1
26ba25