Blame SOURCES/kvm-nbd-server-fix-bitmap-export.patch

7711c0
From d7a0e8fc0484ef18c25e7396baea07dfd6520a30 Mon Sep 17 00:00:00 2001
7711c0
From: John Snow <jsnow@redhat.com>
7711c0
Date: Fri, 22 Mar 2019 03:22:20 +0100
7711c0
Subject: [PATCH 053/163] nbd/server: fix bitmap export
7711c0
7711c0
RH-Author: John Snow <jsnow@redhat.com>
7711c0
Message-id: <20190322032241.8111-8-jsnow@redhat.com>
7711c0
Patchwork-id: 85094
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 07/28] nbd/server: fix bitmap export
7711c0
Bugzilla: 1691563
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
7711c0
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
7711c0
bitmap_to_extents function is broken: it switches dirty variable after
7711c0
every iteration, however it can process only part of dirty (or zero)
7711c0
area during one iteration in case when this area is too large for one
7711c0
extent.
7711c0
7711c0
Fortunately, the bug doesn't produce wrong extent flags: it just inserts
7711c0
a zero-length extent between sequential extents representing large dirty
7711c0
(or zero) area. However, zero-length extents are forbidden by the NBD
7711c0
protocol. So, a careful client should consider such a reply as a server
7711c0
fault, while a less-careful will likely ignore zero-length extents.
7711c0
7711c0
The bug can only be triggered by a client that requests block status
7711c0
for nearly 4G at once (a request of 4G and larger is impossible per
7711c0
the protocol, and requests smaller than 4G less the bitmap granularity
7711c0
cause the loop to quit iterating rather than revisit the tail of the
7711c0
large area); it also cannot trigger if the client used the
7711c0
NBD_CMD_FLAG_REQ_ONE flag.  Since qemu 3.0 as client (using the
7711c0
x-dirty-bitmap extension) always passes the flag, it is immune; and
7711c0
we are not aware of other open-source clients that know how to request
7711c0
qemu:dirty-bitmap:FOO contexts.  Clients that want to avoid the bug
7711c0
could cap block status requests to a smaller length, such as 2G or 3G.
7711c0
7711c0
Fix this by more careful handling of dirty variable.
7711c0
7711c0
Bug was introduced in 3d068aff16
7711c0
 "nbd/server: implement dirty bitmap export", with the whole function.
7711c0
and is present in v3.0.0 release.
7711c0
7711c0
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
Message-Id: <20180914165116.23182-1-vsementsov@virtuozzo.com>
7711c0
CC: qemu-stable@nongnu.org
7711c0
Reviewed-by: Eric Blake <eblake@redhat.com>
7711c0
[eblake: improved commit message]
7711c0
Signed-off-by: Eric Blake <eblake@redhat.com>
7711c0
(cherry picked from commit 6545916d528de7a6b784f4d10e7b236b30bfaced)
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 nbd/server.c | 5 ++++-
7711c0
 1 file changed, 4 insertions(+), 1 deletion(-)
7711c0
7711c0
diff --git a/nbd/server.c b/nbd/server.c
7711c0
index 0ab0dbd..a8ddc4a 100644
7711c0
--- a/nbd/server.c
7711c0
+++ b/nbd/server.c
7711c0
@@ -1951,6 +1951,8 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
7711c0
 
7711c0
     assert(begin < overall_end && nb_extents);
7711c0
     while (begin < overall_end && i < nb_extents) {
7711c0
+        bool next_dirty = !dirty;
7711c0
+
7711c0
         if (dirty) {
7711c0
             end = bdrv_dirty_bitmap_next_zero(bitmap, begin, UINT64_MAX);
7711c0
         } else {
7711c0
@@ -1962,6 +1964,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
7711c0
             end = MIN(bdrv_dirty_bitmap_size(bitmap),
7711c0
                       begin + UINT32_MAX + 1 -
7711c0
                       bdrv_dirty_bitmap_granularity(bitmap));
7711c0
+            next_dirty = dirty;
7711c0
         }
7711c0
         if (dont_fragment && end > overall_end) {
7711c0
             end = overall_end;
7711c0
@@ -1971,7 +1974,7 @@ static unsigned int bitmap_to_extents(BdrvDirtyBitmap *bitmap, uint64_t offset,
7711c0
         extents[i].flags = cpu_to_be32(dirty ? NBD_STATE_DIRTY : 0);
7711c0
         i++;
7711c0
         begin = end;
7711c0
-        dirty = !dirty;
7711c0
+        dirty = next_dirty;
7711c0
     }
7711c0
 
7711c0
     bdrv_dirty_iter_free(it);
7711c0
-- 
7711c0
1.8.3.1
7711c0