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 static void test_sync_op_block_status(BdrvChild *c) 316 { 317 int ret; 318 int64_t n; 319 320 /* Normal success path */ 321 ret = bdrv_is_allocated(c->bs, 0, 65536, &n); 322 g_assert_cmpint(ret, ==, 0); 323 324 /* Early success: No driver support */ 325 bdrv_test.bdrv_co_block_status = NULL; 326 ret = bdrv_is_allocated(c->bs, 0, 65536, &n); 327 g_assert_cmpint(ret, ==, 1); 328 329 /* Early success: bytes = 0 */ 330 ret = bdrv_is_allocated(c->bs, 0, 0, &n); 331 g_assert_cmpint(ret, ==, 0); 332 333 /* Early success: Offset > image size*/ 334 ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n); 335 g_assert_cmpint(ret, ==, 0); 336 } 337 338 static void test_sync_op_flush(BdrvChild *c) 339 { 340 int ret; 341 342 /* Normal success path */ 343 ret = bdrv_flush(c->bs); 344 g_assert_cmpint(ret, ==, 0); 345 346 /* Early success: Read-only image */ 347 c->bs->open_flags &= ~BDRV_O_RDWR; 348 349 ret = bdrv_flush(c->bs); 350 g_assert_cmpint(ret, ==, 0); 351 352 c->bs->open_flags |= BDRV_O_RDWR; 353 } 354 355 static void test_sync_op_blk_flush(BlockBackend *blk) 356 { 357 BlockDriverState *bs = blk_bs(blk); 358 int ret; 359 360 /* Normal success path */ 361 ret = blk_flush(blk); 362 g_assert_cmpint(ret, ==, 0); 363 364 /* Early success: Read-only image */ 365 bs->open_flags &= ~BDRV_O_RDWR; 366 367 ret = blk_flush(blk); 368 g_assert_cmpint(ret, ==, 0); 369 370 bs->open_flags |= BDRV_O_RDWR; 371 } 372 373 static void test_sync_op_check(BdrvChild *c) 374 { 375 BdrvCheckResult result; 376 int ret; 377 378 /* Error: Driver does not implement check */ 379 ret = bdrv_check(c->bs, &result, 0); 380 g_assert_cmpint(ret, ==, -ENOTSUP); 381 } 382 383 static void test_sync_op_activate(BdrvChild *c) 384 { 385 /* Early success: Image is not inactive */ 386 bdrv_activate(c->bs, NULL); 387 } 388 389 390 typedef struct SyncOpTest { 391 const char *name; 392 void (*fn)(BdrvChild *c); 393 void (*blkfn)(BlockBackend *blk); 394 } SyncOpTest; 395 396 const SyncOpTest sync_op_tests[] = { 397 { 398 .name = "/sync-op/pread", 399 .fn = test_sync_op_pread, 400 .blkfn = test_sync_op_blk_pread, 401 }, { 402 .name = "/sync-op/pwrite", 403 .fn = test_sync_op_pwrite, 404 .blkfn = test_sync_op_blk_pwrite, 405 }, { 406 .name = "/sync-op/preadv", 407 .fn = NULL, 408 .blkfn = test_sync_op_blk_preadv, 409 }, { 410 .name = "/sync-op/pwritev", 411 .fn = NULL, 412 .blkfn = test_sync_op_blk_pwritev, 413 }, { 414 .name = "/sync-op/preadv_part", 415 .fn = NULL, 416 .blkfn = test_sync_op_blk_preadv_part, 417 }, { 418 .name = "/sync-op/pwritev_part", 419 .fn = NULL, 420 .blkfn = test_sync_op_blk_pwritev_part, 421 }, { 422 .name = "/sync-op/pwrite_compressed", 423 .fn = NULL, 424 .blkfn = test_sync_op_blk_pwrite_compressed, 425 }, { 426 .name = "/sync-op/pwrite_zeroes", 427 .fn = NULL, 428 .blkfn = test_sync_op_blk_pwrite_zeroes, 429 }, { 430 .name = "/sync-op/load_vmstate", 431 .fn = test_sync_op_load_vmstate, 432 }, { 433 .name = "/sync-op/save_vmstate", 434 .fn = test_sync_op_save_vmstate, 435 }, { 436 .name = "/sync-op/pdiscard", 437 .fn = test_sync_op_pdiscard, 438 .blkfn = test_sync_op_blk_pdiscard, 439 }, { 440 .name = "/sync-op/truncate", 441 .fn = test_sync_op_truncate, 442 .blkfn = test_sync_op_blk_truncate, 443 }, { 444 .name = "/sync-op/block_status", 445 .fn = test_sync_op_block_status, 446 }, { 447 .name = "/sync-op/flush", 448 .fn = test_sync_op_flush, 449 .blkfn = test_sync_op_blk_flush, 450 }, { 451 .name = "/sync-op/check", 452 .fn = test_sync_op_check, 453 }, { 454 .name = "/sync-op/activate", 455 .fn = test_sync_op_activate, 456 }, 457 }; 458 459 /* Test synchronous operations that run in a different iothread, so we have to 460 * poll for the coroutine there to return. */ 461 static void test_sync_op(const void *opaque) 462 { 463 const SyncOpTest *t = opaque; 464 IOThread *iothread = iothread_new(); 465 AioContext *ctx = iothread_get_aio_context(iothread); 466 BlockBackend *blk; 467 BlockDriverState *bs; 468 BdrvChild *c; 469 470 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); 471 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); 472 bs->total_sectors = 65536 / BDRV_SECTOR_SIZE; 473 blk_insert_bs(blk, bs, &error_abort); 474 c = QLIST_FIRST(&bs->parents); 475 476 blk_set_aio_context(blk, ctx, &error_abort); 477 aio_context_acquire(ctx); 478 if (t->fn) { 479 t->fn(c); 480 } 481 if (t->blkfn) { 482 t->blkfn(blk); 483 } 484 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); 485 aio_context_release(ctx); 486 487 bdrv_unref(bs); 488 blk_unref(blk); 489 } 490 491 typedef struct TestBlockJob { 492 BlockJob common; 493 bool should_complete; 494 int n; 495 } TestBlockJob; 496 497 static int test_job_prepare(Job *job) 498 { 499 g_assert(qemu_get_current_aio_context() == qemu_get_aio_context()); 500 return 0; 501 } 502 503 static int coroutine_fn test_job_run(Job *job, Error **errp) 504 { 505 TestBlockJob *s = container_of(job, TestBlockJob, common.job); 506 507 job_transition_to_ready(&s->common.job); 508 while (!s->should_complete) { 509 s->n++; 510 g_assert(qemu_get_current_aio_context() == job->aio_context); 511 512 /* Avoid job_sleep_ns() because it marks the job as !busy. We want to 513 * emulate some actual activity (probably some I/O) here so that the 514 * drain involved in AioContext switches has to wait for this activity 515 * to stop. */ 516 qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000); 517 518 job_pause_point(&s->common.job); 519 } 520 521 g_assert(qemu_get_current_aio_context() == job->aio_context); 522 return 0; 523 } 524 525 static void test_job_complete(Job *job, Error **errp) 526 { 527 TestBlockJob *s = container_of(job, TestBlockJob, common.job); 528 s->should_complete = true; 529 } 530 531 BlockJobDriver test_job_driver = { 532 .job_driver = { 533 .instance_size = sizeof(TestBlockJob), 534 .free = block_job_free, 535 .user_resume = block_job_user_resume, 536 .run = test_job_run, 537 .complete = test_job_complete, 538 .prepare = test_job_prepare, 539 }, 540 }; 541 542 static void test_attach_blockjob(void) 543 { 544 IOThread *iothread = iothread_new(); 545 AioContext *ctx = iothread_get_aio_context(iothread); 546 BlockBackend *blk; 547 BlockDriverState *bs; 548 TestBlockJob *tjob; 549 550 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); 551 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); 552 blk_insert_bs(blk, bs, &error_abort); 553 554 tjob = block_job_create("job0", &test_job_driver, NULL, bs, 555 0, BLK_PERM_ALL, 556 0, 0, NULL, NULL, &error_abort); 557 job_start(&tjob->common.job); 558 559 while (tjob->n == 0) { 560 aio_poll(qemu_get_aio_context(), false); 561 } 562 563 blk_set_aio_context(blk, ctx, &error_abort); 564 565 tjob->n = 0; 566 while (tjob->n == 0) { 567 aio_poll(qemu_get_aio_context(), false); 568 } 569 570 aio_context_acquire(ctx); 571 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); 572 aio_context_release(ctx); 573 574 tjob->n = 0; 575 while (tjob->n == 0) { 576 aio_poll(qemu_get_aio_context(), false); 577 } 578 579 blk_set_aio_context(blk, ctx, &error_abort); 580 581 tjob->n = 0; 582 while (tjob->n == 0) { 583 aio_poll(qemu_get_aio_context(), false); 584 } 585 586 WITH_JOB_LOCK_GUARD() { 587 job_complete_sync_locked(&tjob->common.job, &error_abort); 588 } 589 aio_context_acquire(ctx); 590 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); 591 aio_context_release(ctx); 592 593 bdrv_unref(bs); 594 blk_unref(blk); 595 } 596 597 /* 598 * Test that changing the AioContext for one node in a tree (here through blk) 599 * changes all other nodes as well: 600 * 601 * blk 602 * | 603 * | bs_verify [blkverify] 604 * | / \ 605 * | / \ 606 * bs_a [bdrv_test] bs_b [bdrv_test] 607 * 608 */ 609 static void test_propagate_basic(void) 610 { 611 IOThread *iothread = iothread_new(); 612 AioContext *ctx = iothread_get_aio_context(iothread); 613 AioContext *main_ctx; 614 BlockBackend *blk; 615 BlockDriverState *bs_a, *bs_b, *bs_verify; 616 QDict *options; 617 618 /* 619 * Create bs_a and its BlockBackend. We cannot take the RESIZE 620 * permission because blkverify will not share it on the test 621 * image. 622 */ 623 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE, 624 BLK_PERM_ALL); 625 bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort); 626 blk_insert_bs(blk, bs_a, &error_abort); 627 628 /* Create bs_b */ 629 bs_b = bdrv_new_open_driver(&bdrv_test, "bs_b", BDRV_O_RDWR, &error_abort); 630 631 /* Create blkverify filter that references both bs_a and bs_b */ 632 options = qdict_new(); 633 qdict_put_str(options, "driver", "blkverify"); 634 qdict_put_str(options, "test", "bs_a"); 635 qdict_put_str(options, "raw", "bs_b"); 636 637 bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); 638 639 /* Switch the AioContext */ 640 blk_set_aio_context(blk, ctx, &error_abort); 641 g_assert(blk_get_aio_context(blk) == ctx); 642 g_assert(bdrv_get_aio_context(bs_a) == ctx); 643 g_assert(bdrv_get_aio_context(bs_verify) == ctx); 644 g_assert(bdrv_get_aio_context(bs_b) == ctx); 645 646 /* Switch the AioContext back */ 647 main_ctx = qemu_get_aio_context(); 648 aio_context_acquire(ctx); 649 blk_set_aio_context(blk, main_ctx, &error_abort); 650 aio_context_release(ctx); 651 g_assert(blk_get_aio_context(blk) == main_ctx); 652 g_assert(bdrv_get_aio_context(bs_a) == main_ctx); 653 g_assert(bdrv_get_aio_context(bs_verify) == main_ctx); 654 g_assert(bdrv_get_aio_context(bs_b) == main_ctx); 655 656 bdrv_unref(bs_verify); 657 bdrv_unref(bs_b); 658 bdrv_unref(bs_a); 659 blk_unref(blk); 660 } 661 662 /* 663 * Test that diamonds in the graph don't lead to endless recursion: 664 * 665 * blk 666 * | 667 * bs_verify [blkverify] 668 * / \ 669 * / \ 670 * bs_b [raw] bs_c[raw] 671 * \ / 672 * \ / 673 * bs_a [bdrv_test] 674 */ 675 static void test_propagate_diamond(void) 676 { 677 IOThread *iothread = iothread_new(); 678 AioContext *ctx = iothread_get_aio_context(iothread); 679 AioContext *main_ctx; 680 BlockBackend *blk; 681 BlockDriverState *bs_a, *bs_b, *bs_c, *bs_verify; 682 QDict *options; 683 684 /* Create bs_a */ 685 bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort); 686 687 /* Create bs_b and bc_c */ 688 options = qdict_new(); 689 qdict_put_str(options, "driver", "raw"); 690 qdict_put_str(options, "file", "bs_a"); 691 qdict_put_str(options, "node-name", "bs_b"); 692 bs_b = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); 693 694 options = qdict_new(); 695 qdict_put_str(options, "driver", "raw"); 696 qdict_put_str(options, "file", "bs_a"); 697 qdict_put_str(options, "node-name", "bs_c"); 698 bs_c = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); 699 700 /* Create blkverify filter that references both bs_b and bs_c */ 701 options = qdict_new(); 702 qdict_put_str(options, "driver", "blkverify"); 703 qdict_put_str(options, "test", "bs_b"); 704 qdict_put_str(options, "raw", "bs_c"); 705 706 bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); 707 /* 708 * Do not take the RESIZE permission: This would require the same 709 * from bs_c and thus from bs_a; however, blkverify will not share 710 * it on bs_b, and thus it will not be available for bs_a. 711 */ 712 blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE, 713 BLK_PERM_ALL); 714 blk_insert_bs(blk, bs_verify, &error_abort); 715 716 /* Switch the AioContext */ 717 blk_set_aio_context(blk, ctx, &error_abort); 718 g_assert(blk_get_aio_context(blk) == ctx); 719 g_assert(bdrv_get_aio_context(bs_verify) == ctx); 720 g_assert(bdrv_get_aio_context(bs_a) == ctx); 721 g_assert(bdrv_get_aio_context(bs_b) == ctx); 722 g_assert(bdrv_get_aio_context(bs_c) == ctx); 723 724 /* Switch the AioContext back */ 725 main_ctx = qemu_get_aio_context(); 726 aio_context_acquire(ctx); 727 blk_set_aio_context(blk, main_ctx, &error_abort); 728 aio_context_release(ctx); 729 g_assert(blk_get_aio_context(blk) == main_ctx); 730 g_assert(bdrv_get_aio_context(bs_verify) == main_ctx); 731 g_assert(bdrv_get_aio_context(bs_a) == main_ctx); 732 g_assert(bdrv_get_aio_context(bs_b) == main_ctx); 733 g_assert(bdrv_get_aio_context(bs_c) == main_ctx); 734 735 blk_unref(blk); 736 bdrv_unref(bs_verify); 737 bdrv_unref(bs_c); 738 bdrv_unref(bs_b); 739 bdrv_unref(bs_a); 740 } 741 742 static void test_propagate_mirror(void) 743 { 744 IOThread *iothread = iothread_new(); 745 AioContext *ctx = iothread_get_aio_context(iothread); 746 AioContext *main_ctx = qemu_get_aio_context(); 747 BlockDriverState *src, *target, *filter; 748 BlockBackend *blk; 749 Job *job; 750 Error *local_err = NULL; 751 752 /* Create src and target*/ 753 src = bdrv_new_open_driver(&bdrv_test, "src", BDRV_O_RDWR, &error_abort); 754 target = bdrv_new_open_driver(&bdrv_test, "target", BDRV_O_RDWR, 755 &error_abort); 756 757 /* Start a mirror job */ 758 mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0, 759 MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false, 760 BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT, 761 false, "filter_node", MIRROR_COPY_MODE_BACKGROUND, 762 &error_abort); 763 WITH_JOB_LOCK_GUARD() { 764 job = job_get_locked("job0"); 765 } 766 filter = bdrv_find_node("filter_node"); 767 768 /* Change the AioContext of src */ 769 bdrv_try_change_aio_context(src, ctx, NULL, &error_abort); 770 g_assert(bdrv_get_aio_context(src) == ctx); 771 g_assert(bdrv_get_aio_context(target) == ctx); 772 g_assert(bdrv_get_aio_context(filter) == ctx); 773 g_assert(job->aio_context == ctx); 774 775 /* Change the AioContext of target */ 776 aio_context_acquire(ctx); 777 bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort); 778 aio_context_release(ctx); 779 g_assert(bdrv_get_aio_context(src) == main_ctx); 780 g_assert(bdrv_get_aio_context(target) == main_ctx); 781 g_assert(bdrv_get_aio_context(filter) == main_ctx); 782 783 /* With a BlockBackend on src, changing target must fail */ 784 blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 785 blk_insert_bs(blk, src, &error_abort); 786 787 bdrv_try_change_aio_context(target, ctx, NULL, &local_err); 788 error_free_or_abort(&local_err); 789 790 g_assert(blk_get_aio_context(blk) == main_ctx); 791 g_assert(bdrv_get_aio_context(src) == main_ctx); 792 g_assert(bdrv_get_aio_context(target) == main_ctx); 793 g_assert(bdrv_get_aio_context(filter) == main_ctx); 794 795 /* ...unless we explicitly allow it */ 796 aio_context_acquire(ctx); 797 blk_set_allow_aio_context_change(blk, true); 798 bdrv_try_change_aio_context(target, ctx, NULL, &error_abort); 799 aio_context_release(ctx); 800 801 g_assert(blk_get_aio_context(blk) == ctx); 802 g_assert(bdrv_get_aio_context(src) == ctx); 803 g_assert(bdrv_get_aio_context(target) == ctx); 804 g_assert(bdrv_get_aio_context(filter) == ctx); 805 806 job_cancel_sync_all(); 807 808 aio_context_acquire(ctx); 809 blk_set_aio_context(blk, main_ctx, &error_abort); 810 bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort); 811 aio_context_release(ctx); 812 813 blk_unref(blk); 814 bdrv_unref(src); 815 bdrv_unref(target); 816 } 817 818 static void test_attach_second_node(void) 819 { 820 IOThread *iothread = iothread_new(); 821 AioContext *ctx = iothread_get_aio_context(iothread); 822 AioContext *main_ctx = qemu_get_aio_context(); 823 BlockBackend *blk; 824 BlockDriverState *bs, *filter; 825 QDict *options; 826 827 blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL); 828 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); 829 blk_insert_bs(blk, bs, &error_abort); 830 831 options = qdict_new(); 832 qdict_put_str(options, "driver", "raw"); 833 qdict_put_str(options, "file", "base"); 834 835 aio_context_acquire(ctx); 836 filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort); 837 aio_context_release(ctx); 838 839 g_assert(blk_get_aio_context(blk) == ctx); 840 g_assert(bdrv_get_aio_context(bs) == ctx); 841 g_assert(bdrv_get_aio_context(filter) == ctx); 842 843 aio_context_acquire(ctx); 844 blk_set_aio_context(blk, main_ctx, &error_abort); 845 aio_context_release(ctx); 846 g_assert(blk_get_aio_context(blk) == main_ctx); 847 g_assert(bdrv_get_aio_context(bs) == main_ctx); 848 g_assert(bdrv_get_aio_context(filter) == main_ctx); 849 850 bdrv_unref(filter); 851 bdrv_unref(bs); 852 blk_unref(blk); 853 } 854 855 static void test_attach_preserve_blk_ctx(void) 856 { 857 IOThread *iothread = iothread_new(); 858 AioContext *ctx = iothread_get_aio_context(iothread); 859 BlockBackend *blk; 860 BlockDriverState *bs; 861 862 blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL); 863 bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort); 864 bs->total_sectors = 65536 / BDRV_SECTOR_SIZE; 865 866 /* Add node to BlockBackend that has an iothread context assigned */ 867 blk_insert_bs(blk, bs, &error_abort); 868 g_assert(blk_get_aio_context(blk) == ctx); 869 g_assert(bdrv_get_aio_context(bs) == ctx); 870 871 /* Remove the node again */ 872 aio_context_acquire(ctx); 873 blk_remove_bs(blk); 874 aio_context_release(ctx); 875 g_assert(blk_get_aio_context(blk) == ctx); 876 g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context()); 877 878 /* Re-attach the node */ 879 blk_insert_bs(blk, bs, &error_abort); 880 g_assert(blk_get_aio_context(blk) == ctx); 881 g_assert(bdrv_get_aio_context(bs) == ctx); 882 883 aio_context_acquire(ctx); 884 blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); 885 aio_context_release(ctx); 886 bdrv_unref(bs); 887 blk_unref(blk); 888 } 889 890 int main(int argc, char **argv) 891 { 892 int i; 893 894 bdrv_init(); 895 qemu_init_main_loop(&error_abort); 896 897 g_test_init(&argc, &argv, NULL); 898 899 for (i = 0; i < ARRAY_SIZE(sync_op_tests); i++) { 900 const SyncOpTest *t = &sync_op_tests[i]; 901 g_test_add_data_func(t->name, t, test_sync_op); 902 } 903 904 g_test_add_func("/attach/blockjob", test_attach_blockjob); 905 g_test_add_func("/attach/second_node", test_attach_second_node); 906 g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx); 907 g_test_add_func("/propagate/basic", test_propagate_basic); 908 g_test_add_func("/propagate/diamond", test_propagate_diamond); 909 g_test_add_func("/propagate/mirror", test_propagate_mirror); 910 911 return g_test_run(); 912 } 913