qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v11 0/4] support to migrate with IPv6 address
@ 2012-05-08 14:58 Amos Kong
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings Amos Kong
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Amos Kong @ 2012-05-08 14:58 UTC (permalink / raw)
  To: aliguori, quintela, jasowang, mdroth, qemu-devel, owasserm, laine

Those patches updated help functions in qemu-socket.c,
and used them in migrate-tcp.c to support IPv6 migration.

---
Changes from v1:
- split different changes to small patches, it will be easier to review
- fixed some problem according to Kevin's comment

Changes from v2:
- fix issue of returning real error 
- set s->fd to -1 when parse fails, won't call migrate_fd_error()

Changes from v3:
- try to use help functions in qemu-socket.c

Changes from v4:
- introduce set_socket_error() to restore real errno
- fix connect error process

Changes from v5:
- use error class to pass socket error

Changes from v6:
- merge error process and nonblock support together
- fix leak of repeatedly error_set()
- coding style fix
- fix EWOULDBLOCK process

Changes from v7:
- posix: let EWOULDBLOCK fall through to CONNECT_FAILED path
- add unknown error process
- fix typo

Changes from v8:
- reuse rc variable
- fix a NULL pointer dereference

Changes from v9:
- handle non-blocking correctly if errp is NULL

Changes from v10:
- send out the whole series, no change
- add 'Reviewed-by'

---

Amos Kong (4):
      qerror: add five qerror strings
      sockets: change inet_connect() to support nonblock socket
      sockets: use error class to pass listen error
      use inet_listen()/inet_connect() to support ipv6 migration


 migration-tcp.c |   77 +++++++++++++++----------------------------------------
 migration.c     |   14 ++++++----
 migration.h     |    7 +++--
 nbd.c           |    4 +--
 qemu-char.c     |    4 +--
 qemu-sockets.c  |   60 ++++++++++++++++++++++++++++++++++++-------
 qemu_socket.h   |   10 ++++---
 qerror.c        |   20 ++++++++++++++
 qerror.h        |   15 +++++++++++
 ui/vnc.c        |    5 ++--
 vl.c            |    7 ++++-
 11 files changed, 138 insertions(+), 85 deletions(-)

-- 
Amos Kong

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings
  2012-05-08 14:58 [Qemu-devel] [PATCH v11 0/4] support to migrate with IPv6 address Amos Kong
@ 2012-05-08 14:58 ` Amos Kong
  2012-05-10 16:00   ` Michael Roth
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 2/4] sockets: change inet_connect() to support nonblock socket Amos Kong
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Amos Kong @ 2012-05-08 14:58 UTC (permalink / raw)
  To: aliguori, quintela, jasowang, mdroth, qemu-devel, owasserm, laine

Add five new qerror strings, they are about listen/connect socket:
  QERR_SOCKET_CONNECT_IN_PROGRESS
  QERR_SOCKET_CONNECT_FAILED
  QERR_SOCKET_LISTEN_FAILED
  QERR_SOCKET_BIND_FAILED
  QERR_SOCKET_CREATE_FAILED

Signed-off-by: Amos Kong <akong@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
---
 qerror.c |   20 ++++++++++++++++++++
 qerror.h |   15 +++++++++++++++
 2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/qerror.c b/qerror.c
index 96fbe71..2963b8c 100644
--- a/qerror.c
+++ b/qerror.c
@@ -304,6 +304,26 @@ static const QErrorStringTable qerror_table[] = {
         .error_fmt = QERR_VNC_SERVER_FAILED,
         .desc      = "Could not start VNC server on %(target)",
     },
+    {
+        .error_fmt = QERR_SOCKET_CONNECT_IN_PROGRESS,
+        .desc      = "Connection can not be completed immediately",
+    },
+    {
+        .error_fmt = QERR_SOCKET_CONNECT_FAILED,
+        .desc      = "Failed to connect socket",
+    },
+    {
+        .error_fmt = QERR_SOCKET_LISTEN_FAILED,
+        .desc      = "Failed to listen socket",
+    },
+    {
+        .error_fmt = QERR_SOCKET_BIND_FAILED,
+        .desc      = "Failed to bind socket",
+    },
+    {
+        .error_fmt = QERR_SOCKET_CREATE_FAILED,
+        .desc      = "Failed to create socket",
+    },
     {}
 };
 
diff --git a/qerror.h b/qerror.h
index 5c23c1f..4cbba48 100644
--- a/qerror.h
+++ b/qerror.h
@@ -248,4 +248,19 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_VNC_SERVER_FAILED \
     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
 
