2 * Block tests for iothreads
4 * Copyright (c) 2018 Kevin Wolf <kwolf@redhat.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "qemu/osdep.h"
26 #include "block/block.h"
27 #include "block/block_int-global-state.h"
28 #include "block/blockjob_int.h"
29 #include "sysemu/block-backend.h"
30 #include "qapi/error.h"
31 #include "qapi/qmp/qdict.h"
32 #include "qemu/main-loop.h"
35 static int coroutine_fn
bdrv_test_co_preadv(BlockDriverState
*bs
,
36 int64_t offset
, int64_t bytes
,
38 BdrvRequestFlags flags
)
43 static int coroutine_fn
bdrv_test_co_pwritev(BlockDriverState
*bs
,
44 int64_t offset
, int64_t bytes
,
46 BdrvRequestFlags flags
)
51 static int coroutine_fn
bdrv_test_co_pdiscard(BlockDriverState
*bs
,
52 int64_t offset
, int64_t bytes
)
57 static int coroutine_fn
58 bdrv_test_co_truncate(BlockDriverState
*bs
, int64_t offset
, bool exact
,
59 PreallocMode prealloc
, BdrvRequestFlags flags
,
65 static int coroutine_fn
bdrv_test_co_block_status(BlockDriverState
*bs
,
67 int64_t offset
, int64_t count
,
68 int64_t *pnum
, int64_t *map
,
69 BlockDriverState
**file
)
75 static BlockDriver bdrv_test
= {
76 .format_name
= "test",
79 .bdrv_co_preadv
= bdrv_test_co_preadv
,
80 .bdrv_co_pwritev
= bdrv_test_co_pwritev
,
81 .bdrv_co_pdiscard
= bdrv_test_co_pdiscard
,
82 .bdrv_co_truncate
= bdrv_test_co_truncate
,
83 .bdrv_co_block_status
= bdrv_test_co_block_status
,
86 static void test_sync_op_pread(BdrvChild
*c
)
92 ret
= bdrv_pread(c
, 0, sizeof(buf
), buf
, 0);
93 g_assert_cmpint(ret
, ==, 0);
95 /* Early error: Negative offset */
96 ret
= bdrv_pread(c
, -2, sizeof(buf
), buf
, 0);
97 g_assert_cmpint(ret
, ==, -EIO
);
100 static void test_sync_op_pwrite(BdrvChild
*c
)
102 uint8_t buf
[512] = { 0 };
106 ret
= bdrv_pwrite(c
, 0, sizeof(buf
), buf
, 0);
107 g_assert_cmpint(ret
, ==, 0);
109 /* Early error: Negative offset */
110 ret
= bdrv_pwrite(c
, -2, sizeof(buf
), buf
, 0);
111 g_assert_cmpint(ret
, ==, -EIO
);
114 static void test_sync_op_blk_pread(BlockBackend
*blk
)
120 ret
= blk_pread(blk
, 0, sizeof(buf
), buf
, 0);
121 g_assert_cmpint(ret
, ==, 0);
123 /* Early error: Negative offset */
124 ret
= blk_pread(blk
, -2, sizeof(buf
), buf
, 0);
125 g_assert_cmpint(ret
, ==, -EIO
);
128 static void test_sync_op_blk_pwrite(BlockBackend
*blk
)
130 uint8_t buf
[512] = { 0 };
134 ret
= blk_pwrite(blk
, 0, sizeof(buf
), buf
, 0);
135 g_assert_cmpint(ret
, ==, 0);
137 /* Early error: Negative offset */
138 ret
= blk_pwrite(blk
, -2, sizeof(buf
), buf
, 0);
139 g_assert_cmpint(ret
, ==, -EIO
);
142 static void test_sync_op_blk_preadv(BlockBackend
*blk
)
145 QEMUIOVector qiov
= QEMU_IOVEC_INIT_BUF(qiov
, buf
, sizeof(buf
));
149 ret
= blk_preadv(blk
, 0, sizeof(buf
), &qiov
, 0);
150 g_assert_cmpint(ret
, ==, 0);
152 /* Early error: Negative offset */
153 ret
= blk_preadv(blk
, -2, sizeof(buf
), &qiov
, 0);
154 g_assert_cmpint(ret
, ==, -EIO
);
157 static void test_sync_op_blk_pwritev(BlockBackend
*blk
)
159 uint8_t buf
[512] = { 0 };
160 QEMUIOVector qiov
= QEMU_IOVEC_INIT_BUF(qiov
, buf
, sizeof(buf
));
164 ret
= blk_pwritev(blk
, 0, sizeof(buf
), &qiov
, 0);
165 g_assert_cmpint(ret
, ==, 0);
167 /* Early error: Negative offset */
168 ret
= blk_pwritev(blk
, -2, sizeof(buf
), &qiov
, 0);
169 g_assert_cmpint(ret
, ==, -EIO
);
172 static void test_sync_op_blk_preadv_part(BlockBackend
*blk
)
175 QEMUIOVector qiov
= QEMU_IOVEC_INIT_BUF(qiov
, buf
, sizeof(buf
));
179 ret
= blk_preadv_part(blk
, 0, sizeof(buf
), &qiov
, 0, 0);
180 g_assert_cmpint(ret
, ==, 0);
182 /* Early error: Negative offset */
183 ret
= blk_preadv_part(blk
, -2, sizeof(buf
), &qiov
, 0, 0);
184 g_assert_cmpint(ret
, ==, -EIO
);
187 static void test_sync_op_blk_pwritev_part(BlockBackend
*blk
)
189 uint8_t buf
[512] = { 0 };
190 QEMUIOVector qiov
= QEMU_IOVEC_INIT_BUF(qiov
, buf
, sizeof(buf
));
194 ret
= blk_pwritev_part(blk
, 0, sizeof(buf
), &qiov
, 0, 0);
195 g_assert_cmpint(ret
, ==, 0);
197 /* Early error: Negative offset */
198 ret
= blk_pwritev_part(blk
, -2, sizeof(buf
), &qiov
, 0, 0);
199 g_assert_cmpint(ret
, ==, -EIO
);
202 static void test_sync_op_blk_pwrite_compressed(BlockBackend
*blk
)
204 uint8_t buf
[512] = { 0 };
207 /* Late error: Not supported */
208 ret
= blk_pwrite_compressed(blk
, 0, sizeof(buf
), buf
);
209 g_assert_cmpint(ret
, ==, -ENOTSUP
);
211 /* Early error: Negative offset */
212 ret
= blk_pwrite_compressed(blk
, -2, sizeof(buf
), buf
);
213 g_assert_cmpint(ret
, ==, -EIO
);
216 static void test_sync_op_blk_pwrite_zeroes(BlockBackend
*blk
)
221 ret
= blk_pwrite_zeroes(blk
, 0, 512, 0);
222 g_assert_cmpint(ret
, ==, 0);
224 /* Early error: Negative offset */
225 ret
= blk_pwrite_zeroes(blk
, -2, 512, 0);
226 g_assert_cmpint(ret
, ==, -EIO
);
229 static void test_sync_op_load_vmstate(BdrvChild
*c
)
234 /* Error: Driver does not support snapshots */
235 ret
= bdrv_load_vmstate(c
->bs
, buf
, 0, sizeof(buf
));
236 g_assert_cmpint(ret
, ==, -ENOTSUP
);
239 static void test_sync_op_save_vmstate(BdrvChild
*c
)
241 uint8_t buf
[512] = { 0 };
244 /* Error: Driver does not support snapshots */
245 ret
= bdrv_save_vmstate(c
->bs
, buf
, 0, sizeof(buf
));
246 g_assert_cmpint(ret
, ==, -ENOTSUP
);
249 static void test_sync_op_pdiscard(BdrvChild
*c
)
253 /* Normal success path */
254 c
->bs
->open_flags
|= BDRV_O_UNMAP
;
255 ret
= bdrv_pdiscard(c
, 0, 512);
256 g_assert_cmpint(ret
, ==, 0);
258 /* Early success: UNMAP not supported */
259 c
->bs
->open_flags
&= ~BDRV_O_UNMAP
;
260 ret
= bdrv_pdiscard(c
, 0, 512);
261 g_assert_cmpint(ret
, ==, 0);
263 /* Early error: Negative offset */
264 ret
= bdrv_pdiscard(c
, -2, 512);
265 g_assert_cmpint(ret
, ==, -EIO
);
268 static void test_sync_op_blk_pdiscard(BlockBackend
*blk
)
272 /* Early success: UNMAP not supported */
273 ret
= blk_pdiscard(blk
, 0, 512);
274 g_assert_cmpint(ret
, ==, 0);
276 /* Early error: Negative offset */
277 ret
= blk_pdiscard(blk
, -2, 512);
278 g_assert_cmpint(ret
, ==, -EIO
);
281 static void test_sync_op_truncate(BdrvChild
*c
)
285 /* Normal success path */
286 ret
= bdrv_truncate(c
, 65536, false, PREALLOC_MODE_OFF
, 0, NULL
);
287 g_assert_cmpint(ret
, ==, 0);
289 /* Early error: Negative offset */
290 ret
= bdrv_truncate(c
, -2, false, PREALLOC_MODE_OFF
, 0, NULL
);
291 g_assert_cmpint(ret
, ==, -EINVAL
);
293 /* Error: Read-only image */
294 c
->bs
->open_flags
&= ~BDRV_O_RDWR
;
296 ret
= bdrv_truncate(c
, 65536, false, PREALLOC_MODE_OFF
, 0, NULL
);
297 g_assert_cmpint(ret
, ==, -EACCES
);
299 c
->bs
->open_flags
|= BDRV_O_RDWR
;
302 static void test_sync_op_blk_truncate(BlockBackend
*blk
)
306 /* Normal success path */
307 ret
= blk_truncate(blk
, 65536, false, PREALLOC_MODE_OFF
, 0, NULL
);
308 g_assert_cmpint(ret
, ==, 0);
310 /* Early error: Negative offset */
311 ret
= blk_truncate(blk
, -2, false, PREALLOC_MODE_OFF
, 0, NULL
);
312 g_assert_cmpint(ret
, ==, -EINVAL
);
315 static void test_sync_op_block_status(BdrvChild
*c
)
320 /* Normal success path */
321 ret
= bdrv_is_allocated(c
->bs
, 0, 65536, &n
);
322 g_assert_cmpint(ret
, ==, 0);
324 /* Early success: No driver support */
325 bdrv_test
.bdrv_co_block_status
= NULL
;
326 ret
= bdrv_is_allocated(c
->bs
, 0, 65536, &n
);
327 g_assert_cmpint(ret
, ==, 1);
329 /* Early success: bytes = 0 */
330 ret
= bdrv_is_allocated(c
->bs
, 0, 0, &n
);
331 g_assert_cmpint(ret
, ==, 0);
333 /* Early success: Offset > image size*/
334 ret
= bdrv_is_allocated(c
->bs
, 0x1000000, 0x1000000, &n
);
335 g_assert_cmpint(ret
, ==, 0);
338 static void test_sync_op_flush(BdrvChild
*c
)
342 /* Normal success path */
343 ret
= bdrv_flush(c
->bs
);
344 g_assert_cmpint(ret
, ==, 0);
346 /* Early success: Read-only image */
347 c
->bs
->open_flags
&= ~BDRV_O_RDWR
;
349 ret
= bdrv_flush(c
->bs
);
350 g_assert_cmpint(ret
, ==, 0);
352 c
->bs
->open_flags
|= BDRV_O_RDWR
;
355 static void test_sync_op_blk_flush(BlockBackend
*blk
)
357 BlockDriverState
*bs
= blk_bs(blk
);
360 /* Normal success path */
361 ret
= blk_flush(blk
);
362 g_assert_cmpint(ret
, ==, 0);
364 /* Early success: Read-only image */
365 bs
->open_flags
&= ~BDRV_O_RDWR
;
367 ret
= blk_flush(blk
);
368 g_assert_cmpint(ret
, ==, 0);
370 bs
->open_flags
|= BDRV_O_RDWR
;
373 static void test_sync_op_check(BdrvChild
*c
)
375 BdrvCheckResult result
;
378 /* Error: Driver does not implement check */
379 ret
= bdrv_check(c
->bs
, &result
, 0);
380 g_assert_cmpint(ret
, ==, -ENOTSUP
);
383 static void test_sync_op_activate(BdrvChild
*c
)
385 /* Early success: Image is not inactive */
386 bdrv_activate(c
->bs
, NULL
);
390 typedef struct SyncOpTest
{
392 void (*fn
)(BdrvChild
*c
);
393 void (*blkfn
)(BlockBackend
*blk
);
396 const SyncOpTest sync_op_tests
[] = {
398 .name
= "/sync-op/pread",
399 .fn
= test_sync_op_pread
,
400 .blkfn
= test_sync_op_blk_pread
,
402 .name
= "/sync-op/pwrite",
403 .fn
= test_sync_op_pwrite
,
404 .blkfn
= test_sync_op_blk_pwrite
,
406 .name
= "/sync-op/preadv",
408 .blkfn
= test_sync_op_blk_preadv
,
410 .name
= "/sync-op/pwritev",
412 .blkfn
= test_sync_op_blk_pwritev
,
414 .name
= "/sync-op/preadv_part",
416 .blkfn
= test_sync_op_blk_preadv_part
,
418 .name
= "/sync-op/pwritev_part",
420 .blkfn
= test_sync_op_blk_pwritev_part
,
422 .name
= "/sync-op/pwrite_compressed",
424 .blkfn
= test_sync_op_blk_pwrite_compressed
,
426 .name
= "/sync-op/pwrite_zeroes",
428 .blkfn
= test_sync_op_blk_pwrite_zeroes
,
430 .name
= "/sync-op/load_vmstate",
431 .fn
= test_sync_op_load_vmstate
,
433 .name
= "/sync-op/save_vmstate",
434 .fn
= test_sync_op_save_vmstate
,
436 .name
= "/sync-op/pdiscard",
437 .fn
= test_sync_op_pdiscard
,
438 .blkfn
= test_sync_op_blk_pdiscard
,
440 .name
= "/sync-op/truncate",
441 .fn
= test_sync_op_truncate
,
442 .blkfn
= test_sync_op_blk_truncate
,
444 .name
= "/sync-op/block_status",
445 .fn
= test_sync_op_block_status
,
447 .name
= "/sync-op/flush",
448 .fn
= test_sync_op_flush
,
449 .blkfn
= test_sync_op_blk_flush
,
451 .name
= "/sync-op/check",
452 .fn
= test_sync_op_check
,
454 .name
= "/sync-op/activate",
455 .fn
= test_sync_op_activate
,
459 /* Test synchronous operations that run in a different iothread, so we have to
460 * poll for the coroutine there to return. */
461 static void test_sync_op(const void *opaque
)
463 const SyncOpTest
*t
= opaque
;
464 IOThread
*iothread
= iothread_new();
465 AioContext
*ctx
= iothread_get_aio_context(iothread
);
467 BlockDriverState
*bs
;
470 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
, BLK_PERM_ALL
);
471 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
472 bs
->total_sectors
= 65536 / BDRV_SECTOR_SIZE
;
473 blk_insert_bs(blk
, bs
, &error_abort
);
474 c
= QLIST_FIRST(&bs
->parents
);
476 blk_set_aio_context(blk
, ctx
, &error_abort
);
477 aio_context_acquire(ctx
);
484 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
485 aio_context_release(ctx
);
491 typedef struct TestBlockJob
{
493 bool should_complete
;
497 static int test_job_prepare(Job
*job
)
499 g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
503 static int coroutine_fn
test_job_run(Job
*job
, Error
**errp
)
505 TestBlockJob
*s
= container_of(job
, TestBlockJob
, common
.job
);
507 job_transition_to_ready(&s
->common
.job
);
508 while (!s
->should_complete
) {
510 g_assert(qemu_get_current_aio_context() == job
->aio_context
);
512 /* Avoid job_sleep_ns() because it marks the job as !busy. We want to
513 * emulate some actual activity (probably some I/O) here so that the
514 * drain involved in AioContext switches has to wait for this activity
516 qemu_co_sleep_ns(QEMU_CLOCK_REALTIME
, 1000000);
518 job_pause_point(&s
->common
.job
);
521 g_assert(qemu_get_current_aio_context() == job
->aio_context
);
525 static void test_job_complete(Job
*job
, Error
**errp
)
527 TestBlockJob
*s
= container_of(job
, TestBlockJob
, common
.job
);
528 s
->should_complete
= true;
531 BlockJobDriver test_job_driver
= {
533 .instance_size
= sizeof(TestBlockJob
),
534 .free
= block_job_free
,
535 .user_resume
= block_job_user_resume
,
537 .complete
= test_job_complete
,
538 .prepare
= test_job_prepare
,
542 static void test_attach_blockjob(void)
544 IOThread
*iothread
= iothread_new();
545 AioContext
*ctx
= iothread_get_aio_context(iothread
);
547 BlockDriverState
*bs
;
550 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
, BLK_PERM_ALL
);
551 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
552 blk_insert_bs(blk
, bs
, &error_abort
);
554 tjob
= block_job_create("job0", &test_job_driver
, NULL
, bs
,
556 0, 0, NULL
, NULL
, &error_abort
);
557 job_start(&tjob
->common
.job
);
559 while (tjob
->n
== 0) {
560 aio_poll(qemu_get_aio_context(), false);
563 blk_set_aio_context(blk
, ctx
, &error_abort
);
566 while (tjob
->n
== 0) {
567 aio_poll(qemu_get_aio_context(), false);
570 aio_context_acquire(ctx
);
571 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
572 aio_context_release(ctx
);
575 while (tjob
->n
== 0) {
576 aio_poll(qemu_get_aio_context(), false);
579 blk_set_aio_context(blk
, ctx
, &error_abort
);
582 while (tjob
->n
== 0) {
583 aio_poll(qemu_get_aio_context(), false);
586 WITH_JOB_LOCK_GUARD() {
587 job_complete_sync_locked(&tjob
->common
.job
, &error_abort
);
589 aio_context_acquire(ctx
);
590 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
591 aio_context_release(ctx
);
598 * Test that changing the AioContext for one node in a tree (here through blk)
599 * changes all other nodes as well:
603 * | bs_verify [blkverify]
606 * bs_a [bdrv_test] bs_b [bdrv_test]
609 static void test_propagate_basic(void)
611 IOThread
*iothread
= iothread_new();
612 AioContext
*ctx
= iothread_get_aio_context(iothread
);
613 AioContext
*main_ctx
;
615 BlockDriverState
*bs_a
, *bs_b
, *bs_verify
;
619 * Create bs_a and its BlockBackend. We cannot take the RESIZE
620 * permission because blkverify will not share it on the test
623 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
& ~BLK_PERM_RESIZE
,
625 bs_a
= bdrv_new_open_driver(&bdrv_test
, "bs_a", BDRV_O_RDWR
, &error_abort
);
626 blk_insert_bs(blk
, bs_a
, &error_abort
);
629 bs_b
= bdrv_new_open_driver(&bdrv_test
, "bs_b", BDRV_O_RDWR
, &error_abort
);
631 /* Create blkverify filter that references both bs_a and bs_b */
632 options
= qdict_new();
633 qdict_put_str(options
, "driver", "blkverify");
634 qdict_put_str(options
, "test", "bs_a");
635 qdict_put_str(options
, "raw", "bs_b");
637 bs_verify
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
639 /* Switch the AioContext */
640 blk_set_aio_context(blk
, ctx
, &error_abort
);
641 g_assert(blk_get_aio_context(blk
) == ctx
);
642 g_assert(bdrv_get_aio_context(bs_a
) == ctx
);
643 g_assert(bdrv_get_aio_context(bs_verify
) == ctx
);
644 g_assert(bdrv_get_aio_context(bs_b
) == ctx
);
646 /* Switch the AioContext back */
647 main_ctx
= qemu_get_aio_context();
648 aio_context_acquire(ctx
);
649 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
650 aio_context_release(ctx
);
651 g_assert(blk_get_aio_context(blk
) == main_ctx
);
652 g_assert(bdrv_get_aio_context(bs_a
) == main_ctx
);
653 g_assert(bdrv_get_aio_context(bs_verify
) == main_ctx
);
654 g_assert(bdrv_get_aio_context(bs_b
) == main_ctx
);
656 bdrv_unref(bs_verify
);
663 * Test that diamonds in the graph don't lead to endless recursion:
667 * bs_verify [blkverify]
670 * bs_b [raw] bs_c[raw]
675 static void test_propagate_diamond(void)
677 IOThread
*iothread
= iothread_new();
678 AioContext
*ctx
= iothread_get_aio_context(iothread
);
679 AioContext
*main_ctx
;
681 BlockDriverState
*bs_a
, *bs_b
, *bs_c
, *bs_verify
;
685 bs_a
= bdrv_new_open_driver(&bdrv_test
, "bs_a", BDRV_O_RDWR
, &error_abort
);
687 /* Create bs_b and bc_c */
688 options
= qdict_new();
689 qdict_put_str(options
, "driver", "raw");
690 qdict_put_str(options
, "file", "bs_a");
691 qdict_put_str(options
, "node-name", "bs_b");
692 bs_b
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
694 options
= qdict_new();
695 qdict_put_str(options
, "driver", "raw");
696 qdict_put_str(options
, "file", "bs_a");
697 qdict_put_str(options
, "node-name", "bs_c");
698 bs_c
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
700 /* Create blkverify filter that references both bs_b and bs_c */
701 options
= qdict_new();
702 qdict_put_str(options
, "driver", "blkverify");
703 qdict_put_str(options
, "test", "bs_b");
704 qdict_put_str(options
, "raw", "bs_c");
706 bs_verify
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
708 * Do not take the RESIZE permission: This would require the same
709 * from bs_c and thus from bs_a; however, blkverify will not share
710 * it on bs_b, and thus it will not be available for bs_a.
712 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
& ~BLK_PERM_RESIZE
,
714 blk_insert_bs(blk
, bs_verify
, &error_abort
);
716 /* Switch the AioContext */
717 blk_set_aio_context(blk
, ctx
, &error_abort
);
718 g_assert(blk_get_aio_context(blk
) == ctx
);
719 g_assert(bdrv_get_aio_context(bs_verify
) == ctx
);
720 g_assert(bdrv_get_aio_context(bs_a
) == ctx
);
721 g_assert(bdrv_get_aio_context(bs_b
) == ctx
);
722 g_assert(bdrv_get_aio_context(bs_c
) == ctx
);
724 /* Switch the AioContext back */
725 main_ctx
= qemu_get_aio_context();
726 aio_context_acquire(ctx
);
727 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
728 aio_context_release(ctx
);
729 g_assert(blk_get_aio_context(blk
) == main_ctx
);
730 g_assert(bdrv_get_aio_context(bs_verify
) == main_ctx
);
731 g_assert(bdrv_get_aio_context(bs_a
) == main_ctx
);
732 g_assert(bdrv_get_aio_context(bs_b
) == main_ctx
);
733 g_assert(bdrv_get_aio_context(bs_c
) == main_ctx
);
736 bdrv_unref(bs_verify
);
742 static void test_propagate_mirror(void)
744 IOThread
*iothread
= iothread_new();
745 AioContext
*ctx
= iothread_get_aio_context(iothread
);
746 AioContext
*main_ctx
= qemu_get_aio_context();
747 BlockDriverState
*src
, *target
, *filter
;
750 Error
*local_err
= NULL
;
752 /* Create src and target*/
753 src
= bdrv_new_open_driver(&bdrv_test
, "src", BDRV_O_RDWR
, &error_abort
);
754 target
= bdrv_new_open_driver(&bdrv_test
, "target", BDRV_O_RDWR
,
757 /* Start a mirror job */
758 mirror_start("job0", src
, target
, NULL
, JOB_DEFAULT
, 0, 0, 0,
759 MIRROR_SYNC_MODE_NONE
, MIRROR_OPEN_BACKING_CHAIN
, false,
760 BLOCKDEV_ON_ERROR_REPORT
, BLOCKDEV_ON_ERROR_REPORT
,
761 false, "filter_node", MIRROR_COPY_MODE_BACKGROUND
,
763 WITH_JOB_LOCK_GUARD() {
764 job
= job_get_locked("job0");
766 filter
= bdrv_find_node("filter_node");
768 /* Change the AioContext of src */
769 bdrv_try_change_aio_context(src
, ctx
, NULL
, &error_abort
);
770 g_assert(bdrv_get_aio_context(src
) == ctx
);
771 g_assert(bdrv_get_aio_context(target
) == ctx
);
772 g_assert(bdrv_get_aio_context(filter
) == ctx
);
773 g_assert(job
->aio_context
== ctx
);
775 /* Change the AioContext of target */
776 aio_context_acquire(ctx
);
777 bdrv_try_change_aio_context(target
, main_ctx
, NULL
, &error_abort
);
778 aio_context_release(ctx
);
779 g_assert(bdrv_get_aio_context(src
) == main_ctx
);
780 g_assert(bdrv_get_aio_context(target
) == main_ctx
);
781 g_assert(bdrv_get_aio_context(filter
) == main_ctx
);
783 /* With a BlockBackend on src, changing target must fail */
784 blk
= blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL
);
785 blk_insert_bs(blk
, src
, &error_abort
);
787 bdrv_try_change_aio_context(target
, ctx
, NULL
, &local_err
);
788 error_free_or_abort(&local_err
);
790 g_assert(blk_get_aio_context(blk
) == main_ctx
);
791 g_assert(bdrv_get_aio_context(src
) == main_ctx
);
792 g_assert(bdrv_get_aio_context(target
) == main_ctx
);
793 g_assert(bdrv_get_aio_context(filter
) == main_ctx
);
795 /* ...unless we explicitly allow it */
796 aio_context_acquire(ctx
);
797 blk_set_allow_aio_context_change(blk
, true);
798 bdrv_try_change_aio_context(target
, ctx
, NULL
, &error_abort
);
799 aio_context_release(ctx
);
801 g_assert(blk_get_aio_context(blk
) == ctx
);
802 g_assert(bdrv_get_aio_context(src
) == ctx
);
803 g_assert(bdrv_get_aio_context(target
) == ctx
);
804 g_assert(bdrv_get_aio_context(filter
) == ctx
);
806 job_cancel_sync_all();
808 aio_context_acquire(ctx
);
809 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
810 bdrv_try_change_aio_context(target
, main_ctx
, NULL
, &error_abort
);
811 aio_context_release(ctx
);
818 static void test_attach_second_node(void)
820 IOThread
*iothread
= iothread_new();
821 AioContext
*ctx
= iothread_get_aio_context(iothread
);
822 AioContext
*main_ctx
= qemu_get_aio_context();
824 BlockDriverState
*bs
, *filter
;
827 blk
= blk_new(ctx
, BLK_PERM_ALL
, BLK_PERM_ALL
);
828 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
829 blk_insert_bs(blk
, bs
, &error_abort
);
831 options
= qdict_new();
832 qdict_put_str(options
, "driver", "raw");
833 qdict_put_str(options
, "file", "base");
835 filter
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
836 g_assert(blk_get_aio_context(blk
) == ctx
);
837 g_assert(bdrv_get_aio_context(bs
) == ctx
);
838 g_assert(bdrv_get_aio_context(filter
) == ctx
);
840 aio_context_acquire(ctx
);
841 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
842 aio_context_release(ctx
);
843 g_assert(blk_get_aio_context(blk
) == main_ctx
);
844 g_assert(bdrv_get_aio_context(bs
) == main_ctx
);
845 g_assert(bdrv_get_aio_context(filter
) == main_ctx
);
852 static void test_attach_preserve_blk_ctx(void)
854 IOThread
*iothread
= iothread_new();
855 AioContext
*ctx
= iothread_get_aio_context(iothread
);
857 BlockDriverState
*bs
;
859 blk
= blk_new(ctx
, BLK_PERM_ALL
, BLK_PERM_ALL
);
860 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
861 bs
->total_sectors
= 65536 / BDRV_SECTOR_SIZE
;
863 /* Add node to BlockBackend that has an iothread context assigned */
864 blk_insert_bs(blk
, bs
, &error_abort
);
865 g_assert(blk_get_aio_context(blk
) == ctx
);
866 g_assert(bdrv_get_aio_context(bs
) == ctx
);
868 /* Remove the node again */
869 aio_context_acquire(ctx
);
871 aio_context_release(ctx
);
872 g_assert(blk_get_aio_context(blk
) == ctx
);
873 g_assert(bdrv_get_aio_context(bs
) == qemu_get_aio_context());
875 /* Re-attach the node */
876 blk_insert_bs(blk
, bs
, &error_abort
);
877 g_assert(blk_get_aio_context(blk
) == ctx
);
878 g_assert(bdrv_get_aio_context(bs
) == ctx
);
880 aio_context_acquire(ctx
);
881 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
882 aio_context_release(ctx
);
887 int main(int argc
, char **argv
)
892 qemu_init_main_loop(&error_abort
);
894 g_test_init(&argc
, &argv
, NULL
);
896 for (i
= 0; i
< ARRAY_SIZE(sync_op_tests
); i
++) {
897 const SyncOpTest
*t
= &sync_op_tests
[i
];
898 g_test_add_data_func(t
->name
, t
, test_sync_op
);
901 g_test_add_func("/attach/blockjob", test_attach_blockjob
);
902 g_test_add_func("/attach/second_node", test_attach_second_node
);
903 g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx
);
904 g_test_add_func("/propagate/basic", test_propagate_basic
);
905 g_test_add_func("/propagate/diamond", test_propagate_diamond
);
906 g_test_add_func("/propagate/mirror", test_propagate_mirror
);