Blame SOURCES/kvm-block-add-BDRV_REQ_SERIALISING-flag.patch

1bdc94
From 0ea414a81a3e1372257a54c8756a643b91ae773a Mon Sep 17 00:00:00 2001
1bdc94
From: John Snow <jsnow@redhat.com>
1bdc94
Date: Wed, 18 Jul 2018 22:54:57 +0200
1bdc94
Subject: [PATCH 72/89] block: add BDRV_REQ_SERIALISING flag
1bdc94
1bdc94
RH-Author: John Snow <jsnow@redhat.com>
1bdc94
Message-id: <20180718225511.14878-22-jsnow@redhat.com>
1bdc94
Patchwork-id: 81421
1bdc94
O-Subject: [RHEL-7.6 qemu-kvm-rhev PATCH 21/35] block: add BDRV_REQ_SERIALISING flag
1bdc94
Bugzilla: 1207657
1bdc94
RH-Acked-by: Eric Blake <eblake@redhat.com>
1bdc94
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
1bdc94
RH-Acked-by: Fam Zheng <famz@redhat.com>
1bdc94
1bdc94
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1bdc94
1bdc94
Serialized writes should be used in copy-on-write of backup(sync=none)
1bdc94
for image fleecing scheme.
1bdc94
1bdc94
We need to change an assert in bdrv_aligned_pwritev, added in
1bdc94
28de2dcd88de. The assert may fail now, because call to
1bdc94
wait_serialising_requests here may become first call to it for this
1bdc94
request with serializing flag set. It occurs if the request is aligned
1bdc94
(otherwise, we should already set serializing flag before calling
1bdc94
bdrv_aligned_pwritev and correspondingly waited for all intersecting
1bdc94
requests). However, for aligned requests, we should not care about
1bdc94
outdating of previously read data, as there no such data. Therefore,
1bdc94
let's just update an assert to not care about aligned requests.
1bdc94
1bdc94
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1bdc94
Reviewed-by: Fam Zheng <famz@redhat.com>
1bdc94
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1bdc94
(cherry picked from commit 09d2f948462f4979d18f573a0734d1daae8e67a9)
1bdc94
Signed-off-by: John Snow <jsnow@redhat.com>
1bdc94
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
1bdc94
---
1bdc94
 block/io.c            | 28 +++++++++++++++++++++++++++-
1bdc94
 include/block/block.h | 14 +++++++++++++-
1bdc94
 2 files changed, 40 insertions(+), 2 deletions(-)
1bdc94
1bdc94
diff --git a/block/io.c b/block/io.c
1bdc94
index 2d04289..bb617de 100644
1bdc94
--- a/block/io.c
1bdc94
+++ b/block/io.c
1bdc94
@@ -535,6 +535,18 @@ static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align)
1bdc94
     req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes);
1bdc94
 }
1bdc94
 
1bdc94
+static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req)
1bdc94
+{
1bdc94
+    /*
1bdc94
+     * If the request is serialising, overlap_offset and overlap_bytes are set,
1bdc94
+     * so we can check if the request is aligned. Otherwise, don't care and
1bdc94
+     * return false.
1bdc94
+     */
1bdc94
+
1bdc94
+    return req->serialising && (req->offset == req->overlap_offset) &&
1bdc94
+           (req->bytes == req->overlap_bytes);
1bdc94
+}
1bdc94
+
1bdc94
 /**
1bdc94
  * Round a region to cluster boundaries
1bdc94
  */
1bdc94
@@ -1206,6 +1218,9 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child,
1bdc94
         mark_request_serialising(req, bdrv_get_cluster_size(bs));
1bdc94
     }
1bdc94
 
1bdc94
+    /* BDRV_REQ_SERIALISING is only for write operation */
1bdc94
+    assert(!(flags & BDRV_REQ_SERIALISING));
1bdc94
+
1bdc94
     if (!(flags & BDRV_REQ_NO_SERIALISING)) {
1bdc94
         wait_serialising_requests(req);
1bdc94
     }
