xref: /qemu/tests/unit/test-block-iothread.c (revision b2a3cbb8)
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     WITH_JOB_LOCK_GUARD() {
586         job_complete_sync_locked(&tjob->common.job, &error_abort);
587     }
588     aio_context_acquire(ctx);
589     blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
590     aio_context_release(ctx);
591 
592     bdrv_unref(bs);
593     blk_unref(blk);
594 }
595 
596 /*
597  * Test that changing the AioContext for one node in a tree (here through blk)
598  * changes all other nodes as well:
599  *
600  *  blk
601  *   |
602  *   |  bs_verify [blkverify]
603  *   |   /               \
604  *   |  /                 \
605  *  bs_a [bdrv_test]    bs_b [bdrv_test]
606  *
607  */
608 static void test_propagate_basic(void)
609 {
610     IOThread *iothread = iothread_new();
611     AioContext *ctx = iothread_get_aio_context(iothread);
612     AioContext *main_ctx;
613     BlockBackend *blk;
614     BlockDriverState *bs_a, *bs_b, *bs_verify;
615     QDict *options;
616 
617     /*
618      * Create bs_a and its BlockBackend.  We cannot take the RESIZE
619      * permission because blkverify will not share it on the test
620      * image.
621      */
622     blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
623                   BLK_PERM_ALL);
624     bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
625     blk_insert_bs(blk, bs_a, &error_abort);
626 
627     /* Create bs_b */
628     bs_b = bdrv_new_open_driver(&bdrv_test, "bs_b", BDRV_O_RDWR, &error_abort);
629 
630     /* Create blkverify filter that references both bs_a and bs_b */
631     options = qdict_new();
632     qdict_put_str(options, "driver", "blkverify");
633     qdict_put_str(options, "test", "bs_a");
634     qdict_put_str(options, "raw", "bs_b");
635 
636     bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
637 
638     /* Switch the AioContext */
639     blk_set_aio_context(blk, ctx, &error_abort);
640     g_assert(blk_get_aio_context(blk) == ctx);
641     g_assert(bdrv_get_aio_context(bs_a) == ctx);
642     g_assert(bdrv_get_aio_context(bs_verify) == ctx);
643     g_assert(bdrv_get_aio_context(bs_b) == ctx);
644 
645     /* Switch the AioContext back */
646     main_ctx = qemu_get_aio_context();
647     aio_context_acquire(ctx);
648     blk_set_aio_context(blk, main_ctx, &error_abort);
649     aio_context_release(ctx);
650     g_assert(blk_get_aio_context(blk) == main_ctx);
651     g_assert(bdrv_get_aio_context(bs_a) == main_ctx);
652     g_assert(bdrv_get_aio_context(bs_verify) == main_ctx);
653     g_assert(bdrv_get_aio_context(bs_b) == main_ctx);
654 
655     bdrv_unref(bs_verify);
656     bdrv_unref(bs_b);
657     bdrv_unref(bs_a);
658     blk_unref(blk);
659 }
660 
661 /*
662  * Test that diamonds in the graph don't lead to endless recursion:
663  *
664  *              blk
665  *               |
666  *      bs_verify [blkverify]
667  *       /              \
668  *      /                \
669  *   bs_b [raw]         bs_c[raw]
670  *      \                /
671  *       \              /
672  *       bs_a [bdrv_test]
673  */
674 static void test_propagate_diamond(void)
675 {
676     IOThread *iothread = iothread_new();
677     AioContext *ctx = iothread_get_aio_context(iothread);
678     AioContext *main_ctx;
679     BlockBackend *blk;
680     BlockDriverState *bs_a, *bs_b, *bs_c, *bs_verify;
681     QDict *options;
682 
683     /* Create bs_a */
684     bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
685 
686     /* Create bs_b and bc_c */
687     options = qdict_new();
688     qdict_put_str(options, "driver", "raw");
689     qdict_put_str(options, "file", "bs_a");
690     qdict_put_str(options, "node-name", "bs_b");
691     bs_b = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
692 
693     options = qdict_new();
694     qdict_put_str(options, "driver", "raw");
695     qdict_put_str(options, "file", "bs_a");
696     qdict_put_str(options, "node-name", "bs_c");
697     bs_c = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
698 
699     /* Create blkverify filter that references both bs_b and bs_c */
700     options = qdict_new();
701     qdict_put_str(options, "driver", "blkverify");
702     qdict_put_str(options, "test", "bs_b");
703     qdict_put_str(options, "raw", "bs_c");
704 
705     bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
706     /*
707      * Do not take the RESIZE permission: This would require the same
708      * from bs_c and thus from bs_a; however, blkverify will not share
709      * it on bs_b, and thus it will not be available for bs_a.
710      */
711     blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
712                   BLK_PERM_ALL);
713     blk_insert_bs(blk, bs_verify, &error_abort);
714 
715     /* Switch the AioContext */
716     blk_set_aio_context(blk, ctx, &error_abort);
717     g_assert(blk_get_aio_context(blk) == ctx);
718     g_assert(bdrv_get_aio_context(bs_verify) == ctx);
719     g_assert(bdrv_get_aio_context(bs_a) == ctx);
720     g_assert(bdrv_get_aio_context(bs_b) == ctx);
721     g_assert(bdrv_get_aio_context(bs_c) == ctx);
722 
723     /* Switch the AioContext back */
724     main_ctx = qemu_get_aio_context();
725     aio_context_acquire(ctx);
726     blk_set_aio_context(blk, main_ctx, &error_abort);
727     aio_context_release(ctx);
728     g_assert(blk_get_aio_context(blk) == main_ctx);
729     g_assert(bdrv_get_aio_context(bs_verify) == main_ctx);
730     g_assert(bdrv_get_aio_context(bs_a) == main_ctx);
731     g_assert(bdrv_get_aio_context(bs_b) == main_ctx);
732     g_assert(bdrv_get_aio_context(bs_c) == main_ctx);
733 
734     blk_unref(blk);
735     bdrv_unref(bs_verify);
736     bdrv_unref(bs_c);
737     bdrv_unref(bs_b);
738     bdrv_unref(bs_a);
739 }
740 
741 static void test_propagate_mirror(void)
742 {
743     IOThread *iothread = iothread_new();
744     AioContext *ctx = iothread_get_aio_context(iothread);
745     AioContext *main_ctx = qemu_get_aio_context();
746     BlockDriverState *src, *target, *filter;
747     BlockBackend *blk;
748     Job *job;
749     Error *local_err = NULL;
750 
751     /* Create src and target*/
752     src = bdrv_new_open_driver(&bdrv_test, "src", BDRV_O_RDWR, &error_abort);
753     target = bdrv_new_open_driver(&bdrv_test, "target", BDRV_O_RDWR,
754                                   &error_abort);
755 
756     /* Start a mirror job */
757     mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0,
758                  MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false,
759                  BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
760                  false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
761                  &error_abort);
762     WITH_JOB_LOCK_GUARD() {
763         job = job_get_locked("job0");
764     }
765     filter = bdrv_find_node("filter_node");
766 
767     /* Change the AioContext of src */
768     bdrv_try_change_aio_context(src, ctx, NULL, &error_abort);
769     g_assert(bdrv_get_aio_context(src) == ctx);
770     g_assert(bdrv_get_aio_context(target) == ctx);
771     g_assert(bdrv_get_aio_context(filter) == ctx);
772     g_assert(job->aio_context == ctx);
773 
774     /* Change the AioContext of target */
775     aio_context_acquire(ctx);
776     bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
777     aio_context_release(ctx);
778     g_assert(bdrv_get_aio_context(src) == main_ctx);
779     g_assert(bdrv_get_aio_context(target) == main_ctx);
780     g_assert(bdrv_get_aio_context(filter) == main_ctx);
781 
782     /* With a BlockBackend on src, changing target must fail */
783     blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
784     blk_insert_bs(blk, src, &error_abort);
785 
786     bdrv_try_change_aio_context(target, ctx, NULL, &local_err);
787     error_free_or_abort(&local_err);
788 
789     g_assert(blk_get_aio_context(blk) == main_ctx);
790     g_assert(bdrv_get_aio_context(src) == main_ctx);
791     g_assert(bdrv_get_aio_context(target) == main_ctx);
792     g_assert(bdrv_get_aio_context(filter) == main_ctx);
793 
794     /* ...unless we explicitly allow it */
795     aio_context_acquire(ctx);
796     blk_set_allow_aio_context_change(blk, true);
797     bdrv_try_change_aio_context(target, ctx, NULL, &error_abort);
798     aio_context_release(ctx);
799 
800     g_assert(blk_get_aio_context(blk) == ctx);
801     g_assert(bdrv_get_aio_context(src) == ctx);
802     g_assert(bdrv_get_aio_context(target) == ctx);
803     g_assert(bdrv_get_aio_context(filter) == ctx);
804 
805     job_cancel_sync_all();
806 
807     aio_context_acquire(ctx);
808     blk_set_aio_context(blk, main_ctx, &error_abort);
809     bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
810     aio_context_release(ctx);
811 
812     blk_unref(blk);
813     bdrv_unref(src);
814     bdrv_unref(target);
815 }
816 
817 static void test_attach_second_node(void)
818 {
819     IOThread *iothread = iothread_new();
820     AioContext *ctx = iothread_get_aio_context(iothread);
821     AioContext *main_ctx = qemu_get_aio_context();
822     BlockBackend *blk;
823     BlockDriverState *bs, *filter;
824     QDict *options;
825 
826     blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
827     bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
828     blk_insert_bs(blk, bs, &error_abort);
829 
830     options = qdict_new();
831     qdict_put_str(options, "driver", "raw");
832     qdict_put_str(options, "file", "base");
833 
834     filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
835     g_assert(blk_get_aio_context(blk) == ctx);
836     g_assert(bdrv_get_aio_context(bs) == ctx);
837     g_assert(bdrv_get_aio_context(filter) == ctx);
838 
839     aio_context_acquire(ctx);
840     blk_set_aio_context(blk, main_ctx, &error_abort);
841     aio_context_release(ctx);
842     g_assert(blk_get_aio_context(blk) == main_ctx);
843     g_assert(bdrv_get_aio_context(bs) == main_ctx);
844     g_assert(bdrv_get_aio_context(filter) == main_ctx);
845 
846     bdrv_unref(filter);
847     bdrv_unref(bs);
848     blk_unref(blk);
849 }
850 
851 static void test_attach_preserve_blk_ctx(void)
852 {
853     IOThread *iothread = iothread_new();
854     AioContext *ctx = iothread_get_aio_context(iothread);
855     BlockBackend *blk;
856     BlockDriverState *bs;
857 
858     blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
859     bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
860     bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
861 
862     /* Add node to BlockBackend that has an iothread context assigned */
863     blk_insert_bs(blk, bs, &error_abort);
864     g_assert(blk_get_aio_context(blk) == ctx);
865     g_assert(bdrv_get_aio_context(bs) == ctx);
866 
867     /* Remove the node again */
868     aio_context_acquire(ctx);
869     blk_remove_bs(blk);
870     aio_context_release(ctx);
871     g_assert(blk_get_aio_context(blk) == ctx);
872     g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context());
873 
874     /* Re-attach the node */
875     blk_insert_bs(blk, bs, &error_abort);
876     g_assert(blk_get_aio_context(blk) == ctx);
877     g_assert(bdrv_get_aio_context(bs) == ctx);
878 
879     aio_context_acquire(ctx);
880     blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
881     aio_context_release(ctx);
882     bdrv_unref(bs);
883     blk_unref(blk);
884 }
885 
886 int main(int argc, char **argv)
887 {
888     int i;
889 
890     bdrv_init();
891     qemu_init_main_loop(&error_abort);
892 
893     g_test_init(&argc, &argv, NULL);
894 
895     for (i = 0; i < ARRAY_SIZE(sync_op_tests); i++) {
896         const SyncOpTest *t = &sync_op_tests[i];
897         g_test_add_data_func(t->name, t, test_sync_op);
898     }
899 
900     g_test_add_func("/attach/blockjob", test_attach_blockjob);
901     g_test_add_func("/attach/second_node", test_attach_second_node);
902     g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx);
903     g_test_add_func("/propagate/basic", test_propagate_basic);
904     g_test_add_func("/propagate/diamond", test_propagate_diamond);
905     g_test_add_func("/propagate/mirror", test_propagate_mirror);
906 
907     return g_test_run();
908 }
909