static void test_pair_jobs_fail_cancel_race(void) { BlockJob *job1; BlockJob *job2; BlockJobTxn *txn; int result1 = -EINPROGRESS; int result2 = -EINPROGRESS; txn = block_job_txn_new(); job1 = test_block_job_start(1, true, -ECANCELED, &result1, txn); job2 = test_block_job_start(2, false, 0, &result2, txn); block_job_start(job1); block_job_start(job2); block_job_cancel(job1, false); /* Now make job2 finish before the main loop kicks jobs. This simulates * the race between a pending kick and another job completing. */ block_job_enter(job2); block_job_enter(job2); while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) { aio_poll(qemu_get_aio_context(), true); } g_assert_cmpint(result1, ==, -ECANCELED); g_assert_cmpint(result2, ==, -ECANCELED); block_job_txn_unref(txn); }
static void test_single_job(int expected) { BlockJob *job; BlockJobTxn *txn; int result = -EINPROGRESS; txn = block_job_txn_new(); job = test_block_job_start(1, true, expected, &result, txn); block_job_start(job); if (expected == -ECANCELED) { block_job_cancel(job, false); } while (result == -EINPROGRESS) { aio_poll(qemu_get_aio_context(), true); } g_assert_cmpint(result, ==, expected); block_job_txn_unref(txn); }
static void test_pair_jobs(int expected1, int expected2) { BlockJob *job1; BlockJob *job2; BlockJobTxn *txn; int result1 = -EINPROGRESS; int result2 = -EINPROGRESS; txn = block_job_txn_new(); job1 = test_block_job_start(1, true, expected1, &result1, txn); job2 = test_block_job_start(2, true, expected2, &result2, txn); block_job_start(job1); block_job_start(job2); /* Release our reference now to trigger as many nice * use-after-free bugs as possible. */ block_job_txn_unref(txn); if (expected1 == -ECANCELED) { block_job_cancel(job1, false); } if (expected2 == -ECANCELED) { block_job_cancel(job2, false); } while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) { aio_poll(qemu_get_aio_context(), true); } /* Failure or cancellation of one job cancels the other job */ if (expected1 != 0) { expected2 = -ECANCELED; } else if (expected2 != 0) { expected1 = -ECANCELED; } g_assert_cmpint(result1, ==, expected1); g_assert_cmpint(result2, ==, expected2); }
static void test_pair_jobs(int expected1, int expected2) { BlockJob *job1; BlockJob *job2; BlockJobTxn *txn; int result1 = -EINPROGRESS; int result2 = -EINPROGRESS; txn = block_job_txn_new(); job1 = test_block_job_start(1, true, expected1, &result1); block_job_txn_add_job(txn, job1); job2 = test_block_job_start(2, true, expected2, &result2); block_job_txn_add_job(txn, job2); if (expected1 == -ECANCELED) { block_job_cancel(job1); } if (expected2 == -ECANCELED) { block_job_cancel(job2); } while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) { aio_poll(qemu_get_aio_context(), true); } /* Failure or cancellation of one job cancels the other job */ if (expected1 != 0) { expected2 = -ECANCELED; } else if (expected2 != 0) { expected1 = -ECANCELED; } g_assert_cmpint(result1, ==, expected1); g_assert_cmpint(result2, ==, expected2); block_job_txn_unref(txn); }