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