thebeanogamer / rpms / qemu-kvm

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