]> git.proxmox.com Git - mirror_qemu.git/blobdiff - job-qmp.c
block/export: Conditionally ignore set-context error
[mirror_qemu.git] / job-qmp.c
index b2e18cfd9c19827aa40f94d8f583d49da235ca6c..829a28aa70e3e0a880fe2007ba8ca75a9fc4cbeb 100644 (file)
--- a/job-qmp.c
+++ b/job-qmp.c
  */
 
 #include "qemu/osdep.h"
-#include "qemu-common.h"
 #include "qemu/job.h"
 #include "qapi/qapi-commands-job.h"
 #include "qapi/error.h"
-#include "trace-root.h"
+#include "trace/trace-root.h"
 
 /* Get a job using its ID and acquire its AioContext */
 static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
@@ -115,7 +114,16 @@ void qmp_job_finalize(const char *id, Error **errp)
     }
 
     trace_qmp_job_finalize(job);
+    job_ref(job);
     job_finalize(job, errp);
+
+    /*
+     * Job's context might have changed via job_finalize (and job_txn_apply
+     * automatically acquires the new one), so make sure we release the correct
+     * one.
+     */
+    aio_context = job->aio_context;
+    job_unref(job);
     aio_context_release(aio_context);
 }
 
@@ -132,3 +140,54 @@ void qmp_job_dismiss(const char *id, Error **errp)
     job_dismiss(&job, errp);
     aio_context_release(aio_context);
 }
+
+static JobInfo *job_query_single(Job *job, Error **errp)
+{
+    JobInfo *info;
+    uint64_t progress_current;
+    uint64_t progress_total;
+
+    assert(!job_is_internal(job));
+    progress_get_snapshot(&job->progress, &progress_current,
+                          &progress_total);
+
+    info = g_new(JobInfo, 1);
+    *info = (JobInfo) {
+        .id                 = g_strdup(job->id),
+        .type               = job_type(job),
+        .status             = job->status,
+        .current_progress   = progress_current,
+        .total_progress     = progress_total,
+        .has_error          = !!job->err,
+        .error              = job->err ? \
+                              g_strdup(error_get_pretty(job->err)) : NULL,
+    };
+
+    return info;
+}
+
+JobInfoList *qmp_query_jobs(Error **errp)
+{
+    JobInfoList *head = NULL, **tail = &head;
+    Job *job;
+
+    for (job = job_next(NULL); job; job = job_next(job)) {
+        JobInfo *value;
+        AioContext *aio_context;
+
+        if (job_is_internal(job)) {
+            continue;
+        }
+        aio_context = job->aio_context;
+        aio_context_acquire(aio_context);
+        value = job_query_single(job, errp);
+        aio_context_release(aio_context);
+        if (!value) {
+            qapi_free_JobInfoList(head);
+            return NULL;
+        }
+        QAPI_LIST_APPEND(tail, value);
+    }
+
+    return head;
+}