2 * Block replication tests
4 * Copyright (c) 2016 FUJITSU LIMITED
5 * Author: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
7 * This work is licensed under the terms of the GNU GPL, version 2 or
8 * later. See the COPYING file in the top-level directory.
11 #include "qemu/osdep.h"
13 #include "qapi/error.h"
14 #include "qapi/qmp/qdict.h"
15 #include "replication.h"
16 #include "block/block_int.h"
17 #include "sysemu/block-backend.h"
19 #define IMG_SIZE (64 * 1024 * 1024)
22 #define P_ID "primary-id"
23 static char p_local_disk
[] = "/tmp/p_local_disk.XXXXXX";
26 #define S_ID "secondary-id"
27 #define S_LOCAL_DISK_ID "secondary-local-disk-id"
28 static char s_local_disk
[] = "/tmp/s_local_disk.XXXXXX";
29 static char s_active_disk
[] = "/tmp/s_active_disk.XXXXXX";
30 static char s_hidden_disk
[] = "/tmp/s_hidden_disk.XXXXXX";
32 /* FIXME: steal from blockdev.c */
33 QemuOptsList qemu_drive_opts
= {
35 .head
= QTAILQ_HEAD_INITIALIZER(qemu_drive_opts
.head
),
41 #define NOT_DONE 0x7fffffff
43 static void blk_rw_done(void *opaque
, int ret
)
48 static void test_blk_read(BlockBackend
*blk
, long pattern
,
49 int64_t pattern_offset
, int64_t pattern_count
,
50 int64_t offset
, int64_t count
,
53 void *pattern_buf
= NULL
;
56 int async_ret
= NOT_DONE
;
59 cmp_buf
= g_malloc(pattern_count
);
60 memset(cmp_buf
, pattern
, pattern_count
);
63 pattern_buf
= g_malloc(count
);
65 memset(pattern_buf
, pattern
, count
);
67 memset(pattern_buf
, 0x00, count
);
70 qemu_iovec_init(&qiov
, 1);
71 qemu_iovec_add(&qiov
, pattern_buf
, count
);
73 blk_aio_preadv(blk
, offset
, &qiov
, 0, blk_rw_done
, &async_ret
);
74 while (async_ret
== NOT_DONE
) {
75 main_loop_wait(false);
79 g_assert(async_ret
!= 0);
81 g_assert(async_ret
== 0);
83 g_assert(memcmp(pattern_buf
+ pattern_offset
,
84 cmp_buf
, pattern_count
) <= 0);
90 qemu_iovec_destroy(&qiov
);
93 static void test_blk_write(BlockBackend
*blk
, long pattern
, int64_t offset
,
94 int64_t count
, bool expect_failed
)
96 void *pattern_buf
= NULL
;
98 int async_ret
= NOT_DONE
;
100 pattern_buf
= g_malloc(count
);
102 memset(pattern_buf
, pattern
, count
);
104 memset(pattern_buf
, 0x00, count
);
107 qemu_iovec_init(&qiov
, 1);
108 qemu_iovec_add(&qiov
, pattern_buf
, count
);
110 blk_aio_pwritev(blk
, offset
, &qiov
, 0, blk_rw_done
, &async_ret
);
111 while (async_ret
== NOT_DONE
) {
112 main_loop_wait(false);
116 g_assert(async_ret
!= 0);
118 g_assert(async_ret
== 0);
122 qemu_iovec_destroy(&qiov
);
126 * Create a uniquely-named empty temporary file.
128 static void make_temp(char *template)
132 fd
= mkstemp(template);
137 static void prepare_imgs(void)
139 Error
*local_err
= NULL
;
141 make_temp(p_local_disk
);
142 make_temp(s_local_disk
);
143 make_temp(s_active_disk
);
144 make_temp(s_hidden_disk
);
147 bdrv_img_create(p_local_disk
, "qcow2", NULL
, NULL
, NULL
, IMG_SIZE
,
148 BDRV_O_RDWR
, true, &local_err
);
149 g_assert(!local_err
);
152 bdrv_img_create(s_local_disk
, "qcow2", NULL
, NULL
, NULL
, IMG_SIZE
,
153 BDRV_O_RDWR
, true, &local_err
);
154 g_assert(!local_err
);
155 bdrv_img_create(s_active_disk
, "qcow2", NULL
, NULL
, NULL
, IMG_SIZE
,
156 BDRV_O_RDWR
, true, &local_err
);
157 g_assert(!local_err
);
158 bdrv_img_create(s_hidden_disk
, "qcow2", NULL
, NULL
, NULL
, IMG_SIZE
,
159 BDRV_O_RDWR
, true, &local_err
);
160 g_assert(!local_err
);
163 static void cleanup_imgs(void)
166 unlink(p_local_disk
);
169 unlink(s_local_disk
);
170 unlink(s_active_disk
);
171 unlink(s_hidden_disk
);
174 static BlockBackend
*start_primary(void)
179 Error
*local_err
= NULL
;
182 cmdline
= g_strdup_printf("driver=replication,mode=primary,node-name=xxx,"
183 "file.driver=qcow2,file.file.filename=%s,"
184 "file.file.locking=off"
186 opts
= qemu_opts_parse_noisily(&qemu_drive_opts
, cmdline
, false);
189 qdict
= qemu_opts_to_qdict(opts
, NULL
);
190 qdict_set_default_str(qdict
, BDRV_OPT_CACHE_DIRECT
, "off");
191 qdict_set_default_str(qdict
, BDRV_OPT_CACHE_NO_FLUSH
, "off");
193 blk
= blk_new_open(NULL
, NULL
, qdict
, BDRV_O_RDWR
, &local_err
);
195 g_assert(!local_err
);
197 monitor_add_blk(blk
, P_ID
, &local_err
);
198 g_assert(!local_err
);
205 static void teardown_primary(void)
210 blk
= blk_by_name(P_ID
);
213 monitor_remove_blk(blk
);
217 static void test_primary_read(void)
221 blk
= start_primary();
223 /* read from 0 to IMG_SIZE */
224 test_blk_read(blk
, 0, 0, IMG_SIZE
, 0, IMG_SIZE
, true);
229 static void test_primary_write(void)
233 blk
= start_primary();
235 /* write from 0 to IMG_SIZE */
236 test_blk_write(blk
, 0, 0, IMG_SIZE
, true);
241 static void test_primary_start(void)
243 BlockBackend
*blk
= NULL
;
244 Error
*local_err
= NULL
;
246 blk
= start_primary();
248 replication_start_all(REPLICATION_MODE_PRIMARY
, &local_err
);
249 g_assert(!local_err
);
251 /* read from 0 to IMG_SIZE */
252 test_blk_read(blk
, 0, 0, IMG_SIZE
, 0, IMG_SIZE
, true);
254 /* write 0x22 from 0 to IMG_SIZE */
255 test_blk_write(blk
, 0x22, 0, IMG_SIZE
, false);
260 static void test_primary_stop(void)
262 Error
*local_err
= NULL
;
263 bool failover
= true;
267 replication_start_all(REPLICATION_MODE_PRIMARY
, &local_err
);
268 g_assert(!local_err
);
270 replication_stop_all(failover
, &local_err
);
271 g_assert(!local_err
);
276 static void test_primary_do_checkpoint(void)
278 Error
*local_err
= NULL
;
282 replication_start_all(REPLICATION_MODE_PRIMARY
, &local_err
);
283 g_assert(!local_err
);
285 replication_do_checkpoint_all(&local_err
);
286 g_assert(!local_err
);
291 static void test_primary_get_error_all(void)
293 Error
*local_err
= NULL
;
297 replication_start_all(REPLICATION_MODE_PRIMARY
, &local_err
);
298 g_assert(!local_err
);
300 replication_get_error_all(&local_err
);
301 g_assert(!local_err
);
306 static BlockBackend
*start_secondary(void)
312 Error
*local_err
= NULL
;
314 /* add s_local_disk and forge S_LOCAL_DISK_ID */
315 cmdline
= g_strdup_printf("file.filename=%s,driver=qcow2,"
318 opts
= qemu_opts_parse_noisily(&qemu_drive_opts
, cmdline
, false);
321 qdict
= qemu_opts_to_qdict(opts
, NULL
);
322 qdict_set_default_str(qdict
, BDRV_OPT_CACHE_DIRECT
, "off");
323 qdict_set_default_str(qdict
, BDRV_OPT_CACHE_NO_FLUSH
, "off");
325 blk
= blk_new_open(NULL
, NULL
, qdict
, BDRV_O_RDWR
, &local_err
);
327 monitor_add_blk(blk
, S_LOCAL_DISK_ID
, &local_err
);
328 g_assert(!local_err
);
330 /* format s_local_disk with pattern "0x11" */
331 test_blk_write(blk
, 0x11, 0, IMG_SIZE
, false);
335 /* add S_(ACTIVE/HIDDEN)_DISK and forge S_ID */
336 cmdline
= g_strdup_printf("driver=replication,mode=secondary,top-id=%s,"
337 "file.driver=qcow2,file.file.filename=%s,"
338 "file.file.locking=off,"
339 "file.backing.driver=qcow2,"
340 "file.backing.file.filename=%s,"
341 "file.backing.file.locking=off,"
342 "file.backing.backing=%s"
343 , S_ID
, s_active_disk
, s_hidden_disk
345 opts
= qemu_opts_parse_noisily(&qemu_drive_opts
, cmdline
, false);
348 qdict
= qemu_opts_to_qdict(opts
, NULL
);
349 qdict_set_default_str(qdict
, BDRV_OPT_CACHE_DIRECT
, "off");
350 qdict_set_default_str(qdict
, BDRV_OPT_CACHE_NO_FLUSH
, "off");
352 blk
= blk_new_open(NULL
, NULL
, qdict
, BDRV_O_RDWR
, &local_err
);
354 monitor_add_blk(blk
, S_ID
, &local_err
);
355 g_assert(!local_err
);
362 static void teardown_secondary(void)
364 /* only need to destroy two BBs */
367 /* remove S_LOCAL_DISK_ID */
368 blk
= blk_by_name(S_LOCAL_DISK_ID
);
371 monitor_remove_blk(blk
);
375 blk
= blk_by_name(S_ID
);
378 monitor_remove_blk(blk
);
382 static void test_secondary_read(void)
386 blk
= start_secondary();
388 /* read from 0 to IMG_SIZE */
389 test_blk_read(blk
, 0, 0, IMG_SIZE
, 0, IMG_SIZE
, true);
391 teardown_secondary();
394 static void test_secondary_write(void)
398 blk
= start_secondary();
400 /* write from 0 to IMG_SIZE */
401 test_blk_write(blk
, 0, 0, IMG_SIZE
, true);
403 teardown_secondary();
406 static void test_secondary_start(void)
408 BlockBackend
*top_blk
, *local_blk
;
409 Error
*local_err
= NULL
;
410 bool failover
= true;
412 top_blk
= start_secondary();
413 replication_start_all(REPLICATION_MODE_SECONDARY
, &local_err
);
414 g_assert(!local_err
);
416 /* read from s_local_disk (0, IMG_SIZE) */
417 test_blk_read(top_blk
, 0x11, 0, IMG_SIZE
, 0, IMG_SIZE
, false);
419 /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
420 local_blk
= blk_by_name(S_LOCAL_DISK_ID
);
421 test_blk_write(local_blk
, 0x22, IMG_SIZE
/ 2, IMG_SIZE
/ 2, false);
423 /* replication will backup s_local_disk to s_hidden_disk */
424 test_blk_read(top_blk
, 0x11, IMG_SIZE
/ 2,
425 IMG_SIZE
/ 2, 0, IMG_SIZE
, false);
427 /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
428 test_blk_write(top_blk
, 0x33, 0, IMG_SIZE
/ 2, false);
430 /* read from s_active_disk (0, IMG_SIZE/2) */
431 test_blk_read(top_blk
, 0x33, 0, IMG_SIZE
/ 2,
432 0, IMG_SIZE
/ 2, false);
435 replication_stop_all(failover
, &local_err
);
436 g_assert(!local_err
);
438 teardown_secondary();
442 static void test_secondary_stop(void)
444 BlockBackend
*top_blk
, *local_blk
;
445 Error
*local_err
= NULL
;
446 bool failover
= true;
448 top_blk
= start_secondary();
449 replication_start_all(REPLICATION_MODE_SECONDARY
, &local_err
);
450 g_assert(!local_err
);
452 /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
453 local_blk
= blk_by_name(S_LOCAL_DISK_ID
);
454 test_blk_write(local_blk
, 0x22, IMG_SIZE
/ 2, IMG_SIZE
/ 2, false);
456 /* replication will backup s_local_disk to s_hidden_disk */
457 test_blk_read(top_blk
, 0x11, IMG_SIZE
/ 2,
458 IMG_SIZE
/ 2, 0, IMG_SIZE
, false);
460 /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
461 test_blk_write(top_blk
, 0x33, 0, IMG_SIZE
/ 2, false);
463 /* do active commit */
464 replication_stop_all(failover
, &local_err
);
465 g_assert(!local_err
);
467 /* read from s_local_disk (0, IMG_SIZE / 2) */
468 test_blk_read(top_blk
, 0x33, 0, IMG_SIZE
/ 2,
469 0, IMG_SIZE
/ 2, false);
472 /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
473 test_blk_read(top_blk
, 0x22, IMG_SIZE
/ 2,
474 IMG_SIZE
/ 2, 0, IMG_SIZE
, false);
476 teardown_secondary();
479 static void test_secondary_do_checkpoint(void)
481 BlockBackend
*top_blk
, *local_blk
;
482 Error
*local_err
= NULL
;
483 bool failover
= true;
485 top_blk
= start_secondary();
486 replication_start_all(REPLICATION_MODE_SECONDARY
, &local_err
);
487 g_assert(!local_err
);
489 /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
490 local_blk
= blk_by_name(S_LOCAL_DISK_ID
);
491 test_blk_write(local_blk
, 0x22, IMG_SIZE
/ 2,
492 IMG_SIZE
/ 2, false);
494 /* replication will backup s_local_disk to s_hidden_disk */
495 test_blk_read(top_blk
, 0x11, IMG_SIZE
/ 2,
496 IMG_SIZE
/ 2, 0, IMG_SIZE
, false);
498 replication_do_checkpoint_all(&local_err
);
499 g_assert(!local_err
);
501 /* after checkpoint, read pattern 0x22 from s_local_disk */
502 test_blk_read(top_blk
, 0x22, IMG_SIZE
/ 2,
503 IMG_SIZE
/ 2, 0, IMG_SIZE
, false);
506 replication_stop_all(failover
, &local_err
);
507 g_assert(!local_err
);
509 teardown_secondary();
512 static void test_secondary_get_error_all(void)
514 Error
*local_err
= NULL
;
515 bool failover
= true;
518 replication_start_all(REPLICATION_MODE_SECONDARY
, &local_err
);
519 g_assert(!local_err
);
521 replication_get_error_all(&local_err
);
522 g_assert(!local_err
);
525 replication_stop_all(failover
, &local_err
);
526 g_assert(!local_err
);
528 teardown_secondary();
531 static void sigabrt_handler(int signo
)
536 static void setup_sigabrt_handler(void)
538 struct sigaction sigact
;
540 sigact
= (struct sigaction
) {
541 .sa_handler
= sigabrt_handler
,
542 .sa_flags
= SA_RESETHAND
,
544 sigemptyset(&sigact
.sa_mask
);
545 sigaction(SIGABRT
, &sigact
, NULL
);
548 int main(int argc
, char **argv
)
551 qemu_init_main_loop(&error_fatal
);
554 g_test_init(&argc
, &argv
, NULL
);
555 setup_sigabrt_handler();
560 g_test_add_func("/replication/primary/read", test_primary_read
);
561 g_test_add_func("/replication/primary/write", test_primary_write
);
562 g_test_add_func("/replication/primary/start", test_primary_start
);
563 g_test_add_func("/replication/primary/stop", test_primary_stop
);
564 g_test_add_func("/replication/primary/do_checkpoint",
565 test_primary_do_checkpoint
);
566 g_test_add_func("/replication/primary/get_error_all",
567 test_primary_get_error_all
);
570 g_test_add_func("/replication/secondary/read", test_secondary_read
);
571 g_test_add_func("/replication/secondary/write", test_secondary_write
);
572 g_test_add_func("/replication/secondary/start", test_secondary_start
);
573 g_test_add_func("/replication/secondary/stop", test_secondary_stop
);
574 g_test_add_func("/replication/secondary/do_checkpoint",
575 test_secondary_do_checkpoint
);
576 g_test_add_func("/replication/secondary/get_error_all",
577 test_secondary_get_error_all
);