Migration pull 2019-09-12

New feature:
   UUID validation check from Yury Kotov
 
 plus a bunch of fixes.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEERfXHG0oMt/uXep+pBRYzHrxb/ecFAl16TKwACgkQBRYzHrxb
 /eeeXg//X0n45bzl6yPYELiN1WQdXgLLcvJXioFNEfTCE/XbA5Dkmt0TDYHvmzzJ
 sO8YDb8mq+5d7+bedaZa53Whzn4CkMJ1bT7812sXRemx25qegdwPobGC4GOKR1Co
 2Vd4YEOQfV+OAf3tPWddKtit3mtR0FXpOMauMHbjFC/tbFV9dL6ikeTUsprNYBrY
 dbJb2I7TyIPv1OjjazmybA3zH00EUYac7Ds6S7Q+gw8K7CfTsECYCm4dfPpiQDu0
 eZiNPp+bH0YD2J47pLIfuI1bb0zUtSMRaJ4KJZtO2/dm6mDgG95R63iaSe4DQCO9
 lekX/xBOKdJgySUcsLcmMiqRLL3AB/lR8+8FsoVyrGbhcy1N54izPtupwq8tU5bZ
 +39BUbHcsPCBcXwVVHUQimoH5g/FYAii+KrjDCnSZqFvjmBGnJbcVLwO/f61Sghi
 ehqfvEiqe6SGnbsxCUcoc1Akz1P/DOYxaTGaAn1wtMrQrkRJhTbrX1pedmTViD5m
 v31J93AnROGHWi/slsxrO2jXghlo0W7a5TdKh0bul/N/IbGCTFZH1EbNXAJqkxkV
 4cKbb86vVJRozsqUCbqrs/WZgQrPXyHaXpN1bUQuA5ofUOBlynj2hrnJXMiCITvW
 MckOnKp0tgijdUefgIWmmGNCeSEPSZ25Nd6QGqPXdehoT0JBb2U=
 =W+5Q
 -----END PGP SIGNATURE-----

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

Migration pull 2019-09-12

New feature:
  UUID validation check from Yury Kotov

plus a bunch of fixes.

# gpg: Signature made Thu 12 Sep 2019 14:48:28 BST
# gpg:                using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert/tags/pull-migration-20190912a:
  migration: fix one typo in comment of function migration_total_bytes()
  migration/qemu-file: fix potential buf waste for extra buf_index adjustment
  migration/qemu-file: remove check on writev_buffer in qemu_put_compression_data
  migration: Fix postcopy bw for recovery
  tests/migration: Add a test for validate-uuid capability
  tests/libqtest: Allow setting expected exit status
  migration: Add validate-uuid capability
  qemu-file: Rework old qemu_fflush comment
  migration: register_savevm_live doesn't need dev
  hw/net/vmxnet3: Fix leftover unregister_savevm
  migration: cleanup check on ops in savevm.handlers iterations
  migration: multifd_send_thread always post p->sem_sync when error happen

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-09-13 14:37:48 +01:00
commit 85182c96de
19 changed files with 248 additions and 115 deletions

View File

