* [PATCH]: Implement tcp "nowait" option for migration
@ 2008-08-01 9:07 Chris Lalancette
2008-08-06 9:26 ` Chris Lalancette
0 siblings, 1 reply; 2+ messages in thread
From: Chris Lalancette @ 2008-08-01 9:07 UTC (permalink / raw)
To: kvm-devel
[-- Attachment #1: Type: text/plain, Size: 542 bytes --]
Sometimes you want to be able to start up the receiving side of a live migration
and actually be able to run monitor commands before you do the migration.
Libvirt, in particular, wants to do this for setting up the migration. This
patch implements a "nowait" option to the receiving side so that you start up
the receiving side similar to:
qemu-kvm -M pc -S blah blah -incoming tcp://0:4444,nowait
Then you are able to interact with the monitor before the live migration takes
place.
Signed-off-by: Chris Lalancette <clalance@redhat.com>
[-- Attachment #2: qemu-migration-nowait.patch --]
[-- Type: text/x-patch, Size: 4101 bytes --]
diff --git a/qemu/migration.c b/qemu/migration.c
index a64a287..d16e289 100644
--- a/qemu/migration.c
+++ b/qemu/migration.c
@@ -886,13 +886,10 @@ static int migrate_incoming_fd(int fd)
return ret;
}
-static int migrate_incoming_tcp(const char *host)
+static int migrate_listen_tcp(const char *host, int *outfd)
{
struct sockaddr_in addr;
- socklen_t addrlen = sizeof(addr);
- int fd, sfd;
- ssize_t len;
- uint8_t status = 0;
+ int fd = -1;
int reuse = 1;
int rc;
@@ -928,19 +925,43 @@ static int migrate_incoming_tcp(const char *host)
goto error_socket;
}
+ *outfd = fd;
+
+ return 0;
+
+error_socket:
+ close(fd);
+error:
+ return rc;
+}
+
+struct migrate_tcp_data {
+ int listen_fd;
+ int rc;
+};
+
+static void migrate_incoming_tcp(void *opaque)
+{
+ struct sockaddr_in addr;
+ socklen_t addrlen = sizeof(addr);
+ struct migrate_tcp_data *data = (struct migrate_tcp_data *)opaque;
+ int sfd;
+ ssize_t len;
+ uint8_t status = 0;
+
again:
- sfd = accept(fd, (struct sockaddr *)&addr, &addrlen);
+ sfd = accept(data->listen_fd, (struct sockaddr *)&addr, &addrlen);
if (sfd == -1) {
if (errno == EINTR)
goto again;
perror("accept() failed");
- rc = MIG_STAT_DST_ACCEPT_FAILED;
+ data->rc = MIG_STAT_DST_ACCEPT_FAILED;
goto error_socket;
}
- rc = migrate_incoming_fd(sfd);
- if (rc != 0) {
- fprintf(stderr, "migrate_incoming_fd failed (rc=%d)\n", rc);
+ data->rc = migrate_incoming_fd(sfd);
+ if (data->rc != 0) {
+ fprintf(stderr, "migrate_incoming_fd failed (rc=%d)\n", data->rc);
goto error_accept;
}
@@ -951,13 +972,13 @@ send_ack:
if (len != 1) {
fprintf(stderr, "migration: send_ack: write error len=%zu (%s)\n",
len, strerror(errno));
- rc = MIG_STAT_DST_WRITE_FAILED;
+ data->rc = MIG_STAT_DST_WRITE_FAILED;
goto error_accept;
}
- rc = wait_for_message("WAIT FOR GO", sfd, wait_for_message_timeout);
- if (rc) {
- rc += 200;
+ data->rc = wait_for_message("WAIT FOR GO", sfd, wait_for_message_timeout);
+ if (data->rc) {
+ data->rc += 200;
goto error_accept;
}
@@ -966,7 +987,7 @@ wait_for_go:
if (len == -1 && errno == EAGAIN)
goto wait_for_go;
if (len != 1) {
- rc = MIG_STAT_DST_READ_FAILED;
+ data->rc = MIG_STAT_DST_READ_FAILED;
fprintf(stderr, "migration: wait_for_go: read error len=%zu (%s)\n",
len, strerror(errno));
}
@@ -974,9 +995,10 @@ wait_for_go:
error_accept:
close(sfd);
error_socket:
- close(fd);
-error:
- return rc;
+ qemu_set_fd_handler(data->listen_fd, NULL, NULL, NULL);
+ close(data->listen_fd);
+
+ qemu_free(data);
}
int migrate_incoming(const char *device)
@@ -996,16 +1018,57 @@ int migrate_incoming(const char *device)
}
} else if (strstart(device, "tcp://", &ptr)) {
char *host, *end;
+ struct migrate_tcp_data *data;
+ int is_waitconnect = 1;
+
host = strdup(ptr);
+ if (!host)
+ goto fail;
end = strchr(host, '/');
if (end) *end = 0;
- ret = migrate_incoming_tcp(host);
+
+ data = qemu_mallocz(sizeof(struct migrate_tcp_data));
+ if (!data) {
+ qemu_free(host);
+ goto fail;
+ }
+
+ ptr = host;
+ while((ptr = strchr(ptr,','))) {
+ ptr++;
+ if (!strncmp(ptr,"nowait",6)) {
+ is_waitconnect = 0;
+ } else {
+ printf("Unknown option: %s\n", ptr);
+ qemu_free(host);
+ goto fail;
+ }
+ }
+
+ ret = migrate_listen_tcp(host, &(data->listen_fd));
qemu_free(host);
+ if (ret != 0)
+ goto fail;
+
+ /*
+ * if we made it here, then migrate_incoming_tcp is responsible for
+ * freeing the "data" structure
+ */
+ if (!is_waitconnect) {
+ socket_set_nonblock(data->listen_fd);
+ qemu_set_fd_handler(data->listen_fd, migrate_incoming_tcp, NULL, data);
+ }
+ else {
+ migrate_incoming_tcp(data);
+ ret = data->rc;
+ }
+
} else {
errno = EINVAL;
ret = MIG_STAT_DST_INVALID_PARAMS;
}
+ fail:
return ret;
}
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH]: Implement tcp "nowait" option for migration
2008-08-01 9:07 [PATCH]: Implement tcp "nowait" option for migration Chris Lalancette
@ 2008-08-06 9:26 ` Chris Lalancette
0 siblings, 0 replies; 2+ messages in thread
From: Chris Lalancette @ 2008-08-06 9:26 UTC (permalink / raw)
To: Anthony Liguori; +Cc: kvm-devel
Chris Lalancette wrote:
> Sometimes you want to be able to start up the receiving side of a live migration
> and actually be able to run monitor commands before you do the migration.
> Libvirt, in particular, wants to do this for setting up the migration. This
> patch implements a "nowait" option to the receiving side so that you start up
> the receiving side similar to:
>
> qemu-kvm -M pc -S blah blah -incoming tcp://0:4444,nowait
>
> Then you are able to interact with the monitor before the live migration takes
> place.
Anthony,
Any comments on this patch? I'd like to try to get this in the KVM tree
once Avi gets back, so I would prefer to do any iterations/cleanups now.
Thanks,
Chris Lalancette
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-08-06 9:27 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-01 9:07 [PATCH]: Implement tcp "nowait" option for migration Chris Lalancette
2008-08-06 9:26 ` Chris Lalancette
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox