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/blockjob_int.h"
28 #include "sysemu/block-backend.h"
29 #include "qapi/error.h"
30 #include "qapi/qmp/qdict.h"
31 #include "qemu/main-loop.h"
34 static int coroutine_fn
bdrv_test_co_prwv(BlockDriverState
*bs
,
35 uint64_t offset
, uint64_t bytes
,
36 QEMUIOVector
*qiov
, int flags
)
41 static int coroutine_fn
bdrv_test_co_pdiscard(BlockDriverState
*bs
,
42 int64_t offset
, int bytes
)
47 static int coroutine_fn
48 bdrv_test_co_truncate(BlockDriverState
*bs
, int64_t offset
, bool exact
,
49 PreallocMode prealloc
, BdrvRequestFlags flags
,
55 static int coroutine_fn
bdrv_test_co_block_status(BlockDriverState
*bs
,
57 int64_t offset
, int64_t count
,
58 int64_t *pnum
, int64_t *map
,
59 BlockDriverState
**file
)
65 static BlockDriver bdrv_test
= {
66 .format_name
= "test",
69 .bdrv_co_preadv
= bdrv_test_co_prwv
,
70 .bdrv_co_pwritev
= bdrv_test_co_prwv
,
71 .bdrv_co_pdiscard
= bdrv_test_co_pdiscard
,
72 .bdrv_co_truncate
= bdrv_test_co_truncate
,
73 .bdrv_co_block_status
= bdrv_test_co_block_status
,
76 static void test_sync_op_pread(BdrvChild
*c
)
82 ret
= bdrv_pread(c
, 0, buf
, sizeof(buf
));
83 g_assert_cmpint(ret
, ==, 512);
85 /* Early error: Negative offset */
86 ret
= bdrv_pread(c
, -2, buf
, sizeof(buf
));
87 g_assert_cmpint(ret
, ==, -EIO
);
90 static void test_sync_op_pwrite(BdrvChild
*c
)
92 uint8_t buf
[512] = { 0 };
96 ret
= bdrv_pwrite(c
, 0, buf
, sizeof(buf
));
97 g_assert_cmpint(ret
, ==, 512);
99 /* Early error: Negative offset */
100 ret
= bdrv_pwrite(c
, -2, buf
, sizeof(buf
));
101 g_assert_cmpint(ret
, ==, -EIO
);
104 static void test_sync_op_blk_pread(BlockBackend
*blk
)
110 ret
= blk_pread(blk
, 0, buf
, sizeof(buf
));
111 g_assert_cmpint(ret
, ==, 512);
113 /* Early error: Negative offset */
114 ret
= blk_pread(blk
, -2, buf
, sizeof(buf
));
115 g_assert_cmpint(ret
, ==, -EIO
);
118 static void test_sync_op_blk_pwrite(BlockBackend
*blk
)
120 uint8_t buf
[512] = { 0 };
124 ret
= blk_pwrite(blk
, 0, buf
, sizeof(buf
), 0);
125 g_assert_cmpint(ret
, ==, 512);
127 /* Early error: Negative offset */
128 ret
= blk_pwrite(blk
, -2, buf
, sizeof(buf
), 0);
129 g_assert_cmpint(ret
, ==, -EIO
);
132 static void test_sync_op_load_vmstate(BdrvChild
*c
)
137 /* Error: Driver does not support snapshots */
138 ret
= bdrv_load_vmstate(c
->bs
, buf
, 0, sizeof(buf
));
139 g_assert_cmpint(ret
, ==, -ENOTSUP
);
142 static void test_sync_op_save_vmstate(BdrvChild
*c
)
144 uint8_t buf
[512] = { 0 };
147 /* Error: Driver does not support snapshots */
148 ret
= bdrv_save_vmstate(c
->bs
, buf
, 0, sizeof(buf
));
149 g_assert_cmpint(ret
, ==, -ENOTSUP
);
152 static void test_sync_op_pdiscard(BdrvChild
*c
)
156 /* Normal success path */
157 c
->bs
->open_flags
|= BDRV_O_UNMAP
;
158 ret
= bdrv_pdiscard(c
, 0, 512);
159 g_assert_cmpint(ret
, ==, 0);
161 /* Early success: UNMAP not supported */
162 c
->bs
->open_flags
&= ~BDRV_O_UNMAP
;
163 ret
= bdrv_pdiscard(c
, 0, 512);
164 g_assert_cmpint(ret
, ==, 0);
166 /* Early error: Negative offset */
167 ret
= bdrv_pdiscard(c
, -2, 512);
168 g_assert_cmpint(ret
, ==, -EIO
);
171 static void test_sync_op_blk_pdiscard(BlockBackend
*blk
)
175 /* Early success: UNMAP not supported */
176 ret
= blk_pdiscard(blk
, 0, 512);
177 g_assert_cmpint(ret
, ==, 0);
179 /* Early error: Negative offset */
180 ret
= blk_pdiscard(blk
, -2, 512);
181 g_assert_cmpint(ret
, ==, -EIO
);
184 static void test_sync_op_truncate(BdrvChild
*c
)
188 /* Normal success path */
189 ret
= bdrv_truncate(c
, 65536, false, PREALLOC_MODE_OFF
, 0, NULL
);
190 g_assert_cmpint(ret
, ==, 0);
192 /* Early error: Negative offset */
193 ret
= bdrv_truncate(c
, -2, false, PREALLOC_MODE_OFF
, 0, NULL
);
194 g_assert_cmpint(ret
, ==, -EINVAL
);
196 /* Error: Read-only image */
197 c
->bs
->read_only
= true;
198 c
->bs
->open_flags
&= ~BDRV_O_RDWR
;
200 ret
= bdrv_truncate(c
, 65536, false, PREALLOC_MODE_OFF
, 0, NULL
);
201 g_assert_cmpint(ret
, ==, -EACCES
);
203 c
->bs
->read_only
= false;
204 c
->bs
->open_flags
|= BDRV_O_RDWR
;
207 static void test_sync_op_block_status(BdrvChild
*c
)
212 /* Normal success path */
213 ret
= bdrv_is_allocated(c
->bs
, 0, 65536, &n
);
214 g_assert_cmpint(ret
, ==, 0);
216 /* Early success: No driver support */
217 bdrv_test
.bdrv_co_block_status
= NULL
;
218 ret
= bdrv_is_allocated(c
->bs
, 0, 65536, &n
);
219 g_assert_cmpint(ret
, ==, 1);
221 /* Early success: bytes = 0 */
222 ret
= bdrv_is_allocated(c
->bs
, 0, 0, &n
);
223 g_assert_cmpint(ret
, ==, 0);
225 /* Early success: Offset > image size*/
226 ret
= bdrv_is_allocated(c
->bs
, 0x1000000, 0x1000000, &n
);
227 g_assert_cmpint(ret
, ==, 0);
230 static void test_sync_op_flush(BdrvChild
*c
)
234 /* Normal success path */
235 ret
= bdrv_flush(c
->bs
);
236 g_assert_cmpint(ret
, ==, 0);
238 /* Early success: Read-only image */
239 c
->bs
->read_only
= true;
240 c
->bs
->open_flags
&= ~BDRV_O_RDWR
;
242 ret
= bdrv_flush(c
->bs
);
243 g_assert_cmpint(ret
, ==, 0);
245 c
->bs
->read_only
= false;
246 c
->bs
->open_flags
|= BDRV_O_RDWR
;
249 static void test_sync_op_blk_flush(BlockBackend
*blk
)
251 BlockDriverState
*bs
= blk_bs(blk
);
254 /* Normal success path */
255 ret
= blk_flush(blk
);
256 g_assert_cmpint(ret
, ==, 0);
258 /* Early success: Read-only image */
259 bs
->read_only
= true;
260 bs
->open_flags
&= ~BDRV_O_RDWR
;
262 ret
= blk_flush(blk
);
263 g_assert_cmpint(ret
, ==, 0);
265 bs
->read_only
= false;
266 bs
->open_flags
|= BDRV_O_RDWR
;
269 static void test_sync_op_check(BdrvChild
*c
)
271 BdrvCheckResult result
;
274 /* Error: Driver does not implement check */
275 ret
= bdrv_check(c
->bs
, &result
, 0);
276 g_assert_cmpint(ret
, ==, -ENOTSUP
);
279 static void test_sync_op_invalidate_cache(BdrvChild
*c
)
281 /* Early success: Image is not inactive */
282 bdrv_invalidate_cache(c
->bs
, NULL
);
286 typedef struct SyncOpTest
{
288 void (*fn
)(BdrvChild
*c
);
289 void (*blkfn
)(BlockBackend
*blk
);
292 const SyncOpTest sync_op_tests
[] = {
294 .name
= "/sync-op/pread",
295 .fn
= test_sync_op_pread
,
296 .blkfn
= test_sync_op_blk_pread
,
298 .name
= "/sync-op/pwrite",
299 .fn
= test_sync_op_pwrite
,
300 .blkfn
= test_sync_op_blk_pwrite
,
302 .name
= "/sync-op/load_vmstate",
303 .fn
= test_sync_op_load_vmstate
,
305 .name
= "/sync-op/save_vmstate",
306 .fn
= test_sync_op_save_vmstate
,
308 .name
= "/sync-op/pdiscard",
309 .fn
= test_sync_op_pdiscard
,
310 .blkfn
= test_sync_op_blk_pdiscard
,
312 .name
= "/sync-op/truncate",
313 .fn
= test_sync_op_truncate
,
315 .name
= "/sync-op/block_status",
316 .fn
= test_sync_op_block_status
,
318 .name
= "/sync-op/flush",
319 .fn
= test_sync_op_flush
,
320 .blkfn
= test_sync_op_blk_flush
,
322 .name
= "/sync-op/check",
323 .fn
= test_sync_op_check
,
325 .name
= "/sync-op/invalidate_cache",
326 .fn
= test_sync_op_invalidate_cache
,
330 /* Test synchronous operations that run in a different iothread, so we have to
331 * poll for the coroutine there to return. */
332 static void test_sync_op(const void *opaque
)
334 const SyncOpTest
*t
= opaque
;
335 IOThread
*iothread
= iothread_new();
336 AioContext
*ctx
= iothread_get_aio_context(iothread
);
338 BlockDriverState
*bs
;
341 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
, BLK_PERM_ALL
);
342 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
343 bs
->total_sectors
= 65536 / BDRV_SECTOR_SIZE
;
344 blk_insert_bs(blk
, bs
, &error_abort
);
345 c
= QLIST_FIRST(&bs
->parents
);
347 blk_set_aio_context(blk
, ctx
, &error_abort
);
348 aio_context_acquire(ctx
);
353 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
354 aio_context_release(ctx
);
360 typedef struct TestBlockJob
{
362 bool should_complete
;
366 static int test_job_prepare(Job
*job
)
368 g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
372 static int coroutine_fn
test_job_run(Job
*job
, Error
**errp
)
374 TestBlockJob
*s
= container_of(job
, TestBlockJob
, common
.job
);
376 job_transition_to_ready(&s
->common
.job
);
377 while (!s
->should_complete
) {
379 g_assert(qemu_get_current_aio_context() == job
->aio_context
);
381 /* Avoid job_sleep_ns() because it marks the job as !busy. We want to
382 * emulate some actual activity (probably some I/O) here so that the
383 * drain involved in AioContext switches has to wait for this activity
385 qemu_co_sleep_ns(QEMU_CLOCK_REALTIME
, 1000000);
387 job_pause_point(&s
->common
.job
);
390 g_assert(qemu_get_current_aio_context() == job
->aio_context
);
394 static void test_job_complete(Job
*job
, Error
**errp
)
396 TestBlockJob
*s
= container_of(job
, TestBlockJob
, common
.job
);
397 s
->should_complete
= true;
400 BlockJobDriver test_job_driver
= {
402 .instance_size
= sizeof(TestBlockJob
),
403 .free
= block_job_free
,
404 .user_resume
= block_job_user_resume
,
406 .complete
= test_job_complete
,
407 .prepare
= test_job_prepare
,
411 static void test_attach_blockjob(void)
413 IOThread
*iothread
= iothread_new();
414 AioContext
*ctx
= iothread_get_aio_context(iothread
);
416 BlockDriverState
*bs
;
419 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
, BLK_PERM_ALL
);
420 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
421 blk_insert_bs(blk
, bs
, &error_abort
);
423 tjob
= block_job_create("job0", &test_job_driver
, NULL
, bs
,
425 0, 0, NULL
, NULL
, &error_abort
);
426 job_start(&tjob
->common
.job
);
428 while (tjob
->n
== 0) {
429 aio_poll(qemu_get_aio_context(), false);
432 blk_set_aio_context(blk
, ctx
, &error_abort
);
435 while (tjob
->n
== 0) {
436 aio_poll(qemu_get_aio_context(), false);
439 aio_context_acquire(ctx
);
440 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
441 aio_context_release(ctx
);
444 while (tjob
->n
== 0) {
445 aio_poll(qemu_get_aio_context(), false);
448 blk_set_aio_context(blk
, ctx
, &error_abort
);
451 while (tjob
->n
== 0) {
452 aio_poll(qemu_get_aio_context(), false);
455 aio_context_acquire(ctx
);
456 job_complete_sync(&tjob
->common
.job
, &error_abort
);
457 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
458 aio_context_release(ctx
);
465 * Test that changing the AioContext for one node in a tree (here through blk)
466 * changes all other nodes as well:
470 * | bs_verify [blkverify]
473 * bs_a [bdrv_test] bs_b [bdrv_test]
476 static void test_propagate_basic(void)
478 IOThread
*iothread
= iothread_new();
479 AioContext
*ctx
= iothread_get_aio_context(iothread
);
480 AioContext
*main_ctx
;
482 BlockDriverState
*bs_a
, *bs_b
, *bs_verify
;
486 * Create bs_a and its BlockBackend. We cannot take the RESIZE
487 * permission because blkverify will not share it on the test
490 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
& ~BLK_PERM_RESIZE
,
492 bs_a
= bdrv_new_open_driver(&bdrv_test
, "bs_a", BDRV_O_RDWR
, &error_abort
);
493 blk_insert_bs(blk
, bs_a
, &error_abort
);
496 bs_b
= bdrv_new_open_driver(&bdrv_test
, "bs_b", BDRV_O_RDWR
, &error_abort
);
498 /* Create blkverify filter that references both bs_a and bs_b */
499 options
= qdict_new();
500 qdict_put_str(options
, "driver", "blkverify");
501 qdict_put_str(options
, "test", "bs_a");
502 qdict_put_str(options
, "raw", "bs_b");
504 bs_verify
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
506 /* Switch the AioContext */
507 blk_set_aio_context(blk
, ctx
, &error_abort
);
508 g_assert(blk_get_aio_context(blk
) == ctx
);
509 g_assert(bdrv_get_aio_context(bs_a
) == ctx
);
510 g_assert(bdrv_get_aio_context(bs_verify
) == ctx
);
511 g_assert(bdrv_get_aio_context(bs_b
) == ctx
);
513 /* Switch the AioContext back */
514 main_ctx
= qemu_get_aio_context();
515 aio_context_acquire(ctx
);
516 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
517 aio_context_release(ctx
);
518 g_assert(blk_get_aio_context(blk
) == main_ctx
);
519 g_assert(bdrv_get_aio_context(bs_a
) == main_ctx
);
520 g_assert(bdrv_get_aio_context(bs_verify
) == main_ctx
);
521 g_assert(bdrv_get_aio_context(bs_b
) == main_ctx
);
523 bdrv_unref(bs_verify
);
530 * Test that diamonds in the graph don't lead to endless recursion:
534 * bs_verify [blkverify]
537 * bs_b [raw] bs_c[raw]
542 static void test_propagate_diamond(void)
544 IOThread
*iothread
= iothread_new();
545 AioContext
*ctx
= iothread_get_aio_context(iothread
);
546 AioContext
*main_ctx
;
548 BlockDriverState
*bs_a
, *bs_b
, *bs_c
, *bs_verify
;
552 bs_a
= bdrv_new_open_driver(&bdrv_test
, "bs_a", BDRV_O_RDWR
, &error_abort
);
554 /* Create bs_b and bc_c */
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_b");
559 bs_b
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
561 options
= qdict_new();
562 qdict_put_str(options
, "driver", "raw");
563 qdict_put_str(options
, "file", "bs_a");
564 qdict_put_str(options
, "node-name", "bs_c");
565 bs_c
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
567 /* Create blkverify filter that references both bs_b and bs_c */
568 options
= qdict_new();
569 qdict_put_str(options
, "driver", "blkverify");
570 qdict_put_str(options
, "test", "bs_b");
571 qdict_put_str(options
, "raw", "bs_c");
573 bs_verify
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
575 * Do not take the RESIZE permission: This would require the same
576 * from bs_c and thus from bs_a; however, blkverify will not share
577 * it on bs_b, and thus it will not be available for bs_a.
579 blk
= blk_new(qemu_get_aio_context(), BLK_PERM_ALL
& ~BLK_PERM_RESIZE
,
581 blk_insert_bs(blk
, bs_verify
, &error_abort
);
583 /* Switch the AioContext */
584 blk_set_aio_context(blk
, ctx
, &error_abort
);
585 g_assert(blk_get_aio_context(blk
) == ctx
);
586 g_assert(bdrv_get_aio_context(bs_verify
) == ctx
);
587 g_assert(bdrv_get_aio_context(bs_a
) == ctx
);
588 g_assert(bdrv_get_aio_context(bs_b
) == ctx
);
589 g_assert(bdrv_get_aio_context(bs_c
) == ctx
);
591 /* Switch the AioContext back */
592 main_ctx
= qemu_get_aio_context();
593 aio_context_acquire(ctx
);
594 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
595 aio_context_release(ctx
);
596 g_assert(blk_get_aio_context(blk
) == main_ctx
);
597 g_assert(bdrv_get_aio_context(bs_verify
) == main_ctx
);
598 g_assert(bdrv_get_aio_context(bs_a
) == main_ctx
);
599 g_assert(bdrv_get_aio_context(bs_b
) == main_ctx
);
600 g_assert(bdrv_get_aio_context(bs_c
) == main_ctx
);
603 bdrv_unref(bs_verify
);
609 static void test_propagate_mirror(void)
611 IOThread
*iothread
= iothread_new();
612 AioContext
*ctx
= iothread_get_aio_context(iothread
);
613 AioContext
*main_ctx
= qemu_get_aio_context();
614 BlockDriverState
*src
, *target
, *filter
;
617 Error
*local_err
= NULL
;
619 /* Create src and target*/
620 src
= bdrv_new_open_driver(&bdrv_test
, "src", BDRV_O_RDWR
, &error_abort
);
621 target
= bdrv_new_open_driver(&bdrv_test
, "target", BDRV_O_RDWR
,
624 /* Start a mirror job */
625 mirror_start("job0", src
, target
, NULL
, JOB_DEFAULT
, 0, 0, 0,
626 MIRROR_SYNC_MODE_NONE
, MIRROR_OPEN_BACKING_CHAIN
, false,
627 BLOCKDEV_ON_ERROR_REPORT
, BLOCKDEV_ON_ERROR_REPORT
,
628 false, "filter_node", MIRROR_COPY_MODE_BACKGROUND
,
630 job
= job_get("job0");
631 filter
= bdrv_find_node("filter_node");
633 /* Change the AioContext of src */
634 bdrv_try_set_aio_context(src
, ctx
, &error_abort
);
635 g_assert(bdrv_get_aio_context(src
) == ctx
);
636 g_assert(bdrv_get_aio_context(target
) == ctx
);
637 g_assert(bdrv_get_aio_context(filter
) == ctx
);
638 g_assert(job
->aio_context
== ctx
);
640 /* Change the AioContext of target */
641 aio_context_acquire(ctx
);
642 bdrv_try_set_aio_context(target
, main_ctx
, &error_abort
);
643 aio_context_release(ctx
);
644 g_assert(bdrv_get_aio_context(src
) == main_ctx
);
645 g_assert(bdrv_get_aio_context(target
) == main_ctx
);
646 g_assert(bdrv_get_aio_context(filter
) == main_ctx
);
648 /* With a BlockBackend on src, changing target must fail */
649 blk
= blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL
);
650 blk_insert_bs(blk
, src
, &error_abort
);
652 bdrv_try_set_aio_context(target
, ctx
, &local_err
);
653 error_free_or_abort(&local_err
);
655 g_assert(blk_get_aio_context(blk
) == main_ctx
);
656 g_assert(bdrv_get_aio_context(src
) == main_ctx
);
657 g_assert(bdrv_get_aio_context(target
) == main_ctx
);
658 g_assert(bdrv_get_aio_context(filter
) == main_ctx
);
660 /* ...unless we explicitly allow it */
661 aio_context_acquire(ctx
);
662 blk_set_allow_aio_context_change(blk
, true);
663 bdrv_try_set_aio_context(target
, ctx
, &error_abort
);
664 aio_context_release(ctx
);
666 g_assert(blk_get_aio_context(blk
) == ctx
);
667 g_assert(bdrv_get_aio_context(src
) == ctx
);
668 g_assert(bdrv_get_aio_context(target
) == ctx
);
669 g_assert(bdrv_get_aio_context(filter
) == ctx
);
671 job_cancel_sync_all();
673 aio_context_acquire(ctx
);
674 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
675 bdrv_try_set_aio_context(target
, main_ctx
, &error_abort
);
676 aio_context_release(ctx
);
683 static void test_attach_second_node(void)
685 IOThread
*iothread
= iothread_new();
686 AioContext
*ctx
= iothread_get_aio_context(iothread
);
687 AioContext
*main_ctx
= qemu_get_aio_context();
689 BlockDriverState
*bs
, *filter
;
692 blk
= blk_new(ctx
, BLK_PERM_ALL
, BLK_PERM_ALL
);
693 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
694 blk_insert_bs(blk
, bs
, &error_abort
);
696 options
= qdict_new();
697 qdict_put_str(options
, "driver", "raw");
698 qdict_put_str(options
, "file", "base");
700 filter
= bdrv_open(NULL
, NULL
, options
, BDRV_O_RDWR
, &error_abort
);
701 g_assert(blk_get_aio_context(blk
) == ctx
);
702 g_assert(bdrv_get_aio_context(bs
) == ctx
);
703 g_assert(bdrv_get_aio_context(filter
) == ctx
);
705 aio_context_acquire(ctx
);
706 blk_set_aio_context(blk
, main_ctx
, &error_abort
);
707 aio_context_release(ctx
);
708 g_assert(blk_get_aio_context(blk
) == main_ctx
);
709 g_assert(bdrv_get_aio_context(bs
) == main_ctx
);
710 g_assert(bdrv_get_aio_context(filter
) == main_ctx
);
717 static void test_attach_preserve_blk_ctx(void)
719 IOThread
*iothread
= iothread_new();
720 AioContext
*ctx
= iothread_get_aio_context(iothread
);
722 BlockDriverState
*bs
;
724 blk
= blk_new(ctx
, BLK_PERM_ALL
, BLK_PERM_ALL
);
725 bs
= bdrv_new_open_driver(&bdrv_test
, "base", BDRV_O_RDWR
, &error_abort
);
726 bs
->total_sectors
= 65536 / BDRV_SECTOR_SIZE
;
728 /* Add node to BlockBackend that has an iothread context assigned */
729 blk_insert_bs(blk
, bs
, &error_abort
);
730 g_assert(blk_get_aio_context(blk
) == ctx
);
731 g_assert(bdrv_get_aio_context(bs
) == ctx
);
733 /* Remove the node again */
734 aio_context_acquire(ctx
);
736 aio_context_release(ctx
);
737 g_assert(blk_get_aio_context(blk
) == ctx
);
738 g_assert(bdrv_get_aio_context(bs
) == qemu_get_aio_context());
740 /* Re-attach the node */
741 blk_insert_bs(blk
, bs
, &error_abort
);
742 g_assert(blk_get_aio_context(blk
) == ctx
);
743 g_assert(bdrv_get_aio_context(bs
) == ctx
);
745 aio_context_acquire(ctx
);
746 blk_set_aio_context(blk
, qemu_get_aio_context(), &error_abort
);
747 aio_context_release(ctx
);
752 int main(int argc
, char **argv
)
757 qemu_init_main_loop(&error_abort
);
759 g_test_init(&argc
, &argv
, NULL
);
761 for (i
= 0; i
< ARRAY_SIZE(sync_op_tests
); i
++) {
762 const SyncOpTest
*t
= &sync_op_tests
[i
];
763 g_test_add_data_func(t
->name
, t
, test_sync_op
);
766 g_test_add_func("/attach/blockjob", test_attach_blockjob
);
767 g_test_add_func("/attach/second_node", test_attach_second_node
);
768 g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx
);
769 g_test_add_func("/propagate/basic", test_propagate_basic
);
770 g_test_add_func("/propagate/diamond", test_propagate_diamond
);
771 g_test_add_func("/propagate/mirror", test_propagate_mirror
);