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