mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
116
migration/cpr.c
116
migration/cpr.c
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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).+)))?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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] =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user