You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qemu/tests/qtest/migration/file-tests.c

339 lines
10 KiB
C

/*
* QTest testcases for migration to file
*
* Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
* based on the vhost-user-test.c that is:
* Copyright (c) 2014 Virtual Open Systems Sarl.
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "libqtest.h"
#include "migration/framework.h"
#include "migration/migration-qmp.h"
#include "migration/migration-util.h"
#include "qapi/qmp/qlist.h"
static char *tmpfs;
static void test_precopy_file(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
};
test_file_common(&args, true);
}
#ifndef _WIN32
static void fdset_add_fds(QTestState *qts, const char *file, int flags,
int num_fds, bool direct_io)
{
for (int i = 0; i < num_fds; i++) {
int fd;
#ifdef O_DIRECT
/* only secondary channels can use direct-io */
if (direct_io && i != 0) {
flags |= O_DIRECT;
}
#endif
fd = open(file, flags, 0660);
assert(fd != -1);
qtest_qmp_fds_assert_success(qts, &fd, 1, "{'execute': 'add-fd', "
"'arguments': {'fdset-id': 1}}");
close(fd);
}
}
static void *migrate_hook_start_file_offset_fdset(QTestState *from,
QTestState *to)
{
g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
fdset_add_fds(from, file, O_WRONLY, 1, false);
fdset_add_fds(to, file, O_RDONLY, 1, false);
return NULL;
}
static void test_precopy_file_offset_fdset(void)
{
g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
FILE_TEST_OFFSET);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_file_offset_fdset,
};
test_file_common(&args, false);
}
#endif
static void test_precopy_file_offset(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=%d", tmpfs,
FILE_TEST_FILENAME,
FILE_TEST_OFFSET);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
};
test_file_common(&args, false);
}
static void test_precopy_file_offset_bad(void)
{
/* using a value not supported by qemu_strtosz() */
g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=0x20M",
tmpfs, FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.result = MIG_TEST_QMP_ERROR,
};
test_file_common(&args, false);
}
static void *migrate_hook_start_mapped_ram(QTestState *from,
QTestState *to)
{
migrate_set_capability(from, "mapped-ram", true);
migrate_set_capability(to, "mapped-ram", true);
return NULL;
}
static void test_precopy_file_mapped_ram_live(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_mapped_ram,
};
test_file_common(&args, false);
}
static void test_precopy_file_mapped_ram(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_mapped_ram,
};
test_file_common(&args, true);
}
static void *migrate_hook_start_multifd_mapped_ram(QTestState *from,
QTestState *to)
{
migrate_hook_start_mapped_ram(from, to);
migrate_set_parameter_int(from, "multifd-channels", 4);
migrate_set_parameter_int(to, "multifd-channels", 4);
migrate_set_capability(from, "multifd", true);
migrate_set_capability(to, "multifd", true);
return NULL;
}
static void test_multifd_file_mapped_ram_live(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_multifd_mapped_ram,
};
test_file_common(&args, false);
}
static void test_multifd_file_mapped_ram(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_multifd_mapped_ram,
};
test_file_common(&args, true);
}
static void *migrate_hook_start_multifd_mapped_ram_dio(QTestState *from,
QTestState *to)
{
migrate_hook_start_multifd_mapped_ram(from, to);
migrate_set_parameter_bool(from, "direct-io", true);
migrate_set_parameter_bool(to, "direct-io", true);
return NULL;
}
static void test_multifd_file_mapped_ram_dio(void)
{
g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
FILE_TEST_FILENAME);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_multifd_mapped_ram_dio,
};
if (!probe_o_direct_support(tmpfs)) {
g_test_skip("Filesystem does not support O_DIRECT");
return;
}
test_file_common(&args, true);
}
#ifndef _WIN32
static void migrate_hook_end_multifd_mapped_ram_fdset(QTestState *from,
QTestState *to,
void *opaque)
{
QDict *resp;
QList *fdsets;
/*
* Remove the fdsets after migration, otherwise a second migration
* would fail due fdset reuse.
*/
qtest_qmp_assert_success(from, "{'execute': 'remove-fd', "
"'arguments': { 'fdset-id': 1}}");
/*
* Make sure no fdsets are left after migration, otherwise a
* second migration would fail due fdset reuse.
*/
resp = qtest_qmp(from, "{'execute': 'query-fdsets', "
"'arguments': {}}");
g_assert(qdict_haskey(resp, "return"));
fdsets = qdict_get_qlist(resp, "return");
g_assert(fdsets && qlist_empty(fdsets));
qobject_unref(resp);
}
static void *migrate_hook_start_multifd_mapped_ram_fdset_dio(QTestState *from,
QTestState *to)
{
g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
fdset_add_fds(from, file, O_WRONLY, 2, true);
fdset_add_fds(to, file, O_RDONLY, 2, true);
migrate_hook_start_multifd_mapped_ram(from, to);
migrate_set_parameter_bool(from, "direct-io", true);
migrate_set_parameter_bool(to, "direct-io", true);
return NULL;
}
static void *migrate_hook_start_multifd_mapped_ram_fdset(QTestState *from,
QTestState *to)
{
g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
fdset_add_fds(from, file, O_WRONLY, 2, false);
fdset_add_fds(to, file, O_RDONLY, 2, false);
migrate_hook_start_multifd_mapped_ram(from, to);
return NULL;
}
static void test_multifd_file_mapped_ram_fdset(void)
{
g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
FILE_TEST_OFFSET);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_multifd_mapped_ram_fdset,
.end_hook = migrate_hook_end_multifd_mapped_ram_fdset,
};
test_file_common(&args, true);
}
static void test_multifd_file_mapped_ram_fdset_dio(void)
{
g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
FILE_TEST_OFFSET);
MigrateCommon args = {
.connect_uri = uri,
.listen_uri = "defer",
.start_hook = migrate_hook_start_multifd_mapped_ram_fdset_dio,
.end_hook = migrate_hook_end_multifd_mapped_ram_fdset,
};
if (!probe_o_direct_support(tmpfs)) {
g_test_skip("Filesystem does not support O_DIRECT");
return;
}
test_file_common(&args, true);
}
#endif /* !_WIN32 */
void migration_test_add_file(MigrationTestEnv *env)
{
tmpfs = env->tmpfs;
migration_test_add("/migration/precopy/file",
test_precopy_file);
migration_test_add("/migration/precopy/file/offset",
test_precopy_file_offset);
#ifndef _WIN32
migration_test_add("/migration/precopy/file/offset/fdset",
test_precopy_file_offset_fdset);
#endif
migration_test_add("/migration/precopy/file/offset/bad",
test_precopy_file_offset_bad);
migration_test_add("/migration/precopy/file/mapped-ram",
test_precopy_file_mapped_ram);
migration_test_add("/migration/precopy/file/mapped-ram/live",
test_precopy_file_mapped_ram_live);
migration_test_add("/migration/multifd/file/mapped-ram",
test_multifd_file_mapped_ram);
migration_test_add("/migration/multifd/file/mapped-ram/live",
test_multifd_file_mapped_ram_live);
migration_test_add("/migration/multifd/file/mapped-ram/dio",
test_multifd_file_mapped_ram_dio);
#ifndef _WIN32
migration_test_add("/migration/multifd/file/mapped-ram/fdset",
test_multifd_file_mapped_ram_fdset);
migration_test_add("/migration/multifd/file/mapped-ram/fdset/dio",
test_multifd_file_mapped_ram_fdset_dio);
#endif
}