diff options
Diffstat (limited to 'nbd')
-rw-r--r-- | nbd/client.c | 16 | ||||
-rw-r--r-- | nbd/server.c | 43 |
2 files changed, 46 insertions, 13 deletions
diff --git a/nbd/client.c b/nbd/client.c index d554ae353d..49bf9906f9 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -868,7 +868,8 @@ static int nbd_list_meta_contexts(QIOChannel *ioc, * 2: server is newstyle, but lacks structured replies * 3: server is newstyle and set up for structured replies */ -static int nbd_start_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, +static int nbd_start_negotiate(AioContext *aio_context, QIOChannel *ioc, + QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, bool structured_reply, bool *zeroes, Error **errp) @@ -935,6 +936,10 @@ static int nbd_start_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, return -EINVAL; } ioc = *outioc; + if (aio_context) { + qio_channel_set_blocking(ioc, false, NULL); + qio_channel_attach_aio_context(ioc, aio_context); + } } else { error_setg(errp, "Server does not support STARTTLS"); return -EINVAL; @@ -999,7 +1004,8 @@ static int nbd_negotiate_finish_oldstyle(QIOChannel *ioc, NBDExportInfo *info, * Returns: negative errno: failure talking to server * 0: server is connected */ -int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, +int nbd_receive_negotiate(AioContext *aio_context, QIOChannel *ioc, + QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, NBDExportInfo *info, Error **errp) { @@ -1010,7 +1016,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, assert(info->name); trace_nbd_receive_negotiate_name(info->name); - result = nbd_start_negotiate(ioc, tlscreds, hostname, outioc, + result = nbd_start_negotiate(aio_context, ioc, tlscreds, hostname, outioc, info->structured_reply, &zeroes, errp); info->structured_reply = false; @@ -1130,8 +1136,8 @@ int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, QIOChannel *sioc = NULL; *info = NULL; - result = nbd_start_negotiate(ioc, tlscreds, hostname, &sioc, true, NULL, - errp); + result = nbd_start_negotiate(NULL, ioc, tlscreds, hostname, &sioc, true, + NULL, errp); if (tlscreds && sioc) { ioc = sioc; } diff --git a/nbd/server.c b/nbd/server.c index dbd2ff8555..3eacb89875 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -2105,12 +2105,15 @@ static int nbd_co_receive_request(NBDRequestData *req, NBDRequest *request, return -EINVAL; } - req->data = blk_try_blockalign(client->exp->blk, request->len); - if (req->data == NULL) { - error_setg(errp, "No memory"); - return -ENOMEM; + if (request->type != NBD_CMD_CACHE) { + req->data = blk_try_blockalign(client->exp->blk, request->len); + if (req->data == NULL) { + error_setg(errp, "No memory"); + return -ENOMEM; + } } } + if (request->type == NBD_CMD_WRITE) { if (nbd_read(client->ioc, req->data, request->len, "CMD_WRITE data", errp) < 0) @@ -2195,7 +2198,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, int ret; NBDExport *exp = client->exp; - assert(request->type == NBD_CMD_READ || request->type == NBD_CMD_CACHE); + assert(request->type == NBD_CMD_READ); /* XXX: NBD Protocol only documents use of FUA with WRITE */ if (request->flags & NBD_CMD_FLAG_FUA) { @@ -2207,7 +2210,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, } if (client->structured_reply && !(request->flags & NBD_CMD_FLAG_DF) && - request->len && request->type != NBD_CMD_CACHE) + request->len) { return nbd_co_send_sparse_read(client, request->handle, request->from, data, request->len, errp); @@ -2215,7 +2218,7 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, ret = blk_pread(exp->blk, request->from + exp->dev_offset, data, request->len); - if (ret < 0 || request->type == NBD_CMD_CACHE) { + if (ret < 0) { return nbd_send_generic_reply(client, request->handle, ret, "reading from file failed", errp); } @@ -2234,6 +2237,28 @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request, } } +/* + * nbd_do_cmd_cache + * + * Handle NBD_CMD_CACHE request. + * Return -errno if sending fails. Other errors are reported directly to the + * client as an error reply. + */ +static coroutine_fn int nbd_do_cmd_cache(NBDClient *client, NBDRequest *request, + Error **errp) +{ + int ret; + NBDExport *exp = client->exp; + + assert(request->type == NBD_CMD_CACHE); + + ret = blk_co_preadv(exp->blk, request->from + exp->dev_offset, request->len, + NULL, BDRV_REQ_COPY_ON_READ | BDRV_REQ_PREFETCH); + + return nbd_send_generic_reply(client, request->handle, ret, + "caching data failed", errp); +} + /* Handle NBD request. * Return -errno if sending fails. Other errors are reported directly to the * client as an error reply. */ @@ -2247,8 +2272,10 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, char *msg; switch (request->type) { - case NBD_CMD_READ: case NBD_CMD_CACHE: + return nbd_do_cmd_cache(client, request, errp); + + case NBD_CMD_READ: return nbd_do_cmd_read(client, request, data, errp); case NBD_CMD_WRITE: |