]>
Commit | Line | Data |
---|---|---|
1a90bc81 KW |
1 | /* |
2 | * QMP interface for background jobs | |
3 | * | |
4 | * Copyright (c) 2011 IBM Corp. | |
5 | * Copyright (c) 2012, 2018 Red Hat, Inc. | |
6 | * | |
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | * of this software and associated documentation files (the "Software"), to deal | |
9 | * in the Software without restriction, including without limitation the rights | |
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | * copies of the Software, and to permit persons to whom the Software is | |
12 | * furnished to do so, subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice shall be included in | |
15 | * all copies or substantial portions of the Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
23 | * THE SOFTWARE. | |
24 | */ | |
25 | ||
26 | #include "qemu/osdep.h" | |
1a90bc81 KW |
27 | #include "qemu/job.h" |
28 | #include "qapi/qapi-commands-job.h" | |
29 | #include "qapi/error.h" | |
243af022 | 30 | #include "trace/trace-root.h" |
1a90bc81 | 31 | |
96241124 EGE |
32 | /* |
33 | * Get a job using its ID and acquire its AioContext. | |
34 | * Called with job_mutex held. | |
35 | */ | |
36 | static Job *find_job_locked(const char *id, | |
37 | AioContext **aio_context, | |
38 | Error **errp) | |
1a90bc81 KW |
39 | { |
40 | Job *job; | |
41 | ||
42 | *aio_context = NULL; | |
43 | ||
96241124 | 44 | job = job_get_locked(id); |
1a90bc81 KW |
45 | if (!job) { |
46 | error_setg(errp, "Job not found"); | |
47 | return NULL; | |
48 | } | |
49 | ||
50 | *aio_context = job->aio_context; | |
51 | aio_context_acquire(*aio_context); | |
52 | ||
53 | return job; | |
54 | } | |
55 | ||
56 | void qmp_job_cancel(const char *id, Error **errp) | |
57 | { | |
58 | AioContext *aio_context; | |
96241124 EGE |
59 | Job *job; |
60 | ||
61 | JOB_LOCK_GUARD(); | |
62 | job = find_job_locked(id, &aio_context, errp); | |
1a90bc81 KW |
63 | |
64 | if (!job) { | |
65 | return; | |
66 | } | |
67 | ||
68 | trace_qmp_job_cancel(job); | |
96241124 | 69 | job_user_cancel_locked(job, true, errp); |
1a90bc81 KW |
70 | aio_context_release(aio_context); |
71 | } | |
72 | ||
73 | void qmp_job_pause(const char *id, Error **errp) | |
74 | { | |
75 | AioContext *aio_context; | |
96241124 EGE |
76 | Job *job; |
77 | ||
78 | JOB_LOCK_GUARD(); | |
79 | job = find_job_locked(id, &aio_context, errp); | |
1a90bc81 KW |
80 | |
81 | if (!job) { | |
82 | return; | |
83 | } | |
84 | ||
85 | trace_qmp_job_pause(job); | |
96241124 | 86 | job_user_pause_locked(job, errp); |
1a90bc81 KW |
87 | aio_context_release(aio_context); |
88 | } | |
89 | ||
90 | void qmp_job_resume(const char *id, Error **errp) | |
91 | { | |
92 | AioContext *aio_context; | |
96241124 EGE |
93 | Job *job; |
94 | ||
95 | JOB_LOCK_GUARD(); | |
96 | job = find_job_locked(id, &aio_context, errp); | |
1a90bc81 KW |
97 | |
98 | if (!job) { | |
99 | return; | |
100 | } | |
101 | ||
102 | trace_qmp_job_resume(job); | |
96241124 | 103 | job_user_resume_locked(job, errp); |
1a90bc81 KW |
104 | aio_context_release(aio_context); |
105 | } | |
106 | ||
107 | void qmp_job_complete(const char *id, Error **errp) | |
108 | { | |
109 | AioContext *aio_context; | |
96241124 EGE |
110 | Job *job; |
111 | ||
112 | JOB_LOCK_GUARD(); | |
113 | job = find_job_locked(id, &aio_context, errp); | |
1a90bc81 KW |
114 | |
115 | if (!job) { | |
116 | return; | |
117 | } | |
118 | ||
119 | trace_qmp_job_complete(job); | |
96241124 | 120 | job_complete_locked(job, errp); |
1a90bc81 KW |
121 | aio_context_release(aio_context); |
122 | } | |
123 | ||
124 | void qmp_job_finalize(const char *id, Error **errp) | |
125 | { | |
126 | AioContext *aio_context; | |
96241124 EGE |
127 | Job *job; |
128 | ||
129 | JOB_LOCK_GUARD(); | |
130 | job = find_job_locked(id, &aio_context, errp); | |
1a90bc81 KW |
131 | |
132 | if (!job) { | |
133 | return; | |
134 | } | |
135 | ||
136 | trace_qmp_job_finalize(job); | |
96241124 EGE |
137 | job_ref_locked(job); |
138 | job_finalize_locked(job, errp); | |
b660a84b SR |
139 | |
140 | /* | |
141 | * Job's context might have changed via job_finalize (and job_txn_apply | |
142 | * automatically acquires the new one), so make sure we release the correct | |
143 | * one. | |
144 | */ | |
145 | aio_context = job->aio_context; | |
96241124 | 146 | job_unref_locked(job); |
1a90bc81 KW |
147 | aio_context_release(aio_context); |
148 | } | |
149 | ||
150 | void qmp_job_dismiss(const char *id, Error **errp) | |
151 | { | |
152 | AioContext *aio_context; | |
96241124 EGE |
153 | Job *job; |
154 | ||
155 | JOB_LOCK_GUARD(); | |
156 | job = find_job_locked(id, &aio_context, errp); | |
1a90bc81 KW |
157 | |
158 | if (!job) { | |
159 | return; | |
160 | } | |
161 | ||
162 | trace_qmp_job_dismiss(job); | |
96241124 | 163 | job_dismiss_locked(&job, errp); |
1a90bc81 KW |
164 | aio_context_release(aio_context); |
165 | } | |
456273b0 | 166 | |
880eeec6 EGE |
167 | /* Called with job_mutex held. */ |
168 | static JobInfo *job_query_single_locked(Job *job, Error **errp) | |
456273b0 KW |
169 | { |
170 | JobInfo *info; | |
a7b4f8fc EGE |
171 | uint64_t progress_current; |
172 | uint64_t progress_total; | |
456273b0 KW |
173 | |
174 | assert(!job_is_internal(job)); | |
a7b4f8fc EGE |
175 | progress_get_snapshot(&job->progress, &progress_current, |
176 | &progress_total); | |
456273b0 | 177 | |
456273b0 KW |
178 | info = g_new(JobInfo, 1); |
179 | *info = (JobInfo) { | |
180 | .id = g_strdup(job->id), | |
181 | .type = job_type(job), | |
182 | .status = job->status, | |
a7b4f8fc EGE |
183 | .current_progress = progress_current, |
184 | .total_progress = progress_total, | |
3d1f8b07 JS |
185 | .has_error = !!job->err, |
186 | .error = job->err ? \ | |
187 | g_strdup(error_get_pretty(job->err)) : NULL, | |
456273b0 KW |
188 | }; |
189 | ||
190 | return info; | |
191 | } | |
192 | ||
193 | JobInfoList *qmp_query_jobs(Error **errp) | |
194 | { | |
c3033fd3 | 195 | JobInfoList *head = NULL, **tail = &head; |
456273b0 KW |
196 | Job *job; |
197 | ||
880eeec6 EGE |
198 | JOB_LOCK_GUARD(); |
199 | ||
200 | for (job = job_next_locked(NULL); job; job = job_next_locked(job)) { | |
c3033fd3 | 201 | JobInfo *value; |
456273b0 KW |
202 | AioContext *aio_context; |
203 | ||
204 | if (job_is_internal(job)) { | |
205 | continue; | |
206 | } | |
456273b0 KW |
207 | aio_context = job->aio_context; |
208 | aio_context_acquire(aio_context); | |
880eeec6 | 209 | value = job_query_single_locked(job, errp); |
456273b0 | 210 | aio_context_release(aio_context); |
c3033fd3 | 211 | if (!value) { |
456273b0 KW |
212 | qapi_free_JobInfoList(head); |
213 | return NULL; | |
214 | } | |
c3033fd3 | 215 | QAPI_LIST_APPEND(tail, value); |
456273b0 KW |
216 | } |
217 | ||
218 | return head; | |
219 | } |