qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20200617a' into staging

Migration (and HMP and virtiofs) pull 2020-06-17

Migration:
HMP/migration and test changes from Mao Zhongyi
multifd fix from Laurent Vivier
HMP
qom-set partial reversion/change from David Hildenbrand
now you need -j to pass json format, but it's regained the
old 100M type format.
Memory leak fix from Pan Nengyuan

Virtiofs
fchmod seccomp fix from Max Reitz

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

# gpg: Signature made Wed 17 Jun 2020 19:34:58 BST
# gpg: using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7

* remotes/dgilbert/tags/pull-migration-20200617a:
migration: fix multifd_send_pages() next channel
docs/xbzrle: update 'cache miss rate' and 'encoding rate' to docs
monitor/hmp-cmds: improvements for the 'info migrate'
monitor/hmp-cmds: add 'goto end' to reduce duplicate code.
monitor/hmp-cmds: delete redundant Error check before invoke hmp_handle_error()
monitor/hmp-cmds: don't silently output when running 'migrate_set_downtime' fails
monitor/hmp-cmds: add units for migrate_parameters
tests/migration: fix unreachable path in stress test
tests/migration: mem leak fix
hmp: Make json format optional for qom-set
qom-hmp-cmds: fix a memleak in hmp_qom_get
virtiofsd: Whitelist fchmod

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+56 -51
+5 -3
docs/xbzrle.txt
··· 112 112 cache size: H bytes 113 113 xbzrle transferred: I kbytes 114 114 xbzrle pages: J pages 115 - xbzrle cache miss: K 116 - xbzrle overflow: L 115 + xbzrle cache miss: K pages 116 + xbzrle cache miss rate: L 117 + xbzrle encoding rate: M 118 + xbzrle overflow: N 117 119 118 - xbzrle cache-miss: the number of cache misses to date - high cache-miss rate 120 + xbzrle cache miss: the number of cache misses to date - high cache-miss rate 119 121 indicates that the cache size is set too low. 120 122 xbzrle overflow: the number of overflows in the decoding which where the delta 121 123 could not be compressed. This can happen if the changes in the pages are too
+4 -3
hmp-commands.hx
··· 1806 1806 1807 1807 { 1808 1808 .name = "qom-set", 1809 - .args_type = "path:s,property:s,value:S", 1810 - .params = "path property value", 1811 - .help = "set QOM property", 1809 + .args_type = "json:-j,path:s,property:s,value:S", 1810 + .params = "[-j] path property value", 1811 + .help = "set QOM property.\n\t\t\t" 1812 + "-j: the value is specified in json format.", 1812 1813 .cmd = hmp_qom_set, 1813 1814 .flags = "p", 1814 1815 },
+6
migration/multifd.c
··· 415 415 } 416 416 417 417 qemu_sem_wait(&multifd_send_state->channels_ready); 418 + /* 419 + * next_channel can remain from a previous migration that was 420 + * using more channels, so ensure it doesn't overflow if the 421 + * limit is lower now. 422 + */ 423 + next_channel %= migrate_multifd_channels(); 418 424 for (i = next_channel;; i = (i + 1) % migrate_multifd_channels()) { 419 425 p = &multifd_send_state->params[i]; 420 426
+16 -14
monitor/hmp-cmds.c
··· 299 299 info->xbzrle_cache->bytes >> 10); 300 300 monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n", 301 301 info->xbzrle_cache->pages); 302 - monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n", 302 + monitor_printf(mon, "xbzrle cache miss: %" PRIu64 " pages\n", 303 303 info->xbzrle_cache->cache_miss); 304 304 monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n", 305 305 info->xbzrle_cache->cache_miss_rate); ··· 316 316 info->compression->busy); 317 317 monitor_printf(mon, "compression busy rate: %0.2f\n", 318 318 info->compression->busy_rate); 319 - monitor_printf(mon, "compressed size: %" PRIu64 "\n", 320 - info->compression->compressed_size); 319 + monitor_printf(mon, "compressed size: %" PRIu64 " kbytes\n", 320 + info->compression->compressed_size >> 10); 321 321 monitor_printf(mon, "compression rate: %0.2f\n", 322 322 info->compression->compression_rate); 323 323 } ··· 443 443 MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH), 444 444 params->max_bandwidth); 445 445 assert(params->has_downtime_limit); 446 - monitor_printf(mon, "%s: %" PRIu64 " milliseconds\n", 446 + monitor_printf(mon, "%s: %" PRIu64 " ms\n", 447 447 MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT), 448 448 params->downtime_limit); 449 449 assert(params->has_x_checkpoint_delay); 450 - monitor_printf(mon, "%s: %u\n", 450 + monitor_printf(mon, "%s: %u ms\n", 451 451 MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY), 452 452 params->x_checkpoint_delay); 453 453 assert(params->has_block_incremental); ··· 460 460 monitor_printf(mon, "%s: %s\n", 461 461 MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_COMPRESSION), 462 462 MultiFDCompression_str(params->multifd_compression)); 463 - monitor_printf(mon, "%s: %" PRIu64 "\n", 463 + monitor_printf(mon, "%s: %" PRIu64 " bytes\n", 464 464 MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE), 465 465 params->xbzrle_cache_size); 466 466 monitor_printf(mon, "%s: %" PRIu64 "\n", ··· 1189 1189 /* Kept for backwards compatibility */ 1190 1190 void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict) 1191 1191 { 1192 + Error *err = NULL; 1193 + 1192 1194 double value = qdict_get_double(qdict, "value"); 1193 - qmp_migrate_set_downtime(value, NULL); 1195 + qmp_migrate_set_downtime(value, &err); 1196 + hmp_handle_error(mon, err); 1194 1197 } 1195 1198 1196 1199 void hmp_migrate_set_cache_size(Monitor *mon, const QDict *qdict) ··· 1499 1502 read_only, 1500 1503 BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err); 1501 1504 if (err) { 1502 - hmp_handle_error(mon, err); 1503 - return; 1505 + goto end; 1504 1506 } 1505 1507 } 1506 1508 ··· 1509 1511 &err); 1510 1512 } 1511 1513 1514 + end: 1512 1515 hmp_handle_error(mon, err); 1513 1516 } 1514 1517 ··· 1627 1630 1628 1631 opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); 1629 1632 if (err) { 1630 - hmp_handle_error(mon, err); 1631 - return; 1633 + goto end; 1632 1634 } 1633 1635 1634 1636 obj = user_creatable_add_opts(opts, &err); 1635 1637 qemu_opts_del(opts); 1636 1638 1637 - if (err) { 1638 - hmp_handle_error(mon, err); 1639 - } 1639 + end: 1640 + hmp_handle_error(mon, err); 1641 + 1640 1642 if (obj) { 1641 1643 object_unref(obj); 1642 1644 }
+17 -4
qom/qom-hmp-cmds.c
··· 44 44 45 45 void hmp_qom_set(Monitor *mon, const QDict *qdict) 46 46 { 47 + const bool json = qdict_get_try_bool(qdict, "json", false); 47 48 const char *path = qdict_get_str(qdict, "path"); 48 49 const char *property = qdict_get_str(qdict, "property"); 49 50 const char *value = qdict_get_str(qdict, "value"); 50 51 Error *err = NULL; 51 - QObject *obj; 52 + 53 + if (!json) { 54 + Object *obj = object_resolve_path(path, NULL); 55 + 56 + if (!obj) { 57 + error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND, 58 + "Device '%s' not found", path); 59 + } else { 60 + object_property_parse(obj, value, property, &err); 61 + } 62 + } else { 63 + QObject *obj = qobject_from_json(value, &err); 52 64 53 - obj = qobject_from_json(value, &err); 54 - if (err == NULL) { 55 - qmp_qom_set(path, property, obj, &err); 65 + if (!err) { 66 + qmp_qom_set(path, property, obj, &err); 67 + } 56 68 } 57 69 58 70 hmp_handle_error(mon, err); ··· 71 83 qobject_unref(str); 72 84 } 73 85 86 + qobject_unref(obj); 74 87 hmp_handle_error(mon, err); 75 88 } 76 89
+7 -27
tests/migration/stress.c
··· 167 167 return (tv.tv_sec * 1000ull) + (tv.tv_usec / 1000ull); 168 168 } 169 169 170 - static int stressone(unsigned long long ramsizeMB) 170 + static void stressone(unsigned long long ramsizeMB) 171 171 { 172 172 size_t pagesPerMB = 1024 * 1024 / PAGE_SIZE; 173 - char *ram = malloc(ramsizeMB * 1024 * 1024); 173 + g_autofree char *ram = g_malloc(ramsizeMB * 1024 * 1024); 174 174 char *ramptr; 175 175 size_t i, j, k; 176 - char *data = malloc(PAGE_SIZE); 176 + g_autofree char *data = g_malloc(PAGE_SIZE); 177 177 char *dataptr; 178 178 size_t nMB = 0; 179 179 unsigned long long before, after; 180 180 181 - if (!ram) { 182 - fprintf(stderr, "%s (%05d): ERROR: cannot allocate %llu MB of RAM: %s\n", 183 - argv0, gettid(), ramsizeMB, strerror(errno)); 184 - return -1; 185 - } 186 - if (!data) { 187 - fprintf(stderr, "%s (%d): ERROR: cannot allocate %d bytes of RAM: %s\n", 188 - argv0, gettid(), PAGE_SIZE, strerror(errno)); 189 - free(ram); 190 - return -1; 191 - } 192 - 193 181 /* We don't care about initial state, but we do want 194 182 * to fault it all into RAM, otherwise the first iter 195 183 * of the loop below will be quite slow. We can't use ··· 198 186 memset(ram, 0xfe, ramsizeMB * 1024 * 1024); 199 187 200 188 if (random_bytes(data, PAGE_SIZE) < 0) { 201 - free(ram); 202 - free(data); 203 - return -1; 189 + return; 204 190 } 205 191 206 192 before = now(); ··· 227 213 } 228 214 } 229 215 } 230 - 231 - free(data); 232 - free(ram); 233 216 } 234 217 235 218 ··· 242 225 return NULL; 243 226 } 244 227 245 - static int stress(unsigned long long ramsizeGB, int ncpus) 228 + static void stress(unsigned long long ramsizeGB, int ncpus) 246 229 { 247 230 size_t i; 248 231 unsigned long long ramsizeMB = ramsizeGB * 1024 / ncpus; ··· 255 238 } 256 239 257 240 stressone(ramsizeMB); 258 - 259 - return 0; 260 241 } 261 242 262 243 ··· 352 333 fprintf(stdout, "%s (%05d): INFO: RAM %llu GiB across %d CPUs\n", 353 334 argv0, gettid(), ramsizeGB, ncpus); 354 335 355 - if (stress(ramsizeGB, ncpus) < 0) 356 - exit_failure(); 336 + stress(ramsizeGB, ncpus); 357 337 358 - exit_success(); 338 + exit_failure(); 359 339 }
+1
tools/virtiofsd/seccomp.c
··· 42 42 SCMP_SYS(exit_group), 43 43 SCMP_SYS(fallocate), 44 44 SCMP_SYS(fchdir), 45 + SCMP_SYS(fchmod), 45 46 SCMP_SYS(fchmodat), 46 47 SCMP_SYS(fchownat), 47 48 SCMP_SYS(fcntl),