#include "qemu/sockets.h"
#include "qemu/queue.h"
+#include "qemu/main-loop.h"
//#define DEBUG_NBD
return ret;
}
-static void combine_addr(char *buf, size_t len, const char* address,
- uint16_t port)
-{
- /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
- if (strstr(address, ":")) {
- snprintf(buf, len, "[%s]:%u", address, port);
- } else {
- snprintf(buf, len, "%s:%u", address, port);
- }
-}
-
-int tcp_socket_outgoing_opts(QemuOpts *opts)
-{
- Error *local_err = NULL;
- 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;
-}
-
-int tcp_socket_incoming(const char *address, uint16_t port)
-{
- char address_and_port[128];
- combine_addr(address_and_port, 128, address, port);
- return tcp_socket_incoming_spec(address_and_port);
-}
-
-int tcp_socket_incoming_spec(const char *address_and_port)
-{
- Error *local_err = NULL;
- int fd = inet_listen(address_and_port, NULL, 0, SOCK_STREAM, 0, &local_err);
-
- if (local_err != NULL) {
- qerror_report_err(local_err);
- error_free(local_err);
- }
- return fd;
-}
-
-int unix_socket_incoming(const char *path)
-{
- Error *local_err = NULL;
- int fd = unix_listen(path, NULL, 0, &local_err);
-
- if (local_err != NULL) {
- qerror_report_err(local_err);
- error_free(local_err);
- }
- return fd;
-}
-
-int unix_socket_outgoing(const char *path)
-{
- Error *local_err = NULL;
- int fd = unix_connect(path, &local_err);
-
- if (local_err != NULL) {
- qerror_report_err(local_err);
- error_free(local_err);
- }
- return fd;
-}
-
/* Basic flow for negotiation
Server Client
[ 8 .. 15] magic (NBD_CLIENT_MAGIC)
[16 .. 23] size
[24 .. 25] server flags (0)
- [24 .. 27] export flags
+ [26 .. 27] export flags
[28 .. 151] reserved (0)
Negotiation header with options, part 1:
TRACE("Receiving negotiation.");
- qemu_set_block(csock);
rc = -EINVAL;
if (read_sync(csock, buf, 8) != 8) {
rc = 0;
fail:
- qemu_set_nonblock(csock);
return rc;
}
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;
{
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) {
exp->nbdflags = nbdflags;
exp->size = size == -1 ? bdrv_getlength(bs) : size;
exp->close = close;
+ bdrv_ref(bs);
return exp;
}
}
nbd_export_set_name(exp, NULL);
nbd_export_put(exp);
+ if (exp->bs) {
+ bdrv_unref(exp->bs);
+ exp->bs = NULL;
+ }
}
void nbd_export_get(NBDExport *exp)
{
NBDClient *client = req->client;
int csock = client->sock;
+ uint32_t command;
ssize_t rc;
client->recv_coroutine = qemu_coroutine_self();
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;
}
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) {