diff --git a/include/block/nbd.h b/include/block/nbd.h index 0903d7a603..c90f5e4d9e 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -58,7 +58,8 @@ enum { #define NBD_DEFAULT_PORT 10809 -#define NBD_BUFFER_SIZE (1024*1024) +/* Maximum size of a single READ/WRITE data buffer */ +#define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024) ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); int tcp_socket_incoming(const char *address, uint16_t port); diff --git a/nbd.c b/nbd.c index 761f4ec826..2606403a41 100644 --- a/nbd.c +++ b/nbd.c @@ -844,13 +844,11 @@ void nbd_client_close(NBDClient *client) static NBDRequest *nbd_request_get(NBDClient *client) { NBDRequest *req; - NBDExport *exp = client->exp; assert(client->nb_requests <= MAX_NBD_REQUESTS - 1); client->nb_requests++; req = g_slice_new0(NBDRequest); - req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE); nbd_client_get(client); req->client = client; return req; @@ -860,7 +858,9 @@ static void nbd_request_put(NBDRequest *req) { NBDClient *client = req->client; - qemu_vfree(req->data); + if (req->data) { + qemu_vfree(req->data); + } g_slice_free(NBDRequest, req); if (client->nb_requests-- == MAX_NBD_REQUESTS) { @@ -1007,6 +1007,7 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque { NBDClient *client = req->client; int csock = client->sock; + uint32_t command; ssize_t rc; client->recv_coroutine = qemu_coroutine_self(); @@ -1018,9 +1019,9 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque goto out; } - if (request->len > NBD_BUFFER_SIZE) { + if (request->len > NBD_MAX_BUFFER_SIZE) { LOG("len (%u) is larger than max len (%u)", - request->len, NBD_BUFFER_SIZE); + request->len, NBD_MAX_BUFFER_SIZE); rc = -EINVAL; goto out; } @@ -1034,7 +1035,11 @@ static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *reque TRACE("Decoding type"); - if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) { + command = request->type & NBD_CMD_MASK_COMMAND; + if (command == NBD_CMD_READ || command == NBD_CMD_WRITE) { + req->data = qemu_blockalign(client->exp->bs, request->len); + } + if (command == NBD_CMD_WRITE) { TRACE("Reading %u byte(s)", request->len); if (qemu_co_recv(csock, req->data, request->len) != request->len) {