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