X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=nbd.c;h=2606403a41facd02d5b50d14dcd407b3aa62bd1c;hb=4e906d567a97ee45b4922001bf521dad0bde5268;hp=cec5a9449b350106618430f869951f6b7710d67d;hpb=8a527317059bb6ece8a01a8d5be92b5452fa5ad0;p=qemu.git diff --git a/nbd.c b/nbd.c index cec5a9449..2606403a4 100644 --- a/nbd.c +++ b/nbd.c @@ -16,10 +16,10 @@ * along with this program; if not, see . */ -#include "nbd.h" -#include "block.h" +#include "block/nbd.h" +#include "block/block.h" -#include "qemu-coroutine.h" +#include "block/coroutine.h" #include #include @@ -36,8 +36,8 @@ #include #endif -#include "qemu_socket.h" -#include "qemu-queue.h" +#include "qemu/sockets.h" +#include "qemu/queue.h" //#define DEBUG_NBD @@ -98,7 +98,6 @@ struct NBDExport { off_t size; uint32_t nbdflags; QTAILQ_HEAD(, NBDClient) clients; - QSIMPLEQ_HEAD(, NBDRequest) requests; QTAILQ_ENTRY(NBDExport) next; }; @@ -199,22 +198,15 @@ static void combine_addr(char *buf, size_t len, const char* address, } } -int tcp_socket_outgoing(const char *address, uint16_t port) -{ - char address_and_port[128]; - combine_addr(address_and_port, 128, address, port); - return tcp_socket_outgoing_spec(address_and_port); -} - -int tcp_socket_outgoing_spec(const char *address_and_port) +int tcp_socket_outgoing_opts(QemuOpts *opts) { Error *local_err = NULL; - int fd = inet_connect(address_and_port, &local_err); - + int fd = inet_connect_opts(opts, &local_err, NULL, NULL); if (local_err != NULL) { qerror_report_err(local_err); error_free(local_err); } + return fd; } @@ -393,10 +385,11 @@ static int nbd_send_negotiate(NBDClient *client) [28 .. 151] reserved (0) */ - socket_set_block(csock); + qemu_set_block(csock); rc = -EINVAL; TRACE("Beginning negotiation."); + memset(buf, 0, sizeof(buf)); memcpy(buf, "NBDMAGIC", 8); if (client->exp) { assert ((client->exp->nbdflags & ~65535) == 0); @@ -406,7 +399,6 @@ static int nbd_send_negotiate(NBDClient *client) } else { cpu_to_be64w((uint64_t*)(buf + 8), NBD_OPTS_MAGIC); } - memset(buf + 28, 0, 124); if (client->exp) { if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { @@ -436,7 +428,7 @@ static int nbd_send_negotiate(NBDClient *client) TRACE("Negotiation succeeded."); rc = 0; fail: - socket_set_nonblock(csock); + qemu_set_nonblock(csock); return rc; } @@ -450,7 +442,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, TRACE("Receiving negotiation."); - socket_set_block(csock); + qemu_set_block(csock); rc = -EINVAL; if (read_sync(csock, buf, 8) != 8) { @@ -565,7 +557,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, rc = 0; fail: - socket_set_nonblock(csock); + qemu_set_nonblock(csock); return rc; } @@ -596,24 +588,23 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) return -serrno; } - if (flags & NBD_FLAG_READ_ONLY) { - int read_only = 1; - TRACE("Setting readonly attribute"); + if (ioctl(fd, NBD_SET_FLAGS, flags) < 0) { + if (errno == ENOTTY) { + int read_only = (flags & NBD_FLAG_READ_ONLY) != 0; + TRACE("Setting readonly attribute"); - if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) { + if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) { + int serrno = errno; + LOG("Failed setting read-only attribute"); + return -serrno; + } + } else { int serrno = errno; - LOG("Failed setting read-only attribute"); + LOG("Failed setting flags"); return -serrno; } } - if (ioctl(fd, NBD_SET_FLAGS, flags) < 0 - && errno != ENOTTY) { - int serrno = errno; - LOG("Failed setting flags"); - return -serrno; - } - TRACE("Negotiation ended"); return 0; @@ -853,18 +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++; - if (QSIMPLEQ_EMPTY(&exp->requests)) { - req = g_malloc0(sizeof(NBDRequest)); - req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE); - } else { - req = QSIMPLEQ_FIRST(&exp->requests); - QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); - } + req = g_slice_new0(NBDRequest); nbd_client_get(client); req->client = client; return req; @@ -873,7 +857,12 @@ static NBDRequest *nbd_request_get(NBDClient *client) static void nbd_request_put(NBDRequest *req) { NBDClient *client = req->client; - QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry); + + if (req->data) { + qemu_vfree(req->data); + } + g_slice_free(NBDRequest, req); + if (client->nb_requests-- == MAX_NBD_REQUESTS) { qemu_notify_event(); } @@ -885,7 +874,6 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, void (*close)(NBDExport *)) { NBDExport *exp = g_malloc0(sizeof(NBDExport)); - QSIMPLEQ_INIT(&exp->requests); exp->refcount = 1; QTAILQ_INIT(&exp->clients); exp->bs = bs; @@ -961,13 +949,6 @@ void nbd_export_put(NBDExport *exp) exp->close(exp); } - while (!QSIMPLEQ_EMPTY(&exp->requests)) { - NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests); - QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry); - qemu_vfree(first->data); - g_free(first); - } - g_free(exp); } } @@ -1026,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(); @@ -1037,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; } @@ -1053,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) {