Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-01-08'…
Browse files Browse the repository at this point in the history
… into staging

nbd patches for 2018-01-08

- Eric Blake: 0/2 Optimize sparse reads over NBD
- Murilo Opsfelder Araujo: block/nbd: fix segmentation fault when .desc is not null-terminated

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

* remotes/ericb/tags/pull-nbd-2018-01-08:
  block/nbd: fix segmentation fault when .desc is not null-terminated
  nbd/server: Optimize final chunk of sparse read
  nbd/server: Implement sparse reads atop structured reply

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Jan 9, 2018
2 parents ee98a6b + c436573 commit 3cee4db
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
1 change: 1 addition & 0 deletions block/nbd.c
Expand Up @@ -388,6 +388,7 @@ static QemuOptsList nbd_runtime_opts = {
.type = QEMU_OPT_STRING,
.help = "ID of the TLS credentials to use",
},
{ /* end of list */ }
},
};

Expand Down
79 changes: 76 additions & 3 deletions nbd/server.c
Expand Up @@ -1303,6 +1303,7 @@ static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
uint64_t offset,
void *data,
size_t size,
bool final,
Error **errp)
{
NBDStructuredReadData chunk;
Expand All @@ -1313,13 +1314,73 @@ static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,

assert(size);
trace_nbd_co_send_structured_read(handle, offset, data, size);
set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_OFFSET_DATA,
handle, sizeof(chunk) - sizeof(chunk.h) + size);
set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
NBD_REPLY_TYPE_OFFSET_DATA, handle,
sizeof(chunk) - sizeof(chunk.h) + size);
stq_be_p(&chunk.offset, offset);

return nbd_co_send_iov(client, iov, 2, errp);
}

static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
uint64_t handle,
uint64_t offset,
uint8_t *data,
size_t size,
Error **errp)
{
int ret = 0;
NBDExport *exp = client->exp;
size_t progress = 0;

while (progress < size) {
int64_t pnum;
int status = bdrv_block_status_above(blk_bs(exp->blk), NULL,
offset + progress,
size - progress, &pnum, NULL,
NULL);
bool final;

if (status < 0) {
error_setg_errno(errp, -status, "unable to check for holes");
return status;
}
assert(pnum && pnum <= size - progress);
final = progress + pnum == size;
if (status & BDRV_BLOCK_ZERO) {
NBDStructuredReadHole chunk;
struct iovec iov[] = {
{.iov_base = &chunk, .iov_len = sizeof(chunk)},
};

trace_nbd_co_send_structured_read_hole(handle, offset + progress,
pnum);
set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
NBD_REPLY_TYPE_OFFSET_HOLE,
handle, sizeof(chunk) - sizeof(chunk.h));
stq_be_p(&chunk.offset, offset + progress);
stl_be_p(&chunk.length, pnum);
ret = nbd_co_send_iov(client, iov, 1, errp);
} else {
ret = blk_pread(exp->blk, offset + progress + exp->dev_offset,
data + progress, pnum);
if (ret < 0) {
error_setg_errno(errp, -ret, "reading from file failed");
break;
}
ret = nbd_co_send_structured_read(client, handle, offset + progress,
data + progress, pnum, final,
errp);
}

if (ret < 0) {
break;
}
progress += pnum;
}
return ret;
}

static int coroutine_fn nbd_co_send_structured_error(NBDClient *client,
uint64_t handle,
uint32_t error,
Expand Down Expand Up @@ -1481,6 +1542,17 @@ static coroutine_fn void nbd_trip(void *opaque)
}
}

if (client->structured_reply && !(request.flags & NBD_CMD_FLAG_DF) &&
request.len) {
ret = nbd_co_send_sparse_read(req->client, request.handle,
request.from, req->data, request.len,
&local_err);
if (ret < 0) {
goto reply;
}
goto done;
}

ret = blk_pread(exp->blk, request.from + exp->dev_offset,
req->data, request.len);
if (ret < 0) {
Expand Down Expand Up @@ -1561,7 +1633,8 @@ static coroutine_fn void nbd_trip(void *opaque)
} else if (reply_data_len) {
ret = nbd_co_send_structured_read(req->client, request.handle,
request.from, req->data,
reply_data_len, &local_err);
reply_data_len, true,
&local_err);
} else {
ret = nbd_co_send_structured_done(req->client, request.handle,
&local_err);
Expand Down
1 change: 1 addition & 0 deletions nbd/trace-events
Expand Up @@ -57,6 +57,7 @@ nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients fr
nbd_co_send_simple_reply(uint64_t handle, uint32_t error, const char *errname, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 " (%s), len = %d"
nbd_co_send_structured_done(uint64_t handle) "Send structured reply done: handle = %" PRIu64
nbd_co_send_structured_read(uint64_t handle, uint64_t offset, void *data, size_t size) "Send structured read data reply: handle = %" PRIu64 ", offset = %" PRIu64 ", data = %p, len = %zu"
nbd_co_send_structured_read_hole(uint64_t handle, uint64_t offset, size_t size) "Send structured read hole reply: handle = %" PRIu64 ", offset = %" PRIu64 ", len = %zu"
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_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32
Expand Down

0 comments on commit 3cee4db

Please sign in to comment.