From 63659fe74e76f5c5285466f0c5cfbdca65b3688e Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Mon, 8 Jun 2020 11:31:11 +0200 Subject: [PATCH 01/12] virtiofsd: Whitelist fchmod lo_setattr() invokes fchmod() in a rarely used code path, so it should be whitelisted or virtiofsd will crash with EBADSYS. Said code path can be triggered for example as follows: On the host, in the shared directory, create a file with the sticky bit set and a security.capability xattr: (1) # touch foo (2) # chmod u+s foo (3) # setcap '' foo Then in the guest let some process truncate that file after it has dropped all of its capabilities (at least CAP_FSETID): int main(int argc, char *argv[]) { capng_setpid(getpid()); capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, 0); capng_apply(CAPNG_SELECT_BOTH); ftruncate(open(argv[1], O_RDWR), 0); } This will cause the guest kernel to drop the sticky bit (i.e. perform a mode change) as part of the truncate (where FATTR_FH is set), and that will cause virtiofsd to invoke fchmod() instead of fchmodat(). (A similar configuration exists further below with futimens() vs. utimensat(), but the former is not a syscall but just a wrapper for the latter, so no further whitelisting is required.) Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1842667 Reported-by: Qian Cai Cc: qemu-stable@nongnu.org Signed-off-by: Max Reitz Message-Id: <20200608093111.14942-1-mreitz@redhat.com> Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Vivek Goyal Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/seccomp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/virtiofsd/seccomp.c b/tools/virtiofsd/seccomp.c index bd9e7b083c..3b1522acdd 100644 --- a/tools/virtiofsd/seccomp.c +++ b/tools/virtiofsd/seccomp.c @@ -42,6 +42,7 @@ static const int syscall_whitelist[] = { SCMP_SYS(exit_group), SCMP_SYS(fallocate), SCMP_SYS(fchdir), + SCMP_SYS(fchmod), SCMP_SYS(fchmodat), SCMP_SYS(fchownat), SCMP_SYS(fcntl), From 246da7db3cc103c537b0dd3c1adadbfd9a94ecd7 Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Wed, 3 Jun 2020 03:03:38 -0400 Subject: [PATCH 02/12] qom-hmp-cmds: fix a memleak in hmp_qom_get 'obj' forgot to free at the end of hmp_qom_get(). Fix that. The leak stack: Direct leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7f4e3a779ae8 in __interceptor_malloc (/lib64/libasan.so.5+0xefae8) #1 0x7f4e398f91d5 in g_malloc (/lib64/libglib-2.0.so.0+0x531d5) #2 0x55c9fd9a3999 in qstring_from_substr /build/qemu/src/qobject/qstring.c:45 #3 0x55c9fd894bd3 in qobject_output_type_str /build/qemu/src/qapi/qobject-output-visitor.c:175 #4 0x55c9fd894bd3 in qobject_output_type_str /build/qemu/src/qapi/qobject-output-visitor.c:168 #5 0x55c9fd88b34d in visit_type_str /build/qemu/src/qapi/qapi-visit-core.c:308 #6 0x55c9fd59aa6b in property_get_str /build/qemu/src/qom/object.c:2064 #7 0x55c9fd5adb8a in object_property_get_qobject /build/qemu/src/qom/qom-qobject.c:38 #8 0x55c9fd4a029d in hmp_qom_get /build/qemu/src/qom/qom-hmp-cmds.c:66 Fixes: 89cf4fe34f4 Reported-by: Euler Robot Signed-off-by: Pan Nengyuan Message-Id: <20200603070338.7922-1-pannengyuan@huawei.com> Reviewed-by: Li Qiang Tested-by: Li Qiang Signed-off-by: Dr. David Alan Gilbert --- qom/qom-hmp-cmds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c index 99385b6ad2..158e2d7409 100644 --- a/qom/qom-hmp-cmds.c +++ b/qom/qom-hmp-cmds.c @@ -71,6 +71,7 @@ void hmp_qom_get(Monitor *mon, const QDict *qdict) qobject_unref(str); } + qobject_unref(obj); hmp_handle_error(mon, err); } From 2d9e3dd9be1de3bbdca113673084dd19a8d957c3 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Wed, 10 Jun 2020 09:51:53 +0200 Subject: [PATCH 03/12] hmp: Make json format optional for qom-set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 7d2ef6dcc1cf ("hmp: Simplify qom-set") switched to the json parser, making it possible to specify complex types. However, with this change it is no longer possible to specify proper sizes (e.g., 2G, 128M), turning the interface harder to use for properties that consume sizes. Let's switch back to the previous handling and allow to specify passing json via the "-j" parameter. Cc: Philippe Mathieu-Daudé Cc: Markus Armbruster Cc: Dr. David Alan Gilbert Cc: Paolo Bonzini Cc: "Daniel P. Berrangé" Cc: Eduardo Habkost Signed-off-by: David Hildenbrand Message-Id: <20200610075153.33892-1-david@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- hmp-commands.hx | 7 ++++--- qom/qom-hmp-cmds.c | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 28256209b5..60f395c276 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1806,9 +1806,10 @@ ERST { .name = "qom-set", - .args_type = "path:s,property:s,value:S", - .params = "path property value", - .help = "set QOM property", + .args_type = "json:-j,path:s,property:s,value:S", + .params = "[-j] path property value", + .help = "set QOM property.\n\t\t\t" + "-j: the value is specified in json format.", .cmd = hmp_qom_set, .flags = "p", }, diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c index 158e2d7409..b0abe84cb1 100644 --- a/qom/qom-hmp-cmds.c +++ b/qom/qom-hmp-cmds.c @@ -44,15 +44,27 @@ void hmp_qom_list(Monitor *mon, const QDict *qdict) void hmp_qom_set(Monitor *mon, const QDict *qdict) { + const bool json = qdict_get_try_bool(qdict, "json", false); const char *path = qdict_get_str(qdict, "path"); const char *property = qdict_get_str(qdict, "property"); const char *value = qdict_get_str(qdict, "value"); Error *err = NULL; - QObject *obj; - obj = qobject_from_json(value, &err); - if (err == NULL) { - qmp_qom_set(path, property, obj, &err); + if (!json) { + Object *obj = object_resolve_path(path, NULL); + + if (!obj) { + error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, + "Device '%s' not found", path); + } else { + object_property_parse(obj, value, property, &err); + } + } else { + QObject *obj = qobject_from_json(value, &err); + + if (!err) { + qmp_qom_set(path, property, obj, &err); + } } hmp_handle_error(mon, err); From f663492f40c1e2b500c9eda0625ff8bbb04a478c Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:08:56 +0800 Subject: [PATCH 04/12] tests/migration: mem leak fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘data’ has the possibility of memory leaks, so use the glib macros g_autofree recommended by CODING_STYLE.rst to automatically release the memory that returned from g_malloc(). Signed-off-by: Mao Zhongyi Reviewed-by: Alex Bennée Reviewed-by: Laurent Vivier Message-Id: <20200603080904.997083-2-maozhongyi@cmss.chinamobile.com> Signed-off-by: Dr. David Alan Gilbert --- tests/migration/stress.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/tests/migration/stress.c b/tests/migration/stress.c index 0c23964693..f9626d50ee 100644 --- a/tests/migration/stress.c +++ b/tests/migration/stress.c @@ -170,26 +170,14 @@ static unsigned long long now(void) static int stressone(unsigned long long ramsizeMB) { size_t pagesPerMB = 1024 * 1024 / PAGE_SIZE; - char *ram = malloc(ramsizeMB * 1024 * 1024); + g_autofree char *ram = g_malloc(ramsizeMB * 1024 * 1024); char *ramptr; size_t i, j, k; - char *data = malloc(PAGE_SIZE); + g_autofree char *data = g_malloc(PAGE_SIZE); char *dataptr; size_t nMB = 0; unsigned long long before, after; - if (!ram) { - fprintf(stderr, "%s (%05d): ERROR: cannot allocate %llu MB of RAM: %s\n", - argv0, gettid(), ramsizeMB, strerror(errno)); - return -1; - } - if (!data) { - fprintf(stderr, "%s (%d): ERROR: cannot allocate %d bytes of RAM: %s\n", - argv0, gettid(), PAGE_SIZE, strerror(errno)); - free(ram); - return -1; - } - /* We don't care about initial state, but we do want * to fault it all into RAM, otherwise the first iter * of the loop below will be quite slow. We can't use @@ -198,8 +186,6 @@ static int stressone(unsigned long long ramsizeMB) memset(ram, 0xfe, ramsizeMB * 1024 * 1024); if (random_bytes(data, PAGE_SIZE) < 0) { - free(ram); - free(data); return -1; } @@ -227,9 +213,6 @@ static int stressone(unsigned long long ramsizeMB) } } } - - free(data); - free(ram); } From 71cfce73f454fcdd5b4e8e9629cd6f41900cef13 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:08:57 +0800 Subject: [PATCH 05/12] tests/migration: fix unreachable path in stress test If stressone() or stress() exits it's because of a failure because the test runs forever otherwise, so change stressone and stress type to void to make the exit_failure() as the exit function of main(). Signed-off-by: Mao Zhongyi Reviewed-by: Laurent Vivier Message-Id: <20200603080904.997083-3-maozhongyi@cmss.chinamobile.com> Signed-off-by: Dr. David Alan Gilbert --- tests/migration/stress.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/migration/stress.c b/tests/migration/stress.c index f9626d50ee..a062ef6b55 100644 --- a/tests/migration/stress.c +++ b/tests/migration/stress.c @@ -167,7 +167,7 @@ static unsigned long long now(void) return (tv.tv_sec * 1000ull) + (tv.tv_usec / 1000ull); } -static int stressone(unsigned long long ramsizeMB) +static void stressone(unsigned long long ramsizeMB) { size_t pagesPerMB = 1024 * 1024 / PAGE_SIZE; g_autofree char *ram = g_malloc(ramsizeMB * 1024 * 1024); @@ -186,7 +186,7 @@ static int stressone(unsigned long long ramsizeMB) memset(ram, 0xfe, ramsizeMB * 1024 * 1024); if (random_bytes(data, PAGE_SIZE) < 0) { - return -1; + return; } before = now(); @@ -225,7 +225,7 @@ static void *stressthread(void *arg) return NULL; } -static int stress(unsigned long long ramsizeGB, int ncpus) +static void stress(unsigned long long ramsizeGB, int ncpus) { size_t i; unsigned long long ramsizeMB = ramsizeGB * 1024 / ncpus; @@ -238,8 +238,6 @@ static int stress(unsigned long long ramsizeGB, int ncpus) } stressone(ramsizeMB); - - return 0; } @@ -335,8 +333,7 @@ int main(int argc, char **argv) fprintf(stdout, "%s (%05d): INFO: RAM %llu GiB across %d CPUs\n", argv0, gettid(), ramsizeGB, ncpus); - if (stress(ramsizeGB, ncpus) < 0) - exit_failure(); + stress(ramsizeGB, ncpus); - exit_success(); + exit_failure(); } From 39337f121192c9ca305cb5c1a695f25c35e967ff Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:08:58 +0800 Subject: [PATCH 06/12] monitor/hmp-cmds: add units for migrate_parameters When running: (qemu) info migrate_parameters announce-initial: 50 ms announce-max: 550 ms announce-step: 100 ms compress-wait-thread: on ... max-bandwidth: 33554432 bytes/second downtime-limit: 300 milliseconds x-checkpoint-delay: 20000 ... xbzrle-cache-size: 67108864 add units for the parameters 'x-checkpoint-delay' and 'xbzrle-cache-size', it's easier to read, also move milliseconds to ms to keep the same style. Signed-off-by: Mao Zhongyi Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Stefano Garzarella Message-Id: <20200603080904.997083-4-maozhongyi@cmss.chinamobile.com> Signed-off-by: Dr. David Alan Gilbert --- monitor/hmp-cmds.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index e03adf0d4d..2c630ec88d 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -443,11 +443,11 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH), params->max_bandwidth); assert(params->has_downtime_limit); - monitor_printf(mon, "%s: %" PRIu64 " milliseconds\n", + monitor_printf(mon, "%s: %" PRIu64 " ms\n", MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT), params->downtime_limit); assert(params->has_x_checkpoint_delay); - monitor_printf(mon, "%s: %u\n", + monitor_printf(mon, "%s: %u ms\n", MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY), params->x_checkpoint_delay); assert(params->has_block_incremental); @@ -460,7 +460,7 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%s: %s\n", MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_COMPRESSION), MultiFDCompression_str(params->multifd_compression)); - monitor_printf(mon, "%s: %" PRIu64 "\n", + monitor_printf(mon, "%s: %" PRIu64 " bytes\n", MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE), params->xbzrle_cache_size); monitor_printf(mon, "%s: %" PRIu64 "\n", From fe025508c0c98ff1349c02e6f99b13844d7079b1 Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:08:59 +0800 Subject: [PATCH 07/12] monitor/hmp-cmds: don't silently output when running 'migrate_set_downtime' fails Although 'migrate_set_downtime' has been deprecated and replaced with 'migrate_set_parameter downtime_limit', it has not been completely eliminated, possibly due to compatibility with older versions. I think as long as this old parameter is running, we should report appropriate message when something goes wrong, not be silent. before: (qemu) migrate_set_downtime -1 (qemu) after: (qemu) migrate_set_downtime -1 Error: Parameter 'downtime_limit' expects an integer in the range of 0 to 2000 seconds Signed-off-by: Mao Zhongyi Reviewed-by: Dr. David Alan Gilbert Message-Id: <20200603080904.997083-5-maozhongyi@cmss.chinamobile.com> Signed-off-by: Dr. David Alan Gilbert --- monitor/hmp-cmds.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 2c630ec88d..a704b3469a 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1189,8 +1189,11 @@ void hmp_migrate_pause(Monitor *mon, const QDict *qdict) /* Kept for backwards compatibility */ void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict) { + Error *err = NULL; + double value = qdict_get_double(qdict, "value"); - qmp_migrate_set_downtime(value, NULL); + qmp_migrate_set_downtime(value, &err); + hmp_handle_error(mon, err); } void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict) From 0705ecc4ade74f03df00e8528987e7876a293f3b Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:09:00 +0800 Subject: [PATCH 08/12] monitor/hmp-cmds: delete redundant Error check before invoke hmp_handle_error() hmp_handle_error() does Error check internally. Signed-off-by: Mao Zhongyi Message-Id: <20200603080904.997083-6-maozhongyi@cmss.chinamobile.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- monitor/hmp-cmds.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index a704b3469a..504796d6e9 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1637,9 +1637,8 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) obj = user_creatable_add_opts(opts, &err); qemu_opts_del(opts); - if (err) { - hmp_handle_error(mon, err); - } + hmp_handle_error(mon, err); + if (obj) { object_unref(obj); } From ac9c95b13fc1ccd097834b29d846f25795bd76de Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:09:01 +0800 Subject: [PATCH 09/12] monitor/hmp-cmds: add 'goto end' to reduce duplicate code. Signed-off-by: Mao Zhongyi Message-Id: <20200603080904.997083-7-maozhongyi@cmss.chinamobile.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- monitor/hmp-cmds.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 504796d6e9..00e3362cb0 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1502,8 +1502,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) read_only, BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err); if (err) { - hmp_handle_error(mon, err); - return; + goto end; } } @@ -1512,6 +1511,7 @@ void hmp_change(Monitor *mon, const QDict *qdict) &err); } +end: hmp_handle_error(mon, err); } @@ -1630,13 +1630,13 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); if (err) { - hmp_handle_error(mon, err); - return; + goto end; } obj = user_creatable_add_opts(opts, &err); qemu_opts_del(opts); +end: hmp_handle_error(mon, err); if (obj) { From afb5d01cb6eb05abfe46a6e6a821df4674f13f2f Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:09:02 +0800 Subject: [PATCH 10/12] monitor/hmp-cmds: improvements for the 'info migrate' When running: (qemu) info migrate globals: store-global-state: on only-migratable: off ... xbzrle transferred: 640892 kbytes xbzrle pages: 16645936 pages xbzrle cache miss: 1525426 xbzrle cache miss rate: 0.09 xbzrle encoding rate: 91.42 xbzrle overflow: 40896 ... compression pages: 377710 pages compression busy: 0 compression busy rate: 0.00 compressed size: 463169457 compression rate: 3.33 Add units for 'xbzrle cache miss' and 'compressed size', make it easier to read. Suggested-by: Dr. David Alan Gilbert Signed-off-by: Mao Zhongyi Message-Id: <20200603080904.997083-8-maozhongyi@cmss.chinamobile.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- docs/xbzrle.txt | 2 +- monitor/hmp-cmds.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/xbzrle.txt b/docs/xbzrle.txt index b431bdaf0f..385b4993f8 100644 --- a/docs/xbzrle.txt +++ b/docs/xbzrle.txt @@ -112,7 +112,7 @@ is recommended. cache size: H bytes xbzrle transferred: I kbytes xbzrle pages: J pages - xbzrle cache miss: K + xbzrle cache miss: K pages xbzrle overflow: L xbzrle cache-miss: the number of cache misses to date - high cache-miss rate diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 00e3362cb0..2b0b58a336 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -299,7 +299,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->xbzrle_cache->bytes >> 10); monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n", info->xbzrle_cache->pages); - monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n", + monitor_printf(mon, "xbzrle cache miss: %" PRIu64 " pages\n", info->xbzrle_cache->cache_miss); monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n", info->xbzrle_cache->cache_miss_rate); @@ -316,8 +316,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->compression->busy); monitor_printf(mon, "compression busy rate: %0.2f\n", info->compression->busy_rate); - monitor_printf(mon, "compressed size: %" PRIu64 "\n", - info->compression->compressed_size); + monitor_printf(mon, "compressed size: %" PRIu64 " kbytes\n", + info->compression->compressed_size >> 10); monitor_printf(mon, "compression rate: %0.2f\n", info->compression->compression_rate); } From 6bcd361a52e73889d2123033ce48450289a1933e Mon Sep 17 00:00:00 2001 From: Mao Zhongyi Date: Wed, 3 Jun 2020 16:09:03 +0800 Subject: [PATCH 11/12] docs/xbzrle: update 'cache miss rate' and 'encoding rate' to docs Signed-off-by: Mao Zhongyi Message-Id: <20200603080904.997083-9-maozhongyi@cmss.chinamobile.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- docs/xbzrle.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/xbzrle.txt b/docs/xbzrle.txt index 385b4993f8..6bd1828f34 100644 --- a/docs/xbzrle.txt +++ b/docs/xbzrle.txt @@ -113,9 +113,11 @@ is recommended. xbzrle transferred: I kbytes xbzrle pages: J pages xbzrle cache miss: K pages - xbzrle overflow: L + xbzrle cache miss rate: L + xbzrle encoding rate: M + xbzrle overflow: N -xbzrle cache-miss: the number of cache misses to date - high cache-miss rate +xbzrle cache miss: the number of cache misses to date - high cache-miss rate indicates that the cache size is set too low. xbzrle overflow: the number of overflows in the decoding which where the delta could not be compressed. This can happen if the changes in the pages are too From 7e89a1401a9674c9882948f05f4d17ea7be1c4eb Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Wed, 17 Jun 2020 13:31:54 +0200 Subject: [PATCH 12/12] migration: fix multifd_send_pages() next channel multifd_send_pages() loops around the available channels, the next channel to use between two calls to multifd_send_pages() is stored inside a local static variable, next_channel. It works well, except if the number of channels decreases between two calls to multifd_send_pages(). In this case, the loop can try to access the data of a channel that doesn't exist anymore. The problem can be triggered if we start a migration with a given number of channels and then we cancel the migration to restart it with a lower number. This ends generally with an error like: qemu-system-ppc64: .../util/qemu-thread-posix.c:77: qemu_mutex_lock_impl: Assertion `mutex->initialized' failed. This patch fixes the error by capping next_channel with the current number of channels before using it. Signed-off-by: Laurent Vivier Message-Id: <20200617113154.593233-1-lvivier@redhat.com> Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/multifd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/migration/multifd.c b/migration/multifd.c index 5a3e4d0d46..d0441202aa 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -415,6 +415,12 @@ static int multifd_send_pages(QEMUFile *f) } qemu_sem_wait(&multifd_send_state->channels_ready); + /* + * next_channel can remain from a previous migration that was + * using more channels, so ensure it doesn't overflow if the + * limit is lower now. + */ + next_channel %= migrate_multifd_channels(); for (i = next_channel;; i = (i + 1) % migrate_multifd_channels()) { p = &multifd_send_state->params[i];