Blame SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch

7711c0
From 3086eb8eb3a2bf4aec260fea793519899432ad70 Mon Sep 17 00:00:00 2001
7711c0
From: John Snow <jsnow@redhat.com>
7711c0
Date: Mon, 6 May 2019 17:56:23 +0200
7711c0
Subject: [PATCH 13/53] nbd/server: Advertise actual minimum block size
7711c0
7711c0
RH-Author: John Snow <jsnow@redhat.com>
7711c0
Message-id: <20190506175629.11079-14-jsnow@redhat.com>
7711c0
Patchwork-id: 87196
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 13/19] nbd/server: Advertise actual minimum block 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
Both NBD_CMD_BLOCK_STATUS and structured NBD_CMD_READ will split their
7711c0
reply according to bdrv_block_status() boundaries. If the block device
7711c0
has a request_alignment smaller than 512, but we advertise a block
7711c0
alignment of 512 to the client, then this can result in the server
7711c0
reply violating client expectations by reporting a smaller region of
7711c0
the export than what the client is permitted to address (although this
7711c0
is less of an issue for qemu 4.0 clients, given recent client patches
7711c0
to overlook our non-compliance at EOF).  Since it's always better to
7711c0
be strict in what we send, it is worth advertising the actual minimum
7711c0
block limit rather than blindly rounding it up to 512.
7711c0
7711c0
Note that this patch is not foolproof - it is still possible to
7711c0
provoke non-compliant server behavior using:
7711c0
7711c0
$ qemu-nbd --image-opts driver=blkdebug,align=512,image.driver=file,image.filename=/path/to/non-aligned-file
7711c0
7711c0
That is arguably a bug in the blkdebug driver (it should never pass
7711c0
back block status smaller than its alignment, even if it has to make
7711c0
multiple bdrv_get_status calls and determine the
7711c0
least-common-denominator status among the group to return). It may
7711c0
also be possible to observe issues with a backing layer with smaller
7711c0
alignment than the active layer, although so far I have been unable to
7711c0
write a reliable iotest for that scenario (but again, an issue like
7711c0
that could be argued to be a bug in the block layer, or something
7711c0
where we need a flag to bdrv_block_status() to state whether the
7711c0
result must be aligned to the current layer's limits or can be
7711c0
subdivided for accuracy when chasing backing files).
7711c0
7711c0
Anyways, as blkdebug is not normally used, and as this patch makes our
7711c0
server more interoperable with qemu 3.1 clients, it is worth applying
7711c0
now, even while we still work on a larger patch series for the 4.1
7711c0
timeframe to have byte-accurate file lengths.
7711c0
7711c0
Note that the iotests output changes - for 223 and 233, we can see the
7711c0
server's better granularity advertisement; and for 241, the three test
7711c0
cases have the following effects:
7711c0
- natural alignment: the server's smaller alignment is now advertised,
7711c0
and the hole reported at EOF is now the right result; we've gotten rid
7711c0
of the server's non-compliance
7711c0
- forced server alignment: the server still advertises 512 bytes, but
7711c0
still sends a mid-sector hole. This is still a server compliance bug,
7711c0
which needs to be fixed in the block layer in a later patch; output
7711c0
does not change because the client is already being tolerant of the
7711c0
non-compliance
7711c0
- forced client alignment: the server's smaller alignment means that
7711c0
the client now sees the server's status change mid-sector without any
7711c0
protocol violations, but the fact that the map shows an unaligned
7711c0
mid-sector hole is evidence of the block layer problems with aligned
7711c0
block status, to be fixed in a later patch
7711c0
7711c0
Signed-off-by: Eric Blake <eblake@redhat.com>
7711c0
Message-Id: <20190329042750.14704-7-eblake@redhat.com>
7711c0
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
[eblake: rebase to enhanced iotest 241 coverage]
7711c0
(cherry picked from commit b0245d6478ea5906e3d7a542244d5c015fd47bc7)
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 nbd/server.c               | 13 ++++++++-----
7711c0
 tests/qemu-iotests/223.out |  4 ++--
7711c0
 tests/qemu-iotests/233.out |  2 +-
7711c0
 tests/qemu-iotests/241.out | 10 ++++++----
7711c0
 4 files changed, 17 insertions(+), 12 deletions(-)
7711c0
7711c0
diff --git a/nbd/server.c b/nbd/server.c
7711c0
index 9b87c7f..706f95a 100644
7711c0
--- a/nbd/server.c
7711c0
+++ b/nbd/server.c
7711c0
@@ -607,13 +607,16 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
7711c0
     /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size
