xref: /qemu/tests/unit/test-block-iothread.c (revision 336d354b)
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 }
778