1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "block/block.h"
27#include "block/blockjob_int.h"
28#include "sysemu/block-backend.h"
29#include "qapi/error.h"
30#include "qapi/qmp/qdict.h"
31#include "iothread.h"
32
33static int coroutine_fn bdrv_test_co_prwv(BlockDriverState *bs,
34 uint64_t offset, uint64_t bytes,
35 QEMUIOVector *qiov, int flags)
36{
37 return 0;
38}
39
40static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
41 int64_t offset, int bytes)
42{
43 return 0;
44}
45
46static int coroutine_fn
47bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset,
48 PreallocMode prealloc, Error **errp)
49{
50 return 0;
51}
52
53static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
54 bool want_zero,
55 int64_t offset, int64_t count,
56 int64_t *pnum, int64_t *map,
57 BlockDriverState **file)
58{
59 *pnum = count;
60 return 0;
61}
62
63static BlockDriver bdrv_test = {
64 .format_name = "test",
65 .instance_size = 1,
66
67 .bdrv_co_preadv = bdrv_test_co_prwv,
68 .bdrv_co_pwritev = bdrv_test_co_prwv,
69 .bdrv_co_pdiscard = bdrv_test_co_pdiscard,
70 .bdrv_co_truncate = bdrv_test_co_truncate,
71 .bdrv_co_block_status = bdrv_test_co_block_status,
72};
73
74static void test_sync_op_pread(BdrvChild *c)
75{
76 uint8_t buf[512];
77 int ret;
78
79
80 ret = bdrv_pread(c, 0, buf, sizeof(buf));
81 g_assert_cmpint(ret, ==, 512);
82
83
84 ret = bdrv_pread(c, -2, buf, sizeof(buf));
85 g_assert_cmpint(ret, ==, -EIO);
86}
87
88static void test_sync_op_pwrite(BdrvChild *c)
89{
90 uint8_t buf[512];
91 int ret;
92
93
94 ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
95 g_assert_cmpint(ret, ==, 512);
96
97
98 ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
99 g_assert_cmpint(ret, ==, -EIO);
100}
101
102static void test_sync_op_blk_pread(BlockBackend *blk)
103{
104 uint8_t buf[512];
105 int ret;
106
107
108 ret = blk_pread(blk, 0, buf, sizeof(buf));
109 g_assert_cmpint(ret, ==, 512);
110
111
112 ret = blk_pread(blk, -2, buf, sizeof(buf));
113 g_assert_cmpint(ret, ==, -EIO);
114}
115
116static void test_sync_op_blk_pwrite(BlockBackend *blk)
117{
118 uint8_t buf[512];
119 int ret;
120
121
122 ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
123 g_assert_cmpint(ret, ==, 512);
124
125
126 ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
127 g_assert_cmpint(ret, ==, -EIO);
128}
129
130static void test_sync_op_load_vmstate(BdrvChild *c)
131{
132 uint8_t buf[512];
133 int ret;
134
135
136 ret = bdrv_load_vmstate(c->bs, buf, 0, sizeof(buf));
137 g_assert_cmpint(ret, ==, -ENOTSUP);
138}
139
140static void test_sync_op_save_vmstate(BdrvChild *c)
141{
142 uint8_t buf[512];
143 int ret;
144
145
146 ret = bdrv_save_vmstate(c->bs, buf, 0, sizeof(buf));
147 g_assert_cmpint(ret, ==, -ENOTSUP);
148}
149
150static void test_sync_op_pdiscard(BdrvChild *c)
151{
152 int ret;
153
154
155 c->bs->open_flags |= BDRV_O_UNMAP;
156 ret = bdrv_pdiscard(c, 0, 512);
157 g_assert_cmpint(ret, ==, 0);
158
159
160 c->bs->open_flags &= ~BDRV_O_UNMAP;
161 ret = bdrv_pdiscard(c, 0, 512);
162 g_assert_cmpint(ret, ==, 0);
163
164
165 ret = bdrv_pdiscard(c, -2, 512);
166 g_assert_cmpint(ret, ==, -EIO);
167}
168
169static void test_sync_op_blk_pdiscard(BlockBackend *blk)
170{
171 int ret;
172
173
174 ret = blk_pdiscard(blk, 0, 512);
175 g_assert_cmpint(ret, ==, 0);
176
177
178 ret = blk_pdiscard(blk, -2, 512);
179 g_assert_cmpint(ret, ==, -EIO);
180}
181
182static void test_sync_op_truncate(BdrvChild *c)
183{
184 int ret;
185
186
187 ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
188 g_assert_cmpint(ret, ==, 0);
189
190
191 ret = bdrv_truncate(c, -2, PREALLOC_MODE_OFF, NULL);
192 g_assert_cmpint(ret, ==, -EINVAL);
193
194
195 c->bs->read_only = true;
196 c->bs->open_flags &= ~BDRV_O_RDWR;
197
198 ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
199 g_assert_cmpint(ret, ==, -EACCES);
200
201 c->bs->read_only = false;
202 c->bs->open_flags |= BDRV_O_RDWR;
203}
204
205static void test_sync_op_block_status(BdrvChild *c)
206{
207 int ret;
208 int64_t n;
209
210
211 ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
212 g_assert_cmpint(ret, ==, 0);
213
214
215 bdrv_test.bdrv_co_block_status = NULL;
216 ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
217 g_assert_cmpint(ret, ==, 1);
218
219
220 ret = bdrv_is_allocated(c->bs, 0, 0, &n);
221 g_assert_cmpint(ret, ==, 0);
222
223
224 ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n);
225 g_assert_cmpint(ret, ==, 0);
226}
227
228static void test_sync_op_flush(BdrvChild *c)
229{
230 int ret;
231
232
233 ret = bdrv_flush(c->bs);
234 g_assert_cmpint(ret, ==, 0);
235
236
237 c->bs->read_only = true;
238 c->bs->open_flags &= ~BDRV_O_RDWR;
239
240 ret = bdrv_flush(c->bs);
241 g_assert_cmpint(ret, ==, 0);
242
243 c->bs->read_only = false;
244 c->bs->open_flags |= BDRV_O_RDWR;
245}
246
247static void test_sync_op_blk_flush(BlockBackend *blk)
248{
249 BlockDriverState *bs = blk_bs(blk);
250 int ret;
251
252
253 ret = blk_flush(blk);
254 g_assert_cmpint(ret, ==, 0);
255
256
257 bs->read_only = true;
258 bs->open_flags &= ~BDRV_O_RDWR;
259
260 ret = blk_flush(blk);
261 g_assert_cmpint(ret, ==, 0);
262
263 bs->read_only = false;
264 bs->open_flags |= BDRV_O_RDWR;
265}
266
267static void test_sync_op_check(BdrvChild *c)
268{
269 BdrvCheckResult result;
270 int ret;
271
272
273 ret = bdrv_check(c->bs, &result, 0);
274 g_assert_cmpint(ret, ==, -ENOTSUP);
275}
276
277static void test_sync_op_invalidate_cache(BdrvChild *c)
278{
279
280 bdrv_invalidate_cache(c->bs, NULL);
281}
282
283
284typedef struct SyncOpTest {
285 const char *name;
286 void (*fn)(BdrvChild *c);
287 void (*blkfn)(BlockBackend *blk);
288} SyncOpTest;
289
290const SyncOpTest sync_op_tests[] = {
291 {
292 .name = "/sync-op/pread",
293 .fn = test_sync_op_pread,
294 .blkfn = test_sync_op_blk_pread,
295 }, {
296 .name = "/sync-op/pwrite",
297 .fn = test_sync_op_pwrite,
298 .blkfn = test_sync_op_blk_pwrite,
299 }, {
300 .name = "/sync-op/load_vmstate",
301 .fn = test_sync_op_load_vmstate,
302 }, {
303 .name = "/sync-op/save_vmstate",
304 .fn = test_sync_op_save_vmstate,
305 }, {
306 .name = "/sync-op/pdiscard",
307 .fn = test_sync_op_pdiscard,
308 .blkfn = test_sync_op_blk_pdiscard,
309 }, {
310 .name = "/sync-op/truncate",
311 .fn = test_sync_op_truncate,
312 }, {
313 .name = "/sync-op/block_status",
314 .fn = test_sync_op_block_status,
315 }, {
316 .name = "/sync-op/flush",
317 .fn = test_sync_op_flush,
318 .blkfn = test_sync_op_blk_flush,
319 }, {
320 .name = "/sync-op/check",
321 .fn = test_sync_op_check,
322 }, {
323 .name = "/sync-op/invalidate_cache",
324 .fn = test_sync_op_invalidate_cache,
325 },
326};
327
328
329
330static void test_sync_op(const void *opaque)
331{
332 const SyncOpTest *t = opaque;
333 IOThread *iothread = iothread_new();
334 AioContext *ctx = iothread_get_aio_context(iothread);
335 BlockBackend *blk;
336 BlockDriverState *bs;
337 BdrvChild *c;
338
339 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
340 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
341 bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
342 blk_insert_bs(blk, bs, &error_abort);
343 c = QLIST_FIRST(&bs->parents);
344
345 blk_set_aio_context(blk, ctx, &error_abort);
346 aio_context_acquire(ctx);
347 t->fn(c);
348 if (t->blkfn) {
349 t->blkfn(blk);
350 }
351 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
352 aio_context_release(ctx);
353
354 bdrv_unref(bs);
355 blk_unref(blk);
356}
357
358typedef struct TestBlockJob {
359 BlockJob common;
360 bool should_complete;
361 int n;
362} TestBlockJob;
363
364static int test_job_prepare(Job *job)
365{
366 g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
367 return 0;
368}
369
370static int coroutine_fn test_job_run(Job *job, Error **errp)
371{
372 TestBlockJob *s = container_of(job, TestBlockJob, common.job);
373
374 job_transition_to_ready(&s->common.job);
375 while (!s->should_complete) {
376 s->n++;
377 g_assert(qemu_get_current_aio_context() == job->aio_context);
378
379
380
381
382
383 qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000);
384
385 job_pause_point(&s->common.job);
386 }
387
388 g_assert(qemu_get_current_aio_context() == job->aio_context);
389 return 0;
390}
391
392static void test_job_complete(Job *job, Error **errp)
393{
394 TestBlockJob *s = container_of(job, TestBlockJob, common.job);
395 s->should_complete = true;
396}
397
398BlockJobDriver test_job_driver = {
399 .job_driver = {
400 .instance_size = sizeof(TestBlockJob),
401 .free = block_job_free,
402 .user_resume = block_job_user_resume,
403 .drain = block_job_drain,
404 .run = test_job_run,
405 .complete = test_job_complete,
406 .prepare = test_job_prepare,
407 },
408};
409
410static void test_attach_blockjob(void)
411{
412 IOThread *iothread = iothread_new();
413 AioContext *ctx = iothread_get_aio_context(iothread);
414 BlockBackend *blk;
415 BlockDriverState *bs;
416 TestBlockJob *tjob;
417
418 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
419 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
420 blk_insert_bs(blk, bs, &error_abort);
421
422 tjob = block_job_create("job0", &test_job_driver, NULL, bs,
423 0, BLK_PERM_ALL,
424 0, 0, NULL, NULL, &error_abort);
425 job_start(&tjob->common.job);
426
427 while (tjob->n == 0) {
428 aio_poll(qemu_get_aio_context(), false);
429 }
430
431 blk_set_aio_context(blk, ctx, &error_abort);
432
433 tjob->n = 0;
434 while (tjob->n == 0) {
435 aio_poll(qemu_get_aio_context(), false);
436 }
437
438 aio_context_acquire(ctx);
439 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
440 aio_context_release(ctx);
441
442 tjob->n = 0;
443 while (tjob->n == 0) {
444 aio_poll(qemu_get_aio_context(), false);
445 }
446
447 blk_set_aio_context(blk, ctx, &error_abort);
448
449 tjob->n = 0;
450 while (tjob->n == 0) {
451 aio_poll(qemu_get_aio_context(), false);
452 }
453
454 aio_context_acquire(ctx);
455 job_complete_sync(&tjob->common.job, &error_abort);
456 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
457 aio_context_release(ctx);
458
459 bdrv_unref(bs);
460 blk_unref(blk);
461}
462
463
464
465
466
467
468
469
470
471
472
473
474
475static void test_propagate_basic(void)
476{
477 IOThread *iothread = iothread_new();
478 AioContext *ctx = iothread_get_aio_context(iothread);
479 AioContext *main_ctx;
480 BlockBackend *blk;
481 BlockDriverState *bs_a, *bs_b, *bs_verify;
482 QDict *options;
483
484
485 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
486 bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
487 blk_insert_bs(blk, bs_a, &error_abort);
488
489
490 bs_b = bdrv_new_open_driver(&bdrv_test, "bs_b", BDRV_O_RDWR, &error_abort);
491
492
493 options = qdict_new();
494 qdict_put_str(options, "driver", "blkverify");
495 qdict_put_str(options, "test", "bs_a");
496 qdict_put_str(options, "raw", "bs_b");
497
498 bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
499
500
501 blk_set_aio_context(blk, ctx, &error_abort);
502 g_assert(blk_get_aio_context(blk) == ctx);
503 g_assert(bdrv_get_aio_context(bs_a) == ctx);
504 g_assert(bdrv_get_aio_context(bs_verify) == ctx);
505 g_assert(bdrv_get_aio_context(bs_b) == ctx);
506
507
508 main_ctx = qemu_get_aio_context();
509 aio_context_acquire(ctx);
510 blk_set_aio_context(blk, main_ctx, &error_abort);
511 aio_context_release(ctx);
512 g_assert(blk_get_aio_context(blk) == main_ctx);
513 g_assert(bdrv_get_aio_context(bs_a) == main_ctx);
514 g_assert(bdrv_get_aio_context(bs_verify) == main_ctx);
515 g_assert(bdrv_get_aio_context(bs_b) == main_ctx);
516
517 bdrv_unref(bs_verify);
518 bdrv_unref(bs_b);
519 bdrv_unref(bs_a);
520 blk_unref(blk);
521}
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536static void test_propagate_diamond(void)
537{
538 IOThread *iothread = iothread_new();
539 AioContext *ctx = iothread_get_aio_context(iothread);
540 AioContext *main_ctx;
541 BlockBackend *blk;
542 BlockDriverState *bs_a, *bs_b, *bs_c, *bs_verify;
543 QDict *options;
544
545
546 bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
547
548
549 options = qdict_new();
550 qdict_put_str(options, "driver", "raw");
551 qdict_put_str(options, "file", "bs_a");
552 qdict_put_str(options, "node-name", "bs_b");
553 bs_b = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
554
555 options = qdict_new();
556 qdict_put_str(options, "driver", "raw");
557 qdict_put_str(options, "file", "bs_a");
558 qdict_put_str(options, "node-name", "bs_c");
559 bs_c = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
560
561
562 options = qdict_new();
563 qdict_put_str(options, "driver", "blkverify");
564 qdict_put_str(options, "test", "bs_b");
565 qdict_put_str(options, "raw", "bs_c");
566
567 bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
568 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
569 blk_insert_bs(blk, bs_verify, &error_abort);
570
571
572 blk_set_aio_context(blk, ctx, &error_abort);
573 g_assert(blk_get_aio_context(blk) == ctx);
574 g_assert(bdrv_get_aio_context(bs_verify) == ctx);
575 g_assert(bdrv_get_aio_context(bs_a) == ctx);
576 g_assert(bdrv_get_aio_context(bs_b) == ctx);
577 g_assert(bdrv_get_aio_context(bs_c) == ctx);
578
579
580 main_ctx = qemu_get_aio_context();
581 aio_context_acquire(ctx);
582 blk_set_aio_context(blk, main_ctx, &error_abort);
583 aio_context_release(ctx);
584 g_assert(blk_get_aio_context(blk) == main_ctx);
585 g_assert(bdrv_get_aio_context(bs_verify) == main_ctx);
586 g_assert(bdrv_get_aio_context(bs_a) == main_ctx);
587 g_assert(bdrv_get_aio_context(bs_b) == main_ctx);
588 g_assert(bdrv_get_aio_context(bs_c) == main_ctx);
589
590 blk_unref(blk);
591 bdrv_unref(bs_verify);
592 bdrv_unref(bs_c);
593 bdrv_unref(bs_b);
594 bdrv_unref(bs_a);
595}
596
597static void test_propagate_mirror(void)
598{
599 IOThread *iothread = iothread_new();
600 AioContext *ctx = iothread_get_aio_context(iothread);
601 AioContext *main_ctx = qemu_get_aio_context();
602 BlockDriverState *src, *target, *filter;
603 BlockBackend *blk;
604 Job *job;
605 Error *local_err = NULL;
606
607
608 src = bdrv_new_open_driver(&bdrv_test, "src", BDRV_O_RDWR, &error_abort);
609 target = bdrv_new_open_driver(&bdrv_test, "target", BDRV_O_RDWR,
610 &error_abort);
611
612
613 mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
614 MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN,
615 BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
616 false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
617 &error_abort);
618 job = job_get("job0");
619 filter = bdrv_find_node("filter_node");
620
621
622 bdrv_try_set_aio_context(src, ctx, &error_abort);
623 g_assert(bdrv_get_aio_context(src) == ctx);
624 g_assert(bdrv_get_aio_context(target) == ctx);
625 g_assert(bdrv_get_aio_context(filter) == ctx);
626 g_assert(job->aio_context == ctx);
627
628
629 aio_context_acquire(ctx);
630 bdrv_try_set_aio_context(target, main_ctx, &error_abort);
631 aio_context_release(ctx);
632 g_assert(bdrv_get_aio_context(src) == main_ctx);
633 g_assert(bdrv_get_aio_context(target) == main_ctx);
634 g_assert(bdrv_get_aio_context(filter) == main_ctx);
635
636
637 blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
638 blk_insert_bs(blk, src, &error_abort);
639
640 bdrv_try_set_aio_context(target, ctx, &local_err);
641 g_assert(local_err);
642 error_free(local_err);
643
644 g_assert(blk_get_aio_context(blk) == main_ctx);
645 g_assert(bdrv_get_aio_context(src) == main_ctx);
646 g_assert(bdrv_get_aio_context(target) == main_ctx);
647 g_assert(bdrv_get_aio_context(filter) == main_ctx);
648
649
650 aio_context_acquire(ctx);
651 blk_set_allow_aio_context_change(blk, true);
652 bdrv_try_set_aio_context(target, ctx, &error_abort);
653 aio_context_release(ctx);
654
655 g_assert(blk_get_aio_context(blk) == ctx);
656 g_assert(bdrv_get_aio_context(src) == ctx);
657 g_assert(bdrv_get_aio_context(target) == ctx);
658 g_assert(bdrv_get_aio_context(filter) == ctx);
659
660 job_cancel_sync_all();
661
662 aio_context_acquire(ctx);
663 blk_set_aio_context(blk, main_ctx, &error_abort);
664 bdrv_try_set_aio_context(target, main_ctx, &error_abort);
665 aio_context_release(ctx);
666
667 blk_unref(blk);
668 bdrv_unref(src);
669 bdrv_unref(target);
670}
671
672static void test_attach_second_node(void)
673{
674 IOThread *iothread = iothread_new();
675 AioContext *ctx = iothread_get_aio_context(iothread);
676 AioContext *main_ctx = qemu_get_aio_context();
677 BlockBackend *blk;
678 BlockDriverState *bs, *filter;
679 QDict *options;
680
681 blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
682 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
683 blk_insert_bs(blk, bs, &error_abort);
684
685 options = qdict_new();
686 qdict_put_str(options, "driver", "raw");
687 qdict_put_str(options, "file", "base");
688
689 filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
690 g_assert(blk_get_aio_context(blk) == ctx);
691 g_assert(bdrv_get_aio_context(bs) == ctx);
692 g_assert(bdrv_get_aio_context(filter) == ctx);
693
694 aio_context_acquire(ctx);
695 blk_set_aio_context(blk, main_ctx, &error_abort);
696 aio_context_release(ctx);
697 g_assert(blk_get_aio_context(blk) == main_ctx);
698 g_assert(bdrv_get_aio_context(bs) == main_ctx);
699 g_assert(bdrv_get_aio_context(filter) == main_ctx);
700
701 bdrv_unref(filter);
702 bdrv_unref(bs);
703 blk_unref(blk);
704}
705
706static void test_attach_preserve_blk_ctx(void)
707{
708 IOThread *iothread = iothread_new();
709 AioContext *ctx = iothread_get_aio_context(iothread);
710 BlockBackend *blk;
711 BlockDriverState *bs;
712
713 blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
714 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
715 bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
716
717
718 blk_insert_bs(blk, bs, &error_abort);
719 g_assert(blk_get_aio_context(blk) == ctx);
720 g_assert(bdrv_get_aio_context(bs) == ctx);
721
722
723 aio_context_acquire(ctx);
724 blk_remove_bs(blk);
725 aio_context_release(ctx);
726 g_assert(blk_get_aio_context(blk) == ctx);
727 g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context());
728
729
730 blk_insert_bs(blk, bs, &error_abort);
731 g_assert(blk_get_aio_context(blk) == ctx);
732 g_assert(bdrv_get_aio_context(bs) == ctx);
733
734 aio_context_acquire(ctx);
735 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
736 aio_context_release(ctx);
737 bdrv_unref(bs);
738 blk_unref(blk);
739}
740
741int main(int argc, char **argv)
742{
743 int i;
744
745 bdrv_init();
746 qemu_init_main_loop(&error_abort);
747
748 g_test_init(&argc, &argv, NULL);
749
750 for (i = 0; i < ARRAY_SIZE(sync_op_tests); i++) {
751 const SyncOpTest *t = &sync_op_tests[i];
752 g_test_add_data_func(t->name, t, test_sync_op);
753 }
754
755 g_test_add_func("/attach/blockjob", test_attach_blockjob);
756 g_test_add_func("/attach/second_node", test_attach_second_node);
757 g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx);
758 g_test_add_func("/propagate/basic", test_propagate_basic);
759 g_test_add_func("/propagate/diamond", test_propagate_diamond);
760 g_test_add_func("/propagate/mirror", test_propagate_mirror);
761
762 return g_test_run();
763}
764