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