From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, berrange@redhat.com,
qemu-devel@nongnu.org, mreitz@redhat.com, kraxel@redhat.com,
den@openvz.org
Subject: [PATCH 2/4] qemu-sockets: implement non-blocking connect interface
Date: Mon, 20 Jul 2020 21:07:13 +0300 [thread overview]
Message-ID: <20200720180715.10521-3-vsementsov@virtuozzo.com> (raw)
In-Reply-To: <20200720180715.10521-1-vsementsov@virtuozzo.com>
We are going to implement non-blocking connect in io/channel-socket.
non-blocking connect includes three phases:
1. connect() call
2. wait until socket is ready
3. check result
io/channel-socket has wait-on-socket API (qio_channel_yield(),
qio_channel_wait()), so it's a good place for [2].
Still, the whole thing is not simple, because socket connect in case of
inet socket includes several connect() calls, as SocketAddress may be
parsed into a list of inet addresses. And after each non-blocking
connect() upper layer should have a possibility to wait on the socket.
We may try to implement a kind of abstract list or iterator for
"sub" addresses of SocketAddress, but all this appears to be too
complex and not worth doing (as actually, only inet sockets has such a
"multiple" SocketAddress).
So, let's instead make public API for inet sockets themselves, to be
handled in separate in upper layer, if it needs non-blocking connect.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
include/qemu/sockets.h | 6 ++++++
util/qemu-sockets.c | 45 +++++++++++++++++++++++++++++++++++++-----
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 7d1f813576..7389d6be55 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -34,6 +34,12 @@ int inet_ai_family_from_address(InetSocketAddress *addr,
int inet_parse(InetSocketAddress *addr, const char *str, Error **errp);
int inet_connect(const char *str, Error **errp);
int inet_connect_saddr(InetSocketAddress *saddr, Error **errp);
+int inet_connect_addr(InetSocketAddress *saddr, struct addrinfo *addr,
+ bool blocking, bool *in_progress, Error **errp);
+struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr,
+ Error **errp);
+
+int socket_check(int fd, Error **errp);
NetworkAddressFamily inet_netfamily(int family);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 8ccf4088c2..a02d00f342 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -354,11 +354,17 @@ listen_ok:
((rc) == -EINPROGRESS)
#endif
-static int inet_connect_addr(InetSocketAddress *saddr,
- struct addrinfo *addr, Error **errp)
+int inet_connect_addr(InetSocketAddress *saddr, struct addrinfo *addr,
+ bool blocking, bool *in_progress, Error **errp)
{
int sock, rc;
+ assert(blocking == !in_progress);
+
+ if (in_progress) {
+ *in_progress = false;
+ }
+
sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sock < 0) {
error_setg_errno(errp, errno, "Failed to create socket");
@@ -366,6 +372,10 @@ static int inet_connect_addr(InetSocketAddress *saddr,
}
socket_set_fast_reuse(sock);
+ if (!blocking) {
+ qemu_set_nonblock(sock);
+ }
+
/* connect to peer */
do {
rc = 0;
@@ -374,6 +384,13 @@ static int inet_connect_addr(InetSocketAddress *saddr,
}
} while (rc == -EINTR);
+ if (!blocking && rc == -EINPROGRESS) {
+ if (in_progress) {
+ *in_progress = true;
+ }
+ return sock;
+ }
+
if (rc < 0) {
error_setg_errno(errp, errno, "Failed to connect socket");
closesocket(sock);
@@ -395,8 +412,26 @@ static int inet_connect_addr(InetSocketAddress *saddr,
return sock;
}
-static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr,
- Error **errp)
+int socket_check(int fd, Error **errp)
+{
+ int optval;
+ socklen_t optlen = sizeof(optval);
+ if (qemu_getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) {
+ error_setg_errno(errp, errno, "Unable to check connection");
+ return -1;
+ }
+
+ if (optval != 0) {
+ error_setg_errno(errp, errno, "Connection failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr,
+ Error **errp)
{
struct addrinfo ai, *res;
int rc;
@@ -466,7 +501,7 @@ int inet_connect_saddr(InetSocketAddress *saddr, Error **errp)
for (e = res; e != NULL; e = e->ai_next) {
error_free(local_err);
local_err = NULL;
- sock = inet_connect_addr(saddr, e, &local_err);
+ sock = inet_connect_addr(saddr, e, true, NULL, &local_err);
if (sock >= 0) {
break;
}
--
2.21.0
next prev parent reply other threads:[~2020-07-20 18:10 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-20 18:07 [PATCH for-5.1? 0/4] non-blocking connect Vladimir Sementsov-Ogievskiy
2020-07-20 18:07 ` [PATCH 1/4] qemu-sockets: refactor inet_connect_addr Vladimir Sementsov-Ogievskiy
2020-07-20 18:07 ` Vladimir Sementsov-Ogievskiy [this message]
2020-07-20 18:07 ` [PATCH 3/4] io/channel-socket: implement non-blocking connect Vladimir Sementsov-Ogievskiy
2020-07-20 18:29 ` Daniel P. Berrangé
2020-07-22 11:00 ` Vladimir Sementsov-Ogievskiy
2020-07-22 11:21 ` Daniel P. Berrangé
2020-07-22 12:43 ` Vladimir Sementsov-Ogievskiy
2020-07-22 12:53 ` Daniel P. Berrangé
2020-07-22 13:47 ` Vladimir Sementsov-Ogievskiy
2020-07-22 15:04 ` Vladimir Sementsov-Ogievskiy
2020-07-22 15:21 ` Daniel P. Berrangé
2020-07-22 15:40 ` Vladimir Sementsov-Ogievskiy
2020-07-22 15:43 ` Daniel P. Berrangé
2020-07-22 15:56 ` Vladimir Sementsov-Ogievskiy
2020-07-20 18:07 ` [PATCH 4/4] block/nbd: use non-blocking connect: fix vm hang on connect() Vladimir Sementsov-Ogievskiy
2020-07-23 19:35 ` [PATCH for-5.1? 0/4] non-blocking connect Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200720180715.10521-3-vsementsov@virtuozzo.com \
--to=vsementsov@virtuozzo.com \
--cc=berrange@redhat.com \
--cc=den@openvz.org \
--cc=kraxel@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.