@ -183,8 +183,7 @@ another to load the state back.
.. code:: c
int register_savevm_live(DeviceState *dev,
const char *idstr,
int register_savevm_live(const char *idstr,
int instance_id,
int version_id,
SaveVMHandlers *ops,

View File

@ -2242,13 +2242,10 @@ static void vmxnet3_instance_init(Object *obj)
static void vmxnet3_pci_uninit(PCIDevice *pci_dev)
{
DeviceState *dev = DEVICE(pci_dev);
VMXNET3State *s = VMXNET3(pci_dev);
VMW_CBPRN("Starting uninit...");
unregister_savevm(dev, "vmxnet3-msix", s);
vmxnet3_net_uninit(s);
vmxnet3_cleanup_msix(s);

View File

@ -3078,7 +3078,7 @@ static void spapr_machine_init(MachineState *machine)
* interface, this is a legacy from the sPAPREnvironment structure
* which predated MachineState but had a similar function */
vmstate_register(NULL, 0, &vmstate_spapr, spapr);
register_savevm_live(NULL, "spapr/htab", -1, 1,
register_savevm_live("spapr/htab", -1, 1,
&savevm_htab_handlers, spapr);
qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine),

View File

@ -389,7 +389,7 @@ static inline void s390_skeys_set_migration_enabled(Object *obj, bool value,
ss->migration_enabled = value;
if (ss->migration_enabled) {
register_savevm_live(NULL, TYPE_S390_SKEYS, 0, 1,
register_savevm_live(TYPE_S390_SKEYS, 0, 1,
&savevm_s390_storage_keys, ss);
} else {
unregister_savevm(DEVICE(ss), TYPE_S390_SKEYS, ss);

View File

@ -381,7 +381,7 @@ static void s390_stattrib_instance_init(Object *obj)
{
S390StAttribState *sas = S390_STATTRIB(obj);
register_savevm_live(NULL, TYPE_S390_STATTRIB, 0, 0,
register_savevm_live(TYPE_S390_STATTRIB, 0, 0,
&savevm_s390_stattrib_handlers, sas);
object_property_add_bool(obj, "migration-enabled",

View File

@ -101,7 +101,7 @@ static void s390_tod_realize(DeviceState *dev, Error **errp)
S390TODState *td = S390_TOD(dev);
/* Legacy migration interface */
register_savevm_live(NULL, "todclock", 0, 1, &savevm_tod, td);
register_savevm_live("todclock", 0, 1, &savevm_tod, td);
}
static void s390_tod_class_init(ObjectClass *oc, void *data)

View File

@ -68,8 +68,7 @@ typedef struct SaveVMHandlers {
int (*resume_prepare)(MigrationState *s, void *opaque);
} SaveVMHandlers;
int register_savevm_live(DeviceState *dev,
const char *idstr,
int register_savevm_live(const char *idstr,
int instance_id,
int version_id,
const SaveVMHandlers *ops,

View File

@ -733,7 +733,7 @@ void dirty_bitmap_mig_init(void)
{
QSIMPLEQ_INIT(&dirty_bitmap_mig_state.dbms_list);
register_savevm_live(NULL, "dirty-bitmap", 0, 1,
register_savevm_live("dirty-bitmap", 0, 1,
&savevm_dirty_bitmap_handlers,
&dirty_bitmap_mig_state);
}

View File

@ -1030,6 +1030,6 @@ void blk_mig_init(void)
QSIMPLEQ_INIT(&block_mig_state.blk_list);
qemu_mutex_init(&block_mig_state.lock);
register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers,
register_savevm_live("block", 0, 1, &savevm_block_handlers,
&block_mig_state);
}

View File

@ -2140,6 +2140,15 @@ bool migrate_ignore_shared(void)
return s->enabled_capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
}
bool migrate_validate_uuid(void)
{
MigrationState *s;
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
}
bool migrate_use_events(void)
{
MigrationState *s;
@ -3016,7 +3025,7 @@ static MigThrError migration_detect_error(MigrationState *s)
}
}
/* How many bytes have we transferred since the beggining of the migration */
/* How many bytes have we transferred since the beginning of the migration */
static uint64_t migration_total_bytes(MigrationState *s)
{
return qemu_ftell(s->to_dst_file) + ram_counters.multifd_bytes;
@ -3327,7 +3336,8 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
if (resume) {
/* This is a resumed migration */
rate_limit = INT64_MAX;
rate_limit = s->parameters.max_postcopy_bandwidth /
XFER_LIMIT_RATIO;
} else {
/* This is a fresh new migration */
rate_limit = s->parameters.max_bandwidth / XFER_LIMIT_RATIO;

View File

@ -290,6 +290,7 @@ bool migrate_postcopy_ram(void);
bool migrate_zero_blocks(void);
bool migrate_dirty_bitmaps(void);
bool migrate_ignore_shared(void);
bool migrate_validate_uuid(void);
bool migrate_auto_converge(void);
bool migrate_use_multifd(void);

View File

@ -201,9 +201,8 @@ static void qemu_iovec_release_ram(QEMUFile *f)
/**
* Flushes QEMUFile buffer
*
* If there is writev_buffer QEMUFileOps it uses it otherwise uses
* put_buffer ops. This will flush all pending data. If data was
* only partially flushed, it will set an error state.
* This will flush all pending data. If data was only partially flushed, it
* will set an error state.
*/
void qemu_fflush(QEMUFile *f)
{
@ -382,8 +381,16 @@ int qemu_fclose(QEMUFile *f)
return ret;
}
static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size,
bool may_free)
/*
* Add buf to iovec. Do flush if iovec is full.
*
* Return values:
* 1 iovec is full and flushed
* 0 iovec is not flushed
*
*/
static int add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size,
bool may_free)
{
/* check for adjacent buffer and coalesce them */
if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
@ -401,6 +408,19 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size,
if (f->iovcnt >= MAX_IOV_SIZE) {
qemu_fflush(f);
return 1;
}
return 0;
}
static void add_buf_to_iovec(QEMUFile *f, size_t len)
{
if (!add_to_iovec(f, f->buf + f->buf_index, len, false)) {
f->buf_index += len;
if (f->buf_index == IO_BUF_SIZE) {
qemu_fflush(f);
}
}
}
@ -430,11 +450,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size)
}
memcpy(f->buf + f->buf_index, buf, l);
f->bytes_xfer += l;
add_to_iovec(f, f->buf + f->buf_index, l, false);
f->buf_index += l;
if (f->buf_index == IO_BUF_SIZE) {
qemu_fflush(f);
}
add_buf_to_iovec(f, l);
if (qemu_file_get_error(f)) {
break;
}
@ -451,11 +467,7 @@ void qemu_put_byte(QEMUFile *f, int v)
f->buf[f->buf_index] = v;
f->bytes_xfer++;
add_to_iovec(f, f->buf + f->buf_index, 1, false);
f->buf_index++;
if (f->buf_index == IO_BUF_SIZE) {
qemu_fflush(f);
}
add_buf_to_iovec(f, 1);
}
void qemu_file_skip(QEMUFile *f, int size)
@ -761,13 +773,7 @@ ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream,
}
qemu_put_be32(f, blen);
if (f->ops->writev_buffer) {
add_to_iovec(f, f->buf + f->buf_index, blen, false);
}
f->buf_index += blen;
if (f->buf_index == IO_BUF_SIZE) {
qemu_fflush(f);
}
add_buf_to_iovec(f, blen);
return blen + sizeof(int32_t);
}

View File

@ -1112,6 +1112,7 @@ static void *multifd_send_thread(void *opaque)
rcu_register_thread();
if (multifd_send_initial_packet(p, &local_err) < 0) {
ret = -1;
goto out;
}
/* initial packet */
@ -1179,9 +1180,7 @@ out:
* who pay attention to me.
*/
if (ret != 0) {
if (flags & MULTIFD_FLAG_SYNC) {
qemu_sem_post(&p->sem_sync);
}
qemu_sem_post(&p->sem_sync);
qemu_sem_post(&multifd_send_state->channels_ready);
}
@ -4676,5 +4675,5 @@ static SaveVMHandlers savevm_ram_handlers = {
void ram_mig_init(void)
{
qemu_mutex_init(&XBZRLE.lock);
register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, &ram_state);
register_savevm_live("ram", 0, 4, &savevm_ram_handlers, &ram_state);
}

View File

@ -256,6 +256,7 @@ typedef struct SaveState {
uint32_t target_page_bits;
uint32_t caps_count;
MigrationCapability *capabilities;
QemuUUID uuid;
} SaveState;
static SaveState savevm_state = {
@ -307,6 +308,7 @@ static int configuration_pre_save(void *opaque)
state->capabilities[j++] = i;
}
}
state->uuid = qemu_uuid;
return 0;
}
@ -464,6 +466,48 @@ static const VMStateDescription vmstate_capabilites = {
}
};
static bool vmstate_uuid_needed(void *opaque)
{
return qemu_uuid_set && migrate_validate_uuid();
}
static int vmstate_uuid_post_load(void *opaque, int version_id)
{
SaveState *state = opaque;
char uuid_src[UUID_FMT_LEN + 1];
char uuid_dst[UUID_FMT_LEN + 1];
if (!qemu_uuid_set) {
/*
* It's warning because user might not know UUID in some cases,
* e.g. load an old snapshot
*/
qemu_uuid_unparse(&state->uuid, uuid_src);
warn_report("UUID is received %s, but local uuid isn't set",
uuid_src);
return 0;
}
if (!qemu_uuid_is_equal(&state->uuid, &qemu_uuid)) {
qemu_uuid_unparse(&state->uuid, uuid_src);
qemu_uuid_unparse(&qemu_uuid, uuid_dst);
error_report("UUID received is %s and local is %s", uuid_src, uuid_dst);
return -EINVAL;
}
return 0;
}
static const VMStateDescription vmstate_uuid = {
.name = "configuration/uuid",
.version_id = 1,
.minimum_version_id = 1,
.needed = vmstate_uuid_needed,
.post_load = vmstate_uuid_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT8_ARRAY_V(uuid.data, SaveState, sizeof(QemuUUID), 1),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_configuration = {
.name = "configuration",
.version_id = 1,
@ -478,6 +522,7 @@ static const VMStateDescription vmstate_configuration = {
.subsections = (const VMStateDescription*[]) {
&vmstate_target_page_bits,
&vmstate_capabilites,
&vmstate_uuid,
NULL
}
};
@ -684,8 +729,7 @@ static void savevm_state_handler_insert(SaveStateEntry *nse)
of the system, so instance_id should be removed/replaced.
Meanwhile pass -1 as instance_id if you do not already have a clearly
distinguishing id for all instances of your device class. */
int register_savevm_live(DeviceState *dev,
const char *idstr,
int register_savevm_live(const char *idstr,
int instance_id,
int version_id,
const SaveVMHandlers *ops,
@ -704,26 +748,6 @@ int register_savevm_live(DeviceState *dev,
se->is_ram = 1;
}
if (dev) {
char *id = qdev_get_dev_path(dev);
if (id) {
if (snprintf(se->idstr, sizeof(se->idstr), "%s/", id) >=
sizeof(se->idstr)) {
error_report("Path too long for VMState (%s)", id);
g_free(id);
g_free(se);
return -1;
}
g_free(id);
se->compat = g_new0(CompatEntry, 1);
pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
se->compat->instance_id = instance_id == -1 ?
calculate_compat_instance_id(idstr) : instance_id;
instance_id = -1;
}
}
pstrcat(se->idstr, sizeof(se->idstr), idstr);
if (instance_id == -1) {
@ -1100,7 +1124,7 @@ void qemu_savevm_state_setup(QEMUFile *f)
if (!se->ops || !se->ops->save_setup) {
continue;
}
if (se->ops && se->ops->is_active) {
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@ -1131,7 +1155,7 @@ int qemu_savevm_state_resume_prepare(MigrationState *s)
if (!se->ops || !se->ops->resume_prepare) {
continue;
}
if (se->ops && se->ops->is_active) {
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@ -1227,7 +1251,7 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f)
if (!se->ops || !se->ops->save_live_complete_postcopy) {
continue;
}
if (se->ops && se->ops->is_active) {
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@ -1264,7 +1288,7 @@ int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
continue;
}
if (se->ops && se->ops->is_active) {
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@ -1413,7 +1437,7 @@ void qemu_savevm_state_pending(QEMUFile *f, uint64_t threshold_size,
if (!se->ops || !se->ops->save_live_pending) {
continue;
}
if (se->ops && se->ops->is_active) {
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
@ -2334,7 +2358,7 @@ static int qemu_loadvm_state_setup(QEMUFile *f)
if (!se->ops || !se->ops->load_setup) {
continue;
}
if (se->ops && se->ops->is_active) {
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}

View File

@ -576,7 +576,7 @@ static int net_slirp_init(NetClientState *peer, const char *model,
* specific version?
*/
g_assert(slirp_state_version() == 4);
register_savevm_live(NULL, "slirp", 0, slirp_state_version(),
register_savevm_live("slirp", 0, slirp_state_version(),
&savevm_slirp_state, s->slirp);
s->poll_notifier.notify = net_slirp_poll_notify;

View File

@ -415,6 +415,9 @@
#
# @x-ignore-shared: If enabled, QEMU will not migrate shared memory (since 4.0)
#
# @validate-uuid: Send the UUID of the source to allow the destination
# to ensure it is the same. (since 4.2)
#
# Since: 1.2
##
{ 'enum': 'MigrationCapability',
@ -422,7 +425,7 @@
'compress', 'events', 'postcopy-ram', 'x-colo', 'release-ram',
'block', 'return-path', 'pause-before-switchover', 'multifd',
'dirty-bitmaps', 'postcopy-blocktime', 'late-block-activate',
'x-ignore-shared' ] }
'x-ignore-shared', 'validate-uuid' ] }
##
# @MigrationCapabilityStatus:

View File

@ -41,6 +41,7 @@ struct QTestState
int qmp_fd;
pid_t qemu_pid; /* our child QEMU process */
int wstatus;
int expected_status;
bool big_endian;
bool irq_level[MAX_IRQ];
GString *rx;
@ -111,6 +112,11 @@ bool qtest_probe_child(QTestState *s)
return false;
}
void qtest_set_expected_status(QTestState *s, int status)
{
s->expected_status = status;
}
static void kill_qemu(QTestState *s)
{
pid_t pid = s->qemu_pid;
@ -124,24 +130,23 @@ static void kill_qemu(QTestState *s)
}
/*
* We expect qemu to exit with status 0; anything else is
* Check whether qemu exited with expected exit status; anything else is
* fishy and should be logged with as much detail as possible.
*/
wstatus = s->wstatus;
if (wstatus) {
if (WIFEXITED(wstatus)) {
fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
"process but encountered exit status %d\n",
__FILE__, __LINE__, WEXITSTATUS(wstatus));
} else if (WIFSIGNALED(wstatus)) {
int sig = WTERMSIG(wstatus);
const char *signame = strsignal(sig) ?: "unknown ???";
const char *dump = WCOREDUMP(wstatus) ? " (core dumped)" : "";
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != s->expected_status) {
fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
"process but encountered exit status %d (expected %d)\n",
__FILE__, __LINE__, WEXITSTATUS(wstatus), s->expected_status);
abort();
} else if (WIFSIGNALED(wstatus)) {
int sig = WTERMSIG(wstatus);
const char *signame = strsignal(sig) ?: "unknown ???";
const char *dump = WCOREDUMP(wstatus) ? " (core dumped)" : "";
fprintf(stderr, "%s:%d: kill_qemu() detected QEMU death "
"from signal %d (%s)%s\n",
__FILE__, __LINE__, sig, signame, dump);
}
fprintf(stderr, "%s:%d: kill_qemu() detected QEMU death "
"from signal %d (%s)%s\n",
__FILE__, __LINE__, sig, signame, dump);
abort();
}
}
@ -246,6 +251,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
g_test_message("starting QEMU: %s", command);
s->wstatus = 0;
s->expected_status = 0;
s->qemu_pid = fork();
if (s->qemu_pid == 0) {
setenv("QEMU_AUDIO_DRV", "none", true);

View File

@ -708,4 +708,13 @@ void qmp_assert_error_class(QDict *rsp, const char *class);
*/
bool qtest_probe_child(QTestState *s);
/**
* qtest_set_expected_status:
* @s: QTestState instance to operate on.
* @status: an expected exit status.
*
* Set expected exit status of the child.
*/
void qtest_set_expected_status(QTestState *s, int status);
#endif

View File

@ -512,7 +512,8 @@ static void migrate_postcopy_start(QTestState *from, QTestState *to)
static int test_migrate_start(QTestState **from, QTestState **to,
const char *uri, bool hide_stderr,
bool use_shmem)
bool use_shmem, const char *opts_src,
const char *opts_dst)
{
gchar *cmd_src, *cmd_dst;
char *bootpath = NULL;
@ -521,6 +522,9 @@ static int test_migrate_start(QTestState **from, QTestState **to,
const char *arch = qtest_get_arch();
const char *accel = "kvm:tcg";
opts_src = opts_src ? opts_src : "";
opts_dst = opts_dst ? opts_dst : "";
if (use_shmem) {
if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
g_test_skip("/dev/shm is not supported");
@ -539,16 +543,16 @@ static int test_migrate_start(QTestState **from, QTestState **to,
cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
" -name source,debug-threads=on"
" -serial file:%s/src_serial"
" -drive file=%s,format=raw %s",
" -drive file=%s,format=raw %s %s",
accel, tmpfs, bootpath,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_src);
cmd_dst = g_strdup_printf("-machine accel=%s -m 150M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial"
" -drive file=%s,format=raw"
" -incoming %s %s",
" -incoming %s %s %s",
accel, tmpfs, bootpath, uri,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_dst);
start_address = X86_TEST_MEM_START;
end_address = X86_TEST_MEM_END;
} else if (g_str_equal(arch, "s390x")) {
@ -556,15 +560,15 @@ static int test_migrate_start(QTestState **from, QTestState **to,
extra_opts = use_shmem ? get_shmem_opts("128M", shmem_path) : NULL;
cmd_src = g_strdup_printf("-machine accel=%s -m 128M"
" -name source,debug-threads=on"
" -serial file:%s/src_serial -bios %s %s",
" -serial file:%s/src_serial -bios %s %s %s",
accel, tmpfs, bootpath,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_src);
cmd_dst = g_strdup_printf("-machine accel=%s -m 128M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial -bios %s"
" -incoming %s %s",
" -incoming %s %s %s",
accel, tmpfs, bootpath, uri,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_dst);
start_address = S390_TEST_MEM_START;
end_address = S390_TEST_MEM_END;
} else if (strcmp(arch, "ppc64") == 0) {
@ -575,14 +579,15 @@ static int test_migrate_start(QTestState **from, QTestState **to,
" -prom-env 'use-nvramrc?=true' -prom-env "
"'nvramrc=hex .\" _\" begin %x %x "
"do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
"until' %s", accel, tmpfs, end_address,
start_address, extra_opts ? extra_opts : "");
"until' %s %s", accel, tmpfs, end_address,
start_address, extra_opts ? extra_opts : "",
opts_src);
cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial"
" -incoming %s %s",
" -incoming %s %s %s",
accel, tmpfs, uri,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_dst);
start_address = PPC_TEST_MEM_START;
end_address = PPC_TEST_MEM_END;
@ -592,16 +597,16 @@ static int test_migrate_start(QTestState **from, QTestState **to,
cmd_src = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmsource,debug-threads=on -cpu max "
"-m 150M -serial file:%s/src_serial "
"-kernel %s %s",
"-kernel %s %s %s",
accel, tmpfs, bootpath,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_src);
cmd_dst = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmdest,debug-threads=on -cpu max "
"-m 150M -serial file:%s/dest_serial "
"-kernel %s "
"-incoming %s %s",
"-incoming %s %s %s",
accel, tmpfs, bootpath, uri,
extra_opts ? extra_opts : "");
extra_opts ? extra_opts : "", opts_dst);
start_address = ARM_TEST_MEM_START;
end_address = ARM_TEST_MEM_END;
@ -731,7 +736,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
if (test_migrate_start(&from, &to, uri, hide_error, false)) {
if (test_migrate_start(&from, &to, uri, hide_error, false, NULL, NULL)) {
return -1;
}
@ -841,20 +846,16 @@ static void test_postcopy_recovery(void)
migrate_postcopy_complete(from, to);
}
static void test_baddest(void)
static void wait_for_migration_fail(QTestState *from, bool allow_active)
{
QTestState *from, *to;
QDict *rsp_return;
char *status;
bool failed;
if (test_migrate_start(&from, &to, "tcp:0:0", true, false)) {
return;
}
migrate(from, "tcp:0:0", "{}");
do {
status = migrate_query_status(from);
g_assert(!strcmp(status, "setup") || !(strcmp(status, "failed")));
g_assert(!strcmp(status, "setup") || !strcmp(status, "failed") ||
(allow_active && !strcmp(status, "active")));
failed = !strcmp(status, "failed");
g_free(status);
} while (!failed);
@ -864,7 +865,17 @@ static void test_baddest(void)
g_assert(qdict_haskey(rsp_return, "running"));
g_assert(qdict_get_bool(rsp_return, "running"));
qobject_unref(rsp_return);
}
static void test_baddest(void)
{
QTestState *from, *to;
if (test_migrate_start(&from, &to, "tcp:0:0", true, false, NULL, NULL)) {
return;
}
migrate(from, "tcp:0:0", "{}");
wait_for_migration_fail(from, false);
test_migrate_end(from, to, false);
}
@ -873,7 +884,7 @@ static void test_precopy_unix(void)
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
if (test_migrate_start(&from, &to, uri, false, false)) {
if (test_migrate_start(&from, &to, uri, false, false, NULL, NULL)) {
return;
}
@ -916,7 +927,7 @@ static void test_ignore_shared(void)
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
if (test_migrate_start(&from, &to, uri, false, true)) {
if (test_migrate_start(&from, &to, uri, false, true, NULL, NULL)) {
return;
}
@ -951,7 +962,7 @@ static void test_xbzrle(const char *uri)
{
QTestState *from, *to;
if (test_migrate_start(&from, &to, uri, false, false)) {
if (test_migrate_start(&from, &to, uri, false, false, NULL, NULL)) {
return;
}
@ -1003,7 +1014,8 @@ static void test_precopy_tcp(void)
char *uri;
QTestState *from, *to;
if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", false, false)) {
if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", false, false,
NULL, NULL)) {
return;
}
@ -1049,7 +1061,7 @@ static void test_migrate_fd_proto(void)
QDict *rsp;
const char *error_desc;
if (test_migrate_start(&from, &to, "defer", false, false)) {
if (test_migrate_start(&from, &to, "defer", false, false, NULL, NULL)) {
return;
}
@ -1125,6 +1137,68 @@ static void test_migrate_fd_proto(void)
test_migrate_end(from, to, true);
}
static void do_test_validate_uuid(const char *uuid_arg_src,
const char *uuid_arg_dst,
bool should_fail, bool hide_stderr)
{
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
if (test_migrate_start(&from, &to, uri, hide_stderr, false,
uuid_arg_src, uuid_arg_dst)) {
return;
}
/*
* UUID validation is at the begin of migration. So, the main process of
* migration is not interesting for us here. Thus, set huge downtime for
* very fast migration.
*/
migrate_set_parameter_int(from, "downtime-limit", 1000000);
migrate_set_capability(from, "validate-uuid", true);
/* Wait for the first serial output from the source */
wait_for_serial("src_serial");
migrate(from, uri, "{}");
if (should_fail) {
qtest_set_expected_status(to, 1);
wait_for_migration_fail(from, true);
} else {
wait_for_migration_complete(from);
}
test_migrate_end(from, to, false);
g_free(uri);
}
static void test_validate_uuid(void)
{
do_test_validate_uuid("-uuid 11111111-1111-1111-1111-111111111111",
"-uuid 11111111-1111-1111-1111-111111111111",
false, false);
}
static void test_validate_uuid_error(void)
{
do_test_validate_uuid("-uuid 11111111-1111-1111-1111-111111111111",
"-uuid 22222222-2222-2222-2222-222222222222",
true, true);
}
static void test_validate_uuid_src_not_set(void)
{
do_test_validate_uuid(NULL, "-uuid 11111111-1111-1111-1111-111111111111",
false, true);
}
static void test_validate_uuid_dst_not_set(void)
{
do_test_validate_uuid("-uuid 11111111-1111-1111-1111-111111111111", NULL,
false, true);
}
int main(int argc, char **argv)
{
char template[] = "/tmp/migration-test-XXXXXX";
@ -1180,6 +1254,12 @@ int main(int argc, char **argv)
/* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */
qtest_add_func("/migration/xbzrle/unix", test_xbzrle_unix);
qtest_add_func("/migration/fd_proto", test_migrate_fd_proto);
qtest_add_func("/migration/validate_uuid", test_validate_uuid);
qtest_add_func("/migration/validate_uuid_error", test_validate_uuid_error);
qtest_add_func("/migration/validate_uuid_src_not_set",
test_validate_uuid_src_not_set);
qtest_add_func("/migration/validate_uuid_dst_not_set",
test_validate_uuid_dst_not_set);
ret = g_test_run();