nbd patches for 2019-04-08

- Fix minor issues in recent alignment patches
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABCAAGBQJcq5i8AAoJEKeha0olJ0NqYnwH/ijn04VFDiJs2UJ/Xbc8xIof
 QcwwTB1GaHGxkptmWPndJgtApqJEKCpoY7lMWLEfoulthNLydv5IUwqjWNUrBYL+
 c76oItDlrCZYfR6DJMKtGceANOW4avBBdh1SCYHSw+DTwg5vq5zv1uGkrSsRYWe6
 5w3Qb3I9M/7F/Y/2bLzHe8SanVRYoLk+ouVo22wIj59LBYKrQ0oRa04k1kDhJ6Qv
 HWtkRUSEMfd6WuV3P8n93MDSNii7CNw9gr5tWCH5bxPv4evNhukd6eyE0EMTso0C
 Mmby+rjdlzSLi5KJbvke6c4HQ1geQyrdrt4KKj4AOKioZRc9FmjuuctXqwfZTx4=
 =HeBS
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-04-08' into staging

nbd patches for 2019-04-08

- Fix minor issues in recent alignment patches

# gpg: Signature made Mon 08 Apr 2019 19:53:48 BST
# gpg:                using RSA key A7A16B4A2527436A
# gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full]
# gpg:                 aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full]
# gpg:                 aka "[jpeg image of size 6874]" [full]
# Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2  F3AA A7A1 6B4A 2527 436A

* remotes/ericb/tags/pull-nbd-2019-04-08:
  nbd/client: Fix error message for server with unusable sizing
  nbd/server: Don't fail NBD_OPT_INFO for byte-aligned sources
  nbd/server: Trace client noncompliance on unaligned requests
  nbd/server: Fix blockstatus trace

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-04-08 20:10:21 +01:00
commit 7fe1427b57
3 changed files with 29 additions and 13 deletions

View File

