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