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