xref: /qemu/tests/qtest/migration/file-tests.c (revision b6f568262b48ca0cb3dc018909908017551b5679)
1 /*
2  * QTest testcases for migration to file
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 "libqtest.h"
15 #include "migration/framework.h"
16 #include "migration/migration-qmp.h"
17 #include "migration/migration-util.h"
18 #include "qobject/qlist.h"
19 
20 
21 static char *tmpfs;
22 
test_precopy_file(void)23 static void test_precopy_file(void)
24 {
25     g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
26                                            FILE_TEST_FILENAME);
27     MigrateCommon args = {
28         .connect_uri = uri,
29         .listen_uri = "defer",
30     };
31 
32     test_file_common(&args, true);
33 }
34 
35 #ifndef _WIN32
fdset_add_fds(QTestState * qts,const char * file,int flags,int num_fds,bool direct_io)36 static void fdset_add_fds(QTestState *qts, const char *file, int flags,
37                           int num_fds, bool direct_io)
38 {
39     for (int i = 0; i < num_fds; i++) {
40         int fd;
41 
42 #ifdef O_DIRECT
43         /* only secondary channels can use direct-io */
44         if (direct_io && i != 0) {
45             flags |= O_DIRECT;
46         }
47 #endif
48 
49         fd = open(file, flags, 0660);
50         assert(fd != -1);
51 
52         qtest_qmp_fds_assert_success(qts, &fd, 1, "{'execute': 'add-fd', "
53                                      "'arguments': {'fdset-id': 1}}");
54         close(fd);
55     }
56 }
57 
migrate_hook_start_file_offset_fdset(QTestState * from,QTestState * to)58 static void *migrate_hook_start_file_offset_fdset(QTestState *from,
59                                                   QTestState *to)
60 {
61     g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
62 
63     fdset_add_fds(from, file, O_WRONLY, 1, false);
64     fdset_add_fds(to, file, O_RDONLY, 1, false);
65 
66     return NULL;
67 }
68 
test_precopy_file_offset_fdset(void)69 static void test_precopy_file_offset_fdset(void)
70 {
71     g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
72                                            FILE_TEST_OFFSET);
73     MigrateCommon args = {
74         .connect_uri = uri,
75         .listen_uri = "defer",
76         .start_hook = migrate_hook_start_file_offset_fdset,
77     };
78 
79     test_file_common(&args, false);
80 }
81 #endif
82 
test_precopy_file_offset(void)83 static void test_precopy_file_offset(void)
84 {
85     g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=%d", tmpfs,
86                                            FILE_TEST_FILENAME,
87                                            FILE_TEST_OFFSET);
88     MigrateCommon args = {
89         .connect_uri = uri,
90         .listen_uri = "defer",
91     };
92 
93     test_file_common(&args, false);
94 }
95 
test_precopy_file_offset_bad(void)96 static void test_precopy_file_offset_bad(void)
97 {
98     /* using a value not supported by qemu_strtosz() */
99     g_autofree char *uri = g_strdup_printf("file:%s/%s,offset=0x20M",
100                                            tmpfs, FILE_TEST_FILENAME);
101     MigrateCommon args = {
102         .connect_uri = uri,
103         .listen_uri = "defer",
104         .result = MIG_TEST_QMP_ERROR,
105     };
106 
107     test_file_common(&args, false);
108 }
109 
test_precopy_file_mapped_ram_live(void)110 static void test_precopy_file_mapped_ram_live(void)
111 {
112     g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
113                                            FILE_TEST_FILENAME);
114     MigrateCommon args = {
115         .connect_uri = uri,
116         .listen_uri = "defer",
117         .start = {
118             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
119         },
120     };
121 
122     test_file_common(&args, false);
123 }
124 
test_precopy_file_mapped_ram(void)125 static void test_precopy_file_mapped_ram(void)
126 {
127     g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
128                                            FILE_TEST_FILENAME);
129     MigrateCommon args = {
130         .connect_uri = uri,
131         .listen_uri = "defer",
132         .start = {
133             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
134         },
135     };
136 
137     test_file_common(&args, true);
138 }
139 
test_multifd_file_mapped_ram_live(void)140 static void test_multifd_file_mapped_ram_live(void)
141 {
142     g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
143                                            FILE_TEST_FILENAME);
144     MigrateCommon args = {
145         .connect_uri = uri,
146         .listen_uri = "defer",
147         .start = {
148             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
149             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
150         },
151     };
152 
153     test_file_common(&args, false);
154 }
155 
test_multifd_file_mapped_ram(void)156 static void test_multifd_file_mapped_ram(void)
157 {
158     g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
159                                            FILE_TEST_FILENAME);
160     MigrateCommon args = {
161         .connect_uri = uri,
162         .listen_uri = "defer",
163         .start = {
164             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
165             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
166         },
167     };
168 
169     test_file_common(&args, true);
170 }
171 
migrate_hook_start_multifd_mapped_ram_dio(QTestState * from,QTestState * to)172 static void *migrate_hook_start_multifd_mapped_ram_dio(QTestState *from,
173                                                        QTestState *to)
174 {
175     migrate_set_parameter_bool(from, "direct-io", true);
176     migrate_set_parameter_bool(to, "direct-io", true);
177 
178     return NULL;
179 }
180 
test_multifd_file_mapped_ram_dio(void)181 static void test_multifd_file_mapped_ram_dio(void)
182 {
183     g_autofree char *uri = g_strdup_printf("file:%s/%s", tmpfs,
184                                            FILE_TEST_FILENAME);
185     MigrateCommon args = {
186         .connect_uri = uri,
187         .listen_uri = "defer",
188         .start_hook = migrate_hook_start_multifd_mapped_ram_dio,
189         .start = {
190             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
191             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
192         },
193     };
194 
195     if (!probe_o_direct_support(tmpfs)) {
196         g_test_skip("Filesystem does not support O_DIRECT");
197         return;
198     }
199 
200     test_file_common(&args, true);
201 }
202 
203 #ifndef _WIN32
migrate_hook_end_multifd_mapped_ram_fdset(QTestState * from,QTestState * to,void * opaque)204 static void migrate_hook_end_multifd_mapped_ram_fdset(QTestState *from,
205                                                       QTestState *to,
206                                                       void *opaque)
207 {
208     QDict *resp;
209     QList *fdsets;
210 
211     /*
212      * Remove the fdsets after migration, otherwise a second migration
213      * would fail due fdset reuse.
214      */
215     qtest_qmp_assert_success(from, "{'execute': 'remove-fd', "
216                              "'arguments': { 'fdset-id': 1}}");
217 
218     /*
219      * Make sure no fdsets are left after migration, otherwise a
220      * second migration would fail due fdset reuse.
221      */
222     resp = qtest_qmp(from, "{'execute': 'query-fdsets', "
223                      "'arguments': {}}");
224     g_assert(qdict_haskey(resp, "return"));
225     fdsets = qdict_get_qlist(resp, "return");
226     g_assert(fdsets && qlist_empty(fdsets));
227     qobject_unref(resp);
228 }
229 
migrate_hook_start_multifd_mapped_ram_fdset_dio(QTestState * from,QTestState * to)230 static void *migrate_hook_start_multifd_mapped_ram_fdset_dio(QTestState *from,
231                                                              QTestState *to)
232 {
233     g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
234 
235     fdset_add_fds(from, file, O_WRONLY, 2, true);
236     fdset_add_fds(to, file, O_RDONLY, 2, true);
237 
238     migrate_set_parameter_bool(from, "direct-io", true);
239     migrate_set_parameter_bool(to, "direct-io", true);
240 
241     return NULL;
242 }
243 
migrate_hook_start_multifd_mapped_ram_fdset(QTestState * from,QTestState * to)244 static void *migrate_hook_start_multifd_mapped_ram_fdset(QTestState *from,
245                                                          QTestState *to)
246 {
247     g_autofree char *file = g_strdup_printf("%s/%s", tmpfs, FILE_TEST_FILENAME);
248 
249     fdset_add_fds(from, file, O_WRONLY, 2, false);
250     fdset_add_fds(to, file, O_RDONLY, 2, false);
251 
252     return NULL;
253 }
254 
test_multifd_file_mapped_ram_fdset(void)255 static void test_multifd_file_mapped_ram_fdset(void)
256 {
257     g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
258                                            FILE_TEST_OFFSET);
259     MigrateCommon args = {
260         .connect_uri = uri,
261         .listen_uri = "defer",
262         .start_hook = migrate_hook_start_multifd_mapped_ram_fdset,
263         .end_hook = migrate_hook_end_multifd_mapped_ram_fdset,
264         .start = {
265             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
266             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
267         },
268     };
269 
270     test_file_common(&args, true);
271 }
272 
test_multifd_file_mapped_ram_fdset_dio(void)273 static void test_multifd_file_mapped_ram_fdset_dio(void)
274 {
275     g_autofree char *uri = g_strdup_printf("file:/dev/fdset/1,offset=%d",
276                                            FILE_TEST_OFFSET);
277     MigrateCommon args = {
278         .connect_uri = uri,
279         .listen_uri = "defer",
280         .start_hook = migrate_hook_start_multifd_mapped_ram_fdset_dio,
281         .end_hook = migrate_hook_end_multifd_mapped_ram_fdset,
282         .start = {
283             .caps[MIGRATION_CAPABILITY_MAPPED_RAM] = true,
284             .caps[MIGRATION_CAPABILITY_MULTIFD] = true,
285         },
286     };
287 
288     if (!probe_o_direct_support(tmpfs)) {
289         g_test_skip("Filesystem does not support O_DIRECT");
290         return;
291     }
292 
293     test_file_common(&args, true);
294 }
295 #endif /* !_WIN32 */
296 
migration_test_add_file_smoke(MigrationTestEnv * env)297 static void migration_test_add_file_smoke(MigrationTestEnv *env)
298 {
299     migration_test_add("/migration/precopy/file",
300                        test_precopy_file);
301 
302     migration_test_add("/migration/multifd/file/mapped-ram/dio",
303                        test_multifd_file_mapped_ram_dio);
304 }
305 
migration_test_add_file(MigrationTestEnv * env)306 void migration_test_add_file(MigrationTestEnv *env)
307 {
308     tmpfs = env->tmpfs;
309 
310     migration_test_add_file_smoke(env);
311 
312     if (!env->full_set) {
313         return;
314     }
315 
316     migration_test_add("/migration/precopy/file/offset",
317                        test_precopy_file_offset);
318 #ifndef _WIN32
319     migration_test_add("/migration/precopy/file/offset/fdset",
320                        test_precopy_file_offset_fdset);
321 #endif
322     migration_test_add("/migration/precopy/file/offset/bad",
323                        test_precopy_file_offset_bad);
324 
325     migration_test_add("/migration/precopy/file/mapped-ram",
326                        test_precopy_file_mapped_ram);
327     migration_test_add("/migration/precopy/file/mapped-ram/live",
328                        test_precopy_file_mapped_ram_live);
329 
330     migration_test_add("/migration/multifd/file/mapped-ram",
331                        test_multifd_file_mapped_ram);
332     migration_test_add("/migration/multifd/file/mapped-ram/live",
333                        test_multifd_file_mapped_ram_live);
334 
335 #ifndef _WIN32
336     migration_test_add("/migration/multifd/file/mapped-ram/fdset",
337                        test_multifd_file_mapped_ram_fdset);
338     migration_test_add("/migration/multifd/file/mapped-ram/fdset/dio",
339                        test_multifd_file_mapped_ram_fdset_dio);
340 #endif
341 }
342