Merge tag 'next-pull-request' of https://gitlab.com/peterx/qemu into staging

Migration and mem pull request

- Peter's fix on 2nd migration crashing if the 1st migration cancelled early
- Phil's patch to remove VMS_MULTIPLY_ELEMENTS across tree
- Peter's fix on possible division by zero in recent query-migrate change
- Aadeshveer's cleanup for current_migration references
- Fabiano's fix of auto-converge test
- Maciej's maintainer file update for CPR
- Fabiano's migration qtest refactor to stick with -incoming defer
- Bin's cleanup / fix series all over migration (part of)
- hongmianquan's cpr optimization to use ghash for fd bookkeeping
- Yong's email address update

# -----BEGIN PGP SIGNATURE-----
#
# iIcEABYKADAWIQS5GE3CDMRX2s990ak7X8zN86vXBgUCag4ohxIccGV0ZXJ4QHJl
# ZGhhdC5jb20ACgkQO1/MzfOr1wbcVwD44j47Luc9/YKyug1h33kAIxLmuE3muwry
# Se9mtlhwAgEA1YzFtLxlshi3OqTJ++7AZt/jWv5J9yETXohqowFETAk=
# =KHDN
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 20 May 2026 17:32:55 EDT
# gpg:                using EDDSA key B9184DC20CC457DACF7DD1A93B5FCCCDF3ABD706
# gpg:                issuer "peterx@redhat.com"
# gpg: Good signature from "Peter Xu <xzpeter@gmail.com>" [full]
# gpg:                 aka "Peter Xu <peterx@redhat.com>" [full]
# Primary key fingerprint: B918 4DC2 0CC4 57DA CF7D  D1A9 3B5F CCCD F3AB D706

* tag 'next-pull-request' of https://gitlab.com/peterx/qemu: (29 commits)
  MAINTAINERS: Update email of Yong Huang
  migration/cpr: use hashtable for cpr fds
  migration/multifd: cache channel count in multifd_send_sync_main
  migration/multifd: cache migrate_multifd_channels() in send/recv hot paths
  migration/multifd: fix off-by-one in recv channel ID validation
  migration/savevm: use stack-allocated bitmap in configuration_validate_capabilities
  migration/vmstate: avoid per-element heap churn in vmsd ptr marker field
  migration/global_state: replace strcpy("") with explicit NUL termination
  tests/qtest/migration: Unify URIs
  tests/qtest/migration: Stop passing URI into migrate_start
  tests/qtest/migration: Use defer in dirty_limit test
  tests/qtest/migration: Use defer for auto-converge
  tests/qtest/migration: Use defer for cpr-tests
  tests/qtest/migration: Use defer for all tests
  tests/qtest/migration: Remove multifd compression hook
  tests/qtest/migration: Set compression method in compression-tests
  tests/qtest/migration: Defer by default in precopy_common
  tests/qtest/migration: Use a default TCP URI for precopy
  tests/qtest/migration: Use precopy_unix_common for ignore-shared test
  tests/qtest/migration: Group unix migration tests
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2026-05-21 08:59:54 -04:00
23 changed files with 395 additions and 588 deletions

View File

@@ -3189,6 +3189,7 @@ T: git https://gitlab.com/jsnow/qemu.git jobs
T: git https://gitlab.com/vsementsov/qemu.git block
CheckPoint and Restart (CPR)
M: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
R: Peter Xu <peterx@redhat.com>
R: Fabiano Rosas <farosas@suse.de>
R: Mark Kanda <mark.kanda@oracle.com>
@@ -3778,7 +3779,7 @@ F: migration/rdma*
F: scripts/rdma-migration-helper.sh
Migration dirty limit and dirty page rate
M: Hyman Huang <yong.huang@smartx.com>
M: Hyman Huang <infra.ai.cloud@bitdeer.com>
S: Maintained
F: system/dirtylimit.c
F: include/system/dirtylimit.h
@@ -3788,7 +3789,7 @@ F: include/system/dirtyrate.h
F: docs/devel/migration/dirty-limit.rst
Detached LUKS header
M: Hyman Huang <yong.huang@smartx.com>
M: Hyman Huang <infra.ai.cloud@bitdeer.com>
S: Maintained
F: tests/qemu-iotests/tests/luks-detached-header
F: docs/devel/luks-detached-header.rst

View File

@@ -57,6 +57,7 @@ QEMUFile *cpr_transfer_input(MigrationChannel *channel, Error **errp);
void cpr_transfer_add_hup_watch(MigrationState *s, QIOChannelFunc func,
void *opaque);
void cpr_transfer_source_destroy(MigrationState *s);
bool cpr_transfer_source_active(MigrationState *s);
void cpr_exec_init(void);
QEMUFile *cpr_exec_output(Error **errp);

View File

@@ -105,7 +105,7 @@ enum VMStateFlags {
VMS_ARRAY_OF_POINTER = 0x040,
/* The field is an array of variable size. The uint16_t at opaque
* + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)
* + VMStateField.num_offset
* contains the number of entries in the array. See the VMS_ARRAY
* description regarding array handling in general. May not be
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
@@ -126,14 +126,14 @@ enum VMStateFlags {
VMS_MULTIPLY = 0x200,
/* The field is an array of variable size. The uint8_t at opaque +
* VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)
* VMStateField.num_offset
* contains the number of entries in the array. See the VMS_ARRAY
* description regarding array handling in general. May not be
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
VMS_VARRAY_UINT8 = 0x400,
/* The field is an array of variable size. The uint32_t at opaque
* + VMStateField.num_offset (subject to VMS_MULTIPLY_ELEMENTS)
* + VMStateField.num_offset
* contains the number of entries in the array. See the VMS_ARRAY
* description regarding array handling in general. May not be
* combined with VMS_ARRAY or any other VMS_VARRAY*. */
@@ -150,12 +150,6 @@ enum VMStateFlags {
* cause the individual entries to be allocated. */
VMS_ALLOC = 0x2000,
/* Multiply the number of entries given by the integer at opaque +
* VMStateField.num_offset (see VMS_VARRAY*) with VMStateField.num
* to determine the number of entries in the array. Only valid in
* combination with one of VMS_VARRAY*. */
VMS_MULTIPLY_ELEMENTS = 0x4000,
/* A structure field that is like VMS_STRUCT, but uses
* VMStateField.struct_version_id to tell which version of the
* structure we are referencing to use. */
@@ -446,16 +440,6 @@ extern const VMStateInfo vmstate_info_qlist;
.offset = vmstate_offset_2darray(_state, _field, _type, _n1, _n2), \
}
#define VMSTATE_VARRAY_MULTIPLY(_field, _state, _field_num, _multiply, _info, _type) { \
.name = (stringify(_field)), \
.num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
.num = (_multiply), \
.info = &(_info), \
.size = sizeof(_type), \
.flags = VMS_VARRAY_UINT32|VMS_MULTIPLY_ELEMENTS, \
.offset = vmstate_offset_varray(_state, _field, _type), \
}
#define VMSTATE_SUB_ARRAY(_field, _state, _start, _num, _version, _info, _type) { \
.name = (stringify(_field)), \
.version_id = (_version), \

View File

