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