|
|
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 |
|