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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox