xref: /qemu/blockjob.c (revision 62c9e416)
12f0c9fe6SPaolo Bonzini /*
22f0c9fe6SPaolo Bonzini  * QEMU System Emulator block driver
32f0c9fe6SPaolo Bonzini  *
42f0c9fe6SPaolo Bonzini  * Copyright (c) 2011 IBM Corp.
52f0c9fe6SPaolo Bonzini  * Copyright (c) 2012 Red Hat, Inc.
62f0c9fe6SPaolo Bonzini  *
72f0c9fe6SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
82f0c9fe6SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
92f0c9fe6SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
102f0c9fe6SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
112f0c9fe6SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
122f0c9fe6SPaolo Bonzini  * furnished to do so, subject to the following conditions:
132f0c9fe6SPaolo Bonzini  *
142f0c9fe6SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
152f0c9fe6SPaolo Bonzini  * all copies or substantial portions of the Software.
162f0c9fe6SPaolo Bonzini  *
172f0c9fe6SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
182f0c9fe6SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
192f0c9fe6SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
202f0c9fe6SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
212f0c9fe6SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
222f0c9fe6SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
232f0c9fe6SPaolo Bonzini  * THE SOFTWARE.
242f0c9fe6SPaolo Bonzini  */
252f0c9fe6SPaolo Bonzini 
26d38ea87aSPeter Maydell #include "qemu/osdep.h"
272f0c9fe6SPaolo Bonzini #include "qemu-common.h"
28737e150eSPaolo Bonzini #include "block/block.h"
29c87621eaSJohn Snow #include "block/blockjob_int.h"
30737e150eSPaolo Bonzini #include "block/block_int.h"
31c9de4050SJohn Snow #include "block/trace.h"
32373340b2SMax Reitz #include "sysemu/block-backend.h"
33e688df6bSMarkus Armbruster #include "qapi/error.h"
349af23989SMarkus Armbruster #include "qapi/qapi-events-block-core.h"
35cc7a8ea7SMarkus Armbruster #include "qapi/qmp/qerror.h"
3610817bf0SDaniel P. Berrange #include "qemu/coroutine.h"
371de7afc9SPaolo Bonzini #include "qemu/timer.h"
382f0c9fe6SPaolo Bonzini 
39c55a832fSFam Zheng /* Transactional group of block jobs */
40*62c9e416SKevin Wolf struct JobTxn {
41c55a832fSFam Zheng 
42c55a832fSFam Zheng     /* Is this txn being cancelled? */
43c55a832fSFam Zheng     bool aborting;
44c55a832fSFam Zheng 
45c55a832fSFam Zheng     /* List of jobs */
46*62c9e416SKevin Wolf     QLIST_HEAD(, Job) jobs;
47c55a832fSFam Zheng 
48c55a832fSFam Zheng     /* Reference count */
49c55a832fSFam Zheng     int refcnt;
50c55a832fSFam Zheng };
51c55a832fSFam Zheng 
5288691b37SPaolo Bonzini /*
5388691b37SPaolo Bonzini  * The block job API is composed of two categories of functions.
5488691b37SPaolo Bonzini  *
5588691b37SPaolo Bonzini  * The first includes functions used by the monitor.  The monitor is
5688691b37SPaolo Bonzini  * peculiar in that it accesses the block job list with block_job_get, and
5788691b37SPaolo Bonzini  * therefore needs consistency across block_job_get and the actual operation
5888691b37SPaolo Bonzini  * (e.g. block_job_set_speed).  The consistency is achieved with
5988691b37SPaolo Bonzini  * aio_context_acquire/release.  These functions are declared in blockjob.h.
6088691b37SPaolo Bonzini  *
6188691b37SPaolo Bonzini  * The second includes functions used by the block job drivers and sometimes
6288691b37SPaolo Bonzini  * by the core block layer.  These do not care about locking, because the
6388691b37SPaolo Bonzini  * whole coroutine runs under the AioContext lock, and are declared in
6488691b37SPaolo Bonzini  * blockjob_int.h.
6588691b37SPaolo Bonzini  */
6688691b37SPaolo Bonzini 
67e7c1d78bSKevin Wolf static bool is_block_job(Job *job)
68a7112795SAlberto Garcia {
69e7c1d78bSKevin Wolf     return job_type(job) == JOB_TYPE_BACKUP ||
70e7c1d78bSKevin Wolf            job_type(job) == JOB_TYPE_COMMIT ||
71e7c1d78bSKevin Wolf            job_type(job) == JOB_TYPE_MIRROR ||
72e7c1d78bSKevin Wolf            job_type(job) == JOB_TYPE_STREAM;
73a7112795SAlberto Garcia }
74e7c1d78bSKevin Wolf 
75e7c1d78bSKevin Wolf BlockJob *block_job_next(BlockJob *bjob)
76e7c1d78bSKevin Wolf {
77e7c1d78bSKevin Wolf     Job *job = bjob ? &bjob->job : NULL;
78e7c1d78bSKevin Wolf 
79e7c1d78bSKevin Wolf     do {
80e7c1d78bSKevin Wolf         job = job_next(job);
81e7c1d78bSKevin Wolf     } while (job && !is_block_job(job));
82e7c1d78bSKevin Wolf 
83e7c1d78bSKevin Wolf     return job ? container_of(job, BlockJob, job) : NULL;
84a7112795SAlberto Garcia }
85a7112795SAlberto Garcia 
86ffb1f10cSAlberto Garcia BlockJob *block_job_get(const char *id)
87ffb1f10cSAlberto Garcia {
88e7c1d78bSKevin Wolf     Job *job = job_get(id);
89ffb1f10cSAlberto Garcia 
90e7c1d78bSKevin Wolf     if (job && is_block_job(job)) {
91e7c1d78bSKevin Wolf         return container_of(job, BlockJob, job);
92e7c1d78bSKevin Wolf     } else {
93ffb1f10cSAlberto Garcia         return NULL;
94ffb1f10cSAlberto Garcia     }
95e7c1d78bSKevin Wolf }
96ffb1f10cSAlberto Garcia 
97*62c9e416SKevin Wolf JobTxn *block_job_txn_new(void)
98c8ab5c2dSPaolo Bonzini {
99*62c9e416SKevin Wolf     JobTxn *txn = g_new0(JobTxn, 1);
100c8ab5c2dSPaolo Bonzini     QLIST_INIT(&txn->jobs);
101c8ab5c2dSPaolo Bonzini     txn->refcnt = 1;
102c8ab5c2dSPaolo Bonzini     return txn;
103c8ab5c2dSPaolo Bonzini }
104c8ab5c2dSPaolo Bonzini 
105*62c9e416SKevin Wolf static void block_job_txn_ref(JobTxn *txn)
106c8ab5c2dSPaolo Bonzini {
107c8ab5c2dSPaolo Bonzini     txn->refcnt++;
108c8ab5c2dSPaolo Bonzini }
109c8ab5c2dSPaolo Bonzini 
110*62c9e416SKevin Wolf void block_job_txn_unref(JobTxn *txn)
111c8ab5c2dSPaolo Bonzini {
112c8ab5c2dSPaolo Bonzini     if (txn && --txn->refcnt == 0) {
113c8ab5c2dSPaolo Bonzini         g_free(txn);
114c8ab5c2dSPaolo Bonzini     }
115c8ab5c2dSPaolo Bonzini }
116c8ab5c2dSPaolo Bonzini 
117*62c9e416SKevin Wolf void block_job_txn_add_job(JobTxn *txn, BlockJob *job)
118c8ab5c2dSPaolo Bonzini {
119c8ab5c2dSPaolo Bonzini     if (!txn) {
120c8ab5c2dSPaolo Bonzini         return;
121c8ab5c2dSPaolo Bonzini     }
122c8ab5c2dSPaolo Bonzini 
123c8ab5c2dSPaolo Bonzini     assert(!job->txn);
124c8ab5c2dSPaolo Bonzini     job->txn = txn;
125c8ab5c2dSPaolo Bonzini 
126*62c9e416SKevin Wolf     QLIST_INSERT_HEAD(&txn->jobs, &job->job, txn_list);
127c8ab5c2dSPaolo Bonzini     block_job_txn_ref(txn);
128c8ab5c2dSPaolo Bonzini }
129c8ab5c2dSPaolo Bonzini 
1304ad35181SKevin Wolf void block_job_txn_del_job(BlockJob *job)
131a865cebbSMarc-André Lureau {
132a865cebbSMarc-André Lureau     if (job->txn) {
133*62c9e416SKevin Wolf         QLIST_REMOVE(&job->job, txn_list);
134a865cebbSMarc-André Lureau         block_job_txn_unref(job->txn);
135a865cebbSMarc-André Lureau         job->txn = NULL;
136a865cebbSMarc-André Lureau     }
137a865cebbSMarc-André Lureau }
138a865cebbSMarc-André Lureau 
13905b0d8e3SPaolo Bonzini static void block_job_attached_aio_context(AioContext *new_context,
14005b0d8e3SPaolo Bonzini                                            void *opaque);
14105b0d8e3SPaolo Bonzini static void block_job_detach_aio_context(void *opaque);
14205b0d8e3SPaolo Bonzini 
14380fa2c75SKevin Wolf void block_job_free(Job *job)
14405b0d8e3SPaolo Bonzini {
14580fa2c75SKevin Wolf     BlockJob *bjob = container_of(job, BlockJob, job);
14680fa2c75SKevin Wolf     BlockDriverState *bs = blk_bs(bjob->blk);
14780fa2c75SKevin Wolf 
14880fa2c75SKevin Wolf     assert(!bjob->txn);
14980fa2c75SKevin Wolf 
15005b0d8e3SPaolo Bonzini     bs->job = NULL;
15180fa2c75SKevin Wolf     block_job_remove_all_bdrv(bjob);
15280fa2c75SKevin Wolf     blk_remove_aio_context_notifier(bjob->blk,
15305b0d8e3SPaolo Bonzini                                     block_job_attached_aio_context,
15480fa2c75SKevin Wolf                                     block_job_detach_aio_context, bjob);
15580fa2c75SKevin Wolf     blk_unref(bjob->blk);
15680fa2c75SKevin Wolf     error_free(bjob->blocker);
15705b0d8e3SPaolo Bonzini }
15805b0d8e3SPaolo Bonzini 
159463e0be1SStefan Hajnoczi static void block_job_attached_aio_context(AioContext *new_context,
160463e0be1SStefan Hajnoczi                                            void *opaque)
161463e0be1SStefan Hajnoczi {
162463e0be1SStefan Hajnoczi     BlockJob *job = opaque;
163463e0be1SStefan Hajnoczi 
16408be6fe2SKevin Wolf     job->job.aio_context = new_context;
165463e0be1SStefan Hajnoczi     if (job->driver->attached_aio_context) {
166463e0be1SStefan Hajnoczi         job->driver->attached_aio_context(job, new_context);
167463e0be1SStefan Hajnoczi     }
168463e0be1SStefan Hajnoczi 
169b15de828SKevin Wolf     job_resume(&job->job);
170463e0be1SStefan Hajnoczi }
171463e0be1SStefan Hajnoczi 
172b69f777dSKevin Wolf void block_job_drain(Job *job)
173bae8196dSPaolo Bonzini {
174b69f777dSKevin Wolf     BlockJob *bjob = container_of(job, BlockJob, job);
175bae8196dSPaolo Bonzini 
176b69f777dSKevin Wolf     blk_drain(bjob->blk);
177b69f777dSKevin Wolf     if (bjob->driver->drain) {
178b69f777dSKevin Wolf         bjob->driver->drain(bjob);
179bae8196dSPaolo Bonzini     }
180bae8196dSPaolo Bonzini }
181bae8196dSPaolo Bonzini 
182463e0be1SStefan Hajnoczi static void block_job_detach_aio_context(void *opaque)
183463e0be1SStefan Hajnoczi {
184463e0be1SStefan Hajnoczi     BlockJob *job = opaque;
185463e0be1SStefan Hajnoczi 
186463e0be1SStefan Hajnoczi     /* In case the job terminates during aio_poll()... */
18780fa2c75SKevin Wolf     job_ref(&job->job);
188463e0be1SStefan Hajnoczi 
189b15de828SKevin Wolf     job_pause(&job->job);
190463e0be1SStefan Hajnoczi 
191dbe5e6c1SKevin Wolf     while (!job->job.paused && !job_is_completed(&job->job)) {
192b69f777dSKevin Wolf         job_drain(&job->job);
193463e0be1SStefan Hajnoczi     }
194463e0be1SStefan Hajnoczi 
19508be6fe2SKevin Wolf     job->job.aio_context = NULL;
19680fa2c75SKevin Wolf     job_unref(&job->job);
197463e0be1SStefan Hajnoczi }
198463e0be1SStefan Hajnoczi 
199f321dcb5SPaolo Bonzini static char *child_job_get_parent_desc(BdrvChild *c)
200f321dcb5SPaolo Bonzini {
201f321dcb5SPaolo Bonzini     BlockJob *job = c->opaque;
202252291eaSKevin Wolf     return g_strdup_printf("%s job '%s'", job_type_str(&job->job), job->job.id);
203f321dcb5SPaolo Bonzini }
204f321dcb5SPaolo Bonzini 
205ad90febaSKevin Wolf static void child_job_drained_begin(BdrvChild *c)
206f321dcb5SPaolo Bonzini {
207ad90febaSKevin Wolf     BlockJob *job = c->opaque;
208b15de828SKevin Wolf     job_pause(&job->job);
209f321dcb5SPaolo Bonzini }
210f321dcb5SPaolo Bonzini 
211ad90febaSKevin Wolf static void child_job_drained_end(BdrvChild *c)
212f321dcb5SPaolo Bonzini {
213ad90febaSKevin Wolf     BlockJob *job = c->opaque;
214b15de828SKevin Wolf     job_resume(&job->job);
215f321dcb5SPaolo Bonzini }
216f321dcb5SPaolo Bonzini 
217ad90febaSKevin Wolf static const BdrvChildRole child_job = {
218ad90febaSKevin Wolf     .get_parent_desc    = child_job_get_parent_desc,
219ad90febaSKevin Wolf     .drained_begin      = child_job_drained_begin,
220ad90febaSKevin Wolf     .drained_end        = child_job_drained_end,
221ad90febaSKevin Wolf     .stay_at_node       = true,
222f321dcb5SPaolo Bonzini };
223f321dcb5SPaolo Bonzini 
224bbc02b90SKevin Wolf void block_job_remove_all_bdrv(BlockJob *job)
225bbc02b90SKevin Wolf {
226bbc02b90SKevin Wolf     GSList *l;
227bbc02b90SKevin Wolf     for (l = job->nodes; l; l = l->next) {
228bbc02b90SKevin Wolf         BdrvChild *c = l->data;
229bbc02b90SKevin Wolf         bdrv_op_unblock_all(c->bs, job->blocker);
230bbc02b90SKevin Wolf         bdrv_root_unref_child(c);
231bbc02b90SKevin Wolf     }
232bbc02b90SKevin Wolf     g_slist_free(job->nodes);
233bbc02b90SKevin Wolf     job->nodes = NULL;
234bbc02b90SKevin Wolf }
235bbc02b90SKevin Wolf 
23676d554e2SKevin Wolf int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
23776d554e2SKevin Wolf                        uint64_t perm, uint64_t shared_perm, Error **errp)
23823d402d4SAlberto Garcia {
23976d554e2SKevin Wolf     BdrvChild *c;
24076d554e2SKevin Wolf 
24176d554e2SKevin Wolf     c = bdrv_root_attach_child(bs, name, &child_job, perm, shared_perm,
24276d554e2SKevin Wolf                                job, errp);
24376d554e2SKevin Wolf     if (c == NULL) {
24476d554e2SKevin Wolf         return -EPERM;
24576d554e2SKevin Wolf     }
24676d554e2SKevin Wolf 
24776d554e2SKevin Wolf     job->nodes = g_slist_prepend(job->nodes, c);
24823d402d4SAlberto Garcia     bdrv_ref(bs);
24923d402d4SAlberto Garcia     bdrv_op_block_all(bs, job->blocker);
25076d554e2SKevin Wolf 
25176d554e2SKevin Wolf     return 0;
25223d402d4SAlberto Garcia }
25323d402d4SAlberto Garcia 
254559b935fSJohn Snow bool block_job_is_internal(BlockJob *job)
255559b935fSJohn Snow {
25633e9e9bdSKevin Wolf     return (job->job.id == NULL);
257559b935fSJohn Snow }
258559b935fSJohn Snow 
259bd21935bSKevin Wolf const BlockJobDriver *block_job_driver(BlockJob *job)
260bd21935bSKevin Wolf {
261bd21935bSKevin Wolf     return job->driver;
262bd21935bSKevin Wolf }
263bd21935bSKevin Wolf 
2642da4617aSJohn Snow static int block_job_prepare(BlockJob *job)
2652da4617aSJohn Snow {
2664ad35181SKevin Wolf     if (job->job.ret == 0 && job->driver->prepare) {
2674ad35181SKevin Wolf         job->job.ret = job->driver->prepare(job);
2682da4617aSJohn Snow     }
2694ad35181SKevin Wolf     return job->job.ret;
270c55a832fSFam Zheng }
271c55a832fSFam Zheng 
272004e95dfSKevin Wolf static void job_cancel_async(Job *job, bool force)
2734c241cf5SPaolo Bonzini {
274004e95dfSKevin Wolf     if (job->user_paused) {
275004e95dfSKevin Wolf         /* Do not call job_enter here, the caller will handle it.  */
276004e95dfSKevin Wolf         job->user_paused = false;
277004e95dfSKevin Wolf         if (job->driver->user_resume) {
278004e95dfSKevin Wolf             job->driver->user_resume(job);
2794c241cf5SPaolo Bonzini         }
280004e95dfSKevin Wolf         assert(job->pause_count > 0);
281004e95dfSKevin Wolf         job->pause_count--;
2824c241cf5SPaolo Bonzini     }
283004e95dfSKevin Wolf     job->cancelled = true;
284b76e4458SLiang Li     /* To prevent 'force == false' overriding a previous 'force == true' */
285004e95dfSKevin Wolf     job->force_cancel |= force;
2864c241cf5SPaolo Bonzini }
2874c241cf5SPaolo Bonzini 
288*62c9e416SKevin Wolf static int block_job_txn_apply(JobTxn *txn, int fn(BlockJob *), bool lock)
289efe4d4b7SJohn Snow {
290efe4d4b7SJohn Snow     AioContext *ctx;
291*62c9e416SKevin Wolf     Job *job, *next;
292*62c9e416SKevin Wolf     BlockJob *bjob;
2932da4617aSJohn Snow     int rc = 0;
294efe4d4b7SJohn Snow 
295efe4d4b7SJohn Snow     QLIST_FOREACH_SAFE(job, &txn->jobs, txn_list, next) {
296*62c9e416SKevin Wolf         assert(is_block_job(job));
297*62c9e416SKevin Wolf         bjob = container_of(job, BlockJob, job);
298*62c9e416SKevin Wolf 
2995f241594SJohn Snow         if (lock) {
300*62c9e416SKevin Wolf             ctx = job->aio_context;
301efe4d4b7SJohn Snow             aio_context_acquire(ctx);
3025f241594SJohn Snow         }
303*62c9e416SKevin Wolf         rc = fn(bjob);
3045f241594SJohn Snow         if (lock) {
305efe4d4b7SJohn Snow             aio_context_release(ctx);
3065f241594SJohn Snow         }
3072da4617aSJohn Snow         if (rc) {
3082da4617aSJohn Snow             break;
309efe4d4b7SJohn Snow         }
310efe4d4b7SJohn Snow     }
3112da4617aSJohn Snow     return rc;
3122da4617aSJohn Snow }
313efe4d4b7SJohn Snow 
314c55a832fSFam Zheng static void block_job_completed_txn_abort(BlockJob *job)
315c55a832fSFam Zheng {
316c55a832fSFam Zheng     AioContext *ctx;
317*62c9e416SKevin Wolf     JobTxn *txn = job->txn;
318*62c9e416SKevin Wolf     Job *other_job;
319c55a832fSFam Zheng 
320c55a832fSFam Zheng     if (txn->aborting) {
321c55a832fSFam Zheng         /*
322c55a832fSFam Zheng          * We are cancelled by another job, which will handle everything.
323c55a832fSFam Zheng          */
324c55a832fSFam Zheng         return;
325c55a832fSFam Zheng     }
326c55a832fSFam Zheng     txn->aborting = true;
3274fb588e9SPaolo Bonzini     block_job_txn_ref(txn);
3284fb588e9SPaolo Bonzini 
329c55a832fSFam Zheng     /* We are the first failed job. Cancel other jobs. */
330c55a832fSFam Zheng     QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
331*62c9e416SKevin Wolf         ctx = other_job->aio_context;
332c55a832fSFam Zheng         aio_context_acquire(ctx);
333c55a832fSFam Zheng     }
3344fb588e9SPaolo Bonzini 
3354fb588e9SPaolo Bonzini     /* Other jobs are effectively cancelled by us, set the status for
336c55a832fSFam Zheng      * them; this job, however, may or may not be cancelled, depending
337c55a832fSFam Zheng      * on the caller, so leave it. */
3384fb588e9SPaolo Bonzini     QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
339*62c9e416SKevin Wolf         if (other_job != &job->job) {
340*62c9e416SKevin Wolf             job_cancel_async(other_job, false);
341c55a832fSFam Zheng         }
342c55a832fSFam Zheng     }
3434fb588e9SPaolo Bonzini     while (!QLIST_EMPTY(&txn->jobs)) {
3444fb588e9SPaolo Bonzini         other_job = QLIST_FIRST(&txn->jobs);
345*62c9e416SKevin Wolf         ctx = other_job->aio_context;
346*62c9e416SKevin Wolf         if (!job_is_completed(other_job)) {
347*62c9e416SKevin Wolf             assert(job_is_cancelled(other_job));
348*62c9e416SKevin Wolf             job_finish_sync(other_job, NULL, NULL);
3494fb588e9SPaolo Bonzini         }
350*62c9e416SKevin Wolf         job_finalize_single(other_job);
351c55a832fSFam Zheng         aio_context_release(ctx);
352c55a832fSFam Zheng     }
3534fb588e9SPaolo Bonzini 
3544fb588e9SPaolo Bonzini     block_job_txn_unref(txn);
355c55a832fSFam Zheng }
356c55a832fSFam Zheng 
35711b61fbcSJohn Snow static int block_job_needs_finalize(BlockJob *job)
35811b61fbcSJohn Snow {
359bb02b65cSKevin Wolf     return !job->job.auto_finalize;
36011b61fbcSJohn Snow }
36111b61fbcSJohn Snow 
3624ad35181SKevin Wolf static int block_job_finalize_single(BlockJob *job)
3634ad35181SKevin Wolf {
3644ad35181SKevin Wolf     return job_finalize_single(&job->job);
3654ad35181SKevin Wolf }
3664ad35181SKevin Wolf 
36711b61fbcSJohn Snow static void block_job_do_finalize(BlockJob *job)
36811b61fbcSJohn Snow {
36911b61fbcSJohn Snow     int rc;
37011b61fbcSJohn Snow     assert(job && job->txn);
37111b61fbcSJohn Snow 
37211b61fbcSJohn Snow     /* prepare the transaction to complete */
37311b61fbcSJohn Snow     rc = block_job_txn_apply(job->txn, block_job_prepare, true);
37411b61fbcSJohn Snow     if (rc) {
37511b61fbcSJohn Snow         block_job_completed_txn_abort(job);
37611b61fbcSJohn Snow     } else {
37711b61fbcSJohn Snow         block_job_txn_apply(job->txn, block_job_finalize_single, true);
37811b61fbcSJohn Snow     }
37911b61fbcSJohn Snow }
38011b61fbcSJohn Snow 
3815d4f3769SKevin Wolf static int block_job_transition_to_pending(BlockJob *job)
3825d4f3769SKevin Wolf {
3835d4f3769SKevin Wolf     job_state_transition(&job->job, JOB_STATUS_PENDING);
3845d4f3769SKevin Wolf     if (!job->job.auto_finalize) {
385139a9f02SKevin Wolf         job_event_pending(&job->job);
3865d4f3769SKevin Wolf     }
3875d4f3769SKevin Wolf     return 0;
3885d4f3769SKevin Wolf }
3895d4f3769SKevin Wolf 
390c55a832fSFam Zheng static void block_job_completed_txn_success(BlockJob *job)
391c55a832fSFam Zheng {
392*62c9e416SKevin Wolf     JobTxn *txn = job->txn;
393*62c9e416SKevin Wolf     Job *other_job;
3942da4617aSJohn Snow 
395a50c2ab8SKevin Wolf     job_state_transition(&job->job, JOB_STATUS_WAITING);
396e8af5686SJohn Snow 
397c55a832fSFam Zheng     /*
398c55a832fSFam Zheng      * Successful completion, see if there are other running jobs in this
399c55a832fSFam Zheng      * txn.
400c55a832fSFam Zheng      */
401c55a832fSFam Zheng     QLIST_FOREACH(other_job, &txn->jobs, txn_list) {
402*62c9e416SKevin Wolf         if (!job_is_completed(other_job)) {
403c55a832fSFam Zheng             return;
404c55a832fSFam Zheng         }
405*62c9e416SKevin Wolf         assert(other_job->ret == 0);
406c55a832fSFam Zheng     }
4072da4617aSJohn Snow 
4085d4f3769SKevin Wolf     block_job_txn_apply(txn, block_job_transition_to_pending, false);
40911b61fbcSJohn Snow 
41011b61fbcSJohn Snow     /* If no jobs need manual finalization, automatically do so */
41111b61fbcSJohn Snow     if (block_job_txn_apply(txn, block_job_needs_finalize, false) == 0) {
41211b61fbcSJohn Snow         block_job_do_finalize(job);
41311b61fbcSJohn Snow     }
414c55a832fSFam Zheng }
415c55a832fSFam Zheng 
416da01ff7fSKevin Wolf /* Assumes the job_mutex is held */
417da01ff7fSKevin Wolf static bool job_timer_pending(Job *job)
418da01ff7fSKevin Wolf {
419da01ff7fSKevin Wolf     return timer_pending(&job->sleep_timer);
420da01ff7fSKevin Wolf }
421da01ff7fSKevin Wolf 
4222f0c9fe6SPaolo Bonzini void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
4232f0c9fe6SPaolo Bonzini {
424aa9ef2e6SJohn Snow     int64_t old_speed = job->speed;
4252f0c9fe6SPaolo Bonzini 
426a50c2ab8SKevin Wolf     if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp)) {
4270ec4dfb8SJohn Snow         return;
4280ec4dfb8SJohn Snow     }
42918bb6928SKevin Wolf     if (speed < 0) {
43018bb6928SKevin Wolf         error_setg(errp, QERR_INVALID_PARAMETER, "speed");
4312f0c9fe6SPaolo Bonzini         return;
4322f0c9fe6SPaolo Bonzini     }
4332f0c9fe6SPaolo Bonzini 
43418bb6928SKevin Wolf     ratelimit_set_speed(&job->limit, speed, BLOCK_JOB_SLICE_TIME);
43518bb6928SKevin Wolf 
4362f0c9fe6SPaolo Bonzini     job->speed = speed;
437d4fce188SJohn Snow     if (speed && speed <= old_speed) {
438aa9ef2e6SJohn Snow         return;
439aa9ef2e6SJohn Snow     }
440aa9ef2e6SJohn Snow 
441aa9ef2e6SJohn Snow     /* kick only if a timer is pending */
442da01ff7fSKevin Wolf     job_enter_cond(&job->job, job_timer_pending);
4432f0c9fe6SPaolo Bonzini }
4442f0c9fe6SPaolo Bonzini 
445dee81d51SKevin Wolf int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
446dee81d51SKevin Wolf {
447dee81d51SKevin Wolf     if (!job->speed) {
448dee81d51SKevin Wolf         return 0;
449dee81d51SKevin Wolf     }
450dee81d51SKevin Wolf 
451dee81d51SKevin Wolf     return ratelimit_calculate_delay(&job->limit, n);
452dee81d51SKevin Wolf }
453dee81d51SKevin Wolf 
45411b61fbcSJohn Snow void block_job_finalize(BlockJob *job, Error **errp)
45511b61fbcSJohn Snow {
45633e9e9bdSKevin Wolf     assert(job && job->job.id);
457a50c2ab8SKevin Wolf     if (job_apply_verb(&job->job, JOB_VERB_FINALIZE, errp)) {
45811b61fbcSJohn Snow         return;
45911b61fbcSJohn Snow     }
46011b61fbcSJohn Snow     block_job_do_finalize(job);
46111b61fbcSJohn Snow }
46211b61fbcSJohn Snow 
46375f71059SJohn Snow void block_job_dismiss(BlockJob **jobptr, Error **errp)
46475f71059SJohn Snow {
46575f71059SJohn Snow     BlockJob *job = *jobptr;
46675f71059SJohn Snow     /* similarly to _complete, this is QMP-interface only. */
46733e9e9bdSKevin Wolf     assert(job->job.id);
468a50c2ab8SKevin Wolf     if (job_apply_verb(&job->job, JOB_VERB_DISMISS, errp)) {
46975f71059SJohn Snow         return;
47075f71059SJohn Snow     }
47175f71059SJohn Snow 
4724ad35181SKevin Wolf     job_do_dismiss(&job->job);
47375f71059SJohn Snow     *jobptr = NULL;
47475f71059SJohn Snow }
47575f71059SJohn Snow 
476b76e4458SLiang Li void block_job_cancel(BlockJob *job, bool force)
4778acc72a4SPaolo Bonzini {
478a50c2ab8SKevin Wolf     if (job->job.status == JOB_STATUS_CONCLUDED) {
4794ad35181SKevin Wolf         job_do_dismiss(&job->job);
48011b61fbcSJohn Snow         return;
48111b61fbcSJohn Snow     }
482004e95dfSKevin Wolf     job_cancel_async(&job->job, force);
483da01ff7fSKevin Wolf     if (!job_started(&job->job)) {
4845ccac6f1SJohn Snow         block_job_completed(job, -ECANCELED);
4851908a559SKevin Wolf     } else if (job->job.deferred_to_main_loop) {
48611b61fbcSJohn Snow         block_job_completed_txn_abort(job);
48711b61fbcSJohn Snow     } else {
48811b61fbcSJohn Snow         block_job_enter(job);
4895ccac6f1SJohn Snow     }
4908acc72a4SPaolo Bonzini }
4918acc72a4SPaolo Bonzini 
492b76e4458SLiang Li void block_job_user_cancel(BlockJob *job, bool force, Error **errp)
4930ec4dfb8SJohn Snow {
494a50c2ab8SKevin Wolf     if (job_apply_verb(&job->job, JOB_VERB_CANCEL, errp)) {
4950ec4dfb8SJohn Snow         return;
4960ec4dfb8SJohn Snow     }
497b76e4458SLiang Li     block_job_cancel(job, force);
4980ec4dfb8SJohn Snow }
4990ec4dfb8SJohn Snow 
500345f9e1bSMax Reitz /* A wrapper around block_job_cancel() taking an Error ** parameter so it may be
5016a74c075SKevin Wolf  * used with job_finish_sync() without the need for (rather nasty) function
5026a74c075SKevin Wolf  * pointer casts there. */
5036a74c075SKevin Wolf static void block_job_cancel_err(Job *job, Error **errp)
504345f9e1bSMax Reitz {
5056a74c075SKevin Wolf     BlockJob *bjob = container_of(job, BlockJob, job);
5066a74c075SKevin Wolf     assert(is_block_job(job));
5076a74c075SKevin Wolf     block_job_cancel(bjob, false);
508345f9e1bSMax Reitz }
509345f9e1bSMax Reitz 
510345f9e1bSMax Reitz int block_job_cancel_sync(BlockJob *job)
511345f9e1bSMax Reitz {
5126a74c075SKevin Wolf     return job_finish_sync(&job->job, &block_job_cancel_err, NULL);
513345f9e1bSMax Reitz }
514345f9e1bSMax Reitz 
515a1a2af07SKevin Wolf void block_job_cancel_sync_all(void)
516a1a2af07SKevin Wolf {
517a1a2af07SKevin Wolf     BlockJob *job;
518a1a2af07SKevin Wolf     AioContext *aio_context;
519a1a2af07SKevin Wolf 
520e7c1d78bSKevin Wolf     while ((job = block_job_next(NULL))) {
521b6d2e599SKevin Wolf         aio_context = blk_get_aio_context(job->blk);
522a1a2af07SKevin Wolf         aio_context_acquire(aio_context);
523a1a2af07SKevin Wolf         block_job_cancel_sync(job);
524a1a2af07SKevin Wolf         aio_context_release(aio_context);
525a1a2af07SKevin Wolf     }
526a1a2af07SKevin Wolf }
527a1a2af07SKevin Wolf 
528345f9e1bSMax Reitz int block_job_complete_sync(BlockJob *job, Error **errp)
529345f9e1bSMax Reitz {
5306a74c075SKevin Wolf     return job_finish_sync(&job->job, job_complete, errp);
531345f9e1bSMax Reitz }
532345f9e1bSMax Reitz 
53305df8a6aSKevin Wolf void block_job_progress_update(BlockJob *job, uint64_t done)
53405df8a6aSKevin Wolf {
53505df8a6aSKevin Wolf     job->offset += done;
53605df8a6aSKevin Wolf }
53705df8a6aSKevin Wolf 
53805df8a6aSKevin Wolf void block_job_progress_set_remaining(BlockJob *job, uint64_t remaining)
53905df8a6aSKevin Wolf {
54005df8a6aSKevin Wolf     job->len = job->offset + remaining;
54105df8a6aSKevin Wolf }
54205df8a6aSKevin Wolf 
543559b935fSJohn Snow BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
54430e628b7SPaolo Bonzini {
545559b935fSJohn Snow     BlockJobInfo *info;
546559b935fSJohn Snow 
547559b935fSJohn Snow     if (block_job_is_internal(job)) {
548559b935fSJohn Snow         error_setg(errp, "Cannot query QEMU internal jobs");
549559b935fSJohn Snow         return NULL;
550559b935fSJohn Snow     }
551559b935fSJohn Snow     info = g_new0(BlockJobInfo, 1);
552252291eaSKevin Wolf     info->type      = g_strdup(job_type_str(&job->job));
55333e9e9bdSKevin Wolf     info->device    = g_strdup(job->job.id);
55430e628b7SPaolo Bonzini     info->len       = job->len;
555da01ff7fSKevin Wolf     info->busy      = atomic_read(&job->job.busy);
556da01ff7fSKevin Wolf     info->paused    = job->job.pause_count > 0;
55730e628b7SPaolo Bonzini     info->offset    = job->offset;
55830e628b7SPaolo Bonzini     info->speed     = job->speed;
55932c81a4aSPaolo Bonzini     info->io_status = job->iostatus;
560ef6dbf1eSMax Reitz     info->ready     = job->ready;
561a50c2ab8SKevin Wolf     info->status    = job->job.status;
562bb02b65cSKevin Wolf     info->auto_finalize = job->job.auto_finalize;
563bb02b65cSKevin Wolf     info->auto_dismiss  = job->job.auto_dismiss;
5644ad35181SKevin Wolf     info->has_error = job->job.ret != 0;
5654ad35181SKevin Wolf     info->error     = job->job.ret ? g_strdup(strerror(-job->job.ret)) : NULL;
56630e628b7SPaolo Bonzini     return info;
56730e628b7SPaolo Bonzini }
56832c81a4aSPaolo Bonzini 
56932c81a4aSPaolo Bonzini static void block_job_iostatus_set_err(BlockJob *job, int error)
57032c81a4aSPaolo Bonzini {
57132c81a4aSPaolo Bonzini     if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
57232c81a4aSPaolo Bonzini         job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
57332c81a4aSPaolo Bonzini                                           BLOCK_DEVICE_IO_STATUS_FAILED;
57432c81a4aSPaolo Bonzini     }
57532c81a4aSPaolo Bonzini }
57632c81a4aSPaolo Bonzini 
577139a9f02SKevin Wolf static void block_job_event_cancelled(Notifier *n, void *opaque)
578a66a2a36SPaolo Bonzini {
579139a9f02SKevin Wolf     BlockJob *job = opaque;
580139a9f02SKevin Wolf 
581559b935fSJohn Snow     if (block_job_is_internal(job)) {
582559b935fSJohn Snow         return;
583559b935fSJohn Snow     }
584559b935fSJohn Snow 
585252291eaSKevin Wolf     qapi_event_send_block_job_cancelled(job_type(&job->job),
58633e9e9bdSKevin Wolf                                         job->job.id,
587a66a2a36SPaolo Bonzini                                         job->len,
588a66a2a36SPaolo Bonzini                                         job->offset,
589bcada37bSWenchao Xia                                         job->speed,
590bcada37bSWenchao Xia                                         &error_abort);
591a66a2a36SPaolo Bonzini }
592a66a2a36SPaolo Bonzini 
593139a9f02SKevin Wolf static void block_job_event_completed(Notifier *n, void *opaque)
594a66a2a36SPaolo Bonzini {
595139a9f02SKevin Wolf     BlockJob *job = opaque;
596139a9f02SKevin Wolf     const char *msg = NULL;
597139a9f02SKevin Wolf 
598559b935fSJohn Snow     if (block_job_is_internal(job)) {
599559b935fSJohn Snow         return;
600559b935fSJohn Snow     }
601559b935fSJohn Snow 
6024ad35181SKevin Wolf     if (job->job.ret < 0) {
6034ad35181SKevin Wolf         msg = strerror(-job->job.ret);
604139a9f02SKevin Wolf     }
605139a9f02SKevin Wolf 
606252291eaSKevin Wolf     qapi_event_send_block_job_completed(job_type(&job->job),
60733e9e9bdSKevin Wolf                                         job->job.id,
608bcada37bSWenchao Xia                                         job->len,
609bcada37bSWenchao Xia                                         job->offset,
610bcada37bSWenchao Xia                                         job->speed,
611bcada37bSWenchao Xia                                         !!msg,
612bcada37bSWenchao Xia                                         msg,
613bcada37bSWenchao Xia                                         &error_abort);
614bcada37bSWenchao Xia }
615bcada37bSWenchao Xia 
616139a9f02SKevin Wolf static void block_job_event_pending(Notifier *n, void *opaque)
6175f241594SJohn Snow {
618139a9f02SKevin Wolf     BlockJob *job = opaque;
619139a9f02SKevin Wolf 
6205d4f3769SKevin Wolf     if (block_job_is_internal(job)) {
6215d4f3769SKevin Wolf         return;
6225d4f3769SKevin Wolf     }
6235d4f3769SKevin Wolf 
624252291eaSKevin Wolf     qapi_event_send_block_job_pending(job_type(&job->job),
62533e9e9bdSKevin Wolf                                       job->job.id,
6265f241594SJohn Snow                                       &error_abort);
6275f241594SJohn Snow }
6285f241594SJohn Snow 
62988691b37SPaolo Bonzini /*
63088691b37SPaolo Bonzini  * API for block job drivers and the block layer.  These functions are
63188691b37SPaolo Bonzini  * declared in blockjob_int.h.
63288691b37SPaolo Bonzini  */
63388691b37SPaolo Bonzini 
63488691b37SPaolo Bonzini void *block_job_create(const char *job_id, const BlockJobDriver *driver,
635*62c9e416SKevin Wolf                        JobTxn *txn, BlockDriverState *bs, uint64_t perm,
63688691b37SPaolo Bonzini                        uint64_t shared_perm, int64_t speed, int flags,
63788691b37SPaolo Bonzini                        BlockCompletionFunc *cb, void *opaque, Error **errp)
63888691b37SPaolo Bonzini {
63988691b37SPaolo Bonzini     BlockBackend *blk;
64088691b37SPaolo Bonzini     BlockJob *job;
64188691b37SPaolo Bonzini     int ret;
64288691b37SPaolo Bonzini 
64388691b37SPaolo Bonzini     if (bs->job) {
64488691b37SPaolo Bonzini         error_setg(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
64588691b37SPaolo Bonzini         return NULL;
64688691b37SPaolo Bonzini     }
64788691b37SPaolo Bonzini 
648bb02b65cSKevin Wolf     if (job_id == NULL && !(flags & JOB_INTERNAL)) {
64988691b37SPaolo Bonzini         job_id = bdrv_get_device_name(bs);
65088691b37SPaolo Bonzini     }
65188691b37SPaolo Bonzini 
65288691b37SPaolo Bonzini     blk = blk_new(perm, shared_perm);
65388691b37SPaolo Bonzini     ret = blk_insert_bs(blk, bs, errp);
65488691b37SPaolo Bonzini     if (ret < 0) {
65588691b37SPaolo Bonzini         blk_unref(blk);
65688691b37SPaolo Bonzini         return NULL;
65788691b37SPaolo Bonzini     }
65888691b37SPaolo Bonzini 
65908be6fe2SKevin Wolf     job = job_create(job_id, &driver->job_driver, blk_get_aio_context(blk),
6604ad35181SKevin Wolf                      flags, cb, opaque, errp);
66133e9e9bdSKevin Wolf     if (job == NULL) {
66233e9e9bdSKevin Wolf         blk_unref(blk);
66333e9e9bdSKevin Wolf         return NULL;
66433e9e9bdSKevin Wolf     }
66533e9e9bdSKevin Wolf 
666e7c1d78bSKevin Wolf     assert(is_block_job(&job->job));
66780fa2c75SKevin Wolf     assert(job->job.driver->free == &block_job_free);
668b15de828SKevin Wolf     assert(job->job.driver->user_resume == &block_job_user_resume);
669b69f777dSKevin Wolf     assert(job->job.driver->drain == &block_job_drain);
670e7c1d78bSKevin Wolf 
67188691b37SPaolo Bonzini     job->driver        = driver;
67288691b37SPaolo Bonzini     job->blk           = blk;
67388691b37SPaolo Bonzini 
674139a9f02SKevin Wolf     job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
675139a9f02SKevin Wolf     job->finalize_completed_notifier.notify = block_job_event_completed;
676139a9f02SKevin Wolf     job->pending_notifier.notify = block_job_event_pending;
677139a9f02SKevin Wolf 
678139a9f02SKevin Wolf     notifier_list_add(&job->job.on_finalize_cancelled,
679139a9f02SKevin Wolf                       &job->finalize_cancelled_notifier);
680139a9f02SKevin Wolf     notifier_list_add(&job->job.on_finalize_completed,
681139a9f02SKevin Wolf                       &job->finalize_completed_notifier);
682139a9f02SKevin Wolf     notifier_list_add(&job->job.on_pending, &job->pending_notifier);
683139a9f02SKevin Wolf 
68488691b37SPaolo Bonzini     error_setg(&job->blocker, "block device is in use by block job: %s",
685252291eaSKevin Wolf                job_type_str(&job->job));
68688691b37SPaolo Bonzini     block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
68788691b37SPaolo Bonzini     bs->job = job;
68888691b37SPaolo Bonzini 
68988691b37SPaolo Bonzini     bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
69088691b37SPaolo Bonzini 
69188691b37SPaolo Bonzini     blk_add_aio_context_notifier(blk, block_job_attached_aio_context,
69288691b37SPaolo Bonzini                                  block_job_detach_aio_context, job);
69388691b37SPaolo Bonzini 
69488691b37SPaolo Bonzini     /* Only set speed when necessary to avoid NotSupported error */
69588691b37SPaolo Bonzini     if (speed != 0) {
69688691b37SPaolo Bonzini         Error *local_err = NULL;
69788691b37SPaolo Bonzini 
69888691b37SPaolo Bonzini         block_job_set_speed(job, speed, &local_err);
69988691b37SPaolo Bonzini         if (local_err) {
7004ad35181SKevin Wolf             job_early_fail(&job->job);
70188691b37SPaolo Bonzini             error_propagate(errp, local_err);
70288691b37SPaolo Bonzini             return NULL;
70388691b37SPaolo Bonzini         }
70488691b37SPaolo Bonzini     }
70575859b94SJohn Snow 
70675859b94SJohn Snow     /* Single jobs are modeled as single-job transactions for sake of
70775859b94SJohn Snow      * consolidating the job management logic */
70875859b94SJohn Snow     if (!txn) {
70975859b94SJohn Snow         txn = block_job_txn_new();
71075859b94SJohn Snow         block_job_txn_add_job(txn, job);
71175859b94SJohn Snow         block_job_txn_unref(txn);
71275859b94SJohn Snow     } else {
71375859b94SJohn Snow         block_job_txn_add_job(txn, job);
71475859b94SJohn Snow     }
71575859b94SJohn Snow 
71688691b37SPaolo Bonzini     return job;
71788691b37SPaolo Bonzini }
71888691b37SPaolo Bonzini 
71988691b37SPaolo Bonzini void block_job_completed(BlockJob *job, int ret)
72088691b37SPaolo Bonzini {
721dbe5e6c1SKevin Wolf     assert(job && job->txn && !job_is_completed(&job->job));
72288691b37SPaolo Bonzini     assert(blk_bs(job->blk)->job == job);
7234ad35181SKevin Wolf     job->job.ret = ret;
7244ad35181SKevin Wolf     job_update_rc(&job->job);
7254ad35181SKevin Wolf     trace_block_job_completed(job, ret, job->job.ret);
7264ad35181SKevin Wolf     if (job->job.ret) {
72788691b37SPaolo Bonzini         block_job_completed_txn_abort(job);
72888691b37SPaolo Bonzini     } else {
72988691b37SPaolo Bonzini         block_job_completed_txn_success(job);
73088691b37SPaolo Bonzini     }
73188691b37SPaolo Bonzini }
73288691b37SPaolo Bonzini 
733aa9ef2e6SJohn Snow void block_job_enter(BlockJob *job)
734aa9ef2e6SJohn Snow {
735da01ff7fSKevin Wolf     job_enter_cond(&job->job, NULL);
736aa9ef2e6SJohn Snow }
737aa9ef2e6SJohn Snow 
73888691b37SPaolo Bonzini void block_job_yield(BlockJob *job)
73988691b37SPaolo Bonzini {
740da01ff7fSKevin Wolf     assert(job->job.busy);
74188691b37SPaolo Bonzini 
74288691b37SPaolo Bonzini     /* Check cancellation *before* setting busy = false, too!  */
743daa7f2f9SKevin Wolf     if (job_is_cancelled(&job->job)) {
74488691b37SPaolo Bonzini         return;
74588691b37SPaolo Bonzini     }
74688691b37SPaolo Bonzini 
747da01ff7fSKevin Wolf     if (!job_should_pause(&job->job)) {
748da01ff7fSKevin Wolf         job_do_yield(&job->job, -1);
74988691b37SPaolo Bonzini     }
75088691b37SPaolo Bonzini 
751da01ff7fSKevin Wolf     job_pause_point(&job->job);
75288691b37SPaolo Bonzini }
75388691b37SPaolo Bonzini 
7542caf63a9SPaolo Bonzini void block_job_iostatus_reset(BlockJob *job)
7552caf63a9SPaolo Bonzini {
7564c241cf5SPaolo Bonzini     if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
7574c241cf5SPaolo Bonzini         return;
7584c241cf5SPaolo Bonzini     }
759b15de828SKevin Wolf     assert(job->job.user_paused && job->job.pause_count > 0);
7602caf63a9SPaolo Bonzini     job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
7612caf63a9SPaolo Bonzini }
7622caf63a9SPaolo Bonzini 
763b15de828SKevin Wolf void block_job_user_resume(Job *job)
764b15de828SKevin Wolf {
765b15de828SKevin Wolf     BlockJob *bjob = container_of(job, BlockJob, job);
766b15de828SKevin Wolf     block_job_iostatus_reset(bjob);
767b15de828SKevin Wolf }
768b15de828SKevin Wolf 
769bcada37bSWenchao Xia void block_job_event_ready(BlockJob *job)
770bcada37bSWenchao Xia {
771a50c2ab8SKevin Wolf     job_state_transition(&job->job, JOB_STATUS_READY);
772ef6dbf1eSMax Reitz     job->ready = true;
773ef6dbf1eSMax Reitz 
774559b935fSJohn Snow     if (block_job_is_internal(job)) {
775559b935fSJohn Snow         return;
776559b935fSJohn Snow     }
777559b935fSJohn Snow 
778252291eaSKevin Wolf     qapi_event_send_block_job_ready(job_type(&job->job),
77933e9e9bdSKevin Wolf                                     job->job.id,
780518848a2SMarkus Armbruster                                     job->len,
781518848a2SMarkus Armbruster                                     job->offset,
782518848a2SMarkus Armbruster                                     job->speed, &error_abort);
783a66a2a36SPaolo Bonzini }
784a66a2a36SPaolo Bonzini 
78581e254dcSKevin Wolf BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err,
78632c81a4aSPaolo Bonzini                                         int is_read, int error)
78732c81a4aSPaolo Bonzini {
78832c81a4aSPaolo Bonzini     BlockErrorAction action;
78932c81a4aSPaolo Bonzini 
79032c81a4aSPaolo Bonzini     switch (on_err) {
79132c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_ENOSPC:
7928c398252SKevin Wolf     case BLOCKDEV_ON_ERROR_AUTO:
793a589569fSWenchao Xia         action = (error == ENOSPC) ?
794a589569fSWenchao Xia                  BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
79532c81a4aSPaolo Bonzini         break;
79632c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_STOP:
797a589569fSWenchao Xia         action = BLOCK_ERROR_ACTION_STOP;
79832c81a4aSPaolo Bonzini         break;
79932c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_REPORT:
800a589569fSWenchao Xia         action = BLOCK_ERROR_ACTION_REPORT;
80132c81a4aSPaolo Bonzini         break;
80232c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_IGNORE:
803a589569fSWenchao Xia         action = BLOCK_ERROR_ACTION_IGNORE;
80432c81a4aSPaolo Bonzini         break;
80532c81a4aSPaolo Bonzini     default:
80632c81a4aSPaolo Bonzini         abort();
80732c81a4aSPaolo Bonzini     }
808559b935fSJohn Snow     if (!block_job_is_internal(job)) {
80933e9e9bdSKevin Wolf         qapi_event_send_block_job_error(job->job.id,
8105a2d2cbdSWenchao Xia                                         is_read ? IO_OPERATION_TYPE_READ :
8115a2d2cbdSWenchao Xia                                         IO_OPERATION_TYPE_WRITE,
8125a2d2cbdSWenchao Xia                                         action, &error_abort);
813559b935fSJohn Snow     }
814a589569fSWenchao Xia     if (action == BLOCK_ERROR_ACTION_STOP) {
815b15de828SKevin Wolf         job_pause(&job->job);
816751ebd76SFam Zheng         /* make the pause user visible, which will be resumed from QMP. */
817b15de828SKevin Wolf         job->job.user_paused = true;
81832c81a4aSPaolo Bonzini         block_job_iostatus_set_err(job, error);
81932c81a4aSPaolo Bonzini     }
82032c81a4aSPaolo Bonzini     return action;
82132c81a4aSPaolo Bonzini }
822