]> git.proxmox.com Git - mirror_qemu.git/blob - tests/unit/test-block-iothread.c
vl: Allow ThreadContext objects to be created before the sandbox option
[mirror_qemu.git] / tests / unit / test-block-iothread.c
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_set_aio_context(src, ctx, &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_set_aio_context(target, main_ctx, &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_set_aio_context(target, ctx, &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_set_aio_context(target, ctx, &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_set_aio_context(target, main_ctx, &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 }