26ba25
From 941f553a991d152f7691f5b1e3d8459b4843a51b Mon Sep 17 00:00:00 2001
26ba25
From: Kevin Wolf <kwolf@redhat.com>
26ba25
Date: Tue, 26 Jun 2018 09:48:15 +0200
26ba25
Subject: [PATCH 107/268] job: Add job_event_*()
26ba25
26ba25
RH-Author: Kevin Wolf <kwolf@redhat.com>
26ba25
Message-id: <20180626094856.6924-33-kwolf@redhat.com>
26ba25
Patchwork-id: 81092
26ba25
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH v2 32/73] job: Add job_event_*()
26ba25
Bugzilla: 1513543
26ba25
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
26ba25
RH-Acked-by: Max Reitz <mreitz@redhat.com>
26ba25
RH-Acked-by: Fam Zheng <famz@redhat.com>
26ba25
26ba25
Go through the Job layer in order to send QMP events. For the moment,
26ba25
these functions only call a notifier in the BlockJob layer that sends
26ba25
the existing commands.
26ba25
26ba25
This uses notifiers rather than JobDriver callbacks because internal
26ba25
users of jobs won't receive QMP events, but might still be interested
26ba25
in getting notified for the events.
26ba25
26ba25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26ba25
Reviewed-by: Max Reitz <mreitz@redhat.com>
26ba25
(cherry picked from commit 139a9f020d49e9f863e0d46fd3d0b440dfb3b9d7)
26ba25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26ba25
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
26ba25
---
26ba25
 blockjob.c               | 41 +++++++++++++++++++++++++++--------------
26ba25
 include/block/blockjob.h |  9 +++++++++
26ba25
 include/qemu/job.h       | 18 ++++++++++++++++++
26ba25
 job.c                    | 19 +++++++++++++++++++
26ba25
 4 files changed, 73 insertions(+), 14 deletions(-)
26ba25
26ba25
diff --git a/blockjob.c b/blockjob.c
26ba25
index b4334fb..05d7921 100644
26ba25
--- a/blockjob.c
26ba25
+++ b/blockjob.c
26ba25
@@ -36,10 +36,6 @@
26ba25
 #include "qemu/coroutine.h"
26ba25
 #include "qemu/timer.h"
26ba25
 
26ba25
-static void block_job_event_cancelled(BlockJob *job);
26ba25
-static void block_job_event_completed(BlockJob *job, const char *msg);
26ba25
-static void block_job_event_pending(BlockJob *job);
26ba25
-
26ba25
 /* Transactional group of block jobs */
26ba25
 struct BlockJobTxn {
26ba25
 
26ba25
@@ -352,13 +348,9 @@ static int block_job_finalize_single(BlockJob *job)
26ba25
     /* Emit events only if we actually started */
26ba25
     if (job_started(&job->job)) {
26ba25
         if (job_is_cancelled(&job->job)) {
26ba25
-            block_job_event_cancelled(job);
26ba25
+            job_event_cancelled(&job->job);
26ba25
         } else {
26ba25
-            const char *msg = NULL;
26ba25
-            if (job->ret < 0) {
26ba25
-                msg = strerror(-job->ret);
26ba25
-            }
26ba25
-            block_job_event_completed(job, msg);
26ba25
+            job_event_completed(&job->job);
26ba25
         }
26ba25
     }
26ba25
 
26ba25
@@ -504,7 +496,7 @@ static int block_job_transition_to_pending(BlockJob *job)
26ba25
 {
26ba25
     job_state_transition(&job->job, JOB_STATUS_PENDING);
26ba25
     if (!job->job.auto_finalize) {
26ba25
-        block_job_event_pending(job);
26ba25
+        job_event_pending(&job->job);
26ba25
     }
26ba25
     return 0;
26ba25
 }
26ba25
@@ -712,8 +704,10 @@ static void block_job_iostatus_set_err(BlockJob *job, int error)
26ba25
     }
26ba25
 }
26ba25
 
26ba25
-static void block_job_event_cancelled(BlockJob *job)
26ba25
+static void block_job_event_cancelled(Notifier *n, void *opaque)
26ba25
 {
26ba25
+    BlockJob *job = opaque;
26ba25
+
26ba25
     if (block_job_is_internal(job)) {
26ba25
         return;
26ba25
     }
26ba25
@@ -726,12 +720,19 @@ static void block_job_event_cancelled(BlockJob *job)
26ba25
                                         &error_abort);
26ba25
 }
26ba25
 
26ba25
-static void block_job_event_completed(BlockJob *job, const char *msg)
26ba25
+static void block_job_event_completed(Notifier *n, void *opaque)
26ba25
 {
26ba25
+    BlockJob *job = opaque;
26ba25
+    const char *msg = NULL;
26ba25
+
26ba25
     if (block_job_is_internal(job)) {
26ba25
         return;
26ba25
     }
26ba25
 
26ba25
+    if (job->ret < 0) {
26ba25
+        msg = strerror(-job->ret);
26ba25
+    }
26ba25
+
26ba25
     qapi_event_send_block_job_completed(job_type(&job->job),
26ba25
                                         job->job.id,
26ba25
                                         job->len,
26ba25
@@ -742,8 +743,10 @@ static void block_job_event_completed(BlockJob *job, const char *msg)
26ba25
                                         &error_abort);
26ba25
 }
26ba25
 
