0a122b
From e3fa109f29c42631c5f0f29e6f0167043fbd7a8d Mon Sep 17 00:00:00 2001
0a122b
From: Kevin Wolf <kwolf@redhat.com>
0a122b
Date: Tue, 14 Jan 2014 11:41:35 +0100
0a122b
Subject: [PATCH 26/37] block: Assert serialisation assumptions in pwritev
0a122b
0a122b
Message-id: <1392117622-28812-27-git-send-email-kwolf@redhat.com>
0a122b
Patchwork-id: 57191
0a122b
O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 26/37] block: Assert serialisation assumptions in pwritev
0a122b
Bugzilla: 748906
0a122b
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
0a122b
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
0a122b
RH-Acked-by: Max Reitz <mreitz@redhat.com>
0a122b
0a122b
If a request calls wait_serialising_requests() and actually has to wait
0a122b
in this function (i.e. a coroutine yield), other requests can run and
0a122b
previously read data (like the head or tail buffer) could become
0a122b
outdated. In this case, we would have to restart from the beginning to
0a122b
read in the updated data.
0a122b
0a122b
However, we're lucky and don't actually need to do that: A request can
0a122b
only wait in the first call of wait_serialising_requests() because we
0a122b
mark it as serialising before that call, so any later requests would
0a122b
wait. So as we don't wait in practice, we don't have to reload the data.
0a122b
0a122b
This is an important assumption that may not be broken or data
0a122b
corruption will happen. Document it with some assertions.
0a122b
0a122b
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
0a122b
Reviewed-by: Max Reitz <mreitz@redhat.com>
0a122b
(cherry picked from commit 28de2dcd88de31f50bbd43d9c2fcb046c3a727cb)
0a122b
0a122b
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
0a122b
---
0a122b
 block.c | 16 ++++++++++++----
0a122b
 1 file changed, 12 insertions(+), 4 deletions(-)
0a122b
---
0a122b
 block.c |   16 ++++++++++++----
0a122b
 1 files changed, 12 insertions(+), 4 deletions(-)
0a122b
0a122b
diff --git a/block.c b/block.c
0a122b
index 9eeb072..76de7d2 100644
0a122b
--- a/block.c
0a122b
+++ b/block.c
0a122b
@@ -2153,14 +2153,15 @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req,
0a122b
     return true;
0a122b
 }
0a122b
 
0a122b
-static void coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
0a122b
+static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
0a122b
 {
0a122b
     BlockDriverState *bs = self->bs;
0a122b
     BdrvTrackedRequest *req;
0a122b
     bool retry;
0a122b
+    bool waited = false;
0a122b
 
0a122b
     if (!bs->serialising_in_flight) {
0a122b
-        return;
0a122b
+        return false;
0a122b
     }
0a122b
 
0a122b
     do {
0a122b
@@ -2186,11 +2187,14 @@ static void coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
0a122b
                     qemu_co_queue_wait(&req->wait_queue);
0a122b
                     self->waiting_for = NULL;
0a122b
                     retry = true;
0a122b
+                    waited = true;
0a122b
                     break;
0a122b
                 }
0a122b
             }
0a122b
         }
0a122b
     } while (retry);
0a122b
+
0a122b
+    return waited;
0a122b
 }
0a122b
 
0a122b
 /*
0a122b
@@ -3036,6 +3040,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
0a122b
     QEMUIOVector *qiov, int flags)
0a122b
 {
0a122b
     BlockDriver *drv = bs->drv;
0a122b
+    bool waited;
0a122b
     int ret;
0a122b
 
0a122b
     int64_t sector_num = offset >> BDRV_SECTOR_BITS;
0a122b
@@ -3044,7 +3049,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
0a122b
     assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
0a122b
     assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
0a122b
 
0a122b
-    wait_serialising_requests(req);
0a122b
+    waited = wait_serialising_requests(req);
0a122b
+    assert(!waited || !req->serialising);
0a122b
 
0a122b
     if (flags & BDRV_REQ_ZERO_WRITE) {
0a122b
         ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors, flags);
0a122b
@@ -3142,9 +3148,11 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
0a122b
         QEMUIOVector tail_qiov;
0a122b
         struct iovec tail_iov;
0a122b
         size_t tail_bytes;
0a122b
+        bool waited;
0a122b
 
0a122b
         mark_request_serialising(&req, align);
0a122b
-        wait_serialising_requests(&req;;
0a122b
+        waited = wait_serialising_requests(&req;;
0a122b
+        assert(!waited || !use_local_qiov);
0a122b
 
0a122b
         tail_buf = qemu_blockalign(bs, align);
0a122b
         tail_iov = (struct iovec) {
0a122b
-- 
0a122b
1.7.1
0a122b