|
|
357786 |
From 36cd4342651561d7dda8bccc0520a35ca505c466 Mon Sep 17 00:00:00 2001
|
|
|
357786 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Date: Fri, 21 Sep 2018 12:46:30 +0200
|
|
|
357786 |
Subject: [PATCH 3/3] test-bdrv-drain: Test draining job source child and
|
|
|
357786 |
parent
|
|
|
357786 |
|
|
|
357786 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Message-id: <20180921124630.29036-4-kwolf@redhat.com>
|
|
|
357786 |
Patchwork-id: 82233
|
|
|
357786 |
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 3/3] test-bdrv-drain: Test draining job source child and parent
|
|
|
357786 |
Bugzilla: 1618584
|
|
|
357786 |
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
|
|
|
357786 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
357786 |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
357786 |
|
|
|
357786 |
For the block job drain test, don't only test draining the source and
|
|
|
357786 |
the target node, but create a backing chain for the source
|
|
|
357786 |
(source_backing <- source <- source_overlay) and test draining each of
|
|
|
357786 |
the nodes in it.
|
|
|
357786 |
|
|
|
357786 |
When using iothreads, the source node (and therefore the job) is in a
|
|
|
357786 |
different AioContext than the drain, which happens from the main
|
|
|
357786 |
thread. This way, the main thread waits in AIO_WAIT_WHILE() for the
|
|
|
357786 |
iothread to make process and aio_wait_kick() is required to notify it.
|
|
|
357786 |
The test validates that calling bdrv_wakeup() for a child or a parent
|
|
|
357786 |
node will actually notify AIO_WAIT_WHILE() instead of letting it hang.
|
|
|
357786 |
|
|
|
357786 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
357786 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
357786 |
---
|
|
|
357786 |
tests/test-bdrv-drain.c | 77 ++++++++++++++++++++++++++++++++++++++++++++-----
|
|
|
357786 |
1 file changed, 69 insertions(+), 8 deletions(-)
|
|
|
357786 |
|
|
|
357786 |
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
|
|
|
357786 |
index 7e7ba9b..8641b54 100644
|
|
|
357786 |
--- a/tests/test-bdrv-drain.c
|
|
|
357786 |
+++ b/tests/test-bdrv-drain.c
|
|
|
357786 |
@@ -786,6 +786,7 @@ typedef struct TestBlockJob {
|
|
|
357786 |
BlockJob common;
|
|
|
357786 |
int run_ret;
|
|
|
357786 |
int prepare_ret;
|
|
|
357786 |
+ bool running;
|
|
|
357786 |
bool should_complete;
|
|
|
357786 |
} TestBlockJob;
|
|
|
357786 |
|
|
|
357786 |
@@ -818,12 +819,17 @@ static int coroutine_fn test_job_run(Job *job, Error **errp)
|
|
|
357786 |
{
|
|
|
357786 |
TestBlockJob *s = container_of(job, TestBlockJob, common.job);
|
|
|
357786 |
|
|
|
357786 |
+ /* We are running the actual job code past the pause point in
|
|
|
357786 |
+ * job_co_entry(). */
|
|
|
357786 |
+ s->running = true;
|
|
|
357786 |
+
|
|
|
357786 |
job_transition_to_ready(&s->common.job);
|
|
|
357786 |
while (!s->should_complete) {
|
|
|
357786 |
/* Avoid job_sleep_ns() because it marks the job as !busy. We want to
|
|
|
357786 |
* emulate some actual activity (probably some I/O) here so that drain
|
|
|
357786 |
* has to wait for this activity to stop. */
|
|
|
357786 |
- qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 100000);
|
|
|
357786 |
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000);
|
|
|
357786 |
+
|
|
|
357786 |
job_pause_point(&s->common.job);
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
@@ -856,11 +862,19 @@ enum test_job_result {
|
|
|
357786 |
TEST_JOB_FAIL_PREPARE,
|
|
|
357786 |
};
|
|
|
357786 |
|
|
|
357786 |
-static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
- enum test_job_result result)
|
|
|
357786 |
+enum test_job_drain_node {
|
|
|
357786 |
+ TEST_JOB_DRAIN_SRC,
|
|
|
357786 |
+ TEST_JOB_DRAIN_SRC_CHILD,
|
|
|
357786 |
+ TEST_JOB_DRAIN_SRC_PARENT,
|
|
|
357786 |
+};
|
|
|
357786 |
+
|
|
|
357786 |
+static void test_blockjob_common_drain_node(enum drain_type drain_type,
|
|
|
357786 |
+ bool use_iothread,
|
|
|
357786 |
+ enum test_job_result result,
|
|
|
357786 |
+ enum test_job_drain_node drain_node)
|
|
|
357786 |
{
|
|
|
357786 |
BlockBackend *blk_src, *blk_target;
|
|
|
357786 |
- BlockDriverState *src, *target;
|
|
|
357786 |
+ BlockDriverState *src, *src_backing, *src_overlay, *target, *drain_bs;
|
|
|
357786 |
BlockJob *job;
|
|
|
357786 |
TestBlockJob *tjob;
|
|
|
357786 |
IOThread *iothread = NULL;
|
|
|
357786 |
@@ -869,8 +883,32 @@ static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
|
|
|
357786 |
src = bdrv_new_open_driver(&bdrv_test, "source", BDRV_O_RDWR,
|
|
|
357786 |
&error_abort);
|
|
|
357786 |
+ src_backing = bdrv_new_open_driver(&bdrv_test, "source-backing",
|
|
|
357786 |
+ BDRV_O_RDWR, &error_abort);
|
|
|
357786 |
+ src_overlay = bdrv_new_open_driver(&bdrv_test, "source-overlay",
|
|
|
357786 |
+ BDRV_O_RDWR, &error_abort);
|
|
|
357786 |
+
|
|
|
357786 |
+ bdrv_set_backing_hd(src_overlay, src, &error_abort);
|
|
|
357786 |
+ bdrv_unref(src);
|
|
|
357786 |
+ bdrv_set_backing_hd(src, src_backing, &error_abort);
|
|
|
357786 |
+ bdrv_unref(src_backing);
|
|
|
357786 |
+
|
|
|
357786 |
blk_src = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
|
|
|
357786 |
- blk_insert_bs(blk_src, src, &error_abort);
|
|
|
357786 |
+ blk_insert_bs(blk_src, src_overlay, &error_abort);
|
|
|
357786 |
+
|
|
|
357786 |
+ switch (drain_node) {
|
|
|
357786 |
+ case TEST_JOB_DRAIN_SRC:
|
|
|
357786 |
+ drain_bs = src;
|
|
|
357786 |
+ break;
|
|
|
357786 |
+ case TEST_JOB_DRAIN_SRC_CHILD:
|
|
|
357786 |
+ drain_bs = src_backing;
|
|
|
357786 |
+ break;
|
|
|
357786 |
+ case TEST_JOB_DRAIN_SRC_PARENT:
|
|
|
357786 |
+ drain_bs = src_overlay;
|
|
|
357786 |
+ break;
|
|
|
357786 |
+ default:
|
|
|
357786 |
+ g_assert_not_reached();
|
|
|
357786 |
+ }
|
|
|
357786 |
|
|
|
357786 |
if (use_iothread) {
|
|
|
357786 |
iothread = iothread_new();
|
|
|
357786 |
@@ -906,11 +944,21 @@ static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
job_start(&job->job);
|
|
|
357786 |
aio_context_release(ctx);
|
|
|
357786 |
|
|
|
357786 |
+ if (use_iothread) {
|
|
|
357786 |
+ /* job_co_entry() is run in the I/O thread, wait for the actual job
|
|
|
357786 |
+ * code to start (we don't want to catch the job in the pause point in
|
|
|
357786 |
+ * job_co_entry(). */
|
|
|
357786 |
+ while (!tjob->running) {
|
|
|
357786 |
+ aio_poll(qemu_get_aio_context(), false);
|
|
|
357786 |
+ }
|
|
|
357786 |
+ }
|
|
|
357786 |
+
|
|
|
357786 |
g_assert_cmpint(job->job.pause_count, ==, 0);
|
|
|
357786 |
g_assert_false(job->job.paused);
|
|
|
357786 |
+ g_assert_true(tjob->running);
|
|
|
357786 |
g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
|
|
|
357786 |
|
|
|
357786 |
- do_drain_begin_unlocked(drain_type, src);
|
|
|
357786 |
+ do_drain_begin_unlocked(drain_type, drain_bs);
|
|
|
357786 |
|
|
|
357786 |
if (drain_type == BDRV_DRAIN_ALL) {
|
|
|
357786 |
/* bdrv_drain_all() drains both src and target */
|
|
|
357786 |
@@ -921,7 +969,7 @@ static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
g_assert_true(job->job.paused);
|
|
|
357786 |
g_assert_false(job->job.busy); /* The job is paused */
|
|
|
357786 |
|
|
|
357786 |
- do_drain_end_unlocked(drain_type, src);
|
|
|
357786 |
+ do_drain_end_unlocked(drain_type, drain_bs);
|
|
|
357786 |
|
|
|
357786 |
if (use_iothread) {
|
|
|
357786 |
/* paused is reset in the I/O thread, wait for it */
|
|
|
357786 |
@@ -969,7 +1017,7 @@ static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
|
|
|
357786 |
blk_unref(blk_src);
|
|
|
357786 |
blk_unref(blk_target);
|
|
|
357786 |
- bdrv_unref(src);
|
|
|
357786 |
+ bdrv_unref(src_overlay);
|
|
|
357786 |
bdrv_unref(target);
|
|
|
357786 |
|
|
|
357786 |
if (iothread) {
|
|
|
357786 |
@@ -977,6 +1025,19 @@ static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
}
|
|
|
357786 |
}
|
|
|
357786 |
|
|
|
357786 |
+static void test_blockjob_common(enum drain_type drain_type, bool use_iothread,
|
|
|
357786 |
+ enum test_job_result result)
|
|
|
357786 |
+{
|
|
|
357786 |
+ test_blockjob_common_drain_node(drain_type, use_iothread, result,
|
|
|
357786 |
+ TEST_JOB_DRAIN_SRC);
|
|
|
357786 |
+ test_blockjob_common_drain_node(drain_type, use_iothread, result,
|
|
|
357786 |
+ TEST_JOB_DRAIN_SRC_CHILD);
|
|
|
357786 |
+ if (drain_type == BDRV_SUBTREE_DRAIN) {
|
|
|
357786 |
+ test_blockjob_common_drain_node(drain_type, use_iothread, result,
|
|
|
357786 |
+ TEST_JOB_DRAIN_SRC_PARENT);
|
|
|
357786 |
+ }
|
|
|
357786 |
+}
|
|
|
357786 |
+
|
|
|
357786 |
static void test_blockjob_drain_all(void)
|
|
|
357786 |
{
|
|
|
357786 |
test_blockjob_common(BDRV_DRAIN_ALL, false, TEST_JOB_SUCCESS);
|
|
|
357786 |
--
|
|
|
357786 |
1.8.3.1
|
|
|
357786 |
|