26ba25
-static void block_job_event_pending(BlockJob *job)
26ba25
+static void block_job_event_pending(Notifier *n, void *opaque)
26ba25
 {
26ba25
+    BlockJob *job = opaque;
26ba25
+
26ba25
     if (block_job_is_internal(job)) {
26ba25
         return;
26ba25
     }
26ba25
@@ -799,6 +802,16 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
26ba25
     job->cb            = cb;
26ba25
     job->opaque        = opaque;
26ba25
 
26ba25
+    job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
26ba25
+    job->finalize_completed_notifier.notify = block_job_event_completed;
26ba25
+    job->pending_notifier.notify = block_job_event_pending;
26ba25
+
26ba25
+    notifier_list_add(&job->job.on_finalize_cancelled,
26ba25
+                      &job->finalize_cancelled_notifier);
26ba25
+    notifier_list_add(&job->job.on_finalize_completed,
26ba25
+                      &job->finalize_completed_notifier);
26ba25
+    notifier_list_add(&job->job.on_pending, &job->pending_notifier);
26ba25
+
26ba25
     error_setg(&job->blocker, "block device is in use by block job: %s",
26ba25
                job_type_str(&job->job));
26ba25
     block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
26ba25
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
26ba25
index f9aaaaa..aef0629 100644
26ba25
--- a/include/block/blockjob.h
26ba25
+++ b/include/block/blockjob.h
26ba25
@@ -82,6 +82,15 @@ typedef struct BlockJob {
26ba25
     /** Block other operations when block job is running */
26ba25
     Error *blocker;
26ba25
 
26ba25
+    /** Called when a cancelled job is finalised. */
26ba25
+    Notifier finalize_cancelled_notifier;
26ba25
+
26ba25
+    /** Called when a successfully completed job is finalised. */
26ba25
+    Notifier finalize_completed_notifier;
26ba25
+
26ba25
+    /** Called when the job transitions to PENDING */
26ba25
+    Notifier pending_notifier;
26ba25
+
26ba25
     /** BlockDriverStates that are involved in this block job */
26ba25
     GSList *nodes;
26ba25
 
26ba25
diff --git a/include/qemu/job.h b/include/qemu/job.h
26ba25
index 9783e40..14d9377 100644
26ba25
--- a/include/qemu/job.h
26ba25
+++ b/include/qemu/job.h
26ba25
@@ -105,6 +105,15 @@ typedef struct Job {
26ba25
     /** True if this job should automatically dismiss itself */
26ba25
     bool auto_dismiss;
26ba25
 
26ba25
+    /** Notifiers called when a cancelled job is finalised */
26ba25
+    NotifierList on_finalize_cancelled;
26ba25
+
26ba25
+    /** Notifiers called when a successfully completed job is finalised */
26ba25
+    NotifierList on_finalize_completed;
26ba25
+
26ba25
+    /** Notifiers called when the job transitions to PENDING */
26ba25
+    NotifierList on_pending;
26ba25
+
26ba25
     /** Element of the list of jobs */
26ba25
     QLIST_ENTRY(Job) job_list;
26ba25
 } Job;
26ba25
@@ -182,6 +191,15 @@ void job_ref(Job *job);
26ba25
  */
26ba25
 void job_unref(Job *job);
26ba25
 
26ba25
+/** To be called when a cancelled job is finalised. */
26ba25
+void job_event_cancelled(Job *job);
26ba25
+
26ba25
+/** To be called when a successfully completed job is finalised. */
26ba25
+void job_event_completed(Job *job);
26ba25
+
26ba25
+/** To be called when the job transitions to PENDING */
26ba25
+void job_event_pending(Job *job);
26ba25
+
26ba25
 /**
26ba25
  * Conditionally enter the job coroutine if the job is ready to run, not
26ba25
  * already busy and fn() returns true. fn() is called while under the job_lock
26ba25
diff --git a/job.c b/job.c
26ba25
index dd46170..817c3b4 100644
26ba25
--- a/job.c
26ba25
+++ b/job.c
26ba25
@@ -215,6 +215,10 @@ void *job_create(const char *job_id, const JobDriver *driver, AioContext *ctx,
26ba25
     job->auto_finalize = !(flags & JOB_MANUAL_FINALIZE);
26ba25
     job->auto_dismiss  = !(flags & JOB_MANUAL_DISMISS);
26ba25
 
26ba25
+    notifier_list_init(&job->on_finalize_cancelled);
26ba25
+    notifier_list_init(&job->on_finalize_completed);
26ba25
+    notifier_list_init(&job->on_pending);
26ba25
+
26ba25
     job_state_transition(job, JOB_STATUS_CREATED);
26ba25
     aio_timer_init(qemu_get_aio_context(), &job->sleep_timer,
26ba25
                    QEMU_CLOCK_REALTIME, SCALE_NS,
26ba25
@@ -247,6 +251,21 @@ void job_unref(Job *job)
26ba25
     }
26ba25
 }
26ba25
 
26ba25
+void job_event_cancelled(Job *job)
26ba25
+{
26ba25
+    notifier_list_notify(&job->on_finalize_cancelled, job);
26ba25
+}
26ba25
+
26ba25
+void job_event_completed(Job *job)
26ba25
+{
26ba25
+    notifier_list_notify(&job->on_finalize_completed, job);
26ba25
+}
26ba25
+
26ba25
+void job_event_pending(Job *job)
26ba25
+{
26ba25
+    notifier_list_notify(&job->on_pending, job);
26ba25
+}
26ba25
+
26ba25
 void job_enter_cond(Job *job, bool(*fn)(Job *job))
26ba25
 {
26ba25
     if (!job_started(job)) {
26ba25
-- 
26ba25
1.8.3.1
26ba25