+#define QERR_SOCKET_CONNECT_IN_PROGRESS \
+    "{ 'class': 'SockConnectInprogress', 'data': {} }"
+
+#define QERR_SOCKET_CONNECT_FAILED \
+    "{ 'class': 'SockConnectFailed', 'data': {} }"
+
+#define QERR_SOCKET_LISTEN_FAILED \
+    "{ 'class': 'SockListenFailed', 'data': {} }"
+
+#define QERR_SOCKET_BIND_FAILED \
+    "{ 'class': 'SockBindFailed', 'data': {} }"
+
+#define QERR_SOCKET_CREATE_FAILED \
+    "{ 'class': 'SockCreateFailed', 'data': {} }"
+
 #endif /* QERROR_H */

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v11 2/4] sockets: change inet_connect() to support nonblock socket
  2012-05-08 14:58 [Qemu-devel] [PATCH v11 0/4] support to migrate with IPv6 address Amos Kong
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings Amos Kong
@ 2012-05-08 14:58 ` Amos Kong
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 3/4] sockets: use error class to pass listen error Amos Kong
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 4/4] use inet_listen()/inet_connect() to support ipv6 migration Amos Kong
  3 siblings, 0 replies; 7+ messages in thread
From: Amos Kong @ 2012-05-08 14:58 UTC (permalink / raw)
  To: aliguori, quintela, jasowang, mdroth, qemu-devel, owasserm, laine

Add a bool argument to inet_connect() to assign if set socket
to block/nonblock, and delete original argument 'socktype'
that is unused.
Add a new argument to inet_connect()/inet_connect_opts(),
to pass back connect error by error class.

Retry to connect when -EINTR is got. Connect's successful
for nonblock socket when following errors are got, user
should wait for connecting by select():
  -EINPROGRESS
  -EWOULDBLOCK (win32)
  -WSAEALREADY (win32)

Change nbd, vnc to use new interface.

Signed-off-by: Amos Kong <akong@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 nbd.c          |    2 +-
 qemu-char.c    |    2 +-
 qemu-sockets.c |   43 +++++++++++++++++++++++++++++++++++++------
 qemu_socket.h  |    6 ++++--
 ui/vnc.c       |    2 +-
 5 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/nbd.c b/nbd.c
index 153709f..bebfc49 100644
--- a/nbd.c
+++ b/nbd.c
@@ -162,7 +162,7 @@ int tcp_socket_outgoing(const char *address, uint16_t port)
 
 int tcp_socket_outgoing_spec(const char *address_and_port)
 {
-    return inet_connect(address_and_port, SOCK_STREAM);
+    return inet_connect(address_and_port, true, NULL);
 }
 
 int tcp_socket_incoming(const char *address, uint16_t port)
diff --git a/qemu-char.c b/qemu-char.c
index a9fc504..060bf9d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2446,7 +2446,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
         if (is_listen) {
             fd = inet_listen_opts(opts, 0);
         } else {
-            fd = inet_connect_opts(opts);
+            fd = inet_connect_opts(opts, NULL);
         }
     }
     if (fd < 0) {
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 6bcb8e3..ce3f06c 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -51,6 +51,9 @@ static QemuOptsList dummy_opts = {
         },{
             .name = "ipv6",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "block",
+            .type = QEMU_OPT_BOOL,
         },
         { /* end if list */ }
     },
@@ -194,7 +197,7 @@ listen:
     return slisten;
 }
 
-int inet_connect_opts(QemuOpts *opts)
+int inet_connect_opts(QemuOpts *opts, Error **errp)
 {
     struct addrinfo ai,*res,*e;
     const char *addr;
@@ -202,6 +205,7 @@ int inet_connect_opts(QemuOpts *opts)
     char uaddr[INET6_ADDRSTRLEN+1];
     char uport[33];
     int sock,rc;
+    bool block;
 
     memset(&ai,0, sizeof(ai));
     ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
@@ -210,8 +214,10 @@ int inet_connect_opts(QemuOpts *opts)
 
     addr = qemu_opt_get(opts, "host");
     port = qemu_opt_get(opts, "port");
+    block = qemu_opt_get_bool(opts, "block", 0);
     if (addr == NULL || port == NULL) {
         fprintf(stderr, "inet_connect: host and/or port not specified\n");
+        error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;
     }
 
@@ -224,6 +230,7 @@ int inet_connect_opts(QemuOpts *opts)
     if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
         fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
                 gai_strerror(rc));
+        error_set(errp, QERR_SOCKET_CREATE_FAILED);
 	return -1;
     }
 
@@ -241,19 +248,37 @@ int inet_connect_opts(QemuOpts *opts)
             continue;
         }
         setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
-
+        if (!block) {
+            socket_set_nonblock(sock);
+        }
         /* connect to peer */
-        if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
+        do {
+            rc = 0;
+            if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) {
+                rc = -socket_error();
+            }
+        } while (rc == -EINTR);
+
+  #ifdef _WIN32
+        if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK
+                       || rc == -WSAEALREADY)) {
+  #else
+        if (!block && (rc == -EINPROGRESS)) {
+  #endif
+            error_set(errp, QERR_SOCKET_CONNECT_IN_PROGRESS);
+        } else if (rc < 0) {
             if (NULL == e->ai_next)
                 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
                         inet_strfamily(e->ai_family),
                         e->ai_canonname, uaddr, uport, strerror(errno));
             closesocket(sock);
+            sock = -1;
             continue;
         }
         freeaddrinfo(res);
         return sock;
     }
+    error_set(errp, QERR_SOCKET_CONNECT_FAILED);
     freeaddrinfo(res);
     return -1;
 }
@@ -449,14 +474,20 @@ int inet_listen(const char *str, char *ostr, int olen,
     return sock;
 }
 
-int inet_connect(const char *str, int socktype)
+int inet_connect(const char *str, bool block, Error **errp)
 {
     QemuOpts *opts;
     int sock = -1;
 
     opts = qemu_opts_create(&dummy_opts, NULL, 0);
-    if (inet_parse(opts, str) == 0)
-        sock = inet_connect_opts(opts);
+    if (inet_parse(opts, str) == 0) {
+        if (block) {
+            qemu_opt_set(opts, "block", "on");
+        }
+        sock = inet_connect_opts(opts, errp);
+    } else {
+        error_set(errp, QERR_SOCKET_CREATE_FAILED);
+    }
     qemu_opts_del(opts);
     return sock;
 }
diff --git a/qemu_socket.h b/qemu_socket.h
index a5d0a84..26998ef 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -27,6 +27,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
 #endif /* !_WIN32 */
 
 #include "qemu-option.h"
+#include "error.h"
+#include "qerror.h"
 
 /* misc helpers */
 int qemu_socket(int domain, int type, int protocol);
@@ -40,8 +42,8 @@ int send_all(int fd, const void *buf, int len1);
 int inet_listen_opts(QemuOpts *opts, int port_offset);
 int inet_listen(const char *str, char *ostr, int olen,
                 int socktype, int port_offset);
-int inet_connect_opts(QemuOpts *opts);
-int inet_connect(const char *str, int socktype);
+int inet_connect_opts(QemuOpts *opts, Error **errp);
+int inet_connect(const char *str, bool block, Error **errp);
 int inet_dgram_opts(QemuOpts *opts);
 const char *inet_strfamily(int family);
 
diff --git a/ui/vnc.c b/ui/vnc.c
index deb9ecd..3ae7704 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3068,7 +3068,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
         if (strncmp(display, "unix:", 5) == 0)
             vs->lsock = unix_connect(display+5);
         else
-            vs->lsock = inet_connect(display, SOCK_STREAM);
+            vs->lsock = inet_connect(display, true, NULL);
         if (-1 == vs->lsock) {
             g_free(vs->display);
             vs->display = NULL;

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v11 3/4] sockets: use error class to pass listen error
  2012-05-08 14:58 [Qemu-devel] [PATCH v11 0/4] support to migrate with IPv6 address Amos Kong
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings Amos Kong
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 2/4] sockets: change inet_connect() to support nonblock socket Amos Kong
@ 2012-05-08 14:58 ` Amos Kong
  2012-05-10 16:03   ` Michael Roth
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 4/4] use inet_listen()/inet_connect() to support ipv6 migration Amos Kong
  3 siblings, 1 reply; 7+ messages in thread
From: Amos Kong @ 2012-05-08 14:58 UTC (permalink / raw)
  To: aliguori, quintela, jasowang, mdroth, qemu-devel, owasserm, laine

Add a new argument in inet_listen()/inet_listen_opts()
to pass back listen error.

Change nbd, qemu-char, vnc to use new interface.

Signed-off-by: Amos Kong <akong@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
---
 nbd.c          |    2 +-
 qemu-char.c    |    2 +-
 qemu-sockets.c |   17 ++++++++++++++---
 qemu_socket.h  |    4 ++--
 ui/vnc.c       |    3 ++-
 5 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/nbd.c b/nbd.c
index bebfc49..dc0adf9 100644
--- a/nbd.c
+++ b/nbd.c
@@ -176,7 +176,7 @@ int tcp_socket_incoming_spec(const char *address_and_port)
 {
     char *ostr  = NULL;
     int olen = 0;
-    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0);
+    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0, NULL);
 }
 
 int unix_socket_incoming(const char *path)
diff --git a/qemu-char.c b/qemu-char.c
index 060bf9d..fe1126f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2444,7 +2444,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
         }
     } else {
         if (is_listen) {
-            fd = inet_listen_opts(opts, 0);
+            fd = inet_listen_opts(opts, 0, NULL);
         } else {
             fd = inet_connect_opts(opts, NULL);
         }
diff --git a/qemu-sockets.c b/qemu-sockets.c
index ce3f06c..46c7619 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -103,7 +103,7 @@ const char *inet_strfamily(int family)
     return "unknown";
 }
 
-int inet_listen_opts(QemuOpts *opts, int port_offset)
+int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
 {
     struct addrinfo ai,*res,*e;
     const char *addr;
@@ -120,6 +120,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
     if ((qemu_opt_get(opts, "host") == NULL) ||
         (qemu_opt_get(opts, "port") == NULL)) {
         fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
+        error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;
     }
     pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
@@ -138,6 +139,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
     if (rc != 0) {
         fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
                 gai_strerror(rc));
+        error_set(errp, QERR_SOCKET_CREATE_FAILED);
         return -1;
     }
 
@@ -150,6 +152,9 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
         if (slisten < 0) {
             fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
                     inet_strfamily(e->ai_family), strerror(errno));
+            if (!e->ai_next) {
+                error_set(errp, QERR_SOCKET_CREATE_FAILED);
+            }
             continue;
         }
 
@@ -173,6 +178,9 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
                 fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
                         inet_strfamily(e->ai_family), uaddr, inet_getport(e),
                         strerror(errno));
+                if (!e->ai_next) {
+                    error_set(errp, QERR_SOCKET_BIND_FAILED);
+                }
             }
         }
         closesocket(slisten);
@@ -183,6 +191,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
 
 listen:
     if (listen(slisten,1) != 0) {
+        error_set(errp, QERR_SOCKET_LISTEN_FAILED);
         perror("listen");
         closesocket(slisten);
         freeaddrinfo(res);
@@ -446,7 +455,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
 }
 
 int inet_listen(const char *str, char *ostr, int olen,
-                int socktype, int port_offset)
+                int socktype, int port_offset, Error **errp)
 {
     QemuOpts *opts;
     char *optstr;
@@ -454,7 +463,7 @@ int inet_listen(const char *str, char *ostr, int olen,
 
     opts = qemu_opts_create(&dummy_opts, NULL, 0);
     if (inet_parse(opts, str) == 0) {
-        sock = inet_listen_opts(opts, port_offset);
+        sock = inet_listen_opts(opts, port_offset, errp);
         if (sock != -1 && ostr) {
             optstr = strchr(str, ',');
             if (qemu_opt_get_bool(opts, "ipv6", 0)) {
@@ -469,6 +478,8 @@ int inet_listen(const char *str, char *ostr, int olen,
                          optstr ? optstr : "");
             }
         }
+    } else {
+        error_set(errp, QERR_SOCKET_CREATE_FAILED);
     }
     qemu_opts_del(opts);
     return sock;
diff --git a/qemu_socket.h b/qemu_socket.h
index 26998ef..4689ff3 100644
--- a/qemu_socket.h
+++ b/qemu_socket.h
@@ -39,9 +39,9 @@ void socket_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
 
 /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
-int inet_listen_opts(QemuOpts *opts, int port_offset);
+int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
 int inet_listen(const char *str, char *ostr, int olen,
-                int socktype, int port_offset);
+                int socktype, int port_offset, Error **errp);
 int inet_connect_opts(QemuOpts *opts, Error **errp);
 int inet_connect(const char *str, bool block, Error **errp);
 int inet_dgram_opts(QemuOpts *opts);
diff --git a/ui/vnc.c b/ui/vnc.c
index 3ae7704..be384a5 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3088,7 +3088,8 @@ int vnc_display_open(DisplayState *ds, const char *display)
             pstrcpy(dpy, 256, "unix:");
             vs->lsock = unix_listen(display+5, dpy+5, 256-5);
         } else {
-            vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
+            vs->lsock = inet_listen(display, dpy, 256,
+                                    SOCK_STREAM, 5900, NULL);
         }
         if (-1 == vs->lsock) {
             g_free(dpy);

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [Qemu-devel] [PATCH v11 4/4] use inet_listen()/inet_connect() to support ipv6 migration
  2012-05-08 14:58 [Qemu-devel] [PATCH v11 0/4] support to migrate with IPv6 address Amos Kong
                   ` (2 preceding siblings ...)
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 3/4] sockets: use error class to pass listen error Amos Kong
@ 2012-05-08 14:58 ` Amos Kong
  3 siblings, 0 replies; 7+ messages in thread
From: Amos Kong @ 2012-05-08 14:58 UTC (permalink / raw)
  To: aliguori, quintela, jasowang, mdroth, qemu-devel, owasserm, laine

Use help functions in qemu-socket.c for tcp migration,
which already support ipv6 addresses.

Currently errp will be set to UNDEFINED_ERROR when migration fails,
qemu would output "migration failed: ...", and current user can
see a message("An undefined error has occurred") in monitor.

This patch changed tcp_start_outgoing_migration()/inet_connect()
/inet_connect_opts(), socket error would be passed back,
then current user can see a meaningful err message in monitor.

Qemu will exit if listening fails, so output socket error
to qemu stderr.

For IPv6 brackets must be mandatory if you require a port.
Referencing to RFC5952, the recommended format is:
  [2312::8274]:5200

test status: Successed
listen side: qemu-kvm .... -incoming tcp:[2312::8274]:5200
client side: qemu-kvm ...
             (qemu) migrate -d tcp:[2312::8274]:5200

Signed-off-by: Amos Kong <akong@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 migration-tcp.c |   77 +++++++++++++++----------------------------------------
 migration.c     |   14 ++++++----
 migration.h     |    7 +++--
 vl.c            |    7 ++++-
 4 files changed, 39 insertions(+), 66 deletions(-)

diff --git a/migration-tcp.c b/migration-tcp.c
index 35a5781..440804d 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -79,45 +79,32 @@ static void tcp_wait_for_connect(void *opaque)
     }
 }
 
-int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
+int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
+                                 Error **errp)
 {
-    struct sockaddr_in addr;
-    int ret;
-
-    ret = parse_host_port(&addr, host_port);
-    if (ret < 0) {
-        return ret;
-    }
-
     s->get_error = socket_errno;
     s->write = socket_write;
     s->close = tcp_close;
 
-    s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
-    if (s->fd == -1) {
-        DPRINTF("Unable to open socket");
-        return -socket_error();
-    }
-
-    socket_set_nonblock(s->fd);
-
-    do {
-        ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
-        if (ret == -1) {
-            ret = -socket_error();
-        }
-        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
-            qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
-            return 0;
-        }
-    } while (ret == -EINTR);
+    s->fd = inet_connect(host_port, false, errp);
 
-    if (ret < 0) {
+    if (!error_is_set(errp)) {
+        migrate_fd_connect(s);
+    } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_IN_PROGRESS)) {
+        DPRINTF("connect in progress\n");
+        qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
+    } else if (error_is_type(*errp, QERR_SOCKET_CREATE_FAILED)) {
+        DPRINTF("connect failed\n");
+        return -1;
+    } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_FAILED)) {
         DPRINTF("connect failed\n");
         migrate_fd_error(s);
-        return ret;
+        return -1;
+    } else {
+        DPRINTF("unknown error\n");
+        return -1;
     }
-    migrate_fd_connect(s);
+
     return 0;
 }
 
@@ -155,40 +142,18 @@ out2:
     close(s);
 }
 
-int tcp_start_incoming_migration(const char *host_port)
+int tcp_start_incoming_migration(const char *host_port, Error **errp)
 {
-    struct sockaddr_in addr;
-    int val;
     int s;
 
-    DPRINTF("Attempting to start an incoming migration\n");
-
-    if (parse_host_port(&addr, host_port) < 0) {
-        fprintf(stderr, "invalid host/port combination: %s\n", host_port);
-        return -EINVAL;
-    }
-
-    s = qemu_socket(PF_INET, SOCK_STREAM, 0);
-    if (s == -1) {
-        return -socket_error();
-    }
-
-    val = 1;
-    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
+    s = inet_listen(host_port, NULL, 256, SOCK_STREAM, 0, errp);
 
-    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-        goto err;
-    }
-    if (listen(s, 1) == -1) {
-        goto err;
+    if (s < 0) {
+        return -1;
     }
 
     qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
                          (void *)(intptr_t)s);
 
     return 0;
-
-err:
-    close(s);
-    return -socket_error();
 }
diff --git a/migration.c b/migration.c
index 94f7839..6289bc7 100644
--- a/migration.c
+++ b/migration.c
@@ -60,13 +60,13 @@ static MigrationState *migrate_get_current(void)
     return &current_migration;
 }
 
-int qemu_start_incoming_migration(const char *uri)
+int qemu_start_incoming_migration(const char *uri, Error **errp)
 {
     const char *p;
     int ret;
 
     if (strstart(uri, "tcp:", &p))
-        ret = tcp_start_incoming_migration(p);
+        ret = tcp_start_incoming_migration(p, errp);
 #if !defined(WIN32)
     else if (strstart(uri, "exec:", &p))
         ret =  exec_start_incoming_migration(p);
@@ -413,7 +413,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
     s = migrate_init(blk, inc);
 
     if (strstart(uri, "tcp:", &p)) {
-        ret = tcp_start_outgoing_migration(s, p);
+        ret = tcp_start_outgoing_migration(s, p, errp);
 #if !defined(WIN32)
     } else if (strstart(uri, "exec:", &p)) {
         ret = exec_start_outgoing_migration(s, p);
@@ -428,9 +428,11 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
     }
 
     if (ret < 0) {
-        DPRINTF("migration failed: %s\n", strerror(-ret));
-        /* FIXME: we should return meaningful errors */
-        error_set(errp, QERR_UNDEFINED_ERROR);
+        if (!error_is_set(errp)) {
+            DPRINTF("migration failed: %s\n", strerror(-ret));
+            /* FIXME: we should return meaningful errors */
+            error_set(errp, QERR_UNDEFINED_ERROR);
+        }
         return;
     }
 
diff --git a/migration.h b/migration.h
index 691b367..2e9ca2e 100644
--- a/migration.h
+++ b/migration.h
@@ -37,7 +37,7 @@ struct MigrationState
 
 void process_incoming_migration(QEMUFile *f);
 
-int qemu_start_incoming_migration(const char *uri);
+int qemu_start_incoming_migration(const char *uri, Error **errp);
 
 uint64_t migrate_max_downtime(void);
 
@@ -49,9 +49,10 @@ int exec_start_incoming_migration(const char *host_port);
 
 int exec_start_outgoing_migration(MigrationState *s, const char *host_port);
 
-int tcp_start_incoming_migration(const char *host_port);
+int tcp_start_incoming_migration(const char *host_port, Error **errp);
 
-int tcp_start_outgoing_migration(MigrationState *s, const char *host_port);
+int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
+                                 Error **errp);
 
 int unix_start_incoming_migration(const char *path);
 
diff --git a/vl.c b/vl.c
index ae91a8a..7dd7a04 100644
--- a/vl.c
+++ b/vl.c
@@ -3627,8 +3627,13 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (incoming) {
-        int ret = qemu_start_incoming_migration(incoming);
+        Error *errp = NULL;
+        int ret = qemu_start_incoming_migration(incoming, &errp);
         if (ret < 0) {
+            if (error_is_set(&errp)) {
+                fprintf(stderr, "Migrate: %s\n", error_get_pretty(errp));
+                error_free(errp);
+            }
             fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
                     incoming, ret);
             exit(ret);

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings Amos Kong
@ 2012-05-10 16:00   ` Michael Roth
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Roth @ 2012-05-10 16:00 UTC (permalink / raw)
  To: Amos Kong; +Cc: aliguori, quintela, jasowang, qemu-devel, owasserm, laine

