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