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