On Tue, May 08, 2012 at 10:58:22PM +0800, Amos Kong wrote:
> Add five new qerror strings, they are about listen/connect socket:
>   QERR_SOCKET_CONNECT_IN_PROGRESS
>   QERR_SOCKET_CONNECT_FAILED
>   QERR_SOCKET_LISTEN_FAILED
>   QERR_SOCKET_BIND_FAILED
>   QERR_SOCKET_CREATE_FAILED
> 
> Signed-off-by: Amos Kong <akong@redhat.com>
> Reviewed-by: Orit Wasserman <owasserm@redhat.com>

http://permalink.gmane.org/gmane.comp.emulators.qemu/146969

> ---
>  qerror.c |   20 ++++++++++++++++++++
>  qerror.h |   15 +++++++++++++++
>  2 files changed, 35 insertions(+), 0 deletions(-)
> 
> diff --git a/qerror.c b/qerror.c
> index 96fbe71..2963b8c 100644
> --- a/qerror.c
> +++ b/qerror.c
> @@ -304,6 +304,26 @@ static const QErrorStringTable qerror_table[] = {
>          .error_fmt = QERR_VNC_SERVER_FAILED,
>          .desc      = "Could not start VNC server on %(target)",
>      },
> +    {
> +        .error_fmt = QERR_SOCKET_CONNECT_IN_PROGRESS,
> +        .desc      = "Connection can not be completed immediately",
> +    },
> +    {
> +        .error_fmt = QERR_SOCKET_CONNECT_FAILED,
> +        .desc      = "Failed to connect socket",
> +    },
> +    {
> +        .error_fmt = QERR_SOCKET_LISTEN_FAILED,
> +        .desc      = "Failed to listen socket",
> +    },
> +    {
> +        .error_fmt = QERR_SOCKET_BIND_FAILED,
> +        .desc      = "Failed to bind socket",
> +    },
> +    {
> +        .error_fmt = QERR_SOCKET_CREATE_FAILED,
> +        .desc      = "Failed to create socket",
> +    },
>      {}
>  };
> 
> diff --git a/qerror.h b/qerror.h
> index 5c23c1f..4cbba48 100644
> --- a/qerror.h
> +++ b/qerror.h
> @@ -248,4 +248,19 @@ QError *qobject_to_qerror(const QObject *obj);
>  #define QERR_VNC_SERVER_FAILED \
>      "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
> 
> +#define QERR_SOCKET_CONNECT_IN_PROGRESS \
> +    "{ 'class': 'SockConnectInprogress', 'data': {} }"
> +
> +#define QERR_SOCKET_CONNECT_FAILED \
> +    "{ 'class': 'SockConnectFailed', 'data': {} }"
> +
> +#define QERR_SOCKET_LISTEN_FAILED \
> +    "{ 'class': 'SockListenFailed', 'data': {} }"
> +
> +#define QERR_SOCKET_BIND_FAILED \
> +    "{ 'class': 'SockBindFailed', 'data': {} }"
> +
> +#define QERR_SOCKET_CREATE_FAILED \
> +    "{ 'class': 'SockCreateFailed', 'data': {} }"
> +
>  #endif /* QERROR_H */
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Qemu-devel] [PATCH v11 3/4] sockets: use error class to pass listen error
  2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 3/4] sockets: use error class to pass listen error Amos Kong