1bdc94
@@ -1507,8 +1522,14 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
1bdc94
 
1bdc94
     /* BDRV_REQ_NO_SERIALISING is only for read operation */
1bdc94
     assert(!(flags & BDRV_REQ_NO_SERIALISING));
1bdc94
+
1bdc94
+    if (flags & BDRV_REQ_SERIALISING) {
1bdc94
+        mark_request_serialising(req, bdrv_get_cluster_size(bs));
1bdc94
+    }
1bdc94
+
1bdc94
     waited = wait_serialising_requests(req);
1bdc94
-    assert(!waited || !req->serialising);
1bdc94
+    assert(!waited || !req->serialising ||
1bdc94
+           is_request_serialising_and_aligned(req));
1bdc94
     assert(req->overlap_offset <= offset);
1bdc94
     assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
1bdc94
     if (flags & BDRV_REQ_WRITE_UNCHANGED) {
1bdc94
@@ -2881,6 +2902,8 @@ static int coroutine_fn bdrv_co_copy_range_internal(
1bdc94
         tracked_request_begin(&req, src->bs, src_offset, bytes,
1bdc94
                               BDRV_TRACKED_READ);
1bdc94
 
1bdc94
+        /* BDRV_REQ_SERIALISING is only for write operation */
1bdc94
+        assert(!(read_flags & BDRV_REQ_SERIALISING));
1bdc94
         if (!(read_flags & BDRV_REQ_NO_SERIALISING)) {
1bdc94
             wait_serialising_requests(&req;;
1bdc94
         }
1bdc94
@@ -2900,6 +2923,9 @@ static int coroutine_fn bdrv_co_copy_range_internal(
1bdc94
 
1bdc94
         /* BDRV_REQ_NO_SERIALISING is only for read operation */
1bdc94
         assert(!(write_flags & BDRV_REQ_NO_SERIALISING));
1bdc94
+        if (write_flags & BDRV_REQ_SERIALISING) {
1bdc94
+            mark_request_serialising(&req, bdrv_get_cluster_size(dst->bs));
1bdc94
+        }
1bdc94
         wait_serialising_requests(&req;;
1bdc94
 
1bdc94
         ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
1bdc94
diff --git a/include/block/block.h b/include/block/block.h
1bdc94
index 409db21..8f87eea 100644
1bdc94
--- a/include/block/block.h
1bdc94
+++ b/include/block/block.h
1bdc94
@@ -70,8 +70,20 @@ typedef enum {
1bdc94
      * content. */
1bdc94
     BDRV_REQ_WRITE_UNCHANGED    = 0x40,
1bdc94
 
1bdc94
+    /*
1bdc94
+     * BDRV_REQ_SERIALISING forces request serialisation for writes.
1bdc94
+     * It is used to ensure that writes to the backing file of a backup process
1bdc94
+     * target cannot race with a read of the backup target that defers to the
1bdc94
+     * backing file.
1bdc94
+     *
1bdc94
+     * Note, that BDRV_REQ_SERIALISING is _not_ opposite in meaning to
1bdc94
+     * BDRV_REQ_NO_SERIALISING. A more descriptive name for the latter might be
1bdc94
+     * _DO_NOT_WAIT_FOR_SERIALISING, except that is too long.
1bdc94
+     */
1bdc94
+    BDRV_REQ_SERIALISING        = 0x80,
1bdc94
+
1bdc94
     /* Mask of valid flags */
1bdc94
-    BDRV_REQ_MASK               = 0x7f,
1bdc94
+    BDRV_REQ_MASK               = 0xff,
1bdc94
 } BdrvRequestFlags;
1bdc94
 
1bdc94
 typedef struct BlockSizes {
1bdc94
-- 
1bdc94
1.8.3.1
1bdc94