diff --git a/block/nbd.c b/block/nbd.c index 161b299855..e0af5b4725 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -150,11 +150,19 @@ static int nbd_have_request(void *opaque) static void nbd_reply_ready(void *opaque) { BDRVNBDState *s = opaque; - int i; + uint64_t i; + int ret; if (s->reply.handle == 0) { - /* No reply already in flight. Fetch a header. */ - if (nbd_receive_reply(s->sock, &s->reply) < 0) { + /* No reply already in flight. Fetch a header. It is possible + * that another thread has done the same thing in parallel, so + * the socket is not readable anymore. + */ + ret = nbd_receive_reply(s->sock, &s->reply); + if (ret == -EAGAIN) { + return; + } + if (ret < 0) { s->reply.handle = 0; goto fail; } @@ -164,6 +172,10 @@ static void nbd_reply_ready(void *opaque) * handler acts as a synchronization point and ensures that only * one coroutine is called until the reply finishes. */ i = HANDLE_TO_INDEX(s, s->reply.handle); + if (i >= MAX_NBD_REQUESTS) { + goto fail; + } + if (s->recv_coroutine[i]) { qemu_coroutine_enter(s->recv_coroutine[i], NULL); return; @@ -193,11 +205,10 @@ static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request, qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, nbd_have_request, NULL, s); rc = nbd_send_request(s->sock, request); - if (rc != -1 && iov) { + if (rc >= 0 && iov) { ret = qemu_co_sendv(s->sock, iov, request->len, offset); if (ret != request->len) { - errno = -EIO; - rc = -1; + return -EIO; } } qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, @@ -256,7 +267,7 @@ static int nbd_establish_connection(BlockDriverState *bs) } /* Failed to establish connection */ - if (sock == -1) { + if (sock < 0) { logout("Failed to establish connection to NBD server\n"); return -errno; } @@ -264,10 +275,10 @@ static int nbd_establish_connection(BlockDriverState *bs) /* NBD handshake */ ret = nbd_receive_negotiate(sock, s->export_name, &s->nbdflags, &size, &blocksize); - if (ret == -1) { + if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); closesocket(sock); - return -errno; + return ret; } /* Now that we're connected, set the socket to be non-blocking and @@ -327,14 +338,16 @@ static int nbd_co_readv_1(BlockDriverState *bs, int64_t sector_num, BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + ssize_t ret; request.type = NBD_CMD_READ; request.from = sector_num * 512; request.len = nb_sectors * 512; nbd_coroutine_start(s, &request); - if (nbd_co_send_request(s, &request, NULL, 0) == -1) { - reply.error = errno; + ret = nbd_co_send_request(s, &request, NULL, 0); + if (ret < 0) { + reply.error = -ret; } else { nbd_co_receive_reply(s, &request, &reply, qiov->iov, offset); } @@ -350,6 +363,7 @@ static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num, BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + ssize_t ret; request.type = NBD_CMD_WRITE; if (!bdrv_enable_write_cache(bs) && (s->nbdflags & NBD_FLAG_SEND_FUA)) { @@ -360,8 +374,9 @@ static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num, request.len = nb_sectors * 512; nbd_coroutine_start(s, &request); - if (nbd_co_send_request(s, &request, qiov->iov, offset) == -1) { - reply.error = errno; + ret = nbd_co_send_request(s, &request, qiov->iov, offset); + if (ret < 0) { + reply.error = -ret; } else { nbd_co_receive_reply(s, &request, &reply, NULL, 0); } @@ -412,6 +427,7 @@ static int nbd_co_flush(BlockDriverState *bs) BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + ssize_t ret; if (!(s->nbdflags & NBD_FLAG_SEND_FLUSH)) { return 0; @@ -426,8 +442,9 @@ static int nbd_co_flush(BlockDriverState *bs) request.len = 0; nbd_coroutine_start(s, &request); - if (nbd_co_send_request(s, &request, NULL, 0) == -1) { - reply.error = errno; + ret = nbd_co_send_request(s, &request, NULL, 0); + if (ret < 0) { + reply.error = -ret; } else { nbd_co_receive_reply(s, &request, &reply, NULL, 0); } @@ -441,6 +458,7 @@ static int nbd_co_discard(BlockDriverState *bs, int64_t sector_num, BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + ssize_t ret; if (!(s->nbdflags & NBD_FLAG_SEND_TRIM)) { return 0; @@ -450,8 +468,9 @@ static int nbd_co_discard(BlockDriverState *bs, int64_t sector_num, request.len = nb_sectors * 512; nbd_coroutine_start(s, &request); - if (nbd_co_send_request(s, &request, NULL, 0) == -1) { - reply.error = errno; + ret = nbd_co_send_request(s, &request, NULL, 0); + if (ret < 0) { + reply.error = -ret; } else { nbd_co_receive_reply(s, &request, &reply, NULL, 0); } diff --git a/nbd.c b/nbd.c index 406e555bc6..153709f628 100644 --- a/nbd.c +++ b/nbd.c @@ -18,7 +18,6 @@ #include "nbd.h" #include "block.h" -#include "block_int.h" #include "qemu-coroutine.h" @@ -78,12 +77,10 @@ /* That's all folks */ -#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true) -#define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false) - -size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) +ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) { size_t offset = 0; + int err; if (qemu_in_coroutine()) { if (do_read) { @@ -102,12 +99,16 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) len = send(fd, buffer + offset, size - offset, 0); } - if (len == -1) - errno = socket_error(); + if (len < 0) { + err = socket_error(); - /* recoverable error */ - if (len == -1 && (errno == EAGAIN || errno == EINTR)) { - continue; + /* recoverable error */ + if (err == EINTR || (offset > 0 && err == EAGAIN)) { + continue; + } + + /* unrecoverable error */ + return -err; } /* eof */ @@ -115,17 +116,32 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) break; } - /* unrecoverable error */ - if (len == -1) { - return 0; - } - offset += len; } return offset; } +static ssize_t read_sync(int fd, void *buffer, size_t size) +{ + /* Sockets are kept in blocking mode in the negotiation phase. After + * that, a non-readable socket simply means that another thread stole + * our request/reply. Synchronization is done with recv_coroutine, so + * that this is coroutine-safe. + */ + return nbd_wr_sync(fd, buffer, size, true); +} + +static ssize_t write_sync(int fd, void *buffer, size_t size) +{ + int ret; + do { + /* For writes, we do expect the socket to be writable. */ + ret = nbd_wr_sync(fd, buffer, size, false); + } while (ret == -EAGAIN); + return ret; +} + static void combine_addr(char *buf, size_t len, const char* address, uint16_t port) { @@ -193,6 +209,7 @@ int unix_socket_outgoing(const char *path) static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) { char buf[8 + 8 + 8 + 128]; + int rc; /* Negotiate [ 0 .. 7] passwd ("NBDMAGIC") @@ -202,6 +219,9 @@ static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) [28 .. 151] reserved (0) */ + socket_set_block(csock); + rc = -EINVAL; + TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); @@ -213,13 +233,14 @@ static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("write failed"); - errno = EINVAL; - return -1; + goto fail; } TRACE("Negotiation succeeded."); - - return 0; + rc = 0; +fail: + socket_set_nonblock(csock); + return rc; } int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, @@ -228,20 +249,22 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, char buf[256]; uint64_t magic, s; uint16_t tmp; + int rc; TRACE("Receiving negotiation."); + socket_set_block(csock); + rc = -EINVAL; + if (read_sync(csock, buf, 8) != 8) { LOG("read failed"); - errno = EINVAL; - return -1; + goto fail; } buf[8] = '\0'; if (strlen(buf) == 0) { LOG("server connection closed"); - errno = EINVAL; - return -1; + goto fail; } TRACE("Magic is %c%c%c%c%c%c%c%c", @@ -256,14 +279,12 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, if (memcmp(buf, "NBDMAGIC", 8) != 0) { LOG("Invalid magic received"); - errno = EINVAL; - return -1; + goto fail; } if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("read failed"); - errno = EINVAL; - return -1; + goto fail; } magic = be64_to_cpu(magic); TRACE("Magic is 0x%" PRIx64, magic); @@ -276,61 +297,52 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, TRACE("Checking magic (opts_magic)"); if (magic != 0x49484156454F5054LL) { LOG("Bad magic received"); - errno = EINVAL; - return -1; + goto fail; } if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("flags read failed"); - errno = EINVAL; - return -1; + goto fail; } *flags = be16_to_cpu(tmp) << 16; /* reserved for future use */ if (write_sync(csock, &reserved, sizeof(reserved)) != sizeof(reserved)) { LOG("write failed (reserved)"); - errno = EINVAL; - return -1; + goto fail; } /* write the export name */ magic = cpu_to_be64(magic); if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("write failed (magic)"); - errno = EINVAL; - return -1; + goto fail; } opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { LOG("write failed (opt)"); - errno = EINVAL; - return -1; + goto fail; } namesize = cpu_to_be32(strlen(name)); if (write_sync(csock, &namesize, sizeof(namesize)) != sizeof(namesize)) { LOG("write failed (namesize)"); - errno = EINVAL; - return -1; + goto fail; } if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { LOG("write failed (name)"); - errno = EINVAL; - return -1; + goto fail; } } else { TRACE("Checking magic (cli_magic)"); if (magic != 0x00420281861253LL) { LOG("Bad magic received"); - errno = EINVAL; - return -1; + goto fail; } } if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { LOG("read failed"); - errno = EINVAL; - return -1; + goto fail; } *size = be64_to_cpu(s); *blocksize = 1024; @@ -339,24 +351,25 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, if (!name) { if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) { LOG("read failed (flags)"); - errno = EINVAL; - return -1; + goto fail; } *flags = be32_to_cpup(flags); } else { if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("read failed (tmp)"); - errno = EINVAL; - return -1; + goto fail; } *flags |= be32_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { LOG("read failed (buf)"); - errno = EINVAL; - return -1; + goto fail; } - return 0; + rc = 0; + +fail: + socket_set_nonblock(csock); + return rc; } #ifdef __linux__ @@ -364,29 +377,26 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) { TRACE("Setting NBD socket"); - if (ioctl(fd, NBD_SET_SOCK, csock) == -1) { + if (ioctl(fd, NBD_SET_SOCK, csock) < 0) { int serrno = errno; LOG("Failed to set NBD socket"); - errno = serrno; - return -1; + return -serrno; } TRACE("Setting block size to %lu", (unsigned long)blocksize); - if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) { + if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) < 0) { int serrno = errno; LOG("Failed setting NBD block size"); - errno = serrno; - return -1; + return -serrno; } TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize)); - if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) { + if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) < 0) { int serrno = errno; LOG("Failed setting size (in blocks)"); - errno = serrno; - return -1; + return -serrno; } if (flags & NBD_FLAG_READ_ONLY) { @@ -396,8 +406,7 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) { int serrno = errno; LOG("Failed setting read-only attribute"); - errno = serrno; - return -1; + return -serrno; } } @@ -405,8 +414,7 @@ int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) && errno != ENOTTY) { int serrno = errno; LOG("Failed setting flags"); - errno = serrno; - return -1; + return -serrno; } TRACE("Negotiation ended"); @@ -430,7 +438,7 @@ int nbd_client(int fd) TRACE("Doing NBD loop"); ret = ioctl(fd, NBD_DO_IT); - if (ret == -1 && errno == EPIPE) { + if (ret < 0 && errno == EPIPE) { /* NBD_DO_IT normally returns EPIPE when someone has disconnected * the socket via NBD_DISCONNECT. We do not want to return 1 in * that case. @@ -453,26 +461,24 @@ int nbd_client(int fd) #else int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize) { - errno = ENOTSUP; - return -1; + return -ENOTSUP; } int nbd_disconnect(int fd) { - errno = ENOTSUP; - return -1; + return -ENOTSUP; } int nbd_client(int fd) { - errno = ENOTSUP; - return -1; + return -ENOTSUP; } #endif -int nbd_send_request(int csock, struct nbd_request *request) +ssize_t nbd_send_request(int csock, struct nbd_request *request) { uint8_t buf[4 + 4 + 8 + 8 + 4]; + ssize_t ret; cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); cpu_to_be32w((uint32_t*)(buf + 4), request->type); @@ -484,23 +490,32 @@ int nbd_send_request(int csock, struct nbd_request *request) "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}", request->from, request->len, request->handle, request->type); - if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + ret = write_sync(csock, buf, sizeof(buf)); + if (ret < 0) { + return ret; + } + + if (ret != sizeof(buf)) { LOG("writing to socket failed"); - errno = EINVAL; - return -1; + return -EINVAL; } return 0; } -static int nbd_receive_request(int csock, struct nbd_request *request) +static ssize_t nbd_receive_request(int csock, struct nbd_request *request) { uint8_t buf[4 + 4 + 8 + 8 + 4]; uint32_t magic; + ssize_t ret; - if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + ret = read_sync(csock, buf, sizeof(buf)); + if (ret < 0) { + return ret; + } + + if (ret != sizeof(buf)) { LOG("read failed"); - errno = EINVAL; - return -1; + return -EINVAL; } /* Request @@ -523,23 +538,25 @@ static int nbd_receive_request(int csock, struct nbd_request *request) if (magic != NBD_REQUEST_MAGIC) { LOG("invalid magic (got 0x%x)", magic); - errno = EINVAL; - return -1; + return -EINVAL; } return 0; } -int nbd_receive_reply(int csock, struct nbd_reply *reply) +ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply) { uint8_t buf[NBD_REPLY_SIZE]; uint32_t magic; + ssize_t ret; - memset(buf, 0xAA, sizeof(buf)); + ret = read_sync(csock, buf, sizeof(buf)); + if (ret < 0) { + return ret; + } - if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + if (ret != sizeof(buf)) { LOG("read failed"); - errno = EINVAL; - return -1; + return -EINVAL; } /* Reply @@ -558,15 +575,15 @@ int nbd_receive_reply(int csock, struct nbd_reply *reply) if (magic != NBD_REPLY_MAGIC) { LOG("invalid magic (got 0x%x)", magic); - errno = EINVAL; - return -1; + return -EINVAL; } return 0; } -static int nbd_send_reply(int csock, struct nbd_reply *reply) +static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) { uint8_t buf[4 + 4 + 8]; + ssize_t ret; /* Reply [ 0 .. 3] magic (NBD_REPLY_MAGIC) @@ -579,10 +596,14 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply) TRACE("Sending response to client"); - if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { + ret = write_sync(csock, buf, sizeof(buf)); + if (ret < 0) { + return ret; + } + + if (ret != sizeof(buf)) { LOG("writing to socket failed"); - errno = EINVAL; - return -1; + return -EINVAL; } return 0; } @@ -681,7 +702,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, exp->bs = bs; exp->dev_offset = dev_offset; exp->nbdflags = nbdflags; - exp->size = size == -1 ? exp->bs->total_sectors * 512 : size; + exp->size = size == -1 ? bdrv_getlength(bs) : size; return exp; } @@ -702,12 +723,12 @@ static int nbd_can_read(void *opaque); static void nbd_read(void *opaque); static void nbd_restart_write(void *opaque); -static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, - int len) +static ssize_t nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, + int len) { NBDClient *client = req->client; int csock = client->sock; - int rc, ret; + ssize_t rc, ret; qemu_co_mutex_lock(&client->send_lock); qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, @@ -716,22 +737,15 @@ static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, if (!len) { rc = nbd_send_reply(csock, reply); - if (rc == -1) { - rc = -errno; - } } else { socket_set_cork(csock, 1); rc = nbd_send_reply(csock, reply); - if (rc != -1) { + if (rc >= 0) { ret = qemu_co_send(csock, req->data, len); if (ret != len) { - errno = EIO; - rc = -1; + rc = -EIO; } } - if (rc == -1) { - rc = -errno; - } socket_set_cork(csock, 0); } @@ -741,15 +755,18 @@ static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, return rc; } -static int nbd_co_receive_request(NBDRequest *req, struct nbd_request *request) +static ssize_t nbd_co_receive_request(NBDRequest *req, struct nbd_request *request) { NBDClient *client = req->client; int csock = client->sock; - int rc; + ssize_t rc; client->recv_coroutine = qemu_coroutine_self(); - if (nbd_receive_request(csock, request) == -1) { - rc = -EIO; + rc = nbd_receive_request(csock, request); + if (rc < 0) { + if (rc != -EAGAIN) { + rc = -EIO; + } goto out; } @@ -792,11 +809,14 @@ static void nbd_trip(void *opaque) NBDExport *exp = client->exp; struct nbd_request request; struct nbd_reply reply; - int ret; + ssize_t ret; TRACE("Reading request."); ret = nbd_co_receive_request(req, &request); + if (ret == -EAGAIN) { + goto done; + } if (ret == -EIO) { goto out; } @@ -822,6 +842,15 @@ static void nbd_trip(void *opaque) case NBD_CMD_READ: TRACE("Request type is READ"); + if (request.type & NBD_CMD_FLAG_FUA) { + ret = bdrv_co_flush(exp->bs); + if (ret < 0) { + LOG("flush failed"); + reply.error = -ret; + goto error_reply; + } + } + ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512, req->data, request.len / 512); if (ret < 0) { @@ -862,8 +891,9 @@ static void nbd_trip(void *opaque) } } - if (nbd_co_send_reply(req, &reply, 0) < 0) + if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; + } break; case NBD_CMD_DISC: TRACE("Request type is DISCONNECT"); @@ -877,9 +907,9 @@ static void nbd_trip(void *opaque) LOG("flush failed"); reply.error = -ret; } - - if (nbd_co_send_reply(req, &reply, 0) < 0) + if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; + } break; case NBD_CMD_TRIM: TRACE("Request type is TRIM"); @@ -889,21 +919,24 @@ static void nbd_trip(void *opaque) LOG("discard failed"); reply.error = -ret; } - if (nbd_co_send_reply(req, &reply, 0) < 0) + if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; + } break; default: LOG("invalid request type (%u) received", request.type); invalid_request: reply.error = -EINVAL; error_reply: - if (nbd_co_send_reply(req, &reply, 0) == -1) + if (nbd_co_send_reply(req, &reply, 0) < 0) { goto out; + } break; } TRACE("Request/Reply complete"); +done: nbd_request_put(req); return; @@ -941,7 +974,7 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)) { NBDClient *client; - if (nbd_send_negotiate(csock, exp->size, exp->nbdflags) == -1) { + if (nbd_send_negotiate(csock, exp->size, exp->nbdflags) < 0) { return NULL; } client = g_malloc0(sizeof(NBDClient)); diff --git a/nbd.h b/nbd.h index a8382f096c..40d58d359f 100644 --- a/nbd.h +++ b/nbd.h @@ -59,7 +59,7 @@ enum { #define NBD_BUFFER_SIZE (1024*1024) -size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); +ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); int tcp_socket_outgoing(const char *address, uint16_t port); int tcp_socket_incoming(const char *address, uint16_t port); int tcp_socket_outgoing_spec(const char *address_and_port); @@ -70,8 +70,8 @@ int unix_socket_incoming(const char *path); int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, off_t *size, size_t *blocksize); int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize); -int nbd_send_request(int csock, struct nbd_request *request); -int nbd_receive_reply(int csock, struct nbd_reply *reply); +ssize_t nbd_send_request(int csock, struct nbd_request *request); +ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply); int nbd_client(int fd); int nbd_disconnect(int fd); diff --git a/qemu-nbd.c b/qemu-nbd.c index d4e70410fc..5a0300eb07 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -17,7 +17,7 @@ */ #include "qemu-common.h" -#include "block_int.h" +#include "block.h" #include "nbd.h" #include @@ -126,8 +126,7 @@ static int find_partition(BlockDriverState *bs, int partition, } if (data[510] != 0x55 || data[511] != 0xaa) { - errno = -EINVAL; - return -1; + return -EINVAL; } for (i = 0; i < 4; i++) { @@ -165,8 +164,7 @@ static int find_partition(BlockDriverState *bs, int partition, } } - errno = -ENOENT; - return -1; + return -ENOENT; } static void termsig_handler(int signum) @@ -186,7 +184,7 @@ static void *show_parts(void *arg) * modprobe nbd max_part=63 */ nbd = open(device, O_RDWR); - if (nbd != -1) { + if (nbd >= 0) { close(nbd); } return NULL; @@ -203,25 +201,25 @@ static void *nbd_client_thread(void *arg) pthread_t show_parts_thread; sock = unix_socket_outgoing(sockpath); - if (sock == -1) { + if (sock < 0) { goto out; } ret = nbd_receive_negotiate(sock, NULL, &nbdflags, &size, &blocksize); - if (ret == -1) { + if (ret < 0) { goto out; } fd = open(device, O_RDWR); - if (fd == -1) { + if (fd < 0) { /* Linux-only, we can use %m in printf. */ fprintf(stderr, "Failed to open %s: %m", device); goto out; } ret = nbd_init(fd, sock, nbdflags, size, blocksize); - if (ret == -1) { + if (ret < 0) { goto out; } @@ -268,7 +266,7 @@ static void nbd_accept(void *opaque) int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len); nbd_started = true; - if (fd != -1 && nbd_client_new(exp, fd, nbd_client_closed)) { + if (fd >= 0 && nbd_client_new(exp, fd, nbd_client_closed)) { nb_fds++; } } @@ -410,9 +408,9 @@ int main(int argc, char **argv) if (disconnect) { fd = open(argv[optind], O_RDWR); - if (fd == -1) + if (fd < 0) { err(EXIT_FAILURE, "Cannot open %s", argv[optind]); - + } nbd_disconnect(fd); close(fd); @@ -427,7 +425,7 @@ int main(int argc, char **argv) pid_t pid; int ret; - if (qemu_pipe(stderr_fd) == -1) { + if (qemu_pipe(stderr_fd) < 0) { err(EXIT_FAILURE, "Error setting up communication pipe"); } @@ -441,7 +439,7 @@ int main(int argc, char **argv) /* Temporarily redirect stderr to the parent's pipe... */ dup2(stderr_fd[1], STDERR_FILENO); - if (ret == -1) { + if (ret < 0) { err(EXIT_FAILURE, "Failed to daemonize"); } @@ -459,11 +457,11 @@ int main(int argc, char **argv) while ((ret = read(stderr_fd[0], buf, 1024)) > 0) { errors = true; ret = qemu_write_full(STDERR_FILENO, buf, ret); - if (ret == -1) { + if (ret < 0) { exit(EXIT_FAILURE); } } - if (ret == -1) { + if (ret < 0) { err(EXIT_FAILURE, "Cannot read from daemon"); } @@ -489,11 +487,14 @@ int main(int argc, char **argv) err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]); } - fd_size = bs->total_sectors * 512; + fd_size = bdrv_getlength(bs); - if (partition != -1 && - find_partition(bs, partition, &dev_offset, &fd_size)) { - err(EXIT_FAILURE, "Could not find partition %d", partition); + if (partition != -1) { + ret = find_partition(bs, partition, &dev_offset, &fd_size); + if (ret < 0) { + errno = -ret; + err(EXIT_FAILURE, "Could not find partition %d", partition); + } } exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags); @@ -504,7 +505,7 @@ int main(int argc, char **argv) fd = tcp_socket_incoming(bindto, port); } - if (fd == -1) { + if (fd < 0) { return 1; }