@ -428,7 +428,7 @@ static int nbd_opt_info_or_go(QIOChannel *ioc, uint32_t opt,
} }
if (info->min_block && if (info->min_block &&
!QEMU_IS_ALIGNED(info->size, info->min_block)) { !QEMU_IS_ALIGNED(info->size, info->min_block)) {
error_setg(errp, "export size %" PRIu64 "is not multiple of " error_setg(errp, "export size %" PRIu64 " is not multiple of "
"minimum block size %" PRIu32, info->size, "minimum block size %" PRIu32, info->size,
info->min_block); info->min_block);
nbd_send_opt_abort(ioc); nbd_send_opt_abort(ioc);

View File

@ -124,6 +124,8 @@ struct NBDClient {
int nb_requests; int nb_requests;
bool closing; bool closing;
uint32_t check_align; /* If non-zero, check for aligned client requests */
bool structured_reply; bool structured_reply;
NBDExportMetaContexts export_meta; NBDExportMetaContexts export_meta;
@ -533,6 +535,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
bool blocksize = false; bool blocksize = false;
uint32_t sizes[3]; uint32_t sizes[3];
char buf[sizeof(uint64_t) + sizeof(uint16_t)]; char buf[sizeof(uint64_t) + sizeof(uint16_t)];
uint32_t check_align = 0;
/* Client sends: /* Client sends:
4 bytes: L, name length (can be 0) 4 bytes: L, name length (can be 0)
@ -609,7 +612,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
* whether this is OPT_INFO or OPT_GO. */ * whether this is OPT_INFO or OPT_GO. */
/* minimum - 1 for back-compat, or actual if client will obey it. */ /* minimum - 1 for back-compat, or actual if client will obey it. */
if (client->opt == NBD_OPT_INFO || blocksize) { if (client->opt == NBD_OPT_INFO || blocksize) {
sizes[0] = blk_get_request_alignment(exp->blk); check_align = sizes[0] = blk_get_request_alignment(exp->blk);
} else { } else {
sizes[0] = 1; sizes[0] = 1;
} }
@ -640,11 +643,14 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
return rc; return rc;
} }
/* If the client is just asking for NBD_OPT_INFO, but forgot to /*
* request block sizes, return an error. * If the client is just asking for NBD_OPT_INFO, but forgot to
* TODO: consult blk_bs(blk)->request_align, and only error if it * request block sizes in a situation that would impact
* is not 1? */ * performance, then return an error. But for NBD_OPT_GO, we
if (client->opt == NBD_OPT_INFO && !blocksize) { * tolerate all clients, regardless of alignments.
*/
if (client->opt == NBD_OPT_INFO && !blocksize &&
blk_get_request_alignment(exp->blk) > 1) {
return nbd_negotiate_send_rep_err(client, return nbd_negotiate_send_rep_err(client,
NBD_REP_ERR_BLOCK_SIZE_REQD, NBD_REP_ERR_BLOCK_SIZE_REQD,
errp, errp,
@ -660,6 +666,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
if (client->opt == NBD_OPT_GO) { if (client->opt == NBD_OPT_GO) {
client->exp = exp; client->exp = exp;
client->check_align = check_align;
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
nbd_export_get(client->exp); nbd_export_get(client->exp);
nbd_check_meta_export(client); nbd_check_meta_export(client);
@ -1880,17 +1887,12 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) | flags = (ret & BDRV_BLOCK_ALLOCATED ? 0 : NBD_STATE_HOLE) |
(ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0); (ret & BDRV_BLOCK_ZERO ? NBD_STATE_ZERO : 0);
offset += num;
remaining_bytes -= num;
if (first_extent) { if (first_extent) {
extent->flags = flags; extent->flags = flags;
extent->length = num; extent->length = num;
first_extent = false; first_extent = false;
continue; } else if (flags == extent->flags) {
}
if (flags == extent->flags) {
/* extend current extent */ /* extend current extent */
extent->length += num; extent->length += num;
} else { } else {
@ -1903,6 +1905,8 @@ static int blockstatus_to_extents(BlockDriverState *bs, uint64_t offset,
extent->flags = flags; extent->flags = flags;
extent->length = num; extent->length = num;
} }
offset += num;
remaining_bytes -= num;
} }
extents_end = extent + 1; extents_end = extent + 1;
@ -2129,6 +2133,17 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
return (request->type == NBD_CMD_WRITE || return (request->type == NBD_CMD_WRITE ||
request->type == NBD_CMD_WRITE_ZEROES) ? -ENOSPC : -EINVAL; request->type == NBD_CMD_WRITE_ZEROES) ? -ENOSPC : -EINVAL;
} }
if (client->check_align && !QEMU_IS_ALIGNED(request->from | request->len,
client->check_align)) {
/*
* The block layer gracefully handles unaligned requests, but
* it's still worth tracing client non-compliance
*/
trace_nbd_co_receive_align_compliance(nbd_cmd_lookup(request->type),
request->from,
request->len,
client->check_align);
}
valid_flags = NBD_CMD_FLAG_FUA; valid_flags = NBD_CMD_FLAG_FUA;
if (request->type == NBD_CMD_READ && client->structured_reply) { if (request->type == NBD_CMD_READ && client->structured_reply) {
valid_flags |= NBD_CMD_FLAG_DF; valid_flags |= NBD_CMD_FLAG_DF;

View File

@ -71,4 +71,5 @@ nbd_co_send_extents(uint64_t handle, unsigned int extents, uint32_t id, uint64_t
nbd_co_send_structured_error(uint64_t handle, int err, const char *errname, const char *msg) "Send structured error reply: handle = %" PRIu64 ", error = %d (%s), msg = '%s'" nbd_co_send_structured_error(uint64_t handle, int err, const char *errname, const char *msg) "Send structured error reply: handle = %" PRIu64 ", error = %d (%s), msg = '%s'"
nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)" nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)"
nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32 nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32
nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", align=0x%" PRIx32
nbd_trip(void) "Reading request" nbd_trip(void) "Reading request"