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-common.h" 281a90bc81SKevin Wolf #include "qemu/job.h" 291a90bc81SKevin Wolf #include "qapi/qapi-commands-job.h" 301a90bc81SKevin Wolf #include "qapi/error.h" 311a90bc81SKevin Wolf #include "trace-root.h" 321a90bc81SKevin Wolf 331a90bc81SKevin Wolf /* Get a job using its ID and acquire its AioContext */ 341a90bc81SKevin Wolf static Job *find_job(const char *id, AioContext **aio_context, Error **errp) 351a90bc81SKevin Wolf { 361a90bc81SKevin Wolf Job *job; 371a90bc81SKevin Wolf 381a90bc81SKevin Wolf *aio_context = NULL; 391a90bc81SKevin Wolf 401a90bc81SKevin Wolf job = job_get(id); 411a90bc81SKevin Wolf if (!job) { 421a90bc81SKevin Wolf error_setg(errp, "Job not found"); 431a90bc81SKevin Wolf return NULL; 441a90bc81SKevin Wolf } 451a90bc81SKevin Wolf 461a90bc81SKevin Wolf *aio_context = job->aio_context; 471a90bc81SKevin Wolf aio_context_acquire(*aio_context); 481a90bc81SKevin Wolf 491a90bc81SKevin Wolf return job; 501a90bc81SKevin Wolf } 511a90bc81SKevin Wolf 521a90bc81SKevin Wolf void qmp_job_cancel(const char *id, Error **errp) 531a90bc81SKevin Wolf { 541a90bc81SKevin Wolf AioContext *aio_context; 551a90bc81SKevin Wolf Job *job = find_job(id, &aio_context, errp); 561a90bc81SKevin Wolf 571a90bc81SKevin Wolf if (!job) { 581a90bc81SKevin Wolf return; 591a90bc81SKevin Wolf } 601a90bc81SKevin Wolf 611a90bc81SKevin Wolf trace_qmp_job_cancel(job); 621a90bc81SKevin Wolf job_user_cancel(job, true, errp); 631a90bc81SKevin Wolf aio_context_release(aio_context); 641a90bc81SKevin Wolf } 651a90bc81SKevin Wolf 661a90bc81SKevin Wolf void qmp_job_pause(const char *id, Error **errp) 671a90bc81SKevin Wolf { 681a90bc81SKevin Wolf AioContext *aio_context; 691a90bc81SKevin Wolf Job *job = find_job(id, &aio_context, errp); 701a90bc81SKevin Wolf 711a90bc81SKevin Wolf if (!job) { 721a90bc81SKevin Wolf return; 731a90bc81SKevin Wolf } 741a90bc81SKevin Wolf 751a90bc81SKevin Wolf trace_qmp_job_pause(job); 761a90bc81SKevin Wolf job_user_pause(job, errp); 771a90bc81SKevin Wolf aio_context_release(aio_context); 781a90bc81SKevin Wolf } 791a90bc81SKevin Wolf 801a90bc81SKevin Wolf void qmp_job_resume(const char *id, Error **errp) 811a90bc81SKevin Wolf { 821a90bc81SKevin Wolf AioContext *aio_context; 831a90bc81SKevin Wolf Job *job = find_job(id, &aio_context, errp); 841a90bc81SKevin Wolf 851a90bc81SKevin Wolf if (!job) { 861a90bc81SKevin Wolf return; 871a90bc81SKevin Wolf } 881a90bc81SKevin Wolf 891a90bc81SKevin Wolf trace_qmp_job_resume(job); 901a90bc81SKevin Wolf job_user_resume(job, errp); 911a90bc81SKevin Wolf aio_context_release(aio_context); 921a90bc81SKevin Wolf } 931a90bc81SKevin Wolf 941a90bc81SKevin Wolf void qmp_job_complete(const char *id, Error **errp) 951a90bc81SKevin Wolf { 961a90bc81SKevin Wolf AioContext *aio_context; 971a90bc81SKevin Wolf Job *job = find_job(id, &aio_context, errp); 981a90bc81SKevin Wolf 991a90bc81SKevin Wolf if (!job) { 1001a90bc81SKevin Wolf return; 1011a90bc81SKevin Wolf } 1021a90bc81SKevin Wolf 1031a90bc81SKevin Wolf trace_qmp_job_complete(job); 1041a90bc81SKevin Wolf job_complete(job, errp); 1051a90bc81SKevin Wolf aio_context_release(aio_context); 1061a90bc81SKevin Wolf } 1071a90bc81SKevin Wolf 1081a90bc81SKevin Wolf void qmp_job_finalize(const char *id, Error **errp) 1091a90bc81SKevin Wolf { 1101a90bc81SKevin Wolf AioContext *aio_context; 1111a90bc81SKevin Wolf Job *job = find_job(id, &aio_context, errp); 1121a90bc81SKevin Wolf 1131a90bc81SKevin Wolf if (!job) { 1141a90bc81SKevin Wolf return; 1151a90bc81SKevin Wolf } 1161a90bc81SKevin Wolf 1171a90bc81SKevin Wolf trace_qmp_job_finalize(job); 1181a90bc81SKevin Wolf job_finalize(job, errp); 1191a90bc81SKevin Wolf aio_context_release(aio_context); 1201a90bc81SKevin Wolf } 1211a90bc81SKevin Wolf 1221a90bc81SKevin Wolf void qmp_job_dismiss(const char *id, Error **errp) 1231a90bc81SKevin Wolf { 1241a90bc81SKevin Wolf AioContext *aio_context; 1251a90bc81SKevin Wolf Job *job = find_job(id, &aio_context, errp); 1261a90bc81SKevin Wolf 1271a90bc81SKevin Wolf if (!job) { 1281a90bc81SKevin Wolf return; 1291a90bc81SKevin Wolf } 1301a90bc81SKevin Wolf 1311a90bc81SKevin Wolf trace_qmp_job_dismiss(job); 1321a90bc81SKevin Wolf job_dismiss(&job, errp); 1331a90bc81SKevin Wolf aio_context_release(aio_context); 1341a90bc81SKevin Wolf } 135456273b0SKevin Wolf 136456273b0SKevin Wolf static JobInfo *job_query_single(Job *job, Error **errp) 137456273b0SKevin Wolf { 138456273b0SKevin Wolf JobInfo *info; 139456273b0SKevin Wolf 140456273b0SKevin Wolf assert(!job_is_internal(job)); 141456273b0SKevin Wolf 142456273b0SKevin Wolf info = g_new(JobInfo, 1); 143456273b0SKevin Wolf *info = (JobInfo) { 144456273b0SKevin Wolf .id = g_strdup(job->id), 145456273b0SKevin Wolf .type = job_type(job), 146456273b0SKevin Wolf .status = job->status, 147456273b0SKevin Wolf .current_progress = job->progress_current, 148456273b0SKevin Wolf .total_progress = job->progress_total, 149*3d1f8b07SJohn Snow .has_error = !!job->err, 150*3d1f8b07SJohn Snow .error = job->err ? \ 151*3d1f8b07SJohn Snow g_strdup(error_get_pretty(job->err)) : NULL, 152456273b0SKevin Wolf }; 153456273b0SKevin Wolf 154456273b0SKevin Wolf return info; 155456273b0SKevin Wolf } 156456273b0SKevin Wolf 157456273b0SKevin Wolf JobInfoList *qmp_query_jobs(Error **errp) 158456273b0SKevin Wolf { 159456273b0SKevin Wolf JobInfoList *head = NULL, **p_next = &head; 160456273b0SKevin Wolf Job *job; 161456273b0SKevin Wolf 162456273b0SKevin Wolf for (job = job_next(NULL); job; job = job_next(job)) { 163456273b0SKevin Wolf JobInfoList *elem; 164456273b0SKevin Wolf AioContext *aio_context; 165456273b0SKevin Wolf 166456273b0SKevin Wolf if (job_is_internal(job)) { 167456273b0SKevin Wolf continue; 168456273b0SKevin Wolf } 169456273b0SKevin Wolf elem = g_new0(JobInfoList, 1); 170456273b0SKevin Wolf aio_context = job->aio_context; 171456273b0SKevin Wolf aio_context_acquire(aio_context); 172456273b0SKevin Wolf elem->value = job_query_single(job, errp); 173456273b0SKevin Wolf aio_context_release(aio_context); 174456273b0SKevin Wolf if (!elem->value) { 175456273b0SKevin Wolf g_free(elem); 176456273b0SKevin Wolf qapi_free_JobInfoList(head); 177456273b0SKevin Wolf return NULL; 178456273b0SKevin Wolf } 179456273b0SKevin Wolf *p_next = elem; 180456273b0SKevin Wolf p_next = &elem->next; 181456273b0SKevin Wolf } 182456273b0SKevin Wolf 183456273b0SKevin Wolf return head; 184456273b0SKevin Wolf } 185