From: Chris Lalancette <clalance@redhat.com>
To: Avi Kivity <avi@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] Migration via unix sockets.
Date: Tue, 11 Aug 2009 11:15:59 +0200 [thread overview]
Message-ID: <4A8136CF.5040304@redhat.com> (raw)
In-Reply-To: <4A8005B4.9030600@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1927 bytes --]
Avi Kivity wrote:
> On 08/10/2009 01:23 PM, Chris Lalancette wrote:
>> Chris Lalancette wrote:
>>
>>> Implement migration via unix sockets. While you can fake this using
>>> exec and netcat, this involves forking another process and is
>>> generally not very nice. By doing this directly in qemu, we can avoid
>>> the copy through the external nc command. This is useful for
>>> implementations (such as libvirt) that want to do "secure" migration;
>>> we pipe the data on the sending side into the unix socket, libvirt
>>> picks it up, encrypts it, and transports it, and then on the remote
>>> side libvirt decrypts it, dumps it to another unix socket, and
>>> feeds it into qemu.
>>>
>>> The implementation is straightforward and looks very similar to
>>> migration-exec.c and migration-tcp.c
>>>
>> ping?
>>
>
> It would be nice to support migration via arbitrary fd using the recent
> SCM_RIGHTS support.
A possible implementation of that is attached. I have to say, though, that it
is way more clumsy to use than the unix implementation I posted earlier. On the
outgoing side, you have to use the "getfd" monitor command to pass the fd using
SCM_RIGHTS, then you have to issue another monitor command to start the migration:
(qemu) getfd migration # passes opened fd via SCM_RIGHTS
(qemu) migrate -d fd:migration
On the incoming side, you have to pass the fd via the command-line. That means
that you have to first arrange for it not to be closed on exec, and it also
means that qemu is now depending on the external program to correctly set up the
incoming socket so that qemu can just do the accept() on it.
None of these problems are insurmountable, but they do make it cumbersome to use
in general, and very difficult to use from the command-line.
The other option is that I've misunderstood your intent, and if that is the
case, please correct me where I'm wrong :).
--
Chris Lalancette
[-- Attachment #2: qemu-migration-fd.patch --]
[-- Type: text/x-patch, Size: 5054 bytes --]
diff --git a/Makefile b/Makefile
index c5763b7..a8cd0c9 100644
--- a/Makefile
+++ b/Makefile
@@ -110,7 +110,7 @@ obj-$(CONFIG_BRLAPI) += baum.o
LIBS+=$(BRLAPI_LIBS)
obj-$(CONFIG_WIN32) += tap-win32.o
-obj-$(CONFIG_POSIX) += migration-exec.o
+obj-$(CONFIG_POSIX) += migration-exec.o migration-fd.o
ifdef CONFIG_COREAUDIO
AUDIO_PT = y
diff --git a/migration-fd.c b/migration-fd.c
new file mode 100644
index 0000000..fea5a43
--- /dev/null
+++ b/migration-fd.c
@@ -0,0 +1,146 @@
+/*
+ * QEMU live migration via generic fd
+ *
+ * Copyright Red Hat, Inc. 2009
+ *
+ * Authors:
+ * Chris Lalancette <clalance@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu_socket.h"
+#include "migration.h"
+#include "monitor.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+#include "buffered_file.h"
+#include "block.h"
+#include "qemu_socket.h"
+
+//#define DEBUG_MIGRATION_FD
+
+#ifdef DEBUG_MIGRATION_FD
+#define dprintf(fmt, ...) \
+ do { printf("migration-fd: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+ do { } while (0)
+#endif
+
+static int fd_errno(FdMigrationState *s)
+{
+ return errno;
+}
+
+static int fd_write(FdMigrationState *s, const void * buf, size_t size)
+{
+ return write(s->fd, buf, size);
+}
+
+static int fd_close(FdMigrationState *s)
+{
+ dprintf("fd_close\n");
+ if (s->fd != -1) {
+ close(s->fd);
+ s->fd = -1;
+ }
+ return 0;
+}
+
+MigrationState *fd_start_outgoing_migration(Monitor *mon,
+ const char *fdname,
+ int64_t bandwidth_limit,
+ int detach)
+{
+ FdMigrationState *s;
+
+ s = qemu_mallocz(sizeof(*s));
+
+ s->fd = monitor_get_fd(mon, fdname);
+ if (s->fd == -1) {
+ dprintf("fd_migration: no file descriptor supplied via SCM_RIGHTS\n");
+ qemu_free(s);
+ return NULL;
+ }
+
+ socket_set_nonblock(s->fd);
+
+ s->get_error = fd_errno;
+ s->write = fd_write;
+ s->close = fd_close;
+ s->mig_state.cancel = migrate_fd_cancel;
+ s->mig_state.get_status = migrate_fd_get_status;
+ s->mig_state.release = migrate_fd_release;
+
+ s->state = MIG_STATE_ACTIVE;
+ s->mon_resume = NULL;
+ s->bandwidth_limit = bandwidth_limit;
+
+ if (!detach)
+ migrate_fd_monitor_suspend(s);
+
+ migrate_fd_connect(s);
+
+ return &s->mig_state;
+}
+
+static void fd_accept_incoming_migration(void *opaque)
+{
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ int s = (unsigned long)opaque;
+ QEMUFile *f;
+ int c, ret;
+
+ do {
+ c = accept(s, &addr, &addrlen);
+ } while (c == -1 && socket_error() == EINTR);
+
+ if (c == -1) {
+ fprintf(stderr, "could not accept migration connection\n");
+ return;
+ }
+
+ dprintf("accepted migration\n");
+
+ f = qemu_fopen_socket(c);
+ if (f == NULL) {
+ fprintf(stderr, "could not qemu_fopen socket\n");
+ goto out;
+ }
+
+ ret = qemu_loadvm_state(f);
+ if (ret < 0) {
+ fprintf(stderr, "load of migration failed\n");
+ goto out_fopen;
+ }
+ qemu_announce_self();
+ dprintf("successfully loaded vm state\n");
+
+ /* we've successfully migrated, close the server socket */
+ qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
+ close(s);
+
+out_fopen:
+ qemu_fclose(f);
+out:
+ close(c);
+}
+
+int fd_start_incoming_migration(const char *infd)
+{
+ int fd;
+
+ dprintf("Attempting to start an fd incoming migration\n");
+
+ fd = strtol(infd, NULL, 0);
+
+ qemu_set_fd_handler2(fd, NULL, fd_accept_incoming_migration, NULL,
+ (void *)(unsigned long)fd);
+
+ return 0;
+}
diff --git a/migration.c b/migration.c
index 34e2bc1..c18d595 100644
--- a/migration.c
+++ b/migration.c
@@ -45,4 +45,6 @@ void qemu_start_incoming_migration(const char *uri)
exec_start_incoming_migration(p);
+ else if (strstart(uri, "fd:", &p))
+ fd_start_incoming_migration(p);
#endif
else
fprintf(stderr, "unknown migration protocol: %s\n", uri);
@@ -62,4 +64,6 @@ void do_migrate(Monitor *mon, int detach, const char *uri)
s = exec_start_outgoing_migration(p, max_throttle, detach);
+ else if (strstart(uri, "fd:", &p))
+ s = fd_start_outgoing_migration(mon, p, max_throttle, detach);
#endif
else
monitor_printf(mon, "unknown migration protocol: %s\n", uri);
diff --git a/migration.h b/migration.h
index 0ed1fcb..96dad38 100644
--- a/migration.h
+++ b/migration.h
@@ -79,6 +79,13 @@ MigrationState *unix_start_outgoing_migration(const char *path,
int64_t bandwidth_limit,
int detach);
+int fd_start_incoming_migration(const char *path);
+
+MigrationState *fd_start_outgoing_migration(Monitor *mon,
+ const char *fdname,
+ int64_t bandwidth_limit,
+ int detach);
+
void migrate_fd_monitor_suspend(FdMigrationState *s);
void migrate_fd_error(FdMigrationState *s);
next prev parent reply other threads:[~2009-08-11 9:16 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-05 15:24 [Qemu-devel] [PATCH] Migration via unix sockets Chris Lalancette
2009-08-10 10:23 ` Chris Lalancette
2009-08-10 11:34 ` Avi Kivity
2009-08-11 9:15 ` Chris Lalancette [this message]
2009-08-11 9:35 ` Avi Kivity
2009-08-11 9:44 ` [Qemu-devel] " Paolo Bonzini
2009-08-11 10:06 ` Avi Kivity
2009-08-12 12:20 ` [Qemu-devel] [PATCH] add file descriptor migration Paolo Bonzini
2009-08-18 13:56 ` [Qemu-devel] [PATCH v2] " Paolo Bonzini
2009-08-18 13:59 ` [Qemu-devel] " Chris Lalancette
2009-08-11 10:20 ` [Qemu-devel] [PATCH] Migration via unix sockets Daniel P. Berrange
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=4A8136CF.5040304@redhat.com \
--to=clalance@redhat.com \
--cc=avi@redhat.com \
--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 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).