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