From: Uri Lublin <uril@redhat.com>
To: qemu-devel@nongnu.org
Cc: Uri Lublin <uril@redhat.com>
Subject: [Qemu-devel] migration: adding migration to/from a file (v2)
Date: Thu, 19 Feb 2009 13:45:24 +0200 [thread overview]
Message-ID: <499D4654.9000305@redhat.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 583 bytes --]
Migration to file, uses migration-to-fd (supports live migration).
Migration from file, uses qemu-fopen directly.
pre-save:
(qemu) stop # unless you really want live migration
(qemu) migrate_set_speed 3.5G # not needed, speed things up
save:
(qemu) migrate [-d] file:/path/to/state-file
load:
[shell] <qemu> <params> -incoming file:/path/to/state-file
changes from v1:
- making sure write would not block (using select)
- pass max_throttle as is (can be set by user)
- not checking qemu_mallocz
- compile for non-windows as select is being used.
[-- Attachment #2: 0001-migration-adding-migration-to-from-a-file-v2.patch --]
[-- Type: text/x-patch, Size: 6454 bytes --]
>From adfdf0c43b39b3bd3a52612e3748cf7929af9c8c Mon Sep 17 00:00:00 2001
From: Uri Lublin <uril@redhat.com>
Date: Sun, 18 Jan 2009 18:54:14 +0200
Subject: [PATCH] migration: adding migration to/from a file (v2)
Migration to file, uses migration-to-fd.
Migration from file, uses qemu-fopen directly.
The file should be used only once and removed (or used with -snapshot,
or a the disk-image should be copoied), as the disk image is not
saved, only the VM state.
This version uses select to make sure write() will not block.
Thus this solution is limited to non-Windows hosts.
Signed-off-by: Uri Lublin <uril@redhat.com>
---
Makefile | 2 +-
migration-file.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
migration.c | 4 ++
migration.h | 5 ++
4 files changed, 162 insertions(+), 1 deletions(-)
create mode 100644 migration-file.c
diff --git a/Makefile b/Makefile
index 4f7a55a..6d4a8c8 100644
--- a/Makefile
+++ b/Makefile
@@ -94,7 +94,7 @@ endif
ifdef CONFIG_WIN32
OBJS+=tap-win32.o
else
-OBJS+=migration-exec.o
+OBJS+=migration-exec.o migration-file.o
endif
AUDIO_OBJS = audio.o noaudio.o wavaudio.o mixeng.o
diff --git a/migration-file.c b/migration-file.c
new file mode 100644
index 0000000..cc86ef6
--- /dev/null
+++ b/migration-file.c
@@ -0,0 +1,152 @@
+/*
+ * QEMU live migration
+ *
+ * Copyright IBM, Corp. 2008
+ * Red Hat, Inc. 2009
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Uri Lublin <uril@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 <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include "qemu-common.h"
+#include "migration.h"
+#include "hw/hw.h"
+#include "sysemu.h"
+#include "console.h"
+#include "block.h"
+
+//#define DEBUG_MIGRATION_FILE
+
+#ifdef DEBUG_MIGRATION_FILE
+#define dprintf(fmt, ...) \
+ do { printf("migration-file: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define dprintf(fmt, ...) \
+ do { } while (0)
+#endif
+
+static int file_close(FdMigrationState *s)
+{
+ return close(s->fd);
+}
+
+static int file_errno(FdMigrationState *s)
+{
+ return errno;
+}
+
+/* returns 0 if write will not block
+ * returns -1 and sets errno to EAGAIN if write will block
+ * returns -1 upon error (and sets errno)
+ */
+static int will_write_block(int fd)
+{
+ int n;
+ fd_set wfds;
+ struct timeval tv;
+
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ n = select(fd + 1, NULL, &wfds, NULL, &tv);
+ if (n<0)
+ return n;
+
+ if (!FD_ISSET(fd, &wfds)) {
+ /* Don't block, let migration freeze for a while */
+ dprintf("will block -- setting EAGAIN\n");
+ errno = EAGAIN;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int file_write(FdMigrationState *s, const void * buf, size_t size)
+{
+ int ret;
+
+ ret = will_write_block(s->fd);
+ if (ret == 0)
+ ret = write(s->fd, buf, size);
+ return ret;
+}
+
+MigrationState *file_start_outgoing_migration(const char *filename,
+ int64_t bandwidth_limit,
+ int async)
+{
+ FdMigrationState *s;
+ int fd;
+
+ s = qemu_mallocz(sizeof(*s));
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd < 0) {
+ perror("file_migration: failed to open filename");
+ term_printf("file_migration: failed to open filename %s\n", filename);
+ return NULL;
+ }
+
+ s->fd = fd;
+ s->close = file_close;
+ s->get_error = file_errno;
+ s->write = file_write;
+ 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->detach = !async;
+ s->bandwidth_limit = bandwidth_limit;
+
+ dprintf("start migration to file: name=%s limit=%ld detach=%d\n", filename, bandwidth_limit, s->detach);
+ if (s->detach == 1) {
+ dprintf("detaching from monitor\n");
+ monitor_suspend();
+ s->detach = 2;
+ }
+
+ migrate_fd_connect(s);
+ return &s->mig_state;
+}
+
+int file_start_incoming_migration(const char *filename)
+{
+ int ret;
+ QEMUFile *f;
+
+ dprintf("Starting incoming file migration from '%s'\n", filename);
+ f = qemu_fopen(filename, "rb");
+ if(f == NULL) {
+ perror("failed to open file");
+ term_printf("failed to open file %s\n", filename);
+ return -errno;
+ }
+
+ vm_stop(0); /* just in case */
+ ret = qemu_loadvm_state(f);
+ if (ret < 0) {
+ fprintf(stderr, "in_file_mig: load of migration failed\n");
+ goto err;
+ }
+ qemu_announce_self();
+ dprintf("successfully loaded vm state\n");
+ vm_start();
+ qemu_fclose(f);
+ return 0;
+
+err:
+ qemu_fclose(f);
+ return -errno;
+}
diff --git a/migration.c b/migration.c
index 0ef777a..31c1c2b 100644
--- a/migration.c
+++ b/migration.c
@@ -43,6 +43,8 @@ void qemu_start_incoming_migration(const char *uri)
#if !defined(WIN32)
else if (strstart(uri, "exec:", &p))
exec_start_incoming_migration(p);
+ else if (strstart(uri, "file:", &p))
+ file_start_incoming_migration(p);
#endif
else
fprintf(stderr, "unknown migration protocol: %s\n", uri);
@@ -58,6 +60,8 @@ void do_migrate(int detach, const char *uri)
#if !defined(WIN32)
else if (strstart(uri, "exec:", &p))
s = exec_start_outgoing_migration(p, max_throttle, detach);
+ else if (strstart(uri, "file:", &p))
+ s = file_start_outgoing_migration(p, max_throttle, detach);
#endif
else
term_printf("unknown migration protocol: %s\n", uri);
diff --git a/migration.h b/migration.h
index d9771ad..c22beb9 100644
--- a/migration.h
+++ b/migration.h
@@ -67,6 +67,11 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
int64_t bandwidth_limit,
int detach);
+MigrationState *file_start_outgoing_migration(const char *filename,
+ int64_t bandwidth_limit,
+ int detach);
+int file_start_incoming_migration(const char *filename);
+
void migrate_fd_error(FdMigrationState *s);
void migrate_fd_cleanup(FdMigrationState *s);
--
1.6.0.6
next reply other threads:[~2009-02-19 11:45 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-19 11:45 Uri Lublin [this message]
2009-02-19 13:57 ` [Qemu-devel] migration: adding migration to/from a file (v2) Anthony Liguori
2009-02-19 16:14 ` Uri Lublin
2009-02-19 16:51 ` Anthony Liguori
2009-02-19 19:06 ` Uri Lublin
2009-02-19 20:05 ` Anthony Liguori
2009-02-19 20:28 ` Jamie Lokier
2009-02-19 23:36 ` M. Warner Losh
2009-02-19 23:59 ` Anthony Liguori
2009-02-20 0:36 ` M. Warner Losh
2009-02-19 20:45 ` Uri Lublin
2009-02-19 19:37 ` Jamie Lokier
2009-02-19 20:06 ` Anthony Liguori
2009-02-19 19:33 ` Jamie Lokier
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=499D4654.9000305@redhat.com \
--to=uril@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).