|
@@ -27,6 +27,10 @@
|
|
|
#include "migration-helpers.h"
|
|
|
#include "tests/migration/migration-test.h"
|
|
|
|
|
|
+#if defined(__linux__)
|
|
|
+#include "linux/kvm.h"
|
|
|
+#endif
|
|
|
+
|
|
|
/* TODO actually test the results and get rid of this */
|
|
|
#define qtest_qmp_discard_response(...) qobject_unref(qtest_qmp(__VA_ARGS__))
|
|
|
|
|
@@ -467,6 +471,8 @@ typedef struct {
|
|
|
bool use_shmem;
|
|
|
/* only launch the target process */
|
|
|
bool only_target;
|
|
|
+ /* Use dirty ring if true; dirty logging otherwise */
|
|
|
+ bool use_dirty_ring;
|
|
|
char *opts_source;
|
|
|
char *opts_target;
|
|
|
} MigrateStart;
|
|
@@ -573,11 +579,13 @@ static int test_migrate_start(QTestState **from, QTestState **to,
|
|
|
shmem_opts = g_strdup("");
|
|
|
}
|
|
|
|
|
|
- cmd_source = g_strdup_printf("-accel kvm -accel tcg%s%s "
|
|
|
+ cmd_source = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
|
|
|
"-name source,debug-threads=on "
|
|
|
"-m %s "
|
|
|
"-serial file:%s/src_serial "
|
|
|
"%s %s %s %s",
|
|
|
+ args->use_dirty_ring ?
|
|
|
+ ",dirty-ring-size=4096" : "",
|
|
|
machine_opts ? " -machine " : "",
|
|
|
machine_opts ? machine_opts : "",
|
|
|
memory_size, tmpfs,
|
|
@@ -587,12 +595,14 @@ static int test_migrate_start(QTestState **from, QTestState **to,
|
|
|
*from = qtest_init(cmd_source);
|
|
|
}
|
|
|
|
|
|
- cmd_target = g_strdup_printf("-accel kvm -accel tcg%s%s "
|
|
|
+ cmd_target = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
|
|
|
"-name target,debug-threads=on "
|
|
|
"-m %s "
|
|
|
"-serial file:%s/dest_serial "
|
|
|
"-incoming %s "
|
|
|
"%s %s %s %s",
|
|
|
+ args->use_dirty_ring ?
|
|
|
+ ",dirty-ring-size=4096" : "",
|
|
|
machine_opts ? " -machine " : "",
|
|
|
machine_opts ? machine_opts : "",
|
|
|
memory_size, tmpfs, uri,
|
|
@@ -785,12 +795,14 @@ static void test_baddest(void)
|
|
|
test_migrate_end(from, to, false);
|
|
|
}
|
|
|
|
|
|
-static void test_precopy_unix(void)
|
|
|
+static void test_precopy_unix_common(bool dirty_ring)
|
|
|
{
|
|
|
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
|
|
|
MigrateStart *args = migrate_start_new();
|
|
|
QTestState *from, *to;
|
|
|
|
|
|
+ args->use_dirty_ring = dirty_ring;
|
|
|
+
|
|
|
if (test_migrate_start(&from, &to, uri, args)) {
|
|
|
return;
|
|
|
}
|
|
@@ -825,6 +837,18 @@ static void test_precopy_unix(void)
|
|
|
test_migrate_end(from, to, true);
|
|
|
}
|
|
|
|
|
|
+static void test_precopy_unix(void)
|
|
|
+{
|
|
|
+ /* Using default dirty logging */
|
|
|
+ test_precopy_unix_common(false);
|
|
|
+}
|
|
|
+
|
|
|
+static void test_precopy_unix_dirty_ring(void)
|
|
|
+{
|
|
|
+ /* Using dirty ring tracking */
|
|
|
+ test_precopy_unix_common(true);
|
|
|
+}
|
|
|
+
|
|
|
#if 0
|
|
|
/* Currently upset on aarch64 TCG */
|
|
|
static void test_ignore_shared(void)
|
|
@@ -1369,6 +1393,29 @@ static void test_multifd_tcp_cancel(void)
|
|
|
test_migrate_end(from, to2, true);
|
|
|
}
|
|
|
|
|
|
+static bool kvm_dirty_ring_supported(void)
|
|
|
+{
|
|
|
+#if defined(__linux__)
|
|
|
+ int ret, kvm_fd = open("/dev/kvm", O_RDONLY);
|
|
|
+
|
|
|
+ if (kvm_fd < 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
|
|
|
+ close(kvm_fd);
|
|
|
+
|
|
|
+ /* We test with 4096 slots */
|
|
|
+ if (ret < 4096) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+#else
|
|
|
+ return false;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
int main(int argc, char **argv)
|
|
|
{
|
|
|
char template[] = "/tmp/migration-test-XXXXXX";
|
|
@@ -1439,6 +1486,11 @@ int main(int argc, char **argv)
|
|
|
qtest_add_func("/migration/multifd/tcp/zstd", test_multifd_tcp_zstd);
|
|
|
#endif
|
|
|
|
|
|
+ if (kvm_dirty_ring_supported()) {
|
|
|
+ qtest_add_func("/migration/dirty_ring",
|
|
|
+ test_precopy_unix_dirty_ring);
|
|
|
+ }
|
|
|
+
|
|
|
ret = g_test_run();
|
|
|
|
|
|
g_assert_cmpint(ret, ==, 0);
|