xref: /qemu/blockjob.c (revision 097310b53e9d498ef8e127d52ea57905cbe46ec5)
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 
262f0c9fe6SPaolo Bonzini #include "config-host.h"
272f0c9fe6SPaolo Bonzini #include "qemu-common.h"
282f0c9fe6SPaolo Bonzini #include "trace.h"
29737e150eSPaolo Bonzini #include "block/block.h"
30737e150eSPaolo Bonzini #include "block/blockjob.h"
31737e150eSPaolo Bonzini #include "block/block_int.h"
327b1b5d19SPaolo Bonzini #include "qapi/qmp/qjson.h"
33737e150eSPaolo Bonzini #include "block/coroutine.h"
342f0c9fe6SPaolo Bonzini #include "qmp-commands.h"
351de7afc9SPaolo Bonzini #include "qemu/timer.h"
365a2d2cbdSWenchao Xia #include "qapi-event.h"
372f0c9fe6SPaolo Bonzini 
383fc4b10aSFam Zheng void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
39*097310b5SMarkus Armbruster                        int64_t speed, BlockCompletionFunc *cb,
402f0c9fe6SPaolo Bonzini                        void *opaque, Error **errp)
412f0c9fe6SPaolo Bonzini {
422f0c9fe6SPaolo Bonzini     BlockJob *job;
432f0c9fe6SPaolo Bonzini 
44628ff683SFam Zheng     if (bs->job) {
452f0c9fe6SPaolo Bonzini         error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
462f0c9fe6SPaolo Bonzini         return NULL;
472f0c9fe6SPaolo Bonzini     }
48fa510ebfSFam Zheng     bdrv_ref(bs);
493fc4b10aSFam Zheng     job = g_malloc0(driver->instance_size);
503718d8abSFam Zheng     error_setg(&job->blocker, "block device is in use by block job: %s",
513718d8abSFam Zheng                BlockJobType_lookup[driver->job_type]);
523718d8abSFam Zheng     bdrv_op_block_all(bs, job->blocker);
533718d8abSFam Zheng 
543fc4b10aSFam Zheng     job->driver        = driver;
552f0c9fe6SPaolo Bonzini     job->bs            = bs;
562f0c9fe6SPaolo Bonzini     job->cb            = cb;
572f0c9fe6SPaolo Bonzini     job->opaque        = opaque;
582f0c9fe6SPaolo Bonzini     job->busy          = true;
592f0c9fe6SPaolo Bonzini     bs->job = job;
602f0c9fe6SPaolo Bonzini 
612f0c9fe6SPaolo Bonzini     /* Only set speed when necessary to avoid NotSupported error */
622f0c9fe6SPaolo Bonzini     if (speed != 0) {
632f0c9fe6SPaolo Bonzini         Error *local_err = NULL;
642f0c9fe6SPaolo Bonzini 
652f0c9fe6SPaolo Bonzini         block_job_set_speed(job, speed, &local_err);
6684d18f06SMarkus Armbruster         if (local_err) {
672f0c9fe6SPaolo Bonzini             bs->job = NULL;
683718d8abSFam Zheng             bdrv_op_unblock_all(bs, job->blocker);
693718d8abSFam Zheng             error_free(job->blocker);
702f0c9fe6SPaolo Bonzini             g_free(job);
712f0c9fe6SPaolo Bonzini             error_propagate(errp, local_err);
722f0c9fe6SPaolo Bonzini             return NULL;
732f0c9fe6SPaolo Bonzini         }
742f0c9fe6SPaolo Bonzini     }
752f0c9fe6SPaolo Bonzini     return job;
762f0c9fe6SPaolo Bonzini }
772f0c9fe6SPaolo Bonzini 
7865f46322SPaolo Bonzini void block_job_completed(BlockJob *job, int ret)
792f0c9fe6SPaolo Bonzini {
802f0c9fe6SPaolo Bonzini     BlockDriverState *bs = job->bs;
812f0c9fe6SPaolo Bonzini 
822f0c9fe6SPaolo Bonzini     assert(bs->job == job);
832f0c9fe6SPaolo Bonzini     job->cb(job->opaque, ret);
842f0c9fe6SPaolo Bonzini     bs->job = NULL;
853718d8abSFam Zheng     bdrv_op_unblock_all(bs, job->blocker);
863718d8abSFam Zheng     error_free(job->blocker);
872f0c9fe6SPaolo Bonzini     g_free(job);
882f0c9fe6SPaolo Bonzini }
892f0c9fe6SPaolo Bonzini 
902f0c9fe6SPaolo Bonzini void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
912f0c9fe6SPaolo Bonzini {
922f0c9fe6SPaolo Bonzini     Error *local_err = NULL;
932f0c9fe6SPaolo Bonzini 
943fc4b10aSFam Zheng     if (!job->driver->set_speed) {
950b15abfcSCole Robinson         error_set(errp, QERR_UNSUPPORTED);
962f0c9fe6SPaolo Bonzini         return;
972f0c9fe6SPaolo Bonzini     }
983fc4b10aSFam Zheng     job->driver->set_speed(job, speed, &local_err);
9984d18f06SMarkus Armbruster     if (local_err) {
1002f0c9fe6SPaolo Bonzini         error_propagate(errp, local_err);
1012f0c9fe6SPaolo Bonzini         return;
1022f0c9fe6SPaolo Bonzini     }
1032f0c9fe6SPaolo Bonzini 
1042f0c9fe6SPaolo Bonzini     job->speed = speed;
1052f0c9fe6SPaolo Bonzini }
1062f0c9fe6SPaolo Bonzini 
107aeae883bSPaolo Bonzini void block_job_complete(BlockJob *job, Error **errp)
108aeae883bSPaolo Bonzini {
1093fc4b10aSFam Zheng     if (job->paused || job->cancelled || !job->driver->complete) {
110bfb197e0SMarkus Armbruster         error_set(errp, QERR_BLOCK_JOB_NOT_READY,
111bfb197e0SMarkus Armbruster                   bdrv_get_device_name(job->bs));
112aeae883bSPaolo Bonzini         return;
113aeae883bSPaolo Bonzini     }
114aeae883bSPaolo Bonzini 
1153fc4b10aSFam Zheng     job->driver->complete(job, errp);
116aeae883bSPaolo Bonzini }
117aeae883bSPaolo Bonzini 
1188acc72a4SPaolo Bonzini void block_job_pause(BlockJob *job)
1192f0c9fe6SPaolo Bonzini {
1208acc72a4SPaolo Bonzini     job->paused = true;
1218acc72a4SPaolo Bonzini }
1228acc72a4SPaolo Bonzini 
1238acc72a4SPaolo Bonzini bool block_job_is_paused(BlockJob *job)
1248acc72a4SPaolo Bonzini {
1258acc72a4SPaolo Bonzini     return job->paused;
1268acc72a4SPaolo Bonzini }
1278acc72a4SPaolo Bonzini 
1288acc72a4SPaolo Bonzini void block_job_resume(BlockJob *job)
1298acc72a4SPaolo Bonzini {
1308acc72a4SPaolo Bonzini     job->paused = false;
13132c81a4aSPaolo Bonzini     block_job_iostatus_reset(job);
1322f0c9fe6SPaolo Bonzini     if (job->co && !job->busy) {
1332f0c9fe6SPaolo Bonzini         qemu_coroutine_enter(job->co, NULL);
1342f0c9fe6SPaolo Bonzini     }
1352f0c9fe6SPaolo Bonzini }
1362f0c9fe6SPaolo Bonzini 
1378acc72a4SPaolo Bonzini void block_job_cancel(BlockJob *job)
1388acc72a4SPaolo Bonzini {
1398acc72a4SPaolo Bonzini     job->cancelled = true;
1408acc72a4SPaolo Bonzini     block_job_resume(job);
1418acc72a4SPaolo Bonzini }
1428acc72a4SPaolo Bonzini 
1432f0c9fe6SPaolo Bonzini bool block_job_is_cancelled(BlockJob *job)
1442f0c9fe6SPaolo Bonzini {
1452f0c9fe6SPaolo Bonzini     return job->cancelled;
1462f0c9fe6SPaolo Bonzini }
1472f0c9fe6SPaolo Bonzini 
14832c81a4aSPaolo Bonzini void block_job_iostatus_reset(BlockJob *job)
14932c81a4aSPaolo Bonzini {
15032c81a4aSPaolo Bonzini     job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
1513fc4b10aSFam Zheng     if (job->driver->iostatus_reset) {
1523fc4b10aSFam Zheng         job->driver->iostatus_reset(job);
1533bd293c3SPaolo Bonzini     }
15432c81a4aSPaolo Bonzini }
15532c81a4aSPaolo Bonzini 
1562f0c9fe6SPaolo Bonzini struct BlockCancelData {
1572f0c9fe6SPaolo Bonzini     BlockJob *job;
158*097310b5SMarkus Armbruster     BlockCompletionFunc *cb;
1592f0c9fe6SPaolo Bonzini     void *opaque;
1602f0c9fe6SPaolo Bonzini     bool cancelled;
1612f0c9fe6SPaolo Bonzini     int ret;
1622f0c9fe6SPaolo Bonzini };
1632f0c9fe6SPaolo Bonzini 
1642f0c9fe6SPaolo Bonzini static void block_job_cancel_cb(void *opaque, int ret)
1652f0c9fe6SPaolo Bonzini {
1662f0c9fe6SPaolo Bonzini     struct BlockCancelData *data = opaque;
1672f0c9fe6SPaolo Bonzini 
1682f0c9fe6SPaolo Bonzini     data->cancelled = block_job_is_cancelled(data->job);
1692f0c9fe6SPaolo Bonzini     data->ret = ret;
1702f0c9fe6SPaolo Bonzini     data->cb(data->opaque, ret);
1712f0c9fe6SPaolo Bonzini }
1722f0c9fe6SPaolo Bonzini 
1732f0c9fe6SPaolo Bonzini int block_job_cancel_sync(BlockJob *job)
1742f0c9fe6SPaolo Bonzini {
1752f0c9fe6SPaolo Bonzini     struct BlockCancelData data;
1762f0c9fe6SPaolo Bonzini     BlockDriverState *bs = job->bs;
1772f0c9fe6SPaolo Bonzini 
1782f0c9fe6SPaolo Bonzini     assert(bs->job == job);
1792f0c9fe6SPaolo Bonzini 
1802f0c9fe6SPaolo Bonzini     /* Set up our own callback to store the result and chain to
1812f0c9fe6SPaolo Bonzini      * the original callback.
1822f0c9fe6SPaolo Bonzini      */
1832f0c9fe6SPaolo Bonzini     data.job = job;
1842f0c9fe6SPaolo Bonzini     data.cb = job->cb;
1852f0c9fe6SPaolo Bonzini     data.opaque = job->opaque;
1862f0c9fe6SPaolo Bonzini     data.ret = -EINPROGRESS;
1872f0c9fe6SPaolo Bonzini     job->cb = block_job_cancel_cb;
1882f0c9fe6SPaolo Bonzini     job->opaque = &data;
1892f0c9fe6SPaolo Bonzini     block_job_cancel(job);
1902f0c9fe6SPaolo Bonzini     while (data.ret == -EINPROGRESS) {
191b47ec2c4SPaolo Bonzini         aio_poll(bdrv_get_aio_context(bs), true);
1922f0c9fe6SPaolo Bonzini     }
1932f0c9fe6SPaolo Bonzini     return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
1942f0c9fe6SPaolo Bonzini }
1952f0c9fe6SPaolo Bonzini 
1967483d1e5SAlex Bligh void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
1972f0c9fe6SPaolo Bonzini {
1988acc72a4SPaolo Bonzini     assert(job->busy);
1998acc72a4SPaolo Bonzini 
2002f0c9fe6SPaolo Bonzini     /* Check cancellation *before* setting busy = false, too!  */
2018acc72a4SPaolo Bonzini     if (block_job_is_cancelled(job)) {
2028acc72a4SPaolo Bonzini         return;
2032f0c9fe6SPaolo Bonzini     }
2048acc72a4SPaolo Bonzini 
2058acc72a4SPaolo Bonzini     job->busy = false;
2068acc72a4SPaolo Bonzini     if (block_job_is_paused(job)) {
2078acc72a4SPaolo Bonzini         qemu_coroutine_yield();
2088acc72a4SPaolo Bonzini     } else {
2090b9caf9bSFam Zheng         co_aio_sleep_ns(bdrv_get_aio_context(job->bs), type, ns);
2108acc72a4SPaolo Bonzini     }
2118acc72a4SPaolo Bonzini     job->busy = true;
2122f0c9fe6SPaolo Bonzini }
21330e628b7SPaolo Bonzini 
214dc71ce45SFam Zheng void block_job_yield(BlockJob *job)
215dc71ce45SFam Zheng {
216dc71ce45SFam Zheng     assert(job->busy);
217dc71ce45SFam Zheng 
218dc71ce45SFam Zheng     /* Check cancellation *before* setting busy = false, too!  */
219dc71ce45SFam Zheng     if (block_job_is_cancelled(job)) {
220dc71ce45SFam Zheng         return;
221dc71ce45SFam Zheng     }
222dc71ce45SFam Zheng 
223dc71ce45SFam Zheng     job->busy = false;
224dc71ce45SFam Zheng     qemu_coroutine_yield();
225dc71ce45SFam Zheng     job->busy = true;
226dc71ce45SFam Zheng }
227dc71ce45SFam Zheng 
22830e628b7SPaolo Bonzini BlockJobInfo *block_job_query(BlockJob *job)
22930e628b7SPaolo Bonzini {
23030e628b7SPaolo Bonzini     BlockJobInfo *info = g_new0(BlockJobInfo, 1);
23179e14bf7SFam Zheng     info->type      = g_strdup(BlockJobType_lookup[job->driver->job_type]);
23230e628b7SPaolo Bonzini     info->device    = g_strdup(bdrv_get_device_name(job->bs));
23330e628b7SPaolo Bonzini     info->len       = job->len;
2348d65883fSPaolo Bonzini     info->busy      = job->busy;
2358acc72a4SPaolo Bonzini     info->paused    = job->paused;
23630e628b7SPaolo Bonzini     info->offset    = job->offset;
23730e628b7SPaolo Bonzini     info->speed     = job->speed;
23832c81a4aSPaolo Bonzini     info->io_status = job->iostatus;
23930e628b7SPaolo Bonzini     return info;
24030e628b7SPaolo Bonzini }
24132c81a4aSPaolo Bonzini 
24232c81a4aSPaolo Bonzini static void block_job_iostatus_set_err(BlockJob *job, int error)
24332c81a4aSPaolo Bonzini {
24432c81a4aSPaolo Bonzini     if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
24532c81a4aSPaolo Bonzini         job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
24632c81a4aSPaolo Bonzini                                           BLOCK_DEVICE_IO_STATUS_FAILED;
24732c81a4aSPaolo Bonzini     }
24832c81a4aSPaolo Bonzini }
24932c81a4aSPaolo Bonzini 
250bcada37bSWenchao Xia void block_job_event_cancelled(BlockJob *job)
251a66a2a36SPaolo Bonzini {
252bcada37bSWenchao Xia     qapi_event_send_block_job_cancelled(job->driver->job_type,
253a66a2a36SPaolo Bonzini                                         bdrv_get_device_name(job->bs),
254a66a2a36SPaolo Bonzini                                         job->len,
255a66a2a36SPaolo Bonzini                                         job->offset,
256bcada37bSWenchao Xia                                         job->speed,
257bcada37bSWenchao Xia                                         &error_abort);
258a66a2a36SPaolo Bonzini }
259a66a2a36SPaolo Bonzini 
260bcada37bSWenchao Xia void block_job_event_completed(BlockJob *job, const char *msg)
261a66a2a36SPaolo Bonzini {
262bcada37bSWenchao Xia     qapi_event_send_block_job_completed(job->driver->job_type,
263bcada37bSWenchao Xia                                         bdrv_get_device_name(job->bs),
264bcada37bSWenchao Xia                                         job->len,
265bcada37bSWenchao Xia                                         job->offset,
266bcada37bSWenchao Xia                                         job->speed,
267bcada37bSWenchao Xia                                         !!msg,
268bcada37bSWenchao Xia                                         msg,
269bcada37bSWenchao Xia                                         &error_abort);
270bcada37bSWenchao Xia }
271bcada37bSWenchao Xia 
272bcada37bSWenchao Xia void block_job_event_ready(BlockJob *job)
273bcada37bSWenchao Xia {
274518848a2SMarkus Armbruster     qapi_event_send_block_job_ready(job->driver->job_type,
275518848a2SMarkus Armbruster                                     bdrv_get_device_name(job->bs),
276518848a2SMarkus Armbruster                                     job->len,
277518848a2SMarkus Armbruster                                     job->offset,
278518848a2SMarkus Armbruster                                     job->speed, &error_abort);
279a66a2a36SPaolo Bonzini }
280a66a2a36SPaolo Bonzini 
28132c81a4aSPaolo Bonzini BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
28232c81a4aSPaolo Bonzini                                         BlockdevOnError on_err,
28332c81a4aSPaolo Bonzini                                         int is_read, int error)
28432c81a4aSPaolo Bonzini {
28532c81a4aSPaolo Bonzini     BlockErrorAction action;
28632c81a4aSPaolo Bonzini 
28732c81a4aSPaolo Bonzini     switch (on_err) {
28832c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_ENOSPC:
289a589569fSWenchao Xia         action = (error == ENOSPC) ?
290a589569fSWenchao Xia                  BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
29132c81a4aSPaolo Bonzini         break;
29232c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_STOP:
293a589569fSWenchao Xia         action = BLOCK_ERROR_ACTION_STOP;
29432c81a4aSPaolo Bonzini         break;
29532c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_REPORT:
296a589569fSWenchao Xia         action = BLOCK_ERROR_ACTION_REPORT;
29732c81a4aSPaolo Bonzini         break;
29832c81a4aSPaolo Bonzini     case BLOCKDEV_ON_ERROR_IGNORE:
299a589569fSWenchao Xia         action = BLOCK_ERROR_ACTION_IGNORE;
30032c81a4aSPaolo Bonzini         break;
30132c81a4aSPaolo Bonzini     default:
30232c81a4aSPaolo Bonzini         abort();
30332c81a4aSPaolo Bonzini     }
304823c6863SMarkus Armbruster     qapi_event_send_block_job_error(bdrv_get_device_name(job->bs),
3055a2d2cbdSWenchao Xia                                     is_read ? IO_OPERATION_TYPE_READ :
3065a2d2cbdSWenchao Xia                                     IO_OPERATION_TYPE_WRITE,
3075a2d2cbdSWenchao Xia                                     action, &error_abort);
308a589569fSWenchao Xia     if (action == BLOCK_ERROR_ACTION_STOP) {
30932c81a4aSPaolo Bonzini         block_job_pause(job);
31032c81a4aSPaolo Bonzini         block_job_iostatus_set_err(job, error);
31132c81a4aSPaolo Bonzini         if (bs != job->bs) {
31232c81a4aSPaolo Bonzini             bdrv_iostatus_set_err(bs, error);
31332c81a4aSPaolo Bonzini         }
31432c81a4aSPaolo Bonzini     }
31532c81a4aSPaolo Bonzini     return action;
31632c81a4aSPaolo Bonzini }
317