From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47606) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WoV4o-0002kg-ND for qemu-devel@nongnu.org; Sun, 25 May 2014 05:50:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WoV4g-0005TW-3z for qemu-devel@nongnu.org; Sun, 25 May 2014 05:50:46 -0400 Received: from mail-wi0-x22c.google.com ([2a00:1450:400c:c05::22c]:56982) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WoV4f-0005TO-Mn for qemu-devel@nongnu.org; Sun, 25 May 2014 05:50:38 -0400 Received: by mail-wi0-f172.google.com with SMTP id hi2so2810204wib.11 for ; Sun, 25 May 2014 02:50:36 -0700 (PDT) From: Hani Benhabiles Date: Sun, 25 May 2014 10:50:08 +0100 Message-Id: <1401011408-8033-3-git-send-email-kroosec@gmail.com> In-Reply-To: <1401011408-8033-1-git-send-email-kroosec@gmail.com> References: <1401011408-8033-1-git-send-email-kroosec@gmail.com> Subject: [Qemu-devel] [PATCH 2/2] nbd: Handle NBD_OPT_LIST option. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, famz@redhat.com, kraxel@redhat.com, stefanha@redhat.com Signed-off-by: Hani Benhabiles --- include/block/nbd.h | 4 +++ nbd.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 95d52ab..23e9a84 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -51,6 +51,10 @@ struct nbd_reply { /* New-style client flags. */ #define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0) /* Fixed newstyle protocol. */ +/* Reply types. */ +#define NBD_REP_ACK (1) /* Data sending finished. */ +#define NBD_REP_SERVER (2) /* Export description. */ + #define NBD_CMD_MASK_COMMAND 0x0000ffff #define NBD_CMD_FLAG_FUA (1 << 16) diff --git a/nbd.c b/nbd.c index fb0a9cf..9150fa6 100644 --- a/nbd.c +++ b/nbd.c @@ -64,6 +64,7 @@ #define NBD_REPLY_MAGIC 0x67446698 #define NBD_OPTS_MAGIC 0x49484156454F5054LL #define NBD_CLIENT_MAGIC 0x0000420281861253LL +#define NBD_REP_MAGIC 0x3e889045565a9LL #define NBD_SET_SOCK _IO(0xab, 0) #define NBD_SET_BLKSIZE _IO(0xab, 1) @@ -77,7 +78,8 @@ #define NBD_SET_TIMEOUT _IO(0xab, 9) #define NBD_SET_FLAGS _IO(0xab, 10) -#define NBD_OPT_EXPORT_NAME (1 << 0) +#define NBD_OPT_EXPORT_NAME (1) +#define NBD_OPT_LIST (3) /* Definitions for opaque data types */ @@ -215,6 +217,88 @@ static ssize_t write_sync(int fd, void *buffer, size_t size) */ +static int nbd_send_rep_ack(int csock) +{ + uint64_t magic; + uint32_t opt, type, len; + + magic = cpu_to_be64(NBD_REP_MAGIC); + if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { + LOG("write failed (rep magic)"); + return -EINVAL; + } + opt = cpu_to_be32(NBD_OPT_LIST); + if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { + LOG("write failed (opt list)"); + return -EINVAL; + } + type = cpu_to_be32(NBD_REP_ACK); + if (write_sync(csock, &type, sizeof(type)) != sizeof(type)) { + LOG("write failed (rep ack)"); + return -EINVAL; + } + len = cpu_to_be32(0); + if (write_sync(csock, &len, sizeof(len)) != sizeof(len)) { + LOG("write failed (rep data length)"); + return -EINVAL; + } + return 0; +} + +static int nbd_send_rep_list(int csock, NBDExport *exp) +{ + uint64_t magic, name_len; + uint32_t opt, type, len; + + name_len = strlen(exp->name); + magic = cpu_to_be64(NBD_REP_MAGIC); + if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { + LOG("write failed (magic)"); + return -EINVAL; + } + opt = cpu_to_be32(NBD_OPT_LIST); + if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { + LOG("write failed (opt)"); + return -EINVAL; + } + type = cpu_to_be32(NBD_REP_SERVER); + if (write_sync(csock, &type, sizeof(type)) != sizeof(type)) { + LOG("write failed (reply type)"); + return -EINVAL; + } + len = cpu_to_be32(name_len + sizeof(len)); + if (write_sync(csock, &len, sizeof(len)) != sizeof(len)) { + LOG("write failed (length)"); + return -EINVAL; + } + len = cpu_to_be32(name_len); + if (write_sync(csock, &len, sizeof(len)) != sizeof(len)) { + LOG("write failed (length)"); + return -EINVAL; + } + if (write_sync(csock, exp->name, name_len) != name_len) { + LOG("write failed (buffer)"); + return -EINVAL; + } + return 0; +} + +static int nbd_send_list(NBDClient *client) +{ + int csock; + NBDExport *exp; + + csock = client->sock; + /* For each export, send a NBD_REP_SERVER reply. */ + QTAILQ_FOREACH(exp, &exports, next) { + if (nbd_send_rep_list(csock, exp)) { + return -EINVAL; + } + } + /* Finish with a NBD_REP_ACK. */ + return nbd_send_rep_ack(csock); +} + static int nbd_receive_options(NBDClient *client) { int csock = client->sock; @@ -258,6 +342,13 @@ static int nbd_receive_options(NBDClient *client) goto fail; } TRACE("Checking option"); + if (tmp == be32_to_cpu(NBD_OPT_LIST)) { + if (nbd_send_list(client) < 0) { + return -EINVAL; + } else { + return 1; + } + } if (tmp != be32_to_cpu(NBD_OPT_EXPORT_NAME)) { LOG("Bad option received"); goto fail; @@ -351,6 +442,8 @@ static int nbd_send_negotiate(NBDClient *client) if (rc < 0) { LOG("option negotiation failed"); goto fail; + } else if (rc > 0) { + goto fail; } assert ((client->exp->nbdflags & ~65535) == 0); @@ -1175,7 +1268,7 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, client->refcount = 1; client->exp = exp; client->sock = csock; - if (nbd_send_negotiate(client) < 0) { + if (nbd_send_negotiate(client)) { g_free(client); return NULL; } -- 1.8.3.2