Blame SOURCES/kvm-block-io-fix-copy_range.patch

357786
From 75720bedd9d4ba79f7eff5213f30af5e6c475570 Mon Sep 17 00:00:00 2001
357786
From: John Snow <jsnow@redhat.com>
357786
Date: Tue, 24 Jul 2018 12:59:12 +0200
357786
Subject: [PATCH 70/89] block/io: fix copy_range
357786
357786
RH-Author: John Snow <jsnow@redhat.com>
357786
Message-id: <20180718225511.14878-20-jsnow@redhat.com>
357786
Patchwork-id: 81420
357786
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH 19/35] block/io: fix copy_range
357786
Bugzilla: 1207657
357786
RH-Acked-by: Eric Blake <eblake@redhat.com>
357786
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
357786
RH-Acked-by: Fam Zheng <famz@redhat.com>
357786
357786
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
357786
357786
Here two things are fixed:
357786
357786
1. Architecture
357786
357786
On each recursion step, we go to the child of src or dst, only for one
357786
of them. So, it's wrong to create tracked requests for both on each
357786
step. It leads to tracked requests duplication.
357786
357786
2. Wait for serializing requests on write path independently of
357786
   BDRV_REQ_NO_SERIALISING
357786
357786
Before commit 9ded4a01149 "backup: Use copy offloading",
357786
BDRV_REQ_NO_SERIALISING was used for only one case: read in
357786
copy-on-write operation during backup. Also, the flag was handled only
357786
on read path (in bdrv_co_preadv and bdrv_aligned_preadv).
357786
357786
After 9ded4a01149, flag is used for not waiting serializing operations
357786
on backup target (in same case of copy-on-write operation). This
357786
behavior change is unsubstantiated and potentially dangerous, let's
357786
drop it and add additional asserts and documentation.
357786
357786
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
357786
Reviewed-by: Fam Zheng <famz@redhat.com>
357786
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
357786
(cherry picked from commit 999658a05e61a8d87b65827da665302bb44ce8c9)
357786
Signed-off-by: John Snow <jsnow@redhat.com>
357786
---
357786
 block/io.c            | 43 +++++++++++++++++++++++++++----------------
357786
 include/block/block.h | 12 ++++++++++++
357786
 2 files changed, 39 insertions(+), 16 deletions(-)
357786
357786
diff --git a/block/io.c b/block/io.c
357786
index b6754f3..f8de42f 100644
357786
--- a/block/io.c
357786
+++ b/block/io.c
357786
@@ -1505,6 +1505,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
357786
     max_transfer = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_transfer, INT_MAX),
357786
                                    align);
357786
 
357786
+    /* BDRV_REQ_NO_SERIALISING is only for read operation */
357786
+    assert(!(flags & BDRV_REQ_NO_SERIALISING));
357786
     waited = wait_serialising_requests(req);
357786
     assert(!waited || !req->serialising);
357786
     assert(req->overlap_offset <= offset);
357786
@@ -2847,7 +2849,7 @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
357786
                                                     BdrvRequestFlags flags,
357786
                                                     bool recurse_src)
357786
 {
357786
-    BdrvTrackedRequest src_req, dst_req;
357786
+    BdrvTrackedRequest req;
357786
     int ret;
357786
 
357786
     if (!dst || !dst->bs) {
357786
@@ -2876,32 +2878,41 @@ static int coroutine_fn bdrv_co_copy_range_internal(BdrvChild *src,
357786
         return -ENOTSUP;
357786
     }
357786
 
357786
-    bdrv_inc_in_flight(src->bs);
357786
-    bdrv_inc_in_flight(dst->bs);
357786
-    tracked_request_begin(&src_req, src->bs, src_offset,
357786
-                          bytes, BDRV_TRACKED_READ);
357786
-    tracked_request_begin(&dst_req, dst->bs, dst_offset,
357786
-                          bytes, BDRV_TRACKED_WRITE);
357786
-
357786
-    if (!(flags & BDRV_REQ_NO_SERIALISING)) {
357786
-        wait_serialising_requests(&src_req);
357786
-        wait_serialising_requests(&dst_req);
357786
-    }
357786
     if (recurse_src) {
357786
+        bdrv_inc_in_flight(src->bs);
357786
+        tracked_request_begin(&req, src->bs, src_offset, bytes,
357786
+                              BDRV_TRACKED_READ);
357786
+
357786
+        if (!(flags & BDRV_REQ_NO_SERIALISING)) {
357786
+            wait_serialising_requests(&req;;
357786
+        }
357786
+
357786
         ret = src->bs->drv->bdrv_co_copy_range_from(src->bs,
357786
                                                     src, src_offset,
357786
                                                     dst, dst_offset,
357786
                                                     bytes, flags);
357786
+
357786
+        tracked_request_end(&req;;
357786
+        bdrv_dec_in_flight(src->bs);
357786
     } else {
357786
+        bdrv_inc_in_flight(dst->bs);
357786
+        tracked_request_begin(&req, dst->bs, dst_offset, bytes,
357786
+                              BDRV_TRACKED_WRITE);
357786
+
357786
+        /* BDRV_REQ_NO_SERIALISING is only for read operation,
357786
+         * so we ignore it in flags.
357786
+         */
357786
+        wait_serialising_requests(&req;;
357786
+
357786
         ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
357786
                                                   src, src_offset,
357786
                                                   dst, dst_offset,
357786
                                                   bytes, flags);
357786
+
357786
+        tracked_request_end(&req;;
357786
+        bdrv_dec_in_flight(dst->bs);
357786
     }
357786
-    tracked_request_end(&src_req);
357786
-    tracked_request_end(&dst_req);
357786
-    bdrv_dec_in_flight(src->bs);
357786
-    bdrv_dec_in_flight(dst->bs);
357786
+
357786
     return ret;
357786
 }
357786
 
357786
diff --git a/include/block/block.h b/include/block/block.h
357786
index e1d5e47..716fb5b 100644
357786
--- a/include/block/block.h
357786
+++ b/include/block/block.h
357786
@@ -50,6 +50,18 @@ typedef enum {
357786
      * opened with BDRV_O_UNMAP.
357786
      */
357786
     BDRV_REQ_MAY_UNMAP          = 0x4,
357786
+
357786
+    /*
357786
+     * The BDRV_REQ_NO_SERIALISING flag is only valid for reads and means that
357786
+     * we don't want wait_serialising_requests() during the read operation.
357786
+     *
357786
+     * This flag is used for backup copy-on-write operations, when we need to
357786
+     * read old data before write (write notifier triggered). It is okay since
357786
+     * we already waited for other serializing requests in the initiating write
357786
+     * (see bdrv_aligned_pwritev), and it is necessary if the initiating write
357786
+     * is already serializing (without the flag, the read would deadlock
357786
+     * waiting for the serialising write to complete).
357786
+     */
357786
     BDRV_REQ_NO_SERIALISING     = 0x8,
357786
     BDRV_REQ_FUA                = 0x10,
357786
     BDRV_REQ_WRITE_COMPRESSED   = 0x20,
357786
-- 
357786
1.8.3.1
357786