xref: /qemu/job-qmp.c (revision 96241124)
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"
30243af022SPaolo Bonzini #include "trace/trace-root.h"
311a90bc81SKevin Wolf 
3296241124SEmanuele Giuseppe Esposito /*
3396241124SEmanuele Giuseppe Esposito  * Get a job using its ID and acquire its AioContext.
3496241124SEmanuele Giuseppe Esposito  * Called with job_mutex held.
3596241124SEmanuele Giuseppe Esposito  */
3696241124SEmanuele Giuseppe Esposito static Job *find_job_locked(const char *id,
3796241124SEmanuele Giuseppe Esposito                             AioContext **aio_context,
3896241124SEmanuele Giuseppe Esposito                             Error **errp)
391a90bc81SKevin Wolf {
401a90bc81SKevin Wolf     Job *job;
411a90bc81SKevin Wolf 
421a90bc81SKevin Wolf     *aio_context = NULL;
431a90bc81SKevin Wolf 
4496241124SEmanuele Giuseppe Esposito     job = job_get_locked(id);
451a90bc81SKevin Wolf     if (!job) {
461a90bc81SKevin Wolf         error_setg(errp, "Job not found");
471a90bc81SKevin Wolf         return NULL;
481a90bc81SKevin Wolf     }
491a90bc81SKevin Wolf 
501a90bc81SKevin Wolf     *aio_context = job->aio_context;
511a90bc81SKevin Wolf     aio_context_acquire(*aio_context);
521a90bc81SKevin Wolf 
531a90bc81SKevin Wolf     return job;
541a90bc81SKevin Wolf }
551a90bc81SKevin Wolf 
561a90bc81SKevin Wolf void qmp_job_cancel(const char *id, Error **errp)
571a90bc81SKevin Wolf {
581a90bc81SKevin Wolf     AioContext *aio_context;
5996241124SEmanuele Giuseppe Esposito     Job *job;
6096241124SEmanuele Giuseppe Esposito 
6196241124SEmanuele Giuseppe Esposito     JOB_LOCK_GUARD();
6296241124SEmanuele Giuseppe Esposito     job = find_job_locked(id, &aio_context, errp);
631a90bc81SKevin Wolf 
641a90bc81SKevin Wolf     if (!job) {
651a90bc81SKevin Wolf         return;
661a90bc81SKevin Wolf     }
671a90bc81SKevin Wolf 
681a90bc81SKevin Wolf     trace_qmp_job_cancel(job);
6996241124SEmanuele Giuseppe Esposito     job_user_cancel_locked(job, true, errp);
701a90bc81SKevin Wolf     aio_context_release(aio_context);
711a90bc81SKevin Wolf }
721a90bc81SKevin Wolf 
731a90bc81SKevin Wolf void qmp_job_pause(const char *id, Error **errp)
741a90bc81SKevin Wolf {
751a90bc81SKevin Wolf     AioContext *aio_context;
7696241124SEmanuele Giuseppe Esposito     Job *job;
7796241124SEmanuele Giuseppe Esposito 
7896241124SEmanuele Giuseppe Esposito     JOB_LOCK_GUARD();
7996241124SEmanuele Giuseppe Esposito     job = find_job_locked(id, &aio_context, errp);
801a90bc81SKevin Wolf 
811a90bc81SKevin Wolf     if (!job) {
821a90bc81SKevin Wolf         return;
831a90bc81SKevin Wolf     }
841a90bc81SKevin Wolf 
851a90bc81SKevin Wolf     trace_qmp_job_pause(job);
8696241124SEmanuele Giuseppe Esposito     job_user_pause_locked(job, errp);
871a90bc81SKevin Wolf     aio_context_release(aio_context);
881a90bc81SKevin Wolf }
891a90bc81SKevin Wolf 
901a90bc81SKevin Wolf void qmp_job_resume(const char *id, Error **errp)
911a90bc81SKevin Wolf {
921a90bc81SKevin Wolf     AioContext *aio_context;
9396241124SEmanuele Giuseppe Esposito     Job *job;
9496241124SEmanuele Giuseppe Esposito 
9596241124SEmanuele Giuseppe Esposito     JOB_LOCK_GUARD();
9696241124SEmanuele Giuseppe Esposito     job = find_job_locked(id, &aio_context, errp);
971a90bc81SKevin Wolf 
981a90bc81SKevin Wolf     if (!job) {
991a90bc81SKevin Wolf         return;
1001a90bc81SKevin Wolf     }
1011a90bc81SKevin Wolf 
1021a90bc81SKevin Wolf     trace_qmp_job_resume(job);
10396241124SEmanuele Giuseppe Esposito     job_user_resume_locked(job, errp);
1041a90bc81SKevin Wolf     aio_context_release(aio_context);
1051a90bc81SKevin Wolf }
1061a90bc81SKevin Wolf 
1071a90bc81SKevin Wolf void qmp_job_complete(const char *id, Error **errp)
1081a90bc81SKevin Wolf {
1091a90bc81SKevin Wolf     AioContext *aio_context;
11096241124SEmanuele Giuseppe Esposito     Job *job;
11196241124SEmanuele Giuseppe Esposito 
11296241124SEmanuele Giuseppe Esposito     JOB_LOCK_GUARD();
11396241124SEmanuele Giuseppe Esposito     job = find_job_locked(id, &aio_context, errp);
1141a90bc81SKevin Wolf 
1151a90bc81SKevin Wolf     if (!job) {
1161a90bc81SKevin Wolf         return;
1171a90bc81SKevin Wolf     }
1181a90bc81SKevin Wolf 
1191a90bc81SKevin Wolf     trace_qmp_job_complete(job);
12096241124SEmanuele Giuseppe Esposito     job_complete_locked(job, errp);
1211a90bc81SKevin Wolf     aio_context_release(aio_context);
1221a90bc81SKevin Wolf }
1231a90bc81SKevin Wolf 
1241a90bc81SKevin Wolf void qmp_job_finalize(const char *id, Error **errp)
1251a90bc81SKevin Wolf {
1261a90bc81SKevin Wolf     AioContext *aio_context;
12796241124SEmanuele Giuseppe Esposito     Job *job;
12896241124SEmanuele Giuseppe Esposito 
12996241124SEmanuele Giuseppe Esposito     JOB_LOCK_GUARD();
13096241124SEmanuele Giuseppe Esposito     job = find_job_locked(id, &aio_context, errp);
1311a90bc81SKevin Wolf 
1321a90bc81SKevin Wolf     if (!job) {
1331a90bc81SKevin Wolf         return;
1341a90bc81SKevin Wolf     }
1351a90bc81SKevin Wolf 
1361a90bc81SKevin Wolf     trace_qmp_job_finalize(job);
13796241124SEmanuele Giuseppe Esposito     job_ref_locked(job);
13896241124SEmanuele Giuseppe Esposito     job_finalize_locked(job, errp);
139b660a84bSStefan Reiter 
140b660a84bSStefan Reiter     /*
141b660a84bSStefan Reiter      * Job's context might have changed via job_finalize (and job_txn_apply
142b660a84bSStefan Reiter      * automatically acquires the new one), so make sure we release the correct
143b660a84bSStefan Reiter      * one.
144b660a84bSStefan Reiter      */
145b660a84bSStefan Reiter     aio_context = job->aio_context;
14696241124SEmanuele Giuseppe Esposito     job_unref_locked(job);
1471a90bc81SKevin Wolf     aio_context_release(aio_context);
1481a90bc81SKevin Wolf }
1491a90bc81SKevin Wolf 
1501a90bc81SKevin Wolf void qmp_job_dismiss(const char *id, Error **errp)
1511a90bc81SKevin Wolf {
1521a90bc81SKevin Wolf     AioContext *aio_context;
15396241124SEmanuele Giuseppe Esposito     Job *job;
15496241124SEmanuele Giuseppe Esposito 
15596241124SEmanuele Giuseppe Esposito     JOB_LOCK_GUARD();
15696241124SEmanuele Giuseppe Esposito     job = find_job_locked(id, &aio_context, errp);
1571a90bc81SKevin Wolf 
1581a90bc81SKevin Wolf     if (!job) {
1591a90bc81SKevin Wolf         return;
1601a90bc81SKevin Wolf     }
1611a90bc81SKevin Wolf 
1621a90bc81SKevin Wolf     trace_qmp_job_dismiss(job);
16396241124SEmanuele Giuseppe Esposito     job_dismiss_locked(&job, errp);
1641a90bc81SKevin Wolf     aio_context_release(aio_context);
1651a90bc81SKevin Wolf }
166456273b0SKevin Wolf 
167456273b0SKevin Wolf static JobInfo *job_query_single(Job *job, Error **errp)
168456273b0SKevin Wolf {
169456273b0SKevin Wolf     JobInfo *info;
170a7b4f8fcSEmanuele Giuseppe Esposito     uint64_t progress_current;
171a7b4f8fcSEmanuele Giuseppe Esposito     uint64_t progress_total;
172456273b0SKevin Wolf 
173456273b0SKevin Wolf     assert(!job_is_internal(job));
174a7b4f8fcSEmanuele Giuseppe Esposito     progress_get_snapshot(&job->progress, &progress_current,
175a7b4f8fcSEmanuele Giuseppe Esposito                           &progress_total);
176456273b0SKevin Wolf 
177456273b0SKevin Wolf     info = g_new(JobInfo, 1);
178456273b0SKevin Wolf     *info = (JobInfo) {
179456273b0SKevin Wolf         .id                 = g_strdup(job->id),
180456273b0SKevin Wolf         .type               = job_type(job),
181456273b0SKevin Wolf         .status             = job->status,
182a7b4f8fcSEmanuele Giuseppe Esposito         .current_progress   = progress_current,
183a7b4f8fcSEmanuele Giuseppe Esposito         .total_progress     = progress_total,
1843d1f8b07SJohn Snow         .has_error          = !!job->err,
1853d1f8b07SJohn Snow         .error              = job->err ? \
1863d1f8b07SJohn Snow                               g_strdup(error_get_pretty(job->err)) : NULL,
187456273b0SKevin Wolf     };
188456273b0SKevin Wolf 
189456273b0SKevin Wolf     return info;
190456273b0SKevin Wolf }
191456273b0SKevin Wolf 
192456273b0SKevin Wolf JobInfoList *qmp_query_jobs(Error **errp)
193456273b0SKevin Wolf {
194c3033fd3SEric Blake     JobInfoList *head = NULL, **tail = &head;
195456273b0SKevin Wolf     Job *job;
196456273b0SKevin Wolf 
197456273b0SKevin Wolf     for (job = job_next(NULL); job; job = job_next(job)) {
198c3033fd3SEric Blake         JobInfo *value;
199456273b0SKevin Wolf         AioContext *aio_context;
200456273b0SKevin Wolf 
201456273b0SKevin Wolf         if (job_is_internal(job)) {
202456273b0SKevin Wolf             continue;
203456273b0SKevin Wolf         }
204456273b0SKevin Wolf         aio_context = job->aio_context;
205456273b0SKevin Wolf         aio_context_acquire(aio_context);
206c3033fd3SEric Blake         value = job_query_single(job, errp);
207456273b0SKevin Wolf         aio_context_release(aio_context);
208c3033fd3SEric Blake         if (!value) {
209456273b0SKevin Wolf             qapi_free_JobInfoList(head);
210456273b0SKevin Wolf             return NULL;
211456273b0SKevin Wolf         }
212c3033fd3SEric Blake         QAPI_LIST_APPEND(tail, value);
213456273b0SKevin Wolf     }
214456273b0SKevin Wolf 
215456273b0SKevin Wolf     return head;
216456273b0SKevin Wolf }
217