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 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); 117b660a84bSStefan Reiter job_ref(job); 1181a90bc81SKevin Wolf job_finalize(job, errp); 119b660a84bSStefan Reiter 120b660a84bSStefan Reiter /* 121b660a84bSStefan Reiter * Job's context might have changed via job_finalize (and job_txn_apply 122b660a84bSStefan Reiter * automatically acquires the new one), so make sure we release the correct 123b660a84bSStefan Reiter * one. 124b660a84bSStefan Reiter */ 125b660a84bSStefan Reiter aio_context = job->aio_context; 126b660a84bSStefan 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; 147*a7b4f8fcSEmanuele Giuseppe Esposito uint64_t progress_current; 148*a7b4f8fcSEmanuele Giuseppe Esposito uint64_t progress_total; 149456273b0SKevin Wolf 150456273b0SKevin Wolf assert(!job_is_internal(job)); 151*a7b4f8fcSEmanuele Giuseppe Esposito progress_get_snapshot(&job->progress, &progress_current, 152*a7b4f8fcSEmanuele Giuseppe Esposito &progress_total); 153456273b0SKevin Wolf 154456273b0SKevin Wolf info = g_new(JobInfo, 1); 155456273b0SKevin Wolf *info = (JobInfo) { 156456273b0SKevin Wolf .id = g_strdup(job->id), 157456273b0SKevin Wolf .type = job_type(job), 158456273b0SKevin Wolf .status = job->status, 159*a7b4f8fcSEmanuele Giuseppe Esposito .current_progress = progress_current, 160*a7b4f8fcSEmanuele Giuseppe Esposito .total_progress = progress_total, 1613d1f8b07SJohn Snow .has_error = !!job->err, 1623d1f8b07SJohn Snow .error = job->err ? \ 1633d1f8b07SJohn Snow g_strdup(error_get_pretty(job->err)) : NULL, 164456273b0SKevin Wolf }; 165456273b0SKevin Wolf 166456273b0SKevin Wolf return info; 167456273b0SKevin Wolf } 168456273b0SKevin Wolf 169456273b0SKevin Wolf JobInfoList *qmp_query_jobs(Error **errp) 170456273b0SKevin Wolf { 171c3033fd3SEric Blake JobInfoList *head = NULL, **tail = &head; 172456273b0SKevin Wolf Job *job; 173456273b0SKevin Wolf 174456273b0SKevin Wolf for (job = job_next(NULL); job; job = job_next(job)) { 175c3033fd3SEric Blake JobInfo *value; 176456273b0SKevin Wolf AioContext *aio_context; 177456273b0SKevin Wolf 178456273b0SKevin Wolf if (job_is_internal(job)) { 179456273b0SKevin Wolf continue; 180456273b0SKevin Wolf } 181456273b0SKevin Wolf aio_context = job->aio_context; 182456273b0SKevin Wolf aio_context_acquire(aio_context); 183c3033fd3SEric Blake value = job_query_single(job, errp); 184456273b0SKevin Wolf aio_context_release(aio_context); 185c3033fd3SEric Blake if (!value) { 186456273b0SKevin Wolf qapi_free_JobInfoList(head); 187456273b0SKevin Wolf return NULL; 188456273b0SKevin Wolf } 189c3033fd3SEric Blake QAPI_LIST_APPEND(tail, value); 190456273b0SKevin Wolf } 191456273b0SKevin Wolf 192456273b0SKevin Wolf return head; 193456273b0SKevin Wolf } 194