xref: /openbmc/qemu/block/block-backend.c (revision a03ef88f)
126f54e9aSMarkus Armbruster /*
226f54e9aSMarkus Armbruster  * QEMU Block backends
326f54e9aSMarkus Armbruster  *
460cb2fa7SEric Blake  * Copyright (C) 2014-2016 Red Hat, Inc.
526f54e9aSMarkus Armbruster  *
626f54e9aSMarkus Armbruster  * Authors:
726f54e9aSMarkus Armbruster  *  Markus Armbruster <armbru@redhat.com>,
826f54e9aSMarkus Armbruster  *
926f54e9aSMarkus Armbruster  * This work is licensed under the terms of the GNU LGPL, version 2.1
1026f54e9aSMarkus Armbruster  * or later.  See the COPYING.LIB file in the top-level directory.
1126f54e9aSMarkus Armbruster  */
1226f54e9aSMarkus Armbruster 
1380c71a24SPeter Maydell #include "qemu/osdep.h"
1426f54e9aSMarkus Armbruster #include "sysemu/block-backend.h"
1526f54e9aSMarkus Armbruster #include "block/block_int.h"
16373340b2SMax Reitz #include "block/blockjob.h"
17281d22d8SMax Reitz #include "block/throttle-groups.h"
1818e46a03SMarkus Armbruster #include "sysemu/blockdev.h"
19373340b2SMax Reitz #include "sysemu/sysemu.h"
20a7f53e26SMarkus Armbruster #include "qapi-event.h"
21f348b6d1SVeronia Bahaa #include "qemu/id.h"
221e98fefdSKevin Wolf #include "trace.h"
23a7f53e26SMarkus Armbruster 
24a7f53e26SMarkus Armbruster /* Number of coroutines to reserve per attached device model */
25a7f53e26SMarkus Armbruster #define COROUTINE_POOL_RESERVATION 64
2626f54e9aSMarkus Armbruster 
271bf1cbc9SKevin Wolf #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
281bf1cbc9SKevin Wolf 
294981bdecSMax Reitz static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
304981bdecSMax Reitz 
3126f54e9aSMarkus Armbruster struct BlockBackend {
3226f54e9aSMarkus Armbruster     char *name;
3326f54e9aSMarkus Armbruster     int refcnt;
34f21d96d0SKevin Wolf     BdrvChild *root;
3526f8b3a8SMarkus Armbruster     DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
362cf22d6aSMax Reitz     QTAILQ_ENTRY(BlockBackend) link;         /* for block_backends */
379492b0b9SMax Reitz     QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
38f2cd875dSKevin Wolf     BlockBackendPublic public;
39a7f53e26SMarkus Armbruster 
40a7f53e26SMarkus Armbruster     void *dev;                  /* attached device model, if any */
41a7f53e26SMarkus Armbruster     /* TODO change to DeviceState when all users are qdevified */
42a7f53e26SMarkus Armbruster     const BlockDevOps *dev_ops;
43a7f53e26SMarkus Armbruster     void *dev_opaque;
4468e9ec01SMax Reitz 
4568e9ec01SMax Reitz     /* the block size for which the guest device expects atomicity */
4668e9ec01SMax Reitz     int guest_block_size;
477f0e9da6SMax Reitz 
48281d22d8SMax Reitz     /* If the BDS tree is removed, some of its options are stored here (which
49281d22d8SMax Reitz      * can be used to restore those options in the new BDS on insert) */
50281d22d8SMax Reitz     BlockBackendRootState root_state;
51281d22d8SMax Reitz 
52bfd18d1eSKevin Wolf     bool enable_write_cache;
53bfd18d1eSKevin Wolf 
547f0e9da6SMax Reitz     /* I/O stats (display with "info blockstats"). */
557f0e9da6SMax Reitz     BlockAcctStats stats;
56373340b2SMax Reitz 
57373340b2SMax Reitz     BlockdevOnError on_read_error, on_write_error;
58373340b2SMax Reitz     bool iostatus_enabled;
59373340b2SMax Reitz     BlockDeviceIoStatus iostatus;
603301f6c6SMax Reitz 
61c10c9d96SKevin Wolf     bool allow_write_beyond_eof;
62c10c9d96SKevin Wolf 
633301f6c6SMax Reitz     NotifierList remove_bs_notifiers, insert_bs_notifiers;
6426f54e9aSMarkus Armbruster };
6526f54e9aSMarkus Armbruster 
66e7f7d676SMax Reitz typedef struct BlockBackendAIOCB {
67e7f7d676SMax Reitz     BlockAIOCB common;
68e7f7d676SMax Reitz     QEMUBH *bh;
694981bdecSMax Reitz     BlockBackend *blk;
70e7f7d676SMax Reitz     int ret;
71e7f7d676SMax Reitz } BlockBackendAIOCB;
72e7f7d676SMax Reitz 
73e7f7d676SMax Reitz static const AIOCBInfo block_backend_aiocb_info = {
744981bdecSMax Reitz     .get_aio_context = blk_aiocb_get_aio_context,
75e7f7d676SMax Reitz     .aiocb_size = sizeof(BlockBackendAIOCB),
76e7f7d676SMax Reitz };
77e7f7d676SMax Reitz 
788fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo);
797c8eece4SKevin Wolf static BlockBackend *bdrv_first_blk(BlockDriverState *bs);
808fb3c76cSMarkus Armbruster 
812cf22d6aSMax Reitz /* All BlockBackends */
822cf22d6aSMax Reitz static QTAILQ_HEAD(, BlockBackend) block_backends =
832cf22d6aSMax Reitz     QTAILQ_HEAD_INITIALIZER(block_backends);
842cf22d6aSMax Reitz 
859492b0b9SMax Reitz /* All BlockBackends referenced by the monitor and which are iterated through by
869492b0b9SMax Reitz  * blk_next() */
879492b0b9SMax Reitz static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
889492b0b9SMax Reitz     QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
8926f54e9aSMarkus Armbruster 
90f21d96d0SKevin Wolf static void blk_root_inherit_options(int *child_flags, QDict *child_options,
91f21d96d0SKevin Wolf                                      int parent_flags, QDict *parent_options)
92f21d96d0SKevin Wolf {
93f21d96d0SKevin Wolf     /* We're not supposed to call this function for root nodes */
94f21d96d0SKevin Wolf     abort();
95f21d96d0SKevin Wolf }
96c2066af0SKevin Wolf static void blk_root_drained_begin(BdrvChild *child);
97c2066af0SKevin Wolf static void blk_root_drained_end(BdrvChild *child);
98f21d96d0SKevin Wolf 
995c8cab48SKevin Wolf static void blk_root_change_media(BdrvChild *child, bool load);
1005c8cab48SKevin Wolf static void blk_root_resize(BdrvChild *child);
1015c8cab48SKevin Wolf 
1024c265bf9SKevin Wolf static const char *blk_root_get_name(BdrvChild *child)
1034c265bf9SKevin Wolf {
1044c265bf9SKevin Wolf     return blk_name(child->opaque);
1054c265bf9SKevin Wolf }
1064c265bf9SKevin Wolf 
107f21d96d0SKevin Wolf static const BdrvChildRole child_root = {
108f21d96d0SKevin Wolf     .inherit_options    = blk_root_inherit_options,
109c2066af0SKevin Wolf 
1105c8cab48SKevin Wolf     .change_media       = blk_root_change_media,
1115c8cab48SKevin Wolf     .resize             = blk_root_resize,
1124c265bf9SKevin Wolf     .get_name           = blk_root_get_name,
1135c8cab48SKevin Wolf 
114c2066af0SKevin Wolf     .drained_begin      = blk_root_drained_begin,
115c2066af0SKevin Wolf     .drained_end        = blk_root_drained_end,
116f21d96d0SKevin Wolf };
117f21d96d0SKevin Wolf 
11826f54e9aSMarkus Armbruster /*
119efaa7c4eSMax Reitz  * Create a new BlockBackend with a reference count of one.
12026f54e9aSMarkus Armbruster  * Store an error through @errp on failure, unless it's null.
12126f54e9aSMarkus Armbruster  * Return the new BlockBackend on success, null on failure.
12226f54e9aSMarkus Armbruster  */
123109525adSMax Reitz BlockBackend *blk_new(void)
12426f54e9aSMarkus Armbruster {
12526f54e9aSMarkus Armbruster     BlockBackend *blk;
12626f54e9aSMarkus Armbruster 
12726f54e9aSMarkus Armbruster     blk = g_new0(BlockBackend, 1);
12826f54e9aSMarkus Armbruster     blk->refcnt = 1;
1290c3169dfSKevin Wolf     blk_set_enable_write_cache(blk, true);
1300c3169dfSKevin Wolf 
13127ccdd52SKevin Wolf     qemu_co_queue_init(&blk->public.throttled_reqs[0]);
13227ccdd52SKevin Wolf     qemu_co_queue_init(&blk->public.throttled_reqs[1]);
13327ccdd52SKevin Wolf 
1343301f6c6SMax Reitz     notifier_list_init(&blk->remove_bs_notifiers);
1353301f6c6SMax Reitz     notifier_list_init(&blk->insert_bs_notifiers);
13627ccdd52SKevin Wolf 
1372cf22d6aSMax Reitz     QTAILQ_INSERT_TAIL(&block_backends, blk, link);
13826f54e9aSMarkus Armbruster     return blk;
13926f54e9aSMarkus Armbruster }
14026f54e9aSMarkus Armbruster 
1417e7d56d9SMarkus Armbruster /*
14228eb9b12SMax Reitz  * Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
143ca49a4fdSMax Reitz  *
144ca49a4fdSMax Reitz  * Just as with bdrv_open(), after having called this function the reference to
145ca49a4fdSMax Reitz  * @options belongs to the block layer (even on failure).
146ca49a4fdSMax Reitz  *
147ca49a4fdSMax Reitz  * TODO: Remove @filename and @flags; it should be possible to specify a whole
148ca49a4fdSMax Reitz  * BDS tree just by specifying the @options QDict (or @reference,
149ca49a4fdSMax Reitz  * alternatively). At the time of adding this function, this is not possible,
150ca49a4fdSMax Reitz  * though, so callers of this function have to be able to specify @filename and
151ca49a4fdSMax Reitz  * @flags.
152ca49a4fdSMax Reitz  */
153efaa7c4eSMax Reitz BlockBackend *blk_new_open(const char *filename, const char *reference,
154efaa7c4eSMax Reitz                            QDict *options, int flags, Error **errp)
155ca49a4fdSMax Reitz {
156ca49a4fdSMax Reitz     BlockBackend *blk;
15728eb9b12SMax Reitz     BlockDriverState *bs;
158ca49a4fdSMax Reitz 
159109525adSMax Reitz     blk = blk_new();
1605b363937SMax Reitz     bs = bdrv_open(filename, reference, options, flags, errp);
1615b363937SMax Reitz     if (!bs) {
162ca49a4fdSMax Reitz         blk_unref(blk);
163ca49a4fdSMax Reitz         return NULL;
164ca49a4fdSMax Reitz     }
165ca49a4fdSMax Reitz 
16636fe1331SKevin Wolf     blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk);
16772e775c7SKevin Wolf 
168ca49a4fdSMax Reitz     return blk;
169ca49a4fdSMax Reitz }
170ca49a4fdSMax Reitz 
17126f54e9aSMarkus Armbruster static void blk_delete(BlockBackend *blk)
17226f54e9aSMarkus Armbruster {
17326f54e9aSMarkus Armbruster     assert(!blk->refcnt);
174e5e78550SMax Reitz     assert(!blk->name);
175a7f53e26SMarkus Armbruster     assert(!blk->dev);
176f21d96d0SKevin Wolf     if (blk->root) {
17713855c6bSMax Reitz         blk_remove_bs(blk);
1787e7d56d9SMarkus Armbruster     }
1793301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
1803301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
1812cf22d6aSMax Reitz     QTAILQ_REMOVE(&block_backends, blk, link);
18218e46a03SMarkus Armbruster     drive_info_del(blk->legacy_dinfo);
183979e9b03SAlberto Garcia     block_acct_cleanup(&blk->stats);
18426f54e9aSMarkus Armbruster     g_free(blk);
18526f54e9aSMarkus Armbruster }
18626f54e9aSMarkus Armbruster 
1878fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo)
1888fb3c76cSMarkus Armbruster {
1898fb3c76cSMarkus Armbruster     if (!dinfo) {
1908fb3c76cSMarkus Armbruster         return;
1918fb3c76cSMarkus Armbruster     }
1928fb3c76cSMarkus Armbruster     qemu_opts_del(dinfo->opts);
1938fb3c76cSMarkus Armbruster     g_free(dinfo->serial);
1948fb3c76cSMarkus Armbruster     g_free(dinfo);
1958fb3c76cSMarkus Armbruster }
1968fb3c76cSMarkus Armbruster 
197f636ae85SAlberto Garcia int blk_get_refcnt(BlockBackend *blk)
198f636ae85SAlberto Garcia {
199f636ae85SAlberto Garcia     return blk ? blk->refcnt : 0;
200f636ae85SAlberto Garcia }
201f636ae85SAlberto Garcia 
20226f54e9aSMarkus Armbruster /*
20326f54e9aSMarkus Armbruster  * Increment @blk's reference count.
20426f54e9aSMarkus Armbruster  * @blk must not be null.
20526f54e9aSMarkus Armbruster  */
20626f54e9aSMarkus Armbruster void blk_ref(BlockBackend *blk)
20726f54e9aSMarkus Armbruster {
20826f54e9aSMarkus Armbruster     blk->refcnt++;
20926f54e9aSMarkus Armbruster }
21026f54e9aSMarkus Armbruster 
21126f54e9aSMarkus Armbruster /*
21226f54e9aSMarkus Armbruster  * Decrement @blk's reference count.
21326f54e9aSMarkus Armbruster  * If this drops it to zero, destroy @blk.
21426f54e9aSMarkus Armbruster  * For convenience, do nothing if @blk is null.
21526f54e9aSMarkus Armbruster  */
21626f54e9aSMarkus Armbruster void blk_unref(BlockBackend *blk)
21726f54e9aSMarkus Armbruster {
21826f54e9aSMarkus Armbruster     if (blk) {
21926f54e9aSMarkus Armbruster         assert(blk->refcnt > 0);
22026f54e9aSMarkus Armbruster         if (!--blk->refcnt) {
22126f54e9aSMarkus Armbruster             blk_delete(blk);
22226f54e9aSMarkus Armbruster         }
22326f54e9aSMarkus Armbruster     }
22426f54e9aSMarkus Armbruster }
22526f54e9aSMarkus Armbruster 
2262cf22d6aSMax Reitz /*
2272cf22d6aSMax Reitz  * Behaves similarly to blk_next() but iterates over all BlockBackends, even the
2282cf22d6aSMax Reitz  * ones which are hidden (i.e. are not referenced by the monitor).
2292cf22d6aSMax Reitz  */
2302cf22d6aSMax Reitz static BlockBackend *blk_all_next(BlockBackend *blk)
2312cf22d6aSMax Reitz {
2322cf22d6aSMax Reitz     return blk ? QTAILQ_NEXT(blk, link)
2332cf22d6aSMax Reitz                : QTAILQ_FIRST(&block_backends);
2342cf22d6aSMax Reitz }
2352cf22d6aSMax Reitz 
236d8da3cefSMax Reitz void blk_remove_all_bs(void)
237d8da3cefSMax Reitz {
23874d1b8fcSMax Reitz     BlockBackend *blk = NULL;
239d8da3cefSMax Reitz 
2402cf22d6aSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
241d8da3cefSMax Reitz         AioContext *ctx = blk_get_aio_context(blk);
242d8da3cefSMax Reitz 
243d8da3cefSMax Reitz         aio_context_acquire(ctx);
244f21d96d0SKevin Wolf         if (blk->root) {
245d8da3cefSMax Reitz             blk_remove_bs(blk);
246d8da3cefSMax Reitz         }
247d8da3cefSMax Reitz         aio_context_release(ctx);
248d8da3cefSMax Reitz     }
249d8da3cefSMax Reitz }
250d8da3cefSMax Reitz 
25126f54e9aSMarkus Armbruster /*
2529492b0b9SMax Reitz  * Return the monitor-owned BlockBackend after @blk.
25326f54e9aSMarkus Armbruster  * If @blk is null, return the first one.
25426f54e9aSMarkus Armbruster  * Else, return @blk's next sibling, which may be null.
25526f54e9aSMarkus Armbruster  *
25626f54e9aSMarkus Armbruster  * To iterate over all BlockBackends, do
25726f54e9aSMarkus Armbruster  * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
25826f54e9aSMarkus Armbruster  *     ...
25926f54e9aSMarkus Armbruster  * }
26026f54e9aSMarkus Armbruster  */
26126f54e9aSMarkus Armbruster BlockBackend *blk_next(BlockBackend *blk)
26226f54e9aSMarkus Armbruster {
2639492b0b9SMax Reitz     return blk ? QTAILQ_NEXT(blk, monitor_link)
2649492b0b9SMax Reitz                : QTAILQ_FIRST(&monitor_block_backends);
26526f54e9aSMarkus Armbruster }
26626f54e9aSMarkus Armbruster 
2677c8eece4SKevin Wolf /* Iterates over all top-level BlockDriverStates, i.e. BDSs that are owned by
2687c8eece4SKevin Wolf  * the monitor or attached to a BlockBackend */
26988be7b4bSKevin Wolf BlockDriverState *bdrv_next(BdrvNextIterator *it)
2707c8eece4SKevin Wolf {
27188be7b4bSKevin Wolf     BlockDriverState *bs;
272981f4f57SMax Reitz 
2737c8eece4SKevin Wolf     /* First, return all root nodes of BlockBackends. In order to avoid
2747c8eece4SKevin Wolf      * returning a BDS twice when multiple BBs refer to it, we only return it
2757c8eece4SKevin Wolf      * if the BB is the first one in the parent list of the BDS. */
2767c8eece4SKevin Wolf     if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
277981f4f57SMax Reitz         do {
2787c8eece4SKevin Wolf             it->blk = blk_all_next(it->blk);
27988be7b4bSKevin Wolf             bs = it->blk ? blk_bs(it->blk) : NULL;
28088be7b4bSKevin Wolf         } while (it->blk && (bs == NULL || bdrv_first_blk(bs) != it->blk));
281981f4f57SMax Reitz 
28288be7b4bSKevin Wolf         if (bs) {
28388be7b4bSKevin Wolf             return bs;
2847c8eece4SKevin Wolf         }
2857c8eece4SKevin Wolf         it->phase = BDRV_NEXT_MONITOR_OWNED;
2867c8eece4SKevin Wolf     }
2877c8eece4SKevin Wolf 
2887c8eece4SKevin Wolf     /* Then return the monitor-owned BDSes without a BB attached. Ignore all
2897c8eece4SKevin Wolf      * BDSes that are attached to a BlockBackend here; they have been handled
2907c8eece4SKevin Wolf      * by the above block already */
2917c8eece4SKevin Wolf     do {
2927c8eece4SKevin Wolf         it->bs = bdrv_next_monitor_owned(it->bs);
29388be7b4bSKevin Wolf         bs = it->bs;
29488be7b4bSKevin Wolf     } while (bs && bdrv_has_blk(bs));
2957c8eece4SKevin Wolf 
29688be7b4bSKevin Wolf     return bs;
29788be7b4bSKevin Wolf }
29888be7b4bSKevin Wolf 
29988be7b4bSKevin Wolf BlockDriverState *bdrv_first(BdrvNextIterator *it)
30088be7b4bSKevin Wolf {
30188be7b4bSKevin Wolf     *it = (BdrvNextIterator) {
30288be7b4bSKevin Wolf         .phase = BDRV_NEXT_BACKEND_ROOTS,
30388be7b4bSKevin Wolf     };
30488be7b4bSKevin Wolf 
30588be7b4bSKevin Wolf     return bdrv_next(it);
306981f4f57SMax Reitz }
307981f4f57SMax Reitz 
308981f4f57SMax Reitz /*
309e5e78550SMax Reitz  * Add a BlockBackend into the list of backends referenced by the monitor, with
310e5e78550SMax Reitz  * the given @name acting as the handle for the monitor.
311e5e78550SMax Reitz  * Strictly for use by blockdev.c.
312e5e78550SMax Reitz  *
313e5e78550SMax Reitz  * @name must not be null or empty.
314e5e78550SMax Reitz  *
315e5e78550SMax Reitz  * Returns true on success and false on failure. In the latter case, an Error
316e5e78550SMax Reitz  * object is returned through @errp.
317e5e78550SMax Reitz  */
318e5e78550SMax Reitz bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
319e5e78550SMax Reitz {
320e5e78550SMax Reitz     assert(!blk->name);
321e5e78550SMax Reitz     assert(name && name[0]);
322e5e78550SMax Reitz 
323e5e78550SMax Reitz     if (!id_wellformed(name)) {
324e5e78550SMax Reitz         error_setg(errp, "Invalid device name");
325e5e78550SMax Reitz         return false;
326e5e78550SMax Reitz     }
327e5e78550SMax Reitz     if (blk_by_name(name)) {
328e5e78550SMax Reitz         error_setg(errp, "Device with id '%s' already exists", name);
329e5e78550SMax Reitz         return false;
330e5e78550SMax Reitz     }
331e5e78550SMax Reitz     if (bdrv_find_node(name)) {
332e5e78550SMax Reitz         error_setg(errp,
333e5e78550SMax Reitz                    "Device name '%s' conflicts with an existing node name",
334e5e78550SMax Reitz                    name);
335e5e78550SMax Reitz         return false;
336e5e78550SMax Reitz     }
337e5e78550SMax Reitz 
338e5e78550SMax Reitz     blk->name = g_strdup(name);
339e5e78550SMax Reitz     QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
340e5e78550SMax Reitz     return true;
341e5e78550SMax Reitz }
342e5e78550SMax Reitz 
343e5e78550SMax Reitz /*
344e5e78550SMax Reitz  * Remove a BlockBackend from the list of backends referenced by the monitor.
345e5e78550SMax Reitz  * Strictly for use by blockdev.c.
346e5e78550SMax Reitz  */
347e5e78550SMax Reitz void monitor_remove_blk(BlockBackend *blk)
348e5e78550SMax Reitz {
349e5e78550SMax Reitz     if (!blk->name) {
350e5e78550SMax Reitz         return;
351e5e78550SMax Reitz     }
352e5e78550SMax Reitz 
353e5e78550SMax Reitz     QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
354e5e78550SMax Reitz     g_free(blk->name);
355e5e78550SMax Reitz     blk->name = NULL;
356e5e78550SMax Reitz }
357e5e78550SMax Reitz 
358e5e78550SMax Reitz /*
3597e7d56d9SMarkus Armbruster  * Return @blk's name, a non-null string.
360e5e78550SMax Reitz  * Returns an empty string iff @blk is not referenced by the monitor.
36126f54e9aSMarkus Armbruster  */
36226f54e9aSMarkus Armbruster const char *blk_name(BlockBackend *blk)
36326f54e9aSMarkus Armbruster {
364e5e78550SMax Reitz     return blk->name ?: "";
36526f54e9aSMarkus Armbruster }
36626f54e9aSMarkus Armbruster 
36726f54e9aSMarkus Armbruster /*
36826f54e9aSMarkus Armbruster  * Return the BlockBackend with name @name if it exists, else null.
36926f54e9aSMarkus Armbruster  * @name must not be null.
37026f54e9aSMarkus Armbruster  */
37126f54e9aSMarkus Armbruster BlockBackend *blk_by_name(const char *name)
37226f54e9aSMarkus Armbruster {
37374d1b8fcSMax Reitz     BlockBackend *blk = NULL;
37426f54e9aSMarkus Armbruster 
37526f54e9aSMarkus Armbruster     assert(name);
37674d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
37726f54e9aSMarkus Armbruster         if (!strcmp(name, blk->name)) {
37826f54e9aSMarkus Armbruster             return blk;
37926f54e9aSMarkus Armbruster         }
38026f54e9aSMarkus Armbruster     }
38126f54e9aSMarkus Armbruster     return NULL;
38226f54e9aSMarkus Armbruster }
3837e7d56d9SMarkus Armbruster 
3847e7d56d9SMarkus Armbruster /*
3857e7d56d9SMarkus Armbruster  * Return the BlockDriverState attached to @blk if any, else null.
3867e7d56d9SMarkus Armbruster  */
3877e7d56d9SMarkus Armbruster BlockDriverState *blk_bs(BlockBackend *blk)
3887e7d56d9SMarkus Armbruster {
389f21d96d0SKevin Wolf     return blk->root ? blk->root->bs : NULL;
3907e7d56d9SMarkus Armbruster }
3917e7d56d9SMarkus Armbruster 
3927c8eece4SKevin Wolf static BlockBackend *bdrv_first_blk(BlockDriverState *bs)
393dde33812SKevin Wolf {
394dde33812SKevin Wolf     BdrvChild *child;
395dde33812SKevin Wolf     QLIST_FOREACH(child, &bs->parents, next_parent) {
396dde33812SKevin Wolf         if (child->role == &child_root) {
3977c8eece4SKevin Wolf             return child->opaque;
398dde33812SKevin Wolf         }
399dde33812SKevin Wolf     }
400dde33812SKevin Wolf 
4017c8eece4SKevin Wolf     return NULL;
4027c8eece4SKevin Wolf }
4037c8eece4SKevin Wolf 
4047c8eece4SKevin Wolf /*
4057c8eece4SKevin Wolf  * Returns true if @bs has an associated BlockBackend.
4067c8eece4SKevin Wolf  */
4077c8eece4SKevin Wolf bool bdrv_has_blk(BlockDriverState *bs)
4087c8eece4SKevin Wolf {
4097c8eece4SKevin Wolf     return bdrv_first_blk(bs) != NULL;
410dde33812SKevin Wolf }
411dde33812SKevin Wolf 
412dde33812SKevin Wolf /*
41318e46a03SMarkus Armbruster  * Return @blk's DriveInfo if any, else null.
41418e46a03SMarkus Armbruster  */
41518e46a03SMarkus Armbruster DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
41618e46a03SMarkus Armbruster {
41718e46a03SMarkus Armbruster     return blk->legacy_dinfo;
41818e46a03SMarkus Armbruster }
41918e46a03SMarkus Armbruster 
42018e46a03SMarkus Armbruster /*
42118e46a03SMarkus Armbruster  * Set @blk's DriveInfo to @dinfo, and return it.
42218e46a03SMarkus Armbruster  * @blk must not have a DriveInfo set already.
42318e46a03SMarkus Armbruster  * No other BlockBackend may have the same DriveInfo set.
42418e46a03SMarkus Armbruster  */
42518e46a03SMarkus Armbruster DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
42618e46a03SMarkus Armbruster {
42718e46a03SMarkus Armbruster     assert(!blk->legacy_dinfo);
42818e46a03SMarkus Armbruster     return blk->legacy_dinfo = dinfo;
42918e46a03SMarkus Armbruster }
43018e46a03SMarkus Armbruster 
43118e46a03SMarkus Armbruster /*
43218e46a03SMarkus Armbruster  * Return the BlockBackend with DriveInfo @dinfo.
43318e46a03SMarkus Armbruster  * It must exist.
43418e46a03SMarkus Armbruster  */
43518e46a03SMarkus Armbruster BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
43618e46a03SMarkus Armbruster {
43774d1b8fcSMax Reitz     BlockBackend *blk = NULL;
43818e46a03SMarkus Armbruster 
43974d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
44018e46a03SMarkus Armbruster         if (blk->legacy_dinfo == dinfo) {
44118e46a03SMarkus Armbruster             return blk;
44218e46a03SMarkus Armbruster         }
44318e46a03SMarkus Armbruster     }
44418e46a03SMarkus Armbruster     abort();
44518e46a03SMarkus Armbruster }
44618e46a03SMarkus Armbruster 
44718e46a03SMarkus Armbruster /*
448f2cd875dSKevin Wolf  * Returns a pointer to the publicly accessible fields of @blk.
449f2cd875dSKevin Wolf  */
450f2cd875dSKevin Wolf BlockBackendPublic *blk_get_public(BlockBackend *blk)
451f2cd875dSKevin Wolf {
452f2cd875dSKevin Wolf     return &blk->public;
453f2cd875dSKevin Wolf }
454f2cd875dSKevin Wolf 
455f2cd875dSKevin Wolf /*
456f2cd875dSKevin Wolf  * Returns a BlockBackend given the associated @public fields.
457f2cd875dSKevin Wolf  */
458f2cd875dSKevin Wolf BlockBackend *blk_by_public(BlockBackendPublic *public)
459f2cd875dSKevin Wolf {
460f2cd875dSKevin Wolf     return container_of(public, BlockBackend, public);
461f2cd875dSKevin Wolf }
462f2cd875dSKevin Wolf 
463f2cd875dSKevin Wolf /*
4641c95f7e1SMax Reitz  * Disassociates the currently associated BlockDriverState from @blk.
4651c95f7e1SMax Reitz  */
4661c95f7e1SMax Reitz void blk_remove_bs(BlockBackend *blk)
4671c95f7e1SMax Reitz {
4683301f6c6SMax Reitz     notifier_list_notify(&blk->remove_bs_notifiers, blk);
4697ca7f0f6SKevin Wolf     if (blk->public.throttle_state) {
4707ca7f0f6SKevin Wolf         throttle_timers_detach_aio_context(&blk->public.throttle_timers);
4717ca7f0f6SKevin Wolf     }
4723301f6c6SMax Reitz 
4731c95f7e1SMax Reitz     blk_update_root_state(blk);
4741c95f7e1SMax Reitz 
475f21d96d0SKevin Wolf     bdrv_root_unref_child(blk->root);
476f21d96d0SKevin Wolf     blk->root = NULL;
4771c95f7e1SMax Reitz }
4781c95f7e1SMax Reitz 
4791c95f7e1SMax Reitz /*
4800c3c36d6SMax Reitz  * Associates a new BlockDriverState with @blk.
4810c3c36d6SMax Reitz  */
4820c3c36d6SMax Reitz void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
4830c3c36d6SMax Reitz {
4840c3c36d6SMax Reitz     bdrv_ref(bs);
48536fe1331SKevin Wolf     blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk);
4863301f6c6SMax Reitz 
4873301f6c6SMax Reitz     notifier_list_notify(&blk->insert_bs_notifiers, blk);
4887ca7f0f6SKevin Wolf     if (blk->public.throttle_state) {
4897ca7f0f6SKevin Wolf         throttle_timers_attach_aio_context(
4907ca7f0f6SKevin Wolf             &blk->public.throttle_timers, bdrv_get_aio_context(bs));
4917ca7f0f6SKevin Wolf     }
4920c3c36d6SMax Reitz }
4930c3c36d6SMax Reitz 
4940c3c36d6SMax Reitz /*
495a7f53e26SMarkus Armbruster  * Attach device model @dev to @blk.
496a7f53e26SMarkus Armbruster  * Return 0 on success, -EBUSY when a device model is attached already.
497a7f53e26SMarkus Armbruster  */
498a7f53e26SMarkus Armbruster int blk_attach_dev(BlockBackend *blk, void *dev)
499a7f53e26SMarkus Armbruster /* TODO change to DeviceState *dev when all users are qdevified */
500a7f53e26SMarkus Armbruster {
501a7f53e26SMarkus Armbruster     if (blk->dev) {
502a7f53e26SMarkus Armbruster         return -EBUSY;
503a7f53e26SMarkus Armbruster     }
50484ebe375SMarkus Armbruster     blk_ref(blk);
505a7f53e26SMarkus Armbruster     blk->dev = dev;
506373340b2SMax Reitz     blk_iostatus_reset(blk);
507a7f53e26SMarkus Armbruster     return 0;
508a7f53e26SMarkus Armbruster }
509a7f53e26SMarkus Armbruster 
510a7f53e26SMarkus Armbruster /*
511a7f53e26SMarkus Armbruster  * Attach device model @dev to @blk.
512a7f53e26SMarkus Armbruster  * @blk must not have a device model attached already.
513a7f53e26SMarkus Armbruster  * TODO qdevified devices don't use this, remove when devices are qdevified
514a7f53e26SMarkus Armbruster  */
515a7f53e26SMarkus Armbruster void blk_attach_dev_nofail(BlockBackend *blk, void *dev)
516a7f53e26SMarkus Armbruster {
517a7f53e26SMarkus Armbruster     if (blk_attach_dev(blk, dev) < 0) {
518a7f53e26SMarkus Armbruster         abort();
519a7f53e26SMarkus Armbruster     }
520a7f53e26SMarkus Armbruster }
521a7f53e26SMarkus Armbruster 
522a7f53e26SMarkus Armbruster /*
523a7f53e26SMarkus Armbruster  * Detach device model @dev from @blk.
524a7f53e26SMarkus Armbruster  * @dev must be currently attached to @blk.
525a7f53e26SMarkus Armbruster  */
526a7f53e26SMarkus Armbruster void blk_detach_dev(BlockBackend *blk, void *dev)
527a7f53e26SMarkus Armbruster /* TODO change to DeviceState *dev when all users are qdevified */
528a7f53e26SMarkus Armbruster {
529a7f53e26SMarkus Armbruster     assert(blk->dev == dev);
530a7f53e26SMarkus Armbruster     blk->dev = NULL;
531a7f53e26SMarkus Armbruster     blk->dev_ops = NULL;
532a7f53e26SMarkus Armbruster     blk->dev_opaque = NULL;
53368e9ec01SMax Reitz     blk->guest_block_size = 512;
53484ebe375SMarkus Armbruster     blk_unref(blk);
535a7f53e26SMarkus Armbruster }
536a7f53e26SMarkus Armbruster 
537a7f53e26SMarkus Armbruster /*
538a7f53e26SMarkus Armbruster  * Return the device model attached to @blk if any, else null.
539a7f53e26SMarkus Armbruster  */
540a7f53e26SMarkus Armbruster void *blk_get_attached_dev(BlockBackend *blk)
541a7f53e26SMarkus Armbruster /* TODO change to return DeviceState * when all users are qdevified */
542a7f53e26SMarkus Armbruster {
543a7f53e26SMarkus Armbruster     return blk->dev;
544a7f53e26SMarkus Armbruster }
545a7f53e26SMarkus Armbruster 
546a7f53e26SMarkus Armbruster /*
547a7f53e26SMarkus Armbruster  * Set @blk's device model callbacks to @ops.
548a7f53e26SMarkus Armbruster  * @opaque is the opaque argument to pass to the callbacks.
549a7f53e26SMarkus Armbruster  * This is for use by device models.
550a7f53e26SMarkus Armbruster  */
551a7f53e26SMarkus Armbruster void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
552a7f53e26SMarkus Armbruster                      void *opaque)
553a7f53e26SMarkus Armbruster {
554a7f53e26SMarkus Armbruster     blk->dev_ops = ops;
555a7f53e26SMarkus Armbruster     blk->dev_opaque = opaque;
556a7f53e26SMarkus Armbruster }
557a7f53e26SMarkus Armbruster 
558a7f53e26SMarkus Armbruster /*
559a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of media change.
560a7f53e26SMarkus Armbruster  * If @load is true, notify of media load.
561a7f53e26SMarkus Armbruster  * Else, notify of media eject.
562a7f53e26SMarkus Armbruster  * Also send DEVICE_TRAY_MOVED events as appropriate.
563a7f53e26SMarkus Armbruster  */
564a7f53e26SMarkus Armbruster void blk_dev_change_media_cb(BlockBackend *blk, bool load)
565a7f53e26SMarkus Armbruster {
566a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->change_media_cb) {
567f1f57066SMax Reitz         bool tray_was_open, tray_is_open;
568a7f53e26SMarkus Armbruster 
569f1f57066SMax Reitz         tray_was_open = blk_dev_is_tray_open(blk);
570a7f53e26SMarkus Armbruster         blk->dev_ops->change_media_cb(blk->dev_opaque, load);
571f1f57066SMax Reitz         tray_is_open = blk_dev_is_tray_open(blk);
572f1f57066SMax Reitz 
573f1f57066SMax Reitz         if (tray_was_open != tray_is_open) {
574f1f57066SMax Reitz             qapi_event_send_device_tray_moved(blk_name(blk), tray_is_open,
575f1f57066SMax Reitz                                               &error_abort);
576a7f53e26SMarkus Armbruster         }
577a7f53e26SMarkus Armbruster     }
578a7f53e26SMarkus Armbruster }
579a7f53e26SMarkus Armbruster 
5805c8cab48SKevin Wolf static void blk_root_change_media(BdrvChild *child, bool load)
5815c8cab48SKevin Wolf {
5825c8cab48SKevin Wolf     blk_dev_change_media_cb(child->opaque, load);
5835c8cab48SKevin Wolf }
5845c8cab48SKevin Wolf 
585a7f53e26SMarkus Armbruster /*
586a7f53e26SMarkus Armbruster  * Does @blk's attached device model have removable media?
587a7f53e26SMarkus Armbruster  * %true if no device model is attached.
588a7f53e26SMarkus Armbruster  */
589a7f53e26SMarkus Armbruster bool blk_dev_has_removable_media(BlockBackend *blk)
590a7f53e26SMarkus Armbruster {
591a7f53e26SMarkus Armbruster     return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
592a7f53e26SMarkus Armbruster }
593a7f53e26SMarkus Armbruster 
594a7f53e26SMarkus Armbruster /*
5958f3a73bcSMax Reitz  * Does @blk's attached device model have a tray?
5968f3a73bcSMax Reitz  */
5978f3a73bcSMax Reitz bool blk_dev_has_tray(BlockBackend *blk)
5988f3a73bcSMax Reitz {
5998f3a73bcSMax Reitz     return blk->dev_ops && blk->dev_ops->is_tray_open;
6008f3a73bcSMax Reitz }
6018f3a73bcSMax Reitz 
6028f3a73bcSMax Reitz /*
603a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a media eject request.
604a7f53e26SMarkus Armbruster  * If @force is true, the medium is about to be yanked out forcefully.
605a7f53e26SMarkus Armbruster  */
606a7f53e26SMarkus Armbruster void blk_dev_eject_request(BlockBackend *blk, bool force)
607a7f53e26SMarkus Armbruster {
608a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->eject_request_cb) {
609a7f53e26SMarkus Armbruster         blk->dev_ops->eject_request_cb(blk->dev_opaque, force);
610a7f53e26SMarkus Armbruster     }
611a7f53e26SMarkus Armbruster }
612a7f53e26SMarkus Armbruster 
613a7f53e26SMarkus Armbruster /*
614a7f53e26SMarkus Armbruster  * Does @blk's attached device model have a tray, and is it open?
615a7f53e26SMarkus Armbruster  */
616a7f53e26SMarkus Armbruster bool blk_dev_is_tray_open(BlockBackend *blk)
617a7f53e26SMarkus Armbruster {
6188f3a73bcSMax Reitz     if (blk_dev_has_tray(blk)) {
619a7f53e26SMarkus Armbruster         return blk->dev_ops->is_tray_open(blk->dev_opaque);
620a7f53e26SMarkus Armbruster     }
621a7f53e26SMarkus Armbruster     return false;
622a7f53e26SMarkus Armbruster }
623a7f53e26SMarkus Armbruster 
624a7f53e26SMarkus Armbruster /*
625a7f53e26SMarkus Armbruster  * Does @blk's attached device model have the medium locked?
626a7f53e26SMarkus Armbruster  * %false if the device model has no such lock.
627a7f53e26SMarkus Armbruster  */
628a7f53e26SMarkus Armbruster bool blk_dev_is_medium_locked(BlockBackend *blk)
629a7f53e26SMarkus Armbruster {
630a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->is_medium_locked) {
631a7f53e26SMarkus Armbruster         return blk->dev_ops->is_medium_locked(blk->dev_opaque);
632a7f53e26SMarkus Armbruster     }
633a7f53e26SMarkus Armbruster     return false;
634a7f53e26SMarkus Armbruster }
635a7f53e26SMarkus Armbruster 
636a7f53e26SMarkus Armbruster /*
637a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a backend size change.
638a7f53e26SMarkus Armbruster  */
6395c8cab48SKevin Wolf static void blk_root_resize(BdrvChild *child)
640a7f53e26SMarkus Armbruster {
6415c8cab48SKevin Wolf     BlockBackend *blk = child->opaque;
6425c8cab48SKevin Wolf 
643a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->resize_cb) {
644a7f53e26SMarkus Armbruster         blk->dev_ops->resize_cb(blk->dev_opaque);
645a7f53e26SMarkus Armbruster     }
646a7f53e26SMarkus Armbruster }
647a7f53e26SMarkus Armbruster 
6484be74634SMarkus Armbruster void blk_iostatus_enable(BlockBackend *blk)
6494be74634SMarkus Armbruster {
650373340b2SMax Reitz     blk->iostatus_enabled = true;
651373340b2SMax Reitz     blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
652373340b2SMax Reitz }
653373340b2SMax Reitz 
654373340b2SMax Reitz /* The I/O status is only enabled if the drive explicitly
655373340b2SMax Reitz  * enables it _and_ the VM is configured to stop on errors */
656373340b2SMax Reitz bool blk_iostatus_is_enabled(const BlockBackend *blk)
657373340b2SMax Reitz {
658373340b2SMax Reitz     return (blk->iostatus_enabled &&
659373340b2SMax Reitz            (blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
660373340b2SMax Reitz             blk->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
661373340b2SMax Reitz             blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
662373340b2SMax Reitz }
663373340b2SMax Reitz 
664373340b2SMax Reitz BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
665373340b2SMax Reitz {
666373340b2SMax Reitz     return blk->iostatus;
667373340b2SMax Reitz }
668373340b2SMax Reitz 
669373340b2SMax Reitz void blk_iostatus_disable(BlockBackend *blk)
670373340b2SMax Reitz {
671373340b2SMax Reitz     blk->iostatus_enabled = false;
672373340b2SMax Reitz }
673373340b2SMax Reitz 
674373340b2SMax Reitz void blk_iostatus_reset(BlockBackend *blk)
675373340b2SMax Reitz {
676373340b2SMax Reitz     if (blk_iostatus_is_enabled(blk)) {
677f21d96d0SKevin Wolf         BlockDriverState *bs = blk_bs(blk);
678373340b2SMax Reitz         blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
679f21d96d0SKevin Wolf         if (bs && bs->job) {
680f21d96d0SKevin Wolf             block_job_iostatus_reset(bs->job);
681373340b2SMax Reitz         }
682373340b2SMax Reitz     }
683373340b2SMax Reitz }
684373340b2SMax Reitz 
685373340b2SMax Reitz void blk_iostatus_set_err(BlockBackend *blk, int error)
686373340b2SMax Reitz {
687373340b2SMax Reitz     assert(blk_iostatus_is_enabled(blk));
688373340b2SMax Reitz     if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
689373340b2SMax Reitz         blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
690373340b2SMax Reitz                                           BLOCK_DEVICE_IO_STATUS_FAILED;
691373340b2SMax Reitz     }
6924be74634SMarkus Armbruster }
6934be74634SMarkus Armbruster 
694c10c9d96SKevin Wolf void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow)
695c10c9d96SKevin Wolf {
696c10c9d96SKevin Wolf     blk->allow_write_beyond_eof = allow;
697c10c9d96SKevin Wolf }
698c10c9d96SKevin Wolf 
699e7f7d676SMax Reitz static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
700e7f7d676SMax Reitz                                   size_t size)
701e7f7d676SMax Reitz {
702e7f7d676SMax Reitz     int64_t len;
703e7f7d676SMax Reitz 
704e7f7d676SMax Reitz     if (size > INT_MAX) {
705e7f7d676SMax Reitz         return -EIO;
706e7f7d676SMax Reitz     }
707e7f7d676SMax Reitz 
708c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
709e7f7d676SMax Reitz         return -ENOMEDIUM;
710e7f7d676SMax Reitz     }
711e7f7d676SMax Reitz 
712c10c9d96SKevin Wolf     if (offset < 0) {
713c10c9d96SKevin Wolf         return -EIO;
714c10c9d96SKevin Wolf     }
715c10c9d96SKevin Wolf 
716c10c9d96SKevin Wolf     if (!blk->allow_write_beyond_eof) {
717e7f7d676SMax Reitz         len = blk_getlength(blk);
718e7f7d676SMax Reitz         if (len < 0) {
719e7f7d676SMax Reitz             return len;
720e7f7d676SMax Reitz         }
721e7f7d676SMax Reitz 
722e7f7d676SMax Reitz         if (offset > len || len - offset < size) {
723e7f7d676SMax Reitz             return -EIO;
724e7f7d676SMax Reitz         }
725c10c9d96SKevin Wolf     }
726e7f7d676SMax Reitz 
727e7f7d676SMax Reitz     return 0;
728e7f7d676SMax Reitz }
729e7f7d676SMax Reitz 
730e7f7d676SMax Reitz static int blk_check_request(BlockBackend *blk, int64_t sector_num,
731e7f7d676SMax Reitz                              int nb_sectors)
732e7f7d676SMax Reitz {
733e7f7d676SMax Reitz     if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
734e7f7d676SMax Reitz         return -EIO;
735e7f7d676SMax Reitz     }
736e7f7d676SMax Reitz 
737e7f7d676SMax Reitz     if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
738e7f7d676SMax Reitz         return -EIO;
739e7f7d676SMax Reitz     }
740e7f7d676SMax Reitz 
741e7f7d676SMax Reitz     return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
742e7f7d676SMax Reitz                                   nb_sectors * BDRV_SECTOR_SIZE);
743e7f7d676SMax Reitz }
744e7f7d676SMax Reitz 
7451e98fefdSKevin Wolf int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
7461bf1cbc9SKevin Wolf                                unsigned int bytes, QEMUIOVector *qiov,
7471bf1cbc9SKevin Wolf                                BdrvRequestFlags flags)
7484be74634SMarkus Armbruster {
7491e98fefdSKevin Wolf     int ret;
7501e98fefdSKevin Wolf 
7511e98fefdSKevin Wolf     trace_blk_co_preadv(blk, blk_bs(blk), offset, bytes, flags);
7521e98fefdSKevin Wolf 
7531e98fefdSKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
754e7f7d676SMax Reitz     if (ret < 0) {
755e7f7d676SMax Reitz         return ret;
756e7f7d676SMax Reitz     }
757e7f7d676SMax Reitz 
758441565b2SKevin Wolf     /* throttling disk I/O */
759441565b2SKevin Wolf     if (blk->public.throttle_state) {
760441565b2SKevin Wolf         throttle_group_co_io_limits_intercept(blk, bytes, false);
761441565b2SKevin Wolf     }
762441565b2SKevin Wolf 
763*a03ef88fSKevin Wolf     return bdrv_co_preadv(blk->root, offset, bytes, qiov, flags);
7641bf1cbc9SKevin Wolf }
7651bf1cbc9SKevin Wolf 
7661e98fefdSKevin Wolf int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
767a8823a3bSKevin Wolf                                 unsigned int bytes, QEMUIOVector *qiov,
768a8823a3bSKevin Wolf                                 BdrvRequestFlags flags)
769a8823a3bSKevin Wolf {
770bfd18d1eSKevin Wolf     int ret;
771bfd18d1eSKevin Wolf 
7721e98fefdSKevin Wolf     trace_blk_co_pwritev(blk, blk_bs(blk), offset, bytes, flags);
7731e98fefdSKevin Wolf 
774bfd18d1eSKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
775a8823a3bSKevin Wolf     if (ret < 0) {
776a8823a3bSKevin Wolf         return ret;
777a8823a3bSKevin Wolf     }
778a8823a3bSKevin Wolf 
779441565b2SKevin Wolf     /* throttling disk I/O */
780441565b2SKevin Wolf     if (blk->public.throttle_state) {
781441565b2SKevin Wolf         throttle_group_co_io_limits_intercept(blk, bytes, true);
782441565b2SKevin Wolf     }
783441565b2SKevin Wolf 
784bfd18d1eSKevin Wolf     if (!blk->enable_write_cache) {
785bfd18d1eSKevin Wolf         flags |= BDRV_REQ_FUA;
786bfd18d1eSKevin Wolf     }
787bfd18d1eSKevin Wolf 
788*a03ef88fSKevin Wolf     return bdrv_co_pwritev(blk->root, offset, bytes, qiov, flags);
789a8823a3bSKevin Wolf }
790a8823a3bSKevin Wolf 
7911bf1cbc9SKevin Wolf typedef struct BlkRwCo {
7921bf1cbc9SKevin Wolf     BlockBackend *blk;
7931bf1cbc9SKevin Wolf     int64_t offset;
7941bf1cbc9SKevin Wolf     QEMUIOVector *qiov;
7951bf1cbc9SKevin Wolf     int ret;
7961bf1cbc9SKevin Wolf     BdrvRequestFlags flags;
7971bf1cbc9SKevin Wolf } BlkRwCo;
7981bf1cbc9SKevin Wolf 
7991bf1cbc9SKevin Wolf static void blk_read_entry(void *opaque)
8001bf1cbc9SKevin Wolf {
8011bf1cbc9SKevin Wolf     BlkRwCo *rwco = opaque;
8021bf1cbc9SKevin Wolf 
8031bf1cbc9SKevin Wolf     rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, rwco->qiov->size,
8041bf1cbc9SKevin Wolf                               rwco->qiov, rwco->flags);
8051bf1cbc9SKevin Wolf }
8061bf1cbc9SKevin Wolf 
807a8823a3bSKevin Wolf static void blk_write_entry(void *opaque)
808a8823a3bSKevin Wolf {
809a8823a3bSKevin Wolf     BlkRwCo *rwco = opaque;
810a8823a3bSKevin Wolf 
811a8823a3bSKevin Wolf     rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, rwco->qiov->size,
812a8823a3bSKevin Wolf                                rwco->qiov, rwco->flags);
813a8823a3bSKevin Wolf }
814a8823a3bSKevin Wolf 
815a55d3fbaSKevin Wolf static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
816a55d3fbaSKevin Wolf                    int64_t bytes, CoroutineEntry co_entry,
817fc1453cdSKevin Wolf                    BdrvRequestFlags flags)
8181bf1cbc9SKevin Wolf {
8191bf1cbc9SKevin Wolf     AioContext *aio_context;
8201bf1cbc9SKevin Wolf     QEMUIOVector qiov;
8211bf1cbc9SKevin Wolf     struct iovec iov;
8221bf1cbc9SKevin Wolf     Coroutine *co;
8231bf1cbc9SKevin Wolf     BlkRwCo rwco;
8241bf1cbc9SKevin Wolf 
8251bf1cbc9SKevin Wolf     iov = (struct iovec) {
8261bf1cbc9SKevin Wolf         .iov_base = buf,
827a55d3fbaSKevin Wolf         .iov_len = bytes,
8281bf1cbc9SKevin Wolf     };
8291bf1cbc9SKevin Wolf     qemu_iovec_init_external(&qiov, &iov, 1);
8301bf1cbc9SKevin Wolf 
8311bf1cbc9SKevin Wolf     rwco = (BlkRwCo) {
8321bf1cbc9SKevin Wolf         .blk    = blk,
833a55d3fbaSKevin Wolf         .offset = offset,
8341bf1cbc9SKevin Wolf         .qiov   = &qiov,
835fc1453cdSKevin Wolf         .flags  = flags,
8361bf1cbc9SKevin Wolf         .ret    = NOT_DONE,
8371bf1cbc9SKevin Wolf     };
8381bf1cbc9SKevin Wolf 
839a8823a3bSKevin Wolf     co = qemu_coroutine_create(co_entry);
8401bf1cbc9SKevin Wolf     qemu_coroutine_enter(co, &rwco);
8411bf1cbc9SKevin Wolf 
8421bf1cbc9SKevin Wolf     aio_context = blk_get_aio_context(blk);
8431bf1cbc9SKevin Wolf     while (rwco.ret == NOT_DONE) {
8441bf1cbc9SKevin Wolf         aio_poll(aio_context, true);
8451bf1cbc9SKevin Wolf     }
8461bf1cbc9SKevin Wolf 
8471bf1cbc9SKevin Wolf     return rwco.ret;
8484be74634SMarkus Armbruster }
8494be74634SMarkus Armbruster 
850b7d17f9fSEric Blake int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf,
851b7d17f9fSEric Blake                           int count)
8524be74634SMarkus Armbruster {
8535bd51196SKevin Wolf     int ret;
8545bd51196SKevin Wolf 
855b7d17f9fSEric Blake     ret = blk_check_byte_request(blk, offset, count);
856e7f7d676SMax Reitz     if (ret < 0) {
857e7f7d676SMax Reitz         return ret;
858e7f7d676SMax Reitz     }
859e7f7d676SMax Reitz 
860c2066af0SKevin Wolf     blk_root_drained_begin(blk->root);
861b7d17f9fSEric Blake     ret = blk_pread(blk, offset, buf, count);
862c2066af0SKevin Wolf     blk_root_drained_end(blk->root);
8635bd51196SKevin Wolf     return ret;
8644be74634SMarkus Armbruster }
8654be74634SMarkus Armbruster 
866d004bd52SEric Blake int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
867983a1600SEric Blake                       int count, BdrvRequestFlags flags)
8680df89e8eSKevin Wolf {
869983a1600SEric Blake     return blk_prw(blk, offset, NULL, count, blk_write_entry,
87016aaf975SKevin Wolf                    flags | BDRV_REQ_ZERO_WRITE);
8710df89e8eSKevin Wolf }
8720df89e8eSKevin Wolf 
873720ff280SKevin Wolf int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
874720ff280SKevin Wolf {
875720ff280SKevin Wolf     return bdrv_make_zero(blk->root, flags);
876720ff280SKevin Wolf }
877720ff280SKevin Wolf 
878e7f7d676SMax Reitz static void error_callback_bh(void *opaque)
879e7f7d676SMax Reitz {
880e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb = opaque;
881e7f7d676SMax Reitz     qemu_bh_delete(acb->bh);
882e7f7d676SMax Reitz     acb->common.cb(acb->common.opaque, acb->ret);
883e7f7d676SMax Reitz     qemu_aio_unref(acb);
884e7f7d676SMax Reitz }
885e7f7d676SMax Reitz 
886ca78ecfaSPeter Lieven BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
887ca78ecfaSPeter Lieven                                   BlockCompletionFunc *cb,
888e7f7d676SMax Reitz                                   void *opaque, int ret)
889e7f7d676SMax Reitz {
890e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb;
891e7f7d676SMax Reitz     QEMUBH *bh;
892e7f7d676SMax Reitz 
893e7f7d676SMax Reitz     acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
8944981bdecSMax Reitz     acb->blk = blk;
895e7f7d676SMax Reitz     acb->ret = ret;
896e7f7d676SMax Reitz 
897e7f7d676SMax Reitz     bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb);
898e7f7d676SMax Reitz     acb->bh = bh;
899e7f7d676SMax Reitz     qemu_bh_schedule(bh);
900e7f7d676SMax Reitz 
901e7f7d676SMax Reitz     return &acb->common;
902e7f7d676SMax Reitz }
903e7f7d676SMax Reitz 
90457d6a428SKevin Wolf typedef struct BlkAioEmAIOCB {
90557d6a428SKevin Wolf     BlockAIOCB common;
90657d6a428SKevin Wolf     BlkRwCo rwco;
9077fa84cd8SKevin Wolf     int bytes;
90857d6a428SKevin Wolf     bool has_returned;
90957d6a428SKevin Wolf     QEMUBH* bh;
91057d6a428SKevin Wolf } BlkAioEmAIOCB;
91157d6a428SKevin Wolf 
91257d6a428SKevin Wolf static const AIOCBInfo blk_aio_em_aiocb_info = {
91357d6a428SKevin Wolf     .aiocb_size         = sizeof(BlkAioEmAIOCB),
91457d6a428SKevin Wolf };
91557d6a428SKevin Wolf 
91657d6a428SKevin Wolf static void blk_aio_complete(BlkAioEmAIOCB *acb)
91757d6a428SKevin Wolf {
91857d6a428SKevin Wolf     if (acb->bh) {
91957d6a428SKevin Wolf         assert(acb->has_returned);
92057d6a428SKevin Wolf         qemu_bh_delete(acb->bh);
92157d6a428SKevin Wolf     }
92257d6a428SKevin Wolf     if (acb->has_returned) {
92357d6a428SKevin Wolf         acb->common.cb(acb->common.opaque, acb->rwco.ret);
92457d6a428SKevin Wolf         qemu_aio_unref(acb);
92557d6a428SKevin Wolf     }
92657d6a428SKevin Wolf }
92757d6a428SKevin Wolf 
92857d6a428SKevin Wolf static void blk_aio_complete_bh(void *opaque)
92957d6a428SKevin Wolf {
93057d6a428SKevin Wolf     blk_aio_complete(opaque);
93157d6a428SKevin Wolf }
93257d6a428SKevin Wolf 
9337fa84cd8SKevin Wolf static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
93457d6a428SKevin Wolf                                 QEMUIOVector *qiov, CoroutineEntry co_entry,
93557d6a428SKevin Wolf                                 BdrvRequestFlags flags,
93657d6a428SKevin Wolf                                 BlockCompletionFunc *cb, void *opaque)
93757d6a428SKevin Wolf {
93857d6a428SKevin Wolf     BlkAioEmAIOCB *acb;
93957d6a428SKevin Wolf     Coroutine *co;
94057d6a428SKevin Wolf 
94157d6a428SKevin Wolf     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
94257d6a428SKevin Wolf     acb->rwco = (BlkRwCo) {
94357d6a428SKevin Wolf         .blk    = blk,
94457d6a428SKevin Wolf         .offset = offset,
94557d6a428SKevin Wolf         .qiov   = qiov,
94657d6a428SKevin Wolf         .flags  = flags,
94757d6a428SKevin Wolf         .ret    = NOT_DONE,
94857d6a428SKevin Wolf     };
9497fa84cd8SKevin Wolf     acb->bytes = bytes;
95057d6a428SKevin Wolf     acb->bh = NULL;
95157d6a428SKevin Wolf     acb->has_returned = false;
95257d6a428SKevin Wolf 
95357d6a428SKevin Wolf     co = qemu_coroutine_create(co_entry);
95457d6a428SKevin Wolf     qemu_coroutine_enter(co, acb);
95557d6a428SKevin Wolf 
95657d6a428SKevin Wolf     acb->has_returned = true;
95757d6a428SKevin Wolf     if (acb->rwco.ret != NOT_DONE) {
95857d6a428SKevin Wolf         acb->bh = aio_bh_new(blk_get_aio_context(blk), blk_aio_complete_bh, acb);
95957d6a428SKevin Wolf         qemu_bh_schedule(acb->bh);
96057d6a428SKevin Wolf     }
96157d6a428SKevin Wolf 
96257d6a428SKevin Wolf     return &acb->common;
96357d6a428SKevin Wolf }
96457d6a428SKevin Wolf 
96557d6a428SKevin Wolf static void blk_aio_read_entry(void *opaque)
96657d6a428SKevin Wolf {
96757d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
96857d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
96957d6a428SKevin Wolf 
9707fa84cd8SKevin Wolf     assert(rwco->qiov->size == acb->bytes);
9717fa84cd8SKevin Wolf     rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, acb->bytes,
97257d6a428SKevin Wolf                               rwco->qiov, rwco->flags);
97357d6a428SKevin Wolf     blk_aio_complete(acb);
97457d6a428SKevin Wolf }
97557d6a428SKevin Wolf 
97657d6a428SKevin Wolf static void blk_aio_write_entry(void *opaque)
97757d6a428SKevin Wolf {
97857d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
97957d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
98057d6a428SKevin Wolf 
9817fa84cd8SKevin Wolf     assert(!rwco->qiov || rwco->qiov->size == acb->bytes);
9827fa84cd8SKevin Wolf     rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, acb->bytes,
98357d6a428SKevin Wolf                                rwco->qiov, rwco->flags);
98457d6a428SKevin Wolf     blk_aio_complete(acb);
98557d6a428SKevin Wolf }
98657d6a428SKevin Wolf 
987d004bd52SEric Blake BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
988983a1600SEric Blake                                   int count, BdrvRequestFlags flags,
9894be74634SMarkus Armbruster                                   BlockCompletionFunc *cb, void *opaque)
9904be74634SMarkus Armbruster {
991983a1600SEric Blake     return blk_aio_prwv(blk, offset, count, NULL, blk_aio_write_entry,
992983a1600SEric Blake                         flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
9934be74634SMarkus Armbruster }
9944be74634SMarkus Armbruster 
9954be74634SMarkus Armbruster int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
9964be74634SMarkus Armbruster {
997a55d3fbaSKevin Wolf     int ret = blk_prw(blk, offset, buf, count, blk_read_entry, 0);
998e7f7d676SMax Reitz     if (ret < 0) {
999e7f7d676SMax Reitz         return ret;
1000e7f7d676SMax Reitz     }
1001a55d3fbaSKevin Wolf     return count;
10024be74634SMarkus Armbruster }
10034be74634SMarkus Armbruster 
10048341f00dSEric Blake int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count,
10058341f00dSEric Blake                BdrvRequestFlags flags)
10064be74634SMarkus Armbruster {
10078341f00dSEric Blake     int ret = blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
10088341f00dSEric Blake                       flags);
1009e7f7d676SMax Reitz     if (ret < 0) {
1010e7f7d676SMax Reitz         return ret;
1011e7f7d676SMax Reitz     }
1012a55d3fbaSKevin Wolf     return count;
10134be74634SMarkus Armbruster }
10144be74634SMarkus Armbruster 
10154be74634SMarkus Armbruster int64_t blk_getlength(BlockBackend *blk)
10164be74634SMarkus Armbruster {
1017c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1018c09ba36cSMax Reitz         return -ENOMEDIUM;
1019c09ba36cSMax Reitz     }
1020c09ba36cSMax Reitz 
1021f21d96d0SKevin Wolf     return bdrv_getlength(blk_bs(blk));
10224be74634SMarkus Armbruster }
10234be74634SMarkus Armbruster 
10244be74634SMarkus Armbruster void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
10254be74634SMarkus Armbruster {
1026f21d96d0SKevin Wolf     if (!blk_bs(blk)) {
1027a46fc9c9SMax Reitz         *nb_sectors_ptr = 0;
1028a46fc9c9SMax Reitz     } else {
1029f21d96d0SKevin Wolf         bdrv_get_geometry(blk_bs(blk), nb_sectors_ptr);
10304be74634SMarkus Armbruster     }
1031a46fc9c9SMax Reitz }
10324be74634SMarkus Armbruster 
10331ef01253SMax Reitz int64_t blk_nb_sectors(BlockBackend *blk)
10341ef01253SMax Reitz {
1035c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1036c09ba36cSMax Reitz         return -ENOMEDIUM;
1037c09ba36cSMax Reitz     }
1038c09ba36cSMax Reitz 
1039f21d96d0SKevin Wolf     return bdrv_nb_sectors(blk_bs(blk));
10401ef01253SMax Reitz }
10411ef01253SMax Reitz 
104260cb2fa7SEric Blake BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
104360cb2fa7SEric Blake                            QEMUIOVector *qiov, BdrvRequestFlags flags,
104460cb2fa7SEric Blake                            BlockCompletionFunc *cb, void *opaque)
104560cb2fa7SEric Blake {
104660cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
104760cb2fa7SEric Blake                         blk_aio_read_entry, flags, cb, opaque);
104860cb2fa7SEric Blake }
104960cb2fa7SEric Blake 
105060cb2fa7SEric Blake BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
105160cb2fa7SEric Blake                             QEMUIOVector *qiov, BdrvRequestFlags flags,
105260cb2fa7SEric Blake                             BlockCompletionFunc *cb, void *opaque)
105360cb2fa7SEric Blake {
105460cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
105560cb2fa7SEric Blake                         blk_aio_write_entry, flags, cb, opaque);
105660cb2fa7SEric Blake }
105760cb2fa7SEric Blake 
10584be74634SMarkus Armbruster BlockAIOCB *blk_aio_flush(BlockBackend *blk,
10594be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
10604be74634SMarkus Armbruster {
1061c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1062ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
1063c09ba36cSMax Reitz     }
1064c09ba36cSMax Reitz 
1065f21d96d0SKevin Wolf     return bdrv_aio_flush(blk_bs(blk), cb, opaque);
10664be74634SMarkus Armbruster }
10674be74634SMarkus Armbruster 
10684be74634SMarkus Armbruster BlockAIOCB *blk_aio_discard(BlockBackend *blk,
10694be74634SMarkus Armbruster                             int64_t sector_num, int nb_sectors,
10704be74634SMarkus Armbruster                             BlockCompletionFunc *cb, void *opaque)
10714be74634SMarkus Armbruster {
1072e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1073e7f7d676SMax Reitz     if (ret < 0) {
1074ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, ret);
1075e7f7d676SMax Reitz     }
1076e7f7d676SMax Reitz 
1077f21d96d0SKevin Wolf     return bdrv_aio_discard(blk_bs(blk), sector_num, nb_sectors, cb, opaque);
10784be74634SMarkus Armbruster }
10794be74634SMarkus Armbruster 
10804be74634SMarkus Armbruster void blk_aio_cancel(BlockAIOCB *acb)
10814be74634SMarkus Armbruster {
10824be74634SMarkus Armbruster     bdrv_aio_cancel(acb);
10834be74634SMarkus Armbruster }
10844be74634SMarkus Armbruster 
10854be74634SMarkus Armbruster void blk_aio_cancel_async(BlockAIOCB *acb)
10864be74634SMarkus Armbruster {
10874be74634SMarkus Armbruster     bdrv_aio_cancel_async(acb);
10884be74634SMarkus Armbruster }
10894be74634SMarkus Armbruster 
10904be74634SMarkus Armbruster int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
10914be74634SMarkus Armbruster {
1092c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1093c09ba36cSMax Reitz         return -ENOMEDIUM;
1094c09ba36cSMax Reitz     }
1095c09ba36cSMax Reitz 
1096f21d96d0SKevin Wolf     return bdrv_ioctl(blk_bs(blk), req, buf);
10974be74634SMarkus Armbruster }
10984be74634SMarkus Armbruster 
10994be74634SMarkus Armbruster BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
11004be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
11014be74634SMarkus Armbruster {
1102c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1103ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
1104c09ba36cSMax Reitz     }
1105c09ba36cSMax Reitz 
1106f21d96d0SKevin Wolf     return bdrv_aio_ioctl(blk_bs(blk), req, buf, cb, opaque);
11074be74634SMarkus Armbruster }
11084be74634SMarkus Armbruster 
11092bb0dce7SMax Reitz int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
11102bb0dce7SMax Reitz {
1111e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1112e7f7d676SMax Reitz     if (ret < 0) {
1113e7f7d676SMax Reitz         return ret;
1114e7f7d676SMax Reitz     }
1115e7f7d676SMax Reitz 
1116f21d96d0SKevin Wolf     return bdrv_co_discard(blk_bs(blk), sector_num, nb_sectors);
11172bb0dce7SMax Reitz }
11182bb0dce7SMax Reitz 
11192bb0dce7SMax Reitz int blk_co_flush(BlockBackend *blk)
11202bb0dce7SMax Reitz {
1121c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1122c09ba36cSMax Reitz         return -ENOMEDIUM;
1123c09ba36cSMax Reitz     }
1124c09ba36cSMax Reitz 
1125f21d96d0SKevin Wolf     return bdrv_co_flush(blk_bs(blk));
11262bb0dce7SMax Reitz }
11272bb0dce7SMax Reitz 
11284be74634SMarkus Armbruster int blk_flush(BlockBackend *blk)
11294be74634SMarkus Armbruster {
1130c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1131c09ba36cSMax Reitz         return -ENOMEDIUM;
1132c09ba36cSMax Reitz     }
1133c09ba36cSMax Reitz 
1134f21d96d0SKevin Wolf     return bdrv_flush(blk_bs(blk));
11354be74634SMarkus Armbruster }
11364be74634SMarkus Armbruster 
113797b0385aSAlexander Yarygin void blk_drain(BlockBackend *blk)
113897b0385aSAlexander Yarygin {
1139f21d96d0SKevin Wolf     if (blk_bs(blk)) {
1140f21d96d0SKevin Wolf         bdrv_drain(blk_bs(blk));
114197b0385aSAlexander Yarygin     }
1142a46fc9c9SMax Reitz }
114397b0385aSAlexander Yarygin 
11444be74634SMarkus Armbruster void blk_drain_all(void)
11454be74634SMarkus Armbruster {
11464be74634SMarkus Armbruster     bdrv_drain_all();
11474be74634SMarkus Armbruster }
11484be74634SMarkus Armbruster 
1149373340b2SMax Reitz void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
1150373340b2SMax Reitz                       BlockdevOnError on_write_error)
1151373340b2SMax Reitz {
1152373340b2SMax Reitz     blk->on_read_error = on_read_error;
1153373340b2SMax Reitz     blk->on_write_error = on_write_error;
1154373340b2SMax Reitz }
1155373340b2SMax Reitz 
11564be74634SMarkus Armbruster BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
11574be74634SMarkus Armbruster {
1158373340b2SMax Reitz     return is_read ? blk->on_read_error : blk->on_write_error;
11594be74634SMarkus Armbruster }
11604be74634SMarkus Armbruster 
11614be74634SMarkus Armbruster BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
11624be74634SMarkus Armbruster                                       int error)
11634be74634SMarkus Armbruster {
1164373340b2SMax Reitz     BlockdevOnError on_err = blk_get_on_error(blk, is_read);
1165373340b2SMax Reitz 
1166373340b2SMax Reitz     switch (on_err) {
1167373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_ENOSPC:
1168373340b2SMax Reitz         return (error == ENOSPC) ?
1169373340b2SMax Reitz                BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
1170373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_STOP:
1171373340b2SMax Reitz         return BLOCK_ERROR_ACTION_STOP;
1172373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_REPORT:
1173373340b2SMax Reitz         return BLOCK_ERROR_ACTION_REPORT;
1174373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_IGNORE:
1175373340b2SMax Reitz         return BLOCK_ERROR_ACTION_IGNORE;
1176373340b2SMax Reitz     default:
1177373340b2SMax Reitz         abort();
1178373340b2SMax Reitz     }
11794be74634SMarkus Armbruster }
11804be74634SMarkus Armbruster 
1181373340b2SMax Reitz static void send_qmp_error_event(BlockBackend *blk,
1182373340b2SMax Reitz                                  BlockErrorAction action,
1183373340b2SMax Reitz                                  bool is_read, int error)
1184373340b2SMax Reitz {
1185373340b2SMax Reitz     IoOperationType optype;
1186373340b2SMax Reitz 
1187373340b2SMax Reitz     optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
1188373340b2SMax Reitz     qapi_event_send_block_io_error(blk_name(blk), optype, action,
1189373340b2SMax Reitz                                    blk_iostatus_is_enabled(blk),
1190373340b2SMax Reitz                                    error == ENOSPC, strerror(error),
1191373340b2SMax Reitz                                    &error_abort);
1192373340b2SMax Reitz }
1193373340b2SMax Reitz 
1194373340b2SMax Reitz /* This is done by device models because, while the block layer knows
1195373340b2SMax Reitz  * about the error, it does not know whether an operation comes from
1196373340b2SMax Reitz  * the device or the block layer (from a job, for example).
1197373340b2SMax Reitz  */
11984be74634SMarkus Armbruster void blk_error_action(BlockBackend *blk, BlockErrorAction action,
11994be74634SMarkus Armbruster                       bool is_read, int error)
12004be74634SMarkus Armbruster {
1201373340b2SMax Reitz     assert(error >= 0);
1202373340b2SMax Reitz 
1203373340b2SMax Reitz     if (action == BLOCK_ERROR_ACTION_STOP) {
1204373340b2SMax Reitz         /* First set the iostatus, so that "info block" returns an iostatus
1205373340b2SMax Reitz          * that matches the events raised so far (an additional error iostatus
1206373340b2SMax Reitz          * is fine, but not a lost one).
1207373340b2SMax Reitz          */
1208373340b2SMax Reitz         blk_iostatus_set_err(blk, error);
1209373340b2SMax Reitz 
1210373340b2SMax Reitz         /* Then raise the request to stop the VM and the event.
1211373340b2SMax Reitz          * qemu_system_vmstop_request_prepare has two effects.  First,
1212373340b2SMax Reitz          * it ensures that the STOP event always comes after the
1213373340b2SMax Reitz          * BLOCK_IO_ERROR event.  Second, it ensures that even if management
1214373340b2SMax Reitz          * can observe the STOP event and do a "cont" before the STOP
1215373340b2SMax Reitz          * event is issued, the VM will not stop.  In this case, vm_start()
1216373340b2SMax Reitz          * also ensures that the STOP/RESUME pair of events is emitted.
1217373340b2SMax Reitz          */
1218373340b2SMax Reitz         qemu_system_vmstop_request_prepare();
1219373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
1220373340b2SMax Reitz         qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
1221373340b2SMax Reitz     } else {
1222373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
1223373340b2SMax Reitz     }
12244be74634SMarkus Armbruster }
12254be74634SMarkus Armbruster 
12264be74634SMarkus Armbruster int blk_is_read_only(BlockBackend *blk)
12274be74634SMarkus Armbruster {
1228f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1229f21d96d0SKevin Wolf 
1230f21d96d0SKevin Wolf     if (bs) {
1231f21d96d0SKevin Wolf         return bdrv_is_read_only(bs);
1232061959e8SMax Reitz     } else {
1233061959e8SMax Reitz         return blk->root_state.read_only;
1234061959e8SMax Reitz     }
12354be74634SMarkus Armbruster }
12364be74634SMarkus Armbruster 
12374be74634SMarkus Armbruster int blk_is_sg(BlockBackend *blk)
12384be74634SMarkus Armbruster {
1239f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1240f21d96d0SKevin Wolf 
1241f21d96d0SKevin Wolf     if (!bs) {
1242a46fc9c9SMax Reitz         return 0;
1243a46fc9c9SMax Reitz     }
1244a46fc9c9SMax Reitz 
1245f21d96d0SKevin Wolf     return bdrv_is_sg(bs);
12464be74634SMarkus Armbruster }
12474be74634SMarkus Armbruster 
12484be74634SMarkus Armbruster int blk_enable_write_cache(BlockBackend *blk)
12494be74634SMarkus Armbruster {
1250bfd18d1eSKevin Wolf     return blk->enable_write_cache;
12514be74634SMarkus Armbruster }
12524be74634SMarkus Armbruster 
12534be74634SMarkus Armbruster void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
12544be74634SMarkus Armbruster {
1255bfd18d1eSKevin Wolf     blk->enable_write_cache = wce;
12564be74634SMarkus Armbruster }
12574be74634SMarkus Armbruster 
12582bb0dce7SMax Reitz void blk_invalidate_cache(BlockBackend *blk, Error **errp)
12592bb0dce7SMax Reitz {
1260f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1261f21d96d0SKevin Wolf 
1262f21d96d0SKevin Wolf     if (!bs) {
1263c09ba36cSMax Reitz         error_setg(errp, "Device '%s' has no medium", blk->name);
1264c09ba36cSMax Reitz         return;
1265c09ba36cSMax Reitz     }
1266c09ba36cSMax Reitz 
1267f21d96d0SKevin Wolf     bdrv_invalidate_cache(bs, errp);
12682bb0dce7SMax Reitz }
12692bb0dce7SMax Reitz 
1270e031f750SMax Reitz bool blk_is_inserted(BlockBackend *blk)
12714be74634SMarkus Armbruster {
1272f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1273f21d96d0SKevin Wolf 
1274f21d96d0SKevin Wolf     return bs && bdrv_is_inserted(bs);
1275db0284f8SMax Reitz }
1276db0284f8SMax Reitz 
1277db0284f8SMax Reitz bool blk_is_available(BlockBackend *blk)
1278db0284f8SMax Reitz {
1279db0284f8SMax Reitz     return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
12804be74634SMarkus Armbruster }
12814be74634SMarkus Armbruster 
12824be74634SMarkus Armbruster void blk_lock_medium(BlockBackend *blk, bool locked)
12834be74634SMarkus Armbruster {
1284f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1285f21d96d0SKevin Wolf 
1286f21d96d0SKevin Wolf     if (bs) {
1287f21d96d0SKevin Wolf         bdrv_lock_medium(bs, locked);
12884be74634SMarkus Armbruster     }
1289a46fc9c9SMax Reitz }
12904be74634SMarkus Armbruster 
12914be74634SMarkus Armbruster void blk_eject(BlockBackend *blk, bool eject_flag)
12924be74634SMarkus Armbruster {
1293f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1294f21d96d0SKevin Wolf 
1295f21d96d0SKevin Wolf     if (bs) {
1296f21d96d0SKevin Wolf         bdrv_eject(bs, eject_flag);
12974be74634SMarkus Armbruster     }
1298a46fc9c9SMax Reitz }
12994be74634SMarkus Armbruster 
13004be74634SMarkus Armbruster int blk_get_flags(BlockBackend *blk)
13014be74634SMarkus Armbruster {
1302f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1303f21d96d0SKevin Wolf 
1304f21d96d0SKevin Wolf     if (bs) {
1305f21d96d0SKevin Wolf         return bdrv_get_flags(bs);
1306061959e8SMax Reitz     } else {
1307061959e8SMax Reitz         return blk->root_state.open_flags;
1308061959e8SMax Reitz     }
13094be74634SMarkus Armbruster }
13104be74634SMarkus Armbruster 
13115def6b80SEric Blake /* Returns the maximum transfer length, in bytes; guaranteed nonzero */
13125def6b80SEric Blake uint32_t blk_get_max_transfer(BlockBackend *blk)
1313454057b7SPeter Lieven {
1314f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
13155def6b80SEric Blake     uint32_t max = 0;
1316f21d96d0SKevin Wolf 
1317f21d96d0SKevin Wolf     if (bs) {
13185def6b80SEric Blake         max = bs->bl.max_transfer;
1319a46fc9c9SMax Reitz     }
13205def6b80SEric Blake     return MIN_NON_ZERO(max, INT_MAX);
1321454057b7SPeter Lieven }
1322454057b7SPeter Lieven 
1323648296e0SStefan Hajnoczi int blk_get_max_iov(BlockBackend *blk)
1324648296e0SStefan Hajnoczi {
1325f21d96d0SKevin Wolf     return blk->root->bs->bl.max_iov;
1326648296e0SStefan Hajnoczi }
1327648296e0SStefan Hajnoczi 
13284be74634SMarkus Armbruster void blk_set_guest_block_size(BlockBackend *blk, int align)
13294be74634SMarkus Armbruster {
133068e9ec01SMax Reitz     blk->guest_block_size = align;
13314be74634SMarkus Armbruster }
13324be74634SMarkus Armbruster 
1333f1c17521SPaolo Bonzini void *blk_try_blockalign(BlockBackend *blk, size_t size)
1334f1c17521SPaolo Bonzini {
1335f21d96d0SKevin Wolf     return qemu_try_blockalign(blk ? blk_bs(blk) : NULL, size);
1336f1c17521SPaolo Bonzini }
1337f1c17521SPaolo Bonzini 
13384be74634SMarkus Armbruster void *blk_blockalign(BlockBackend *blk, size_t size)
13394be74634SMarkus Armbruster {
1340f21d96d0SKevin Wolf     return qemu_blockalign(blk ? blk_bs(blk) : NULL, size);
13414be74634SMarkus Armbruster }
13424be74634SMarkus Armbruster 
13434be74634SMarkus Armbruster bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
13444be74634SMarkus Armbruster {
1345f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1346f21d96d0SKevin Wolf 
1347f21d96d0SKevin Wolf     if (!bs) {
1348a46fc9c9SMax Reitz         return false;
1349a46fc9c9SMax Reitz     }
1350a46fc9c9SMax Reitz 
1351f21d96d0SKevin Wolf     return bdrv_op_is_blocked(bs, op, errp);
13524be74634SMarkus Armbruster }
13534be74634SMarkus Armbruster 
13544be74634SMarkus Armbruster void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
13554be74634SMarkus Armbruster {
1356f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1357f21d96d0SKevin Wolf 
1358f21d96d0SKevin Wolf     if (bs) {
1359f21d96d0SKevin Wolf         bdrv_op_unblock(bs, op, reason);
13604be74634SMarkus Armbruster     }
1361a46fc9c9SMax Reitz }
13624be74634SMarkus Armbruster 
13634be74634SMarkus Armbruster void blk_op_block_all(BlockBackend *blk, Error *reason)
13644be74634SMarkus Armbruster {
1365f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1366f21d96d0SKevin Wolf 
1367f21d96d0SKevin Wolf     if (bs) {
1368f21d96d0SKevin Wolf         bdrv_op_block_all(bs, reason);
13694be74634SMarkus Armbruster     }
1370a46fc9c9SMax Reitz }
13714be74634SMarkus Armbruster 
13724be74634SMarkus Armbruster void blk_op_unblock_all(BlockBackend *blk, Error *reason)
13734be74634SMarkus Armbruster {
1374f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1375f21d96d0SKevin Wolf 
1376f21d96d0SKevin Wolf     if (bs) {
1377f21d96d0SKevin Wolf         bdrv_op_unblock_all(bs, reason);
13784be74634SMarkus Armbruster     }
1379a46fc9c9SMax Reitz }
13804be74634SMarkus Armbruster 
13814be74634SMarkus Armbruster AioContext *blk_get_aio_context(BlockBackend *blk)
13824be74634SMarkus Armbruster {
1383f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1384f21d96d0SKevin Wolf 
1385f21d96d0SKevin Wolf     if (bs) {
1386f21d96d0SKevin Wolf         return bdrv_get_aio_context(bs);
13874981bdecSMax Reitz     } else {
13884981bdecSMax Reitz         return qemu_get_aio_context();
13894981bdecSMax Reitz     }
13904981bdecSMax Reitz }
13914981bdecSMax Reitz 
13924981bdecSMax Reitz static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
13934981bdecSMax Reitz {
13944981bdecSMax Reitz     BlockBackendAIOCB *blk_acb = DO_UPCAST(BlockBackendAIOCB, common, acb);
13954981bdecSMax Reitz     return blk_get_aio_context(blk_acb->blk);
13964be74634SMarkus Armbruster }
13974be74634SMarkus Armbruster 
13984be74634SMarkus Armbruster void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
13994be74634SMarkus Armbruster {
1400f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1401f21d96d0SKevin Wolf 
1402f21d96d0SKevin Wolf     if (bs) {
14037ca7f0f6SKevin Wolf         if (blk->public.throttle_state) {
14047ca7f0f6SKevin Wolf             throttle_timers_detach_aio_context(&blk->public.throttle_timers);
14057ca7f0f6SKevin Wolf         }
1406f21d96d0SKevin Wolf         bdrv_set_aio_context(bs, new_context);
14077ca7f0f6SKevin Wolf         if (blk->public.throttle_state) {
14087ca7f0f6SKevin Wolf             throttle_timers_attach_aio_context(&blk->public.throttle_timers,
14097ca7f0f6SKevin Wolf                                                new_context);
14107ca7f0f6SKevin Wolf         }
14114be74634SMarkus Armbruster     }
1412a46fc9c9SMax Reitz }
14134be74634SMarkus Armbruster 
14142019ba0aSMax Reitz void blk_add_aio_context_notifier(BlockBackend *blk,
14152019ba0aSMax Reitz         void (*attached_aio_context)(AioContext *new_context, void *opaque),
14162019ba0aSMax Reitz         void (*detach_aio_context)(void *opaque), void *opaque)
14172019ba0aSMax Reitz {
1418f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1419f21d96d0SKevin Wolf 
1420f21d96d0SKevin Wolf     if (bs) {
1421f21d96d0SKevin Wolf         bdrv_add_aio_context_notifier(bs, attached_aio_context,
14222019ba0aSMax Reitz                                       detach_aio_context, opaque);
14232019ba0aSMax Reitz     }
1424a46fc9c9SMax Reitz }
14252019ba0aSMax Reitz 
14262019ba0aSMax Reitz void blk_remove_aio_context_notifier(BlockBackend *blk,
14272019ba0aSMax Reitz                                      void (*attached_aio_context)(AioContext *,
14282019ba0aSMax Reitz                                                                   void *),
14292019ba0aSMax Reitz                                      void (*detach_aio_context)(void *),
14302019ba0aSMax Reitz                                      void *opaque)
14312019ba0aSMax Reitz {
1432f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1433f21d96d0SKevin Wolf 
1434f21d96d0SKevin Wolf     if (bs) {
1435f21d96d0SKevin Wolf         bdrv_remove_aio_context_notifier(bs, attached_aio_context,
14362019ba0aSMax Reitz                                          detach_aio_context, opaque);
14372019ba0aSMax Reitz     }
1438a46fc9c9SMax Reitz }
14392019ba0aSMax Reitz 
14403301f6c6SMax Reitz void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
14413301f6c6SMax Reitz {
14423301f6c6SMax Reitz     notifier_list_add(&blk->remove_bs_notifiers, notify);
14433301f6c6SMax Reitz }
14443301f6c6SMax Reitz 
14453301f6c6SMax Reitz void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
14463301f6c6SMax Reitz {
14473301f6c6SMax Reitz     notifier_list_add(&blk->insert_bs_notifiers, notify);
14483301f6c6SMax Reitz }
14493301f6c6SMax Reitz 
14504be74634SMarkus Armbruster void blk_io_plug(BlockBackend *blk)
14514be74634SMarkus Armbruster {
1452f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1453f21d96d0SKevin Wolf 
1454f21d96d0SKevin Wolf     if (bs) {
1455f21d96d0SKevin Wolf         bdrv_io_plug(bs);
14564be74634SMarkus Armbruster     }
1457a46fc9c9SMax Reitz }
14584be74634SMarkus Armbruster 
14594be74634SMarkus Armbruster void blk_io_unplug(BlockBackend *blk)
14604be74634SMarkus Armbruster {
1461f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1462f21d96d0SKevin Wolf 
1463f21d96d0SKevin Wolf     if (bs) {
1464f21d96d0SKevin Wolf         bdrv_io_unplug(bs);
14654be74634SMarkus Armbruster     }
1466a46fc9c9SMax Reitz }
14674be74634SMarkus Armbruster 
14684be74634SMarkus Armbruster BlockAcctStats *blk_get_stats(BlockBackend *blk)
14694be74634SMarkus Armbruster {
14707f0e9da6SMax Reitz     return &blk->stats;
14714be74634SMarkus Armbruster }
14724be74634SMarkus Armbruster 
14734be74634SMarkus Armbruster void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
14744be74634SMarkus Armbruster                   BlockCompletionFunc *cb, void *opaque)
14754be74634SMarkus Armbruster {
14764be74634SMarkus Armbruster     return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
14774be74634SMarkus Armbruster }
14781ef01253SMax Reitz 
1479d004bd52SEric Blake int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
1480983a1600SEric Blake                                       int count, BdrvRequestFlags flags)
14811ef01253SMax Reitz {
1482983a1600SEric Blake     return blk_co_pwritev(blk, offset, count, NULL,
148316aaf975SKevin Wolf                           flags | BDRV_REQ_ZERO_WRITE);
14841ef01253SMax Reitz }
14851ef01253SMax Reitz 
14861ef01253SMax Reitz int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
14871ef01253SMax Reitz                          const uint8_t *buf, int nb_sectors)
14881ef01253SMax Reitz {
1489e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1490e7f7d676SMax Reitz     if (ret < 0) {
1491e7f7d676SMax Reitz         return ret;
1492e7f7d676SMax Reitz     }
1493e7f7d676SMax Reitz 
1494f21d96d0SKevin Wolf     return bdrv_write_compressed(blk_bs(blk), sector_num, buf, nb_sectors);
14951ef01253SMax Reitz }
14961ef01253SMax Reitz 
14971ef01253SMax Reitz int blk_truncate(BlockBackend *blk, int64_t offset)
14981ef01253SMax Reitz {
1499c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1500c09ba36cSMax Reitz         return -ENOMEDIUM;
1501c09ba36cSMax Reitz     }
1502c09ba36cSMax Reitz 
1503f21d96d0SKevin Wolf     return bdrv_truncate(blk_bs(blk), offset);
15041ef01253SMax Reitz }
15051ef01253SMax Reitz 
15061ef01253SMax Reitz int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
15071ef01253SMax Reitz {
1508e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1509e7f7d676SMax Reitz     if (ret < 0) {
1510e7f7d676SMax Reitz         return ret;
1511e7f7d676SMax Reitz     }
1512e7f7d676SMax Reitz 
1513f21d96d0SKevin Wolf     return bdrv_discard(blk_bs(blk), sector_num, nb_sectors);
15141ef01253SMax Reitz }
15151ef01253SMax Reitz 
15161ef01253SMax Reitz int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
15171ef01253SMax Reitz                      int64_t pos, int size)
15181ef01253SMax Reitz {
1519bfd18d1eSKevin Wolf     int ret;
1520bfd18d1eSKevin Wolf 
1521c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1522c09ba36cSMax Reitz         return -ENOMEDIUM;
1523c09ba36cSMax Reitz     }
1524c09ba36cSMax Reitz 
1525bfd18d1eSKevin Wolf     ret = bdrv_save_vmstate(blk_bs(blk), buf, pos, size);
1526bfd18d1eSKevin Wolf     if (ret < 0) {
1527bfd18d1eSKevin Wolf         return ret;
1528bfd18d1eSKevin Wolf     }
1529bfd18d1eSKevin Wolf 
1530bfd18d1eSKevin Wolf     if (ret == size && !blk->enable_write_cache) {
1531bfd18d1eSKevin Wolf         ret = bdrv_flush(blk_bs(blk));
1532bfd18d1eSKevin Wolf     }
1533bfd18d1eSKevin Wolf 
1534bfd18d1eSKevin Wolf     return ret < 0 ? ret : size;
15351ef01253SMax Reitz }
15361ef01253SMax Reitz 
15371ef01253SMax Reitz int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
15381ef01253SMax Reitz {
1539c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1540c09ba36cSMax Reitz         return -ENOMEDIUM;
1541c09ba36cSMax Reitz     }
1542c09ba36cSMax Reitz 
1543f21d96d0SKevin Wolf     return bdrv_load_vmstate(blk_bs(blk), buf, pos, size);
15441ef01253SMax Reitz }
1545f0272c4dSEkaterina Tumanova 
1546f0272c4dSEkaterina Tumanova int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz)
1547f0272c4dSEkaterina Tumanova {
1548c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1549c09ba36cSMax Reitz         return -ENOMEDIUM;
1550c09ba36cSMax Reitz     }
1551c09ba36cSMax Reitz 
1552f21d96d0SKevin Wolf     return bdrv_probe_blocksizes(blk_bs(blk), bsz);
1553f0272c4dSEkaterina Tumanova }
1554f0272c4dSEkaterina Tumanova 
1555f0272c4dSEkaterina Tumanova int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo)
1556f0272c4dSEkaterina Tumanova {
1557c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1558c09ba36cSMax Reitz         return -ENOMEDIUM;
1559c09ba36cSMax Reitz     }
1560c09ba36cSMax Reitz 
1561f21d96d0SKevin Wolf     return bdrv_probe_geometry(blk_bs(blk), geo);
1562f0272c4dSEkaterina Tumanova }
1563281d22d8SMax Reitz 
1564281d22d8SMax Reitz /*
1565281d22d8SMax Reitz  * Updates the BlockBackendRootState object with data from the currently
1566281d22d8SMax Reitz  * attached BlockDriverState.
1567281d22d8SMax Reitz  */
1568281d22d8SMax Reitz void blk_update_root_state(BlockBackend *blk)
1569281d22d8SMax Reitz {
1570f21d96d0SKevin Wolf     assert(blk->root);
1571281d22d8SMax Reitz 
1572f21d96d0SKevin Wolf     blk->root_state.open_flags    = blk->root->bs->open_flags;
1573f21d96d0SKevin Wolf     blk->root_state.read_only     = blk->root->bs->read_only;
1574f21d96d0SKevin Wolf     blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
1575281d22d8SMax Reitz }
1576281d22d8SMax Reitz 
157738cb18f5SMax Reitz /*
157838cb18f5SMax Reitz  * Applies the information in the root state to the given BlockDriverState. This
157938cb18f5SMax Reitz  * does not include the flags which have to be specified for bdrv_open(), use
158038cb18f5SMax Reitz  * blk_get_open_flags_from_root_state() to inquire them.
158138cb18f5SMax Reitz  */
158238cb18f5SMax Reitz void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs)
158338cb18f5SMax Reitz {
158438cb18f5SMax Reitz     bs->detect_zeroes = blk->root_state.detect_zeroes;
158538cb18f5SMax Reitz }
158638cb18f5SMax Reitz 
158738cb18f5SMax Reitz /*
158838cb18f5SMax Reitz  * Returns the flags to be used for bdrv_open() of a BlockDriverState which is
158938cb18f5SMax Reitz  * supposed to inherit the root state.
159038cb18f5SMax Reitz  */
159138cb18f5SMax Reitz int blk_get_open_flags_from_root_state(BlockBackend *blk)
159238cb18f5SMax Reitz {
159338cb18f5SMax Reitz     int bs_flags;
159438cb18f5SMax Reitz 
159538cb18f5SMax Reitz     bs_flags = blk->root_state.read_only ? 0 : BDRV_O_RDWR;
159638cb18f5SMax Reitz     bs_flags |= blk->root_state.open_flags & ~BDRV_O_RDWR;
159738cb18f5SMax Reitz 
159838cb18f5SMax Reitz     return bs_flags;
159938cb18f5SMax Reitz }
160038cb18f5SMax Reitz 
1601281d22d8SMax Reitz BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
1602281d22d8SMax Reitz {
1603281d22d8SMax Reitz     return &blk->root_state;
1604281d22d8SMax Reitz }
16051393f212SMax Reitz 
16061393f212SMax Reitz int blk_commit_all(void)
16071393f212SMax Reitz {
1608fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
1609fe1a9cbcSMax Reitz 
1610fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
1611fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
1612fe1a9cbcSMax Reitz 
1613fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
1614f21d96d0SKevin Wolf         if (blk_is_inserted(blk) && blk->root->bs->backing) {
1615f21d96d0SKevin Wolf             int ret = bdrv_commit(blk->root->bs);
1616fe1a9cbcSMax Reitz             if (ret < 0) {
1617fe1a9cbcSMax Reitz                 aio_context_release(aio_context);
1618fe1a9cbcSMax Reitz                 return ret;
1619fe1a9cbcSMax Reitz             }
1620fe1a9cbcSMax Reitz         }
1621fe1a9cbcSMax Reitz         aio_context_release(aio_context);
1622fe1a9cbcSMax Reitz     }
1623fe1a9cbcSMax Reitz     return 0;
1624fe1a9cbcSMax Reitz }
1625fe1a9cbcSMax Reitz 
1626fe1a9cbcSMax Reitz int blk_flush_all(void)
1627fe1a9cbcSMax Reitz {
1628fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
1629fe1a9cbcSMax Reitz     int result = 0;
1630fe1a9cbcSMax Reitz 
1631fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
1632fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
1633fe1a9cbcSMax Reitz         int ret;
1634fe1a9cbcSMax Reitz 
1635fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
1636fe1a9cbcSMax Reitz         if (blk_is_inserted(blk)) {
1637fe1a9cbcSMax Reitz             ret = blk_flush(blk);
1638fe1a9cbcSMax Reitz             if (ret < 0 && !result) {
1639fe1a9cbcSMax Reitz                 result = ret;
1640fe1a9cbcSMax Reitz             }
1641fe1a9cbcSMax Reitz         }
1642fe1a9cbcSMax Reitz         aio_context_release(aio_context);
1643fe1a9cbcSMax Reitz     }
1644fe1a9cbcSMax Reitz 
1645fe1a9cbcSMax Reitz     return result;
16461393f212SMax Reitz }
164797148076SKevin Wolf 
164897148076SKevin Wolf 
164997148076SKevin Wolf /* throttling disk I/O limits */
165097148076SKevin Wolf void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
165197148076SKevin Wolf {
165297148076SKevin Wolf     throttle_group_config(blk, cfg);
165397148076SKevin Wolf }
165497148076SKevin Wolf 
165597148076SKevin Wolf void blk_io_limits_disable(BlockBackend *blk)
165697148076SKevin Wolf {
165797148076SKevin Wolf     assert(blk->public.throttle_state);
1658c2066af0SKevin Wolf     bdrv_drained_begin(blk_bs(blk));
165997148076SKevin Wolf     throttle_group_unregister_blk(blk);
1660c2066af0SKevin Wolf     bdrv_drained_end(blk_bs(blk));
166197148076SKevin Wolf }
166297148076SKevin Wolf 
166397148076SKevin Wolf /* should be called before blk_set_io_limits if a limit is set */
166497148076SKevin Wolf void blk_io_limits_enable(BlockBackend *blk, const char *group)
166597148076SKevin Wolf {
166697148076SKevin Wolf     assert(!blk->public.throttle_state);
166797148076SKevin Wolf     throttle_group_register_blk(blk, group);
166897148076SKevin Wolf }
166997148076SKevin Wolf 
167097148076SKevin Wolf void blk_io_limits_update_group(BlockBackend *blk, const char *group)
167197148076SKevin Wolf {
167297148076SKevin Wolf     /* this BB is not part of any group */
167397148076SKevin Wolf     if (!blk->public.throttle_state) {
167497148076SKevin Wolf         return;
167597148076SKevin Wolf     }
167697148076SKevin Wolf 
167797148076SKevin Wolf     /* this BB is a part of the same group than the one we want */
167897148076SKevin Wolf     if (!g_strcmp0(throttle_group_get_name(blk), group)) {
167997148076SKevin Wolf         return;
168097148076SKevin Wolf     }
168197148076SKevin Wolf 
168297148076SKevin Wolf     /* need to change the group this bs belong to */
168397148076SKevin Wolf     blk_io_limits_disable(blk);
168497148076SKevin Wolf     blk_io_limits_enable(blk, group);
168597148076SKevin Wolf }
1686c2066af0SKevin Wolf 
1687c2066af0SKevin Wolf static void blk_root_drained_begin(BdrvChild *child)
1688c2066af0SKevin Wolf {
1689c2066af0SKevin Wolf     BlockBackend *blk = child->opaque;
1690c2066af0SKevin Wolf 
169136fe1331SKevin Wolf     /* Note that blk->root may not be accessible here yet if we are just
169236fe1331SKevin Wolf      * attaching to a BlockDriverState that is drained. Use child instead. */
169336fe1331SKevin Wolf 
1694c2066af0SKevin Wolf     if (blk->public.io_limits_disabled++ == 0) {
1695c2066af0SKevin Wolf         throttle_group_restart_blk(blk);
1696c2066af0SKevin Wolf     }
1697c2066af0SKevin Wolf }
1698c2066af0SKevin Wolf 
1699c2066af0SKevin Wolf static void blk_root_drained_end(BdrvChild *child)
1700c2066af0SKevin Wolf {
1701c2066af0SKevin Wolf     BlockBackend *blk = child->opaque;
1702c2066af0SKevin Wolf 
1703c2066af0SKevin Wolf     assert(blk->public.io_limits_disabled);
1704c2066af0SKevin Wolf     --blk->public.io_limits_disabled;
1705c2066af0SKevin Wolf }
1706