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