aboutsummaryrefslogtreecommitdiff
path: root/nbd/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'nbd/server.c')
-rw-r--r--nbd/server.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/nbd/server.c b/nbd/server.c
index 1b8c861989..1c4c5474ad 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -124,6 +124,8 @@ struct NBDClient {
int nb_requests;
bool closing;
+ uint32_t check_align; /* If non-zero, check for aligned client requests */
+
bool structured_reply;
NBDExportMetaContexts export_meta;
@@ -533,6 +535,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
bool blocksize = false;
uint32_t sizes[3];
char buf[sizeof(uint64_t) + sizeof(uint16_t)];
+ uint32_t check_align = 0;
/* Client sends:
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. */
/* minimum - 1 for back-compat, or actual if client will obey it. */
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 {
sizes[0] = 1;
}
@@ -660,6 +663,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags,
if (client->opt == NBD_OPT_GO) {
client->exp = exp;
+ client->check_align = check_align;
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
nbd_export_get(client->exp);
nbd_check_meta_export(client);
@@ -2126,6 +2130,17 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request,
return (request->type == NBD_CMD_WRITE ||
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;
if (request->type == NBD_CMD_READ && client->structured_reply) {
valid_flags |= NBD_CMD_FLAG_DF;