From: Chris Lalancette <clalance@redhat.com>
To: kvm-devel <kvm@vger.kernel.org>
Subject: [PATCH]: Implement tcp "nowait" option for migration
Date: Fri, 01 Aug 2008 11:07:13 +0200 [thread overview]
Message-ID: <4892D241.5090000@redhat.com> (raw)
[-- 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;
}
next reply other threads:[~2008-08-01 9:08 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-01 9:07 Chris Lalancette [this message]
2008-08-06 9:26 ` [PATCH]: Implement tcp "nowait" option for migration Chris Lalancette
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=4892D241.5090000@redhat.com \
--to=clalance@redhat.com \
--cc=kvm@vger.kernel.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.