Blame SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch

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