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 167*880eeec6SEmanuele Giuseppe Esposito /* Called with job_mutex held. */ 168*880eeec6SEmanuele Giuseppe Esposito static JobInfo *job_query_single_locked(Job *job, Error **errp) 169456273b0SKevin Wolf { 170456273b0SKevin Wolf JobInfo *info; 171a7b4f8fcSEmanuele Giuseppe Esposito uint64_t progress_current; 172a7b4f8fcSEmanuele Giuseppe Esposito uint64_t progress_total; 173456273b0SKevin Wolf 174456273b0SKevin Wolf assert(!job_is_internal(job)); 175a7b4f8fcSEmanuele Giuseppe Esposito progress_get_snapshot(&job->progress, &progress_current, 176a7b4f8fcSEmanuele Giuseppe Esposito &progress_total); 177456273b0SKevin Wolf 178456273b0SKevin Wolf info = g_new(JobInfo, 1); 179456273b0SKevin Wolf *info = (JobInfo) { 180456273b0SKevin Wolf .id = g_strdup(job->id), 181456273b0SKevin Wolf .type = job_type(job), 182456273b0SKevin Wolf .status = job->status, 183a7b4f8fcSEmanuele Giuseppe Esposito .current_progress = progress_current, 184a7b4f8fcSEmanuele Giuseppe Esposito .total_progress = progress_total, 1853d1f8b07SJohn Snow .has_error = !!job->err, 1863d1f8b07SJohn Snow .error = job->err ? \ 1873d1f8b07SJohn Snow g_strdup(error_get_pretty(job->err)) : NULL, 188456273b0SKevin Wolf }; 189456273b0SKevin Wolf 190456273b0SKevin Wolf return info; 191456273b0SKevin Wolf } 192456273b0SKevin Wolf 193456273b0SKevin Wolf JobInfoList *qmp_query_jobs(Error **errp) 194456273b0SKevin Wolf { 195c3033fd3SEric Blake JobInfoList *head = NULL, **tail = &head; 196456273b0SKevin Wolf Job *job; 197456273b0SKevin Wolf 198*880eeec6SEmanuele Giuseppe Esposito JOB_LOCK_GUARD(); 199*880eeec6SEmanuele Giuseppe Esposito 200*880eeec6SEmanuele Giuseppe Esposito for (job = job_next_locked(NULL); job; job = job_next_locked(job)) { 201c3033fd3SEric Blake JobInfo *value; 202456273b0SKevin Wolf AioContext *aio_context; 203456273b0SKevin Wolf 204456273b0SKevin Wolf if (job_is_internal(job)) { 205456273b0SKevin Wolf continue; 206456273b0SKevin Wolf } 207456273b0SKevin Wolf aio_context = job->aio_context; 208456273b0SKevin Wolf aio_context_acquire(aio_context); 209*880eeec6SEmanuele Giuseppe Esposito value = job_query_single_locked(job, errp); 210456273b0SKevin Wolf aio_context_release(aio_context); 211c3033fd3SEric Blake if (!value) { 212456273b0SKevin Wolf qapi_free_JobInfoList(head); 213456273b0SKevin Wolf return NULL; 214456273b0SKevin Wolf } 215c3033fd3SEric Blake QAPI_LIST_APPEND(tail, value); 216456273b0SKevin Wolf } 217456273b0SKevin Wolf 218456273b0SKevin Wolf return head; 219456273b0SKevin Wolf } 220