7711c0
      * according to whether the client requested it, and according to
7711c0
      * whether this is OPT_INFO or OPT_GO. */
7711c0
-    /* minimum - 1 for back-compat, or 512 if client is new enough.
7711c0
-     * TODO: consult blk_bs(blk)->bl.request_alignment? */
7711c0
-    sizes[0] =
7711c0
-            (client->opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1;
7711c0
+    /* minimum - 1 for back-compat, or actual if client will obey it. */
7711c0
+    if (client->opt == NBD_OPT_INFO || blocksize) {
7711c0
+        sizes[0] = blk_get_request_alignment(exp->blk);
7711c0
+    } else {
7711c0
+        sizes[0] = 1;
7711c0
+    }
7711c0
+    assert(sizes[0] <= NBD_MAX_BUFFER_SIZE);
7711c0
     /* preferred - Hard-code to 4096 for now.
7711c0
      * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */
7711c0
-    sizes[1] = 4096;
7711c0
+    sizes[1] = MAX(4096, sizes[0]);
7711c0
     /* maximum - At most 32M, but smaller as appropriate. */
7711c0
     sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE);
7711c0
     trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]);
7711c0
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
7711c0
index a620f82..805cfbf 100644
7711c0
--- a/tests/qemu-iotests/223.out
7711c0
+++ b/tests/qemu-iotests/223.out
7711c0
@@ -41,7 +41,7 @@ exports available: 2
7711c0
  export: 'n'
7711c0
   size:  4194304
7711c0
   flags: 0x4ef ( readonly flush fua trim zeroes df cache )
7711c0
-  min block: 512
7711c0
+  min block: 1
7711c0
   opt block: 4096
7711c0
   max block: 33554432
7711c0
   available meta contexts: 2
7711c0
@@ -50,7 +50,7 @@ exports available: 2
7711c0
  export: 'n2'
7711c0
   size:  4194304
7711c0
   flags: 0x4ed ( flush fua trim zeroes df cache )
7711c0
-  min block: 512
7711c0
+  min block: 1
7711c0
   opt block: 4096
7711c0
   max block: 33554432
7711c0
   available meta contexts: 2
7711c0
diff --git a/tests/qemu-iotests/233.out b/tests/qemu-iotests/233.out
7711c0
index 6d45f3b..cd83b86 100644
7711c0
--- a/tests/qemu-iotests/233.out
7711c0
+++ b/tests/qemu-iotests/233.out
7711c0
@@ -33,7 +33,7 @@ exports available: 1
7711c0
  export: ''
7711c0
   size:  67108864
7711c0
   flags: 0x4ed ( flush fua trim zeroes df cache )
7711c0
-  min block: 512
7711c0
+  min block: 1
7711c0
   opt block: 4096
7711c0
   max block: 33554432
7711c0
   available meta contexts: 1
7711c0
diff --git a/tests/qemu-iotests/241.out b/tests/qemu-iotests/241.out
7711c0
index f22eabb..f481074 100644
7711c0
--- a/tests/qemu-iotests/241.out
7711c0
+++ b/tests/qemu-iotests/241.out
7711c0
@@ -3,8 +3,9 @@ QA output created by 241
7711c0
 === Exporting unaligned raw image, natural alignment ===
7711c0
 
7711c0
   size:  1024
7711c0
-  min block: 512
7711c0
-[{ "start": 0, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
7711c0
+  min block: 1
7711c0
+[{ "start": 0, "length": 1000, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
7711c0
+{ "start": 1000, "length": 24, "depth": 0, "zero": true, "data": true, "offset": OFFSET}]
7711c0
 1 KiB (0x400) bytes     allocated at offset 0 bytes (0x0)
7711c0
 
7711c0
 === Exporting unaligned raw image, forced server sector alignment ===
7711c0
@@ -20,7 +21,8 @@ WARNING: Image format was not specified for '/home/eblake/qemu/tests/qemu-iotest
7711c0
 === Exporting unaligned raw image, forced client sector alignment ===
7711c0
 
7711c0
   size:  1024
7711c0
-  min block: 512
7711c0
-[{ "start": 0, "length": 1024, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
7711c0
+  min block: 1
7711c0
+[{ "start": 0, "length": 1000, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
7711c0
+{ "start": 1000, "length": 24, "depth": 0, "zero": true, "data": true, "offset": OFFSET}]
7711c0
 1 KiB (0x400) bytes     allocated at offset 0 bytes (0x0)
7711c0
 *** done
7711c0
-- 
7711c0
1.8.3.1
7711c0