xref: /qemu/job-qmp.c (revision b660a84b)
11a90bc81SKevin Wolf /*
21a90bc81SKevin Wolf  * QMP interface for background jobs
31a90bc81SKevin Wolf  *
41a90bc81SKevin Wolf  * Copyright (c) 2011 IBM Corp.
51a90bc81SKevin Wolf  * Copyright (c) 2012, 2018 Red Hat, Inc.
61a90bc81SKevin Wolf  *
71a90bc81SKevin Wolf  * Permission is hereby granted, free of charge, to any person obtaining a copy
81a90bc81SKevin Wolf  * of this software and associated documentation files (the "Software"), to deal
91a90bc81SKevin Wolf  * in the Software without restriction, including without limitation the rights
101a90bc81SKevin Wolf  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111a90bc81SKevin Wolf  * copies of the Software, and to permit persons to whom the Software is
121a90bc81SKevin Wolf  * furnished to do so, subject to the following conditions:
131a90bc81SKevin Wolf  *
141a90bc81SKevin Wolf  * The above copyright notice and this permission notice shall be included in
151a90bc81SKevin Wolf  * all copies or substantial portions of the Software.
161a90bc81SKevin Wolf  *
171a90bc81SKevin Wolf  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181a90bc81SKevin Wolf  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191a90bc81SKevin Wolf  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
201a90bc81SKevin Wolf  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211a90bc81SKevin Wolf  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221a90bc81SKevin Wolf  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
231a90bc81SKevin Wolf  * THE SOFTWARE.
241a90bc81SKevin Wolf  */
251a90bc81SKevin Wolf 
261a90bc81SKevin Wolf #include "qemu/osdep.h"
271a90bc81SKevin Wolf #include "qemu/job.h"
281a90bc81SKevin Wolf #include "qapi/qapi-commands-job.h"
291a90bc81SKevin Wolf #include "qapi/error.h"
301a90bc81SKevin Wolf #include "trace-root.h"
311a90bc81SKevin Wolf 
321a90bc81SKevin Wolf /* Get a job using its ID and acquire its AioContext */
331a90bc81SKevin Wolf static Job *find_job(const char *id, AioContext **aio_context, Error **errp)
341a90bc81SKevin Wolf {
351a90bc81SKevin Wolf     Job *job;
361a90bc81SKevin Wolf 
371a90bc81SKevin Wolf     *aio_context = NULL;
381a90bc81SKevin Wolf 
391a90bc81SKevin Wolf     job = job_get(id);
401a90bc81SKevin Wolf     if (!job) {
411a90bc81SKevin Wolf         error_setg(errp, "Job not found");
421a90bc81SKevin Wolf         return NULL;
431a90bc81SKevin Wolf     }
441a90bc81SKevin Wolf 
451a90bc81SKevin Wolf     *aio_context = job->aio_context;
461a90bc81SKevin Wolf     aio_context_acquire(*aio_context);
471a90bc81SKevin Wolf 
481a90bc81SKevin Wolf     return job;
491a90bc81SKevin Wolf }
501a90bc81SKevin Wolf 
511a90bc81SKevin Wolf void qmp_job_cancel(const char *id, Error **errp)
521a90bc81SKevin Wolf {
531a90bc81SKevin Wolf     AioContext *aio_context;
541a90bc81SKevin Wolf     Job *job = find_job(id, &aio_context, errp);
551a90bc81SKevin Wolf 
561a90bc81SKevin Wolf     if (!job) {
571a90bc81SKevin Wolf         return;
581a90bc81SKevin Wolf     }
591a90bc81SKevin Wolf 
601a90bc81SKevin Wolf     trace_qmp_job_cancel(job);
611a90bc81SKevin Wolf     job_user_cancel(job, true, errp);
621a90bc81SKevin Wolf     aio_context_release(aio_context);
631a90bc81SKevin Wolf }
641a90bc81SKevin Wolf 
651a90bc81SKevin Wolf void qmp_job_pause(const char *id, Error **errp)
661a90bc81SKevin Wolf {
671a90bc81SKevin Wolf     AioContext *aio_context;
681a90bc81SKevin Wolf     Job *job = find_job(id, &aio_context, errp);
691a90bc81SKevin Wolf 
701a90bc81SKevin Wolf     if (!job) {
711a90bc81SKevin Wolf         return;
721a90bc81SKevin Wolf     }
731a90bc81SKevin Wolf 
741a90bc81SKevin Wolf     trace_qmp_job_pause(job);
751a90bc81SKevin Wolf     job_user_pause(job, errp);
761a90bc81SKevin Wolf     aio_context_release(aio_context);
771a90bc81SKevin Wolf }
781a90bc81SKevin Wolf 
791a90bc81SKevin Wolf void qmp_job_resume(const char *id, Error **errp)
801a90bc81SKevin Wolf {
811a90bc81SKevin Wolf     AioContext *aio_context;
821a90bc81SKevin Wolf     Job *job = find_job(id, &aio_context, errp);
831a90bc81SKevin Wolf 
841a90bc81SKevin Wolf     if (!job) {
851a90bc81SKevin Wolf         return;
861a90bc81SKevin Wolf     }
871a90bc81SKevin Wolf 
881a90bc81SKevin Wolf     trace_qmp_job_resume(job);
891a90bc81SKevin Wolf     job_user_resume(job, errp);
901a90bc81SKevin Wolf     aio_context_release(aio_context);
911a90bc81SKevin Wolf }
921a90bc81SKevin Wolf 
931a90bc81SKevin Wolf void qmp_job_complete(const char *id, Error **errp)
941a90bc81SKevin Wolf {
951a90bc81SKevin Wolf     AioContext *aio_context;
961a90bc81SKevin Wolf     Job *job = find_job(id, &aio_context, errp);
971a90bc81SKevin Wolf 
981a90bc81SKevin Wolf     if (!job) {
991a90bc81SKevin Wolf         return;
1001a90bc81SKevin Wolf     }
1011a90bc81SKevin Wolf 
1021a90bc81SKevin Wolf     trace_qmp_job_complete(job);
1031a90bc81SKevin Wolf     job_complete(job, errp);
1041a90bc81SKevin Wolf     aio_context_release(aio_context);
1051a90bc81SKevin Wolf }
1061a90bc81SKevin Wolf 
1071a90bc81SKevin Wolf void qmp_job_finalize(const char *id, Error **errp)
1081a90bc81SKevin Wolf {
1091a90bc81SKevin Wolf     AioContext *aio_context;
1101a90bc81SKevin Wolf     Job *job = find_job(id, &aio_context, errp);
1111a90bc81SKevin Wolf 
1121a90bc81SKevin Wolf     if (!job) {
1131a90bc81SKevin Wolf         return;
1141a90bc81SKevin Wolf     }
1151a90bc81SKevin Wolf 
1161a90bc81SKevin Wolf     trace_qmp_job_finalize(job);
117*b660a84bSStefan Reiter     job_ref(job);
1181a90bc81SKevin Wolf     job_finalize(job, errp);
119*b660a84bSStefan Reiter 
120*b660a84bSStefan Reiter     /*
121*b660a84bSStefan Reiter      * Job's context might have changed via job_finalize (and job_txn_apply
122*b660a84bSStefan Reiter      * automatically acquires the new one), so make sure we release the correct
123*b660a84bSStefan Reiter      * one.
124*b660a84bSStefan Reiter      */
125*b660a84bSStefan Reiter     aio_context = job->aio_context;
126*b660a84bSStefan Reiter     job_unref(job);
1271a90bc81SKevin Wolf     aio_context_release(aio_context);
1281a90bc81SKevin Wolf }
1291a90bc81SKevin Wolf 
1301a90bc81SKevin Wolf void qmp_job_dismiss(const char *id, Error **errp)
1311a90bc81SKevin Wolf {
1321a90bc81SKevin Wolf     AioContext *aio_context;
1331a90bc81SKevin Wolf     Job *job = find_job(id, &aio_context, errp);
1341a90bc81SKevin Wolf 
1351a90bc81SKevin Wolf     if (!job) {
1361a90bc81SKevin Wolf         return;
1371a90bc81SKevin Wolf     }
1381a90bc81SKevin Wolf 
1391a90bc81SKevin Wolf     trace_qmp_job_dismiss(job);
1401a90bc81SKevin Wolf     job_dismiss(&job, errp);
1411a90bc81SKevin Wolf     aio_context_release(aio_context);
1421a90bc81SKevin Wolf }
143456273b0SKevin Wolf 
144456273b0SKevin Wolf static JobInfo *job_query_single(Job *job, Error **errp)
145456273b0SKevin Wolf {
146456273b0SKevin Wolf     JobInfo *info;
147456273b0SKevin Wolf 
148456273b0SKevin Wolf     assert(!job_is_internal(job));
149456273b0SKevin Wolf 
150456273b0SKevin Wolf     info = g_new(JobInfo, 1);
151456273b0SKevin Wolf     *info = (JobInfo) {
152456273b0SKevin Wolf         .id                 = g_strdup(job->id),
153456273b0SKevin Wolf         .type               = job_type(job),
154456273b0SKevin Wolf         .status             = job->status,
15501fe1ca9SVladimir Sementsov-Ogievskiy         .current_progress   = job->progress.current,
15601fe1ca9SVladimir Sementsov-Ogievskiy         .total_progress     = job->progress.total,
1573d1f8b07SJohn Snow         .has_error          = !!job->err,
1583d1f8b07SJohn Snow         .error              = job->err ? \
1593d1f8b07SJohn Snow                               g_strdup(error_get_pretty(job->err)) : NULL,
160456273b0SKevin Wolf     };
161456273b0SKevin Wolf 
162456273b0SKevin Wolf     return info;
163456273b0SKevin Wolf }
164456273b0SKevin Wolf 
165456273b0SKevin Wolf JobInfoList *qmp_query_jobs(Error **errp)
166456273b0SKevin Wolf {
167456273b0SKevin Wolf     JobInfoList *head = NULL, **p_next = &head;
168456273b0SKevin Wolf     Job *job;
169456273b0SKevin Wolf 
170456273b0SKevin Wolf     for (job = job_next(NULL); job; job = job_next(job)) {
171456273b0SKevin Wolf         JobInfoList *elem;
172456273b0SKevin Wolf         AioContext *aio_context;
173456273b0SKevin Wolf 
174456273b0SKevin Wolf         if (job_is_internal(job)) {
175456273b0SKevin Wolf             continue;
176456273b0SKevin Wolf         }
177456273b0SKevin Wolf         elem = g_new0(JobInfoList, 1);
178456273b0SKevin Wolf         aio_context = job->aio_context;
179456273b0SKevin Wolf         aio_context_acquire(aio_context);
180456273b0SKevin Wolf         elem->value = job_query_single(job, errp);
181456273b0SKevin Wolf         aio_context_release(aio_context);
182456273b0SKevin Wolf         if (!elem->value) {
183456273b0SKevin Wolf             g_free(elem);
184456273b0SKevin Wolf             qapi_free_JobInfoList(head);
185456273b0SKevin Wolf             return NULL;
186456273b0SKevin Wolf         }
187456273b0SKevin Wolf         *p_next = elem;
188456273b0SKevin Wolf         p_next = &elem->next;
189456273b0SKevin Wolf     }
190456273b0SKevin Wolf 
191456273b0SKevin Wolf     return head;
192456273b0SKevin Wolf }
193