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-common.h"
  28#include "qemu/job.h"
  29#include "qapi/qapi-commands-job.h"
  30#include "qapi/error.h"
  31#include "trace-root.h"
  32
  33/* Get a job using its ID and acquire its AioContext */
  34static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
  35{
  36    Job *job;
  37
  38    *aio_context = NULL;
  39
  40    job = job_get(id);
  41    if (!job) {
  42        error_setg(errp, "Job not found");
  43        return NULL;
  44    }
  45
  46    *aio_context = job->aio_context;
  47    aio_context_acquire(*aio_context);
  48
  49    return job;
  50}
  51
  52void qmp_job_cancel(const char *id, Error **errp)
  53{
  54    AioContext *aio_context;
  55    Job *job = find_job(id, &aio_context, errp);
  56
  57    if (!job) {
  58        return;
  59    }
  60
  61    trace_qmp_job_cancel(job);
  62    job_user_cancel(job, true, errp);
  63    aio_context_release(aio_context);
  64}
  65
  66void qmp_job_pause(const char *id, Error **errp)
  67{
  68    AioContext *aio_context;
  69    Job *job = find_job(id, &aio_context, errp);
  70
  71    if (!job) {
  72        return;
  73    }
  74
  75    trace_qmp_job_pause(job);
  76    job_user_pause(job, errp);
  77    aio_context_release(aio_context);
  78}
  79
  80void qmp_job_resume(const char *id, Error **errp)
  81{
  82    AioContext *aio_context;
  83    Job *job = find_job(id, &aio_context, errp);
  84
  85    if (!job) {
  86        return;
  87    }
  88
  89    trace_qmp_job_resume(job);
  90    job_user_resume(job, errp);
  91    aio_context_release(aio_context);
  92}
  93
  94void qmp_job_complete(const char *id, Error **errp)
  95{
  96    AioContext *aio_context;
  97    Job *job = find_job(id, &aio_context, errp);
  98
  99    if (!job) {
 100        return;
 101    }
 102
 103    trace_qmp_job_complete(job);
 104    job_complete(job, errp);
 105    aio_context_release(aio_context);
 106}
 107
 108void qmp_job_finalize(const char *id, Error **errp)
 109{
 110    AioContext *aio_context;
 111    Job *job = find_job(id, &aio_context, errp);
 112
 113    if (!job) {
 114        return;
 115    }
 116
 117    trace_qmp_job_finalize(job);
 118    job_finalize(job, errp);
 119    aio_context_release(aio_context);
 120}
 121
 122void qmp_job_dismiss(const char *id, Error **errp)
 123{
 124    AioContext *aio_context;
 125    Job *job = find_job(id, &aio_context, errp);
 126
 127    if (!job) {
 128        return;
 129    }
 130
 131    trace_qmp_job_dismiss(job);
 132    job_dismiss(&job, errp);
 133    aio_context_release(aio_context);
 134}
 135
 136static JobInfo *job_query_single(Job *job, Error **errp)
 137{
 138    JobInfo *info;
 139
 140    assert(!job_is_internal(job));
 141
 142    info = g_new(JobInfo, 1);
 143    *info = (JobInfo) {
 144        .id                 = g_strdup(job->id),
 145        .type               = job_type(job),
 146        .status             = job->status,
 147        .current_progress   = job->progress_current,
 148        .total_progress     = job->progress_total,
 149        .has_error          = !!job->err,
 150        .error              = job->err ? \
 151                              g_strdup(error_get_pretty(job->err)) : NULL,
 152    };
 153
 154    return info;
 155}
 156
 157JobInfoList *qmp_query_jobs(Error **errp)
 158{
 159    JobInfoList *head = NULL, **p_next = &head;
 160    Job *job;
 161
 162    for (job = job_next(NULL); job; job = job_next(job)) {
 163        JobInfoList *elem;
 164        AioContext *aio_context;
 165
 166        if (job_is_internal(job)) {
 167            continue;
 168        }
 169        elem = g_new0(JobInfoList, 1);
 170        aio_context = job->aio_context;
 171        aio_context_acquire(aio_context);
 172        elem->value = job_query_single(job, errp);
 173        aio_context_release(aio_context);
 174        if (!elem->value) {
 175            g_free(elem);
 176            qapi_free_JobInfoList(head);
 177            return NULL;
 178        }
 179        *p_next = elem;
 180        p_next = &elem->next;
 181    }
 182
 183    return head;
 184}
 185