qemu/job-qmp.c
<<
>>
Prefs
   1/*
   2 * QMP interface for background jobs
   3 *
   4 * Copyright (c) 2011 IBM Corp.
   5 * Copyright (c) 2012, 2018 Red Hat, Inc.
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "qemu/job.h"
  28#include "qapi/qapi-commands-job.h"
  29#include "qapi/error.h"
  30#include "trace/trace-root.h"
  31
  32/*
  33 * Get a job using its ID. Called with job_mutex held.
  34 */
  35static Job *find_job_locked(const char *id, Error **errp)
  36{
  37    Job *job;
  38
  39    job = job_get_locked(id);
  40    if (!job) {
  41        error_setg(errp, "Job not found");
  42        return NULL;
  43    }
  44
  45    return job;
  46}
  47
  48void qmp_job_cancel(const char *id, Error **errp)
  49{
  50    Job *job;
  51
  52    JOB_LOCK_GUARD();
  53    job = find_job_locked(id, errp);
  54
  55    if (!job) {
  56        return;
  57    }
  58
  59    trace_qmp_job_cancel(job);
  60    job_user_cancel_locked(job, true, errp);
  61}
  62
  63void qmp_job_pause(const char *id, Error **errp)
  64{
  65    Job *job;
  66
  67    JOB_LOCK_GUARD();
  68    job = find_job_locked(id, errp);
  69
  70    if (!job) {
  71        return;
  72    }
  73
  74    trace_qmp_job_pause(job);
  75    job_user_pause_locked(job, errp);
  76}
  77
  78void qmp_job_resume(const char *id, Error **errp)
  79{
  80    Job *job;
  81
  82    JOB_LOCK_GUARD();
  83    job = find_job_locked(id, errp);
  84
  85    if (!job) {
  86        return;
  87    }
  88
  89    trace_qmp_job_resume(job);
  90    job_user_resume_locked(job, errp);
  91}
  92
  93void qmp_job_complete(const char *id, Error **errp)
  94{
  95    Job *job;
  96
  97    JOB_LOCK_GUARD();
  98    job = find_job_locked(id, errp);
  99
 100    if (!job) {
 101        return;
 102    }
 103
 104    trace_qmp_job_complete(job);
 105    job_complete_locked(job, errp);
 106}
 107
 108void qmp_job_finalize(const char *id, Error **errp)
 109{
 110    Job *job;
 111
 112    JOB_LOCK_GUARD();
 113    job = find_job_locked(id, errp);
 114
 115    if (!job) {
 116        return;
 117    }
 118
 119    trace_qmp_job_finalize(job);
 120    job_ref_locked(job);
 121    job_finalize_locked(job, errp);
 122
 123    job_unref_locked(job);
 124}
 125
 126void qmp_job_dismiss(const char *id, Error **errp)
 127{
 128    Job *job;
 129
 130    JOB_LOCK_GUARD();
 131    job = find_job_locked(id, errp);
 132
 133    if (!job) {
 134        return;
 135    }
 136
 137    trace_qmp_job_dismiss(job);
 138    job_dismiss_locked(&job, errp);
 139}
 140
 141/* Called with job_mutex held. */
 142static JobInfo *job_query_single_locked(Job *job, Error **errp)
 143{
 144    JobInfo *info;
 145    uint64_t progress_current;
 146    uint64_t progress_total;
 147
 148    assert(!job_is_internal(job));
 149    progress_get_snapshot(&job->progress, &progress_current,
 150                          &progress_total);
 151
 152    info = g_new(JobInfo, 1);
 153    *info = (JobInfo) {
 154        .id                 = g_strdup(job->id),
 155        .type               = job_type(job),
 156        .status             = job->status,
 157        .current_progress   = progress_current,
 158        .total_progress     = progress_total,
 159        .has_error          = !!job->err,
 160        .error              = job->err ? \
 161                              g_strdup(error_get_pretty(job->err)) : NULL,
 162    };
 163
 164    return info;
 165}
 166
 167JobInfoList *qmp_query_jobs(Error **errp)
 168{
 169    JobInfoList *head = NULL, **tail = &head;
 170    Job *job;
 171
 172    JOB_LOCK_GUARD();
 173
 174    for (job = job_next_locked(NULL); job; job = job_next_locked(job)) {
 175        JobInfo *value;
 176
 177        if (job_is_internal(job)) {
 178            continue;
 179        }
 180        value = job_query_single_locked(job, errp);
 181        if (!value) {
 182            qapi_free_JobInfoList(head);
 183            return NULL;
 184        }
 185        QAPI_LIST_APPEND(tail, value);
 186    }
 187
 188    return head;
 189}
 190