From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603778406729.7894122158691; Tue, 5 Sep 2017 02:29:38 -0700 (PDT) Received: from localhost ([::1]:57691 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpAAr-0006un-Ak for importer@patchew.org; Tue, 05 Sep 2017 05:29:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41176) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4E-0001B3-JB for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA44-0002g2-RT for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52640) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA44-0002fU-Lw for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:36 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A1017BDEF; Tue, 5 Sep 2017 09:22:35 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id DAD3060BF1; Tue, 5 Sep 2017 09:22:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A1017BDEF Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:22 +0100 Message-Id: <20170905092230.8243-2-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 05 Sep 2017 09:22:35 +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] [PULL v1 1/9] io: fix temp directory used by test-io-channel-tls test 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: Peter Maydell Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The test-io-channel-tls test was mistakenly using two of the same directories as test-crypto-tlssession. This causes a sporadic failure when using make -j$BIGNUM. Reported-by: Dr. David Alan Gilbert Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Daniel P. Berrange --- tests/test-io-channel-tls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c index 8eaa208e1b..ff96877323 100644 --- a/tests/test-io-channel-tls.c +++ b/tests/test-io-channel-tls.c @@ -127,8 +127,8 @@ static void test_io_channel_tls(const void *opaque) /* We'll use this for our fake client-server connection */ g_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, channel) =3D=3D 0); =20 -#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/" -#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/" +#define CLIENT_CERT_DIR "tests/test-io-channel-tls-client/" +#define SERVER_CERT_DIR "tests/test-io-channel-tls-server/" mkdir(CLIENT_CERT_DIR, 0700); mkdir(SERVER_CERT_DIR, 0700); =20 --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 150460360094295.00079179036345; Tue, 5 Sep 2017 02:26:40 -0700 (PDT) Received: from localhost ([::1]:57679 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA7z-0004MB-Ql for importer@patchew.org; Tue, 05 Sep 2017 05:26:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41219) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4H-0001De-5Z for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA46-0002gv-AS for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45188) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA46-0002gQ-1M for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:38 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 12A124A6F1; Tue, 5 Sep 2017 09:22:37 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1F4260BF1; Tue, 5 Sep 2017 09:22:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 12A124A6F1 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:23 +0100 Message-Id: <20170905092230.8243-3-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 05 Sep 2017 09:22:37 +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] [PULL v1 2/9] tests: Add test-listen - a stress test for QEMU socket listen 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: Peter Maydell , Knut Omang Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Knut Omang There's a potential race condition between multiple bind()'s attempting to bind to the same port, which occasionally allows more than one bind to succeed against the same port. When a subsequent listen() call is made with the same socket only one will succeed. The current QEMU code does however not take this situation into account and the listen will cause the code to break out and fail even when there are actually available ports to use. This test exposes two subtests: /socket/listen-serial /socket/listen-compete The "compete" subtest creates a number of threads and have them all trying = to bind to the same port with a large enough offset input to allow all threads to get it's own port. The "serial" subtest just does the same, except in series in a single thread. The serial version passes, probably in most versions of QEMU. The parallel version exposes the problem in a relatively reliable way, eg. it fails a majority of times, but not with a 100% rate, occasional passes can be seen. Nevertheless this is quite good given that the bug was tricky to reproduce and has been left undetected for a while. The problem seems to be present in all versions of QEMU. The original failure scenario occurred with VNC port allocation in a traditional Xen based build, in different code but with similar functionality. Reported-by: Bhavesh Davda Signed-off-by: Knut Omang Reviewed-by: Yuval Shaia Reviewed-by: Bhavesh Davda Reviewed-by: Girish Moodalbail Signed-off-by: Daniel P. Berrange --- tests/Makefile.include | 2 + tests/test-listen.c | 253 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 255 insertions(+) create mode 100644 tests/test-listen.c diff --git a/tests/Makefile.include b/tests/Makefile.include index f08b7418f0..a231754517 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -151,6 +151,7 @@ check-unit-y +=3D tests/test-bufferiszero$(EXESUF) gcov-files-check-bufferiszero-y =3D util/bufferiszero.c check-unit-y +=3D tests/test-uuid$(EXESUF) check-unit-y +=3D tests/ptimer-test$(EXESUF) +#check-unit-y +=3D tests/test-listen$(EXESUF) gcov-files-ptimer-test-y =3D hw/core/ptimer.c check-unit-y +=3D tests/test-qapi-util$(EXESUF) gcov-files-test-qapi-util-y =3D qapi/qapi-util.c @@ -796,6 +797,7 @@ tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer= .o tests/test-qapi-util$(EXESUF): tests/test-qapi-util.o $(test-util-obj-y) tests/numa-test$(EXESUF): tests/numa-test.o tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/boot-sector.o test= s/acpi-utils.o +tests/test-listen$(EXESUF): tests/test-listen.o $(test-util-obj-y) =20 tests/migration/stress$(EXESUF): tests/migration/stress.o $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"L= INK","$(TARGET_DIR)$@") diff --git a/tests/test-listen.c b/tests/test-listen.c new file mode 100644 index 0000000000..03c4c8f03b --- /dev/null +++ b/tests/test-listen.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Author: Knut Omang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or later + * as published by the Free Software Foundation. + * + * Test parallel port listen configuration with + * dynamic port allocation + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qemu-common.h" +#include "qemu/thread.h" +#include "qemu/sockets.h" +#include "qapi/error.h" + +#define NAME_LEN 1024 +#define PORT_LEN 16 + +struct thr_info { + QemuThread thread; + int to_port; + bool ipv4; + bool ipv6; + int got_port; + int eno; + int fd; + const char *errstr; + char hostname[NAME_LEN + 1]; + char port[PORT_LEN + 1]; +}; + + +/* These two functions taken from test-io-channel-socket.c */ +static int check_bind(const char *hostname, bool *has_proto) +{ + int fd =3D -1; + struct addrinfo ai, *res =3D NULL; + int rc; + int ret =3D -1; + + memset(&ai, 0, sizeof(ai)); + ai.ai_flags =3D AI_CANONNAME | AI_ADDRCONFIG; + ai.ai_family =3D AF_UNSPEC; + ai.ai_socktype =3D SOCK_STREAM; + + /* lookup */ + rc =3D getaddrinfo(hostname, NULL, &ai, &res); + if (rc !=3D 0) { + if (rc =3D=3D EAI_ADDRFAMILY || + rc =3D=3D EAI_FAMILY) { + *has_proto =3D false; + goto done; + } + goto cleanup; + } + + fd =3D qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (fd < 0) { + goto cleanup; + } + + if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) { + if (errno =3D=3D EADDRNOTAVAIL) { + *has_proto =3D false; + goto done; + } + goto cleanup; + } + + *has_proto =3D true; + done: + ret =3D 0; + + cleanup: + if (fd !=3D -1) { + close(fd); + } + if (res) { + freeaddrinfo(res); + } + return ret; +} + +static int check_protocol_support(bool *has_ipv4, bool *has_ipv6) +{ + if (check_bind("127.0.0.1", has_ipv4) < 0) { + return -1; + } + if (check_bind("::1", has_ipv6) < 0) { + return -1; + } + + return 0; +} + +static void *listener_thread(void *arg) +{ + struct thr_info *thr =3D (struct thr_info *)arg; + SocketAddress addr =3D { + .type =3D SOCKET_ADDRESS_TYPE_INET, + .u =3D { + .inet =3D { + .host =3D thr->hostname, + .port =3D thr->port, + .has_ipv4 =3D thr->ipv4, + .ipv4 =3D thr->ipv4, + .has_ipv6 =3D thr->ipv6, + .ipv6 =3D thr->ipv6, + .has_to =3D true, + .to =3D thr->to_port, + }, + }, + }; + Error *err =3D NULL; + int fd; + + fd =3D socket_listen(&addr, &err); + if (fd < 0) { + thr->eno =3D errno; + thr->errstr =3D error_get_pretty(err); + } else { + struct sockaddr_in a; + socklen_t a_len =3D sizeof(a); + g_assert_cmpint(getsockname(fd, (struct sockaddr *)&a, &a_len), = =3D=3D, 0); + thr->got_port =3D ntohs(a.sin_port); + thr->fd =3D fd; + } + return arg; +} + + +static void listen_compete_nthr(bool threaded, int nthreads, + int start_port, int max_offset, + bool ipv4, bool ipv6) +{ + int i; + int failed_listens =3D 0; + struct thr_info *thr =3D g_new0(struct thr_info, nthreads); + int used[max_offset + 1]; + + memset(used, 0, sizeof(used)); + for (i =3D 0; i < nthreads; i++) { + snprintf(thr[i].port, PORT_LEN, "%d", start_port); + strcpy(thr[i].hostname, "localhost"); + thr[i].to_port =3D start_port + max_offset; + thr[i].ipv4 =3D ipv4; + thr[i].ipv6 =3D ipv6; + } + + for (i =3D 0; i < nthreads; i++) { + if (threaded) { + qemu_thread_create(&thr[i].thread, "listener", + listener_thread, &thr[i], + QEMU_THREAD_JOINABLE); + } else { + listener_thread(&thr[i]); + } + } + + if (threaded) { + for (i =3D 0; i < nthreads; i++) { + qemu_thread_join(&thr[i].thread); + } + } + for (i =3D 0; i < nthreads; i++) { + if (thr[i].got_port) { + closesocket(thr[i].fd); + } + } + + for (i =3D 0; i < nthreads; i++) { + if (thr[i].eno !=3D 0) { + const char *m; + g_printerr("** Failed to assign a port to thread %d (errno =3D= %d)\n", + i, thr[i].eno); + /* This is what we are interested in capturing - + * catch and report details if something unexpected happens: + */ + m =3D strstr(thr[i].errstr, "Failed to listen on socket"); + if (m !=3D NULL) { + g_assert_cmpstr(thr[i].errstr, =3D=3D, + "Failed to listen on socket: Address already in use"); + } + failed_listens++; + } else { + int assigned_port =3D thr[i].got_port; + g_assert_cmpint(assigned_port, <=3D , thr[i].to_port); + g_assert_cmpint(used[assigned_port - start_port], =3D=3D , 0); + } + } + g_assert_cmpint(failed_listens, =3D=3D, 0); + g_free(thr); +} + + +static void listen_compete_ipv4(void) +{ + listen_compete_nthr(true, 200, 5920, 300, true, false); +} + +static void listen_serial_ipv4(void) +{ + listen_compete_nthr(false, 200, 6300, 300, true, false); +} + +static void listen_compete_ipv6(void) +{ + listen_compete_nthr(true, 200, 5920, 300, true, false); +} + +static void listen_serial_ipv6(void) +{ + listen_compete_nthr(false, 200, 6300, 300, false, true); +} + +static void listen_compete_gen(void) +{ + listen_compete_nthr(true, 200, 5920, 300, true, true); +} + +static void listen_serial_gen(void) +{ + listen_compete_nthr(false, 200, 6300, 300, true, true); +} + + +int main(int argc, char **argv) +{ + bool has_ipv4, has_ipv6; + g_test_init(&argc, &argv, NULL); + + if (check_protocol_support(&has_ipv4, &has_ipv6) < 0) { + return 1; + } + + if (has_ipv4) { + g_test_add_func("/socket/listen-serial/ipv4", listen_serial_ipv4); + g_test_add_func("/socket/listen-compete/ipv4", listen_compete_ipv4= ); + } + if (has_ipv6) { + g_test_add_func("/socket/listen-serial/ipv6", listen_serial_ipv6); + g_test_add_func("/socket/listen-compete/ipv6", listen_compete_ipv6= ); + } + if (has_ipv4 && has_ipv6) { + g_test_add_func("/socket/listen-serial/generic", listen_serial_gen= ); + g_test_add_func("/socket/listen-compete/generic", listen_compete_g= en); + } + return g_test_run(); +} --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603619628910.2276213654923; Tue, 5 Sep 2017 02:26:59 -0700 (PDT) Received: from localhost ([::1]:57681 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA8I-0004fW-Kz for importer@patchew.org; Tue, 05 Sep 2017 05:26:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41148) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4C-00018w-9n for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA47-0002hQ-Di for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54766) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA47-0002h3-5Y for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:39 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3A8EC806A0; Tue, 5 Sep 2017 09:22:38 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5039360BEC; Tue, 5 Sep 2017 09:22:37 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3A8EC806A0 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:24 +0100 Message-Id: <20170905092230.8243-4-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Tue, 05 Sep 2017 09:22:38 +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] [PULL v1 3/9] sockets: factor out a new try_bind() function 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: Peter Maydell , Knut Omang Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Knut Omang A refactoring step to prepare for the problem exposed by the test-listen test in the previous commit. Simplify and reorganize the IPv6 specific extra measures and move it out of the for loop to increase code readability. No semantic changes. Signed-off-by: Knut Omang Reviewed-by: Daniel P. Berrange Signed-off-by: Daniel P. Berrange --- util/qemu-sockets.c | 69 ++++++++++++++++++++++++++++++-------------------= ---- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 1358c81bcc..b4a2f243f4 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -149,6 +149,44 @@ int inet_ai_family_from_address(InetSocketAddress *add= r, return PF_UNSPEC; } =20 +static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo = *e) +{ +#ifndef IPV6_V6ONLY + return bind(socket, e->ai_addr, e->ai_addrlen); +#else + /* + * Deals with first & last cases in matrix in comment + * for inet_ai_family_from_address(). + */ + int v6only =3D + ((!saddr->has_ipv4 && !saddr->has_ipv6) || + (saddr->has_ipv4 && saddr->ipv4 && + saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1; + int stat; + + rebind: + if (e->ai_family =3D=3D PF_INET6) { + qemu_setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, + sizeof(v6only)); + } + + stat =3D bind(socket, e->ai_addr, e->ai_addrlen); + if (!stat) { + return 0; + } + + /* If we got EADDRINUSE from an IPv6 bind & v6only is unset, + * it could be that the IPv4 port is already claimed, so retry + * with v6only set + */ + if (e->ai_family =3D=3D PF_INET6 && errno =3D=3D EADDRINUSE && !v6only= ) { + v6only =3D 1; + goto rebind; + } + return stat; +#endif +} + static int inet_listen_saddr(InetSocketAddress *saddr, int port_offset, bool update_addr, @@ -228,39 +266,10 @@ static int inet_listen_saddr(InetSocketAddress *saddr, port_min =3D inet_getport(e); port_max =3D saddr->has_to ? saddr->to + port_offset : port_min; for (p =3D port_min; p <=3D port_max; p++) { -#ifdef IPV6_V6ONLY - /* - * Deals with first & last cases in matrix in comment - * for inet_ai_family_from_address(). - */ - int v6only =3D - ((!saddr->has_ipv4 && !saddr->has_ipv6) || - (saddr->has_ipv4 && saddr->ipv4 && - saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1; -#endif inet_setport(e, p); -#ifdef IPV6_V6ONLY - rebind: - if (e->ai_family =3D=3D PF_INET6) { - qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &v6onl= y, - sizeof(v6only)); - } -#endif - if (bind(slisten, e->ai_addr, e->ai_addrlen) =3D=3D 0) { + if (try_bind(slisten, saddr, e) >=3D 0) { goto listen; } - -#ifdef IPV6_V6ONLY - /* If we got EADDRINUSE from an IPv6 bind & V6ONLY is unset, - * it could be that the IPv4 port is already claimed, so retry - * with V6ONLY set - */ - if (e->ai_family =3D=3D PF_INET6 && errno =3D=3D EADDRINUSE &&= !v6only) { - v6only =3D 1; - goto rebind; - } -#endif - if (p =3D=3D port_max) { if (!e->ai_next) { error_setg_errno(errp, errno, "Failed to bind socket"); --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603499918306.3630374221914; Tue, 5 Sep 2017 02:24:59 -0700 (PDT) Received: from localhost ([::1]:57668 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA6M-0002fe-RR for importer@patchew.org; Tue, 05 Sep 2017 05:24:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41162) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4D-00019p-A0 for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA48-0002iJ-FU for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:45 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35672) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA48-0002hY-A2 for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:40 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 66CF9285B2; Tue, 5 Sep 2017 09:22:39 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7A1F86E50A; Tue, 5 Sep 2017 09:22:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 66CF9285B2 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:25 +0100 Message-Id: <20170905092230.8243-5-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 05 Sep 2017 09:22:39 +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] [PULL v1 4/9] sockets: factor out create_fast_reuse_socket 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: Peter Maydell , Knut Omang Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Knut Omang Another refactoring step to prepare for fixing the problem exposed with the test-listen test in the previous commit Signed-off-by: Knut Omang Reviewed-by: Daniel P. Berrange Signed-off-by: Daniel P. Berrange --- util/qemu-sockets.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index b4a2f243f4..d0d20476e5 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -149,6 +149,16 @@ int inet_ai_family_from_address(InetSocketAddress *add= r, return PF_UNSPEC; } =20 +static int create_fast_reuse_socket(struct addrinfo *e) +{ + int slisten =3D qemu_socket(e->ai_family, e->ai_socktype, e->ai_protoc= ol); + if (slisten < 0) { + return -1; + } + socket_set_fast_reuse(slisten); + return slisten; +} + static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo = *e) { #ifndef IPV6_V6ONLY @@ -253,7 +263,8 @@ static int inet_listen_saddr(InetSocketAddress *saddr, getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, NI_NUMERICHOST | NI_NUMERICSERV); - slisten =3D qemu_socket(e->ai_family, e->ai_socktype, e->ai_protoc= ol); + + slisten =3D create_fast_reuse_socket(e); if (slisten < 0) { if (!e->ai_next) { error_setg_errno(errp, errno, "Failed to create socket"); @@ -261,8 +272,6 @@ static int inet_listen_saddr(InetSocketAddress *saddr, continue; } =20 - socket_set_fast_reuse(slisten); - port_min =3D inet_getport(e); port_max =3D saddr->has_to ? saddr->to + port_offset : port_min; for (p =3D port_min; p <=3D port_max; p++) { --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603927049694.5197554107705; Tue, 5 Sep 2017 02:32:07 -0700 (PDT) Received: from localhost ([::1]:57705 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpADF-0000r5-Uf for importer@patchew.org; Tue, 05 Sep 2017 05:32:05 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41189) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4F-0001Bi-3m for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA49-0002jd-RV for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36348) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA49-0002ia-JS for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:41 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B3A907EA8B; Tue, 5 Sep 2017 09:22:40 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id A79D560BEC; Tue, 5 Sep 2017 09:22:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B3A907EA8B Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:26 +0100 Message-Id: <20170905092230.8243-6-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 05 Sep 2017 09:22:40 +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] [PULL v1 5/9] sockets: Handle race condition between binds to the same port 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: Peter Maydell , Knut Omang Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Knut Omang If an offset of ports is specified to the inet_listen_saddr function(), and two or more processes tries to bind from these ports at the same time, occasionally more than one process may be able to bind to the same port. The condition is detected by listen() but too late to avoid a failure. This function is called by socket_listen() and used by all socket listening code in QEMU, so all cases where any form of dynamic port selection is used should be subject to this issue. Add code to close and re-establish the socket when this condition is observed, hiding the race condition from the user. Also clean up some issues with error handling to allow more accurate reporting of the cause of an error. This has been developed and tested by means of the test-listen unit test in the previous commit. Enable the test for make check now that it passes. Reviewed-by: Bhavesh Davda Reviewed-by: Yuval Shaia Reviewed-by: Girish Moodalbail Signed-off-by: Knut Omang Reviewed-by: Daniel P. Berrange Signed-off-by: Daniel P. Berrange --- tests/Makefile.include | 2 +- util/qemu-sockets.c | 58 +++++++++++++++++++++++++++++++++++-----------= ---- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index a231754517..eef4088d5c 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -151,7 +151,7 @@ check-unit-y +=3D tests/test-bufferiszero$(EXESUF) gcov-files-check-bufferiszero-y =3D util/bufferiszero.c check-unit-y +=3D tests/test-uuid$(EXESUF) check-unit-y +=3D tests/ptimer-test$(EXESUF) -#check-unit-y +=3D tests/test-listen$(EXESUF) +check-unit-y +=3D tests/test-listen$(EXESUF) gcov-files-ptimer-test-y =3D hw/core/ptimer.c check-unit-y +=3D tests/test-qapi-util$(EXESUF) gcov-files-test-qapi-util-y =3D qapi/qapi-util.c diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index d0d20476e5..6a511fbf76 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -206,7 +206,10 @@ static int inet_listen_saddr(InetSocketAddress *saddr, char port[33]; char uaddr[INET6_ADDRSTRLEN+1]; char uport[33]; - int slisten, rc, port_min, port_max, p; + int rc, port_min, port_max, p; + int slisten =3D 0; + int saved_errno =3D 0; + bool socket_created =3D false; Error *err =3D NULL; =20 memset(&ai,0, sizeof(ai)); @@ -258,7 +261,7 @@ static int inet_listen_saddr(InetSocketAddress *saddr, return -1; } =20 - /* create socket + bind */ + /* create socket + bind/listen */ for (e =3D res; e !=3D NULL; e =3D e->ai_next) { getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, @@ -266,37 +269,58 @@ static int inet_listen_saddr(InetSocketAddress *saddr, =20 slisten =3D create_fast_reuse_socket(e); if (slisten < 0) { - if (!e->ai_next) { - error_setg_errno(errp, errno, "Failed to create socket"); - } continue; } =20 + socket_created =3D true; port_min =3D inet_getport(e); port_max =3D saddr->has_to ? saddr->to + port_offset : port_min; for (p =3D port_min; p <=3D port_max; p++) { inet_setport(e, p); - if (try_bind(slisten, saddr, e) >=3D 0) { - goto listen; - } - if (p =3D=3D port_max) { - if (!e->ai_next) { + rc =3D try_bind(slisten, saddr, e); + if (rc) { + if (errno =3D=3D EADDRINUSE) { + continue; + } else { error_setg_errno(errp, errno, "Failed to bind socket"); + goto listen_failed; } } + if (!listen(slisten, 1)) { + goto listen_ok; + } + if (errno !=3D EADDRINUSE) { + error_setg_errno(errp, errno, "Failed to listen on socket"= ); + goto listen_failed; + } + /* Someone else managed to bind to the same port and beat us + * to listen on it! Socket semantics does not allow us to + * recover from this situation, so we need to recreate the + * socket to allow bind attempts for subsequent ports: + */ + closesocket(slisten); + slisten =3D create_fast_reuse_socket(e); + if (slisten < 0) { + error_setg_errno(errp, errno, + "Failed to recreate failed listening sock= et"); + goto listen_failed; + } } + } + error_setg_errno(errp, errno, + socket_created ? + "Failed to find an available port" : + "Failed to create a socket"); +listen_failed: + saved_errno =3D errno; + if (slisten >=3D 0) { closesocket(slisten); } freeaddrinfo(res); + errno =3D saved_errno; return -1; =20 -listen: - if (listen(slisten,1) !=3D 0) { - error_setg_errno(errp, errno, "Failed to listen on socket"); - closesocket(slisten); - freeaddrinfo(res); - return -1; - } +listen_ok: if (update_addr) { g_free(saddr->host); saddr->host =3D g_strdup(uaddr); --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603764010726.6597886513208; Tue, 5 Sep 2017 02:29:24 -0700 (PDT) Received: from localhost ([::1]:57689 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpAAc-0006gH-3o for importer@patchew.org; Tue, 05 Sep 2017 05:29:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41236) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4H-0001EE-NN for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA4B-0002lO-Kj for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:2282) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA4B-0002kR-Bi for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:43 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 64F7CC04B924; Tue, 5 Sep 2017 09:22:42 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0254C60BEC; Tue, 5 Sep 2017 09:22:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 64F7CC04B924 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:27 +0100 Message-Id: <20170905092230.8243-7-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 05 Sep 2017 09:22:42 +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] [PULL v1 6/9] util: remove the obsolete non-blocking connect 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: Peter Maydell , Cao jin , Mao Zhongyi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Cao jin The non-blocking connect mechanism is obsolete, and it doesn't work well in inet connection, because it will call getaddrinfo first and getaddrinfo will blocks on DNS lookups. Since commit e65c67e4 & d984464e, the non-blocking connect of migration goes through QIOChannel in a different manner(using a thread), and nobody use this old non-blocking connect anymore. Any newly written code which needs a non-blocking connect should use the QIOChannel code, so we can drop NonBlockingConnectHandler as a concept entirely. Suggested-by: Daniel P. Berrange Signed-off-by: Cao jin Signed-off-by: Mao Zhongyi Reviewed-by: Juan Quintela Signed-off-by: Daniel P. Berrange --- block/sheepdog.c | 2 +- block/ssh.c | 2 +- include/qemu/sockets.h | 12 +-- io/channel-socket.c | 2 +- util/qemu-sockets.c | 205 ++++++---------------------------------------= ---- 5 files changed, 28 insertions(+), 195 deletions(-) diff --git a/block/sheepdog.c b/block/sheepdog.c index abb2e79065..64ab07f3b7 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -591,7 +591,7 @@ static int connect_to_sdog(BDRVSheepdogState *s, Error = **errp) { int fd; =20 - fd =3D socket_connect(s->addr, NULL, NULL, errp); + fd =3D socket_connect(s->addr, errp); =20 if (s->addr->type =3D=3D SOCKET_ADDRESS_TYPE_INET && fd >=3D 0) { int ret =3D socket_set_nodelay(fd); diff --git a/block/ssh.c b/block/ssh.c index e8f0404c03..b049a16eb9 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -678,7 +678,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *optio= ns, } =20 /* Open the socket and connect. */ - s->sock =3D inet_connect_saddr(s->inet, NULL, NULL, errp); + s->sock =3D inet_connect_saddr(s->inet, errp); if (s->sock < 0) { ret =3D -EIO; goto err; diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index ef6b5591f7..639cc079d9 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -27,18 +27,11 @@ int socket_set_fast_reuse(int fd); #define SHUT_RDWR 2 #endif =20 -/* callback function for nonblocking connect - * valid fd on success, negative error code on failure - */ -typedef void NonBlockingConnectHandler(int fd, Error *err, void *opaque); - int inet_ai_family_from_address(InetSocketAddress *addr, Error **errp); int inet_parse(InetSocketAddress *addr, const char *str, Error **errp); int inet_connect(const char *str, Error **errp); -int inet_connect_saddr(InetSocketAddress *saddr, - NonBlockingConnectHandler *callback, void *opaque, - Error **errp); +int inet_connect_saddr(InetSocketAddress *saddr, Error **errp); =20 NetworkAddressFamily inet_netfamily(int family); =20 @@ -46,8 +39,7 @@ int unix_listen(const char *path, char *ostr, int olen, E= rror **errp); int unix_connect(const char *path, Error **errp); =20 SocketAddress *socket_parse(const char *str, Error **errp); -int socket_connect(SocketAddress *addr, NonBlockingConnectHandler *callbac= k, - void *opaque, Error **errp); +int socket_connect(SocketAddress *addr, Error **errp); int socket_listen(SocketAddress *addr, Error **errp); void socket_listen_cleanup(int fd, Error **errp); int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp= ); diff --git a/io/channel-socket.c b/io/channel-socket.c index 591d27e8c3..563e297357 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -140,7 +140,7 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *i= oc, int fd; =20 trace_qio_channel_socket_connect_sync(ioc, addr); - fd =3D socket_connect(addr, NULL, NULL, errp); + fd =3D socket_connect(addr, errp); if (fd < 0) { trace_qio_channel_socket_connect_fail(ioc); return -1; diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 6a511fbf76..b47fb45885 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -342,88 +342,19 @@ listen_ok: ((rc) =3D=3D -EINPROGRESS) #endif =20 -/* Struct to store connect state for non blocking connect */ -typedef struct ConnectState { - int fd; - struct addrinfo *addr_list; - struct addrinfo *current_addr; - NonBlockingConnectHandler *callback; - void *opaque; -} ConnectState; - -static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, - ConnectState *connect_state, Error **errp); +static int inet_connect_addr(struct addrinfo *addr, Error **errp); =20 -static void wait_for_connect(void *opaque) -{ - ConnectState *s =3D opaque; - int val =3D 0, rc =3D 0; - socklen_t valsize =3D sizeof(val); - bool in_progress; - Error *err =3D NULL; - - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); - - do { - rc =3D qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize= ); - } while (rc =3D=3D -1 && errno =3D=3D EINTR); - - /* update rc to contain error */ - if (!rc && val) { - rc =3D -1; - errno =3D val; - } - - /* connect error */ - if (rc < 0) { - error_setg_errno(&err, errno, "Error connecting to socket"); - closesocket(s->fd); - s->fd =3D rc; - } - - /* try to connect to the next address on the list */ - if (s->current_addr) { - while (s->current_addr->ai_next !=3D NULL && s->fd < 0) { - s->current_addr =3D s->current_addr->ai_next; - s->fd =3D inet_connect_addr(s->current_addr, &in_progress, s, = NULL); - if (s->fd < 0) { - error_free(err); - err =3D NULL; - error_setg_errno(&err, errno, "Unable to start socket conn= ect"); - } - /* connect in progress */ - if (in_progress) { - goto out; - } - } - - freeaddrinfo(s->addr_list); - } - - if (s->callback) { - s->callback(s->fd, err, s->opaque); - } - g_free(s); -out: - error_free(err); -} - -static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, - ConnectState *connect_state, Error **errp) +static int inet_connect_addr(struct addrinfo *addr, Error **errp) { int sock, rc; =20 - *in_progress =3D false; - sock =3D qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_prot= ocol); if (sock < 0) { error_setg_errno(errp, errno, "Failed to create socket"); return -1; } socket_set_fast_reuse(sock); - if (connect_state !=3D NULL) { - qemu_set_nonblock(sock); - } + /* connect to peer */ do { rc =3D 0; @@ -432,15 +363,12 @@ static int inet_connect_addr(struct addrinfo *addr, b= ool *in_progress, } } while (rc =3D=3D -EINTR); =20 - if (connect_state !=3D NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { - connect_state->fd =3D sock; - qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); - *in_progress =3D true; - } else if (rc < 0) { + if (rc < 0) { error_setg_errno(errp, errno, "Failed to connect socket"); closesocket(sock); return -1; } + return sock; } =20 @@ -498,44 +426,24 @@ static struct addrinfo *inet_parse_connect_saddr(Inet= SocketAddress *saddr, * * @saddr: Inet socket address specification * @errp: set on error - * @callback: callback function for non-blocking connect - * @opaque: opaque for callback function * * Returns: -1 on error, file descriptor on success. - * - * If @callback is non-null, the connect is non-blocking. If this - * function succeeds, callback will be called when the connection - * completes, with the file descriptor on success, or -1 on error. */ -int inet_connect_saddr(InetSocketAddress *saddr, - NonBlockingConnectHandler *callback, void *opaque, - Error **errp) +int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) { Error *local_err =3D NULL; struct addrinfo *res, *e; int sock =3D -1; - bool in_progress; - ConnectState *connect_state =3D NULL; =20 res =3D inet_parse_connect_saddr(saddr, errp); if (!res) { return -1; } =20 - if (callback !=3D NULL) { - connect_state =3D g_malloc0(sizeof(*connect_state)); - connect_state->addr_list =3D res; - connect_state->callback =3D callback; - connect_state->opaque =3D opaque; - } - for (e =3D res; e !=3D NULL; e =3D e->ai_next) { error_free(local_err); local_err =3D NULL; - if (connect_state !=3D NULL) { - connect_state->current_addr =3D e; - } - sock =3D inet_connect_addr(e, &in_progress, connect_state, &local_= err); + sock =3D inet_connect_addr(e, &local_err); if (sock >=3D 0) { break; } @@ -543,15 +451,8 @@ int inet_connect_saddr(InetSocketAddress *saddr, =20 if (sock < 0) { error_propagate(errp, local_err); - } else if (in_progress) { - /* wait_for_connect() will do the rest */ - return sock; - } else { - if (callback) { - callback(sock, NULL, opaque); - } } - g_free(connect_state); + freeaddrinfo(res); return sock; } @@ -730,7 +631,7 @@ int inet_connect(const char *str, Error **errp) InetSocketAddress *addr =3D g_new(InetSocketAddress, 1); =20 if (!inet_parse(addr, str, errp)) { - sock =3D inet_connect_saddr(addr, NULL, NULL, errp); + sock =3D inet_connect_saddr(addr, errp); } qapi_free_InetSocketAddress(addr); return sock; @@ -763,21 +664,16 @@ static bool vsock_parse_vaddr_to_sockaddr(const Vsock= SocketAddress *vaddr, return true; } =20 -static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_prog= ress, - ConnectState *connect_state, Error **errp) +static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) { int sock, rc; =20 - *in_progress =3D false; - sock =3D qemu_socket(AF_VSOCK, SOCK_STREAM, 0); if (sock < 0) { error_setg_errno(errp, errno, "Failed to create socket"); return -1; } - if (connect_state !=3D NULL) { - qemu_set_nonblock(sock); - } + /* connect to peer */ do { rc =3D 0; @@ -786,50 +682,26 @@ static int vsock_connect_addr(const struct sockaddr_v= m *svm, bool *in_progress, } } while (rc =3D=3D -EINTR); =20 - if (connect_state !=3D NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { - connect_state->fd =3D sock; - qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); - *in_progress =3D true; - } else if (rc < 0) { + if (rc < 0) { error_setg_errno(errp, errno, "Failed to connect socket"); closesocket(sock); return -1; } + return sock; } =20 -static int vsock_connect_saddr(VsockSocketAddress *vaddr, - NonBlockingConnectHandler *callback, - void *opaque, - Error **errp) +static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) { struct sockaddr_vm svm; int sock =3D -1; - bool in_progress; - ConnectState *connect_state =3D NULL; =20 if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { return -1; } =20 - if (callback !=3D NULL) { - connect_state =3D g_malloc0(sizeof(*connect_state)); - connect_state->callback =3D callback; - connect_state->opaque =3D opaque; - } + sock =3D vsock_connect_addr(&svm, errp); =20 - sock =3D vsock_connect_addr(&svm, &in_progress, connect_state, errp); - if (sock < 0) { - /* do nothing */ - } else if (in_progress) { - /* wait_for_connect() will do the rest */ - return sock; - } else { - if (callback) { - callback(sock, NULL, opaque); - } - } - g_free(connect_state); return sock; } =20 @@ -889,9 +761,7 @@ static void vsock_unsupported(Error **errp) error_setg(errp, "socket family AF_VSOCK unsupported"); } =20 -static int vsock_connect_saddr(VsockSocketAddress *vaddr, - NonBlockingConnectHandler *callback, - void *opaque, Error **errp) +static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) { vsock_unsupported(errp); return -1; @@ -994,12 +864,9 @@ err: return -1; } =20 -static int unix_connect_saddr(UnixSocketAddress *saddr, - NonBlockingConnectHandler *callback, void *o= paque, - Error **errp) +static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) { struct sockaddr_un un; - ConnectState *connect_state =3D NULL; int sock, rc; =20 if (saddr->path =3D=3D NULL) { @@ -1012,12 +879,6 @@ static int unix_connect_saddr(UnixSocketAddress *sadd= r, error_setg_errno(errp, errno, "Failed to create socket"); return -1; } - if (callback !=3D NULL) { - connect_state =3D g_malloc0(sizeof(*connect_state)); - connect_state->callback =3D callback; - connect_state->opaque =3D opaque; - qemu_set_nonblock(sock); - } =20 if (strlen(saddr->path) > sizeof(un.sun_path)) { error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); @@ -1038,29 +899,16 @@ static int unix_connect_saddr(UnixSocketAddress *sad= dr, } } while (rc =3D=3D -EINTR); =20 - if (connect_state !=3D NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { - connect_state->fd =3D sock; - qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); - return sock; - } else if (rc >=3D 0) { - /* non blocking socket immediate success, call callback */ - if (callback !=3D NULL) { - callback(sock, NULL, opaque); - } - } - if (rc < 0) { error_setg_errno(errp, -rc, "Failed to connect socket %s", saddr->path); goto err; } =20 - g_free(connect_state); return sock; =20 err: close(sock); - g_free(connect_state); return -1; } =20 @@ -1075,9 +923,7 @@ static int unix_listen_saddr(UnixSocketAddress *saddr, return -1; } =20 -static int unix_connect_saddr(UnixSocketAddress *saddr, - NonBlockingConnectHandler *callback, void *o= paque, - Error **errp) +static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) { error_setg(errp, "unix sockets are not available on windows"); errno =3D ENOTSUP; @@ -1123,7 +969,7 @@ int unix_connect(const char *path, Error **errp) =20 saddr =3D g_new0(UnixSocketAddress, 1); saddr->path =3D g_strdup(path); - sock =3D unix_connect_saddr(saddr, NULL, NULL, errp); + sock =3D unix_connect_saddr(saddr, errp); qapi_free_UnixSocketAddress(saddr); return sock; } @@ -1168,30 +1014,25 @@ fail: return NULL; } =20 -int socket_connect(SocketAddress *addr, NonBlockingConnectHandler *callbac= k, - void *opaque, Error **errp) +int socket_connect(SocketAddress *addr, Error **errp) { int fd; =20 switch (addr->type) { case SOCKET_ADDRESS_TYPE_INET: - fd =3D inet_connect_saddr(&addr->u.inet, callback, opaque, errp); + fd =3D inet_connect_saddr(&addr->u.inet, errp); break; =20 case SOCKET_ADDRESS_TYPE_UNIX: - fd =3D unix_connect_saddr(&addr->u.q_unix, callback, opaque, errp); + fd =3D unix_connect_saddr(&addr->u.q_unix, errp); break; =20 case SOCKET_ADDRESS_TYPE_FD: fd =3D monitor_get_fd(cur_mon, addr->u.fd.str, errp); - if (fd >=3D 0 && callback) { - qemu_set_nonblock(fd); - callback(fd, NULL, opaque); - } break; =20 case SOCKET_ADDRESS_TYPE_VSOCK: - fd =3D vsock_connect_saddr(&addr->u.vsock, callback, opaque, errp); + fd =3D vsock_connect_saddr(&addr->u.vsock, errp); break; =20 default: --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603638468183.5621389093011; Tue, 5 Sep 2017 02:27:18 -0700 (PDT) Received: from localhost ([::1]:57682 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA8b-0004uD-EF for importer@patchew.org; Tue, 05 Sep 2017 05:27:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41217) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4H-0001DZ-3N for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA4C-0002mE-GP for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44374) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA4C-0002le-As for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:44 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 701BA7E424; Tue, 5 Sep 2017 09:22:43 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id A6BFF60BEC; Tue, 5 Sep 2017 09:22:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 701BA7E424 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:28 +0100 Message-Id: <20170905092230.8243-8-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 05 Sep 2017 09:22:43 +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] [PULL v1 7/9] io: fix typo in docs comment for qio_channel_read 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: Peter Maydell Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Reviewed-by: Eric Blake Signed-off-by: Daniel P. Berrange --- include/io/channel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/io/channel.h b/include/io/channel.h index db9bb022a1..54f3dc252f 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -299,7 +299,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc, Error **errp); =20 /** - * qio_channel_readv: + * qio_channel_read: * @ioc: the channel object * @buf: the memory region to read data into * @buflen: the length of @buf --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504604092937884.8515255823615; Tue, 5 Sep 2017 02:34:52 -0700 (PDT) Received: from localhost ([::1]:57717 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpAFv-00036y-NH for importer@patchew.org; Tue, 05 Sep 2017 05:34:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41268) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4J-0001GE-U7 for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA4E-0002oH-IT for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:51 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35822) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA4E-0002nK-9Q for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:46 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 671CF356EA; Tue, 5 Sep 2017 09:22:45 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id B2B9660BEC; Tue, 5 Sep 2017 09:22:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 671CF356EA Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:29 +0100 Message-Id: <20170905092230.8243-9-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 05 Sep 2017 09:22:45 +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] [PULL v1 8/9] io: add new qio_channel_{readv, writev, read, write}_all 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: Peter Maydell Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These functions wait until they are able to read / write the full requested data buffer(s). Reviewed-by: Eric Blake Signed-off-by: Daniel P. Berrange --- include/io/channel.h | 90 +++++++++++++++++++++++++++++++++++++++ io/channel.c | 94 +++++++++++++++++++++++++++++++++++++++++ tests/io-channel-helpers.c | 102 ++++-------------------------------------= ---- 3 files changed, 193 insertions(+), 93 deletions(-) diff --git a/include/io/channel.h b/include/io/channel.h index 54f3dc252f..8f25893c45 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -269,6 +269,58 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc, Error **errp); =20 /** + * qio_channel_readv_all: + * @ioc: the channel object + * @iov: the array of memory regions to read data into + * @niov: the length of the @iov array + * @errp: pointer to a NULL-initialized error object + * + * Read data from the IO channel, storing it in the + * memory regions referenced by @iov. Each element + * in the @iov will be fully populated with data + * before the next one is used. The @niov parameter + * specifies the total number of elements in @iov. + * + * The function will wait for all requested data + * to be read, yielding from the current coroutine + * if required. + * + * If end-of-file occurs before all requested data + * has been read, an error will be reported. + * + * Returns: 0 if all bytes were read, or -1 on error + */ +int qio_channel_readv_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + Error **errp); + + +/** + * qio_channel_writev_all: + * @ioc: the channel object + * @iov: the array of memory regions to write data from + * @niov: the length of the @iov array + * @errp: pointer to a NULL-initialized error object + * + * Write data to the IO channel, reading it from the + * memory regions referenced by @iov. Each element + * in the @iov will be fully sent, before the next + * one is used. The @niov parameter specifies the + * total number of elements in @iov. + * + * The function will wait for all requested data + * to be written, yielding from the current coroutine + * if required. + * + * Returns: 0 if all bytes were written, or -1 on error + */ +int qio_channel_writev_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + Error **erp); + +/** * qio_channel_readv: * @ioc: the channel object * @iov: the array of memory regions to read data into @@ -331,6 +383,44 @@ ssize_t qio_channel_write(QIOChannel *ioc, Error **errp); =20 /** + * qio_channel_read_all: + * @ioc: the channel object + * @buf: the memory region to read data into + * @buflen: the number of bytes to @buf + * @errp: pointer to a NULL-initialized error object + * + * Reads @buflen bytes into @buf, possibly blocking or (if the + * channel is non-blocking) yielding from the current coroutine + * multiple times until the entire content is read. If end-of-file + * occurs it will return an error rather than a short-read. Otherwise + * behaves as qio_channel_read(). + * + * Returns: 0 if all bytes were read, or -1 on error + */ +int qio_channel_read_all(QIOChannel *ioc, + char *buf, + size_t buflen, + Error **errp); +/** + * qio_channel_write_all: + * @ioc: the channel object + * @buf: the memory region to write data into + * @buflen: the number of bytes to @buf + * @errp: pointer to a NULL-initialized error object + * + * Writes @buflen bytes from @buf, possibly blocking or (if the + * channel is non-blocking) yielding from the current coroutine + * multiple times until the entire content is written. Otherwise + * behaves as qio_channel_write(). + * + * Returns: 0 if all bytes were written, or -1 on error + */ +int qio_channel_write_all(QIOChannel *ioc, + const char *buf, + size_t buflen, + Error **errp); + +/** * qio_channel_set_blocking: * @ioc: the channel object * @enabled: the blocking flag state diff --git a/io/channel.c b/io/channel.c index 1cfb8b33a2..5e8c2f0a91 100644 --- a/io/channel.c +++ b/io/channel.c @@ -22,6 +22,7 @@ #include "io/channel.h" #include "qapi/error.h" #include "qemu/main-loop.h" +#include "qemu/iov.h" =20 bool qio_channel_has_feature(QIOChannel *ioc, QIOChannelFeature feature) @@ -85,6 +86,79 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc, } =20 =20 + +int qio_channel_readv_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + Error **errp) +{ + int ret =3D -1; + struct iovec *local_iov =3D g_new(struct iovec, niov); + struct iovec *local_iov_head =3D local_iov; + unsigned int nlocal_iov =3D niov; + + nlocal_iov =3D iov_copy(local_iov, nlocal_iov, + iov, niov, + 0, iov_size(iov, niov)); + + while (nlocal_iov > 0) { + ssize_t len; + len =3D qio_channel_readv(ioc, local_iov, nlocal_iov, errp); + if (len =3D=3D QIO_CHANNEL_ERR_BLOCK) { + qio_channel_wait(ioc, G_IO_IN); + continue; + } else if (len < 0) { + goto cleanup; + } else if (len =3D=3D 0) { + error_setg(errp, + "Unexpected end-of-file before all bytes were read"= ); + goto cleanup; + } + + iov_discard_front(&local_iov, &nlocal_iov, len); + } + + ret =3D 0; + + cleanup: + g_free(local_iov_head); + return ret; +} + +int qio_channel_writev_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + Error **errp) +{ + int ret =3D -1; + struct iovec *local_iov =3D g_new(struct iovec, niov); + struct iovec *local_iov_head =3D local_iov; + unsigned int nlocal_iov =3D niov; + + nlocal_iov =3D iov_copy(local_iov, nlocal_iov, + iov, niov, + 0, iov_size(iov, niov)); + + while (nlocal_iov > 0) { + ssize_t len; + len =3D qio_channel_writev(ioc, local_iov, nlocal_iov, errp); + if (len =3D=3D QIO_CHANNEL_ERR_BLOCK) { + qio_channel_wait(ioc, G_IO_OUT); + continue; + } + if (len < 0) { + goto cleanup; + } + + iov_discard_front(&local_iov, &nlocal_iov, len); + } + + ret =3D 0; + cleanup: + g_free(local_iov_head); + return ret; +} + ssize_t qio_channel_readv(QIOChannel *ioc, const struct iovec *iov, size_t niov, @@ -123,6 +197,26 @@ ssize_t qio_channel_write(QIOChannel *ioc, } =20 =20 +int qio_channel_read_all(QIOChannel *ioc, + char *buf, + size_t buflen, + Error **errp) +{ + struct iovec iov =3D { .iov_base =3D buf, .iov_len =3D buflen }; + return qio_channel_readv_all(ioc, &iov, 1, errp); +} + + +int qio_channel_write_all(QIOChannel *ioc, + const char *buf, + size_t buflen, + Error **errp) +{ + struct iovec iov =3D { .iov_base =3D (char *)buf, .iov_len =3D buflen = }; + return qio_channel_writev_all(ioc, &iov, 1, errp); +} + + int qio_channel_set_blocking(QIOChannel *ioc, bool enabled, Error **errp) diff --git a/tests/io-channel-helpers.c b/tests/io-channel-helpers.c index 05e5579cf8..5430e1389d 100644 --- a/tests/io-channel-helpers.c +++ b/tests/io-channel-helpers.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "io-channel-helpers.h" #include "qapi/error.h" +#include "qemu/iov.h" =20 struct QIOChannelTest { QIOChannel *src; @@ -37,77 +38,17 @@ struct QIOChannelTest { }; =20 =20 -static void test_skip_iovec(struct iovec **iov, - size_t *niov, - size_t skip, - struct iovec *old) -{ - size_t offset =3D 0; - size_t i; - - for (i =3D 0; i < *niov; i++) { - if (skip < (*iov)[i].iov_len) { - old->iov_len =3D (*iov)[i].iov_len; - old->iov_base =3D (*iov)[i].iov_base; - - (*iov)[i].iov_len -=3D skip; - (*iov)[i].iov_base +=3D skip; - break; - } else { - skip -=3D (*iov)[i].iov_len; - - if (i =3D=3D 0 && old->iov_base) { - (*iov)[i].iov_len =3D old->iov_len; - (*iov)[i].iov_base =3D old->iov_base; - old->iov_len =3D 0; - old->iov_base =3D NULL; - } - - offset++; - } - } - - *iov =3D *iov + offset; - *niov -=3D offset; -} - - /* This thread sends all data using iovecs */ static gpointer test_io_thread_writer(gpointer opaque) { QIOChannelTest *data =3D opaque; - struct iovec *iov =3D data->inputv; - size_t niov =3D data->niov; - struct iovec old =3D { 0 }; =20 qio_channel_set_blocking(data->src, data->blocking, NULL); =20 - while (niov) { - ssize_t ret; - ret =3D qio_channel_writev(data->src, - iov, - niov, - &data->writeerr); - if (ret =3D=3D QIO_CHANNEL_ERR_BLOCK) { - if (data->blocking) { - error_setg(&data->writeerr, - "Unexpected I/O blocking"); - break; - } else { - qio_channel_wait(data->src, - G_IO_OUT); - continue; - } - } else if (ret < 0) { - break; - } else if (ret =3D=3D 0) { - error_setg(&data->writeerr, - "Unexpected zero length write"); - break; - } - - test_skip_iovec(&iov, &niov, ret, &old); - } + qio_channel_writev_all(data->src, + data->inputv, + data->niov, + &data->writeerr); =20 return NULL; } @@ -117,38 +58,13 @@ static gpointer test_io_thread_writer(gpointer opaque) static gpointer test_io_thread_reader(gpointer opaque) { QIOChannelTest *data =3D opaque; - struct iovec *iov =3D data->outputv; - size_t niov =3D data->niov; - struct iovec old =3D { 0 }; =20 qio_channel_set_blocking(data->dst, data->blocking, NULL); =20 - while (niov) { - ssize_t ret; - - ret =3D qio_channel_readv(data->dst, - iov, - niov, - &data->readerr); - - if (ret =3D=3D QIO_CHANNEL_ERR_BLOCK) { - if (data->blocking) { - error_setg(&data->readerr, - "Unexpected I/O blocking"); - break; - } else { - qio_channel_wait(data->dst, - G_IO_IN); - continue; - } - } else if (ret < 0) { - break; - } else if (ret =3D=3D 0) { - break; - } - - test_skip_iovec(&iov, &niov, ret, &old); - } + qio_channel_readv_all(data->dst, + data->outputv, + data->niov, + &data->readerr); =20 return NULL; } --=20 2.13.5 From nobody Sun Apr 28 20:01:30 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1504603656085585.0507542451583; Tue, 5 Sep 2017 02:27:36 -0700 (PDT) Received: from localhost ([::1]:57683 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA8s-0005Ai-Lc for importer@patchew.org; Tue, 05 Sep 2017 05:27:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41271) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dpA4K-0001GH-14 for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dpA4F-0002pB-Fh for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43456) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dpA4F-0002of-AH for qemu-devel@nongnu.org; Tue, 05 Sep 2017 05:22:47 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 699904620F; Tue, 5 Sep 2017 09:22:46 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.63]) by smtp.corp.redhat.com (Postfix) with ESMTP id A5E2A60BEC; Tue, 5 Sep 2017 09:22:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 699904620F Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=berrange@redhat.com From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Tue, 5 Sep 2017 10:22:30 +0100 Message-Id: <20170905092230.8243-10-berrange@redhat.com> In-Reply-To: <20170905092230.8243-1-berrange@redhat.com> References: <20170905092230.8243-1-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 05 Sep 2017 09:22:46 +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] [PULL v1 9/9] io: fix check for handshake completion in TLS test 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: Peter Maydell Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The TLS I/O channel test had mistakenly used && instead of || when checking for handshake completion. As a result it could terminate the handshake process before it had actually completed. This was harmless before but changes in GNUTLS 3.6.0 exposed this bug and caused the test suite to fail. Reviewed-by: Eric Blake Signed-off-by: Daniel P. Berrange --- tests/test-io-channel-tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c index ff96877323..a210d01ba5 100644 --- a/tests/test-io-channel-tls.c +++ b/tests/test-io-channel-tls.c @@ -218,7 +218,7 @@ static void test_io_channel_tls(const void *opaque) mainloop =3D g_main_context_default(); do { g_main_context_iteration(mainloop, TRUE); - } while (!clientHandshake.finished && + } while (!clientHandshake.finished || !serverHandshake.finished); =20 g_assert(clientHandshake.failed =3D=3D data->expectClientFail); --=20 2.13.5