diff --git a/block/nbd-client.c b/block/nbd-client.c index 6e1c97cad0b9c52382436a17781980b4f24ae6b2..28bfb62bede6351a7949513b6d9456f017007279 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -373,7 +373,7 @@ void nbd_client_session_close(NbdClientSession *client) } int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs, - int sock, const char *export) + int sock, const char *export, Error **errp) { int ret; @@ -382,7 +382,7 @@ int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs, qemu_set_block(sock); ret = nbd_receive_negotiate(sock, export, &client->nbdflags, &client->size, - &client->blocksize); + &client->blocksize, errp); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); closesocket(sock); diff --git a/block/nbd-client.h b/block/nbd-client.h index cd478f3a987947d34169e8f20cc0fcae6d5c7b02..cfeecc2775c583ecbacf13db3f2fa7ce5f42fe8b 100644 --- a/block/nbd-client.h +++ b/block/nbd-client.h @@ -36,7 +36,7 @@ typedef struct NbdClientSession { } NbdClientSession; int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs, - int sock, const char *export_name); + int sock, const char *export_name, Error **errp); void nbd_client_session_close(NbdClientSession *client); int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num, diff --git a/block/nbd.c b/block/nbd.c index 04cc8450762a8a6645dbb770e86550347c612567..2e208317156d6380e35da0cb8e6fb75fc301c5f7 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -271,7 +271,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, } /* NBD handshake */ - result = nbd_client_session_init(&s->client, bs, sock, export); + result = nbd_client_session_init(&s->client, bs, sock, export, errp); g_free(export); return result; } diff --git a/include/block/nbd.h b/include/block/nbd.h index 348302c90b8b1d3ff16aa371d3fccc05aabc340b..b75959556c181b994d2693655c43f054bf4a8263 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -75,7 +75,7 @@ enum { ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read); int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, - off_t *size, size_t *blocksize); + off_t *size, size_t *blocksize, Error **errp); int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize); ssize_t nbd_send_request(int csock, struct nbd_request *request); ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply); diff --git a/nbd.c b/nbd.c index 53cf82be0b2c91ac6c3fd47fd02bc77bdadea727..e56afbc1621c05464678de69c9815e9d4d6803a5 100644 --- a/nbd.c +++ b/nbd.c @@ -494,7 +494,7 @@ fail: } int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, - off_t *size, size_t *blocksize) + off_t *size, size_t *blocksize, Error **errp) { char buf[256]; uint64_t magic, s; @@ -506,13 +506,13 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, rc = -EINVAL; if (read_sync(csock, buf, 8) != 8) { - LOG("read failed"); + error_setg(errp, "Failed to read data"); goto fail; } buf[8] = '\0'; if (strlen(buf) == 0) { - LOG("server connection closed"); + error_setg(errp, "Server connection closed unexpectedly"); goto fail; } @@ -527,12 +527,12 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, qemu_isprint(buf[7]) ? buf[7] : '.'); if (memcmp(buf, "NBDMAGIC", 8) != 0) { - LOG("Invalid magic received"); + error_setg(errp, "Invalid magic received"); goto fail; } if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { - LOG("read failed"); + error_setg(errp, "Failed to read magic"); goto fail; } magic = be64_to_cpu(magic); @@ -545,52 +545,60 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, TRACE("Checking magic (opts_magic)"); if (magic != NBD_OPTS_MAGIC) { - LOG("Bad magic received"); + if (magic == NBD_CLIENT_MAGIC) { + error_setg(errp, "Server does not support export names"); + } else { + error_setg(errp, "Bad magic received"); + } goto fail; } if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { - LOG("flags read failed"); + error_setg(errp, "Failed to read server flags"); 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)"); + error_setg(errp, "Failed to read reserved field"); goto fail; } /* write the export name */ magic = cpu_to_be64(magic); if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { - LOG("write failed (magic)"); + error_setg(errp, "Failed to send export name magic"); goto fail; } opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { - LOG("write failed (opt)"); + error_setg(errp, "Failed to send export name option number"); goto fail; } namesize = cpu_to_be32(strlen(name)); if (write_sync(csock, &namesize, sizeof(namesize)) != sizeof(namesize)) { - LOG("write failed (namesize)"); + error_setg(errp, "Failed to send export name length"); goto fail; } if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { - LOG("write failed (name)"); + error_setg(errp, "Failed to send export name"); goto fail; } } else { TRACE("Checking magic (cli_magic)"); if (magic != NBD_CLIENT_MAGIC) { - LOG("Bad magic received"); + if (magic == NBD_OPTS_MAGIC) { + error_setg(errp, "Server requires an export name"); + } else { + error_setg(errp, "Bad magic received"); + } goto fail; } } if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { - LOG("read failed"); + error_setg(errp, "Failed to read export length"); goto fail; } *size = be64_to_cpu(s); @@ -599,19 +607,19 @@ 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)"); + error_setg(errp, "Failed to read export flags"); goto fail; } *flags = be32_to_cpup(flags); } else { if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { - LOG("read failed (tmp)"); + error_setg(errp, "Failed to read export flags"); goto fail; } *flags |= be32_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { - LOG("read failed (buf)"); + error_setg(errp, "Failed to read reserved block"); goto fail; } rc = 0; diff --git a/qemu-nbd.c b/qemu-nbd.c index d222512412f52dce681fc9db833287d3c8fcd14d..4d8df0838595411d171e1d5eb178a383ac88bcc8 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -284,6 +284,7 @@ static void *nbd_client_thread(void *arg) int fd, sock; int ret; pthread_t show_parts_thread; + Error *local_error = NULL; sock = unix_socket_outgoing(sockpath); if (sock < 0) { @@ -291,8 +292,12 @@ static void *nbd_client_thread(void *arg) } ret = nbd_receive_negotiate(sock, NULL, &nbdflags, - &size, &blocksize); + &size, &blocksize, &local_error); if (ret < 0) { + if (local_error) { + fprintf(stderr, "%s\n", error_get_pretty(local_error)); + error_free(local_error); + } goto out_socket; } diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083 index 991a9d91db9b2e83ab2abea30aa87e468c8ed8a5..1b2d3f1156c2c7df86d6334069c967698d9c1dc7 100755 --- a/tests/qemu-iotests/083 +++ b/tests/qemu-iotests/083 @@ -56,7 +56,8 @@ filter_nbd() { # # Filter out the TCP port number since this changes between runs. sed -e 's#^.*nbd\.c:.*##g' \ - -e 's#nbd:127\.0\.0\.1:[^:]*:#nbd:127\.0\.0\.1:PORT:#g' + -e 's#nbd:127\.0\.0\.1:[^:]*:#nbd:127\.0\.0\.1:PORT:#g' \ + -e 's#\(exportname=foo\|PORT\): Failed to .*$#\1#' } check_disconnect() { diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out index fd397f421ffbf51581663f1d563dfbd7b987b1db..8c1441bf4f03345417dc323182a395e74c015aff 100644 --- a/tests/qemu-iotests/083.out +++ b/tests/qemu-iotests/083.out @@ -1,62 +1,52 @@ QA output created by 083 === Check disconnect before neg1 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect after neg1 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect 8 neg1 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect 16 neg1 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect before export === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect after export === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect 4 export === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect 12 export === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect 16 export === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect before neg2 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect after neg2 === @@ -66,14 +56,12 @@ read failed: Input/output error === Check disconnect 8 neg2 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect 10 neg2 === - -qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo no file open, try 'help open' === Check disconnect before request === @@ -119,32 +107,27 @@ read 512/512 bytes at offset 0 === Check disconnect before neg-classic === - -qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT no file open, try 'help open' === Check disconnect 8 neg-classic === - -qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT no file open, try 'help open' === Check disconnect 16 neg-classic === - -qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT no file open, try 'help open' === Check disconnect 24 neg-classic === - -qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT no file open, try 'help open' === Check disconnect 28 neg-classic === - -qemu-io: can't open device nbd:127.0.0.1:PORT: Could not open image: Invalid argument +qemu-io: can't open device nbd:127.0.0.1:PORT no file open, try 'help open' === Check disconnect after neg-classic ===