@@ -6,6 +6,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "qapi/clone-visitor.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-migration.h"
@@ -79,6 +80,7 @@ QEMUFile *cpr_transfer_input(MigrationChannel *channel, Error **errp)
void cpr_transfer_add_hup_watch(MigrationState *s, QIOChannelFunc func,
void *opaque)
{
assert(bql_locked());
s->hup_source = qio_channel_create_watch(cpr_state_ioc(), G_IO_HUP);
g_source_set_callback(s->hup_source,
(GSourceFunc)func,
@@ -89,9 +91,17 @@ void cpr_transfer_add_hup_watch(MigrationState *s, QIOChannelFunc func,
void cpr_transfer_source_destroy(MigrationState *s)
{
assert(bql_locked());
if (s->hup_source) {
g_source_destroy(s->hup_source);
g_source_unref(s->hup_source);
s->hup_source = NULL;
}
}
bool cpr_transfer_source_active(MigrationState *s)
{
/* Whenever the HUP gsource is available, it's active. */
assert(bql_locked());
return s->hup_source;
}

View File

@@ -24,6 +24,7 @@
/* cpr state container for all information to be saved. */
CprState cpr_state;
static GHashTable *cpr_fds_hash;
/****************************************************************************/
@@ -48,6 +49,84 @@ static const VMStateDescription vmstate_cpr_fd = {
}
};
static guint cpr_fd_hash(gconstpointer v)
{
const CprFd *elem = v;
return g_str_hash(elem->name) ^ elem->id;
}
static gboolean cpr_fd_equal(gconstpointer a, gconstpointer b)
{
const CprFd *elem_a = a;
const CprFd *elem_b = b;
return !strcmp(elem_a->name, elem_b->name) && elem_a->id == elem_b->id;
}
static void cpr_fd_destroy(gpointer data)
{
CprFd *elem = data;
g_free(elem->name);
g_free(elem);
}
static GHashTable *get_cpr_fds_hash(void)
{
if (!cpr_fds_hash) {
cpr_fds_hash = g_hash_table_new_full(cpr_fd_hash, cpr_fd_equal,
cpr_fd_destroy, NULL);
}
return cpr_fds_hash;
}
static void cpr_fd_hash_insert(CprFd *elem)
{
/* Use the same CprFd as key and value. */
g_hash_table_insert(get_cpr_fds_hash(), elem, elem);
}
static int cpr_fd_pre_save(void *opaque)
{
CprState *state = (CprState *)opaque;
GHashTableIter iter;
CprFd *elem;
QLIST_INIT(&state->fds);
g_hash_table_iter_init(&iter, get_cpr_fds_hash());
while (g_hash_table_iter_next(&iter, (gpointer *)&elem, NULL)) {
QLIST_INSERT_HEAD(&state->fds, elem, next);
}
return 0;
}
static int cpr_fd_post_load(void *opaque, int version_id)
{
CprState *state = (CprState *)opaque;
CprFd *elem;
while ((elem = QLIST_FIRST(&state->fds))) {
QLIST_REMOVE(elem, next);
/*
* Preserve legacy QLIST lookup semantics if duplicate keys exist in
* the incoming stream: the first matching entry wins.
*/
if (g_hash_table_contains(get_cpr_fds_hash(), elem)) {
cpr_fd_destroy(elem);
continue;
}
cpr_fd_hash_insert(elem);
}
return 0;
}
void cpr_save_fd(const char *name, int id, int fd)
{
CprFd *elem = g_new0(CprFd, 1);
@@ -57,37 +136,34 @@ void cpr_save_fd(const char *name, int id, int fd)
elem->namelen = strlen(name) + 1;
elem->id = id;
elem->fd = fd;
QLIST_INSERT_HEAD(&cpr_state.fds, elem, next);
cpr_fd_hash_insert(elem);
}
static CprFd *find_fd(CprFdList *head, const char *name, int id)
static CprFd *find_fd(const char *name, int id)
{
CprFd *elem;
CprFd key = {
.name = (char *)name,
.id = id,
};
QLIST_FOREACH(elem, head, next) {
if (!strcmp(elem->name, name) && elem->id == id) {
return elem;
}
}
return NULL;
return g_hash_table_lookup(get_cpr_fds_hash(), &key);
}
void cpr_delete_fd(const char *name, int id)
{
CprFd *elem = find_fd(&cpr_state.fds, name, id);
CprFd key = {
.name = (char *)name,
.id = id,
};
if (elem) {
QLIST_REMOVE(elem, next);
g_free(elem->name);
g_free(elem);
}
g_hash_table_remove(get_cpr_fds_hash(), &key);
trace_cpr_delete_fd(name, id);
}
int cpr_find_fd(const char *name, int id)
{
CprFd *elem = find_fd(&cpr_state.fds, name, id);
CprFd *elem = find_fd(name, id);
int fd = elem ? elem->fd : -1;
trace_cpr_find_fd(name, id, fd);
@@ -96,7 +172,7 @@ int cpr_find_fd(const char *name, int id)
void cpr_resave_fd(const char *name, int id, int fd)
{
CprFd *elem = find_fd(&cpr_state.fds, name, id);
CprFd *elem = find_fd(name, id);
int old_fd = elem ? elem->fd : -1;
if (old_fd < 0) {
@@ -125,9 +201,11 @@ int cpr_open_fd(const char *path, int flags, const char *name, int id,
bool cpr_walk_fd(cpr_walk_fd_cb cb)
{
GHashTableIter iter;
CprFd *elem;
QLIST_FOREACH(elem, &cpr_state.fds, next) {
g_hash_table_iter_init(&iter, get_cpr_fds_hash());
while (g_hash_table_iter_next(&iter, (gpointer *)&elem, NULL)) {
g_assert(elem->fd >= 0);
if (!cb(elem->fd)) {
return false;
@@ -141,6 +219,8 @@ static const VMStateDescription vmstate_cpr_state = {
.name = CPR_STATE,
.version_id = 1,
.minimum_version_id = 1,
.pre_save = cpr_fd_pre_save,
.post_load = cpr_fd_post_load,
.fields = (VMStateField[]) {
VMSTATE_QLIST_V(fds, CprState, 1, vmstate_cpr_fd, CprFd, next),
VMSTATE_END_OF_LIST()

View File

@@ -148,7 +148,7 @@ static const VMStateDescription vmstate_globalstate = {
void register_global_state(void)
{
/* We would use it independently that we receive it */
strcpy((char *)&global_state.runstate, "");
global_state.runstate[0] = '\0';
global_state.received = false;
vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
}

View File

@@ -63,6 +63,7 @@
#include "system/dirtylimit.h"
#include "qemu/sockets.h"
#include "system/kvm.h"
#include "math.h"
#define NOTIFIER_ELEM_INIT(array, elem) \
[elem] = NOTIFIER_WITH_RETURN_LIST_INITIALIZER((array)[elem])
@@ -1029,7 +1030,7 @@ bool migration_is_running(void)
static bool migration_is_active(void)
{
MigrationState *s = current_migration;
MigrationState *s = migrate_get_current();
return (s->state == MIGRATION_STATUS_ACTIVE ||
s->state == MIGRATION_STATUS_POSTCOPY_DEVICE ||
@@ -1044,12 +1045,29 @@ static bool migrate_show_downtime(MigrationState *s)
/* Return expected downtime (unit: milliseconds) */
int64_t migration_downtime_calc_expected(MigrationState *s)
{
double expected_ms;
if (mig_stats.dirty_sync_count <= 1) {
return migrate_downtime_limit();
}
return mig_stats.dirty_bytes_last_sync /
expected_ms = mig_stats.dirty_bytes_last_sync /
migration_get_switchover_bw(s) * 1000;
/*
* If we haven't been able to transfer any data, the result here could
* be NaN (for 0 / 0) or infinity (something else / 0).
*
* Return INT64_MAX as our best approximation to "this will take
* forever to complete". If the problem is transient (e.g. we just
* haven't started to transfer yet) we'll recalculate to a more
* accurate figure later.
*/
if (isnan(expected_ms) || expected_ms >= (double)INT64_MAX) {
return INT64_MAX;
}
return (int64_t) expected_ms;
}
static void populate_time_info(MigrationInfo *info, MigrationState *s)
@@ -1502,14 +1520,19 @@ void migration_cancel(void)
}
/*
* If migration_connect_outgoing has not been called, then there
* is no path that will complete the cancellation. Do it now.
* This is cpr-transfer specific processing.
*
* If this is true, it means cpr-transfer migration is waiting for the
* destination to send HUP event on CPR channel to continue the next
* phase. If so, do the cleanup proactively to avoid get stuck in
* CANCELLING state.
*/
if (setup && !s->to_dst_file) {
migrate_set_state(&s->state, MIGRATION_STATUS_CANCELLING,
MIGRATION_STATUS_CANCELLED);
cpr_state_close();
cpr_transfer_source_destroy(s);
if (cpr_transfer_source_active(s)) {
assert(migrate_mode() == MIG_MODE_CPR_TRANSFER);
assert(setup && !s->to_dst_file);
migration_cleanup(s);
/* Now all things should have been released */
assert(!cpr_transfer_source_active(s));
}
}
@@ -1634,7 +1657,7 @@ bool migration_in_bg_snapshot(void)
bool migration_thread_is_self(void)
{
MigrationState *s = current_migration;
MigrationState *s = migrate_get_current();
return qemu_thread_is_self(&s->thread);
}
@@ -2045,12 +2068,22 @@ static gboolean migration_connect_outgoing_cb(QIOChannel *channel,
MigrationState *s = migrate_get_current();
Error *local_err = NULL;
/*
* Detach and release the GSource right after use. We rely on this to
* detect this small cpr-transfer window of "waiting for HUP event".
*/
cpr_transfer_source_destroy(s);
migration_connect_outgoing(s, opaque, &local_err);
if (local_err) {
migration_connect_error_propagate(s, local_err);
}
/*
* This is redundant as we do cpr_transfer_source_destroy() at the
* entry, but it's benign; glib will just skip the detach.
*/
return G_SOURCE_REMOVE;
}
@@ -3062,7 +3095,7 @@ static MigThrError postcopy_pause(MigrationState *s)
void migration_file_set_error(int ret, Error *err)
{
MigrationState *s = current_migration;
MigrationState *s = migrate_get_current();
WITH_QEMU_LOCK_GUARD(&s->qemu_file_lock) {
if (s->to_dst_file) {

View File

@@ -512,6 +512,11 @@ struct MigrationState {
bool postcopy_package_loaded;
/*
* When set, it means cpr-transfer is waiting for the HUP signal from
* destination to continue the 2nd step of migration via the main
* channel.
*/
GSource *hup_source;
/*

View File

@@ -210,9 +210,9 @@ static int multifd_recv_initial_packet(QIOChannel *c, Error **errp)
return -1;
}
if (msg.id > migrate_multifd_channels()) {
error_setg(errp, "multifd: received channel id %u is greater than "
"number of channels %u", msg.id, migrate_multifd_channels());
if (msg.id >= migrate_multifd_channels()) {
error_setg(errp, "multifd: received channel id %u exceeds "
"channel count %u", msg.id, migrate_multifd_channels());
return -1;
}
@@ -362,13 +362,15 @@ bool multifd_send(MultiFDSendData **send_data)
/* We wait here, until at least one channel is ready */
qemu_sem_wait(&multifd_send_state->channels_ready);
int thread_count = migrate_multifd_channels();
/*
* 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()) {
next_channel %= thread_count;
for (i = next_channel;; i = (i + 1) % thread_count) {
if (multifd_send_should_exit()) {
return false;
}
@@ -378,7 +380,7 @@ bool multifd_send(MultiFDSendData **send_data)
* sender thread can clear it.
*/
if (qatomic_read(&p->pending_job) == false) {
next_channel = (i + 1) % migrate_multifd_channels();
next_channel = (i + 1) % thread_count;
break;
}
}
@@ -609,13 +611,15 @@ static int multifd_zero_copy_flush(QIOChannel *c)
int multifd_send_sync_main(MultiFDSyncReq req)
{
int i;
int thread_count;
bool flush_zero_copy;
assert(req != MULTIFD_SYNC_NONE);
thread_count = migrate_multifd_channels();
flush_zero_copy = migrate_zero_copy_send();
for (i = 0; i < migrate_multifd_channels(); i++) {
for (i = 0; i < thread_count; i++) {
MultiFDSendParams *p = &multifd_send_state->params[i];
if (multifd_send_should_exit()) {
@@ -632,7 +636,7 @@ int multifd_send_sync_main(MultiFDSyncReq req)
qatomic_set(&p->pending_sync, req);
qemu_sem_post(&p->sem);
}
for (i = 0; i < migrate_multifd_channels(); i++) {
for (i = 0; i < thread_count; i++) {
MultiFDSendParams *p = &multifd_send_state->params[i];
if (multifd_send_should_exit()) {
@@ -998,6 +1002,7 @@ bool multifd_recv(void)
int i;
static int next_recv_channel;
MultiFDRecvParams *p = NULL;
int thread_count = migrate_multifd_channels();
MultiFDRecvData *data = multifd_recv_state->data;
/*
@@ -1005,8 +1010,8 @@ bool multifd_recv(void)
* using more channels, so ensure it doesn't overflow if the
* limit is lower now.
*/
next_recv_channel %= migrate_multifd_channels();
for (i = next_recv_channel;; i = (i + 1) % migrate_multifd_channels()) {
next_recv_channel %= thread_count;
for (i = next_recv_channel;; i = (i + 1) % thread_count) {
if (multifd_recv_should_exit()) {
return false;
}
@@ -1014,7 +1019,7 @@ bool multifd_recv(void)
p = &multifd_recv_state->params[i];
if (qatomic_read(&p->pending_job) == false) {
next_recv_channel = (i + 1) % migrate_multifd_channels();
next_recv_channel = (i + 1) % thread_count;
break;
}
}

View File

@@ -347,10 +347,10 @@ static bool configuration_validate_capabilities(SaveState *state)
{
bool ret = true;
MigrationState *s = migrate_get_current();
unsigned long *source_caps_bm;
DECLARE_BITMAP(source_caps_bm, MIGRATION_CAPABILITY__MAX);
int i;
source_caps_bm = bitmap_new(MIGRATION_CAPABILITY__MAX);
bitmap_zero(source_caps_bm, MIGRATION_CAPABILITY__MAX);
for (i = 0; i < state->caps_count; i++) {
MigrationCapability capability = state->capabilities[i];
set_bit(capability, source_caps_bm);
@@ -373,7 +373,6 @@ static bool configuration_validate_capabilities(SaveState *state)
}
}
g_free(source_caps_bm);
return ret;
}

View File

@@ -59,29 +59,23 @@ vmstate_field_exists(const VMStateDescription *vmsd, const VMStateField *field,
* array of a VMS_ARRAY_OF_POINTER VMSD field. It's needed because we
* can't dereference the NULL pointer.
*/
static const VMStateField *
vmsd_create_ptr_marker_field(const VMStateField *field)
static void
vmsd_init_ptr_marker_field(VMStateField *fake, const VMStateField *field)
{
VMStateField *fake = g_new0(VMStateField, 1);
/* It can only happen on an array of pointers! */
assert(field->flags & VMS_ARRAY_OF_POINTER);
/* Some of fake's properties should match the original's */
fake->name = field->name;
fake->version_id = field->version_id;
/* Do not need "field_exists" check as it always exists */
fake->field_exists = NULL;
/* See vmstate_info_ptr_marker - use 1 byte to represent ptr status */
fake->size = 1;
fake->info = &vmstate_info_ptr_marker;
fake->flags = VMS_SINGLE;
/* All the rest fields shouldn't matter.. */
return (const VMStateField *)fake;
/* See vmstate_info_ptr_marker - 1 byte represents ptr status */
*fake = (VMStateField) {
.name = field->name,
.version_id = field->version_id,
/* Marker always exists, no field_exists callback needed */
.field_exists = NULL,
.size = 1,
.info = &vmstate_info_ptr_marker,
.flags = VMS_SINGLE,
/* All other fields stay zero-initialised */
};
}
static int vmstate_n_elems(void *opaque, const VMStateField *field)
@@ -100,10 +94,6 @@ static int vmstate_n_elems(void *opaque, const VMStateField *field)
n_elems = *(uint8_t *)(opaque + field->num_offset);
}
if (field->flags & VMS_MULTIPLY_ELEMENTS) {
n_elems *= field->num;
}
trace_vmstate_n_elems(field->name, n_elems);
return n_elems;
}
@@ -680,6 +670,7 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
for (i = 0; i < n_elems; i++) {
void *curr_elem = first_elem + size * i;
const VMStateField *inner_field;
VMStateField marker_field;
/* maximum number of elements to compress in the JSON blob */
int max_elems = vmsd_can_compress(field) ? (n_elems - i) : 1;
bool use_marker_field, is_null = false;
@@ -693,7 +684,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
use_marker_field = use_dynamic_array || is_null;
if (use_marker_field) {
inner_field = vmsd_create_ptr_marker_field(field);
vmsd_init_ptr_marker_field(&marker_field, field);
inner_field = &marker_field;
} else {
inner_field = field;
}
@@ -730,11 +722,6 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
inner_field, vmdesc_loop,
i, max_elems, errp);
/* If we used a fake temp field.. free it now */
if (use_marker_field) {
g_clear_pointer((gpointer *)&inner_field, g_free);
}
if (!ok) {
goto out;
}

View File

@@ -114,12 +114,4 @@ impl VMStateField {
assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0);
self.with_varray_flag_unchecked(flag)
}
#[must_use]
pub const fn with_varray_multiply(mut self, num: u32) -> Self {
assert!(num <= 0x7FFF_FFFFu32);
self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0);
self.num = num as i32;
self
}
}

View File

@@ -159,8 +159,7 @@ macro_rules! vmstate_of {
)$(.with_varray_flag($crate::call_func_with_field!(
$crate::vmstate::vmstate_varray_flag,
$struct_name,
$($num).+))
$(.with_varray_multiply($factor))?)?
$($num).+)))?
}
};
}

View File

@@ -118,34 +118,6 @@ fn test_vmstate_varray_uint16_unsafe() {
assert!(foo_fields[2].field_exists.is_none());
}
#[test]
fn test_vmstate_varray_multiply() {
let foo_fields: &[VMStateField] =
unsafe { slice::from_raw_parts(VMSTATE_FOOA.as_ref().fields, 5) };
// 4th VMStateField ("arr_mul") in VMSTATE_FOOA (corresponding to
// VMSTATE_VARRAY_MULTIPLY)
assert_eq!(
unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(),
b"arr_mul\0"
);
assert_eq!(foo_fields[3].offset, 6);
assert_eq!(foo_fields[3].num_offset, 12);
assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_int8 });
assert_eq!(foo_fields[3].version_id, 0);
assert_eq!(foo_fields[3].size, 1);
assert_eq!(foo_fields[3].num, 16);
assert_eq!(
foo_fields[3].flags.0,
VMStateFlags::VMS_VARRAY_UINT32.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0
);
assert!(foo_fields[3].vmsd.is_null());
assert!(foo_fields[3].field_exists.is_none());
// The last VMStateField in VMSTATE_FOOA.
assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END);
}
// =========================== Test VMSTATE_FOOB ===========================
// Test the use cases of the vmstate macro, corresponding to the following C
// macro variants:
@@ -256,33 +228,6 @@ fn test_vmstate_struct_varray_uint8() {
assert!(foo_fields[2].field_exists.is_none());
}
#[test]
fn test_vmstate_struct_varray_uint32_multiply() {
let foo_fields: &[VMStateField] =
unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) };
// 4th VMStateField ("arr_a_mul") in VMSTATE_FOOB (corresponding to
// (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32)
assert_eq!(
unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(),
b"arr_a_mul\0"
);
assert_eq!(foo_fields[3].offset, 64);
assert_eq!(foo_fields[3].num_offset, 124);
assert!(foo_fields[3].info.is_null()); // VMSTATE_STRUCT_VARRAY_UINT8 doesn't set info field.
assert_eq!(foo_fields[3].version_id, 2);
assert_eq!(foo_fields[3].size, 20);
assert_eq!(foo_fields[3].num, 32);
assert_eq!(
foo_fields[3].flags.0,
VMStateFlags::VMS_STRUCT.0
| VMStateFlags::VMS_VARRAY_UINT32.0
| VMStateFlags::VMS_MULTIPLY_ELEMENTS.0
);
assert_eq!(foo_fields[3].vmsd, VMSTATE_FOOA.as_ref());
assert!(foo_fields[3].field_exists.is_none());
}
#[test]
fn test_vmstate_macro_array() {
let foo_fields: &[VMStateField] =

View File

@@ -45,7 +45,7 @@ static int test_colo_common(MigrateCommon *args,
args->start.caps[MIGRATION_CAPABILITY_RETURN_PATH] = true;
args->start.caps[MIGRATION_CAPABILITY_X_COLO] = true;
if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return -1;
}
@@ -55,10 +55,12 @@ static int test_colo_common(MigrateCommon *args,
data_hook = args->start_hook(from, to);
}
migrate_incoming_qmp(to, args->uri, NULL, "{}");
migrate_ensure_converge(from);
wait_for_serial("src_serial");
migrate_qmp(from, to, args->connect_uri, NULL, "{}");
migrate_qmp(from, to, NULL, NULL, "{}");
wait_for_migration_status(from, "colo", NULL);
wait_for_resume(to, get_dst());
@@ -103,21 +105,15 @@ static void test_colo_plain_common(MigrateCommon *args,
bool failover_during_checkpoint,
bool primary_failover)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->uri = "tcp:127.0.0.1:0";
test_colo_common(args, failover_during_checkpoint, primary_failover);
}
static void *hook_start_multifd(QTestState *from, QTestState *to)
{
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
}
static void test_colo_multifd_common(MigrateCommon *args,
bool failover_during_checkpoint,
bool primary_failover)
{
args->listen_uri = "defer";
args->start_hook = hook_start_multifd;
args->uri = "tcp:127.0.0.1:0";
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
test_colo_common(args, failover_during_checkpoint, primary_failover);
}

View File

@@ -20,6 +20,13 @@
static char *tmpfs;
static void set_multifd_compression(QTestState *from, QTestState *to,
const char *method)
{
migrate_set_parameter_str(from, "multifd-compression", method);
migrate_set_parameter_str(to, "multifd-compression", method);
}
#ifdef CONFIG_ZSTD
static void *
migrate_hook_start_precopy_tcp_multifd_zstd(QTestState *from,
@@ -27,13 +34,13 @@ migrate_hook_start_precopy_tcp_multifd_zstd(QTestState *from,
{
migrate_set_parameter_int(from, "multifd-zstd-level", 2);
migrate_set_parameter_int(to, "multifd-zstd-level", 2);
set_multifd_compression(from, to, "zstd");
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "zstd");
return NULL;
}
static void test_multifd_tcp_zstd(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_zstd;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -43,7 +50,6 @@ static void test_multifd_tcp_zstd(char *name, MigrateCommon *args)
static void test_multifd_postcopy_tcp_zstd(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_zstd,
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -60,13 +66,13 @@ migrate_hook_start_precopy_tcp_multifd_qatzip(QTestState *from,
{
migrate_set_parameter_int(from, "multifd-qatzip-level", 2);
migrate_set_parameter_int(to, "multifd-qatzip-level", 2);
set_multifd_compression(from, to, "qatzip");
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "qatzip");
return NULL;
}
static void test_multifd_tcp_qatzip(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_qatzip;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -80,12 +86,12 @@ static void *
migrate_hook_start_precopy_tcp_multifd_qpl(QTestState *from,
QTestState *to)
{
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "qpl");
set_multifd_compression(from, to, "qpl");
return NULL;
}
static void test_multifd_tcp_qpl(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_qpl;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -99,12 +105,12 @@ static void *
migrate_hook_start_precopy_tcp_multifd_uadk(QTestState *from,
QTestState *to)
{
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "uadk");
set_multifd_compression(from, to, "uadk");
return NULL;
}
static void test_multifd_tcp_uadk(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_uadk;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -123,10 +129,6 @@ migrate_hook_start_xbzrle(QTestState *from,
static void test_precopy_unix_xbzrle(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->connect_uri = uri;
args->listen_uri = uri;
args->start_hook = migrate_hook_start_xbzrle;
args->iterations = 2;
/*
@@ -137,7 +139,7 @@ static void test_precopy_unix_xbzrle(char *name, MigrateCommon *args)
args->start.caps[MIGRATION_CAPABILITY_XBZRLE] = true;
test_precopy_common(args);
test_precopy_unix_common(args);
}
static void *
@@ -150,13 +152,13 @@ migrate_hook_start_precopy_tcp_multifd_zlib(QTestState *from,
*/
migrate_set_parameter_int(from, "multifd-zlib-level", 2);
migrate_set_parameter_int(to, "multifd-zlib-level", 2);
set_multifd_compression(from, to, "zlib");
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "zlib");
return NULL;
}
static void test_multifd_tcp_zlib(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_zlib;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;

View File

@@ -15,6 +15,9 @@
#include "migration/framework.h"
#include "migration/migration-qmp.h"
#include "migration/migration-util.h"
#include "qapi/error.h"
#include "qobject/qjson.h"
#include "qobject/qlist.h"
static char *tmpfs;
@@ -32,8 +35,7 @@ static void test_mode_reboot(char *name, MigrateCommon *args)
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
args->start_hook = migrate_hook_start_mode_reboot;
args->start.mem_type = MEM_TYPE_SHMEM;
@@ -42,10 +44,56 @@ static void test_mode_reboot(char *name, MigrateCommon *args)
test_file_common(args, true);
}
static void *test_mode_transfer_start(QTestState *from, QTestState *to)
static int test_transfer(MigrateCommon *args, const char *cpr_channel,
bool incoming_defer)
{
QTestState *from, *to;
QObject *obj, *out_channels = qobject_from_json(args->connect_channels,
&error_abort);
QList *channels_list;
/*
* The cpr channel must be included in outgoing channels, but not in
* migrate-incoming channels.
*/
channels_list = qobject_to(QList, out_channels);
obj = migrate_str_to_channel(cpr_channel);
qlist_append(channels_list, obj);
if (migrate_start(&from, &to, &args->start)) {
return -1;
}
migrate_set_parameter_str(from, "mode", "cpr-transfer");
return NULL;
wait_for_serial("src_serial");
qtest_qmp_assert_success(from, "{ 'execute' : 'stop'}");
wait_for_stop(from, get_src());
migrate_ensure_converge(from);
migrate_qmp(from, to, NULL, out_channels, "{}");
qtest_connect(to);
qtest_qmp_handshake(to, NULL);
if (incoming_defer) {
QObject *in_channels = qobject_from_json(args->connect_channels,
&error_abort);
migrate_incoming_qmp(to, NULL, in_channels, "{}");
}
wait_for_migration_complete(from);
wait_for_migration_complete(to);
qtest_qmp_assert_success(to, "{ 'execute' : 'cont'}");
wait_for_resume(to, get_dst());
wait_for_serial("dest_serial");
migrate_end(from, to, true);
return 0;
}
/*
@@ -80,21 +128,25 @@ static void test_mode_transfer_common(MigrateCommon *args, bool incoming_defer)
int cpr_sockfd = qtest_socket_server(cpr_path);
g_assert(cpr_sockfd >= 0);
opts_target = g_strdup_printf("-incoming cpr,addr.transport=socket,"
"addr.type=fd,addr.str=%d %s",
cpr_sockfd, opts);
if (incoming_defer) {
opts_target = g_strdup_printf("-incoming cpr,addr.transport=socket,"
"addr.type=fd,addr.str=%d %s",
cpr_sockfd, opts);
} else {
opts_target = g_strdup_printf("-incoming %s "
"-incoming cpr,addr.transport=socket,"
"addr.type=fd,addr.str=%d %s",
uri, cpr_sockfd, opts);
}
args->listen_uri = incoming_defer ? "defer" : uri;
args->connect_channels = connect_channels;
args->cpr_channel = cpr_channel;
args->start_hook = test_mode_transfer_start;
args->start.opts_source = opts;
args->start.opts_target = opts_target;
args->start.defer_target_connect = true;
args->start.mem_type = MEM_TYPE_MEMFD;
if (test_precopy_common(args) < 0) {
if (test_transfer(args, cpr_channel, incoming_defer) < 0) {
close(cpr_sockfd);
unlink(cpr_path);
}
@@ -127,7 +179,7 @@ static void set_cpr_exec_args(QTestState *who, MigrateCommon *args)
*/
g_assert(args->start.hide_stderr == false);
ret = migrate_args(&from_args, &to_args, args->listen_uri, &args->start);
ret = migrate_args(&from_args, &to_args, &args->start);
g_assert(!ret);
qtest_from_args = qtest_qemu_args(from_args);
@@ -174,11 +226,11 @@ static void test_cpr_exec(MigrateCommon *args)
{
QTestState *from, *to;
void *data_hook = NULL;
g_autofree char *connect_uri = g_strdup(args->connect_uri);
g_autofree char *connect_uri = g_strdup(args->uri);
g_autofree char *filename = g_strdup_printf("%s/%s", tmpfs,
FILE_TEST_FILENAME);
if (migrate_start(&from, NULL, args->listen_uri, &args->start)) {
if (migrate_start(&from, NULL, &args->start)) {
return;
}
@@ -228,10 +280,7 @@ static void test_mode_exec(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
g_autofree char *listen_uri = g_strdup_printf("defer");
args->connect_uri = uri;
args->listen_uri = listen_uri;
args->uri = uri;
args->start_hook = test_mode_exec_start;
args->start.only_source = true;

View File

@@ -47,8 +47,7 @@ static void test_file_connect_outgoing_fd_leak(char *name, MigrateCommon *args)
return;
}
args->listen_uri = "defer";
if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -67,11 +66,6 @@ static void test_file_connect_outgoing_fd_leak(char *name, MigrateCommon *args)
static void test_precopy_file(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
test_file_common(args, true);
}
@@ -113,8 +107,7 @@ static void test_precopy_file_offset_fdset(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
FILE_TEST_OFFSET);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
args->start_hook = migrate_hook_start_file_offset_fdset;
test_file_common(args, false);
@@ -127,9 +120,7 @@ static void test_precopy_file_offset(char *name, MigrateCommon *args)
FILE_TEST_FILENAME,
FILE_TEST_OFFSET);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
test_file_common(args, false);
}
@@ -139,8 +130,7 @@ static void test_precopy_file_offset_bad(char *name, MigrateCommon *args)
g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=0x20M",
tmpfs, FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
args->result = MIG_TEST_QMP_ERROR;
test_file_common(args, false);
@@ -148,12 +138,6 @@ static void test_precopy_file_offset_bad(char *name, MigrateCommon *args)
static void test_precopy_file_mapped_ram_live(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->start.caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true;
test_file_common(args, false);
@@ -161,12 +145,6 @@ static void test_precopy_file_mapped_ram_live(char *name, MigrateCommon *args)
static void test_precopy_file_mapped_ram(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->start.caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true;
test_file_common(args, true);
@@ -174,11 +152,6 @@ static void test_precopy_file_mapped_ram(char *name, MigrateCommon *args)
static void test_multifd_file_mapped_ram_live(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
args->start.caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true;
@@ -187,12 +160,6 @@ static void test_multifd_file_mapped_ram_live(char *name, MigrateCommon *args)
static void test_multifd_file_mapped_ram(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
args->start.caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true;
@@ -210,10 +177,6 @@ static void *migrate_hook_start_multifd_mapped_ram_dio(QTestState *from,
static void test_multifd_file_mapped_ram_dio(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_mapped_ram_dio;
args->start.caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true;
@@ -284,8 +247,7 @@ static void test_multifd_file_mapped_ram_fdset(char *name, MigrateCommon *args)
g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
FILE_TEST_OFFSET);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
args->start_hook = migrate_hook_start_multifd_mapped_ram_fdset;
args->end_hook = migrate_hook_end_multifd_mapped_ram_fdset;
@@ -300,8 +262,7 @@ static void test_multifd_file_mapped_ram_fdset_dio(char *name,
{
g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
FILE_TEST_OFFSET);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
args->start_hook = migrate_hook_start_multifd_mapped_ram_fdset_dio;
args->end_hook = migrate_hook_end_multifd_mapped_ram_fdset;
@@ -329,11 +290,6 @@ static void migration_test_add_file_smoke(MigrationTestEnv *env)
static void
test_precopy_file_mapped_ram_ignore_shared(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
args->connect_uri = uri;
args->listen_uri = "defer";
args->start.caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true;
args->start.caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED] = true;

View File

@@ -20,7 +20,6 @@
#include "ppc-util.h"
#include "qapi/error.h"
#include "qobject/qjson.h"
#include "qobject/qlist.h"
#include "qemu/bswap.h"
#include "qemu/module.h"
#include "qemu/option.h"
@@ -309,7 +308,7 @@ static char *migrate_mem_type_get_opts(MemType type, const char *memory_size)
return opts;
}
int migrate_args(char **from, char **to, const char *uri, MigrateStart *args)
int migrate_args(char **from, char **to, MigrateStart *args)
{
/* options for source and target */
g_autofree gchar *arch_opts = NULL;
@@ -424,11 +423,11 @@ int migrate_args(char **from, char **to, const char *uri, MigrateStart *args)
"-name target,debug-threads=on "
"%s "
"-serial file:%s/dest_serial "
"-incoming %s "
"-incoming defer "
"%s %s %s %s",
kvm_opts ? kvm_opts : "",
machine, machine_opts,
memory_backend, tmpfs, uri,
memory_backend, tmpfs,
events,
arch_opts ? arch_opts : "",
args->opts_target ? args->opts_target : "",
@@ -475,8 +474,7 @@ static void migrate_mem_type_cleanup(MemType type)
}
}
int migrate_start(QTestState **from, QTestState **to, const char *uri,
MigrateStart *args)
int migrate_start(QTestState **from, QTestState **to, MigrateStart *args)
{
g_autofree gchar *cmd_source = NULL;
g_autofree gchar *cmd_target = NULL;
@@ -491,7 +489,7 @@ int migrate_start(QTestState **from, QTestState **to, const char *uri,
bootfile_create(qtest_get_arch(), tmpfs, args->suspend_me);
src_state.suspend_me = args->suspend_me;
if (migrate_args(&cmd_source, &cmd_target, uri, args)) {
if (migrate_args(&cmd_source, &cmd_target, args)) {
return -1;
}
@@ -564,7 +562,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
args->start.caps[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME] = true;
args->start.caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] = true;
if (migrate_start(&from, &to, "defer", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return -1;
}
@@ -833,12 +831,10 @@ int test_precopy_common(MigrateCommon *args)
{
QTestState *from, *to;
void *data_hook = NULL;
QObject *in_channels = NULL;
QObject *out_channels = NULL;
QObject *channels = NULL;
const char *listen_uri = args->uri ?: "tcp:127.0.0.1:0";
g_assert(!args->cpr_channel || args->connect_channels);
if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return -1;
}
@@ -846,6 +842,8 @@ int test_precopy_common(MigrateCommon *args)
data_hook = args->start_hook(from, to);
}
migrate_incoming_qmp(to, listen_uri, NULL, "{}");
/* Wait for the first serial output from the source */
if (args->result == MIG_TEST_SUCCEED) {
wait_for_serial("src_serial");
@@ -869,40 +867,16 @@ int test_precopy_common(MigrateCommon *args)
}
}
/*
* The cpr channel must be included in outgoing channels, but not in
* migrate-incoming channels.
*/
if (args->connect_channels) {
if (args->start.defer_target_connect &&
!strcmp(args->listen_uri, "defer")) {
in_channels = qobject_from_json(args->connect_channels,
&error_abort);
}
out_channels = qobject_from_json(args->connect_channels, &error_abort);
if (args->cpr_channel) {
QList *channels_list = qobject_to(QList, out_channels);
QObject *obj = migrate_str_to_channel(args->cpr_channel);
qlist_append(channels_list, obj);
}
channels = qobject_from_json(args->connect_channels, &error_abort);
}
if (args->result == MIG_TEST_QMP_ERROR) {
migrate_qmp_fail(from, args->connect_uri, out_channels, "{}");
migrate_qmp_fail(from, args->uri, channels, "{}");
goto finish;
}
migrate_qmp(from, to, args->connect_uri, out_channels, "{}");
if (args->start.defer_target_connect) {
qtest_connect(to);
qtest_qmp_handshake(to, NULL);
if (!strcmp(args->listen_uri, "defer")) {
migrate_incoming_qmp(to, args->connect_uri, in_channels, "{}");
}
}
migrate_qmp(from, to, args->uri, channels, "{}");
if (args->result != MIG_TEST_SUCCEED) {
bool allow_active = args->result == MIG_TEST_FAIL;
@@ -962,6 +936,14 @@ finish:
return 0;
}
void test_precopy_unix_common(MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->uri = uri;
test_precopy_common(args);
}
static void file_dirty_offset_region(void)
{
g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
@@ -999,11 +981,17 @@ void test_file_common(MigrateCommon *args, bool stop_src)
QTestState *from, *to;
void *data_hook = NULL;
bool check_offset = false;
g_autofree char *uri = NULL;
if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
if (!args->uri) {
uri = g_strdup_printf("file:%s/%s", tmpfs, FILE_TEST_FILENAME);
args->uri = uri;
}
/*
* File migration is never live. We can keep the source VM running
* during migration, but the destination will not be running
@@ -1011,7 +999,7 @@ void test_file_common(MigrateCommon *args, bool stop_src)
*/
g_assert_false(args->live);
if (g_strrstr(args->connect_uri, "offset=")) {
if (g_strrstr(args->uri, "offset=")) {
check_offset = true;
/*
* This comes before the start_hook because it's equivalent to
@@ -1034,18 +1022,18 @@ void test_file_common(MigrateCommon *args, bool stop_src)
}
if (args->result == MIG_TEST_QMP_ERROR) {
migrate_qmp_fail(from, args->connect_uri, NULL, "{}");
migrate_qmp_fail(from, args->uri, NULL, "{}");
goto finish;
}
migrate_qmp(from, to, args->connect_uri, NULL, "{}");
migrate_qmp(from, to, args->uri, NULL, "{}");
wait_for_migration_complete(from);
/*
* We need to wait for the source to finish before starting the
* destination.
*/
migrate_incoming_qmp(to, args->connect_uri, NULL, "{}");
migrate_incoming_qmp(to, args->uri, NULL, "{}");
wait_for_migration_complete(to);
if (stop_src) {
@@ -1067,19 +1055,6 @@ finish:
migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
}
void *migrate_hook_start_precopy_tcp_multifd_common(QTestState *from,
QTestState *to,
const char *method)
{
migrate_set_parameter_str(from, "multifd-compression", method);
migrate_set_parameter_str(to, "multifd-compression", method);
/* Start incoming migration from the 1st socket */
migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}");
return NULL;
}
QTestMigrationState *get_src(void)
{
return &src_state;

View File

@@ -163,16 +163,14 @@ typedef struct {
/* Optional: fine tune start parameters */
MigrateStart start;
/* Required: the URI for the dst QEMU to listen on */
const char *listen_uri;
/*
* Optional: the URI for the src QEMU to connect to
* If NULL, then it will query the dst QEMU for its actual
* listening address and use that as the connect address.
* This allows for dynamically picking a free TCP port.
* Optional: the migration URI. If NULL, the common code should
* provide a default. For socket migration, the source QEMU may
* query the dst QEMU for the listening address and use that as
* the connection address. This allows for dynamically picking a
* free TCP port.
*/
const char *connect_uri;
const char *uri;
/*
* Optional: JSON-formatted list of src QEMU URIs. If a port is
@@ -181,9 +179,6 @@ typedef struct {
*/
const char *connect_channels;
/* Optional: the cpr migration channel, in JSON or dotted keys format */
const char *cpr_channel;
/* Optional: callback to run at start to set migration parameters */
TestMigrateStartHook start_hook;
/* Optional: callback to run at finish to cleanup */
@@ -234,19 +229,16 @@ void wait_for_serial(const char *side);
void migrate_prepare_for_dirty_mem(QTestState *from);
void migrate_wait_for_dirty_mem(QTestState *from, QTestState *to);
int migrate_args(char **from, char **to, const char *uri, MigrateStart *args);
int migrate_start(QTestState **from, QTestState **to, const char *uri,
MigrateStart *args);
int migrate_args(char **from, char **to, MigrateStart *args);
int migrate_start(QTestState **from, QTestState **to, MigrateStart *args);
void migrate_end(QTestState *from, QTestState *to, bool test_dest);
void test_postcopy_common(MigrateCommon *args);
void test_postcopy_recovery_common(MigrateCommon *args,
PostcopyRecoveryFailStage fail_stage);
int test_precopy_common(MigrateCommon *args);
void test_precopy_unix_common(MigrateCommon *args);
void test_file_common(MigrateCommon *args, bool stop_src);
void *migrate_hook_start_precopy_tcp_multifd_common(QTestState *from,
QTestState *to,
const char *method);
typedef struct QTestMigrationState QTestMigrationState;
QTestMigrationState *get_src(void);

View File

@@ -28,9 +28,11 @@ static void test_baddest(char *name, MigrateCommon *args)
args->start.hide_stderr = true;
if (migrate_start(&from, &to, "tcp:127.0.0.1:0", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}");
migrate_qmp(from, to, "tcp:127.0.0.1:0", NULL, "{}");
wait_for_migration_fail(from, false);
migrate_end(from, to, false);
@@ -52,8 +54,7 @@ static void test_analyze_script(char *name, MigrateCommon *args)
return;
}
/* dummy url */
if (migrate_start(&from, &to, "tcp:127.0.0.1:0", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -69,6 +70,7 @@ static void test_analyze_script(char *name, MigrateCommon *args)
uri = g_strdup_printf("exec:cat > %s", file);
migrate_ensure_converge(from);
migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}");
migrate_qmp(from, to, uri, NULL, "{}");
wait_for_migration_complete(from);
@@ -90,40 +92,22 @@ static void test_analyze_script(char *name, MigrateCommon *args)
}
#endif
static void test_ignore_shared(char *name, MigrateCommon *args)
static void ignore_shared_assert_skipped(QTestState *from, QTestState *to,
void *data)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
args->start.mem_type = MEM_TYPE_SHMEM;
args->start.caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED] = true;
if (migrate_start(&from, &to, uri, &args->start)) {
return;
}
migrate_ensure_non_converge(from);
migrate_prepare_for_dirty_mem(from);
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
migrate_qmp(from, to, uri, NULL, "{}");
migrate_wait_for_dirty_mem(from, to);
wait_for_stop(from, get_src());
qtest_qmp_eventwait(to, "RESUME");
wait_for_serial("dest_serial");
wait_for_migration_complete(from);
/* Check whether shared RAM has been really skipped */
g_assert_cmpint(
read_ram_property_int(from, "transferred"), <, 4 * 1024 * 1024);
}
migrate_end(from, to, true);
static void test_ignore_shared(char *name, MigrateCommon *args)
{
args->live = true;
args->start.mem_type = MEM_TYPE_SHMEM;
args->start.caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED] = true;
args->end_hook = ignore_shared_assert_skipped;
test_precopy_unix_common(args);
}
static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
@@ -131,7 +115,7 @@ static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
if (migrate_start(&from, &to, "defer", args)) {
if (migrate_start(&from, &to, args)) {
return;
}
@@ -196,13 +180,15 @@ static void do_test_validate_uri_channel(MigrateCommon *args)
QTestState *from, *to;
QObject *channels;
if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
migrate_incoming_qmp(to, "tcp:127.0.0.1:0", NULL, "{}");
/*
* 'uri' and 'channels' validation is checked even before the migration
* starts.
@@ -210,7 +196,7 @@ static void do_test_validate_uri_channel(MigrateCommon *args)
channels = args->connect_channels ?
qobject_from_json(args->connect_channels, &error_abort) :
NULL;
migrate_qmp_fail(from, args->connect_uri, channels, "{}");
migrate_qmp_fail(from, args->uri, channels, "{}");
migrate_end(from, to, false);
}
@@ -248,7 +234,7 @@ static void test_validate_caps_pair(char *test_path, MigrateCommon *args)
args->start.hide_stderr = true;
args->start.only_source = true;
if (migrate_start(&from, &to, "defer", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -266,8 +252,7 @@ static void test_validate_caps_pair(char *test_path, MigrateCommon *args)
static void test_validate_uri_channels_both_set(char *name, MigrateCommon *args)
{
args->listen_uri = "defer",
args->connect_uri = "tcp:127.0.0.1:0",
args->uri = "tcp:127.0.0.1:0",
args->connect_channels = ("[ { ""'channel-type': 'main',"
" 'addr': { 'transport': 'socket',"
" 'type': 'inet',"
@@ -281,7 +266,6 @@ static void test_validate_uri_channels_both_set(char *name, MigrateCommon *args)
static void test_validate_uri_channels_none_set(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start.hide_stderr = true;
do_test_validate_uri_channel(args);

View File

@@ -37,62 +37,40 @@ static char *tmpfs;
static void test_precopy_unix_plain(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->listen_uri = uri;
args->connect_uri = uri;
/*
* The simplest use case of precopy, covering smoke tests of
* get-dirty-log dirty tracking.
*/
args->live = true;
test_precopy_common(args);
test_precopy_unix_common(args);
}
static void test_precopy_unix_suspend_live(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->listen_uri = uri;
args->connect_uri = uri;
/*
* despite being live, the test is fast because the src
* suspends immediately.
*/
args->live = true;
args->start.suspend_me = true;
test_precopy_common(args);
test_precopy_unix_common(args);
}
static void test_precopy_unix_suspend_notlive(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->listen_uri = uri;
args->connect_uri = uri;
args->start.suspend_me = true;
test_precopy_common(args);
test_precopy_unix_common(args);
}
static void test_precopy_unix_dirty_ring(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->listen_uri = uri;
args->connect_uri = uri;
/*
* Besides the precopy/unix basic test, cover dirty ring interface
* rather than get-dirty-log.
*/
args->live = true;
args->start.use_dirty_ring = true;
test_precopy_common(args);
test_precopy_unix_common(args);
}
#ifdef CONFIG_RDMA
@@ -183,8 +161,7 @@ static void __test_precopy_rdma_plain(MigrateCommon *args, bool ipv6)
**/
g_autofree char *uri = g_strdup_printf("rdma:%s:29200", buffer);
args->listen_uri = uri;
args->connect_uri = uri;
args->uri = uri;
test_precopy_common(args);
}
@@ -202,14 +179,11 @@ static void test_precopy_rdma_plain_ipv6(char *name, MigrateCommon *args)
static void test_precopy_tcp_plain(char *name, MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
test_precopy_common(args);
}
static void test_precopy_tcp_switchover_ack(char *name, MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
/*
* Source VM must be running in order to consider the switchover ACK
* when deciding to do switchover or not.
@@ -239,9 +213,6 @@ static void *migrate_hook_start_fd(QTestState *from,
" 'arguments': { 'fdname': 'fd-mig' }}");
close(pair[0]);
/* Start incoming migration from the 1st socket */
migrate_incoming_qmp(to, "fd:fd-mig", NULL, "{}");
/* Send the 2nd socket to the target */
qtest_qmp_fds_assert_success(from, &pair[1], 1,
"{ 'execute': 'getfd',"
@@ -282,8 +253,7 @@ static void migrate_hook_end_fd(QTestState *from,
static void test_precopy_fd_socket(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->connect_uri = "fd:fd-mig";
args->uri = "fd:fd-mig";
args->start_hook = migrate_hook_start_fd;
args->end_hook = migrate_hook_end_fd;
@@ -291,37 +261,14 @@ static void test_precopy_fd_socket(char *name, MigrateCommon *args)
}
#endif /* _WIN32 */
/*
* The way auto_converge works, we need to do too many passes to
* run this test. Auto_converge logic is only run once every
* three iterations, so:
*
* - 3 iterations without auto_converge enabled
* - 3 iterations with pct = 5
* - 3 iterations with pct = 30
* - 3 iterations with pct = 55
* - 3 iterations with pct = 80
* - 3 iterations with pct = 95 (max(95, 80 + 25))
*
* To make things even worse, we need to run the initial stage at
* 3MB/s so we enter autoconverge even when host is (over)loaded.
*/
static void test_auto_converge(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
int64_t percentage;
/*
* We want the test to be stable and as fast as possible.
* E.g., with 1Gb/s bandwidth migration may pass without throttling,
* so we need to decrease a bandwidth.
*/
const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
uint64_t prev_dirty_sync_cnt, dirty_sync_cnt;
int max_try_count, hit = 0;
if (migrate_start(&from, &to, uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -330,21 +277,17 @@ static void test_auto_converge(char *name, MigrateCommon *args)
migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct);
migrate_set_parameter_int(from, "max-cpu-throttle", max_pct);
/*
* Set the initial parameters so that the migration could not converge
* without throttling.
*/
migrate_ensure_non_converge(from);
/* To check remaining size after precopy */
migrate_set_capability(from, "pause-before-switchover", true);
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
migrate_incoming_qmp(to, uri, NULL, "{}");
migrate_qmp(from, to, uri, NULL, "{}");
/* Wait for throttling begins */
/* Wait until throttling begins */
percentage = 0;
do {
percentage = read_migrate_property_int(from, "cpu-throttle-percentage");
@@ -357,36 +300,8 @@ static void test_auto_converge(char *name, MigrateCommon *args)
/* The first percentage of throttling should be at least init_pct */
g_assert_cmpint(percentage, >=, init_pct);
/*
* End the loop when the dirty sync count greater than 1.
*/
while ((dirty_sync_cnt = get_migration_pass(from)) < 2) {
usleep(1000 * 1000);
}
prev_dirty_sync_cnt = dirty_sync_cnt;
/*
* The RAMBlock dirty sync count must changes in 5 seconds, here we set
* the timeout to 10 seconds to ensure it changes.
*
* Note that migrate_ensure_non_converge set the max-bandwidth to 3MB/s,
* while the qtest mem is >= 100MB, one iteration takes at least 33s (100/3)
* to complete; this ensures that the RAMBlock dirty sync occurs.
*/
max_try_count = 10;
while (--max_try_count) {
dirty_sync_cnt = get_migration_pass(from);
if (dirty_sync_cnt != prev_dirty_sync_cnt) {
hit = 1;
break;
}
prev_dirty_sync_cnt = dirty_sync_cnt;
sleep(1);
}
g_assert_cmpint(hit, ==, 1);
/* Now, when we tested that throttling works, let it converge */
/* throttling always ignores the first pass */
assert(get_migration_pass(from) == 2);
migrate_ensure_converge(from);
/*
@@ -408,18 +323,10 @@ static void test_auto_converge(char *name, MigrateCommon *args)
migrate_end(from, to, true);
}
static void *
migrate_hook_start_precopy_tcp_multifd(QTestState *from,
QTestState *to)
{
return migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
}
static void *
migrate_hook_start_precopy_tcp_multifd_zero_page_legacy(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
migrate_set_parameter_str(from, "zero-page-detection", "legacy");
return NULL;
}
@@ -428,15 +335,12 @@ static void *
migrate_hook_start_precopy_tcp_multifd_no_zero_page(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
migrate_set_parameter_str(from, "zero-page-detection", "none");
return NULL;
}
static void test_multifd_tcp_uri_none(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd;
/*
* Multifd is more complicated than most of the features, it
* directly takes guest page buffers when sending, make sure
@@ -451,7 +355,6 @@ static void test_multifd_tcp_uri_none(char *name, MigrateCommon *args)
static void test_multifd_tcp_zero_page_legacy(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_zero_page_legacy;
/*
* Multifd is more complicated than most of the features, it
@@ -467,7 +370,6 @@ static void test_multifd_tcp_zero_page_legacy(char *name, MigrateCommon *args)
static void test_multifd_tcp_no_zero_page(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd_no_zero_page;
/*
* Multifd is more complicated than most of the features, it
@@ -483,8 +385,6 @@ static void test_multifd_tcp_no_zero_page(char *name, MigrateCommon *args)
static void test_multifd_tcp_channels_none(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_precopy_tcp_multifd;
args->live = true;
args->connect_channels = ("[ { 'channel-type': 'main',"
" 'addr': { 'transport': 'socket',"
@@ -514,7 +414,7 @@ static void test_multifd_tcp_cancel(MigrateCommon *args, bool postcopy_ram)
args->start.hide_stderr = true;
if (migrate_start(&from, &to, "defer", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -560,7 +460,7 @@ static void test_multifd_tcp_cancel(MigrateCommon *args, bool postcopy_ram)
args->start.only_target = true;
if (migrate_start(&from, &to2, "defer", &args->start)) {
if (migrate_start(&from, &to2, &args->start)) {
return;
}
@@ -734,7 +634,7 @@ static void test_cancel_src_after_status(char *test_path, MigrateCommon *args)
args->start.hide_stderr = true;
if (migrate_start(&from, &to, "defer", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -1070,10 +970,10 @@ static void test_dirty_limit(char *name, MigrateCommon *args)
args->start.hide_stderr = true;
args->start.use_dirty_ring = true;
args->connect_uri = uri;
args->uri = uri;
/* Start src, dst vm */
if (migrate_start(&from, &to, "defer", &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
@@ -1081,8 +981,8 @@ static void test_dirty_limit(char *name, MigrateCommon *args)
migrate_dirty_limit_wait_showup(from, dirtylimit_period, dirtylimit_value);
/* Start migrate */
migrate_incoming_qmp(to, args->connect_uri, NULL, "{}");
migrate_qmp(from, to, args->connect_uri, NULL, "{}");
migrate_incoming_qmp(to, args->uri, NULL, "{}");
migrate_qmp(from, to, args->uri, NULL, "{}");
/* Wait for dirty limit throttle begin */
throttle_us_per_full = 0;
@@ -1114,19 +1014,19 @@ static void test_dirty_limit(char *name, MigrateCommon *args)
/* Assert dirty limit is not in service */
g_assert_cmpint(throttle_us_per_full, ==, 0);
args->listen_uri = uri;
args->connect_uri = uri;
args->uri = uri;
args->start.only_target = true;
args->start.use_dirty_ring = true;
/* Restart dst vm, src vm already show up so we needn't wait anymore */
if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
if (migrate_start(&from, &to, &args->start)) {
return;
}
/* Start migrate */
migrate_qmp(from, to, args->connect_uri, NULL, "{}");
migrate_incoming_qmp(to, args->uri, NULL, "{}");
migrate_qmp(from, to, args->uri, NULL, "{}");
/* Wait for dirty limit throttle begin */
throttle_us_per_full = 0;

View File

@@ -424,14 +424,10 @@ static void test_multifd_postcopy_preempt_recovery_tls_psk(char *name,
static void test_precopy_unix_tls_psk(char *name, MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->connect_uri = uri;
args->listen_uri = uri;
args->start_hook = migrate_hook_start_tls_psk_match;
args->end_hook = migrate_hook_end_tls_psk;
test_precopy_common(args);
test_precopy_unix_common(args);
}
#ifdef CONFIG_TASN1
@@ -440,8 +436,7 @@ static void test_precopy_unix_tls_x509_default_host(char *name,
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->connect_uri = uri;
args->listen_uri = "defer";
args->uri = uri;
args->start_hook = migrate_hook_start_tls_x509_default_host;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;
@@ -454,20 +449,15 @@ static void test_precopy_unix_tls_x509_default_host(char *name,
static void test_precopy_unix_tls_x509_override_host(char *name,
MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
args->connect_uri = uri;
args->listen_uri = uri;
args->start_hook = migrate_hook_start_tls_x509_override_host;
args->end_hook = migrate_hook_end_tls_x509;
test_precopy_common(args);
test_precopy_unix_common(args);
}
#endif /* CONFIG_TASN1 */
static void test_precopy_tcp_tls_psk_match(char *name, MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_psk_match;
args->end_hook = migrate_hook_end_tls_psk;
@@ -476,7 +466,6 @@ static void test_precopy_tcp_tls_psk_match(char *name, MigrateCommon *args)
static void test_precopy_tcp_tls_psk_mismatch(char *name, MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_psk_mismatch;
args->end_hook = migrate_hook_end_tls_psk;
args->result = MIG_TEST_FAIL;
@@ -496,7 +485,6 @@ static void *migrate_hook_start_no_tls(QTestState *from, QTestState *to)
static void test_precopy_tcp_no_tls(char *name, MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_no_tls;
/* the no_tls start hook requires no cleanup actions */
args->end_hook = NULL;
@@ -522,8 +510,6 @@ migrate_hook_start_tls_x509_no_host(QTestState *from, QTestState *to)
static void test_precopy_tcp_tls_no_hostname(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->connect_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_no_host;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;
@@ -537,7 +523,6 @@ static void test_precopy_tcp_tls_no_hostname(char *name, MigrateCommon *args)
static void test_precopy_tcp_tls_x509_default_host(char *name,
MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_default_host;
args->end_hook = migrate_hook_end_tls_x509;
@@ -547,7 +532,6 @@ static void test_precopy_tcp_tls_x509_default_host(char *name,
static void test_precopy_tcp_tls_x509_override_host(char *name,
MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_override_host;
args->end_hook = migrate_hook_end_tls_x509;
@@ -557,8 +541,6 @@ static void test_precopy_tcp_tls_x509_override_host(char *name,
static void test_precopy_tcp_tls_x509_mismatch_host(char *name,
MigrateCommon *args)
{
args->listen_uri = "defer";
args->connect_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_mismatch_host;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;
@@ -571,7 +553,6 @@ static void test_precopy_tcp_tls_x509_mismatch_host(char *name,
static void test_precopy_tcp_tls_x509_friendly_client(char *name,
MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_friendly_client;
args->end_hook = migrate_hook_end_tls_x509;
@@ -581,7 +562,6 @@ static void test_precopy_tcp_tls_x509_friendly_client(char *name,
static void test_precopy_tcp_tls_x509_hostile_client(char *name,
MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_hostile_client;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;
@@ -594,7 +574,6 @@ static void test_precopy_tcp_tls_x509_hostile_client(char *name,
static void test_precopy_tcp_tls_x509_allow_anon_client(char *name,
MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_allow_anon_client;
args->end_hook = migrate_hook_end_tls_x509;
@@ -604,7 +583,6 @@ static void test_precopy_tcp_tls_x509_allow_anon_client(char *name,
static void test_precopy_tcp_tls_x509_reject_anon_client(char *name,
MigrateCommon *args)
{
args->listen_uri = "tcp:127.0.0.1:0";
args->start_hook = migrate_hook_start_tls_x509_reject_anon_client;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;
@@ -615,68 +593,9 @@ static void test_precopy_tcp_tls_x509_reject_anon_client(char *name,
}
#endif /* CONFIG_TASN1 */
static void *
migrate_hook_start_multifd_tcp_tls_psk_match(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_psk_match(from, to);
}
static void *
migrate_hook_start_multifd_tcp_tls_psk_mismatch(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_psk_mismatch(from, to);
}
#ifdef CONFIG_TASN1
static void *
migrate_hook_start_multifd_tls_x509_default_host(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_x509_default_host(from, to);
}
static void *
migrate_hook_start_multifd_tls_x509_override_host(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_x509_override_host(from, to);
}
static void *
migrate_hook_start_multifd_tls_x509_mismatch_host(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_x509_mismatch_host(from, to);
}
static void *
migrate_hook_start_multifd_tls_x509_allow_anon_client(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_x509_allow_anon_client(from, to);
}
static void *
migrate_hook_start_multifd_tls_x509_reject_anon_client(QTestState *from,
QTestState *to)
{
migrate_hook_start_precopy_tcp_multifd_common(from, to, "none");
return migrate_hook_start_tls_x509_reject_anon_client(from, to);
}
#endif /* CONFIG_TASN1 */
static void test_multifd_tcp_tls_psk_match(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tcp_tls_psk_match;
args->start_hook = migrate_hook_start_tls_psk_match;
args->end_hook = migrate_hook_end_tls_psk;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -686,8 +605,7 @@ static void test_multifd_tcp_tls_psk_match(char *name, MigrateCommon *args)
static void test_multifd_tcp_tls_psk_mismatch(char *name, MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tcp_tls_psk_mismatch;
args->start_hook = migrate_hook_start_tls_psk_mismatch;
args->end_hook = migrate_hook_end_tls_psk;
args->result = MIG_TEST_FAIL;
@@ -700,8 +618,7 @@ static void test_multifd_tcp_tls_psk_mismatch(char *name, MigrateCommon *args)
static void test_multifd_postcopy_tcp_tls_psk_match(char *name,
MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tcp_tls_psk_match;
args->start_hook = migrate_hook_start_tls_psk_match;
args->end_hook = migrate_hook_end_tls_psk;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -714,8 +631,7 @@ static void test_multifd_postcopy_tcp_tls_psk_match(char *name,
static void test_multifd_tcp_tls_x509_default_host(char *name,
MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tls_x509_default_host;
args->start_hook = migrate_hook_start_tls_x509_default_host;
args->end_hook = migrate_hook_end_tls_x509;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -726,8 +642,7 @@ static void test_multifd_tcp_tls_x509_default_host(char *name,
static void test_multifd_tcp_tls_x509_override_host(char *name,
MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tls_x509_override_host;
args->start_hook = migrate_hook_start_tls_x509_override_host;
args->end_hook = migrate_hook_end_tls_x509;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -751,8 +666,7 @@ static void test_multifd_tcp_tls_x509_mismatch_host(char *name,
* to load migration state, and thus just aborts the migration
* without exiting.
*/
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tls_x509_mismatch_host;
args->start_hook = migrate_hook_start_tls_x509_mismatch_host;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;
@@ -765,8 +679,7 @@ static void test_multifd_tcp_tls_x509_mismatch_host(char *name,
static void test_multifd_tcp_tls_x509_allow_anon_client(char *name,
MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tls_x509_allow_anon_client;
args->start_hook = migrate_hook_start_tls_x509_allow_anon_client;
args->end_hook = migrate_hook_end_tls_x509;
args->start.caps[MIGRATION_CAPABILITY_MULTIFD] = true;
@@ -777,8 +690,7 @@ static void test_multifd_tcp_tls_x509_allow_anon_client(char *name,
static void test_multifd_tcp_tls_x509_reject_anon_client(char *name,
MigrateCommon *args)
{
args->listen_uri = "defer";
args->start_hook = migrate_hook_start_multifd_tls_x509_reject_anon_client;
args->start_hook = migrate_hook_start_tls_x509_reject_anon_client;
args->end_hook = migrate_hook_end_tls_x509;
args->result = MIG_TEST_FAIL;