|
|
7711c0 |
From 7122c1ace9649d525da8670d5e57aaa8b7c6a686 Mon Sep 17 00:00:00 2001
|
|
|
7711c0 |
From: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Date: Mon, 6 May 2019 17:56:18 +0200
|
|
|
7711c0 |
Subject: [PATCH 08/53] nbd/client: Lower min_block for block-status, unaligned
|
|
|
7711c0 |
size
|
|
|
7711c0 |
|
|
|
7711c0 |
RH-Author: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Message-id: <20190506175629.11079-9-jsnow@redhat.com>
|
|
|
7711c0 |
Patchwork-id: 87187
|
|
|
7711c0 |
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 08/19] nbd/client: Lower min_block for block-status, unaligned size
|
|
|
7711c0 |
Bugzilla: 1692018
|
|
|
7711c0 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
|
|
|
7711c0 |
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
From: Eric Blake <eblake@redhat.com>
|
|
|
7711c0 |
|
|
|
7711c0 |
We have a latent bug in our NBD client code, tickled by the brand new
|
|
|
7711c0 |
nbdkit 1.11.10 block status support:
|
|
|
7711c0 |
|
|
|
7711c0 |
$ nbdkit --filter=log --filter=truncate -U - \
|
|
|
7711c0 |
data data="1" size=511 truncate=64K logfile=/dev/stdout \
|
|
|
7711c0 |
--run 'qemu-img convert $nbd /var/tmp/out'
|
|
|
7711c0 |
...
|
|
|
7711c0 |
qemu-img: block/io.c:2122: bdrv_co_block_status: Assertion `*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' failed.
|
|
|
7711c0 |
|
|
|
7711c0 |
The culprit? Our implementation of .bdrv_co_block_status can return
|
|
|
7711c0 |
unaligned block status for any server that operates with a lower
|
|
|
7711c0 |
actual alignment than what we tell the block layer in
|
|
|
7711c0 |
request_alignment, in violation of the block layer's constraints. To
|
|
|
7711c0 |
date, we've been unable to trip the bug, because qemu as NBD server
|
|
|
7711c0 |
always advertises block sizing (at which point it is a server bug if
|
|
|
7711c0 |
the server sends unaligned status - although qemu 3.1 is such a server
|
|
|
7711c0 |
and I've sent separate patches for 4.0 both to get the server to obey
|
|
|
7711c0 |
the spec, and to let the client to tolerate server oddities at EOF).
|
|
|
7711c0 |
|
|
|
7711c0 |
But nbdkit does not (yet) advertise block sizing, and therefore is not
|
|
|
7711c0 |
in violation of the spec for returning block status at whatever
|
|
|
7711c0 |
boundaries it wants, and those unaligned results can occur anywhere
|
|
|
7711c0 |
rather than just at EOF. While we are still wise to avoid sending
|
|
|
7711c0 |
sub-sector read/write requests to a server of unknown origin, we MUST
|
|
|
7711c0 |
consider that a server telling us block status without an advertised
|
|
|
7711c0 |
block size is correct. So, we either have to munge unaligned answers
|
|
|
7711c0 |
from the server into aligned ones that we hand back to the block
|
|
|
7711c0 |
layer, or we have to tell the block layer about a smaller alignment.
|
|
|
7711c0 |
|
|
|
7711c0 |
Similarly, if the server advertises an image size that is not
|
|
|
7711c0 |
sector-aligned, we might as well assume that the server intends to let
|
|
|
7711c0 |
us access those tail bytes, and therefore supports a minimum block
|
|
|
7711c0 |
size of 1, regardless of whether the server supports block status
|
|
|
7711c0 |
(although we still need more patches to fix the problem that with an
|
|
|
7711c0 |
unaligned image, we can send read or block status requests that exceed
|
|
|
7711c0 |
EOF to the server). Again, qemu as server cannot trip this problem
|
|
|
7711c0 |
(because it rounds images to sector alignment), but nbdkit advertised
|
|
|
7711c0 |
unaligned size even before it gained block status support.
|
|
|
7711c0 |
|
|
|
7711c0 |
Solve both alignment problems at once by using better heuristics on
|
|
|
7711c0 |
what alignment to report to the block layer when the server did not
|
|
|
7711c0 |
give us something to work with. Note that very few NBD servers
|
|
|
7711c0 |
implement block status (to date, only qemu and nbdkit are known to do
|
|
|
7711c0 |
so); and as the NBD spec mentioned block sizing constraints prior to
|
|
|
7711c0 |
documenting block status, it can be assumed that any future
|
|
|
7711c0 |
implementations of block status are aware that they must advertise
|
|
|
7711c0 |
block size if they want a minimum size other than 1.
|
|
|
7711c0 |
|
|
|
7711c0 |
We've had a long history of struggles with picking the right alignment
|
|
|
7711c0 |
to use in the block layer, as evidenced by the commit message of
|
|
|
7711c0 |
fd8d372d (v2.12) that introduced the current choice of forced 512-byte
|
|
|
7711c0 |
alignment.
|
|
|
7711c0 |
|
|
|
7711c0 |
There is no iotest coverage for this fix, because qemu can't provoke
|
|
|
7711c0 |
it, and I didn't want to make test 241 dependent on nbdkit.
|
|
|
7711c0 |
|
|
|
7711c0 |
Fixes: fd8d372d
|
|
|
7711c0 |
Reported-by: Richard W.M. Jones <rjones@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Eric Blake <eblake@redhat.com>
|
|
|
7711c0 |
Message-Id: <20190329042750.14704-3-eblake@redhat.com>
|
|
|
7711c0 |
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
|
|
|
7711c0 |
Tested-by: Richard W.M. Jones <rjones@redhat.com>
|
|
|
7711c0 |
(cherry picked from commit 7da537f70d929800ba9c657b8a47a7b827695ccc)
|
|
|
7711c0 |
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
|
7711c0 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
7711c0 |
---
|
|
|
7711c0 |
block/nbd.c | 19 ++++++++++++++++++-
|
|
|
7711c0 |
1 file changed, 18 insertions(+), 1 deletion(-)
|
|
|
7711c0 |
|
|
|
7711c0 |
diff --git a/block/nbd.c b/block/nbd.c
|
|
|
7711c0 |
index 838a8fe..670b9bd 100644
|
|
|
7711c0 |
--- a/block/nbd.c
|
|
|
7711c0 |
+++ b/block/nbd.c
|
|
|
7711c0 |
@@ -437,7 +437,24 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
|
|
|
7711c0 |
uint32_t min = s->info.min_block;
|
|
|
7711c0 |
uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block);
|
|
|
7711c0 |
|
|
|
7711c0 |
- bs->bl.request_alignment = min ? min : BDRV_SECTOR_SIZE;
|
|
|
7711c0 |
+ /*
|
|
|
7711c0 |
+ * If the server did not advertise an alignment:
|
|
|
7711c0 |
+ * - a size that is not sector-aligned implies that an alignment
|
|
|
7711c0 |
+ * of 1 can be used to access those tail bytes
|
|
|
7711c0 |
+ * - advertisement of block status requires an alignment of 1, so
|
|
|
7711c0 |
+ * that we don't violate block layer constraints that block
|
|
|
7711c0 |
+ * status is always aligned (as we can't control whether the
|
|
|
7711c0 |
+ * server will report sub-sector extents, such as a hole at EOF
|
|
|
7711c0 |
+ * on an unaligned POSIX file)
|
|
|
7711c0 |
+ * - otherwise, assume the server is so old that we are safer avoiding
|
|
|
7711c0 |
+ * sub-sector requests
|
|
|
7711c0 |
+ */
|
|
|
7711c0 |
+ if (!min) {
|
|
|
7711c0 |
+ min = (!QEMU_IS_ALIGNED(s->info.size, BDRV_SECTOR_SIZE) ||
|
|
|
7711c0 |
+ s->info.base_allocation) ? 1 : BDRV_SECTOR_SIZE;
|
|
|
7711c0 |
+ }
|
|
|
7711c0 |
+
|
|
|
7711c0 |
+ bs->bl.request_alignment = min;
|
|
|
7711c0 |
bs->bl.max_pdiscard = max;
|
|
|
7711c0 |
bs->bl.max_pwrite_zeroes = max;
|
|
|
7711c0 |
bs->bl.max_transfer = max;
|
|
|
7711c0 |
--
|
|
|
7711c0 |
1.8.3.1
|
|
|
7711c0 |
|