*/
#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)
}
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);
}
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;
+}