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