|
|
1bdc94 |
From 29117d8ea323429138020a8de63119f15da01d83 Mon Sep 17 00:00:00 2001
|
|
|
1bdc94 |
From: Kevin Wolf <kwolf@redhat.com>
|
|
|
1bdc94 |
Date: Fri, 14 Sep 2018 10:55:25 +0200
|
|
|
1bdc94 |
Subject: [PATCH 34/49] blockjob: Wake up BDS when job becomes idle
|
|
|
1bdc94 |
|
|
|
1bdc94 |
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
|
1bdc94 |
Message-id: <20180914105540.18077-28-kwolf@redhat.com>
|
|
|
1bdc94 |
Patchwork-id: 82180
|
|
|
1bdc94 |
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 27/42] blockjob: Wake up BDS when job becomes idle
|
|
|
1bdc94 |
Bugzilla: 1601212
|
|
|
1bdc94 |
RH-Acked-by: John Snow <jsnow@redhat.com>
|
|
|
1bdc94 |
RH-Acked-by: Max Reitz <mreitz@redhat.com>
|
|
|
1bdc94 |
RH-Acked-by: Fam Zheng <famz@redhat.com>
|
|
|
1bdc94 |
|
|
|
1bdc94 |
In the context of draining a BDS, the .drained_poll callback of block
|
|
|
1bdc94 |
jobs is called. If this returns true (i.e. there is still some activity
|
|
|
1bdc94 |
pending), the drain operation may call aio_poll() with blocking=true to
|
|
|
1bdc94 |
wait for completion.
|
|
|
1bdc94 |
|
|
|
1bdc94 |
As soon as the pending activity is completed and the job finally arrives
|
|
|
1bdc94 |
in a quiescent state (i.e. its coroutine either yields with busy=false
|
|
|
1bdc94 |
or terminates), the block job must notify the aio_poll() loop to wake
|
|
|
1bdc94 |
up, otherwise we get a deadlock if both are running in different
|
|
|
1bdc94 |
threads.
|
|
|
1bdc94 |
|
|
|
1bdc94 |
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
|
1bdc94 |
Reviewed-by: Fam Zheng <famz@redhat.com>
|
|
|
1bdc94 |
Reviewed-by: Max Reitz <mreitz@redhat.com>
|
|
|
1bdc94 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
1bdc94 |
---
|
|
|
1bdc94 |
blockjob.c | 18 ++++++++++++++++++
|
|
|
1bdc94 |
include/block/blockjob.h | 13 +++++++++++++
|
|
|
1bdc94 |
include/qemu/job.h | 3 +++
|
|
|
1bdc94 |
job.c | 7 +++++++
|
|
|
1bdc94 |
4 files changed, 41 insertions(+)
|
|
|
1bdc94 |
|
|
|
1bdc94 |
diff --git a/blockjob.c b/blockjob.c
|
|
|
1bdc94 |
index be5903a..8d27e8e 100644
|
|
|
1bdc94 |
--- a/blockjob.c
|
|
|
1bdc94 |
+++ b/blockjob.c
|
|
|
1bdc94 |
@@ -221,6 +221,22 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
|
|
1bdc94 |
return 0;
|
|
|
1bdc94 |
}
|
|
|
1bdc94 |
|
|
|
1bdc94 |
+void block_job_wakeup_all_bdrv(BlockJob *job)
|
|
|
1bdc94 |
+{
|
|
|
1bdc94 |
+ GSList *l;
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
+ for (l = job->nodes; l; l = l->next) {
|
|
|
1bdc94 |
+ BdrvChild *c = l->data;
|
|
|
1bdc94 |
+ bdrv_wakeup(c->bs);
|
|
|
1bdc94 |
+ }
|
|
|
1bdc94 |
+}
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
+static void block_job_on_idle(Notifier *n, void *opaque)
|
|
|
1bdc94 |
+{
|
|
|
1bdc94 |
+ BlockJob *job = opaque;
|
|
|
1bdc94 |
+ block_job_wakeup_all_bdrv(job);
|
|
|
1bdc94 |
+}
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
bool block_job_is_internal(BlockJob *job)
|
|
|
1bdc94 |
{
|
|
|
1bdc94 |
return (job->job.id == NULL);
|
|
|
1bdc94 |
@@ -419,6 +435,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|
|
1bdc94 |
job->finalize_completed_notifier.notify = block_job_event_completed;
|
|
|
1bdc94 |
job->pending_notifier.notify = block_job_event_pending;
|
|
|
1bdc94 |
job->ready_notifier.notify = block_job_event_ready;
|
|
|
1bdc94 |
+ job->idle_notifier.notify = block_job_on_idle;
|
|
|
1bdc94 |
|
|
|
1bdc94 |
notifier_list_add(&job->job.on_finalize_cancelled,
|
|
|
1bdc94 |
&job->finalize_cancelled_notifier);
|
|
|
1bdc94 |
@@ -426,6 +443,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
|
|
1bdc94 |
&job->finalize_completed_notifier);
|
|
|
1bdc94 |
notifier_list_add(&job->job.on_pending, &job->pending_notifier);
|
|
|
1bdc94 |
notifier_list_add(&job->job.on_ready, &job->ready_notifier);
|
|
|
1bdc94 |
+ notifier_list_add(&job->job.on_idle, &job->idle_notifier);
|
|
|
1bdc94 |
|
|
|
1bdc94 |
error_setg(&job->blocker, "block device is in use by block job: %s",
|
|
|
1bdc94 |
job_type_str(&job->job));
|
|
|
1bdc94 |
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
|
|
|
1bdc94 |
index 32c00b7..2290bbb 100644
|
|
|
1bdc94 |
--- a/include/block/blockjob.h
|
|
|
1bdc94 |
+++ b/include/block/blockjob.h
|
|
|
1bdc94 |
@@ -70,6 +70,9 @@ typedef struct BlockJob {
|
|
|
1bdc94 |
/** Called when the job transitions to READY */
|
|
|
1bdc94 |
Notifier ready_notifier;
|
|
|
1bdc94 |
|
|
|
1bdc94 |
+ /** Called when the job coroutine yields or terminates */
|
|
|
1bdc94 |
+ Notifier idle_notifier;
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
/** BlockDriverStates that are involved in this block job */
|
|
|
1bdc94 |
GSList *nodes;
|
|
|
1bdc94 |
} BlockJob;
|
|
|
1bdc94 |
@@ -119,6 +122,16 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
|
|
1bdc94 |
void block_job_remove_all_bdrv(BlockJob *job);
|
|
|
1bdc94 |
|
|
|
1bdc94 |
/**
|
|
|
1bdc94 |
+ * block_job_wakeup_all_bdrv:
|
|
|
1bdc94 |
+ * @job: The block job
|
|
|
1bdc94 |
+ *
|
|
|
1bdc94 |
+ * Calls bdrv_wakeup() for all BlockDriverStates that have been added to the
|
|
|
1bdc94 |
+ * job. This function is to be called whenever child_job_drained_poll() would
|
|
|
1bdc94 |
+ * go from true to false to notify waiting drain requests.
|
|
|
1bdc94 |
+ */
|
|
|
1bdc94 |
+void block_job_wakeup_all_bdrv(BlockJob *job);
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
+/**
|
|
|
1bdc94 |
* block_job_set_speed:
|
|
|
1bdc94 |
* @job: The job to set the speed for.
|
|
|
1bdc94 |
* @speed: The new value
|
|
|
1bdc94 |
diff --git a/include/qemu/job.h b/include/qemu/job.h
|
|
|
1bdc94 |
index fdaa06f..407d549 100644
|
|
|
1bdc94 |
--- a/include/qemu/job.h
|
|
|
1bdc94 |
+++ b/include/qemu/job.h
|
|
|
1bdc94 |
@@ -156,6 +156,9 @@ typedef struct Job {
|
|
|
1bdc94 |
/** Notifiers called when the job transitions to READY */
|
|
|
1bdc94 |
NotifierList on_ready;
|
|
|
1bdc94 |
|
|
|
1bdc94 |
+ /** Notifiers called when the job coroutine yields or terminates */
|
|
|
1bdc94 |
+ NotifierList on_idle;
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
/** Element of the list of jobs */
|
|
|
1bdc94 |
QLIST_ENTRY(Job) job_list;
|
|
|
1bdc94 |
|
|
|
1bdc94 |
diff --git a/job.c b/job.c
|
|
|
1bdc94 |
index db53163..5a0ccc7 100644
|
|
|
1bdc94 |
--- a/job.c
|
|
|
1bdc94 |
+++ b/job.c
|
|
|
1bdc94 |
@@ -397,6 +397,11 @@ static void job_event_ready(Job *job)
|
|
|
1bdc94 |
notifier_list_notify(&job->on_ready, job);
|
|
|
1bdc94 |
}
|
|
|
1bdc94 |
|
|
|
1bdc94 |
+static void job_event_idle(Job *job)
|
|
|
1bdc94 |
+{
|
|
|
1bdc94 |
+ notifier_list_notify(&job->on_idle, job);
|
|
|
1bdc94 |
+}
|
|
|
1bdc94 |
+
|
|
|
1bdc94 |
void job_enter_cond(Job *job, bool(*fn)(Job *job))
|
|
|
1bdc94 |
{
|
|
|
1bdc94 |
if (!job_started(job)) {
|
|
|
1bdc94 |
@@ -442,6 +447,7 @@ static void coroutine_fn job_do_yield(Job *job, uint64_t ns)
|
|
|
1bdc94 |
timer_mod(&job->sleep_timer, ns);
|
|
|
1bdc94 |
}
|
|
|
1bdc94 |
job->busy = false;
|
|
|
1bdc94 |
+ job_event_idle(job);
|
|
|
1bdc94 |
job_unlock();
|
|
|
1bdc94 |
qemu_coroutine_yield();
|
|
|
1bdc94 |
|
|
|
1bdc94 |
@@ -860,6 +866,7 @@ static void coroutine_fn job_co_entry(void *opaque)
|
|
|
1bdc94 |
assert(job && job->driver && job->driver->run);
|
|
|
1bdc94 |
job_pause_point(job);
|
|
|
1bdc94 |
job->ret = job->driver->run(job, &job->err);
|
|
|
1bdc94 |
+ job_event_idle(job);
|
|
|
1bdc94 |
job->deferred_to_main_loop = true;
|
|
|
1bdc94 |
aio_bh_schedule_oneshot(qemu_get_aio_context(), job_exit, job);
|
|
|
1bdc94 |
}
|
|
|
1bdc94 |
--
|
|
|
1bdc94 |
1.8.3.1
|
|
|
1bdc94 |
|