@ 2012-05-10 16:03   ` Michael Roth
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Roth @ 2012-05-10 16:03 UTC (permalink / raw)
  To: Amos Kong; +Cc: aliguori, quintela, jasowang, qemu-devel, owasserm, laine

On Tue, May 08, 2012 at 10:58:40PM +0800, Amos Kong wrote:
> Add a new argument in inet_listen()/inet_listen_opts()
> to pass back listen error.
> 
> Change nbd, qemu-char, vnc to use new interface.
> 
> Signed-off-by: Amos Kong <akong@redhat.com>
> Reviewed-by: Orit Wasserman <owasserm@redhat.com>

Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>

> ---
>  nbd.c          |    2 +-
>  qemu-char.c    |    2 +-
>  qemu-sockets.c |   17 ++++++++++++++---
>  qemu_socket.h  |    4 ++--
>  ui/vnc.c       |    3 ++-
>  5 files changed, 20 insertions(+), 8 deletions(-)
> 
> diff --git a/nbd.c b/nbd.c
> index bebfc49..dc0adf9 100644
> --- a/nbd.c
> +++ b/nbd.c
> @@ -176,7 +176,7 @@ int tcp_socket_incoming_spec(const char *address_and_port)
>  {
>      char *ostr  = NULL;
>      int olen = 0;
> -    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0);
> +    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0, NULL);
>  }
> 
>  int unix_socket_incoming(const char *path)
> diff --git a/qemu-char.c b/qemu-char.c
> index 060bf9d..fe1126f 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -2444,7 +2444,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
>          }
>      } else {
>          if (is_listen) {
> -            fd = inet_listen_opts(opts, 0);
> +            fd = inet_listen_opts(opts, 0, NULL);
>          } else {
>              fd = inet_connect_opts(opts, NULL);
>          }
> diff --git a/qemu-sockets.c b/qemu-sockets.c
> index ce3f06c..46c7619 100644
> --- a/qemu-sockets.c
> +++ b/qemu-sockets.c
> @@ -103,7 +103,7 @@ const char *inet_strfamily(int family)
>      return "unknown";
>  }
> 
> -int inet_listen_opts(QemuOpts *opts, int port_offset)
> +int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
>  {
>      struct addrinfo ai,*res,*e;
>      const char *addr;
> @@ -120,6 +120,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>      if ((qemu_opt_get(opts, "host") == NULL) ||
>          (qemu_opt_get(opts, "port") == NULL)) {
>          fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
> +        error_set(errp, QERR_SOCKET_CREATE_FAILED);
>          return -1;
>      }
>      pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
> @@ -138,6 +139,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>      if (rc != 0) {
>          fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
>                  gai_strerror(rc));
> +        error_set(errp, QERR_SOCKET_CREATE_FAILED);
>          return -1;
>      }
> 
> @@ -150,6 +152,9 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>          if (slisten < 0) {
>              fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
>                      inet_strfamily(e->ai_family), strerror(errno));
> +            if (!e->ai_next) {
> +                error_set(errp, QERR_SOCKET_CREATE_FAILED);
> +            }
>              continue;
>          }
> 
> @@ -173,6 +178,9 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
>                  fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
>                          inet_strfamily(e->ai_family), uaddr, inet_getport(e),
>                          strerror(errno));
> +                if (!e->ai_next) {
> +                    error_set(errp, QERR_SOCKET_BIND_FAILED);
> +                }
>              }
>          }
>          closesocket(slisten);
> @@ -183,6 +191,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
> 
>  listen:
>      if (listen(slisten,1) != 0) {
> +        error_set(errp, QERR_SOCKET_LISTEN_FAILED);
>          perror("listen");
>          closesocket(slisten);
>          freeaddrinfo(res);
> @@ -446,7 +455,7 @@ static int inet_parse(QemuOpts *opts, const char *str)
>  }
> 
>  int inet_listen(const char *str, char *ostr, int olen,
> -                int socktype, int port_offset)
> +                int socktype, int port_offset, Error **errp)
>  {
>      QemuOpts *opts;
>      char *optstr;
> @@ -454,7 +463,7 @@ int inet_listen(const char *str, char *ostr, int olen,
> 
>      opts = qemu_opts_create(&dummy_opts, NULL, 0);
>      if (inet_parse(opts, str) == 0) {
> -        sock = inet_listen_opts(opts, port_offset);
> +        sock = inet_listen_opts(opts, port_offset, errp);
>          if (sock != -1 && ostr) {
>              optstr = strchr(str, ',');
>              if (qemu_opt_get_bool(opts, "ipv6", 0)) {
> @@ -469,6 +478,8 @@ int inet_listen(const char *str, char *ostr, int olen,
>                           optstr ? optstr : "");
>              }
>          }
> +    } else {
> +        error_set(errp, QERR_SOCKET_CREATE_FAILED);
>      }
>      qemu_opts_del(opts);
>      return sock;
> diff --git a/qemu_socket.h b/qemu_socket.h
> index 26998ef..4689ff3 100644
> --- a/qemu_socket.h
> +++ b/qemu_socket.h
> @@ -39,9 +39,9 @@ void socket_set_nonblock(int fd);
>  int send_all(int fd, const void *buf, int len1);
> 
>  /* New, ipv6-ready socket helper functions, see qemu-sockets.c */
> -int inet_listen_opts(QemuOpts *opts, int port_offset);
> +int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp);
>  int inet_listen(const char *str, char *ostr, int olen,
> -                int socktype, int port_offset);
> +                int socktype, int port_offset, Error **errp);
>  int inet_connect_opts(QemuOpts *opts, Error **errp);
>  int inet_connect(const char *str, bool block, Error **errp);
>  int inet_dgram_opts(QemuOpts *opts);
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 3ae7704..be384a5 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -3088,7 +3088,8 @@ int vnc_display_open(DisplayState *ds, const char *display)
>              pstrcpy(dpy, 256, "unix:");
>              vs->lsock = unix_listen(display+5, dpy+5, 256-5);
>          } else {
> -            vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
> +            vs->lsock = inet_listen(display, dpy, 256,
> +                                    SOCK_STREAM, 5900, NULL);
>          }
>          if (-1 == vs->lsock) {
>              g_free(dpy);
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-05-10 16:03 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-08 14:58 [Qemu-devel] [PATCH v11 0/4] support to migrate with IPv6 address Amos Kong
2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 1/4] qerror: add five qerror strings Amos Kong
2012-05-10 16:00   ` Michael Roth
2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 2/4] sockets: change inet_connect() to support nonblock socket Amos Kong
2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 3/4] sockets: use error class to pass listen error Amos Kong
2012-05-10 16:03   ` Michael Roth
2012-05-08 14:58 ` [Qemu-devel] [PATCH v11 4/4] use inet_listen()/inet_connect() to support ipv6 migration Amos Kong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).