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 "iothread.h"
  32
  33static int coroutine_fn bdrv_test_co_prwv(BlockDriverState *bs,
  34                                          uint64_t offset, uint64_t bytes,
  35                                          QEMUIOVector *qiov, int flags)
  36{
  37    return 0;
  38}
  39
  40static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
  41                                              int64_t offset, int bytes)
  42{
  43    return 0;
  44}
  45
  46static int coroutine_fn
  47bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset,
  48                      PreallocMode prealloc, Error **errp)
  49{
  50    return 0;
  51}
  52
  53static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
  54                                                  bool want_zero,
  55                                                  int64_t offset, int64_t count,
  56                                                  int64_t *pnum, int64_t *map,
  57                                                  BlockDriverState **file)
  58{
  59    *pnum = count;
  60    return 0;
  61}
  62
  63static BlockDriver bdrv_test = {
  64    .format_name            = "test",
  65    .instance_size          = 1,
  66
  67    .bdrv_co_preadv         = bdrv_test_co_prwv,
  68    .bdrv_co_pwritev        = bdrv_test_co_prwv,
  69    .bdrv_co_pdiscard       = bdrv_test_co_pdiscard,
  70    .bdrv_co_truncate       = bdrv_test_co_truncate,
  71    .bdrv_co_block_status   = bdrv_test_co_block_status,
  72};
  73
  74static void test_sync_op_pread(BdrvChild *c)
  75{
  76    uint8_t buf[512];
  77    int ret;
  78
  79    /* Success */
  80    ret = bdrv_pread(c, 0, buf, sizeof(buf));
  81    g_assert_cmpint(ret, ==, 512);
  82
  83    /* Early error: Negative offset */
  84    ret = bdrv_pread(c, -2, buf, sizeof(buf));
  85    g_assert_cmpint(ret, ==, -EIO);
  86}
  87
  88static void test_sync_op_pwrite(BdrvChild *c)
  89{
  90    uint8_t buf[512];
  91    int ret;
  92
  93    /* Success */
  94    ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
  95    g_assert_cmpint(ret, ==, 512);
  96
  97    /* Early error: Negative offset */
  98    ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
  99    g_assert_cmpint(ret, ==, -EIO);
 100}
 101
 102static void test_sync_op_blk_pread(BlockBackend *blk)
 103{
 104    uint8_t buf[512];
 105    int ret;
 106
 107    /* Success */
 108    ret = blk_pread(blk, 0, buf, sizeof(buf));
 109    g_assert_cmpint(ret, ==, 512);
 110
 111    /* Early error: Negative offset */
 112    ret = blk_pread(blk, -2, buf, sizeof(buf));
 113    g_assert_cmpint(ret, ==, -EIO);
 114}
 115
 116static void test_sync_op_blk_pwrite(BlockBackend *blk)
 117{
 118    uint8_t buf[512];
 119    int ret;
 120
 121    /* Success */
 122    ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
 123    g_assert_cmpint(ret, ==, 512);
 124
 125    /* Early error: Negative offset */
 126    ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
 127    g_assert_cmpint(ret, ==, -EIO);
 128}
 129
 130static void test_sync_op_load_vmstate(BdrvChild *c)
 131{
 132    uint8_t buf[512];
 133    int ret;
 134
 135    /* Error: Driver does not support snapshots */
 136    ret = bdrv_load_vmstate(c->bs, buf, 0, sizeof(buf));
 137    g_assert_cmpint(ret, ==, -ENOTSUP);
 138}
 139
 140static void test_sync_op_save_vmstate(BdrvChild *c)
 141{
 142    uint8_t buf[512];
 143    int ret;
 144
 145    /* Error: Driver does not support snapshots */
 146    ret = bdrv_save_vmstate(c->bs, buf, 0, sizeof(buf));
 147    g_assert_cmpint(ret, ==, -ENOTSUP);
 148}
 149
 150static void test_sync_op_pdiscard(BdrvChild *c)
 151{
 152    int ret;
 153
 154    /* Normal success path */
 155    c->bs->open_flags |= BDRV_O_UNMAP;
 156    ret = bdrv_pdiscard(c, 0, 512);
 157    g_assert_cmpint(ret, ==, 0);
 158
 159    /* Early success: UNMAP not supported */
 160    c->bs->open_flags &= ~BDRV_O_UNMAP;
 161    ret = bdrv_pdiscard(c, 0, 512);
 162    g_assert_cmpint(ret, ==, 0);
 163
 164    /* Early error: Negative offset */
 165    ret = bdrv_pdiscard(c, -2, 512);
 166    g_assert_cmpint(ret, ==, -EIO);
 167}
 168
 169static void test_sync_op_blk_pdiscard(BlockBackend *blk)
 170{
 171    int ret;
 172
 173    /* Early success: UNMAP not supported */
 174    ret = blk_pdiscard(blk, 0, 512);
 175    g_assert_cmpint(ret, ==, 0);
 176
 177    /* Early error: Negative offset */
 178    ret = blk_pdiscard(blk, -2, 512);
 179    g_assert_cmpint(ret, ==, -EIO);
 180}
 181
 182static void test_sync_op_truncate(BdrvChild *c)
 183{
 184    int ret;
 185
 186    /* Normal success path */
 187    ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
 188    g_assert_cmpint(ret, ==, 0);
 189
 190    /* Early error: Negative offset */
 191    ret = bdrv_truncate(c, -2, PREALLOC_MODE_OFF, NULL);
 192    g_assert_cmpint(ret, ==, -EINVAL);
 193
 194    /* Error: Read-only image */
 195    c->bs->read_only = true;
 196    c->bs->open_flags &= ~BDRV_O_RDWR;
 197
 198    ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
 199    g_assert_cmpint(ret, ==, -EACCES);
 200
 201    c->bs->read_only = false;
 202    c->bs->open_flags |= BDRV_O_RDWR;
 203}
 204
 205static void test_sync_op_block_status(BdrvChild *c)
 206{
 207    int ret;
 208    int64_t n;
 209
 210    /* Normal success path */
 211    ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
 212    g_assert_cmpint(ret, ==, 0);
 213
 214    /* Early success: No driver support */
 215    bdrv_test.bdrv_co_block_status = NULL;
 216    ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
 217    g_assert_cmpint(ret, ==, 1);
 218
 219    /* Early success: bytes = 0 */
 220    ret = bdrv_is_allocated(c->bs, 0, 0, &n);
 221    g_assert_cmpint(ret, ==, 0);
 222
 223    /* Early success: Offset > image size*/
 224    ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n);
 225    g_assert_cmpint(ret, ==, 0);
 226}
 227
 228static void test_sync_op_flush(BdrvChild *c)
 229{
 230    int ret;
 231
 232    /* Normal success path */
 233    ret = bdrv_flush(c->bs);
 234    g_assert_cmpint(ret, ==, 0);
 235
 236    /* Early success: Read-only image */
 237    c->bs->read_only = true;
 238    c->bs->open_flags &= ~BDRV_O_RDWR;
 239
 240    ret = bdrv_flush(c->bs);
 241    g_assert_cmpint(ret, ==, 0);
 242
 243    c->bs->read_only = false;
 244    c->bs->open_flags |= BDRV_O_RDWR;
 245}
 246
 247static void test_sync_op_blk_flush(BlockBackend *blk)
 248{
 249    BlockDriverState *bs = blk_bs(blk);
 250    int ret;
 251
 252    /* Normal success path */
 253    ret = blk_flush(blk);
 254    g_assert_cmpint(ret, ==, 0);
 255
 256    /* Early success: Read-only image */
 257    bs->read_only = true;
 258    bs->open_flags &= ~BDRV_O_RDWR;
 259
 260    ret = blk_flush(blk);
 261    g_assert_cmpint(ret, ==, 0);
 262
 263    bs->read_only = false;
 264    bs->open_flags |= BDRV_O_RDWR;
 265}
 266
 267static void test_sync_op_check(BdrvChild *c)
 268{
 269    BdrvCheckResult result;
 270    int ret;
 271
 272    /* Error: Driver does not implement check */
 273    ret = bdrv_check(c->bs, &result, 0);
 274    g_assert_cmpint(ret, ==, -ENOTSUP);
 275}
 276
 277static void test_sync_op_invalidate_cache(BdrvChild *c)
 278{
 279    /* Early success: Image is not inactive */
 280    bdrv_invalidate_cache(c->bs, NULL);
 281}
 282
 283
 284typedef struct SyncOpTest {
 285    const char *name;
 286    void (*fn)(BdrvChild *c);
 287    void (*blkfn)(BlockBackend *blk);
 288} SyncOpTest;
 289
 290const SyncOpTest sync_op_tests[] = {
 291    {
 292        .name   = "/sync-op/pread",
 293        .fn     = test_sync_op_pread,
 294        .blkfn  = test_sync_op_blk_pread,
 295    }, {
 296        .name   = "/sync-op/pwrite",
 297        .fn     = test_sync_op_pwrite,
 298        .blkfn  = test_sync_op_blk_pwrite,
 299    }, {
 300        .name   = "/sync-op/load_vmstate",
 301        .fn     = test_sync_op_load_vmstate,
 302    }, {
 303        .name   = "/sync-op/save_vmstate",
 304        .fn     = test_sync_op_save_vmstate,
 305    }, {
 306        .name   = "/sync-op/pdiscard",
 307        .fn     = test_sync_op_pdiscard,
 308        .blkfn  = test_sync_op_blk_pdiscard,
 309    }, {
 310        .name   = "/sync-op/truncate",
 311        .fn     = test_sync_op_truncate,
 312    }, {
 313        .name   = "/sync-op/block_status",
 314        .fn     = test_sync_op_block_status,
 315    }, {
 316        .name   = "/sync-op/flush",
 317        .fn     = test_sync_op_flush,
 318        .blkfn  = test_sync_op_blk_flush,
 319    }, {
 320        .name   = "/sync-op/check",
 321        .fn     = test_sync_op_check,
 322    }, {
 323        .name   = "/sync-op/invalidate_cache",
 324        .fn     = test_sync_op_invalidate_cache,
 325    },
 326};
 327
 328/* Test synchronous operations that run in a different iothread, so we have to
 329 * poll for the coroutine there to return. */
 330static void test_sync_op(const void *opaque)
 331{
 332    const SyncOpTest *t = opaque;
 333    IOThread *iothread = iothread_new();
 334    AioContext *ctx = iothread_get_aio_context(iothread);
 335    BlockBackend *blk;
 336    BlockDriverState *bs;
 337    BdrvChild *c;
 338
 339    blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
 340    bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
 341    bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
 342    blk_insert_bs(blk, bs, &error_abort);
 343    c = QLIST_FIRST(&bs->parents);
 344
 345    blk_set_aio_context(blk, ctx, &error_abort);
 346    aio_context_acquire(ctx);
 347    t->fn(c);
 348    if (t->blkfn) {
 349        t->blkfn(blk);
 350    }
 351    blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
 352    aio_context_release(ctx);
 353
 354    bdrv_unref(bs);
 355    blk_unref(blk);
 356}
 357
 358typedef struct TestBlockJob {
 359    BlockJob common;
 360    bool should_complete;
 361    int n;
 362} TestBlockJob;
 363
 364static int test_job_prepare(Job *job)
 365{
 366    g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
 367    return 0;
 368}
 369
 370static int coroutine_fn test_job_run(Job *job, Error **errp)
 371{
 372    TestBlockJob *s = container_of(job, TestBlockJob, common.job);
 373
 374    job_transition_to_ready(&s->common.job);
 375    while (!s->should_complete) {
 376        s->n++;
 377        g_assert(qemu_get_current_aio_context() == job->aio_context);
 378
 379        /* Avoid job_sleep_ns() because it marks the job as !busy. We want to
 380         * emulate some actual activity (probably some I/O) here so that the
 381         * drain involved in AioContext switches has to wait for this activity
 382         * to stop. */
 383        qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000);
 384
 385        job_pause_point(&s->common.job);
 386    }
 387
 388    g_assert(qemu_get_current_aio_context() == job->aio_context);
 389    return 0;
 390}
 391
 392static void test_job_complete(Job *job, Error **errp)
 393{
 394    TestBlockJob *s = container_of(job, TestBlockJob, common.job);
 395    s->should_complete = true;
 396}
 397
 398BlockJobDriver test_job_driver = {
 399    .job_driver = {
 400        .instance_size  = sizeof(TestBlockJob),
 401        .free           = block_job_free,
 402        .user_resume    = block_job_user_resume,
 403        .drain          = block_job_drain,
 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,
 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