From patchwork Fri Nov 30 22:03:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006230 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367kG6f4Zz9sB7 for ; Sat, 1 Dec 2018 09:05:42 +1100 (AEDT) Received: from localhost ([::1]:34808 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSquq-000560-Cj for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:05:40 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55926) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtH-0004Mv-6i for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtG-0004AA-3g for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39636) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqt9-0003JU-65; Fri, 30 Nov 2018 17:03:55 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 70BD3C05D3F3; Fri, 30 Nov 2018 22:03:54 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id B1F1F1057072; Fri, 30 Nov 2018 22:03:53 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:30 -0600 Message-Id: <20181130220344.3350618-2-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 30 Nov 2018 22:03:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 01/14] qemu-nbd: Use program name in error messages X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Max Reitz , nsoffer@redhat.com, jsnow@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This changes output from: $ qemu-nbd nosuch Failed to blk_new_open 'nosuch': Could not open 'nosuch': No such file or directory to something more consistent with qemu-img and qemu: $ qemu-nbd nosuch qemu-nbd: Failed to blk_new_open 'nosuch': Could not open 'nosuch': No such file or directory Update the lone affected test to match. (Hmm - is it sad that we don't do much testing of expected failures?) Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- qemu-nbd.c | 1 + tests/qemu-iotests/233.out | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index ca7109652e5..e169b839ece 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -571,6 +571,7 @@ int main(int argc, char **argv) #endif module_call_init(MODULE_INIT_TRACE); + error_set_progname(argv[0]); qcrypto_init(&error_fatal); module_call_init(MODULE_INIT_QOM); diff --git a/tests/qemu-iotests/233.out b/tests/qemu-iotests/233.out index 94acd9b9479..5f416721b03 100644 --- a/tests/qemu-iotests/233.out +++ b/tests/qemu-iotests/233.out @@ -27,7 +27,7 @@ virtual size: 64M (67108864 bytes) disk size: unavailable == check TLS with different CA fails == -option negotiation failed: Verify failed: No certificate was found. +qemu-nbd: option negotiation failed: Verify failed: No certificate was found. qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': The certificate hasn't got a known issuer == perform I/O over TLS == From patchwork Fri Nov 30 22:03:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006232 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367mB4F9Mz9sB7 for ; Sat, 1 Dec 2018 09:07:21 +1100 (AEDT) Received: from localhost ([::1]:34824 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqwP-0006Mj-Uu for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:07:17 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55929) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtH-0004N0-8n for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtG-0004AG-4O for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40290) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqt9-0003Mc-Pa; Fri, 30 Nov 2018 17:03:55 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2356B3082DDB; Fri, 30 Nov 2018 22:03:55 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8CFE21057072; Fri, 30 Nov 2018 22:03:54 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:31 -0600 Message-Id: <20181130220344.3350618-3-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Fri, 30 Nov 2018 22:03:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 02/14] nbd/client: More consistent error messages X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Consolidate on using decimal (not hex) and on outputting the option reply name (not just value) when the client reports protocol discrepancies from the server. While it won't affect normal operation, it makes debugging additions easier. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- nbd/client.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index b4d457a19ad..b667a1b56fd 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -132,8 +132,9 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt, return -1; } if (reply->option != opt) { - error_setg(errp, "Unexpected option type %x expected %x", - reply->option, opt); + error_setg(errp, "Unexpected option type %u (%s) expected %u (%s)", + reply->option, nbd_opt_lookup(reply->option), + opt, nbd_opt_lookup(opt)); nbd_send_opt_abort(ioc); return -1; } @@ -265,8 +266,9 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match, } return 0; } else if (reply.type != NBD_REP_SERVER) { - error_setg(errp, "Unexpected reply type %" PRIx32 " expected %x", - reply.type, NBD_REP_SERVER); + error_setg(errp, "Unexpected reply type %u (%s) expected %u (%s)", + reply.type, nbd_rep_lookup(reply.type), + NBD_REP_SERVER, nbd_rep_lookup(NBD_REP_SERVER)); nbd_send_opt_abort(ioc); return -1; } @@ -378,9 +380,9 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, return 1; } if (reply.type != NBD_REP_INFO) { - error_setg(errp, "unexpected reply type %" PRIu32 - " (%s), expected %u", - reply.type, nbd_rep_lookup(reply.type), NBD_REP_INFO); + error_setg(errp, "unexpected reply type %u (%s), expected %u (%s)", + reply.type, nbd_rep_lookup(reply.type), + NBD_REP_INFO, nbd_rep_lookup(NBD_REP_INFO)); nbd_send_opt_abort(ioc); return -1; } @@ -704,8 +706,9 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, } if (reply.type != NBD_REP_ACK) { - error_setg(errp, "Unexpected reply type %" PRIx32 " expected %x", - reply.type, NBD_REP_ACK); + error_setg(errp, "Unexpected reply type %u (%s) expected %u (%s)", + reply.type, nbd_rep_lookup(reply.type), + NBD_REP_ACK, nbd_rep_lookup(NBD_REP_ACK)); nbd_send_opt_abort(ioc); return -1; } From patchwork Fri Nov 30 22:03:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006235 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367qx4vYDz9sB7 for ; Sat, 1 Dec 2018 09:10:37 +1100 (AEDT) Received: from localhost ([::1]:34850 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqzb-00024I-38 for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:10:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55955) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtI-0004Nw-15 for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtG-0004BH-8d for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:50468) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtA-0003T2-Fl; Fri, 30 Nov 2018 17:03:56 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D1CD3307D84D; Fri, 30 Nov 2018 22:03:55 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4607B1057072; Fri, 30 Nov 2018 22:03:55 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:32 -0600 Message-Id: <20181130220344.3350618-4-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Fri, 30 Nov 2018 22:03:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 03/14] qemu-nbd: Fail earlier for -c/-d on non-linux X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Connecting to a /dev/nbdN device is a Linux-specific action. We were already masking -c and -d from 'qemu-nbd --help' on non-linux. However, while -d fails with a sensible error message, it took hunting through a couple of files to prove that. What's more, the code for -c doesn't fail until after it has created a pthread and tried to open a device - possibly even printing an error message with %m on a non-Linux platform in spite of the comment that %m is glibc-specific. Make the failure happen sooner, then get rid of stubs that are no longer needed because of the early exits. While at it: tweak the blank newlines in --help output to be consistent, whether or not built on Linux. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones --- nbd/client.c | 18 +----------------- qemu-nbd.c | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index b667a1b56fd..0be89f9e641 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -1029,23 +1029,7 @@ int nbd_disconnect(int fd) return 0; } -#else -int nbd_init(int fd, QIOChannelSocket *ioc, NBDExportInfo *info, - Error **errp) -{ - error_setg(errp, "nbd_init is only supported on Linux"); - return -ENOTSUP; -} - -int nbd_client(int fd) -{ - return -ENOTSUP; -} -int nbd_disconnect(int fd) -{ - return -ENOTSUP; -} -#endif +#endif /* __linux__ */ int nbd_send_request(QIOChannel *ioc, NBDRequest *request) { diff --git a/qemu-nbd.c b/qemu-nbd.c index e169b839ece..55e29bd9a7e 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -43,6 +43,12 @@ #include "trace/control.h" #include "qemu-version.h" +#ifdef __linux__ +#define HAVE_NBD_DEVICE 1 +#else +#define HAVE_NBD_DEVICE 0 +#endif + #define SOCKET_PATH "/var/lock/qemu-nbd-%s" #define QEMU_NBD_OPT_CACHE 256 #define QEMU_NBD_OPT_AIO 257 @@ -98,11 +104,11 @@ static void usage(const char *name) " specify tracing options\n" " --fork fork off the server process and exit the parent\n" " once the server is running\n" -#ifdef __linux__ +#if HAVE_NBD_DEVICE +"\n" "Kernel NBD client support:\n" " -c, --connect=DEV connect FILE to the local NBD device DEV\n" " -d, --disconnect disconnect the specified device\n" -"\n" #endif "\n" "Block device options:\n" @@ -236,6 +242,7 @@ static void termsig_handler(int signum) } +#if HAVE_NBD_DEVICE static void *show_parts(void *arg) { char *device = arg; @@ -321,6 +328,7 @@ out: kill(getpid(), SIGTERM); return (void *) EXIT_FAILURE; } +#endif /* HAVE_NBD_DEVICE */ static int nbd_can_accept(void) { @@ -815,6 +823,7 @@ int main(int argc, char **argv) } if (disconnect) { +#if HAVE_NBD_DEVICE int nbdfd = open(argv[optind], O_RDWR); if (nbdfd < 0) { error_report("Cannot open %s: %s", argv[optind], @@ -828,6 +837,10 @@ int main(int argc, char **argv) printf("%s disconnected\n", argv[optind]); return 0; +#else + error_report("Kernel /dev/nbdN support not available"); + exit(EXIT_FAILURE); +#endif } if ((device && !verbose) || fork_process) { @@ -1006,6 +1019,7 @@ int main(int argc, char **argv) nbd_export_set_description(exp, export_description); if (device) { +#if HAVE_NBD_DEVICE int ret; ret = pthread_create(&client_thread, NULL, nbd_client_thread, device); @@ -1013,6 +1027,10 @@ int main(int argc, char **argv) error_report("Failed to create client thread: %s", strerror(ret)); exit(EXIT_FAILURE); } +#else + error_report("Kernel /dev/nbdN support not available"); + exit(EXIT_FAILURE); +#endif } else { /* Shut up GCC warnings. */ memset(&client_thread, 0, sizeof(client_thread)); From patchwork Fri Nov 30 22:03:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006229 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367jn2gQwz9sB7 for ; Sat, 1 Dec 2018 09:05:17 +1100 (AEDT) Received: from localhost ([::1]:34803 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSquQ-0004lh-Or for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:05:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55947) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtH-0004Nq-UA for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtG-0004C5-D8 for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49866) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtB-0003XV-6w; Fri, 30 Nov 2018 17:03:57 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8925C3091D5C; Fri, 30 Nov 2018 22:03:56 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id F17E91057072; Fri, 30 Nov 2018 22:03:55 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:33 -0600 Message-Id: <20181130220344.3350618-5-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Fri, 30 Nov 2018 22:03:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 04/14] qemu-nbd: Simplify --partition handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Our open-coding of strtol handling forgot to handle overflow conditions. What's more, since we insiste on a user-supplied partition to be non-zero, we can use 0 rather than -1 for our initial value to distinguish when a partition is not being served, for slightly more optimal code. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- qemu-nbd.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index 55e29bd9a7e..866e64779f1 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -546,7 +546,7 @@ int main(int argc, char **argv) int opt_ind = 0; char *end; int flags = BDRV_O_RDWR; - int partition = -1; + int partition = 0; int ret = 0; bool seen_cache = false; bool seen_discard = false; @@ -685,13 +685,9 @@ int main(int argc, char **argv) flags &= ~BDRV_O_RDWR; break; case 'P': - partition = strtol(optarg, &end, 0); - if (*end) { - error_report("Invalid partition `%s'", optarg); - exit(EXIT_FAILURE); - } - if (partition < 1 || partition > 8) { - error_report("Invalid partition %d", partition); + if (qemu_strtoi(optarg, NULL, 0, &partition) < 0 || + partition < 1 || partition > 8) { + error_report("Invalid partition %s", optarg); exit(EXIT_FAILURE); } break; @@ -1004,7 +1000,7 @@ int main(int argc, char **argv) } fd_size -= dev_offset; - if (partition != -1) { + if (partition) { ret = find_partition(blk, partition, &dev_offset, &fd_size); if (ret < 0) { error_report("Could not find partition %d: %s", partition, From patchwork Fri Nov 30 22:03:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006239 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367v93GP3z9sB7 for ; Sat, 1 Dec 2018 09:13:25 +1100 (AEDT) Received: from localhost ([::1]:34868 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr2I-0004hs-S5 for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:13:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55956) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtI-0004Nx-1C for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtG-0004CB-F6 for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:03 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38174) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtB-0003bJ-U0; Fri, 30 Nov 2018 17:03:58 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 45C083002887; Fri, 30 Nov 2018 22:03:57 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id AD7951057072; Fri, 30 Nov 2018 22:03:56 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:34 -0600 Message-Id: <20181130220344.3350618-6-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Fri, 30 Nov 2018 22:03:57 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 05/14] nbd/client: Drop pointless buf variable X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" There's no need to read into a temporary buffer (oversized since commit 7d3123e1) followed by a byteswap into a uint64_t to check for a magic number via memcmp(), when the code immediately below demonstrates reading into the uint64_t then byteswapping in place and checking for a magic number via integer math. What's more, having a different error message when the server's first reply byte is 0 is unusual - it's no different from any other wrong magic number, and we already detected short reads. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- nbd/nbd-internal.h | 1 + nbd/client.c | 14 +++----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index eeff78d3c98..306a533dcd1 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -46,6 +46,7 @@ /* Size of oldstyle negotiation */ #define NBD_OLDSTYLE_NEGOTIATE_SIZE (8 + 8 + 8 + 4 + 124) +#define NBD_INIT_MAGIC 0x4e42444d41474943LL #define NBD_REQUEST_MAGIC 0x25609513 #define NBD_OPTS_MAGIC 0x49484156454F5054LL #define NBD_CLIENT_MAGIC 0x0000420281861253LL diff --git a/nbd/client.c b/nbd/client.c index 0be89f9e641..17ee24492a4 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -731,7 +731,6 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, QIOChannel **outioc, NBDExportInfo *info, Error **errp) { - char buf[256]; uint64_t magic; int rc; bool zeroes = true; @@ -752,21 +751,14 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, goto fail; } - if (nbd_read(ioc, buf, 8, errp) < 0) { + if (nbd_read(ioc, &magic, sizeof(magic), errp) < 0) { error_prepend(errp, "Failed to read data: "); goto fail; } - - buf[8] = '\0'; - if (strlen(buf) == 0) { - error_setg(errp, "Server connection closed unexpectedly"); - goto fail; - } - - magic = ldq_be_p(buf); + magic = be64_to_cpu(magic); trace_nbd_receive_negotiate_magic(magic); - if (memcmp(buf, "NBDMAGIC", 8) != 0) { + if (magic != NBD_INIT_MAGIC) { error_setg(errp, "Invalid magic received"); goto fail; } From patchwork Fri Nov 30 22:03:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006238 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367sW67yDz9sB7 for ; Sat, 1 Dec 2018 09:11:59 +1100 (AEDT) Received: from localhost ([::1]:34859 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr0v-0003CB-Cv for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:11:57 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56018) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtJ-0004Pn-Gp for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtH-0004Fa-7K for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:05 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34668) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtC-0003fn-Ph; Fri, 30 Nov 2018 17:03:58 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 238243154865; Fri, 30 Nov 2018 22:03:58 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6BF211057072; Fri, 30 Nov 2018 22:03:57 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:35 -0600 Message-Id: <20181130220344.3350618-7-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Fri, 30 Nov 2018 22:03:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 06/14] nbd/client: Move export name into NBDExportInfo X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Max Reitz , nsoffer@redhat.com, jsnow@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Refactor the 'name' parameter of nbd_receive_negotiate() from being a separate parameter into being part of the in-out 'info'. This also spills over to a simplification of nbd_opt_go(). The main driver for this refactoring is that an upcoming patch would like to add support to qemu-nbd to list information about all exports available on a server, where the name(s) will be provided by the server instead of the client. But another benefit is that we can now allow the client to explicitly specify the empty export name "" even when connecting to an oldstyle server (even if qemu is no longer such a server after commit 7f7dfe2a). Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- include/block/nbd.h | 8 ++++---- block/nbd-client.c | 5 +++-- nbd/client.c | 39 ++++++++++++++++++--------------------- qemu-nbd.c | 6 ++++-- nbd/trace-events | 2 +- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 6a5bfe5d559..65feff8ba96 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -262,6 +262,7 @@ struct NBDExportInfo { /* Set by client before nbd_receive_negotiate() */ bool request_sizes; char *x_dirty_bitmap; + char *name; /* must be non-NULL */ /* In-out fields, set by client before nbd_receive_negotiate() and * updated by server results during nbd_receive_negotiate() */ @@ -279,10 +280,9 @@ struct NBDExportInfo { }; typedef struct NBDExportInfo NBDExportInfo; -int nbd_receive_negotiate(QIOChannel *ioc, const char *name, - QCryptoTLSCreds *tlscreds, const char *hostname, - QIOChannel **outioc, NBDExportInfo *info, - Error **errp); +int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, + const char *hostname, QIOChannel **outioc, + NBDExportInfo *info, Error **errp); int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info, Error **errp); int nbd_send_request(QIOChannel *ioc, NBDRequest *request); diff --git a/block/nbd-client.c b/block/nbd-client.c index fc5b7eda8ee..417971d8b05 100644 --- a/block/nbd-client.c +++ b/block/nbd-client.c @@ -984,10 +984,11 @@ int nbd_client_init(BlockDriverState *bs, client->info.structured_reply = true; client->info.base_allocation = true; client->info.x_dirty_bitmap = g_strdup(x_dirty_bitmap); - ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export, - tlscreds, hostname, + client->info.name = g_strdup(export ?: ""); + ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), tlscreds, hostname, &client->ioc, &client->info, errp); g_free(client->info.x_dirty_bitmap); + g_free(client->info.name); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); return ret; diff --git a/nbd/client.c b/nbd/client.c index 17ee24492a4..b5818a99d21 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -320,15 +320,14 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match, } -/* Returns -1 if NBD_OPT_GO proves the export @wantname cannot be +/* Returns -1 if NBD_OPT_GO proves the export @info->name cannot be * used, 0 if NBD_OPT_GO is unsupported (fall back to NBD_OPT_LIST and * NBD_OPT_EXPORT_NAME in that case), and > 0 if the export is good to - * go (with @info populated). */ -static int nbd_opt_go(QIOChannel *ioc, const char *wantname, - NBDExportInfo *info, Error **errp) + * go (with the rest of @info populated). */ +static int nbd_opt_go(QIOChannel *ioc, NBDExportInfo *info, Error **errp) { NBDOptionReply reply; - uint32_t len = strlen(wantname); + uint32_t len = strlen(info->name); uint16_t type; int error; char *buf; @@ -338,10 +337,10 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, * flags still 0 is a witness of a broken server. */ info->flags = 0; - trace_nbd_opt_go_start(wantname); + trace_nbd_opt_go_start(info->name); buf = g_malloc(4 + len + 2 + 2 * info->request_sizes + 1); stl_be_p(buf, len); - memcpy(buf + 4, wantname, len); + memcpy(buf + 4, info->name, len); /* At most one request, everything else up to server */ stw_be_p(buf + 4 + len, info->request_sizes); if (info->request_sizes) { @@ -726,10 +725,9 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, return 0; } -int nbd_receive_negotiate(QIOChannel *ioc, const char *name, - QCryptoTLSCreds *tlscreds, const char *hostname, - QIOChannel **outioc, NBDExportInfo *info, - Error **errp) +int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, + const char *hostname, QIOChannel **outioc, + NBDExportInfo *info, Error **errp) { uint64_t magic; int rc; @@ -739,6 +737,8 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, trace_nbd_receive_negotiate(tlscreds, hostname ? hostname : ""); + assert(info->name); + trace_nbd_receive_negotiate_name(info->name); info->structured_reply = false; info->base_allocation = false; rc = -EINVAL; @@ -807,10 +807,6 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, goto fail; } } - if (!name) { - trace_nbd_receive_negotiate_default_name(); - name = ""; - } if (fixedNewStyle) { int result; @@ -826,7 +822,8 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, if (info->structured_reply && base_allocation) { result = nbd_negotiate_simple_meta_context( - ioc, name, info->x_dirty_bitmap ?: "base:allocation", + ioc, info->name, + info->x_dirty_bitmap ?: "base:allocation", &info->meta_base_allocation_id, errp); if (result < 0) { goto fail; @@ -839,7 +836,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, * TLS). If it is not available, fall back to * NBD_OPT_LIST for nicer error messages about a missing * export, then use NBD_OPT_EXPORT_NAME. */ - result = nbd_opt_go(ioc, name, info, errp); + result = nbd_opt_go(ioc, info, errp); if (result < 0) { goto fail; } @@ -852,12 +849,12 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, * query gives us better error reporting if the * export name is not available. */ - if (nbd_receive_query_exports(ioc, name, errp) < 0) { + if (nbd_receive_query_exports(ioc, info->name, errp) < 0) { goto fail; } } /* write the export name request */ - if (nbd_send_option_request(ioc, NBD_OPT_EXPORT_NAME, -1, name, + if (nbd_send_option_request(ioc, NBD_OPT_EXPORT_NAME, -1, info->name, errp) < 0) { goto fail; } @@ -877,8 +874,8 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name, } else if (magic == NBD_CLIENT_MAGIC) { uint32_t oldflags; - if (name) { - error_setg(errp, "Server does not support export names"); + if (*info->name) { + error_setg(errp, "Server does not support non-empty export names"); goto fail; } if (tlscreds) { diff --git a/qemu-nbd.c b/qemu-nbd.c index 866e64779f1..c57053a0795 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -263,7 +263,7 @@ static void *show_parts(void *arg) static void *nbd_client_thread(void *arg) { char *device = arg; - NBDExportInfo info = { .request_sizes = false, }; + NBDExportInfo info = { .request_sizes = false, .name = g_strdup("") }; QIOChannelSocket *sioc; int fd; int ret; @@ -278,7 +278,7 @@ static void *nbd_client_thread(void *arg) goto out; } - ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, + ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, NULL, NULL, &info, &local_error); if (ret < 0) { if (local_error) { @@ -317,6 +317,7 @@ static void *nbd_client_thread(void *arg) } close(fd); object_unref(OBJECT(sioc)); + free(info.name); kill(getpid(), SIGTERM); return (void *) EXIT_SUCCESS; @@ -325,6 +326,7 @@ out_fd: out_socket: object_unref(OBJECT(sioc)); out: + free(info.name); kill(getpid(), SIGTERM); return (void *) EXIT_FAILURE; } diff --git a/nbd/trace-events b/nbd/trace-events index 5e1d4afe8e6..289337d0dc3 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -15,7 +15,7 @@ nbd_opt_meta_reply(const char *context, uint32_t id) "Received mapping of contex nbd_receive_negotiate(void *tlscreds, const char *hostname) "Receiving negotiation tlscreds=%p hostname=%s" nbd_receive_negotiate_magic(uint64_t magic) "Magic is 0x%" PRIx64 nbd_receive_negotiate_server_flags(uint32_t globalflags) "Global flags are 0x%" PRIx32 -nbd_receive_negotiate_default_name(void) "Using default NBD export name \"\"" +nbd_receive_negotiate_name(const char *name) "Requesting NBD export name \"%s\"" nbd_receive_negotiate_size_flags(uint64_t size, uint16_t flags) "Size is %" PRIu64 ", export flags 0x%" PRIx16 nbd_init_set_socket(void) "Setting NBD socket" nbd_init_set_block_size(unsigned long block_size) "Setting block size to %lu" From patchwork Fri Nov 30 22:03:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006242 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367xk6Rwwz9sB7 for ; Sat, 1 Dec 2018 09:15:38 +1100 (AEDT) Received: from localhost ([::1]:34884 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr4S-0007ax-Co for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:15:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56006) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtJ-0004PG-4V for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtH-0004FP-5x for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:05 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55212) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtD-0003jJ-Hj; Fri, 30 Nov 2018 17:03:59 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D42349D781; Fri, 30 Nov 2018 22:03:58 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 45A221057072; Fri, 30 Nov 2018 22:03:58 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:36 -0600 Message-Id: <20181130220344.3350618-8-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 30 Nov 2018 22:03:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 07/14] nbd/client: Refactor nbd_negotiate_simple_meta_context() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Change the signature to make it easier for a future patch to reuse this function for calling NBD_OPT_LIST_META_CONTEXT with 0 or 1 queries. Also, always allocate space for the received name, even if it doesn't match expected lengths (no point trying to optimize the unlikely error case, and tracing the received rather than expected name can help debug a server implementation). While there are now slightly different traces, and the error message for a server replying with too many contexts is different, there are no runtime-observable changes in behavior for the more common case of the lone caller interacting with a compliant server. Signed-off-by: Eric Blake Tested-by: Richard W.M. Jones --- nbd/client.c | 105 +++++++++++++++++++++++++++-------------------- nbd/trace-events | 2 +- 2 files changed, 61 insertions(+), 46 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index b5818a99d21..1dc8f83e19a 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -603,49 +603,57 @@ static QIOChannel *nbd_receive_starttls(QIOChannel *ioc, } /* nbd_negotiate_simple_meta_context: - * Set one meta context. Simple means that reply must contain zero (not - * negotiated) or one (negotiated) contexts. More contexts would be considered - * as a protocol error. It's also implied that meta-data query equals queried - * context name, so, if server replies with something different than @context, - * it is considered an error too. - * return 1 for successful negotiation, context_id is set - * 0 if operation is unsupported, + * List or set meta context data for export @info->name, based on @opt. + * For list, leave @context NULL for 0 queries, or supplied for a single + * query; all replies are ignored, and the call merely traces server behavior. + * For set, @context must result in at most one matching server reply, in + * which case @info->meta_base_allocation_id is set to the resulting id. + * return 1 for successful negotiation, + * 0 if operation is unsupported or context unavailable, * -1 with errp set for any other error */ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, - const char *export, + int32_t opt, const char *context, - uint32_t *context_id, + NBDExportInfo *info, Error **errp) { int ret; NBDOptionReply reply; uint32_t received_id = 0; bool received = false; - uint32_t export_len = strlen(export); - uint32_t context_len = strlen(context); - uint32_t data_len = sizeof(export_len) + export_len + - sizeof(uint32_t) + /* number of queries */ - sizeof(context_len) + context_len; - char *data = g_malloc(data_len); - char *p = data; + uint32_t export_len = strlen(info->name); + uint32_t context_len; + uint32_t data_len = sizeof(export_len) + export_len + sizeof(uint32_t); + char *data; + char *p; - trace_nbd_opt_meta_request(context, export); + if (!context) { + assert(opt == NBD_OPT_LIST_META_CONTEXT); + } else { + context_len = strlen(context); + data_len += sizeof(context_len) + context_len; + } + data = g_malloc(data_len); + p = data; + + trace_nbd_opt_meta_request(nbd_opt_lookup(opt), context ?: "(all)", + info->name); stl_be_p(p, export_len); - memcpy(p += sizeof(export_len), export, export_len); - stl_be_p(p += export_len, 1); - stl_be_p(p += sizeof(uint32_t), context_len); - memcpy(p += sizeof(context_len), context, context_len); + memcpy(p += sizeof(export_len), info->name, export_len); + stl_be_p(p += export_len, !!context); + if (context) { + stl_be_p(p += sizeof(uint32_t), context_len); + memcpy(p += sizeof(context_len), context, context_len); + } - ret = nbd_send_option_request(ioc, NBD_OPT_SET_META_CONTEXT, data_len, data, - errp); + ret = nbd_send_option_request(ioc, opt, data_len, data, errp); g_free(data); if (ret < 0) { return ret; } - if (nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &reply, - errp) < 0) + if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) { return -1; } @@ -655,10 +663,10 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, return ret; } - if (reply.type == NBD_REP_META_CONTEXT) { + while (reply.type == NBD_REP_META_CONTEXT) { char *name; - if (reply.length != sizeof(received_id) + context_len) { + if (reply.length <= sizeof(received_id)) { error_setg(errp, "Failed to negotiate meta context '%s', server " "answered with unexpected length %" PRIu32, context, reply.length); @@ -678,23 +686,31 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, return -1; } name[reply.length] = '\0'; - if (strcmp(context, name)) { - error_setg(errp, "Failed to negotiate meta context '%s', server " - "answered with different context '%s'", context, - name); - g_free(name); - nbd_send_opt_abort(ioc); - return -1; + + trace_nbd_opt_meta_reply(name, received_id); + if (opt == NBD_OPT_SET_META_CONTEXT) { + if (received) { + error_setg(errp, "Server replied with more than one context"); + free(name); + nbd_send_opt_abort(ioc); + return -1; + } + + if (strcmp(context, name)) { + error_setg(errp, + "Failed to negotiate meta context '%s', server " + "answered with different context '%s'", context, + name); + g_free(name); + nbd_send_opt_abort(ioc); + return -1; + } } g_free(name); - - trace_nbd_opt_meta_reply(context, received_id); received = true; /* receive NBD_REP_ACK */ - if (nbd_receive_option_reply(ioc, NBD_OPT_SET_META_CONTEXT, &reply, - errp) < 0) - { + if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) { return -1; } @@ -717,12 +733,11 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, return -1; } - if (received) { - *context_id = received_id; - return 1; + if (received && opt == NBD_OPT_SET_META_CONTEXT) { + info->meta_base_allocation_id = received_id; } - return 0; + return received || opt == NBD_OPT_LIST_META_CONTEXT; } int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, @@ -822,9 +837,9 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, if (info->structured_reply && base_allocation) { result = nbd_negotiate_simple_meta_context( - ioc, info->name, + ioc, NBD_OPT_SET_META_CONTEXT, info->x_dirty_bitmap ?: "base:allocation", - &info->meta_base_allocation_id, errp); + info, errp); if (result < 0) { goto fail; } diff --git a/nbd/trace-events b/nbd/trace-events index 289337d0dc3..5d0d202fad2 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -10,7 +10,7 @@ nbd_receive_query_exports_start(const char *wantname) "Querying export list for nbd_receive_query_exports_success(const char *wantname) "Found desired export name '%s'" nbd_receive_starttls_new_client(void) "Setting up TLS" nbd_receive_starttls_tls_handshake(void) "Starting TLS handshake" -nbd_opt_meta_request(const char *context, const char *export) "Requesting to set meta context %s for export %s" +nbd_opt_meta_request(const char *opt, const char *context, const char *export) "Requesting to %s %s for export %s" nbd_opt_meta_reply(const char *context, uint32_t id) "Received mapping of context %s to id %" PRIu32 nbd_receive_negotiate(void *tlscreds, const char *hostname) "Receiving negotiation tlscreds=%p hostname=%s" nbd_receive_negotiate_magic(uint64_t magic) "Magic is 0x%" PRIx64 From patchwork Fri Nov 30 22:03:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006234 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367p73hBtz9sDN for ; Sat, 1 Dec 2018 09:09:03 +1100 (AEDT) Received: from localhost ([::1]:34835 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqy4-0000oZ-Vd for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:09:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55995) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtI-0004P0-To for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtH-0004Ff-7a for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:04 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52186) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtE-0003px-7x; Fri, 30 Nov 2018 17:04:00 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8FE2B3DE0D; Fri, 30 Nov 2018 22:03:59 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id F2DF81057072; Fri, 30 Nov 2018 22:03:58 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:37 -0600 Message-Id: <20181130220344.3350618-9-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 30 Nov 2018 22:03:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 08/14] nbd/client: Refactor nbd_receive_list() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add some parameters to make this function reusable in upcoming export listing, where we will want to capture the name and description rather than compare against a user-supplied name. No change in semantics to the existing caller. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones --- nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index 1dc8f83e19a..27785c55d0a 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -232,18 +232,21 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply, return result; } -/* Process another portion of the NBD_OPT_LIST reply. Set *@match if - * the current reply matches @want or if the server does not support - * NBD_OPT_LIST, otherwise leave @match alone. Return 0 if iteration - * is complete, positive if more replies are expected, or negative - * with @errp set if an unrecoverable error occurred. */ +/* Process another portion of the NBD_OPT_LIST reply. If @want, then + * set *@match if the current reply matches @want or if the server + * does not support NBD_OPT_LIST, otherwise leave @match alone. + * Otherwise, @nameout and @description are malloc'd to contain + * NUL-terminated copies of the reply. Return 0 if iteration is + * complete, positive if more replies are expected, or negative with + * @errp set if an unrecoverable error occurred. */ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match, - Error **errp) + char **nameout, char **description, Error **errp) { NBDOptionReply reply; uint32_t len; uint32_t namelen; - char name[NBD_MAX_NAME_SIZE + 1]; + char array[NBD_MAX_NAME_SIZE + 1]; + char *name = array; int error; if (nbd_receive_option_reply(ioc, NBD_OPT_LIST, &reply, errp) < 0) { @@ -253,7 +256,12 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match, if (error <= 0) { /* The server did not support NBD_OPT_LIST, so set *match on * the assumption that any name will be accepted. */ - *match = true; + if (want) { + *match = true; + } else if (!error) { + error_setg(errp, "Server does not support export lists"); + error = -1; + } return error; } len = reply.length; @@ -290,30 +298,49 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match, nbd_send_opt_abort(ioc); return -1; } - if (namelen != strlen(want)) { - if (nbd_drop(ioc, len, errp) < 0) { - error_prepend(errp, - "failed to skip export name with wrong length: "); - nbd_send_opt_abort(ioc); - return -1; + if (want) { + if (namelen != strlen(want)) { + if (nbd_drop(ioc, len, errp) < 0) { + error_prepend(errp, + "failed to skip export name with wrong length: "); + nbd_send_opt_abort(ioc); + return -1; + } + return 1; } - return 1; + assert(namelen < sizeof(array)); + } else { + assert(nameout); + *nameout = name = g_new(char, namelen + 1); } - assert(namelen < sizeof(name)); if (nbd_read(ioc, name, namelen, errp) < 0) { error_prepend(errp, "failed to read export name: "); nbd_send_opt_abort(ioc); + if (!want) { + free(name); + } return -1; } name[namelen] = '\0'; len -= namelen; - if (nbd_drop(ioc, len, errp) < 0) { + if (!want) { + assert(description); + *description = g_new(char, len + 1); + if (nbd_read(ioc, *description, len, errp) < 0) { + error_prepend(errp, "failed to read export description: "); + nbd_send_opt_abort(ioc); + free(name); + free(*description); + return -1; + } + (*description)[len] = '\0'; + } else if (nbd_drop(ioc, len, errp) < 0) { error_prepend(errp, "failed to read export description: "); nbd_send_opt_abort(ioc); return -1; } - if (!strcmp(name, want)) { + if (want && !strcmp(name, want)) { *match = true; } return 1; @@ -498,7 +525,8 @@ static int nbd_receive_query_exports(QIOChannel *ioc, } while (1) { - int ret = nbd_receive_list(ioc, wantname, &foundExport, errp); + int ret = nbd_receive_list(ioc, wantname, &foundExport, + NULL, NULL, errp); if (ret < 0) { /* Server gave unexpected reply */ From patchwork Fri Nov 30 22:03:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006240 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367wP2bJqz9sB7 for ; Sat, 1 Dec 2018 09:14:29 +1100 (AEDT) Received: from localhost ([::1]:34876 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr3K-0006hc-IZ for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:14:26 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56074) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtO-0004Ru-2G for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtJ-0004TZ-FL for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34674) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtE-0003xC-UH; Fri, 30 Nov 2018 17:04:01 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 45DAE3154849; Fri, 30 Nov 2018 22:04:00 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id AED811057073; Fri, 30 Nov 2018 22:03:59 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:38 -0600 Message-Id: <20181130220344.3350618-10-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Fri, 30 Nov 2018 22:04:00 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 09/14] nbd/client: Refactor return of nbd_receive_negotiate() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The function could only ever return 0 or -EINVAL; make this clearer by dropping a useless 'fail:' label. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- nbd/client.c | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index 27785c55d0a..1ed5009642e 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -773,7 +773,6 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, NBDExportInfo *info, Error **errp) { uint64_t magic; - int rc; bool zeroes = true; bool structured_reply = info->structured_reply; bool base_allocation = info->base_allocation; @@ -784,31 +783,30 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, trace_nbd_receive_negotiate_name(info->name); info->structured_reply = false; info->base_allocation = false; - rc = -EINVAL; if (outioc) { *outioc = NULL; } if (tlscreds && !outioc) { error_setg(errp, "Output I/O channel required for TLS"); - goto fail; + return -EINVAL; } if (nbd_read(ioc, &magic, sizeof(magic), errp) < 0) { error_prepend(errp, "Failed to read data: "); - goto fail; + return -EINVAL; } magic = be64_to_cpu(magic); trace_nbd_receive_negotiate_magic(magic); if (magic != NBD_INIT_MAGIC) { error_setg(errp, "Invalid magic received"); - goto fail; + return -EINVAL; } if (nbd_read(ioc, &magic, sizeof(magic), errp) < 0) { error_prepend(errp, "Failed to read magic: "); - goto fail; + return -EINVAL; } magic = be64_to_cpu(magic); trace_nbd_receive_negotiate_magic(magic); @@ -820,7 +818,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, if (nbd_read(ioc, &globalflags, sizeof(globalflags), errp) < 0) { error_prepend(errp, "Failed to read server flags: "); - goto fail; + return -EINVAL; } globalflags = be16_to_cpu(globalflags); trace_nbd_receive_negotiate_server_flags(globalflags); @@ -836,18 +834,18 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, clientflags = cpu_to_be32(clientflags); if (nbd_write(ioc, &clientflags, sizeof(clientflags), errp) < 0) { error_prepend(errp, "Failed to send clientflags field: "); - goto fail; + return -EINVAL; } if (tlscreds) { if (fixedNewStyle) { *outioc = nbd_receive_starttls(ioc, tlscreds, hostname, errp); if (!*outioc) { - goto fail; + return -EINVAL; } ioc = *outioc; } else { error_setg(errp, "Server does not support STARTTLS"); - goto fail; + return -EINVAL; } } if (fixedNewStyle) { @@ -858,7 +856,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, NBD_OPT_STRUCTURED_REPLY, errp); if (result < 0) { - goto fail; + return -EINVAL; } info->structured_reply = result == 1; } @@ -869,7 +867,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, info->x_dirty_bitmap ?: "base:allocation", info, errp); if (result < 0) { - goto fail; + return -EINVAL; } info->base_allocation = result == 1; } @@ -881,7 +879,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, * export, then use NBD_OPT_EXPORT_NAME. */ result = nbd_opt_go(ioc, info, errp); if (result < 0) { - goto fail; + return -EINVAL; } if (result > 0) { return 0; @@ -893,25 +891,25 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, * export name is not available. */ if (nbd_receive_query_exports(ioc, info->name, errp) < 0) { - goto fail; + return -EINVAL; } } /* write the export name request */ if (nbd_send_option_request(ioc, NBD_OPT_EXPORT_NAME, -1, info->name, errp) < 0) { - goto fail; + return -EINVAL; } /* Read the response */ if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) { error_prepend(errp, "Failed to read export length: "); - goto fail; + return -EINVAL; } info->size = be64_to_cpu(info->size); if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) { error_prepend(errp, "Failed to read export flags: "); - goto fail; + return -EINVAL; } info->flags = be16_to_cpu(info->flags); } else if (magic == NBD_CLIENT_MAGIC) { @@ -919,43 +917,40 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, if (*info->name) { error_setg(errp, "Server does not support non-empty export names"); - goto fail; + return -EINVAL; } if (tlscreds) { error_setg(errp, "Server does not support STARTTLS"); - goto fail; + return -EINVAL; } if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) { error_prepend(errp, "Failed to read export length: "); - goto fail; + return -EINVAL; } info->size = be64_to_cpu(info->size); if (nbd_read(ioc, &oldflags, sizeof(oldflags), errp) < 0) { error_prepend(errp, "Failed to read export flags: "); - goto fail; + return -EINVAL; } oldflags = be32_to_cpu(oldflags); if (oldflags & ~0xffff) { error_setg(errp, "Unexpected export flags %0x" PRIx32, oldflags); - goto fail; + return -EINVAL; } info->flags = oldflags; } else { error_setg(errp, "Bad magic received"); - goto fail; + return -EINVAL; } trace_nbd_receive_negotiate_size_flags(info->size, info->flags); if (zeroes && nbd_drop(ioc, 124, errp) < 0) { error_prepend(errp, "Failed to read reserved block: "); - goto fail; + return -EINVAL; } - rc = 0; - -fail: - return rc; + return 0; } #ifdef __linux__ From patchwork Fri Nov 30 22:03:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006237 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367rb1dxVz9sB7 for ; Sat, 1 Dec 2018 09:11:11 +1100 (AEDT) Received: from localhost ([::1]:34857 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr08-0002XB-LV for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:11:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56072) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtO-0004Rs-1x for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtK-0004cM-PL for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55228) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtF-00045I-QP; Fri, 30 Nov 2018 17:04:02 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0D0D91F8C5; Fri, 30 Nov 2018 22:04:01 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 699B51057073; Fri, 30 Nov 2018 22:04:00 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:39 -0600 Message-Id: <20181130220344.3350618-11-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 30 Nov 2018 22:04:01 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 10/14] nbd/client: Split handshake into two functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" An upcoming patch will add the ability for qemu-nbd to list the services provided by an NBD server. Share the common code of the TLS handshake by splitting the initial exchange into a separate function, leaving only the export handling in the original function. Functionally, there should be no change in behavior in this patch, although some of the code motion may be difficult to follow due to indentation changes (view with 'git diff -w' for a smaller changeset). Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- nbd/client.c | 142 ++++++++++++++++++++++++++++++----------------- nbd/trace-events | 2 +- 2 files changed, 92 insertions(+), 52 deletions(-) diff --git a/nbd/client.c b/nbd/client.c index 1ed5009642e..a282712724d 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -768,21 +768,22 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, return received || opt == NBD_OPT_LIST_META_CONTEXT; } -int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, - const char *hostname, QIOChannel **outioc, - NBDExportInfo *info, Error **errp) +/* Start the handshake to the server. After a positive return, the server + * is ready to accept additional NBD_OPT requests. + * Returns: negative errno: failure talking to server + * 0: server is oldstyle, client must still parse export size + * 1: server is newstyle, but can only accept EXPORT_NAME + * 2: server is newstyle, but lacks structured replies + * 3: server is newstyle and set up for structured replies + */ +static int nbd_start_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, + const char *hostname, QIOChannel **outioc, + bool structured_reply, bool *zeroes, + Error **errp) { uint64_t magic; - bool zeroes = true; - bool structured_reply = info->structured_reply; - bool base_allocation = info->base_allocation; - trace_nbd_receive_negotiate(tlscreds, hostname ? hostname : ""); - - assert(info->name); - trace_nbd_receive_negotiate_name(info->name); - info->structured_reply = false; - info->base_allocation = false; + trace_nbd_start_negotiate(tlscreds, hostname ? hostname : ""); if (outioc) { *outioc = NULL; @@ -827,7 +828,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, clientflags |= NBD_FLAG_C_FIXED_NEWSTYLE; } if (globalflags & NBD_FLAG_NO_ZEROES) { - zeroes = false; + *zeroes = false; clientflags |= NBD_FLAG_C_NO_ZEROES; } /* client requested flags */ @@ -849,7 +850,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, } } if (fixedNewStyle) { - int result; + int result = 0; if (structured_reply) { result = nbd_request_simple_option(ioc, @@ -858,42 +859,86 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, if (result < 0) { return -EINVAL; } - info->structured_reply = result == 1; } + return 2 + result; + } else { + return 1; + } + } else if (magic == NBD_CLIENT_MAGIC) { + if (tlscreds) { + error_setg(errp, "Server does not support STARTTLS"); + return -EINVAL; + } + return 0; + } else { + error_setg(errp, "Bad magic received"); + return -EINVAL; + } +} - if (info->structured_reply && base_allocation) { - result = nbd_negotiate_simple_meta_context( +/* Connect to server, complete negotiation, and move into transmission phase. + * Returns: negative errno: failure talking to server + * 0: server is connected + */ +int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, + const char *hostname, QIOChannel **outioc, + NBDExportInfo *info, Error **errp) +{ + int result; + bool zeroes = true; + bool base_allocation = info->base_allocation; + uint32_t oldflags; + + assert(info->name); + trace_nbd_receive_negotiate_name(info->name); + + result = nbd_start_negotiate(ioc, tlscreds, hostname, outioc, + info->structured_reply, &zeroes, errp); + + info->structured_reply = false; + info->base_allocation = false; + if (tlscreds && *outioc) { + ioc = *outioc; + } + + switch (result) { + case 3: /* newstyle, with structured replies */ + info->structured_reply = true; + if (base_allocation) { + result = nbd_negotiate_simple_meta_context( ioc, NBD_OPT_SET_META_CONTEXT, info->x_dirty_bitmap ?: "base:allocation", info, errp); - if (result < 0) { - return -EINVAL; - } - info->base_allocation = result == 1; - } - - /* Try NBD_OPT_GO first - if it works, we are done (it - * also gives us a good message if the server requires - * TLS). If it is not available, fall back to - * NBD_OPT_LIST for nicer error messages about a missing - * export, then use NBD_OPT_EXPORT_NAME. */ - result = nbd_opt_go(ioc, info, errp); if (result < 0) { return -EINVAL; } - if (result > 0) { - return 0; - } - /* Check our desired export is present in the - * server export list. Since NBD_OPT_EXPORT_NAME - * cannot return an error message, running this - * query gives us better error reporting if the - * export name is not available. - */ - if (nbd_receive_query_exports(ioc, info->name, errp) < 0) { - return -EINVAL; - } + info->base_allocation = result == 1; } + /* fall through */ + case 2: /* newstyle, try OPT_GO */ + /* Try NBD_OPT_GO first - if it works, we are done (it + * also gives us a good message if the server requires + * TLS). If it is not available, fall back to + * NBD_OPT_LIST for nicer error messages about a missing + * export, then use NBD_OPT_EXPORT_NAME. */ + result = nbd_opt_go(ioc, info, errp); + if (result < 0) { + return -EINVAL; + } + if (result > 0) { + return 0; + } + /* Check our desired export is present in the + * server export list. Since NBD_OPT_EXPORT_NAME + * cannot return an error message, running this + * query gives us better error reporting if the + * export name is not available. + */ + if (nbd_receive_query_exports(ioc, info->name, errp) < 0) { + return -EINVAL; + } + /* fall through */ + case 1: /* newstyle, but limited to EXPORT_NAME */ /* write the export name request */ if (nbd_send_option_request(ioc, NBD_OPT_EXPORT_NAME, -1, info->name, errp) < 0) { @@ -912,17 +957,12 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, return -EINVAL; } info->flags = be16_to_cpu(info->flags); - } else if (magic == NBD_CLIENT_MAGIC) { - uint32_t oldflags; - + break; + case 0: /* oldstyle, parse length and flags */ if (*info->name) { error_setg(errp, "Server does not support non-empty export names"); return -EINVAL; } - if (tlscreds) { - error_setg(errp, "Server does not support STARTTLS"); - return -EINVAL; - } if (nbd_read(ioc, &info->size, sizeof(info->size), errp) < 0) { error_prepend(errp, "Failed to read export length: "); @@ -940,9 +980,9 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, return -EINVAL; } info->flags = oldflags; - } else { - error_setg(errp, "Bad magic received"); - return -EINVAL; + break; + default: + return result; } trace_nbd_receive_negotiate_size_flags(info->size, info->flags); diff --git a/nbd/trace-events b/nbd/trace-events index 5d0d202fad2..570b04997ff 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -12,7 +12,7 @@ nbd_receive_starttls_new_client(void) "Setting up TLS" nbd_receive_starttls_tls_handshake(void) "Starting TLS handshake" nbd_opt_meta_request(const char *opt, const char *context, const char *export) "Requesting to %s %s for export %s" nbd_opt_meta_reply(const char *context, uint32_t id) "Received mapping of context %s to id %" PRIu32 -nbd_receive_negotiate(void *tlscreds, const char *hostname) "Receiving negotiation tlscreds=%p hostname=%s" +nbd_start_negotiate(void *tlscreds, const char *hostname) "Receiving negotiation tlscreds=%p hostname=%s" nbd_receive_negotiate_magic(uint64_t magic) "Magic is 0x%" PRIx64 nbd_receive_negotiate_server_flags(uint32_t globalflags) "Global flags are 0x%" PRIx32 nbd_receive_negotiate_name(const char *name) "Requesting NBD export name \"%s\"" From patchwork Fri Nov 30 22:03:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006243 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367zv5WL5z9sDN for ; Sat, 1 Dec 2018 09:17:31 +1100 (AEDT) Received: from localhost ([::1]:34893 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr6H-0000S0-7z for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:17:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56147) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtR-0004W6-Ec for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtP-00058u-QW for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:13 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42662) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtJ-0004PH-6S; Fri, 30 Nov 2018 17:04:05 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5F73B3001FD2; Fri, 30 Nov 2018 22:04:04 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 290AE1057073; Fri, 30 Nov 2018 22:04:01 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:40 -0600 Message-Id: <20181130220344.3350618-12-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Fri, 30 Nov 2018 22:04:04 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 11/14] nbd/client: Add nbd_receive_export_list() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Max Reitz , nsoffer@redhat.com, jsnow@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" We want to be able to detect whether a given qemu NBD server is exposing the right export(s) and dirty bitmaps, at least for regression testing. We could use 'nbd-client -l' from the upstream NBD project to list exports, but it's annoying to rely on out-of-tree binaries; furthermore, nbd-client doesn't necessarily know about all of the qemu NBD extensions. Thus, we plan on adding a new mode to qemu-nbd that merely sniffs all possible information from the server during handshake phase, then disconnects and dumps the information. This patch adds the low-level client code for grabbing the list of exports. It benefits from the recent refactoring patches, as well as a minor tweak of changing nbd_opt_go() to nbd_opt_info_go(), in order to share as much code as possible when it comes to doing validation of server replies. The resulting information is stored in an array of NBDExportInfo which has been expanded to hold more members, along with a convenience function for freeing the list. Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones --- include/block/nbd.h | 15 +++- nbd/client.c | 166 ++++++++++++++++++++++++++++++++++++++++++-- nbd/trace-events | 2 +- 3 files changed, 174 insertions(+), 9 deletions(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index 65feff8ba96..74d006b8d62 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -262,6 +262,9 @@ struct NBDExportInfo { /* Set by client before nbd_receive_negotiate() */ bool request_sizes; char *x_dirty_bitmap; + + /* Set by client before nbd_receive_negotiate(), or by server results + * during nbd_receive_export_list() */ char *name; /* must be non-NULL */ /* In-out fields, set by client before nbd_receive_negotiate() and @@ -269,7 +272,8 @@ struct NBDExportInfo { bool structured_reply; bool base_allocation; /* base:allocation context for NBD_CMD_BLOCK_STATUS */ - /* Set by server results during nbd_receive_negotiate() */ + /* Set by server results during nbd_receive_negotiate() and + * nbd_receive_export_list() */ uint64_t size; uint16_t flags; uint32_t min_block; @@ -277,12 +281,21 @@ struct NBDExportInfo { uint32_t max_block; uint32_t meta_base_allocation_id; + + /* Set by server results during nbd_receive_export_list() */ + char *description; + int n_contexts; + char **contexts; }; typedef struct NBDExportInfo NBDExportInfo; int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, const char *hostname, QIOChannel **outioc, NBDExportInfo *info, Error **errp); +void nbd_free_export_list(NBDExportInfo *info, int count); +int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, + const char *hostname, NBDExportInfo **info, + Error **errp); int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info, Error **errp); int nbd_send_request(QIOChannel *ioc, NBDRequest *request); diff --git a/nbd/client.c b/nbd/client.c index a282712724d..6292de560ee 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -351,7 +351,8 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match, * used, 0 if NBD_OPT_GO is unsupported (fall back to NBD_OPT_LIST and * NBD_OPT_EXPORT_NAME in that case), and > 0 if the export is good to * go (with the rest of @info populated). */ -static int nbd_opt_go(QIOChannel *ioc, NBDExportInfo *info, Error **errp) +static int nbd_opt_info_go(QIOChannel *ioc, uint32_t opt, + NBDExportInfo *info, Error **errp) { NBDOptionReply reply; uint32_t len = strlen(info->name); @@ -364,7 +365,8 @@ static int nbd_opt_go(QIOChannel *ioc, NBDExportInfo *info, Error **errp) * flags still 0 is a witness of a broken server. */ info->flags = 0; - trace_nbd_opt_go_start(info->name); + assert(opt == NBD_OPT_GO || opt == NBD_OPT_INFO); + trace_nbd_opt_go_start(nbd_opt_lookup(opt), info->name); buf = g_malloc(4 + len + 2 + 2 * info->request_sizes + 1); stl_be_p(buf, len); memcpy(buf + 4, info->name, len); @@ -373,7 +375,7 @@ static int nbd_opt_go(QIOChannel *ioc, NBDExportInfo *info, Error **errp) if (info->request_sizes) { stw_be_p(buf + 4 + len + 2, NBD_INFO_BLOCK_SIZE); } - error = nbd_send_option_request(ioc, NBD_OPT_GO, + error = nbd_send_option_request(ioc, opt, 4 + len + 2 + 2 * info->request_sizes, buf, errp); g_free(buf); @@ -382,7 +384,7 @@ static int nbd_opt_go(QIOChannel *ioc, NBDExportInfo *info, Error **errp) } while (1) { - if (nbd_receive_option_reply(ioc, NBD_OPT_GO, &reply, errp) < 0) { + if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) { return -1; } error = nbd_handle_reply_err(ioc, &reply, errp); @@ -733,8 +735,12 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, nbd_send_opt_abort(ioc); return -1; } + g_free(name); + } else { + info->contexts = g_renew(char *, info->contexts, + ++info->n_contexts); + info->contexts[info->n_contexts - 1] = name; } - g_free(name); received = true; /* receive NBD_REP_ACK */ @@ -828,7 +834,9 @@ static int nbd_start_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, clientflags |= NBD_FLAG_C_FIXED_NEWSTYLE; } if (globalflags & NBD_FLAG_NO_ZEROES) { - *zeroes = false; + if (zeroes) { + *zeroes = false; + } clientflags |= NBD_FLAG_C_NO_ZEROES; } /* client requested flags */ @@ -921,7 +929,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, * TLS). If it is not available, fall back to * NBD_OPT_LIST for nicer error messages about a missing * export, then use NBD_OPT_EXPORT_NAME. */ - result = nbd_opt_go(ioc, info, errp); + result = nbd_opt_info_go(ioc, NBD_OPT_GO, info, errp); if (result < 0) { return -EINVAL; } @@ -993,6 +1001,150 @@ int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, return 0; } +/* Clean up result of nbd_receive_export_list */ +void nbd_free_export_list(NBDExportInfo *info, int count) +{ + int i, j; + + for (i = 0; info && i < count; i++) { + free(info[i].name); + free(info[i].description); + for (j = 0; j < info[i].n_contexts; j++) { + free(info[i].contexts[j]); + } + free(info[i].contexts); + } + free(info); +} + +/* Query details about a server's exports, then disconnect without + * going into transmission phase. Return a count of the exports listed + * in @info by the server, or -1 on error. Caller must free @info. */ +int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds, + const char *hostname, NBDExportInfo **info, + Error **errp) +{ + int result; + int count = 0; + int i; + int rc; + int ret = -1; + NBDExportInfo *array = NULL; + uint32_t oldflags; + QIOChannel *sioc = NULL; + bool try_context = true; + + *info = NULL; + result = nbd_start_negotiate(ioc, tlscreds, hostname, &sioc, true, NULL, + errp); + if (tlscreds && sioc) { + ioc = sioc; + } + + switch (result) { + case 2: + /* meta contexts are only useful with structured reply */ + try_context = false; + /* fall through */ + case 3: + /* newstyle - use NBD_OPT_LIST to populate array, then try + * NBD_OPT_INFO on each array member. If structured replies + * are enabled, also try NBD_OPT_LIST_META_CONTEXT. */ + if (nbd_send_option_request(ioc, NBD_OPT_LIST, 0, NULL, errp) < 0) { + goto out; + } + while (1) { + char *name; + char *desc; + + rc = nbd_receive_list(ioc, NULL, NULL, &name, &desc, errp); + if (rc < 0) { + goto out; + } else if (rc == 0) { + break; + } + array = g_renew(NBDExportInfo, array, ++count); + memset(&array[count - 1], 0, sizeof(*array)); + array[count - 1].name = name; + array[count - 1].description = desc; + array[count - 1].structured_reply = result == 3; + } + + for (i = 0; i < count; i++) { + array[i].request_sizes = true; + rc = nbd_opt_info_go(ioc, NBD_OPT_INFO, &array[i], errp); + if (rc < 0) { + goto out; + } else if (rc == 0) { + /* Pointless to try rest of loop. If OPT_INFO doesn't work, + * it's unlikely that meta contexts work either */ + break; + } + + if (try_context) { + rc = nbd_negotiate_simple_meta_context( + ioc, NBD_OPT_LIST_META_CONTEXT, NULL, &array[i], errp); + if (rc < 0) { + goto out; + } else if (rc == 0) { + try_context = false; + } + } + } + + /* Send NBD_OPT_ABORT as a courtesy before hanging up */ + nbd_send_opt_abort(ioc); + break; + case 1: /* newstyle, but limited to EXPORT_NAME */ + error_setg(errp, "Server does not support export lists"); + /* We can't even send NBD_OPT_ABORT, so merely hang up */ + goto out; + case 0: /* oldstyle, parse length and flags */ + array = g_new0(NBDExportInfo, 1); + array->name = g_strdup(""); + count = 1; + + if (nbd_read(ioc, &array->size, sizeof(array->size), errp) < 0) { + error_prepend(errp, "Failed to read export length: "); + goto out; + } + array->size = be64_to_cpu(array->size); + + if (nbd_read(ioc, &oldflags, sizeof(oldflags), errp) < 0) { + error_prepend(errp, "Failed to read export flags: "); + goto out; + } + oldflags = be32_to_cpu(oldflags); + if (oldflags & ~0xffff) { + error_setg(errp, "Unexpected export flags %0x" PRIx32, oldflags); + goto out; + } + array->flags = oldflags; + + /* Send NBD_CMD_DISC as a courtesy to the server, but ignore all + * errors now that we have the information we wanted. */ + if (nbd_drop(ioc, 124, NULL) == 0) { + NBDRequest request = { .type = NBD_CMD_DISC }; + + nbd_send_request(ioc, &request); + } + break; + default: + goto out; + } + + *info = array; + array = NULL; + ret = count; + + out: + qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); + qio_channel_close(ioc, NULL); + object_unref(OBJECT(sioc)); + nbd_free_export_list(array, count); + return ret; +} + #ifdef __linux__ int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info, Error **errp) diff --git a/nbd/trace-events b/nbd/trace-events index 570b04997ff..2cf83ebed15 100644 --- a/nbd/trace-events +++ b/nbd/trace-events @@ -2,7 +2,7 @@ nbd_send_option_request(uint32_t opt, const char *name, uint32_t len) "Sending option request %" PRIu32" (%s), len %" PRIu32 nbd_receive_option_reply(uint32_t option, const char *optname, uint32_t type, const char *typename, uint32_t length) "Received option reply %" PRIu32" (%s), type %" PRIu32" (%s), len %" PRIu32 nbd_reply_err_unsup(uint32_t option, const char *name) "server doesn't understand request %" PRIu32 " (%s), attempting fallback" -nbd_opt_go_start(const char *name) "Attempting NBD_OPT_GO for export '%s'" +nbd_opt_go_start(const char *opt, const char *name) "Attempting %s for export '%s'" nbd_opt_go_success(void) "Export is good to go" nbd_opt_go_info_unknown(int info, const char *name) "Ignoring unknown info %d (%s)" nbd_opt_go_info_block_size(uint32_t minimum, uint32_t preferred, uint32_t maximum) "Block sizes are 0x%" PRIx32 ", 0x%" PRIx32 ", 0x%" PRIx32 From patchwork Fri Nov 30 22:03:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006236 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367qy39Knz9sDP for ; Sat, 1 Dec 2018 09:10:38 +1100 (AEDT) Received: from localhost ([::1]:34849 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqzb-00022v-U6 for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:10:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56121) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtQ-0004Um-5a for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtP-00053y-9N for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:58950) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtJ-0004SK-Sk; Fri, 30 Nov 2018 17:04:06 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 16C5699D2D; Fri, 30 Nov 2018 22:04:05 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7D34C105B1FA; Fri, 30 Nov 2018 22:04:04 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:41 -0600 Message-Id: <20181130220344.3350618-13-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 30 Nov 2018 22:04:05 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 12/14] nbd/client: Work around 3.0 bug for listing meta contexts X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Commit 3d068aff forgot to advertise available qemu: contexts when the client requests a list with 0 queries. Furthermore, 3.0 shipped with a qemu-img hack of x-dirty-bitmap (commit 216ee365) that _silently_ acts as though the entire image is clean if a requested bitmap is not present. Both bugs have been recently fixed to give full output from the start, and to refuse a connection if a requested x-dirty-bitmap was not found. Still, it is likely that there will be users that have to work with a mix of old and new qemu versions, depending on which features get backported where, at which point being able to rely on 'qemu-img --list' output to know for sure whether a given NBD export has the desired dirty bitmap is much nicer than blindly connecting and risking that the entire image may appear clean. We can make our --list code smart enough to work around buggy servers by tracking whether we've seen any qemu: replies in the original 0-query list; if not, recurse to a single query on "qemu:" (which may still have no replies, but then we know for sure we didn't trip up on the server bug). Signed-off-by: Eric Blake --- Done as a separate patch to make it easier to revert when we no longer care about 3.0 servers --- nbd/client.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nbd/client.c b/nbd/client.c index 6292de560ee..928ecabd420 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -21,6 +21,7 @@ #include "qapi/error.h" #include "trace.h" #include "nbd-internal.h" +#include "qemu/cutils.h" /* Definitions for opaque data types */ @@ -736,12 +737,13 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, return -1; } g_free(name); + received = true; } else { info->contexts = g_renew(char *, info->contexts, ++info->n_contexts); info->contexts[info->n_contexts - 1] = name; + received |= strstart(name, "qemu:", NULL); } - received = true; /* receive NBD_REP_ACK */ if (nbd_receive_option_reply(ioc, opt, &reply, errp) < 0) { @@ -771,6 +773,13 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc, info->meta_base_allocation_id = received_id; } + /* Recurse to work around qemu 3.0 bug - the server forgot to send + * "qemu:" replies to 0 queries. */ + if (!context && !received) { + return nbd_negotiate_simple_meta_context(ioc, opt, "qemu:", info, + errp); + } + return received || opt == NBD_OPT_LIST_META_CONTEXT; } From patchwork Fri Nov 30 22:03:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006244 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43680v2vtRz9sB7 for ; Sat, 1 Dec 2018 09:18:23 +1100 (AEDT) Received: from localhost ([::1]:34896 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr76-00011L-TQ for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:18:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56152) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtR-0004WL-OJ for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtQ-0005CW-5h for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:13 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40508) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtK-0004Xc-Fw; Fri, 30 Nov 2018 17:04:06 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C20C630842AB; Fri, 30 Nov 2018 22:04:05 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id 345F11057075; Fri, 30 Nov 2018 22:04:05 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:42 -0600 Message-Id: <20181130220344.3350618-14-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.40]); Fri, 30 Nov 2018 22:04:05 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 13/14] qemu-nbd: Add --list option X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: nsoffer@redhat.com, vsementsov@virtuozzo.com, jsnow@redhat.com, rjones@redhat.com, qemu-block@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" We want to be able to detect whether a given qemu NBD server is exposing the right export(s) and dirty bitmaps, at least for regression testing. We could use 'nbd-client -l' from the upstream NBD project to list exports, but it's annoying to rely on out-of-tree binaries; furthermore, nbd-client doesn't necessarily know about all of the qemu NBD extensions. Thus, we plan on adding a new mode to qemu-nbd that merely sniffs all possible information from the server during handshake phase, then disconnects and dumps the information. This patch actually implements --list/-L, while reusing other options such as --tls-creds for now designating how to connect as the client (rather than their non-list usage of how to operate as the server). I debated about adding this functionality to something akin to 'qemu-img info' - but that tool does not readily lend itself to connecting to an arbitrary NBD server without also tying to a specific export (I may, however, still add ImageInfoSpecificNBD for reporting the bitmaps available when connecting to a single export). And, while it may feel a bit odd that normally qemu-nbd is a server but 'qemu-nbd -L' is a client, we are not really making the qemu-nbd binary that much larger, because 'qemu-nbd -c' has to operate as both server and client simultaneously across two threads when feeding the kernel module for /dev/nbdN access. Sample output: $ qemu-nbd -L exports available: 1 export: '' size: 65536 flags: 0x4ed ( flush fua trim zeroes df cache ) min block: 512 opt block: 4096 max block: 33554432 available meta contexts: 1 base:allocation Signed-off-by: Eric Blake --- qemu-nbd.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 141 insertions(+), 12 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index c57053a0795..e19a841b869 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -76,6 +76,7 @@ static void usage(const char *name) { (printf) ( "Usage: %s [OPTIONS] FILE\n" +" or: %s -L [OPTIONS]\n" "QEMU Disk Network Block Device Server\n" "\n" " -h, --help display this help and exit\n" @@ -97,6 +98,7 @@ static void usage(const char *name) " -P, --partition=NUM only expose partition NUM\n" "\n" "General purpose options:\n" +" -L, --list list NBD exports visible to client\n" " --object type,id=ID,... define an object such as 'secret' for providing\n" " passwords and/or encryption keys\n" " --tls-creds=ID use id of an earlier --object to provide TLS\n" @@ -130,7 +132,7 @@ static void usage(const char *name) " --image-opts treat FILE as a full set of image options\n" "\n" QEMU_HELP_BOTTOM "\n" - , name, NBD_DEFAULT_PORT, "DEVICE"); + , name, name, NBD_DEFAULT_PORT, "DEVICE"); } static void version(const char *name) @@ -242,6 +244,92 @@ static void termsig_handler(int signum) } +static int qemu_nbd_client_list(SocketAddress *saddr, QCryptoTLSCreds *tls, + const char *hostname) +{ + int ret = EXIT_FAILURE; + int rc; + Error *err = NULL; + QIOChannelSocket *sioc; + NBDExportInfo *list; + int i, j; + + sioc = qio_channel_socket_new(); + if (qio_channel_socket_connect_sync(sioc, saddr, &err) < 0) { + error_report_err(err); + goto out; + } + rc = nbd_receive_export_list(QIO_CHANNEL(sioc), tls, hostname, &list, + &err); + if (rc < 0) { + if (err) { + error_report_err(err); + } + goto out_socket; + } + printf("exports available: %d\n", rc); + for (i = 0; i < rc; i++) { + printf(" export: '%s'\n", list[i].name); + if (list[i].description && *list[i].description) { + printf(" description: %s\n", list[i].description); + } + if (list[i].flags & NBD_FLAG_HAS_FLAGS) { + printf(" size: %" PRIu64 "\n", list[i].size); + printf(" flags: 0x%x (", list[i].flags); + if (list[i].flags & NBD_FLAG_READ_ONLY) { + printf(" readonly"); + } + if (list[i].flags & NBD_FLAG_SEND_FLUSH) { + printf(" flush"); + } + if (list[i].flags & NBD_FLAG_SEND_FUA) { + printf(" fua"); + } + if (list[i].flags & NBD_FLAG_ROTATIONAL) { + printf(" rotational"); + } + if (list[i].flags & NBD_FLAG_SEND_TRIM) { + printf(" trim"); + } + if (list[i].flags & NBD_FLAG_SEND_WRITE_ZEROES) { + printf(" zeroes"); + } + if (list[i].flags & NBD_FLAG_SEND_DF) { + printf(" df"); + } + if (list[i].flags & NBD_FLAG_CAN_MULTI_CONN) { + printf(" multi"); + } + if (list[i].flags & NBD_FLAG_SEND_RESIZE) { + printf(" resize"); + } + if (list[i].flags & NBD_FLAG_SEND_CACHE) { + printf(" cache"); + } + printf(" )\n"); + } + if (list[i].min_block) { + printf(" min block: %u\n", list[i].min_block); + printf(" opt block: %u\n", list[i].opt_block); + printf(" max block: %u\n", list[i].max_block); + } + if (list[i].n_contexts) { + printf(" available meta contexts: %d\n", list[i].n_contexts); + for (j = 0; j < list[i].n_contexts; j++) { + printf(" %s\n", list[i].contexts[j]); + } + } + } + nbd_free_export_list(list, rc); + + ret = EXIT_SUCCESS; + out_socket: + object_unref(OBJECT(sioc)); + out: + return ret; +} + + #if HAVE_NBD_DEVICE static void *show_parts(void *arg) { @@ -424,7 +512,8 @@ static QemuOptsList qemu_object_opts = { -static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp) +static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, bool list, + Error **errp) { Object *obj; QCryptoTLSCreds *creds; @@ -444,10 +533,18 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp) return NULL; } - if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { - error_setg(errp, - "Expecting TLS credentials with a server endpoint"); - return NULL; + if (list) { + if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) { + error_setg(errp, + "Expecting TLS credentials with a client endpoint"); + return NULL; + } + } else { + if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { + error_setg(errp, + "Expecting TLS credentials with a server endpoint"); + return NULL; + } } object_ref(obj); return creds; @@ -470,7 +567,8 @@ static void setup_address_and_port(const char **address, const char **port) static const char *socket_activation_validate_opts(const char *device, const char *sockpath, const char *address, - const char *port) + const char *port, + bool list) { if (device != NULL) { return "NBD device can't be set when using socket activation"; @@ -488,6 +586,10 @@ static const char *socket_activation_validate_opts(const char *device, return "TCP port number can't be set when using socket activation"; } + if (list) { + return "List mode is incompatible with socket activation"; + } + return NULL; } @@ -511,7 +613,7 @@ int main(int argc, char **argv) off_t fd_size; QemuOpts *sn_opts = NULL; const char *sn_id_or_name = NULL; - const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:x:T:D:"; + const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:x:T:D:L"; struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, @@ -523,6 +625,7 @@ int main(int argc, char **argv) { "partition", required_argument, NULL, 'P' }, { "connect", required_argument, NULL, 'c' }, { "disconnect", no_argument, NULL, 'd' }, + { "list", no_argument, NULL, 'L' }, { "snapshot", no_argument, NULL, 's' }, { "load-snapshot", required_argument, NULL, 'l' }, { "nocache", no_argument, NULL, 'n' }, @@ -558,13 +661,14 @@ int main(int argc, char **argv) Error *local_err = NULL; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; QDict *options = NULL; - const char *export_name = ""; /* Default export name */ + const char *export_name = NULL; const char *export_description = NULL; const char *tlscredsid = NULL; bool imageOpts = false; bool writethrough = true; char *trace_file = NULL; bool fork_process = false; + bool list = false; int old_stderr = -1; unsigned socket_activation; @@ -764,13 +868,32 @@ int main(int argc, char **argv) case QEMU_NBD_OPT_FORK: fork_process = true; break; + case 'L': + list = true; + break; } } - if ((argc - optind) != 1) { + if (list) { + if (argc != optind) { + error_report("List mode is incompatible with a file name"); + exit(EXIT_FAILURE); + } + if (export_name || export_description || dev_offset || partition || + device || disconnect || fmt || sn_id_or_name) { + error_report("List mode is incompatible with per-device settings"); + exit(EXIT_FAILURE); + } + if (fork_process) { + error_report("List mode is incompatible with forking"); + exit(EXIT_FAILURE); + } + } else if ((argc - optind) != 1) { error_report("Invalid number of arguments"); error_printf("Try `%s --help' for more information.\n", argv[0]); exit(EXIT_FAILURE); + } else if (!export_name) { + export_name = ""; } qemu_opts_foreach(&qemu_object_opts, @@ -789,7 +912,8 @@ int main(int argc, char **argv) } else { /* Using socket activation - check user didn't use -p etc. */ const char *err_msg = socket_activation_validate_opts(device, sockpath, - bindto, port); + bindto, port, + list); if (err_msg != NULL) { error_report("%s", err_msg); exit(EXIT_FAILURE); @@ -812,7 +936,7 @@ int main(int argc, char **argv) error_report("TLS is not supported with a host device"); exit(EXIT_FAILURE); } - tlscreds = nbd_get_tls_creds(tlscredsid, &local_err); + tlscreds = nbd_get_tls_creds(tlscredsid, list, &local_err); if (local_err) { error_report("Failed to get TLS creds %s", error_get_pretty(local_err)); @@ -820,6 +944,11 @@ int main(int argc, char **argv) } } + if (list) { + saddr = nbd_build_socket_address(sockpath, bindto, port); + return qemu_nbd_client_list(saddr, tlscreds, bindto); + } + if (disconnect) { #if HAVE_NBD_DEVICE int nbdfd = open(argv[optind], O_RDWR); From patchwork Fri Nov 30 22:03:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 1006241 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4367wz14XWz9sB7 for ; Sat, 1 Dec 2018 09:14:59 +1100 (AEDT) Received: from localhost ([::1]:34879 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSr3o-00072q-Lw for incoming@patchwork.ozlabs.org; Fri, 30 Nov 2018 17:14:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56127) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gSqtQ-0004VK-Kt for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gSqtP-00056H-GL for qemu-devel@nongnu.org; Fri, 30 Nov 2018 17:04:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40346) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gSqtL-0004cX-AT; Fri, 30 Nov 2018 17:04:07 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A6A0C3082E51; Fri, 30 Nov 2018 22:04:06 +0000 (UTC) Received: from red.redhat.com (ovpn-117-105.phx2.redhat.com [10.3.117.105]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC93E1057073; Fri, 30 Nov 2018 22:04:05 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 30 Nov 2018 16:03:43 -0600 Message-Id: <20181130220344.3350618-15-eblake@redhat.com> In-Reply-To: <20181130220344.3350618-1-eblake@redhat.com> References: <20181130220344.3350618-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Fri, 30 Nov 2018 22:04:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 14/14] iotests: Enhance 223, 233 to cover 'qemu-nbd --list' X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , vsementsov@virtuozzo.com, qemu-block@nongnu.org, rjones@redhat.com, Max Reitz , nsoffer@redhat.com, jsnow@redhat.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Any good new feature deserves some regression testing :) Coverage includes: - 223: what happens when there are 0 or more than 1 export, proof that we can see multiple contexts including qemu:dirty-bitmap - 233: proof that we can list over TLS, and that mix-and-match of plain/TLS listings sanely Signed-off-by: Eric Blake Reviewed-by: Richard W.M. Jones Tested-by: Richard W.M. Jones Reviewed-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/223 | 2 ++ tests/qemu-iotests/223.out | 20 ++++++++++++++++++++ tests/qemu-iotests/233 | 10 ++++++++++ tests/qemu-iotests/233.out | 15 +++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223 index 397b865d347..e64747a9a61 100755 --- a/tests/qemu-iotests/223 +++ b/tests/qemu-iotests/223 @@ -119,6 +119,7 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"x-block-dirty-bitmap-disable", _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-start", "arguments":{"addr":{"type":"unix", "data":{"path":"'"$TEST_DIR/nbd"'"}}}}' "return" +$QEMU_NBD_PROG -L -k "$TEST_DIR/nbd" _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add", "arguments":{"device":"n"}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap", @@ -127,6 +128,7 @@ _send_qemu_cmd $QEMU_HANDLE '{"execute":"nbd-server-add", "arguments":{"device":"n", "name":"n2"}}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"x-nbd-server-add-bitmap", "arguments":{"name":"n2", "bitmap":"b2"}}' "return" +$QEMU_NBD_PROG -L -k "$TEST_DIR/nbd" echo echo "=== Contrast normal status to large granularity dirty-bitmap ===" diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index de417477de0..3342bff3447 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -29,10 +29,30 @@ wrote 2097152/2097152 bytes at offset 2097152 {"return": {}} {"return": {}} {"return": {}} +exports available: 0 {"return": {}} {"return": {}} {"return": {}} {"return": {}} +exports available: 2 + export: 'n' + size: 4194304 + flags: 0x4ef ( readonly flush fua trim zeroes df cache ) + min block: 512 + opt block: 4096 + max block: 33554432 + available meta contexts: 2 + base:allocation + qemu:dirty-bitmap:b + export: 'n2' + size: 4194304 + flags: 0x4ef ( readonly flush fua trim zeroes df cache ) + min block: 512 + opt block: 4096 + max block: 33554432 + available meta contexts: 2 + base:allocation + qemu:dirty-bitmap:b2 === Contrast normal status to large granularity dirty-bitmap === diff --git a/tests/qemu-iotests/233 b/tests/qemu-iotests/233 index 1814efe3333..5d694d9d242 100755 --- a/tests/qemu-iotests/233 +++ b/tests/qemu-iotests/233 @@ -72,6 +72,9 @@ $QEMU_IMG info --image-opts \ --object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \ driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \ 2>&1 | sed "s/$nbd_tcp_port/PORT/g" +$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port \ + --object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \ + --tls-creds=tls0 nbd_server_stop @@ -84,6 +87,7 @@ nbd_server_start_tcp_socket \ -f $IMGFMT "$TEST_IMG" $QEMU_IMG info nbd://localhost:$nbd_tcp_port 2>&1 | sed "s/$nbd_tcp_port/PORT/g" +$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port echo echo "== check TLS works ==" @@ -91,6 +95,9 @@ $QEMU_IMG info --image-opts \ --object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \ driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \ 2>&1 | sed "s/$nbd_tcp_port/PORT/g" +$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port \ + --object tls-creds-x509,dir=${tls_dir}/client1,endpoint=client,id=tls0 \ + --tls-creds=tls0 echo echo "== check TLS with different CA fails ==" @@ -98,6 +105,9 @@ $QEMU_IMG info --image-opts \ --object tls-creds-x509,dir=${tls_dir}/client2,endpoint=client,id=tls0 \ driver=nbd,host=$nbd_tcp_addr,port=$nbd_tcp_port,tls-creds=tls0 \ 2>&1 | sed "s/$nbd_tcp_port/PORT/g" +$QEMU_NBD_PROG -L -b $nbd_tcp_addr -p $nbd_tcp_port \ + --object tls-creds-x509,dir=${tls_dir}/client2,endpoint=client,id=tls0 \ + --tls-creds=tls0 echo echo "== perform I/O over TLS ==" diff --git a/tests/qemu-iotests/233.out b/tests/qemu-iotests/233.out index 5f416721b03..ab669488669 100644 --- a/tests/qemu-iotests/233.out +++ b/tests/qemu-iotests/233.out @@ -15,20 +15,35 @@ wrote 1048576/1048576 bytes at offset 1048576 == check TLS client to plain server fails == qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Denied by server for option 5 (starttls) server reported: TLS not configured +qemu-nbd: Denied by server for option 5 (starttls) +server reported: TLS not configured == check plain client to TLS server fails == qemu-img: Could not open 'nbd://localhost:PORT': TLS negotiation required before option 8 (structured reply) server reported: Option 0x8 not permitted before TLS +qemu-nbd: TLS negotiation required before option 8 (structured reply) +server reported: Option 0x8 not permitted before TLS == check TLS works == image: nbd://127.0.0.1:PORT file format: nbd virtual size: 64M (67108864 bytes) disk size: unavailable +exports available: 1 + export: '' + size: 67108864 + flags: 0x4ed ( flush fua trim zeroes df cache ) + min block: 512 + opt block: 4096 + max block: 33554432 + available meta contexts: 1 + base:allocation == check TLS with different CA fails == qemu-nbd: option negotiation failed: Verify failed: No certificate was found. qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': The certificate hasn't got a known issuer +qemu-nbd: option negotiation failed: Verify failed: No certificate was found. +qemu-nbd: The certificate hasn't got a known issuer == perform I/O over TLS == read 1048576/1048576 bytes at offset 1048576