xref: /qemu/tests/qtest/migration/migration-util.c (revision d128c341a744ba3e92fa67d9f1b02dd9a7bd68b9)
1 /*
2  * QTest migration utilities
3  *
4  * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
5  *   based on the vhost-user-test.c that is:
6  *      Copyright (c) 2014 Virtual Open Systems Sarl.
7  *
8  * This work is licensed under the terms of the GNU GPL, version 2 or later.
9  * See the COPYING file in the top-level directory.
10  *
11  */
12 
13 #include "qemu/osdep.h"
14 #include "qemu/ctype.h"
15 #include "qapi/qapi-visit-sockets.h"
16 #include "qapi/qobject-input-visitor.h"
17 #include "qapi/error.h"
18 #include "qobject/qlist.h"
19 #include "qemu/cutils.h"
20 #include "qemu/memalign.h"
21 
22 #include "migration/bootfile.h"
23 #include "migration/migration-util.h"
24 
25 #if defined(__linux__)
26 #include <sys/ioctl.h>
27 #include <sys/syscall.h>
28 #endif
29 
30 /* for uffd_version_check() */
31 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
32 #include <sys/eventfd.h>
33 #include "qemu/userfaultfd.h"
34 #endif
35 
36 /* For dirty ring test; so far only x86_64 is supported */
37 #if defined(__linux__) && defined(HOST_X86_64)
38 #include "linux/kvm.h"
39 #endif
40 
41 
42 static char *SocketAddress_to_str(SocketAddress *addr)
43 {
44     switch (addr->type) {
45     case SOCKET_ADDRESS_TYPE_INET:
46         return g_strdup_printf("tcp:%s:%s",
47                                addr->u.inet.host,
48                                addr->u.inet.port);
49     case SOCKET_ADDRESS_TYPE_UNIX:
50         return g_strdup_printf("unix:%s",
51                                addr->u.q_unix.path);
52     case SOCKET_ADDRESS_TYPE_FD:
53         return g_strdup_printf("fd:%s", addr->u.fd.str);
54     case SOCKET_ADDRESS_TYPE_VSOCK:
55         return g_strdup_printf("vsock:%s:%s",
56                                addr->u.vsock.cid,
57                                addr->u.vsock.port);
58     default:
59         return g_strdup("unknown address type");
60     }
61 }
62 
63 static QDict *SocketAddress_to_qdict(SocketAddress *addr)
64 {
65     QDict *dict = qdict_new();
66 
67     switch (addr->type) {
68     case SOCKET_ADDRESS_TYPE_INET:
69         qdict_put_str(dict, "type", "inet");
70         qdict_put_str(dict, "host", addr->u.inet.host);
71         qdict_put_str(dict, "port", addr->u.inet.port);
72         break;
73     case SOCKET_ADDRESS_TYPE_UNIX:
74         qdict_put_str(dict, "type", "unix");
75         qdict_put_str(dict, "path", addr->u.q_unix.path);
76         break;
77     case SOCKET_ADDRESS_TYPE_FD:
78         qdict_put_str(dict, "type", "fd");
79         qdict_put_str(dict, "str", addr->u.fd.str);
80         break;
81     case SOCKET_ADDRESS_TYPE_VSOCK:
82         qdict_put_str(dict, "type", "vsock");
83         qdict_put_str(dict, "cid", addr->u.vsock.cid);
84         qdict_put_str(dict, "port", addr->u.vsock.port);
85         break;
86     default:
87         g_assert_not_reached();
88     }
89 
90     return dict;
91 }
92 
93 static SocketAddressList *migrate_get_socket_address(QTestState *who)
94 {
95     QDict *rsp;
96     SocketAddressList *addrs;
97     Visitor *iv = NULL;
98     QObject *object;
99 
100     rsp = migrate_query(who);
101     object = qdict_get(rsp, "socket-address");
102 
103     iv = qobject_input_visitor_new(object);
104     visit_type_SocketAddressList(iv, NULL, &addrs, &error_abort);
105     visit_free(iv);
106 
107     qobject_unref(rsp);
108     return addrs;
109 }
110 
111 char *migrate_get_connect_uri(QTestState *who)
112 {
113     SocketAddressList *addrs;
114     char *connect_uri;
115 
116     addrs = migrate_get_socket_address(who);
117     connect_uri = SocketAddress_to_str(addrs->value);
118 
119     qapi_free_SocketAddressList(addrs);
120     return connect_uri;
121 }
122 
123 static QDict *
124 migrate_get_connect_qdict(QTestState *who)
125 {
126     SocketAddressList *addrs;
127     QDict *connect_qdict;
128 
129     addrs = migrate_get_socket_address(who);
130     connect_qdict = SocketAddress_to_qdict(addrs->value);
131 
132     qapi_free_SocketAddressList(addrs);
133     return connect_qdict;
134 }
135 
136 void migrate_set_ports(QTestState *to, QList *channel_list)
137 {
138     g_autoptr(QDict) addr = NULL;
139     QListEntry *entry;
140     const char *addr_port = NULL;
141 
142     QLIST_FOREACH_ENTRY(channel_list, entry) {
143         QDict *channel = qobject_to(QDict, qlist_entry_obj(entry));
144         QDict *addrdict = qdict_get_qdict(channel, "addr");
145 
146         if (!qdict_haskey(addrdict, "port") ||
147             strcmp(qdict_get_str(addrdict, "port"), "0")) {
148             continue;
149         }
150 
151         /*
152          * Fetch addr only if needed, so tests that are not yet connected to
153          * the monitor do not query it.  Such tests cannot use port=0.
154          */
155         if (!addr) {
156             addr = migrate_get_connect_qdict(to);
157         }
158 
159         if (qdict_haskey(addr, "port")) {
160             addr_port = qdict_get_str(addr, "port");
161             qdict_put_str(addrdict, "port", addr_port);
162         }
163     }
164 }
165 
166 bool migrate_watch_for_events(QTestState *who, const char *name,
167                               QDict *event, void *opaque)
168 {
169     QTestMigrationState *state = opaque;
170 
171     if (g_str_equal(name, "STOP")) {
172         state->stop_seen = true;
173         return true;
174     } else if (g_str_equal(name, "SUSPEND")) {
175         state->suspend_seen = true;
176         return true;
177     } else if (g_str_equal(name, "RESUME")) {
178         state->resume_seen = true;
179         return true;
180     }
181 
182     return false;
183 }
184 
185 char *find_common_machine_version(const char *mtype, const char *var1,
186                                   const char *var2)
187 {
188     g_autofree char *type1 = qtest_resolve_machine_alias(var1, mtype);
189     g_autofree char *type2 = qtest_resolve_machine_alias(var2, mtype);
190 
191     g_assert(type1 && type2);
192 
193     if (g_str_equal(type1, type2)) {
194         /* either can be used */
195         return g_strdup(type1);
196     }
197 
198     if (qtest_has_machine_with_env(var2, type1)) {
199         return g_strdup(type1);
200     }
201 
202     if (qtest_has_machine_with_env(var1, type2)) {
203         return g_strdup(type2);
204     }
205 
206     g_test_message("No common machine version for machine type '%s' between "
207                    "binaries %s and %s", mtype, getenv(var1), getenv(var2));
208     g_assert_not_reached();
209 }
210 
211 char *resolve_machine_version(const char *alias, const char *var1,
212                               const char *var2)
213 {
214     const char *mname = g_getenv("QTEST_QEMU_MACHINE_TYPE");
215     g_autofree char *machine_name = NULL;
216 
217     if (mname) {
218         const char *dash = strrchr(mname, '-');
219         const char *dot = strrchr(mname, '.');
220 
221         machine_name = g_strdup(mname);
222 
223         if (dash && dot) {
224             assert(qtest_has_machine(machine_name));
225             return g_steal_pointer(&machine_name);
226         }
227         /* else: probably an alias, let it be resolved below */
228     } else {
229         /* use the hardcoded alias */
230         machine_name = g_strdup(alias);
231     }
232 
233     return find_common_machine_version(machine_name, var1, var2);
234 }
235 
236 typedef struct {
237     char *name;
238     void (*func)(void);
239 } MigrationTest;
240 
241 static void migration_test_destroy(gpointer data)
242 {
243     MigrationTest *test = (MigrationTest *)data;
244 
245     g_free(test->name);
246     g_free(test);
247 }
248 
249 static void migration_test_wrapper(const void *data)
250 {
251     MigrationTest *test = (MigrationTest *)data;
252 
253     g_test_message("Running /%s%s", qtest_get_arch(), test->name);
254     test->func();
255 }
256 
257 void migration_test_add(const char *path, void (*fn)(void))
258 {
259     MigrationTest *test = g_new0(MigrationTest, 1);
260 
261     test->func = fn;
262     test->name = g_strdup(path);
263 
264     qtest_add_data_func_full(path, test, migration_test_wrapper,
265                              migration_test_destroy);
266 }
267 
268 #ifdef O_DIRECT
269 /*
270  * Probe for O_DIRECT support on the filesystem. Since this is used
271  * for tests, be conservative, if anything fails, assume it's
272  * unsupported.
273  */
274 bool probe_o_direct_support(const char *tmpfs)
275 {
276     g_autofree char *filename = g_strdup_printf("%s/probe-o-direct", tmpfs);
277     int fd, flags = O_CREAT | O_RDWR | O_TRUNC | O_DIRECT;
278     void *buf;
279     ssize_t ret, len;
280     uint64_t offset;
281 
282     fd = open(filename, flags, 0660);
283     if (fd < 0) {
284         unlink(filename);
285         return false;
286     }
287 
288     /*
289      * Using 1MB alignment as conservative choice to satisfy any
290      * plausible architecture default page size, and/or filesystem
291      * alignment restrictions.
292      */
293     len = 0x100000;
294     offset = 0x100000;
295 
296     buf = qemu_try_memalign(len, len);
297     g_assert(buf);
298     memset(buf, 0, len);
299 
300     ret = pwrite(fd, buf, len, offset);
301     unlink(filename);
302     g_free(buf);
303 
304     if (ret < 0) {
305         return false;
306     }
307 
308     return true;
309 }
310 #endif
311 
312 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
313 bool ufd_version_check(bool *uffd_feature_thread_id)
314 {
315     struct uffdio_api api_struct;
316     uint64_t ioctl_mask;
317 
318     int ufd = uffd_open(O_CLOEXEC);
319 
320     if (ufd == -1) {
321         g_test_message("Skipping test: userfaultfd not available");
322         return false;
323     }
324 
325     api_struct.api = UFFD_API;
326     api_struct.features = 0;
327     if (ioctl(ufd, UFFDIO_API, &api_struct)) {
328         g_test_message("Skipping test: UFFDIO_API failed");
329         return false;
330     }
331 
332     if (uffd_feature_thread_id) {
333         *uffd_feature_thread_id = api_struct.features & UFFD_FEATURE_THREAD_ID;
334     }
335 
336     ioctl_mask = (1ULL << _UFFDIO_REGISTER |
337                   1ULL << _UFFDIO_UNREGISTER);
338     if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
339         g_test_message("Skipping test: Missing userfault feature");
340         return false;
341     }
342 
343     return true;
344 }
345 #else
346 bool ufd_version_check(bool *uffd_feature_thread_id)
347 {
348     g_test_message("Skipping test: Userfault not available (builtdtime)");
349     return false;
350 }
351 #endif
352 
353 bool kvm_dirty_ring_supported(void)
354 {
355 #if defined(__linux__) && defined(HOST_X86_64)
356     int ret, kvm_fd = open("/dev/kvm", O_RDONLY);
357 
358     if (kvm_fd < 0) {
359         return false;
360     }
361 
362     ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
363     close(kvm_fd);
364 
365     /* We test with 4096 slots */
366     if (ret < 4096) {
367         return false;
368     }
369 
370     return true;
371 #else
372     return false;
373 #endif
374 }
375