diff --git a/migration-Add-zstd-support-in-multi-thread-compressi.patch b/migration-Add-zstd-support-in-multi-thread-compressi.patch new file mode 100644 index 0000000..a84bb36 --- /dev/null +++ b/migration-Add-zstd-support-in-multi-thread-compressi.patch @@ -0,0 +1,231 @@ +From 54a1b546e0bd0cc41669bf7ade806c6c777c96ad Mon Sep 17 00:00:00 2001 +From: Zeyu Jin +Date: Sat, 30 Jan 2021 16:15:10 +0800 +Subject: [PATCH] migration: Add zstd support in multi-thread compression + +This patch enables zstd option in multi-thread compression. + +Signed-off-by: Zeyu Jin +Signed-off-by: Ying Fang +--- + hw/core/qdev-properties-system.c | 2 +- + migration/ram.c | 130 ++++++++++++++++++++++++++++++- + qapi/migration.json | 2 +- + 3 files changed, 130 insertions(+), 4 deletions(-) + +diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c +index 67ed89b406..6d48903c87 100644 +--- a/hw/core/qdev-properties-system.c ++++ b/hw/core/qdev-properties-system.c +@@ -406,7 +406,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) + const PropertyInfo qdev_prop_compress_method = { + .name = "CompressMethod", + .description = "multi-thread compression method, " +- "zlib", ++ "zlib/zstd", + .enum_table = &CompressMethod_lookup, + .get = get_enum, + .set = set_enum, +diff --git a/migration/ram.c b/migration/ram.c +index 3ed808a4ca..ba1e729c39 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -59,6 +59,10 @@ + #include "savevm.h" + #include "qemu/iov.h" + ++#ifdef CONFIG_ZSTD ++#include ++#include ++#endif + /***********************************************************/ + /* ram save/restore */ + +@@ -415,11 +419,16 @@ struct CompressParam { + ram_addr_t offset; + + /* internally used fields */ +- z_stream stream; + uint8_t *originbuf; + + /* for zlib compression */ + z_stream stream; ++ ++#ifdef CONFIG_ZSTD ++ ZSTD_CStream *zstd_cs; ++ ZSTD_inBuffer in; ++ ZSTD_outBuffer out; ++#endif + }; + typedef struct CompressParam CompressParam; + +@@ -434,6 +443,11 @@ struct DecompressParam { + + /* for zlib compression */ + z_stream stream; ++#ifdef CONFIG_ZSTD ++ ZSTD_DStream *zstd_ds; ++ ZSTD_inBuffer in; ++ ZSTD_outBuffer out; ++#endif + }; + typedef struct DecompressParam DecompressParam; + +@@ -482,7 +496,7 @@ static int zlib_save_setup(CompressParam *param) + } + + static ssize_t zlib_compress_data(CompressParam *param, size_t size) +- ++{ + int err; + uint8_t *dest = NULL; + z_stream *stream = ¶m->stream; +@@ -567,6 +581,103 @@ static int zlib_check_len(int len) + return len < 0 || len > compressBound(TARGET_PAGE_SIZE); + } + ++#ifdef CONFIG_ZSTD ++static int zstd_save_setup(CompressParam *param) ++{ ++ int res; ++ param->zstd_cs = ZSTD_createCStream(); ++ if (!param->zstd_cs) { ++ return -1; ++ } ++ res = ZSTD_initCStream(param->zstd_cs, migrate_compress_level()); ++ if (ZSTD_isError(res)) { ++ return -1; ++ } ++ return 0; ++} ++static void zstd_save_cleanup(CompressParam *param) ++{ ++ ZSTD_freeCStream(param->zstd_cs); ++ param->zstd_cs = NULL; ++} ++static ssize_t zstd_compress_data(CompressParam *param, size_t size) ++{ ++ int ret; ++ uint8_t *dest = NULL; ++ uint8_t *p = param->originbuf; ++ QEMUFile *f = f = param->file; ++ ssize_t blen = qemu_put_compress_start(f, &dest); ++ if (blen < ZSTD_compressBound(size)) { ++ return -1; ++ } ++ param->out.dst = dest; ++ param->out.size = blen; ++ param->out.pos = 0; ++ param->in.src = p; ++ param->in.size = size; ++ param->in.pos = 0; ++ do { ++ ret = ZSTD_compressStream2(param->zstd_cs, ¶m->out, ++ ¶m->in, ZSTD_e_end); ++ } while (ret > 0 && (param->in.size - param->in.pos > 0) ++ && (param->out.size - param->out.pos > 0)); ++ if (ret > 0 && (param->in.size - param->in.pos > 0)) { ++ return -1; ++ } ++ if (ZSTD_isError(ret)) { ++ return -1; ++ } ++ blen = param->out.pos; ++ qemu_put_compress_end(f, blen); ++ return blen + sizeof(int32_t); ++} ++ ++static int zstd_load_setup(DecompressParam *param) ++{ ++ int ret; ++ param->zstd_ds = ZSTD_createDStream(); ++ if (!param->zstd_ds) { ++ return -1; ++ } ++ ret = ZSTD_initDStream(param->zstd_ds); ++ if (ZSTD_isError(ret)) { ++ return -1; ++ } ++ return 0; ++} ++static void zstd_load_cleanup(DecompressParam *param) ++{ ++ ZSTD_freeDStream(param->zstd_ds); ++ param->zstd_ds = NULL; ++} ++static int ++zstd_decompress_data(DecompressParam *param, uint8_t *dest, size_t size) ++{ ++ int ret; ++ param->out.dst = dest; ++ param->out.size = size; ++ param->out.pos = 0; ++ param->in.src = param->compbuf; ++ param->in.size = param->len; ++ param->in.pos = 0; ++ do { ++ ret = ZSTD_decompressStream(param->zstd_ds, ¶m->out, ¶m->in); ++ } while (ret > 0 && (param->in.size - param->in.pos > 0) ++ && (param->out.size - param->out.pos > 0)); ++ if (ret > 0 && (param->in.size - param->in.pos > 0)) { ++ return -1; ++ } ++ if (ZSTD_isError(ret)) { ++ return -1; ++ } ++ return ret; ++} ++static int zstd_check_len(int len) ++{ ++ return len < 0 || len > ZSTD_compressBound(TARGET_PAGE_SIZE); ++} ++#endif ++ + static int set_compress_ops(void) + { + compress_ops = g_new0(MigrationCompressOps, 1); +@@ -577,6 +688,13 @@ static int set_compress_ops(void) + compress_ops->save_cleanup = zlib_save_cleanup; + compress_ops->compress_data = zlib_compress_data; + break; ++#ifdef CONFIG_ZSTD ++ case COMPRESS_METHOD_ZSTD: ++ compress_ops->save_setup = zstd_save_setup; ++ compress_ops->save_cleanup = zstd_save_cleanup; ++ compress_ops->compress_data = zstd_compress_data; ++ break; ++#endif + default: + return -1; + } +@@ -595,6 +713,14 @@ static int set_decompress_ops(void) + decompress_ops->decompress_data = zlib_decompress_data; + decompress_ops->check_len = zlib_check_len; + break; ++#ifdef CONFIG_ZSTD ++ case COMPRESS_METHOD_ZSTD: ++ decompress_ops->load_setup = zstd_load_setup; ++ decompress_ops->load_cleanup = zstd_load_cleanup; ++ decompress_ops->decompress_data = zstd_decompress_data; ++ decompress_ops->check_len = zstd_check_len; ++ break; ++#endif + default: + return -1; + } +diff --git a/qapi/migration.json b/qapi/migration.json +index b0e8c493ee..587ef65872 100644 +--- a/qapi/migration.json ++++ b/qapi/migration.json +@@ -493,7 +493,7 @@ + # + ## + { 'enum': 'CompressMethod', +- 'data': [ 'zlib' ] } ++ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] } + + ## + # @MigrationParameter: +-- +2.27.0 +