331 lines
11 KiB
Diff
331 lines
11 KiB
Diff
|
|
From cf6f31249817380e91cbc4e55b189216645fac18 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Chuan Zheng <zhengchuan@huawei.com>
|
||
|
|
Date: Sat, 30 Jan 2021 15:21:17 +0800
|
||
|
|
Subject: [PATCH] migration: Refactoring multi-thread compress migration
|
||
|
|
|
||
|
|
Code refactor for the compression procedure which includes:
|
||
|
|
|
||
|
|
1. Move qemu_compress_data and qemu_put_compression_data from qemu-file.c to
|
||
|
|
ram.c, for the reason that most part of the code logical has nothing to do
|
||
|
|
with qemu-file. Besides, the decompression code is located at ram.c only.
|
||
|
|
|
||
|
|
2. Simplify the function input arguments for compression and decompression.
|
||
|
|
Wrap the input into the param structure which already exists. This change also
|
||
|
|
makes the function much more flexible for other compression methods.
|
||
|
|
|
||
|
|
Signed-off-by: Chuan Zheng <zhengchuan@huawei.com>
|
||
|
|
Signed-off-by: Zeyu Jin <jinzeyu@huawei.com>
|
||
|
|
Signed-off-by: Ying Fang <fangying1@huawei.com>
|
||
|
|
---
|
||
|
|
migration/meson.build | 4 +-
|
||
|
|
migration/migration-hmp-cmds.c | 1 -
|
||
|
|
migration/qemu-file.c | 61 +++++-------------------
|
||
|
|
migration/qemu-file.h | 4 +-
|
||
|
|
migration/ram-compress.c | 87 ++++++++++++++++++++++++----------
|
||
|
|
5 files changed, 77 insertions(+), 80 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/migration/meson.build b/migration/meson.build
|
||
|
|
index 92b1cc4297..d9b46ef0df 100644
|
||
|
|
--- a/migration/meson.build
|
||
|
|
+++ b/migration/meson.build
|
||
|
|
@@ -22,7 +22,6 @@ system_ss.add(files(
|
||
|
|
'migration.c',
|
||
|
|
'multifd.c',
|
||
|
|
'multifd-zlib.c',
|
||
|
|
- 'ram-compress.c',
|
||
|
|
'options.c',
|
||
|
|
'postcopy-ram.c',
|
||
|
|
'savevm.c',
|
||
|
|
@@ -43,4 +42,5 @@ system_ss.add(when: zstd, if_true: files('multifd-zstd.c'))
|
||
|
|
|
||
|
|
specific_ss.add(when: 'CONFIG_SYSTEM_ONLY',
|
||
|
|
if_true: files('ram.c',
|
||
|
|
- 'target.c'))
|
||
|
|
+ 'target.c',
|
||
|
|
+ 'ram-compress.c'))
|
||
|
|
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
|
||
|
|
index 261ec1e35c..1fa6a5f478 100644
|
||
|
|
--- a/migration/migration-hmp-cmds.c
|
||
|
|
+++ b/migration/migration-hmp-cmds.c
|
||
|
|
@@ -22,7 +22,6 @@
|
||
|
|
#include "qapi/qapi-commands-migration.h"
|
||
|
|
#include "qapi/qapi-visit-migration.h"
|
||
|
|
#include "qapi/qmp/qdict.h"
|
||
|
|
-#include "qapi/qapi-visit-migration.h"
|
||
|
|
#include "qapi/string-input-visitor.h"
|
||
|
|
#include "qapi/string-output-visitor.h"
|
||
|
|
#include "qemu/cutils.h"
|
||
|
|
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
|
||
|
|
index 94231ff295..bd1dbc3db1 100644
|
||
|
|
--- a/migration/qemu-file.c
|
||
|
|
+++ b/migration/qemu-file.c
|
||
|
|
@@ -669,55 +669,6 @@ uint64_t qemu_get_be64(QEMUFile *f)
|
||
|
|
return v;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/* return the size after compression, or negative value on error */
|
||
|
|
-static int qemu_compress_data(z_stream *stream, uint8_t *dest, size_t dest_len,
|
||
|
|
- const uint8_t *source, size_t source_len)
|
||
|
|
-{
|
||
|
|
- int err;
|
||
|
|
-
|
||
|
|
- err = deflateReset(stream);
|
||
|
|
- if (err != Z_OK) {
|
||
|
|
- return -1;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- stream->avail_in = source_len;
|
||
|
|
- stream->next_in = (uint8_t *)source;
|
||
|
|
- stream->avail_out = dest_len;
|
||
|
|
- stream->next_out = dest;
|
||
|
|
-
|
||
|
|
- err = deflate(stream, Z_FINISH);
|
||
|
|
- if (err != Z_STREAM_END) {
|
||
|
|
- return -1;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- return stream->next_out - dest;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-/* Compress size bytes of data start at p and store the compressed
|
||
|
|
- * data to the buffer of f.
|
||
|
|
- *
|
||
|
|
- * Since the file is dummy file with empty_ops, return -1 if f has no space to
|
||
|
|
- * save the compressed data.
|
||
|
|
- */
|
||
|
|
-ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
|
||
|
|
- const uint8_t *p, size_t size)
|
||
|
|
-{
|
||
|
|
- ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
|
||
|
|
-
|
||
|
|
- if (blen < compressBound(size)) {
|
||
|
|
- return -1;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- blen = qemu_compress_data(stream, f->buf + f->buf_index + sizeof(int32_t),
|
||
|
|
- blen, p, size);
|
||
|
|
- if (blen < 0) {
|
||
|
|
- return -1;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- qemu_put_be32(f, blen);
|
||
|
|
- add_buf_to_iovec(f, blen);
|
||
|
|
- return blen + sizeof(int32_t);
|
||
|
|
-}
|
||
|
|
|
||
|
|
/* Put the data in the buffer of f_src to the buffer of f_des, and
|
||
|
|
* then reset the buf_index of f_src to 0.
|
||
|
|
@@ -834,3 +785,15 @@ int qemu_file_get_to_fd(QEMUFile *f, int fd, size_t size)
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+ssize_t qemu_put_compress_start(QEMUFile *f, uint8_t **dest_ptr)
|
||
|
|
+{
|
||
|
|
+ *dest_ptr = f->buf + f->buf_index + sizeof(int32_t);
|
||
|
|
+ return IO_BUF_SIZE - f->buf_index - sizeof(int32_t);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void qemu_put_compress_end(QEMUFile *f, unsigned int v)
|
||
|
|
+{
|
||
|
|
+ qemu_put_be32(f, v);
|
||
|
|
+ add_buf_to_iovec(f, v);
|
||
|
|
+}
|
||
|
|
diff --git a/migration/qemu-file.h b/migration/qemu-file.h
|
||
|
|
index 8aec9fabf7..8afa95732b 100644
|
||
|
|
--- a/migration/qemu-file.h
|
||
|
|
+++ b/migration/qemu-file.h
|
||
|
|
@@ -54,8 +54,8 @@ void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size,
|
||
|
|
|
||
|
|
size_t coroutine_mixed_fn qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset);
|
||
|
|
size_t coroutine_mixed_fn qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size);
|
||
|
|
-ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
|
||
|
|
- const uint8_t *p, size_t size);
|
||
|
|
+ssize_t qemu_put_compress_start(QEMUFile *f, uint8_t **dest_ptr);
|
||
|
|
+void qemu_put_compress_end(QEMUFile *f, unsigned int v);
|
||
|
|
int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src);
|
||
|
|
bool qemu_file_buffer_empty(QEMUFile *file);
|
||
|
|
|
||
|
|
diff --git a/migration/ram-compress.c b/migration/ram-compress.c
|
||
|
|
index fa4388f6a6..2be344acbc 100644
|
||
|
|
--- a/migration/ram-compress.c
|
||
|
|
+++ b/migration/ram-compress.c
|
||
|
|
@@ -28,7 +28,6 @@
|
||
|
|
|
||
|
|
#include "qemu/osdep.h"
|
||
|
|
#include "qemu/cutils.h"
|
||
|
|
-
|
||
|
|
#include "ram-compress.h"
|
||
|
|
|
||
|
|
#include "qemu/error-report.h"
|
||
|
|
@@ -40,6 +39,7 @@
|
||
|
|
#include "exec/ramblock.h"
|
||
|
|
#include "ram.h"
|
||
|
|
#include "migration-stats.h"
|
||
|
|
+#include "exec/ram_addr.h"
|
||
|
|
|
||
|
|
static struct {
|
||
|
|
int64_t pages;
|
||
|
|
@@ -83,28 +83,22 @@ static QemuThread *decompress_threads;
|
||
|
|
static QemuMutex decomp_done_lock;
|
||
|
|
static QemuCond decomp_done_cond;
|
||
|
|
|
||
|
|
-static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
|
||
|
|
- RAMBlock *block, ram_addr_t offset,
|
||
|
|
- uint8_t *source_buf);
|
||
|
|
+static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block);
|
||
|
|
|
||
|
|
static void *do_data_compress(void *opaque)
|
||
|
|
{
|
||
|
|
CompressParam *param = opaque;
|
||
|
|
RAMBlock *block;
|
||
|
|
- ram_addr_t offset;
|
||
|
|
CompressResult result;
|
||
|
|
|
||
|
|
qemu_mutex_lock(¶m->mutex);
|
||
|
|
while (!param->quit) {
|
||
|
|
if (param->trigger) {
|
||
|
|
block = param->block;
|
||
|
|
- offset = param->offset;
|
||
|
|
param->trigger = false;
|
||
|
|
qemu_mutex_unlock(¶m->mutex);
|
||
|
|
|
||
|
|
- result = do_compress_ram_page(param->file, ¶m->stream,
|
||
|
|
- block, offset, param->originbuf);
|
||
|
|
-
|
||
|
|
+ result = do_compress_ram_page(param, block);
|
||
|
|
qemu_mutex_lock(&comp_done_lock);
|
||
|
|
param->done = true;
|
||
|
|
param->result = result;
|
||
|
|
@@ -204,15 +198,57 @@ exit:
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
-static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
|
||
|
|
- RAMBlock *block, ram_addr_t offset,
|
||
|
|
- uint8_t *source_buf)
|
||
|
|
+/*
|
||
|
|
+ * Compress size bytes of data start at p and store the compressed
|
||
|
|
+ * data to the buffer of f.
|
||
|
|
+ *
|
||
|
|
+ * Since the file is dummy file with empty_ops, return -1 if f has no space to
|
||
|
|
+ * save the compressed data.
|
||
|
|
+ */
|
||
|
|
+static ssize_t qemu_put_compression_data(CompressParam *param, size_t size)
|
||
|
|
+{
|
||
|
|
+ int err;
|
||
|
|
+ uint8_t *dest = NULL;
|
||
|
|
+ z_stream *stream = ¶m->stream;
|
||
|
|
+ uint8_t *p = param->originbuf;
|
||
|
|
+ QEMUFile *f = f = param->file;
|
||
|
|
+ ssize_t blen = qemu_put_compress_start(f, &dest);
|
||
|
|
+
|
||
|
|
+ if (blen < compressBound(size)) {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ err = deflateReset(stream);
|
||
|
|
+ if (err != Z_OK) {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ stream->avail_in = size;
|
||
|
|
+ stream->next_in = p;
|
||
|
|
+ stream->avail_out = blen;
|
||
|
|
+ stream->next_out = dest;
|
||
|
|
+
|
||
|
|
+ err = deflate(stream, Z_FINISH);
|
||
|
|
+ if (err != Z_STREAM_END) {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ blen = stream->next_out - dest;
|
||
|
|
+ if (blen < 0) {
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ qemu_put_compress_end(f, blen);
|
||
|
|
+ return blen + sizeof(int32_t);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static CompressResult do_compress_ram_page(CompressParam *param, RAMBlock *block)
|
||
|
|
{
|
||
|
|
- uint8_t *p = block->host + offset;
|
||
|
|
+ uint8_t *p = block->host + (param->offset & TARGET_PAGE_MASK);
|
||
|
|
size_t page_size = qemu_target_page_size();
|
||
|
|
int ret;
|
||
|
|
|
||
|
|
- assert(qemu_file_buffer_empty(f));
|
||
|
|
+ assert(qemu_file_buffer_empty(param->file));
|
||
|
|
|
||
|
|
if (buffer_is_zero(p, page_size)) {
|
||
|
|
return RES_ZEROPAGE;
|
||
|
|
@@ -223,12 +259,12 @@ static CompressResult do_compress_ram_page(QEMUFile *f, z_stream *stream,
|
||
|
|
* so that we can catch up the error during compression and
|
||
|
|
* decompression
|
||
|
|
*/
|
||
|
|
- memcpy(source_buf, p, page_size);
|
||
|
|
- ret = qemu_put_compression_data(f, stream, source_buf, page_size);
|
||
|
|
+ memcpy(param->originbuf, p, page_size);
|
||
|
|
+ ret = qemu_put_compression_data(param, page_size);
|
||
|
|
if (ret < 0) {
|
||
|
|
qemu_file_set_error(migrate_get_current()->to_dst_file, ret);
|
||
|
|
error_report("compressed data failed!");
|
||
|
|
- qemu_fflush(f);
|
||
|
|
+ qemu_fflush(param->file);
|
||
|
|
return RES_NONE;
|
||
|
|
}
|
||
|
|
return RES_COMPRESS;
|
||
|
|
@@ -322,19 +358,20 @@ bool compress_page_with_multi_thread(RAMBlock *block, ram_addr_t offset,
|
||
|
|
|
||
|
|
/* return the size after decompression, or negative value on error */
|
||
|
|
static int
|
||
|
|
-qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len,
|
||
|
|
- const uint8_t *source, size_t source_len)
|
||
|
|
+qemu_uncompress_data(DecompressParam *param, uint8_t *dest, size_t pagesize)
|
||
|
|
{
|
||
|
|
int err;
|
||
|
|
|
||
|
|
+ z_stream *stream = ¶m->stream;
|
||
|
|
+
|
||
|
|
err = inflateReset(stream);
|
||
|
|
if (err != Z_OK) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
- stream->avail_in = source_len;
|
||
|
|
- stream->next_in = (uint8_t *)source;
|
||
|
|
- stream->avail_out = dest_len;
|
||
|
|
+ stream->avail_in = param->len;
|
||
|
|
+ stream->next_in = param->compbuf;
|
||
|
|
+ stream->avail_out = pagesize;
|
||
|
|
stream->next_out = dest;
|
||
|
|
|
||
|
|
err = inflate(stream, Z_NO_FLUSH);
|
||
|
|
@@ -350,20 +387,18 @@ static void *do_data_decompress(void *opaque)
|
||
|
|
DecompressParam *param = opaque;
|
||
|
|
unsigned long pagesize;
|
||
|
|
uint8_t *des;
|
||
|
|
- int len, ret;
|
||
|
|
+ int ret;
|
||
|
|
|
||
|
|
qemu_mutex_lock(¶m->mutex);
|
||
|
|
while (!param->quit) {
|
||
|
|
if (param->des) {
|
||
|
|
des = param->des;
|
||
|
|
- len = param->len;
|
||
|
|
param->des = 0;
|
||
|
|
qemu_mutex_unlock(¶m->mutex);
|
||
|
|
|
||
|
|
pagesize = qemu_target_page_size();
|
||
|
|
|
||
|
|
- ret = qemu_uncompress_data(¶m->stream, des, pagesize,
|
||
|
|
- param->compbuf, len);
|
||
|
|
+ ret = qemu_uncompress_data(param, des, pagesize);
|
||
|
|
if (ret < 0 && migrate_get_current()->decompress_error_check) {
|
||
|
|
error_report("decompress data failed");
|
||
|
|
qemu_file_set_error(decomp_file, ret);
|
||
|
|
--
|
||
|
|
2.27.0
|
||
|
|
|