xref: /qemu/tests/unit/test-block-iothread.c (revision d0fb9657)
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_prwv(BlockDriverState *bs,
35                                           uint64_t offset, uint64_t bytes,
36                                           QEMUIOVector *qiov, int flags)
37 {
38     return 0;
39 }
40 
41 static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
42                                               int64_t offset, int bytes)
43 {
44     return 0;
45 }
46 
47 static int coroutine_fn
48 bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
49                       PreallocMode prealloc, BdrvRequestFlags flags,
50                       Error **errp)
51 {
52     return 0;
53 }
54 
55 static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
56                                                   bool want_zero,
57                                                   int64_t offset, int64_t count,
58                                                   int64_t *pnum, int64_t *map,
59                                                   BlockDriverState **file)
60 {
61     *pnum = count;
62     return 0;
63 }
64 
65 static BlockDriver bdrv_test = {
66     .format_name            = "test",
67     .instance_size          = 1,
68 
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,
74 };
75 
76 static void test_sync_op_pread(BdrvChild *c)
77 {
78     uint8_t buf[512];
79     int ret;
80 
81     /* Success */
82     ret = bdrv_pread(c, 0, buf, sizeof(buf));
83     g_assert_cmpint(ret, ==, 512);
84 
85     /* Early error: Negative offset */
86     ret = bdrv_pread(c, -2, buf, sizeof(buf));
87     g_assert_cmpint(ret, ==, -EIO);
88 }
89 
90 static void test_sync_op_pwrite(BdrvChild *c)
91 {
92     uint8_t buf[512] = { 0 };
93     int ret;
94 
95     /* Success */
96     ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
97     g_assert_cmpint(ret, ==, 512);
98 
99     /* Early error: Negative offset */
100     ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
101     g_assert_cmpint(ret, ==, -EIO);
102 }
103 
104 static void test_sync_op_blk_pread(BlockBackend *blk)
105 {
106     uint8_t buf[512];
107     int ret;
108 
109     /* Success */
110     ret = blk_pread(blk, 0, buf, sizeof(buf));
111     g_assert_cmpint(ret, ==, 512);
112 
113     /* Early error: Negative offset */
114     ret = blk_pread(blk, -2, buf, sizeof(buf));
115     g_assert_cmpint(ret, ==, -EIO);
116 }
117 
118 static void test_sync_op_blk_pwrite(BlockBackend *blk)
119 {
120     uint8_t buf[512] = { 0 };
121     int ret;
122 
123     /* Success */
124     ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
125     g_assert_cmpint(ret, ==, 512);
126 
127     /* Early error: Negative offset */
128     ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
129     g_assert_cmpint(ret, ==, -EIO);
130 }
131 
132 static void test_sync_op_load_vmstate(BdrvChild *c)
133 {
134     uint8_t buf[512];
135     int ret;
136 
137     /* Error: Driver does not support snapshots */
138     ret = bdrv_load_vmstate(c->bs, buf, 0, sizeof(buf));
139     g_assert_cmpint(ret, ==, -ENOTSUP);
140 }
141 
142 static void test_sync_op_save_vmstate(BdrvChild *c)
143 {
144     uint8_t buf[512] = { 0 };
145     int ret;
146 
147     /* Error: Driver does not support snapshots */
148     ret = bdrv_save_vmstate(c->bs, buf, 0, sizeof(buf));
149     g_assert_cmpint(ret, ==, -ENOTSUP);
150 }
151 
152 static void test_sync_op_pdiscard(BdrvChild *c)
153 {
154     int ret;
155 
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);
160 
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);
165 
166     /* Early error: Negative offset */
167     ret = bdrv_pdiscard(c, -2, 512);
168     g_assert_cmpint(ret, ==, -EIO);
169 }
170 
171 static void test_sync_op_blk_pdiscard(BlockBackend *blk)
172 {
173     int ret;
174 
175     /* Early success: UNMAP not supported */
176     ret = blk_pdiscard(blk, 0, 512);
177     g_assert_cmpint(ret, ==, 0);
178 
179     /* Early error: Negative offset */
180     ret = blk_pdiscard(blk, -2, 512);
181     g_assert_cmpint(ret, ==, -EIO);
182 }
183 
184 static void test_sync_op_truncate(BdrvChild *c)
185 {
186     int ret;
187 
188     /* Normal success path */
189     ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
190     g_assert_cmpint(ret, ==, 0);
191 
192     /* Early error: Negative offset */
193     ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
194     g_assert_cmpint(ret, ==, -EINVAL);
195 
196     /* Error: Read-only image */
197     c->bs->read_only = true;
198     c->bs->open_flags &= ~BDRV_O_RDWR;
199 
200     ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
201     g_assert_cmpint(ret, ==, -EACCES);
202 
203     c->bs->read_only = false;
204     c->bs->open_flags |= BDRV_O_RDWR;
205 }
206 
207 static void test_sync_op_block_status(BdrvChild *c)
208 {
209     int ret;
210     int64_t n;
211 
212     /* Normal success path */
213     ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
214     g_assert_cmpint(ret, ==, 0);
215 
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);
220 
221     /* Early success: bytes = 0 */
222     ret = bdrv_is_allocated(c->bs, 0, 0, &n);
223     g_assert_cmpint(ret, ==, 0);
224 
225     /* Early success: Offset > image size*/
226     ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n);
227     g_assert_cmpint(ret, ==, 0);
228 }
229 
230 static void test_sync_op_flush(BdrvChild *c)
231 {
232     int ret;
233 
234     /* Normal success path */
235     ret = bdrv_flush(c->bs);
236     g_assert_cmpint(ret, ==, 0);
237 
238     /* Early success: Read-only image */
239     c->bs->read_only = true;
240     c->bs->open_flags &= ~BDRV_O_RDWR;
241 
242     ret = bdrv_flush(c->bs);
243     g_assert_cmpint(ret, ==, 0);
244 
245     c->bs->read_only = false;
246     c->bs->open_flags |= BDRV_O_RDWR;
247 }
248 
249 static void test_sync_op_blk_flush(BlockBackend *blk)
250 {
251     BlockDriverState *bs = blk_bs(blk);
252     int ret;
253 
254     /* Normal success path */
255     ret = blk_flush(blk);
256     g_assert_cmpint(ret, ==, 0);
257 
258     /* Early success: Read-only image */
259     bs->read_only = true;
260     bs->open_flags &= ~BDRV_O_RDWR;
261 
262     ret = blk_flush(blk);
263     g_assert_cmpint(ret, ==, 0);
264 
265     bs->read_only = false;
266     bs->open_flags |= BDRV_O_RDWR;
267 }
268 
269 static void test_sync_op_check(BdrvChild *c)
270 {
271     BdrvCheckResult result;
272     int ret;
273 
274     /* Error: Driver does not implement check */
275     ret = bdrv_check(c->bs, &result, 0);
276     g_assert_cmpint(ret, ==, -ENOTSUP);
277 }
278 
279 static void test_sync_op_invalidate_cache(BdrvChild *c)
280 {
281     /* Early success: Image is not inactive */
282     bdrv_invalidate_cache(c->bs, NULL);
283 }
284 
285 
286 typedef struct SyncOpTest {
287     const char *name;
288     void (*fn)(BdrvChild *c);
289     void (*blkfn)(BlockBackend *blk);
290 } SyncOpTest;
291 
292 const SyncOpTest sync_op_tests[] = {
293     {
294         .name   = "/sync-op/pread",
295         .fn     = test_sync_op_pread,
296         .blkfn  = test_sync_op_blk_pread,
297     }, {
298         .name   = "/sync-op/pwrite",
299         .fn     = test_sync_op_pwrite,
300         .blkfn  = test_sync_op_blk_pwrite,
301     }, {
302         .name   = "/sync-op/load_vmstate",
303         .fn     = test_sync_op_load_vmstate,
304     }, {
305         .name   = "/sync-op/save_vmstate",
306         .fn     = test_sync_op_save_vmstate,
307     }, {
308         .name   = "/sync-op/pdiscard",
309         .fn     = test_sync_op_pdiscard,
310         .blkfn  = test_sync_op_blk_pdiscard,
311     }, {
312         .name   = "/sync-op/truncate",
313         .fn     = test_sync_op_truncate,
314     }, {
315         .name   = "/sync-op/block_status",
316         .fn     = test_sync_op_block_status,
317     }, {
318         .name   = "/sync-op/flush",
319         .fn     = test_sync_op_flush,
320         .blkfn  = test_sync_op_blk_flush,
321     }, {
322         .name   = "/sync-op/check",
323         .fn     = test_sync_op_check,
324     }, {
325         .name   = "/sync-op/invalidate_cache",
326         .fn     = test_sync_op_invalidate_cache,
327     },
328 };
329 
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)
333 {
334     const SyncOpTest *t = opaque;
335     IOThread *iothread = iothread_new();
336     AioContext *ctx = iothread_get_aio_context(iothread);
337     BlockBackend *blk;
338     BlockDriverState *bs;
339     BdrvChild *c;
340 
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);
346 
347     blk_set_aio_context(blk, ctx, &error_abort);
348     aio_context_acquire(ctx);
349     t->fn(c);
350     if (t->blkfn) {
351         t->blkfn(blk);
352     }
353     blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
354     aio_context_release(ctx);
355 
356     bdrv_unref(bs);
357     blk_unref(blk);
358 }
359 
360 typedef struct TestBlockJob {
361     BlockJob common;
362     bool should_complete;
363     int n;
364 } TestBlockJob;
365 
366 static int test_job_prepare(Job *job)
367 {
368     g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
369     return 0;
370 }
371 
372 static int coroutine_fn test_job_run(Job *job, Error **errp)
373 {
374     TestBlockJob *s = container_of(job, TestBlockJob, common.job);
375 
376     job_transition_to_ready(&s->common.job);
377     while (!s->should_complete) {
378         s->n++;
379         g_assert(qemu_get_current_aio_context() == job->aio_context);
380 
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
384          * to stop. */
385         qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000);
386 
387         job_pause_point(&s->common.job);
388     }
389 
390     g_assert(qemu_get_current_aio_context() == job->aio_context);
391     return 0;
392 }
393 
394 static void test_job_complete(Job *job, Error **errp)
395 {
396     TestBlockJob *s = container_of(job, TestBlockJob, common.job);
397     s->should_complete = true;
398 }
399 
400 BlockJobDriver test_job_driver = {
401     .job_driver = {
402         .instance_size  = sizeof(TestBlockJob),
403         .free           = block_job_free,
404         .user_resume    = block_job_user_resume,
405         .run            = test_job_run,
406         .complete       = test_job_complete,
407         .prepare        = test_job_prepare,
408     },
409 };
410 
411 static void test_attach_blockjob(void)
412 {
413     IOThread *iothread = iothread_new();
414     AioContext *ctx = iothread_get_aio_context(iothread);
415     BlockBackend *blk;
416     BlockDriverState *bs;
417     TestBlockJob *tjob;
418 
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);
422 
423     tjob = block_job_create("job0", &test_job_driver, NULL, bs,
424                             0, BLK_PERM_ALL,
425                             0, 0, NULL, NULL, &error_abort);
426     job_start(&tjob->common.job);
427 
428     while (tjob->n == 0) {
429         aio_poll(qemu_get_aio_context(), false);
430     }
431 
432     blk_set_aio_context(blk, ctx, &error_abort);
433 
434     tjob->n = 0;
435     while (tjob->n == 0) {
436         aio_poll(qemu_get_aio_context(), false);
437     }
438 
439     aio_context_acquire(ctx);
440     blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
441     aio_context_release(ctx);
442 
443     tjob->n = 0;
444     while (tjob->n == 0) {
445         aio_poll(qemu_get_aio_context(), false);
446     }
447 
448     blk_set_aio_context(blk, ctx, &error_abort);
449 
450     tjob->n = 0;
451     while (tjob->n == 0) {
452         aio_poll(qemu_get_aio_context(), false);
453     }
454 
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);
459 
460     bdrv_unref(bs);
461     blk_unref(blk);
462 }
463 
464 /*
465  * Test that changing the AioContext for one node in a tree (here through blk)
466  * changes all other nodes as well:
467  *
468  *  blk
469  *   |
470  *   |  bs_verify [blkverify]
471  *   |   /               \
472  *   |  /                 \
473  *  bs_a [bdrv_test]    bs_b [bdrv_test]
474  *
475  */
476 static void test_propagate_basic(void)
477 {
478     IOThread *iothread = iothread_new();
479     AioContext *ctx = iothread_get_aio_context(iothread);
480     AioContext *main_ctx;
481     BlockBackend *blk;
482     BlockDriverState *bs_a, *bs_b, *bs_verify;
483     QDict *options;
484 
485     /*
486      * Create bs_a and its BlockBackend.  We cannot take the RESIZE
487      * permission because blkverify will not share it on the test
488      * image.
489      */
490     blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
491                   BLK_PERM_ALL);
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);
494 
495     /* Create bs_b */
496     bs_b = bdrv_new_open_driver(&bdrv_test, "bs_b", BDRV_O_RDWR, &error_abort);
497 
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");
503 
504     bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
505 
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);
512 
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);
522 
523     bdrv_unref(bs_verify);
524     bdrv_unref(bs_b);
525     bdrv_unref(bs_a);
526     blk_unref(blk);
527 }
528 
529 /*
530  * Test that diamonds in the graph don't lead to endless recursion:
531  *
532  *              blk
533  *               |
534  *      bs_verify [blkverify]
535  *       /              \
536  *      /                \
537  *   bs_b [raw]         bs_c[raw]
538  *      \                /
539  *       \              /
540  *       bs_a [bdrv_test]
541  */
542 static void test_propagate_diamond(void)
543 {
544     IOThread *iothread = iothread_new();
545     AioContext *ctx = iothread_get_aio_context(iothread);
546     AioContext *main_ctx;
547     BlockBackend *blk;
548     BlockDriverState *bs_a, *bs_b, *bs_c, *bs_verify;
549     QDict *options;
550 
551     /* Create bs_a */
552     bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
553 
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);
560 
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);
566 
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");
572 
573     bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
574     /*
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.
578      */
579     blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
580                   BLK_PERM_ALL);
581     blk_insert_bs(blk, bs_verify, &error_abort);
582 
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);
590 
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);
601 
602     blk_unref(blk);
603     bdrv_unref(bs_verify);
604     bdrv_unref(bs_c);
605     bdrv_unref(bs_b);
606     bdrv_unref(bs_a);
607 }
608 
609 static void test_propagate_mirror(void)
610 {
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;
615     BlockBackend *blk;
616     Job *job;
617     Error *local_err = NULL;
618 
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,
622                                   &error_abort);
623 
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,
629                  &error_abort);
630     job = job_get("job0");
631     filter = bdrv_find_node("filter_node");
632 
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);
639 
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);
647 
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);
651 
652     bdrv_try_set_aio_context(target, ctx, &local_err);
653     error_free_or_abort(&local_err);
654 
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);
659 
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);
665 
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);
670 
671     job_cancel_sync_all();
672 
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);
677 
678     blk_unref(blk);
679     bdrv_unref(src);
680     bdrv_unref(target);
681 }
682 
683 static void test_attach_second_node(void)
684 {
685     IOThread *iothread = iothread_new();
686     AioContext *ctx = iothread_get_aio_context(iothread);
687     AioContext *main_ctx = qemu_get_aio_context();
688     BlockBackend *blk;
689     BlockDriverState *bs, *filter;
690     QDict *options;
691 
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);
695 
696     options = qdict_new();
697     qdict_put_str(options, "driver", "raw");
698     qdict_put_str(options, "file", "base");
699 
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);
704 
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);
711 
712     bdrv_unref(filter);
713     bdrv_unref(bs);
714     blk_unref(blk);
715 }
716 
717 static void test_attach_preserve_blk_ctx(void)
718 {
719     IOThread *iothread = iothread_new();
720     AioContext *ctx = iothread_get_aio_context(iothread);
721     BlockBackend *blk;
722     BlockDriverState *bs;
723 
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;
727 
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);
732 
733     /* Remove the node again */
734     aio_context_acquire(ctx);
735     blk_remove_bs(blk);
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());
739 
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);
744 
745     aio_context_acquire(ctx);
746     blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
747     aio_context_release(ctx);
748     bdrv_unref(bs);
749     blk_unref(blk);
750 }
751 
752 int main(int argc, char **argv)
753 {
754     int i;
755 
756     bdrv_init();
757     qemu_init_main_loop(&error_abort);
758 
759     g_test_init(&argc, &argv, NULL);
760 
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);
764     }
765 
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);
772 
773     return g_test_run();
774 }
775