Blame SOURCES/kvm-qcow2-Always-execute-preallocate-in-a-coroutine.patch

4a2fec
From 98ebc4e55985747726bbcbedecbe06fed8d7ea0a Mon Sep 17 00:00:00 2001
4a2fec
From: Max Reitz <mreitz@redhat.com>
4a2fec
Date: Mon, 27 Nov 2017 16:19:58 +0100
4a2fec
Subject: [PATCH 03/21] qcow2: Always execute preallocate() in a coroutine
4a2fec
4a2fec
RH-Author: Max Reitz <mreitz@redhat.com>
4a2fec
Message-id: <20171127161959.13234-4-mreitz@redhat.com>
4a2fec
Patchwork-id: 77913
4a2fec
O-Subject: [RHV-7.5 qemu-kvm-rhev PATCH 3/4] qcow2: Always execute preallocate() in a coroutine
4a2fec
Bugzilla: 1414049
4a2fec
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
4a2fec
RH-Acked-by: Fam Zheng <famz@redhat.com>
4a2fec
RH-Acked-by: John Snow <jsnow@redhat.com>
4a2fec
4a2fec
Some qcow2 functions (at least perform_cow()) expect s->lock to be
4a2fec
taken.  Therefore, if we want to make use of them, we should execute
4a2fec
preallocate() (as "preallocate_co") in a coroutine so that we can use
4a2fec
the qemu_co_mutex_* functions.
4a2fec
4a2fec
Signed-off-by: Max Reitz <mreitz@redhat.com>
4a2fec
Message-id: 20171009215533.12530-3-mreitz@redhat.com
4a2fec
Cc: qemu-stable@nongnu.org
4a2fec
Reviewed-by: Eric Blake <eblake@redhat.com>
4a2fec
Reviewed-by: Jeff Cody <jcody@redhat.com>
4a2fec
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
Signed-off-by: Max Reitz <mreitz@redhat.com>
4a2fec
(cherry picked from commit 572b07bea1d1a0f7726fd95c2613c76002a379bc)
4a2fec
Signed-off-by: Max Reitz <mreitz@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 block/qcow2.c | 41 ++++++++++++++++++++++++++++++++++-------
4a2fec
 1 file changed, 34 insertions(+), 7 deletions(-)
4a2fec
4a2fec
diff --git a/block/qcow2.c b/block/qcow2.c
4a2fec
index 2cfe706..b26cbbf 100644
4a2fec
--- a/block/qcow2.c
4a2fec
+++ b/block/qcow2.c
4a2fec
@@ -2476,6 +2476,14 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
4a2fec
 }
4a2fec
 
4a2fec
 
4a2fec
+typedef struct PreallocCo {
4a2fec
+    BlockDriverState *bs;
4a2fec
+    uint64_t offset;
4a2fec
+    uint64_t new_length;
4a2fec
+
4a2fec
+    int ret;
4a2fec
+} PreallocCo;
4a2fec
+
4a2fec
 /**
4a2fec
  * Preallocates metadata structures for data clusters between @offset (in the
4a2fec
  * guest disk) and @new_length (which is thus generally the new guest disk
4a2fec
@@ -2483,9 +2491,12 @@ static int qcow2_set_up_encryption(BlockDriverState *bs, const char *encryptfmt,
4a2fec
  *
4a2fec
  * Returns: 0 on success, -errno on failure.
4a2fec
  */
4a2fec
-static int preallocate(BlockDriverState *bs,
4a2fec
-                       uint64_t offset, uint64_t new_length)
4a2fec
+static void coroutine_fn preallocate_co(void *opaque)
4a2fec
 {
4a2fec
+    PreallocCo *params = opaque;
4a2fec
+    BlockDriverState *bs = params->bs;
4a2fec
+    uint64_t offset = params->offset;
4a2fec
+    uint64_t new_length = params->new_length;
4a2fec
     BDRVQcow2State *s = bs->opaque;
4a2fec
     uint64_t bytes;
4a2fec
     uint64_t host_offset = 0;
4a2fec
@@ -2493,9 +2504,7 @@ static int preallocate(BlockDriverState *bs,
4a2fec
     int ret;
4a2fec
     QCowL2Meta *meta;
4a2fec
 
4a2fec
-    if (qemu_in_coroutine()) {
4a2fec
-        qemu_co_mutex_lock(&s->lock);
4a2fec
-    }
4a2fec
+    qemu_co_mutex_lock(&s->lock);
4a2fec
 
4a2fec
     assert(offset <= new_length);
4a2fec
     bytes = new_length - offset;
4a2fec
@@ -2549,10 +2558,28 @@ static int preallocate(BlockDriverState *bs,
4a2fec
     ret = 0;
4a2fec
 
4a2fec
 done:
4a2fec
+    qemu_co_mutex_unlock(&s->lock);
4a2fec
+    params->ret = ret;
4a2fec
+}
4a2fec
+
4a2fec
+static int preallocate(BlockDriverState *bs,
4a2fec
+                       uint64_t offset, uint64_t new_length)
4a2fec
+{
4a2fec
+    PreallocCo params = {
4a2fec
+        .bs         = bs,
4a2fec
+        .offset     = offset,
4a2fec
+        .new_length = new_length,
4a2fec
+        .ret        = -EINPROGRESS,
4a2fec
+    };
4a2fec
+
4a2fec
     if (qemu_in_coroutine()) {
4a2fec
-        qemu_co_mutex_unlock(&s->lock);
4a2fec
+        preallocate_co(&params);
4a2fec
+    } else {
4a2fec
+        Coroutine *co = qemu_coroutine_create(preallocate_co, &params);
4a2fec
+        bdrv_coroutine_enter(bs, co);
4a2fec
+        BDRV_POLL_WHILE(bs, params.ret == -EINPROGRESS);
4a2fec
     }
4a2fec
-    return ret;
4a2fec
+    return params.ret;
4a2fec
 }
4a2fec
 
4a2fec
 /* qcow2_refcount_metadata_size:
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec