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