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

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