[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH v1: 05/12] migration: support custom page loadin
From: |
mrhines |
Subject: |
[Qemu-devel] [RFC PATCH v1: 05/12] migration: support custom page loading |
Date: |
Mon, 21 Oct 2013 01:14:15 +0000 |
From: "Michael R. Hines" <address@hidden>
Just as RDMA has custom routines for saving memory,
this provides us with custom routines for loading memory.
Micro-checkpointing needs this support in order to be able
to handle loading of the latest checkpoint into memory
as they are received from the network.
Signed-off-by: Michael R. Hines <address@hidden>
---
arch_init.c | 17 ++++++++++++-----
include/migration/migration.h | 12 ++++++++++--
include/migration/qemu-file.h | 16 ++++++++++++++--
savevm.c | 27 ++++++++++++++++++++++++---
4 files changed, 60 insertions(+), 12 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index b139512..9cf7d18 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -684,7 +684,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
/* In doubt sent page as normal */
bytes_sent = -1;
ret = ram_control_save_page(f, block->offset,
- offset, TARGET_PAGE_SIZE, &bytes_sent);
+ block->host, offset, TARGET_PAGE_SIZE, &bytes_sent);
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
if (ret != RAM_SAVE_CONTROL_DELAYED) {
@@ -712,9 +712,11 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
/* XBZRLE overflow or normal page */
if (bytes_sent == -1) {
bytes_sent = save_block_hdr(f, block, offset, cont,
RAM_SAVE_FLAG_PAGE);
- qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
- bytes_sent += TARGET_PAGE_SIZE;
- acct_info.norm_pages++;
+ if (ret != RAM_SAVE_CONTROL_DELAYED) {
+ qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
+ bytes_sent += TARGET_PAGE_SIZE;
+ acct_info.norm_pages++;
+ }
}
/* if page is unmodified, continue to the next */
@@ -1133,13 +1135,18 @@ static int ram_load(QEMUFile *f, void *opaque, int
version_id)
ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
} else if (flags & RAM_SAVE_FLAG_PAGE) {
void *host;
+ int r;
host = host_from_stream_offset(f, addr, flags);
if (!host) {
return -EINVAL;
}
- qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
+ r = ram_control_load_page(f, host, TARGET_PAGE_SIZE);
+
+ if (r == RAM_LOAD_CONTROL_NOT_SUPP) {
+ qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
+ }
} else if (flags & RAM_SAVE_FLAG_XBZRLE) {
void *host = host_from_stream_offset(f, addr, flags);
if (!host) {
diff --git a/include/migration/migration.h b/include/migration/migration.h
index 3ad06c5..ac1b438 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -169,9 +169,17 @@ void ram_control_load_hook(QEMUFile *f, uint64_t flags);
#define RAM_SAVE_CONTROL_NOT_SUPP -1000
#define RAM_SAVE_CONTROL_DELAYED -2000
+#define RAM_LOAD_CONTROL_NOT_SUPP -3000
+#define RAM_LOAD_CONTROL_DELAYED -4000
-size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
- ram_addr_t offset, size_t size,
+#define RDMA_CONTROL_VERSION_CURRENT 1
+
+int ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
+ uint8_t *host_addr,
+ ram_addr_t offset, long size,
int *bytes_sent);
+int ram_control_load_page(QEMUFile *f,
+ void *host_addr,
+ long size);
#endif
diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 0f757fb..d396b40 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -76,12 +76,22 @@ typedef int (QEMURamHookFunc)(QEMUFile *f, void *opaque,
uint64_t flags);
* This function allows override of where the RAM page
* is saved (such as RDMA, for example.)
*/
-typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque,
+typedef int (QEMURamSaveFunc)(QEMUFile *f, void *opaque,
ram_addr_t block_offset,
+ uint8_t *host_addr,
ram_addr_t offset,
- size_t size,
+ long size,
int *bytes_sent);
+/*
+ * This function allows override of where the RAM page
+ * is saved (such as RDMA, for example.)
+ */
+typedef int (QEMURamLoadFunc)(QEMUFile *f,
+ void *opaque,
+ void *host_addr,
+ long size);
+
typedef struct QEMUFileOps {
QEMUFilePutBufferFunc *put_buffer;
QEMUFileGetBufferFunc *get_buffer;
@@ -92,12 +102,14 @@ typedef struct QEMUFileOps {
QEMURamHookFunc *after_ram_iterate;
QEMURamHookFunc *hook_ram_load;
QEMURamSaveFunc *save_page;
+ QEMURamLoadFunc *load_page;
} QEMUFileOps;
QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
QEMUFile *qemu_fopen(const char *filename, const char *mode);
QEMUFile *qemu_fdopen(int fd, const char *mode);
QEMUFile *qemu_fopen_socket(int fd, const char *mode);
+QEMUFile *qemu_fopen_mc(void *opaque, const char *mode);
QEMUFile *qemu_popen_cmd(const char *command, const char *mode);
int qemu_get_fd(QEMUFile *f);
int qemu_fclose(QEMUFile *f);
diff --git a/savevm.c b/savevm.c
index 2f631d4..05f8a05 100644
--- a/savevm.c
+++ b/savevm.c
@@ -661,14 +661,17 @@ void ram_control_load_hook(QEMUFile *f, uint64_t flags)
}
}
-size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
- ram_addr_t offset, size_t size, int *bytes_sent)
+int ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
+ uint8_t *host_addr,
+ ram_addr_t offset, long size, int *bytes_sent)
{
if (f->ops->save_page) {
int ret = f->ops->save_page(f, f->opaque, block_offset,
+ host_addr,
offset, size, bytes_sent);
- if (ret != RAM_SAVE_CONTROL_DELAYED) {
+ if (ret != RAM_SAVE_CONTROL_DELAYED
+ && ret != RAM_SAVE_CONTROL_NOT_SUPP) {
if (bytes_sent && *bytes_sent > 0) {
qemu_update_position(f, *bytes_sent);
} else if (ret < 0) {
@@ -682,6 +685,24 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t
block_offset,
return RAM_SAVE_CONTROL_NOT_SUPP;
}
+int ram_control_load_page(QEMUFile *f, void *host_addr, long size)
+{
+ if (f->ops->load_page) {
+ int ret = f->ops->load_page(f, f->opaque, host_addr, size);
+
+ if (ret != RAM_LOAD_CONTROL_DELAYED
+ && ret != RAM_LOAD_CONTROL_NOT_SUPP) {
+ if (ret < 0) {
+ qemu_file_set_error(f, ret);
+ }
+ }
+
+ return ret;
+ }
+
+ return RAM_LOAD_CONTROL_NOT_SUPP;
+}
+
static void qemu_fill_buffer(QEMUFile *f)
{
int len;
--
1.8.1.2
- [Qemu-devel] [RFC PATCH v1: 00/12] fault tolerance through micro-checkpointing, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 02/12] rdma: remove reference to github.com, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 01/12] mc: add documentation for micro-checkpointing, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 03/12] migration: introduce parallelization of migration_bitmap, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 04/12] mc: introduce a "checkpointing" status check into the VCPU states, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 05/12] migration: support custom page loading,
mrhines <=
- [Qemu-devel] [RFC PATCH v1: 06/12] rdma: accelerated memcpy() support, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 07/12] mc: introduce state machine error handling and migration_bitmap prep, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 08/12] mc: modified QMP statistics and migration_thread handoff, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 09/12] mc: core logic, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 10/12] mc: configure and makefile support, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 11/12] mc: register MC qemu-file functions and expose MC tunable capability, mrhines, 2013/10/20
- [Qemu-devel] [RFC PATCH v1: 12/12] mc: activate and use MC core logic if requested, mrhines, 2013/10/20