xref: /openbmc/qemu/block/block-backend.c (revision 27ccdd52)
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"
22a7f53e26SMarkus Armbruster 
23a7f53e26SMarkus Armbruster /* Number of coroutines to reserve per attached device model */
24a7f53e26SMarkus Armbruster #define COROUTINE_POOL_RESERVATION 64
2526f54e9aSMarkus Armbruster 
261bf1cbc9SKevin Wolf #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
271bf1cbc9SKevin Wolf 
284981bdecSMax Reitz static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
294981bdecSMax Reitz 
3026f54e9aSMarkus Armbruster struct BlockBackend {
3126f54e9aSMarkus Armbruster     char *name;
3226f54e9aSMarkus Armbruster     int refcnt;
33f21d96d0SKevin Wolf     BdrvChild *root;
3426f8b3a8SMarkus Armbruster     DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
352cf22d6aSMax Reitz     QTAILQ_ENTRY(BlockBackend) link;         /* for block_backends */
369492b0b9SMax Reitz     QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
37f2cd875dSKevin Wolf     BlockBackendPublic public;
38a7f53e26SMarkus Armbruster 
39a7f53e26SMarkus Armbruster     void *dev;                  /* attached device model, if any */
40a7f53e26SMarkus Armbruster     /* TODO change to DeviceState when all users are qdevified */
41a7f53e26SMarkus Armbruster     const BlockDevOps *dev_ops;
42a7f53e26SMarkus Armbruster     void *dev_opaque;
4368e9ec01SMax Reitz 
4468e9ec01SMax Reitz     /* the block size for which the guest device expects atomicity */
4568e9ec01SMax Reitz     int guest_block_size;
467f0e9da6SMax Reitz 
47281d22d8SMax Reitz     /* If the BDS tree is removed, some of its options are stored here (which
48281d22d8SMax Reitz      * can be used to restore those options in the new BDS on insert) */
49281d22d8SMax Reitz     BlockBackendRootState root_state;
50281d22d8SMax Reitz 
51bfd18d1eSKevin Wolf     bool enable_write_cache;
52bfd18d1eSKevin Wolf 
537f0e9da6SMax Reitz     /* I/O stats (display with "info blockstats"). */
547f0e9da6SMax Reitz     BlockAcctStats stats;
55373340b2SMax Reitz 
56373340b2SMax Reitz     BlockdevOnError on_read_error, on_write_error;
57373340b2SMax Reitz     bool iostatus_enabled;
58373340b2SMax Reitz     BlockDeviceIoStatus iostatus;
593301f6c6SMax Reitz 
60c10c9d96SKevin Wolf     bool allow_write_beyond_eof;
61c10c9d96SKevin Wolf 
623301f6c6SMax Reitz     NotifierList remove_bs_notifiers, insert_bs_notifiers;
6326f54e9aSMarkus Armbruster };
6426f54e9aSMarkus Armbruster 
65e7f7d676SMax Reitz typedef struct BlockBackendAIOCB {
66e7f7d676SMax Reitz     BlockAIOCB common;
67e7f7d676SMax Reitz     QEMUBH *bh;
684981bdecSMax Reitz     BlockBackend *blk;
69e7f7d676SMax Reitz     int ret;
70e7f7d676SMax Reitz } BlockBackendAIOCB;
71e7f7d676SMax Reitz 
72e7f7d676SMax Reitz static const AIOCBInfo block_backend_aiocb_info = {
734981bdecSMax Reitz     .get_aio_context = blk_aiocb_get_aio_context,
74e7f7d676SMax Reitz     .aiocb_size = sizeof(BlockBackendAIOCB),
75e7f7d676SMax Reitz };
76e7f7d676SMax Reitz 
778fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo);
788fb3c76cSMarkus Armbruster 
792cf22d6aSMax Reitz /* All BlockBackends */
802cf22d6aSMax Reitz static QTAILQ_HEAD(, BlockBackend) block_backends =
812cf22d6aSMax Reitz     QTAILQ_HEAD_INITIALIZER(block_backends);
822cf22d6aSMax Reitz 
839492b0b9SMax Reitz /* All BlockBackends referenced by the monitor and which are iterated through by
849492b0b9SMax Reitz  * blk_next() */
859492b0b9SMax Reitz static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
869492b0b9SMax Reitz     QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
8726f54e9aSMarkus Armbruster 
88f21d96d0SKevin Wolf static void blk_root_inherit_options(int *child_flags, QDict *child_options,
89f21d96d0SKevin Wolf                                      int parent_flags, QDict *parent_options)
90f21d96d0SKevin Wolf {
91f21d96d0SKevin Wolf     /* We're not supposed to call this function for root nodes */
92f21d96d0SKevin Wolf     abort();
93f21d96d0SKevin Wolf }
94f21d96d0SKevin Wolf 
95f21d96d0SKevin Wolf static const BdrvChildRole child_root = {
96f21d96d0SKevin Wolf     .inherit_options = blk_root_inherit_options,
97f21d96d0SKevin Wolf };
98f21d96d0SKevin Wolf 
9926f54e9aSMarkus Armbruster /*
100efaa7c4eSMax Reitz  * Create a new BlockBackend with a reference count of one.
10126f54e9aSMarkus Armbruster  * Store an error through @errp on failure, unless it's null.
10226f54e9aSMarkus Armbruster  * Return the new BlockBackend on success, null on failure.
10326f54e9aSMarkus Armbruster  */
104efaa7c4eSMax Reitz BlockBackend *blk_new(Error **errp)
10526f54e9aSMarkus Armbruster {
10626f54e9aSMarkus Armbruster     BlockBackend *blk;
10726f54e9aSMarkus Armbruster 
10826f54e9aSMarkus Armbruster     blk = g_new0(BlockBackend, 1);
10926f54e9aSMarkus Armbruster     blk->refcnt = 1;
110*27ccdd52SKevin Wolf     qemu_co_queue_init(&blk->public.throttled_reqs[0]);
111*27ccdd52SKevin Wolf     qemu_co_queue_init(&blk->public.throttled_reqs[1]);
112*27ccdd52SKevin Wolf 
1133301f6c6SMax Reitz     notifier_list_init(&blk->remove_bs_notifiers);
1143301f6c6SMax Reitz     notifier_list_init(&blk->insert_bs_notifiers);
115*27ccdd52SKevin Wolf 
1162cf22d6aSMax Reitz     QTAILQ_INSERT_TAIL(&block_backends, blk, link);
11726f54e9aSMarkus Armbruster     return blk;
11826f54e9aSMarkus Armbruster }
11926f54e9aSMarkus Armbruster 
1207e7d56d9SMarkus Armbruster /*
1217e7d56d9SMarkus Armbruster  * Create a new BlockBackend with a new BlockDriverState attached.
1227e7d56d9SMarkus Armbruster  * Otherwise just like blk_new(), which see.
1237e7d56d9SMarkus Armbruster  */
124efaa7c4eSMax Reitz BlockBackend *blk_new_with_bs(Error **errp)
1257e7d56d9SMarkus Armbruster {
1267e7d56d9SMarkus Armbruster     BlockBackend *blk;
1277e7d56d9SMarkus Armbruster     BlockDriverState *bs;
1287e7d56d9SMarkus Armbruster 
129efaa7c4eSMax Reitz     blk = blk_new(errp);
1307e7d56d9SMarkus Armbruster     if (!blk) {
1317e7d56d9SMarkus Armbruster         return NULL;
1327e7d56d9SMarkus Armbruster     }
1337e7d56d9SMarkus Armbruster 
1347f06d47eSMarkus Armbruster     bs = bdrv_new_root();
135f21d96d0SKevin Wolf     blk->root = bdrv_root_attach_child(bs, "root", &child_root);
1367e7d56d9SMarkus Armbruster     bs->blk = blk;
1377e7d56d9SMarkus Armbruster     return blk;
1387e7d56d9SMarkus Armbruster }
1397e7d56d9SMarkus Armbruster 
140ca49a4fdSMax Reitz /*
141ca49a4fdSMax Reitz  * Calls blk_new_with_bs() and then calls bdrv_open() on the BlockDriverState.
142ca49a4fdSMax Reitz  *
143ca49a4fdSMax Reitz  * Just as with bdrv_open(), after having called this function the reference to
144ca49a4fdSMax Reitz  * @options belongs to the block layer (even on failure).
145ca49a4fdSMax Reitz  *
146ca49a4fdSMax Reitz  * TODO: Remove @filename and @flags; it should be possible to specify a whole
147ca49a4fdSMax Reitz  * BDS tree just by specifying the @options QDict (or @reference,
148ca49a4fdSMax Reitz  * alternatively). At the time of adding this function, this is not possible,
149ca49a4fdSMax Reitz  * though, so callers of this function have to be able to specify @filename and
150ca49a4fdSMax Reitz  * @flags.
151ca49a4fdSMax Reitz  */
152efaa7c4eSMax Reitz BlockBackend *blk_new_open(const char *filename, const char *reference,
153efaa7c4eSMax Reitz                            QDict *options, int flags, Error **errp)
154ca49a4fdSMax Reitz {
155ca49a4fdSMax Reitz     BlockBackend *blk;
156ca49a4fdSMax Reitz     int ret;
157ca49a4fdSMax Reitz 
158efaa7c4eSMax Reitz     blk = blk_new_with_bs(errp);
159ca49a4fdSMax Reitz     if (!blk) {
160ca49a4fdSMax Reitz         QDECREF(options);
161ca49a4fdSMax Reitz         return NULL;
162ca49a4fdSMax Reitz     }
163ca49a4fdSMax Reitz 
164f21d96d0SKevin Wolf     ret = bdrv_open(&blk->root->bs, filename, reference, options, flags, errp);
165ca49a4fdSMax Reitz     if (ret < 0) {
166ca49a4fdSMax Reitz         blk_unref(blk);
167ca49a4fdSMax Reitz         return NULL;
168ca49a4fdSMax Reitz     }
169ca49a4fdSMax Reitz 
17072e775c7SKevin Wolf     blk_set_enable_write_cache(blk, true);
17172e775c7SKevin Wolf 
172ca49a4fdSMax Reitz     return blk;
173ca49a4fdSMax Reitz }
174ca49a4fdSMax Reitz 
17526f54e9aSMarkus Armbruster static void blk_delete(BlockBackend *blk)
17626f54e9aSMarkus Armbruster {
17726f54e9aSMarkus Armbruster     assert(!blk->refcnt);
178e5e78550SMax Reitz     assert(!blk->name);
179a7f53e26SMarkus Armbruster     assert(!blk->dev);
180f21d96d0SKevin Wolf     if (blk->root) {
18113855c6bSMax Reitz         blk_remove_bs(blk);
1827e7d56d9SMarkus Armbruster     }
1833301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
1843301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
185281d22d8SMax Reitz     if (blk->root_state.throttle_state) {
186281d22d8SMax Reitz         g_free(blk->root_state.throttle_group);
187281d22d8SMax Reitz         throttle_group_unref(blk->root_state.throttle_state);
188281d22d8SMax Reitz     }
1892cf22d6aSMax Reitz     QTAILQ_REMOVE(&block_backends, blk, link);
19018e46a03SMarkus Armbruster     drive_info_del(blk->legacy_dinfo);
191979e9b03SAlberto Garcia     block_acct_cleanup(&blk->stats);
19226f54e9aSMarkus Armbruster     g_free(blk);
19326f54e9aSMarkus Armbruster }
19426f54e9aSMarkus Armbruster 
1958fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo)
1968fb3c76cSMarkus Armbruster {
1978fb3c76cSMarkus Armbruster     if (!dinfo) {
1988fb3c76cSMarkus Armbruster         return;
1998fb3c76cSMarkus Armbruster     }
2008fb3c76cSMarkus Armbruster     qemu_opts_del(dinfo->opts);
2018fb3c76cSMarkus Armbruster     g_free(dinfo->serial);
2028fb3c76cSMarkus Armbruster     g_free(dinfo);
2038fb3c76cSMarkus Armbruster }
2048fb3c76cSMarkus Armbruster 
205f636ae85SAlberto Garcia int blk_get_refcnt(BlockBackend *blk)
206f636ae85SAlberto Garcia {
207f636ae85SAlberto Garcia     return blk ? blk->refcnt : 0;
208f636ae85SAlberto Garcia }
209f636ae85SAlberto Garcia 
21026f54e9aSMarkus Armbruster /*
21126f54e9aSMarkus Armbruster  * Increment @blk's reference count.
21226f54e9aSMarkus Armbruster  * @blk must not be null.
21326f54e9aSMarkus Armbruster  */
21426f54e9aSMarkus Armbruster void blk_ref(BlockBackend *blk)
21526f54e9aSMarkus Armbruster {
21626f54e9aSMarkus Armbruster     blk->refcnt++;
21726f54e9aSMarkus Armbruster }
21826f54e9aSMarkus Armbruster 
21926f54e9aSMarkus Armbruster /*
22026f54e9aSMarkus Armbruster  * Decrement @blk's reference count.
22126f54e9aSMarkus Armbruster  * If this drops it to zero, destroy @blk.
22226f54e9aSMarkus Armbruster  * For convenience, do nothing if @blk is null.
22326f54e9aSMarkus Armbruster  */
22426f54e9aSMarkus Armbruster void blk_unref(BlockBackend *blk)
22526f54e9aSMarkus Armbruster {
22626f54e9aSMarkus Armbruster     if (blk) {
22726f54e9aSMarkus Armbruster         assert(blk->refcnt > 0);
22826f54e9aSMarkus Armbruster         if (!--blk->refcnt) {
22926f54e9aSMarkus Armbruster             blk_delete(blk);
23026f54e9aSMarkus Armbruster         }
23126f54e9aSMarkus Armbruster     }
23226f54e9aSMarkus Armbruster }
23326f54e9aSMarkus Armbruster 
2342cf22d6aSMax Reitz /*
2352cf22d6aSMax Reitz  * Behaves similarly to blk_next() but iterates over all BlockBackends, even the
2362cf22d6aSMax Reitz  * ones which are hidden (i.e. are not referenced by the monitor).
2372cf22d6aSMax Reitz  */
2382cf22d6aSMax Reitz static BlockBackend *blk_all_next(BlockBackend *blk)
2392cf22d6aSMax Reitz {
2402cf22d6aSMax Reitz     return blk ? QTAILQ_NEXT(blk, link)
2412cf22d6aSMax Reitz                : QTAILQ_FIRST(&block_backends);
2422cf22d6aSMax Reitz }
2432cf22d6aSMax Reitz 
244d8da3cefSMax Reitz void blk_remove_all_bs(void)
245d8da3cefSMax Reitz {
24674d1b8fcSMax Reitz     BlockBackend *blk = NULL;
247d8da3cefSMax Reitz 
2482cf22d6aSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
249d8da3cefSMax Reitz         AioContext *ctx = blk_get_aio_context(blk);
250d8da3cefSMax Reitz 
251d8da3cefSMax Reitz         aio_context_acquire(ctx);
252f21d96d0SKevin Wolf         if (blk->root) {
253d8da3cefSMax Reitz             blk_remove_bs(blk);
254d8da3cefSMax Reitz         }
255d8da3cefSMax Reitz         aio_context_release(ctx);
256d8da3cefSMax Reitz     }
257d8da3cefSMax Reitz }
258d8da3cefSMax Reitz 
25926f54e9aSMarkus Armbruster /*
2609492b0b9SMax Reitz  * Return the monitor-owned BlockBackend after @blk.
26126f54e9aSMarkus Armbruster  * If @blk is null, return the first one.
26226f54e9aSMarkus Armbruster  * Else, return @blk's next sibling, which may be null.
26326f54e9aSMarkus Armbruster  *
26426f54e9aSMarkus Armbruster  * To iterate over all BlockBackends, do
26526f54e9aSMarkus Armbruster  * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
26626f54e9aSMarkus Armbruster  *     ...
26726f54e9aSMarkus Armbruster  * }
26826f54e9aSMarkus Armbruster  */
26926f54e9aSMarkus Armbruster BlockBackend *blk_next(BlockBackend *blk)
27026f54e9aSMarkus Armbruster {
2719492b0b9SMax Reitz     return blk ? QTAILQ_NEXT(blk, monitor_link)
2729492b0b9SMax Reitz                : QTAILQ_FIRST(&monitor_block_backends);
27326f54e9aSMarkus Armbruster }
27426f54e9aSMarkus Armbruster 
27526f54e9aSMarkus Armbruster /*
276981f4f57SMax Reitz  * Iterates over all BlockDriverStates which are attached to a BlockBackend.
277981f4f57SMax Reitz  * This function is for use by bdrv_next().
278981f4f57SMax Reitz  *
279981f4f57SMax Reitz  * @bs must be NULL or a BDS that is attached to a BB.
280981f4f57SMax Reitz  */
281981f4f57SMax Reitz BlockDriverState *blk_next_root_bs(BlockDriverState *bs)
282981f4f57SMax Reitz {
283981f4f57SMax Reitz     BlockBackend *blk;
284981f4f57SMax Reitz 
285981f4f57SMax Reitz     if (bs) {
286981f4f57SMax Reitz         assert(bs->blk);
287981f4f57SMax Reitz         blk = bs->blk;
288981f4f57SMax Reitz     } else {
289981f4f57SMax Reitz         blk = NULL;
290981f4f57SMax Reitz     }
291981f4f57SMax Reitz 
292981f4f57SMax Reitz     do {
293981f4f57SMax Reitz         blk = blk_all_next(blk);
294f21d96d0SKevin Wolf     } while (blk && !blk->root);
295981f4f57SMax Reitz 
296f21d96d0SKevin Wolf     return blk ? blk->root->bs : NULL;
297981f4f57SMax Reitz }
298981f4f57SMax Reitz 
299981f4f57SMax Reitz /*
300e5e78550SMax Reitz  * Add a BlockBackend into the list of backends referenced by the monitor, with
301e5e78550SMax Reitz  * the given @name acting as the handle for the monitor.
302e5e78550SMax Reitz  * Strictly for use by blockdev.c.
303e5e78550SMax Reitz  *
304e5e78550SMax Reitz  * @name must not be null or empty.
305e5e78550SMax Reitz  *
306e5e78550SMax Reitz  * Returns true on success and false on failure. In the latter case, an Error
307e5e78550SMax Reitz  * object is returned through @errp.
308e5e78550SMax Reitz  */
309e5e78550SMax Reitz bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
310e5e78550SMax Reitz {
311e5e78550SMax Reitz     assert(!blk->name);
312e5e78550SMax Reitz     assert(name && name[0]);
313e5e78550SMax Reitz 
314e5e78550SMax Reitz     if (!id_wellformed(name)) {
315e5e78550SMax Reitz         error_setg(errp, "Invalid device name");
316e5e78550SMax Reitz         return false;
317e5e78550SMax Reitz     }
318e5e78550SMax Reitz     if (blk_by_name(name)) {
319e5e78550SMax Reitz         error_setg(errp, "Device with id '%s' already exists", name);
320e5e78550SMax Reitz         return false;
321e5e78550SMax Reitz     }
322e5e78550SMax Reitz     if (bdrv_find_node(name)) {
323e5e78550SMax Reitz         error_setg(errp,
324e5e78550SMax Reitz                    "Device name '%s' conflicts with an existing node name",
325e5e78550SMax Reitz                    name);
326e5e78550SMax Reitz         return false;
327e5e78550SMax Reitz     }
328e5e78550SMax Reitz 
329e5e78550SMax Reitz     blk->name = g_strdup(name);
330e5e78550SMax Reitz     QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
331e5e78550SMax Reitz     return true;
332e5e78550SMax Reitz }
333e5e78550SMax Reitz 
334e5e78550SMax Reitz /*
335e5e78550SMax Reitz  * Remove a BlockBackend from the list of backends referenced by the monitor.
336e5e78550SMax Reitz  * Strictly for use by blockdev.c.
337e5e78550SMax Reitz  */
338e5e78550SMax Reitz void monitor_remove_blk(BlockBackend *blk)
339e5e78550SMax Reitz {
340e5e78550SMax Reitz     if (!blk->name) {
341e5e78550SMax Reitz         return;
342e5e78550SMax Reitz     }
343e5e78550SMax Reitz 
344e5e78550SMax Reitz     QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
345e5e78550SMax Reitz     g_free(blk->name);
346e5e78550SMax Reitz     blk->name = NULL;
347e5e78550SMax Reitz }
348e5e78550SMax Reitz 
349e5e78550SMax Reitz /*
3507e7d56d9SMarkus Armbruster  * Return @blk's name, a non-null string.
351e5e78550SMax Reitz  * Returns an empty string iff @blk is not referenced by the monitor.
35226f54e9aSMarkus Armbruster  */
35326f54e9aSMarkus Armbruster const char *blk_name(BlockBackend *blk)
35426f54e9aSMarkus Armbruster {
355e5e78550SMax Reitz     return blk->name ?: "";
35626f54e9aSMarkus Armbruster }
35726f54e9aSMarkus Armbruster 
35826f54e9aSMarkus Armbruster /*
35926f54e9aSMarkus Armbruster  * Return the BlockBackend with name @name if it exists, else null.
36026f54e9aSMarkus Armbruster  * @name must not be null.
36126f54e9aSMarkus Armbruster  */
36226f54e9aSMarkus Armbruster BlockBackend *blk_by_name(const char *name)
36326f54e9aSMarkus Armbruster {
36474d1b8fcSMax Reitz     BlockBackend *blk = NULL;
36526f54e9aSMarkus Armbruster 
36626f54e9aSMarkus Armbruster     assert(name);
36774d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
36826f54e9aSMarkus Armbruster         if (!strcmp(name, blk->name)) {
36926f54e9aSMarkus Armbruster             return blk;
37026f54e9aSMarkus Armbruster         }
37126f54e9aSMarkus Armbruster     }
37226f54e9aSMarkus Armbruster     return NULL;
37326f54e9aSMarkus Armbruster }
3747e7d56d9SMarkus Armbruster 
3757e7d56d9SMarkus Armbruster /*
3767e7d56d9SMarkus Armbruster  * Return the BlockDriverState attached to @blk if any, else null.
3777e7d56d9SMarkus Armbruster  */
3787e7d56d9SMarkus Armbruster BlockDriverState *blk_bs(BlockBackend *blk)
3797e7d56d9SMarkus Armbruster {
380f21d96d0SKevin Wolf     return blk->root ? blk->root->bs : NULL;
3817e7d56d9SMarkus Armbruster }
3827e7d56d9SMarkus Armbruster 
3837e7d56d9SMarkus Armbruster /*
38418e46a03SMarkus Armbruster  * Return @blk's DriveInfo if any, else null.
38518e46a03SMarkus Armbruster  */
38618e46a03SMarkus Armbruster DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
38718e46a03SMarkus Armbruster {
38818e46a03SMarkus Armbruster     return blk->legacy_dinfo;
38918e46a03SMarkus Armbruster }
39018e46a03SMarkus Armbruster 
39118e46a03SMarkus Armbruster /*
39218e46a03SMarkus Armbruster  * Set @blk's DriveInfo to @dinfo, and return it.
39318e46a03SMarkus Armbruster  * @blk must not have a DriveInfo set already.
39418e46a03SMarkus Armbruster  * No other BlockBackend may have the same DriveInfo set.
39518e46a03SMarkus Armbruster  */
39618e46a03SMarkus Armbruster DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
39718e46a03SMarkus Armbruster {
39818e46a03SMarkus Armbruster     assert(!blk->legacy_dinfo);
39918e46a03SMarkus Armbruster     return blk->legacy_dinfo = dinfo;
40018e46a03SMarkus Armbruster }
40118e46a03SMarkus Armbruster 
40218e46a03SMarkus Armbruster /*
40318e46a03SMarkus Armbruster  * Return the BlockBackend with DriveInfo @dinfo.
40418e46a03SMarkus Armbruster  * It must exist.
40518e46a03SMarkus Armbruster  */
40618e46a03SMarkus Armbruster BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
40718e46a03SMarkus Armbruster {
40874d1b8fcSMax Reitz     BlockBackend *blk = NULL;
40918e46a03SMarkus Armbruster 
41074d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
41118e46a03SMarkus Armbruster         if (blk->legacy_dinfo == dinfo) {
41218e46a03SMarkus Armbruster             return blk;
41318e46a03SMarkus Armbruster         }
41418e46a03SMarkus Armbruster     }
41518e46a03SMarkus Armbruster     abort();
41618e46a03SMarkus Armbruster }
41718e46a03SMarkus Armbruster 
41818e46a03SMarkus Armbruster /*
419f2cd875dSKevin Wolf  * Returns a pointer to the publicly accessible fields of @blk.
420f2cd875dSKevin Wolf  */
421f2cd875dSKevin Wolf BlockBackendPublic *blk_get_public(BlockBackend *blk)
422f2cd875dSKevin Wolf {
423f2cd875dSKevin Wolf     return &blk->public;
424f2cd875dSKevin Wolf }
425f2cd875dSKevin Wolf 
426f2cd875dSKevin Wolf /*
427f2cd875dSKevin Wolf  * Returns a BlockBackend given the associated @public fields.
428f2cd875dSKevin Wolf  */
429f2cd875dSKevin Wolf BlockBackend *blk_by_public(BlockBackendPublic *public)
430f2cd875dSKevin Wolf {
431f2cd875dSKevin Wolf     return container_of(public, BlockBackend, public);
432f2cd875dSKevin Wolf }
433f2cd875dSKevin Wolf 
434f2cd875dSKevin Wolf /*
4351c95f7e1SMax Reitz  * Disassociates the currently associated BlockDriverState from @blk.
4361c95f7e1SMax Reitz  */
4371c95f7e1SMax Reitz void blk_remove_bs(BlockBackend *blk)
4381c95f7e1SMax Reitz {
439f21d96d0SKevin Wolf     assert(blk->root->bs->blk == blk);
44013855c6bSMax Reitz 
4413301f6c6SMax Reitz     notifier_list_notify(&blk->remove_bs_notifiers, blk);
4423301f6c6SMax Reitz 
4431c95f7e1SMax Reitz     blk_update_root_state(blk);
444*27ccdd52SKevin Wolf     if (blk->public.throttle_state) {
445a5614993SKevin Wolf         bdrv_io_limits_disable(blk->root->bs);
446a5614993SKevin Wolf     }
4471c95f7e1SMax Reitz 
448f21d96d0SKevin Wolf     blk->root->bs->blk = NULL;
449f21d96d0SKevin Wolf     bdrv_root_unref_child(blk->root);
450f21d96d0SKevin Wolf     blk->root = NULL;
4511c95f7e1SMax Reitz }
4521c95f7e1SMax Reitz 
4531c95f7e1SMax Reitz /*
4540c3c36d6SMax Reitz  * Associates a new BlockDriverState with @blk.
4550c3c36d6SMax Reitz  */
4560c3c36d6SMax Reitz void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
4570c3c36d6SMax Reitz {
458f21d96d0SKevin Wolf     assert(!blk->root && !bs->blk);
4590c3c36d6SMax Reitz     bdrv_ref(bs);
460f21d96d0SKevin Wolf     blk->root = bdrv_root_attach_child(bs, "root", &child_root);
4610c3c36d6SMax Reitz     bs->blk = blk;
4623301f6c6SMax Reitz 
4633301f6c6SMax Reitz     notifier_list_notify(&blk->insert_bs_notifiers, blk);
4640c3c36d6SMax Reitz }
4650c3c36d6SMax Reitz 
4660c3c36d6SMax Reitz /*
467a7f53e26SMarkus Armbruster  * Attach device model @dev to @blk.
468a7f53e26SMarkus Armbruster  * Return 0 on success, -EBUSY when a device model is attached already.
469a7f53e26SMarkus Armbruster  */
470a7f53e26SMarkus Armbruster int blk_attach_dev(BlockBackend *blk, void *dev)
471a7f53e26SMarkus Armbruster /* TODO change to DeviceState *dev when all users are qdevified */
472a7f53e26SMarkus Armbruster {
473a7f53e26SMarkus Armbruster     if (blk->dev) {
474a7f53e26SMarkus Armbruster         return -EBUSY;
475a7f53e26SMarkus Armbruster     }
47684ebe375SMarkus Armbruster     blk_ref(blk);
477a7f53e26SMarkus Armbruster     blk->dev = dev;
478373340b2SMax Reitz     blk_iostatus_reset(blk);
479a7f53e26SMarkus Armbruster     return 0;
480a7f53e26SMarkus Armbruster }
481a7f53e26SMarkus Armbruster 
482a7f53e26SMarkus Armbruster /*
483a7f53e26SMarkus Armbruster  * Attach device model @dev to @blk.
484a7f53e26SMarkus Armbruster  * @blk must not have a device model attached already.
485a7f53e26SMarkus Armbruster  * TODO qdevified devices don't use this, remove when devices are qdevified
486a7f53e26SMarkus Armbruster  */
487a7f53e26SMarkus Armbruster void blk_attach_dev_nofail(BlockBackend *blk, void *dev)
488a7f53e26SMarkus Armbruster {
489a7f53e26SMarkus Armbruster     if (blk_attach_dev(blk, dev) < 0) {
490a7f53e26SMarkus Armbruster         abort();
491a7f53e26SMarkus Armbruster     }
492a7f53e26SMarkus Armbruster }
493a7f53e26SMarkus Armbruster 
494a7f53e26SMarkus Armbruster /*
495a7f53e26SMarkus Armbruster  * Detach device model @dev from @blk.
496a7f53e26SMarkus Armbruster  * @dev must be currently attached to @blk.
497a7f53e26SMarkus Armbruster  */
498a7f53e26SMarkus Armbruster void blk_detach_dev(BlockBackend *blk, void *dev)
499a7f53e26SMarkus Armbruster /* TODO change to DeviceState *dev when all users are qdevified */
500a7f53e26SMarkus Armbruster {
501a7f53e26SMarkus Armbruster     assert(blk->dev == dev);
502a7f53e26SMarkus Armbruster     blk->dev = NULL;
503a7f53e26SMarkus Armbruster     blk->dev_ops = NULL;
504a7f53e26SMarkus Armbruster     blk->dev_opaque = NULL;
50568e9ec01SMax Reitz     blk->guest_block_size = 512;
50684ebe375SMarkus Armbruster     blk_unref(blk);
507a7f53e26SMarkus Armbruster }
508a7f53e26SMarkus Armbruster 
509a7f53e26SMarkus Armbruster /*
510a7f53e26SMarkus Armbruster  * Return the device model attached to @blk if any, else null.
511a7f53e26SMarkus Armbruster  */
512a7f53e26SMarkus Armbruster void *blk_get_attached_dev(BlockBackend *blk)
513a7f53e26SMarkus Armbruster /* TODO change to return DeviceState * when all users are qdevified */
514a7f53e26SMarkus Armbruster {
515a7f53e26SMarkus Armbruster     return blk->dev;
516a7f53e26SMarkus Armbruster }
517a7f53e26SMarkus Armbruster 
518a7f53e26SMarkus Armbruster /*
519a7f53e26SMarkus Armbruster  * Set @blk's device model callbacks to @ops.
520a7f53e26SMarkus Armbruster  * @opaque is the opaque argument to pass to the callbacks.
521a7f53e26SMarkus Armbruster  * This is for use by device models.
522a7f53e26SMarkus Armbruster  */
523a7f53e26SMarkus Armbruster void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
524a7f53e26SMarkus Armbruster                      void *opaque)
525a7f53e26SMarkus Armbruster {
526a7f53e26SMarkus Armbruster     blk->dev_ops = ops;
527a7f53e26SMarkus Armbruster     blk->dev_opaque = opaque;
528a7f53e26SMarkus Armbruster }
529a7f53e26SMarkus Armbruster 
530a7f53e26SMarkus Armbruster /*
531a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of media change.
532a7f53e26SMarkus Armbruster  * If @load is true, notify of media load.
533a7f53e26SMarkus Armbruster  * Else, notify of media eject.
534a7f53e26SMarkus Armbruster  * Also send DEVICE_TRAY_MOVED events as appropriate.
535a7f53e26SMarkus Armbruster  */
536a7f53e26SMarkus Armbruster void blk_dev_change_media_cb(BlockBackend *blk, bool load)
537a7f53e26SMarkus Armbruster {
538a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->change_media_cb) {
539f1f57066SMax Reitz         bool tray_was_open, tray_is_open;
540a7f53e26SMarkus Armbruster 
541f1f57066SMax Reitz         tray_was_open = blk_dev_is_tray_open(blk);
542a7f53e26SMarkus Armbruster         blk->dev_ops->change_media_cb(blk->dev_opaque, load);
543f1f57066SMax Reitz         tray_is_open = blk_dev_is_tray_open(blk);
544f1f57066SMax Reitz 
545f1f57066SMax Reitz         if (tray_was_open != tray_is_open) {
546f1f57066SMax Reitz             qapi_event_send_device_tray_moved(blk_name(blk), tray_is_open,
547f1f57066SMax Reitz                                               &error_abort);
548a7f53e26SMarkus Armbruster         }
549a7f53e26SMarkus Armbruster     }
550a7f53e26SMarkus Armbruster }
551a7f53e26SMarkus Armbruster 
552a7f53e26SMarkus Armbruster /*
553a7f53e26SMarkus Armbruster  * Does @blk's attached device model have removable media?
554a7f53e26SMarkus Armbruster  * %true if no device model is attached.
555a7f53e26SMarkus Armbruster  */
556a7f53e26SMarkus Armbruster bool blk_dev_has_removable_media(BlockBackend *blk)
557a7f53e26SMarkus Armbruster {
558a7f53e26SMarkus Armbruster     return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
559a7f53e26SMarkus Armbruster }
560a7f53e26SMarkus Armbruster 
561a7f53e26SMarkus Armbruster /*
5628f3a73bcSMax Reitz  * Does @blk's attached device model have a tray?
5638f3a73bcSMax Reitz  */
5648f3a73bcSMax Reitz bool blk_dev_has_tray(BlockBackend *blk)
5658f3a73bcSMax Reitz {
5668f3a73bcSMax Reitz     return blk->dev_ops && blk->dev_ops->is_tray_open;
5678f3a73bcSMax Reitz }
5688f3a73bcSMax Reitz 
5698f3a73bcSMax Reitz /*
570a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a media eject request.
571a7f53e26SMarkus Armbruster  * If @force is true, the medium is about to be yanked out forcefully.
572a7f53e26SMarkus Armbruster  */
573a7f53e26SMarkus Armbruster void blk_dev_eject_request(BlockBackend *blk, bool force)
574a7f53e26SMarkus Armbruster {
575a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->eject_request_cb) {
576a7f53e26SMarkus Armbruster         blk->dev_ops->eject_request_cb(blk->dev_opaque, force);
577a7f53e26SMarkus Armbruster     }
578a7f53e26SMarkus Armbruster }
579a7f53e26SMarkus Armbruster 
580a7f53e26SMarkus Armbruster /*
581a7f53e26SMarkus Armbruster  * Does @blk's attached device model have a tray, and is it open?
582a7f53e26SMarkus Armbruster  */
583a7f53e26SMarkus Armbruster bool blk_dev_is_tray_open(BlockBackend *blk)
584a7f53e26SMarkus Armbruster {
5858f3a73bcSMax Reitz     if (blk_dev_has_tray(blk)) {
586a7f53e26SMarkus Armbruster         return blk->dev_ops->is_tray_open(blk->dev_opaque);
587a7f53e26SMarkus Armbruster     }
588a7f53e26SMarkus Armbruster     return false;
589a7f53e26SMarkus Armbruster }
590a7f53e26SMarkus Armbruster 
591a7f53e26SMarkus Armbruster /*
592a7f53e26SMarkus Armbruster  * Does @blk's attached device model have the medium locked?
593a7f53e26SMarkus Armbruster  * %false if the device model has no such lock.
594a7f53e26SMarkus Armbruster  */
595a7f53e26SMarkus Armbruster bool blk_dev_is_medium_locked(BlockBackend *blk)
596a7f53e26SMarkus Armbruster {
597a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->is_medium_locked) {
598a7f53e26SMarkus Armbruster         return blk->dev_ops->is_medium_locked(blk->dev_opaque);
599a7f53e26SMarkus Armbruster     }
600a7f53e26SMarkus Armbruster     return false;
601a7f53e26SMarkus Armbruster }
602a7f53e26SMarkus Armbruster 
603a7f53e26SMarkus Armbruster /*
604a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a backend size change.
605a7f53e26SMarkus Armbruster  */
606a7f53e26SMarkus Armbruster void blk_dev_resize_cb(BlockBackend *blk)
607a7f53e26SMarkus Armbruster {
608a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->resize_cb) {
609a7f53e26SMarkus Armbruster         blk->dev_ops->resize_cb(blk->dev_opaque);
610a7f53e26SMarkus Armbruster     }
611a7f53e26SMarkus Armbruster }
612a7f53e26SMarkus Armbruster 
6134be74634SMarkus Armbruster void blk_iostatus_enable(BlockBackend *blk)
6144be74634SMarkus Armbruster {
615373340b2SMax Reitz     blk->iostatus_enabled = true;
616373340b2SMax Reitz     blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
617373340b2SMax Reitz }
618373340b2SMax Reitz 
619373340b2SMax Reitz /* The I/O status is only enabled if the drive explicitly
620373340b2SMax Reitz  * enables it _and_ the VM is configured to stop on errors */
621373340b2SMax Reitz bool blk_iostatus_is_enabled(const BlockBackend *blk)
622373340b2SMax Reitz {
623373340b2SMax Reitz     return (blk->iostatus_enabled &&
624373340b2SMax Reitz            (blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
625373340b2SMax Reitz             blk->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
626373340b2SMax Reitz             blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
627373340b2SMax Reitz }
628373340b2SMax Reitz 
629373340b2SMax Reitz BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
630373340b2SMax Reitz {
631373340b2SMax Reitz     return blk->iostatus;
632373340b2SMax Reitz }
633373340b2SMax Reitz 
634373340b2SMax Reitz void blk_iostatus_disable(BlockBackend *blk)
635373340b2SMax Reitz {
636373340b2SMax Reitz     blk->iostatus_enabled = false;
637373340b2SMax Reitz }
638373340b2SMax Reitz 
639373340b2SMax Reitz void blk_iostatus_reset(BlockBackend *blk)
640373340b2SMax Reitz {
641373340b2SMax Reitz     if (blk_iostatus_is_enabled(blk)) {
642f21d96d0SKevin Wolf         BlockDriverState *bs = blk_bs(blk);
643373340b2SMax Reitz         blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
644f21d96d0SKevin Wolf         if (bs && bs->job) {
645f21d96d0SKevin Wolf             block_job_iostatus_reset(bs->job);
646373340b2SMax Reitz         }
647373340b2SMax Reitz     }
648373340b2SMax Reitz }
649373340b2SMax Reitz 
650373340b2SMax Reitz void blk_iostatus_set_err(BlockBackend *blk, int error)
651373340b2SMax Reitz {
652373340b2SMax Reitz     assert(blk_iostatus_is_enabled(blk));
653373340b2SMax Reitz     if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
654373340b2SMax Reitz         blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
655373340b2SMax Reitz                                           BLOCK_DEVICE_IO_STATUS_FAILED;
656373340b2SMax Reitz     }
6574be74634SMarkus Armbruster }
6584be74634SMarkus Armbruster 
659c10c9d96SKevin Wolf void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow)
660c10c9d96SKevin Wolf {
661c10c9d96SKevin Wolf     blk->allow_write_beyond_eof = allow;
662c10c9d96SKevin Wolf }
663c10c9d96SKevin Wolf 
664e7f7d676SMax Reitz static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
665e7f7d676SMax Reitz                                   size_t size)
666e7f7d676SMax Reitz {
667e7f7d676SMax Reitz     int64_t len;
668e7f7d676SMax Reitz 
669e7f7d676SMax Reitz     if (size > INT_MAX) {
670e7f7d676SMax Reitz         return -EIO;
671e7f7d676SMax Reitz     }
672e7f7d676SMax Reitz 
673c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
674e7f7d676SMax Reitz         return -ENOMEDIUM;
675e7f7d676SMax Reitz     }
676e7f7d676SMax Reitz 
677c10c9d96SKevin Wolf     if (offset < 0) {
678c10c9d96SKevin Wolf         return -EIO;
679c10c9d96SKevin Wolf     }
680c10c9d96SKevin Wolf 
681c10c9d96SKevin Wolf     if (!blk->allow_write_beyond_eof) {
682e7f7d676SMax Reitz         len = blk_getlength(blk);
683e7f7d676SMax Reitz         if (len < 0) {
684e7f7d676SMax Reitz             return len;
685e7f7d676SMax Reitz         }
686e7f7d676SMax Reitz 
687e7f7d676SMax Reitz         if (offset > len || len - offset < size) {
688e7f7d676SMax Reitz             return -EIO;
689e7f7d676SMax Reitz         }
690c10c9d96SKevin Wolf     }
691e7f7d676SMax Reitz 
692e7f7d676SMax Reitz     return 0;
693e7f7d676SMax Reitz }
694e7f7d676SMax Reitz 
695e7f7d676SMax Reitz static int blk_check_request(BlockBackend *blk, int64_t sector_num,
696e7f7d676SMax Reitz                              int nb_sectors)
697e7f7d676SMax Reitz {
698e7f7d676SMax Reitz     if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
699e7f7d676SMax Reitz         return -EIO;
700e7f7d676SMax Reitz     }
701e7f7d676SMax Reitz 
702e7f7d676SMax Reitz     if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
703e7f7d676SMax Reitz         return -EIO;
704e7f7d676SMax Reitz     }
705e7f7d676SMax Reitz 
706e7f7d676SMax Reitz     return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
707e7f7d676SMax Reitz                                   nb_sectors * BDRV_SECTOR_SIZE);
708e7f7d676SMax Reitz }
709e7f7d676SMax Reitz 
7101bf1cbc9SKevin Wolf static int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
7111bf1cbc9SKevin Wolf                                       unsigned int bytes, QEMUIOVector *qiov,
7121bf1cbc9SKevin Wolf                                       BdrvRequestFlags flags)
7134be74634SMarkus Armbruster {
7141bf1cbc9SKevin Wolf     int ret = blk_check_byte_request(blk, offset, bytes);
715e7f7d676SMax Reitz     if (ret < 0) {
716e7f7d676SMax Reitz         return ret;
717e7f7d676SMax Reitz     }
718e7f7d676SMax Reitz 
719cab3a356SKevin Wolf     return bdrv_co_preadv(blk_bs(blk), offset, bytes, qiov, flags);
7201bf1cbc9SKevin Wolf }
7211bf1cbc9SKevin Wolf 
722a8823a3bSKevin Wolf static int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
723a8823a3bSKevin Wolf                                       unsigned int bytes, QEMUIOVector *qiov,
724a8823a3bSKevin Wolf                                       BdrvRequestFlags flags)
725a8823a3bSKevin Wolf {
726bfd18d1eSKevin Wolf     int ret;
727bfd18d1eSKevin Wolf 
728bfd18d1eSKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
729a8823a3bSKevin Wolf     if (ret < 0) {
730a8823a3bSKevin Wolf         return ret;
731a8823a3bSKevin Wolf     }
732a8823a3bSKevin Wolf 
733bfd18d1eSKevin Wolf     if (!blk->enable_write_cache) {
734bfd18d1eSKevin Wolf         flags |= BDRV_REQ_FUA;
735bfd18d1eSKevin Wolf     }
736bfd18d1eSKevin Wolf 
737cab3a356SKevin Wolf     return bdrv_co_pwritev(blk_bs(blk), offset, bytes, qiov, flags);
738a8823a3bSKevin Wolf }
739a8823a3bSKevin Wolf 
7401bf1cbc9SKevin Wolf typedef struct BlkRwCo {
7411bf1cbc9SKevin Wolf     BlockBackend *blk;
7421bf1cbc9SKevin Wolf     int64_t offset;
7431bf1cbc9SKevin Wolf     QEMUIOVector *qiov;
7441bf1cbc9SKevin Wolf     int ret;
7451bf1cbc9SKevin Wolf     BdrvRequestFlags flags;
7461bf1cbc9SKevin Wolf } BlkRwCo;
7471bf1cbc9SKevin Wolf 
7481bf1cbc9SKevin Wolf static void blk_read_entry(void *opaque)
7491bf1cbc9SKevin Wolf {
7501bf1cbc9SKevin Wolf     BlkRwCo *rwco = opaque;
7511bf1cbc9SKevin Wolf 
7521bf1cbc9SKevin Wolf     rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, rwco->qiov->size,
7531bf1cbc9SKevin Wolf                               rwco->qiov, rwco->flags);
7541bf1cbc9SKevin Wolf }
7551bf1cbc9SKevin Wolf 
756a8823a3bSKevin Wolf static void blk_write_entry(void *opaque)
757a8823a3bSKevin Wolf {
758a8823a3bSKevin Wolf     BlkRwCo *rwco = opaque;
759a8823a3bSKevin Wolf 
760a8823a3bSKevin Wolf     rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, rwco->qiov->size,
761a8823a3bSKevin Wolf                                rwco->qiov, rwco->flags);
762a8823a3bSKevin Wolf }
763a8823a3bSKevin Wolf 
764a55d3fbaSKevin Wolf static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
765a55d3fbaSKevin Wolf                    int64_t bytes, CoroutineEntry co_entry,
766fc1453cdSKevin Wolf                    BdrvRequestFlags flags)
7671bf1cbc9SKevin Wolf {
7681bf1cbc9SKevin Wolf     AioContext *aio_context;
7691bf1cbc9SKevin Wolf     QEMUIOVector qiov;
7701bf1cbc9SKevin Wolf     struct iovec iov;
7711bf1cbc9SKevin Wolf     Coroutine *co;
7721bf1cbc9SKevin Wolf     BlkRwCo rwco;
7731bf1cbc9SKevin Wolf 
7741bf1cbc9SKevin Wolf     iov = (struct iovec) {
7751bf1cbc9SKevin Wolf         .iov_base = buf,
776a55d3fbaSKevin Wolf         .iov_len = bytes,
7771bf1cbc9SKevin Wolf     };
7781bf1cbc9SKevin Wolf     qemu_iovec_init_external(&qiov, &iov, 1);
7791bf1cbc9SKevin Wolf 
7801bf1cbc9SKevin Wolf     rwco = (BlkRwCo) {
7811bf1cbc9SKevin Wolf         .blk    = blk,
782a55d3fbaSKevin Wolf         .offset = offset,
7831bf1cbc9SKevin Wolf         .qiov   = &qiov,
784fc1453cdSKevin Wolf         .flags  = flags,
7851bf1cbc9SKevin Wolf         .ret    = NOT_DONE,
7861bf1cbc9SKevin Wolf     };
7871bf1cbc9SKevin Wolf 
788a8823a3bSKevin Wolf     co = qemu_coroutine_create(co_entry);
7891bf1cbc9SKevin Wolf     qemu_coroutine_enter(co, &rwco);
7901bf1cbc9SKevin Wolf 
7911bf1cbc9SKevin Wolf     aio_context = blk_get_aio_context(blk);
7921bf1cbc9SKevin Wolf     while (rwco.ret == NOT_DONE) {
7931bf1cbc9SKevin Wolf         aio_poll(aio_context, true);
7941bf1cbc9SKevin Wolf     }
7951bf1cbc9SKevin Wolf 
7961bf1cbc9SKevin Wolf     return rwco.ret;
7974be74634SMarkus Armbruster }
7984be74634SMarkus Armbruster 
799b7d17f9fSEric Blake int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf,
800b7d17f9fSEric Blake                           int count)
8014be74634SMarkus Armbruster {
8025bd51196SKevin Wolf     int ret;
8035bd51196SKevin Wolf 
804b7d17f9fSEric Blake     ret = blk_check_byte_request(blk, offset, count);
805e7f7d676SMax Reitz     if (ret < 0) {
806e7f7d676SMax Reitz         return ret;
807e7f7d676SMax Reitz     }
808e7f7d676SMax Reitz 
809*27ccdd52SKevin Wolf     bdrv_no_throttling_begin(blk_bs(blk));
810b7d17f9fSEric Blake     ret = blk_pread(blk, offset, buf, count);
811*27ccdd52SKevin Wolf     bdrv_no_throttling_end(blk_bs(blk));
8125bd51196SKevin Wolf     return ret;
8134be74634SMarkus Armbruster }
8144be74634SMarkus Armbruster 
815983a1600SEric Blake int blk_write_zeroes(BlockBackend *blk, int64_t offset,
816983a1600SEric Blake                      int count, BdrvRequestFlags flags)
8170df89e8eSKevin Wolf {
818983a1600SEric Blake     return blk_prw(blk, offset, NULL, count, blk_write_entry,
81916aaf975SKevin Wolf                    flags | BDRV_REQ_ZERO_WRITE);
8200df89e8eSKevin Wolf }
8210df89e8eSKevin Wolf 
822e7f7d676SMax Reitz static void error_callback_bh(void *opaque)
823e7f7d676SMax Reitz {
824e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb = opaque;
825e7f7d676SMax Reitz     qemu_bh_delete(acb->bh);
826e7f7d676SMax Reitz     acb->common.cb(acb->common.opaque, acb->ret);
827e7f7d676SMax Reitz     qemu_aio_unref(acb);
828e7f7d676SMax Reitz }
829e7f7d676SMax Reitz 
830ca78ecfaSPeter Lieven BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
831ca78ecfaSPeter Lieven                                   BlockCompletionFunc *cb,
832e7f7d676SMax Reitz                                   void *opaque, int ret)
833e7f7d676SMax Reitz {
834e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb;
835e7f7d676SMax Reitz     QEMUBH *bh;
836e7f7d676SMax Reitz 
837e7f7d676SMax Reitz     acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
8384981bdecSMax Reitz     acb->blk = blk;
839e7f7d676SMax Reitz     acb->ret = ret;
840e7f7d676SMax Reitz 
841e7f7d676SMax Reitz     bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb);
842e7f7d676SMax Reitz     acb->bh = bh;
843e7f7d676SMax Reitz     qemu_bh_schedule(bh);
844e7f7d676SMax Reitz 
845e7f7d676SMax Reitz     return &acb->common;
846e7f7d676SMax Reitz }
847e7f7d676SMax Reitz 
84857d6a428SKevin Wolf typedef struct BlkAioEmAIOCB {
84957d6a428SKevin Wolf     BlockAIOCB common;
85057d6a428SKevin Wolf     BlkRwCo rwco;
8517fa84cd8SKevin Wolf     int bytes;
85257d6a428SKevin Wolf     bool has_returned;
85357d6a428SKevin Wolf     QEMUBH* bh;
85457d6a428SKevin Wolf } BlkAioEmAIOCB;
85557d6a428SKevin Wolf 
85657d6a428SKevin Wolf static const AIOCBInfo blk_aio_em_aiocb_info = {
85757d6a428SKevin Wolf     .aiocb_size         = sizeof(BlkAioEmAIOCB),
85857d6a428SKevin Wolf };
85957d6a428SKevin Wolf 
86057d6a428SKevin Wolf static void blk_aio_complete(BlkAioEmAIOCB *acb)
86157d6a428SKevin Wolf {
86257d6a428SKevin Wolf     if (acb->bh) {
86357d6a428SKevin Wolf         assert(acb->has_returned);
86457d6a428SKevin Wolf         qemu_bh_delete(acb->bh);
86557d6a428SKevin Wolf     }
86657d6a428SKevin Wolf     if (acb->has_returned) {
86757d6a428SKevin Wolf         acb->common.cb(acb->common.opaque, acb->rwco.ret);
86857d6a428SKevin Wolf         qemu_aio_unref(acb);
86957d6a428SKevin Wolf     }
87057d6a428SKevin Wolf }
87157d6a428SKevin Wolf 
87257d6a428SKevin Wolf static void blk_aio_complete_bh(void *opaque)
87357d6a428SKevin Wolf {
87457d6a428SKevin Wolf     blk_aio_complete(opaque);
87557d6a428SKevin Wolf }
87657d6a428SKevin Wolf 
8777fa84cd8SKevin Wolf static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
87857d6a428SKevin Wolf                                 QEMUIOVector *qiov, CoroutineEntry co_entry,
87957d6a428SKevin Wolf                                 BdrvRequestFlags flags,
88057d6a428SKevin Wolf                                 BlockCompletionFunc *cb, void *opaque)
88157d6a428SKevin Wolf {
88257d6a428SKevin Wolf     BlkAioEmAIOCB *acb;
88357d6a428SKevin Wolf     Coroutine *co;
88457d6a428SKevin Wolf 
88557d6a428SKevin Wolf     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
88657d6a428SKevin Wolf     acb->rwco = (BlkRwCo) {
88757d6a428SKevin Wolf         .blk    = blk,
88857d6a428SKevin Wolf         .offset = offset,
88957d6a428SKevin Wolf         .qiov   = qiov,
89057d6a428SKevin Wolf         .flags  = flags,
89157d6a428SKevin Wolf         .ret    = NOT_DONE,
89257d6a428SKevin Wolf     };
8937fa84cd8SKevin Wolf     acb->bytes = bytes;
89457d6a428SKevin Wolf     acb->bh = NULL;
89557d6a428SKevin Wolf     acb->has_returned = false;
89657d6a428SKevin Wolf 
89757d6a428SKevin Wolf     co = qemu_coroutine_create(co_entry);
89857d6a428SKevin Wolf     qemu_coroutine_enter(co, acb);
89957d6a428SKevin Wolf 
90057d6a428SKevin Wolf     acb->has_returned = true;
90157d6a428SKevin Wolf     if (acb->rwco.ret != NOT_DONE) {
90257d6a428SKevin Wolf         acb->bh = aio_bh_new(blk_get_aio_context(blk), blk_aio_complete_bh, acb);
90357d6a428SKevin Wolf         qemu_bh_schedule(acb->bh);
90457d6a428SKevin Wolf     }
90557d6a428SKevin Wolf 
90657d6a428SKevin Wolf     return &acb->common;
90757d6a428SKevin Wolf }
90857d6a428SKevin Wolf 
90957d6a428SKevin Wolf static void blk_aio_read_entry(void *opaque)
91057d6a428SKevin Wolf {
91157d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
91257d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
91357d6a428SKevin Wolf 
9147fa84cd8SKevin Wolf     assert(rwco->qiov->size == acb->bytes);
9157fa84cd8SKevin Wolf     rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, acb->bytes,
91657d6a428SKevin Wolf                               rwco->qiov, rwco->flags);
91757d6a428SKevin Wolf     blk_aio_complete(acb);
91857d6a428SKevin Wolf }
91957d6a428SKevin Wolf 
92057d6a428SKevin Wolf static void blk_aio_write_entry(void *opaque)
92157d6a428SKevin Wolf {
92257d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
92357d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
92457d6a428SKevin Wolf 
9257fa84cd8SKevin Wolf     assert(!rwco->qiov || rwco->qiov->size == acb->bytes);
9267fa84cd8SKevin Wolf     rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, acb->bytes,
92757d6a428SKevin Wolf                                rwco->qiov, rwco->flags);
92857d6a428SKevin Wolf     blk_aio_complete(acb);
92957d6a428SKevin Wolf }
93057d6a428SKevin Wolf 
931983a1600SEric Blake BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t offset,
932983a1600SEric Blake                                  int count, BdrvRequestFlags flags,
9334be74634SMarkus Armbruster                                  BlockCompletionFunc *cb, void *opaque)
9344be74634SMarkus Armbruster {
935983a1600SEric Blake     return blk_aio_prwv(blk, offset, count, NULL, blk_aio_write_entry,
936983a1600SEric Blake                         flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
9374be74634SMarkus Armbruster }
9384be74634SMarkus Armbruster 
9394be74634SMarkus Armbruster int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
9404be74634SMarkus Armbruster {
941a55d3fbaSKevin Wolf     int ret = blk_prw(blk, offset, buf, count, blk_read_entry, 0);
942e7f7d676SMax Reitz     if (ret < 0) {
943e7f7d676SMax Reitz         return ret;
944e7f7d676SMax Reitz     }
945a55d3fbaSKevin Wolf     return count;
9464be74634SMarkus Armbruster }
9474be74634SMarkus Armbruster 
9488341f00dSEric Blake int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count,
9498341f00dSEric Blake                BdrvRequestFlags flags)
9504be74634SMarkus Armbruster {
9518341f00dSEric Blake     int ret = blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
9528341f00dSEric Blake                       flags);
953e7f7d676SMax Reitz     if (ret < 0) {
954e7f7d676SMax Reitz         return ret;
955e7f7d676SMax Reitz     }
956a55d3fbaSKevin Wolf     return count;
9574be74634SMarkus Armbruster }
9584be74634SMarkus Armbruster 
9594be74634SMarkus Armbruster int64_t blk_getlength(BlockBackend *blk)
9604be74634SMarkus Armbruster {
961c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
962c09ba36cSMax Reitz         return -ENOMEDIUM;
963c09ba36cSMax Reitz     }
964c09ba36cSMax Reitz 
965f21d96d0SKevin Wolf     return bdrv_getlength(blk_bs(blk));
9664be74634SMarkus Armbruster }
9674be74634SMarkus Armbruster 
9684be74634SMarkus Armbruster void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
9694be74634SMarkus Armbruster {
970f21d96d0SKevin Wolf     if (!blk_bs(blk)) {
971a46fc9c9SMax Reitz         *nb_sectors_ptr = 0;
972a46fc9c9SMax Reitz     } else {
973f21d96d0SKevin Wolf         bdrv_get_geometry(blk_bs(blk), nb_sectors_ptr);
9744be74634SMarkus Armbruster     }
975a46fc9c9SMax Reitz }
9764be74634SMarkus Armbruster 
9771ef01253SMax Reitz int64_t blk_nb_sectors(BlockBackend *blk)
9781ef01253SMax Reitz {
979c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
980c09ba36cSMax Reitz         return -ENOMEDIUM;
981c09ba36cSMax Reitz     }
982c09ba36cSMax Reitz 
983f21d96d0SKevin Wolf     return bdrv_nb_sectors(blk_bs(blk));
9841ef01253SMax Reitz }
9851ef01253SMax Reitz 
98660cb2fa7SEric Blake BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
98760cb2fa7SEric Blake                            QEMUIOVector *qiov, BdrvRequestFlags flags,
98860cb2fa7SEric Blake                            BlockCompletionFunc *cb, void *opaque)
98960cb2fa7SEric Blake {
99060cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
99160cb2fa7SEric Blake                         blk_aio_read_entry, flags, cb, opaque);
99260cb2fa7SEric Blake }
99360cb2fa7SEric Blake 
99460cb2fa7SEric Blake BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
99560cb2fa7SEric Blake                             QEMUIOVector *qiov, BdrvRequestFlags flags,
99660cb2fa7SEric Blake                             BlockCompletionFunc *cb, void *opaque)
99760cb2fa7SEric Blake {
99860cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
99960cb2fa7SEric Blake                         blk_aio_write_entry, flags, cb, opaque);
100060cb2fa7SEric Blake }
100160cb2fa7SEric Blake 
10024be74634SMarkus Armbruster BlockAIOCB *blk_aio_flush(BlockBackend *blk,
10034be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
10044be74634SMarkus Armbruster {
1005c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1006ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
1007c09ba36cSMax Reitz     }
1008c09ba36cSMax Reitz 
1009f21d96d0SKevin Wolf     return bdrv_aio_flush(blk_bs(blk), cb, opaque);
10104be74634SMarkus Armbruster }
10114be74634SMarkus Armbruster 
10124be74634SMarkus Armbruster BlockAIOCB *blk_aio_discard(BlockBackend *blk,
10134be74634SMarkus Armbruster                             int64_t sector_num, int nb_sectors,
10144be74634SMarkus Armbruster                             BlockCompletionFunc *cb, void *opaque)
10154be74634SMarkus Armbruster {
1016e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1017e7f7d676SMax Reitz     if (ret < 0) {
1018ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, ret);
1019e7f7d676SMax Reitz     }
1020e7f7d676SMax Reitz 
1021f21d96d0SKevin Wolf     return bdrv_aio_discard(blk_bs(blk), sector_num, nb_sectors, cb, opaque);
10224be74634SMarkus Armbruster }
10234be74634SMarkus Armbruster 
10244be74634SMarkus Armbruster void blk_aio_cancel(BlockAIOCB *acb)
10254be74634SMarkus Armbruster {
10264be74634SMarkus Armbruster     bdrv_aio_cancel(acb);
10274be74634SMarkus Armbruster }
10284be74634SMarkus Armbruster 
10294be74634SMarkus Armbruster void blk_aio_cancel_async(BlockAIOCB *acb)
10304be74634SMarkus Armbruster {
10314be74634SMarkus Armbruster     bdrv_aio_cancel_async(acb);
10324be74634SMarkus Armbruster }
10334be74634SMarkus Armbruster 
10344be74634SMarkus Armbruster int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs)
10354be74634SMarkus Armbruster {
1036e7f7d676SMax Reitz     int i, ret;
1037e7f7d676SMax Reitz 
1038e7f7d676SMax Reitz     for (i = 0; i < num_reqs; i++) {
1039e7f7d676SMax Reitz         ret = blk_check_request(blk, reqs[i].sector, reqs[i].nb_sectors);
1040e7f7d676SMax Reitz         if (ret < 0) {
1041e7f7d676SMax Reitz             return ret;
1042e7f7d676SMax Reitz         }
1043e7f7d676SMax Reitz     }
1044e7f7d676SMax Reitz 
1045f21d96d0SKevin Wolf     return bdrv_aio_multiwrite(blk_bs(blk), reqs, num_reqs);
10464be74634SMarkus Armbruster }
10474be74634SMarkus Armbruster 
10484be74634SMarkus Armbruster int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
10494be74634SMarkus Armbruster {
1050c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1051c09ba36cSMax Reitz         return -ENOMEDIUM;
1052c09ba36cSMax Reitz     }
1053c09ba36cSMax Reitz 
1054f21d96d0SKevin Wolf     return bdrv_ioctl(blk_bs(blk), req, buf);
10554be74634SMarkus Armbruster }
10564be74634SMarkus Armbruster 
10574be74634SMarkus Armbruster BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
10584be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
10594be74634SMarkus Armbruster {
1060c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1061ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
1062c09ba36cSMax Reitz     }
1063c09ba36cSMax Reitz 
1064f21d96d0SKevin Wolf     return bdrv_aio_ioctl(blk_bs(blk), req, buf, cb, opaque);
10654be74634SMarkus Armbruster }
10664be74634SMarkus Armbruster 
10672bb0dce7SMax Reitz int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
10682bb0dce7SMax Reitz {
1069e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1070e7f7d676SMax Reitz     if (ret < 0) {
1071e7f7d676SMax Reitz         return ret;
1072e7f7d676SMax Reitz     }
1073e7f7d676SMax Reitz 
1074f21d96d0SKevin Wolf     return bdrv_co_discard(blk_bs(blk), sector_num, nb_sectors);
10752bb0dce7SMax Reitz }
10762bb0dce7SMax Reitz 
10772bb0dce7SMax Reitz int blk_co_flush(BlockBackend *blk)
10782bb0dce7SMax Reitz {
1079c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1080c09ba36cSMax Reitz         return -ENOMEDIUM;
1081c09ba36cSMax Reitz     }
1082c09ba36cSMax Reitz 
1083f21d96d0SKevin Wolf     return bdrv_co_flush(blk_bs(blk));
10842bb0dce7SMax Reitz }
10852bb0dce7SMax Reitz 
10864be74634SMarkus Armbruster int blk_flush(BlockBackend *blk)
10874be74634SMarkus Armbruster {
1088c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1089c09ba36cSMax Reitz         return -ENOMEDIUM;
1090c09ba36cSMax Reitz     }
1091c09ba36cSMax Reitz 
1092f21d96d0SKevin Wolf     return bdrv_flush(blk_bs(blk));
10934be74634SMarkus Armbruster }
10944be74634SMarkus Armbruster 
109597b0385aSAlexander Yarygin void blk_drain(BlockBackend *blk)
109697b0385aSAlexander Yarygin {
1097f21d96d0SKevin Wolf     if (blk_bs(blk)) {
1098f21d96d0SKevin Wolf         bdrv_drain(blk_bs(blk));
109997b0385aSAlexander Yarygin     }
1100a46fc9c9SMax Reitz }
110197b0385aSAlexander Yarygin 
11024be74634SMarkus Armbruster void blk_drain_all(void)
11034be74634SMarkus Armbruster {
11044be74634SMarkus Armbruster     bdrv_drain_all();
11054be74634SMarkus Armbruster }
11064be74634SMarkus Armbruster 
1107373340b2SMax Reitz void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
1108373340b2SMax Reitz                       BlockdevOnError on_write_error)
1109373340b2SMax Reitz {
1110373340b2SMax Reitz     blk->on_read_error = on_read_error;
1111373340b2SMax Reitz     blk->on_write_error = on_write_error;
1112373340b2SMax Reitz }
1113373340b2SMax Reitz 
11144be74634SMarkus Armbruster BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
11154be74634SMarkus Armbruster {
1116373340b2SMax Reitz     return is_read ? blk->on_read_error : blk->on_write_error;
11174be74634SMarkus Armbruster }
11184be74634SMarkus Armbruster 
11194be74634SMarkus Armbruster BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
11204be74634SMarkus Armbruster                                       int error)
11214be74634SMarkus Armbruster {
1122373340b2SMax Reitz     BlockdevOnError on_err = blk_get_on_error(blk, is_read);
1123373340b2SMax Reitz 
1124373340b2SMax Reitz     switch (on_err) {
1125373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_ENOSPC:
1126373340b2SMax Reitz         return (error == ENOSPC) ?
1127373340b2SMax Reitz                BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
1128373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_STOP:
1129373340b2SMax Reitz         return BLOCK_ERROR_ACTION_STOP;
1130373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_REPORT:
1131373340b2SMax Reitz         return BLOCK_ERROR_ACTION_REPORT;
1132373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_IGNORE:
1133373340b2SMax Reitz         return BLOCK_ERROR_ACTION_IGNORE;
1134373340b2SMax Reitz     default:
1135373340b2SMax Reitz         abort();
1136373340b2SMax Reitz     }
11374be74634SMarkus Armbruster }
11384be74634SMarkus Armbruster 
1139373340b2SMax Reitz static void send_qmp_error_event(BlockBackend *blk,
1140373340b2SMax Reitz                                  BlockErrorAction action,
1141373340b2SMax Reitz                                  bool is_read, int error)
1142373340b2SMax Reitz {
1143373340b2SMax Reitz     IoOperationType optype;
1144373340b2SMax Reitz 
1145373340b2SMax Reitz     optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
1146373340b2SMax Reitz     qapi_event_send_block_io_error(blk_name(blk), optype, action,
1147373340b2SMax Reitz                                    blk_iostatus_is_enabled(blk),
1148373340b2SMax Reitz                                    error == ENOSPC, strerror(error),
1149373340b2SMax Reitz                                    &error_abort);
1150373340b2SMax Reitz }
1151373340b2SMax Reitz 
1152373340b2SMax Reitz /* This is done by device models because, while the block layer knows
1153373340b2SMax Reitz  * about the error, it does not know whether an operation comes from
1154373340b2SMax Reitz  * the device or the block layer (from a job, for example).
1155373340b2SMax Reitz  */
11564be74634SMarkus Armbruster void blk_error_action(BlockBackend *blk, BlockErrorAction action,
11574be74634SMarkus Armbruster                       bool is_read, int error)
11584be74634SMarkus Armbruster {
1159373340b2SMax Reitz     assert(error >= 0);
1160373340b2SMax Reitz 
1161373340b2SMax Reitz     if (action == BLOCK_ERROR_ACTION_STOP) {
1162373340b2SMax Reitz         /* First set the iostatus, so that "info block" returns an iostatus
1163373340b2SMax Reitz          * that matches the events raised so far (an additional error iostatus
1164373340b2SMax Reitz          * is fine, but not a lost one).
1165373340b2SMax Reitz          */
1166373340b2SMax Reitz         blk_iostatus_set_err(blk, error);
1167373340b2SMax Reitz 
1168373340b2SMax Reitz         /* Then raise the request to stop the VM and the event.
1169373340b2SMax Reitz          * qemu_system_vmstop_request_prepare has two effects.  First,
1170373340b2SMax Reitz          * it ensures that the STOP event always comes after the
1171373340b2SMax Reitz          * BLOCK_IO_ERROR event.  Second, it ensures that even if management
1172373340b2SMax Reitz          * can observe the STOP event and do a "cont" before the STOP
1173373340b2SMax Reitz          * event is issued, the VM will not stop.  In this case, vm_start()
1174373340b2SMax Reitz          * also ensures that the STOP/RESUME pair of events is emitted.
1175373340b2SMax Reitz          */
1176373340b2SMax Reitz         qemu_system_vmstop_request_prepare();
1177373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
1178373340b2SMax Reitz         qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
1179373340b2SMax Reitz     } else {
1180373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
1181373340b2SMax Reitz     }
11824be74634SMarkus Armbruster }
11834be74634SMarkus Armbruster 
11844be74634SMarkus Armbruster int blk_is_read_only(BlockBackend *blk)
11854be74634SMarkus Armbruster {
1186f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1187f21d96d0SKevin Wolf 
1188f21d96d0SKevin Wolf     if (bs) {
1189f21d96d0SKevin Wolf         return bdrv_is_read_only(bs);
1190061959e8SMax Reitz     } else {
1191061959e8SMax Reitz         return blk->root_state.read_only;
1192061959e8SMax Reitz     }
11934be74634SMarkus Armbruster }
11944be74634SMarkus Armbruster 
11954be74634SMarkus Armbruster int blk_is_sg(BlockBackend *blk)
11964be74634SMarkus Armbruster {
1197f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1198f21d96d0SKevin Wolf 
1199f21d96d0SKevin Wolf     if (!bs) {
1200a46fc9c9SMax Reitz         return 0;
1201a46fc9c9SMax Reitz     }
1202a46fc9c9SMax Reitz 
1203f21d96d0SKevin Wolf     return bdrv_is_sg(bs);
12044be74634SMarkus Armbruster }
12054be74634SMarkus Armbruster 
12064be74634SMarkus Armbruster int blk_enable_write_cache(BlockBackend *blk)
12074be74634SMarkus Armbruster {
1208bfd18d1eSKevin Wolf     return blk->enable_write_cache;
12094be74634SMarkus Armbruster }
12104be74634SMarkus Armbruster 
12114be74634SMarkus Armbruster void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
12124be74634SMarkus Armbruster {
1213bfd18d1eSKevin Wolf     blk->enable_write_cache = wce;
12144be74634SMarkus Armbruster }
12154be74634SMarkus Armbruster 
12162bb0dce7SMax Reitz void blk_invalidate_cache(BlockBackend *blk, Error **errp)
12172bb0dce7SMax Reitz {
1218f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1219f21d96d0SKevin Wolf 
1220f21d96d0SKevin Wolf     if (!bs) {
1221c09ba36cSMax Reitz         error_setg(errp, "Device '%s' has no medium", blk->name);
1222c09ba36cSMax Reitz         return;
1223c09ba36cSMax Reitz     }
1224c09ba36cSMax Reitz 
1225f21d96d0SKevin Wolf     bdrv_invalidate_cache(bs, errp);
12262bb0dce7SMax Reitz }
12272bb0dce7SMax Reitz 
1228e031f750SMax Reitz bool blk_is_inserted(BlockBackend *blk)
12294be74634SMarkus Armbruster {
1230f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1231f21d96d0SKevin Wolf 
1232f21d96d0SKevin Wolf     return bs && bdrv_is_inserted(bs);
1233db0284f8SMax Reitz }
1234db0284f8SMax Reitz 
1235db0284f8SMax Reitz bool blk_is_available(BlockBackend *blk)
1236db0284f8SMax Reitz {
1237db0284f8SMax Reitz     return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
12384be74634SMarkus Armbruster }
12394be74634SMarkus Armbruster 
12404be74634SMarkus Armbruster void blk_lock_medium(BlockBackend *blk, bool locked)
12414be74634SMarkus Armbruster {
1242f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1243f21d96d0SKevin Wolf 
1244f21d96d0SKevin Wolf     if (bs) {
1245f21d96d0SKevin Wolf         bdrv_lock_medium(bs, locked);
12464be74634SMarkus Armbruster     }
1247a46fc9c9SMax Reitz }
12484be74634SMarkus Armbruster 
12494be74634SMarkus Armbruster void blk_eject(BlockBackend *blk, bool eject_flag)
12504be74634SMarkus Armbruster {
1251f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1252f21d96d0SKevin Wolf 
1253f21d96d0SKevin Wolf     if (bs) {
1254f21d96d0SKevin Wolf         bdrv_eject(bs, eject_flag);
12554be74634SMarkus Armbruster     }
1256a46fc9c9SMax Reitz }
12574be74634SMarkus Armbruster 
12584be74634SMarkus Armbruster int blk_get_flags(BlockBackend *blk)
12594be74634SMarkus Armbruster {
1260f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1261f21d96d0SKevin Wolf 
1262f21d96d0SKevin Wolf     if (bs) {
1263f21d96d0SKevin Wolf         return bdrv_get_flags(bs);
1264061959e8SMax Reitz     } else {
1265061959e8SMax Reitz         return blk->root_state.open_flags;
1266061959e8SMax Reitz     }
12674be74634SMarkus Armbruster }
12684be74634SMarkus Armbruster 
1269454057b7SPeter Lieven int blk_get_max_transfer_length(BlockBackend *blk)
1270454057b7SPeter Lieven {
1271f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1272f21d96d0SKevin Wolf 
1273f21d96d0SKevin Wolf     if (bs) {
1274f21d96d0SKevin Wolf         return bs->bl.max_transfer_length;
1275a46fc9c9SMax Reitz     } else {
1276a46fc9c9SMax Reitz         return 0;
1277a46fc9c9SMax Reitz     }
1278454057b7SPeter Lieven }
1279454057b7SPeter Lieven 
1280648296e0SStefan Hajnoczi int blk_get_max_iov(BlockBackend *blk)
1281648296e0SStefan Hajnoczi {
1282f21d96d0SKevin Wolf     return blk->root->bs->bl.max_iov;
1283648296e0SStefan Hajnoczi }
1284648296e0SStefan Hajnoczi 
12854be74634SMarkus Armbruster void blk_set_guest_block_size(BlockBackend *blk, int align)
12864be74634SMarkus Armbruster {
128768e9ec01SMax Reitz     blk->guest_block_size = align;
12884be74634SMarkus Armbruster }
12894be74634SMarkus Armbruster 
1290f1c17521SPaolo Bonzini void *blk_try_blockalign(BlockBackend *blk, size_t size)
1291f1c17521SPaolo Bonzini {
1292f21d96d0SKevin Wolf     return qemu_try_blockalign(blk ? blk_bs(blk) : NULL, size);
1293f1c17521SPaolo Bonzini }
1294f1c17521SPaolo Bonzini 
12954be74634SMarkus Armbruster void *blk_blockalign(BlockBackend *blk, size_t size)
12964be74634SMarkus Armbruster {
1297f21d96d0SKevin Wolf     return qemu_blockalign(blk ? blk_bs(blk) : NULL, size);
12984be74634SMarkus Armbruster }
12994be74634SMarkus Armbruster 
13004be74634SMarkus Armbruster bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
13014be74634SMarkus Armbruster {
1302f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1303f21d96d0SKevin Wolf 
1304f21d96d0SKevin Wolf     if (!bs) {
1305a46fc9c9SMax Reitz         return false;
1306a46fc9c9SMax Reitz     }
1307a46fc9c9SMax Reitz 
1308f21d96d0SKevin Wolf     return bdrv_op_is_blocked(bs, op, errp);
13094be74634SMarkus Armbruster }
13104be74634SMarkus Armbruster 
13114be74634SMarkus Armbruster void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
13124be74634SMarkus Armbruster {
1313f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1314f21d96d0SKevin Wolf 
1315f21d96d0SKevin Wolf     if (bs) {
1316f21d96d0SKevin Wolf         bdrv_op_unblock(bs, op, reason);
13174be74634SMarkus Armbruster     }
1318a46fc9c9SMax Reitz }
13194be74634SMarkus Armbruster 
13204be74634SMarkus Armbruster void blk_op_block_all(BlockBackend *blk, Error *reason)
13214be74634SMarkus Armbruster {
1322f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1323f21d96d0SKevin Wolf 
1324f21d96d0SKevin Wolf     if (bs) {
1325f21d96d0SKevin Wolf         bdrv_op_block_all(bs, reason);
13264be74634SMarkus Armbruster     }
1327a46fc9c9SMax Reitz }
13284be74634SMarkus Armbruster 
13294be74634SMarkus Armbruster void blk_op_unblock_all(BlockBackend *blk, Error *reason)
13304be74634SMarkus Armbruster {
1331f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1332f21d96d0SKevin Wolf 
1333f21d96d0SKevin Wolf     if (bs) {
1334f21d96d0SKevin Wolf         bdrv_op_unblock_all(bs, reason);
13354be74634SMarkus Armbruster     }
1336a46fc9c9SMax Reitz }
13374be74634SMarkus Armbruster 
13384be74634SMarkus Armbruster AioContext *blk_get_aio_context(BlockBackend *blk)
13394be74634SMarkus Armbruster {
1340f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1341f21d96d0SKevin Wolf 
1342f21d96d0SKevin Wolf     if (bs) {
1343f21d96d0SKevin Wolf         return bdrv_get_aio_context(bs);
13444981bdecSMax Reitz     } else {
13454981bdecSMax Reitz         return qemu_get_aio_context();
13464981bdecSMax Reitz     }
13474981bdecSMax Reitz }
13484981bdecSMax Reitz 
13494981bdecSMax Reitz static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
13504981bdecSMax Reitz {
13514981bdecSMax Reitz     BlockBackendAIOCB *blk_acb = DO_UPCAST(BlockBackendAIOCB, common, acb);
13524981bdecSMax Reitz     return blk_get_aio_context(blk_acb->blk);
13534be74634SMarkus Armbruster }
13544be74634SMarkus Armbruster 
13554be74634SMarkus Armbruster void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
13564be74634SMarkus Armbruster {
1357f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1358f21d96d0SKevin Wolf 
1359f21d96d0SKevin Wolf     if (bs) {
1360f21d96d0SKevin Wolf         bdrv_set_aio_context(bs, new_context);
13614be74634SMarkus Armbruster     }
1362a46fc9c9SMax Reitz }
13634be74634SMarkus Armbruster 
13642019ba0aSMax Reitz void blk_add_aio_context_notifier(BlockBackend *blk,
13652019ba0aSMax Reitz         void (*attached_aio_context)(AioContext *new_context, void *opaque),
13662019ba0aSMax Reitz         void (*detach_aio_context)(void *opaque), void *opaque)
13672019ba0aSMax Reitz {
1368f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1369f21d96d0SKevin Wolf 
1370f21d96d0SKevin Wolf     if (bs) {
1371f21d96d0SKevin Wolf         bdrv_add_aio_context_notifier(bs, attached_aio_context,
13722019ba0aSMax Reitz                                       detach_aio_context, opaque);
13732019ba0aSMax Reitz     }
1374a46fc9c9SMax Reitz }
13752019ba0aSMax Reitz 
13762019ba0aSMax Reitz void blk_remove_aio_context_notifier(BlockBackend *blk,
13772019ba0aSMax Reitz                                      void (*attached_aio_context)(AioContext *,
13782019ba0aSMax Reitz                                                                   void *),
13792019ba0aSMax Reitz                                      void (*detach_aio_context)(void *),
13802019ba0aSMax Reitz                                      void *opaque)
13812019ba0aSMax Reitz {
1382f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1383f21d96d0SKevin Wolf 
1384f21d96d0SKevin Wolf     if (bs) {
1385f21d96d0SKevin Wolf         bdrv_remove_aio_context_notifier(bs, attached_aio_context,
13862019ba0aSMax Reitz                                          detach_aio_context, opaque);
13872019ba0aSMax Reitz     }
1388a46fc9c9SMax Reitz }
13892019ba0aSMax Reitz 
13903301f6c6SMax Reitz void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
13913301f6c6SMax Reitz {
13923301f6c6SMax Reitz     notifier_list_add(&blk->remove_bs_notifiers, notify);
13933301f6c6SMax Reitz }
13943301f6c6SMax Reitz 
13953301f6c6SMax Reitz void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
13963301f6c6SMax Reitz {
13973301f6c6SMax Reitz     notifier_list_add(&blk->insert_bs_notifiers, notify);
13983301f6c6SMax Reitz }
13993301f6c6SMax Reitz 
14004be74634SMarkus Armbruster void blk_io_plug(BlockBackend *blk)
14014be74634SMarkus Armbruster {
1402f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1403f21d96d0SKevin Wolf 
1404f21d96d0SKevin Wolf     if (bs) {
1405f21d96d0SKevin Wolf         bdrv_io_plug(bs);
14064be74634SMarkus Armbruster     }
1407a46fc9c9SMax Reitz }
14084be74634SMarkus Armbruster 
14094be74634SMarkus Armbruster void blk_io_unplug(BlockBackend *blk)
14104be74634SMarkus Armbruster {
1411f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1412f21d96d0SKevin Wolf 
1413f21d96d0SKevin Wolf     if (bs) {
1414f21d96d0SKevin Wolf         bdrv_io_unplug(bs);
14154be74634SMarkus Armbruster     }
1416a46fc9c9SMax Reitz }
14174be74634SMarkus Armbruster 
14184be74634SMarkus Armbruster BlockAcctStats *blk_get_stats(BlockBackend *blk)
14194be74634SMarkus Armbruster {
14207f0e9da6SMax Reitz     return &blk->stats;
14214be74634SMarkus Armbruster }
14224be74634SMarkus Armbruster 
14234be74634SMarkus Armbruster void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
14244be74634SMarkus Armbruster                   BlockCompletionFunc *cb, void *opaque)
14254be74634SMarkus Armbruster {
14264be74634SMarkus Armbruster     return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
14274be74634SMarkus Armbruster }
14281ef01253SMax Reitz 
1429983a1600SEric Blake int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t offset,
1430983a1600SEric Blake                                      int count, BdrvRequestFlags flags)
14311ef01253SMax Reitz {
1432983a1600SEric Blake     return blk_co_pwritev(blk, offset, count, NULL,
143316aaf975SKevin Wolf                           flags | BDRV_REQ_ZERO_WRITE);
14341ef01253SMax Reitz }
14351ef01253SMax Reitz 
14361ef01253SMax Reitz int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
14371ef01253SMax Reitz                          const uint8_t *buf, int nb_sectors)
14381ef01253SMax Reitz {
1439e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1440e7f7d676SMax Reitz     if (ret < 0) {
1441e7f7d676SMax Reitz         return ret;
1442e7f7d676SMax Reitz     }
1443e7f7d676SMax Reitz 
1444f21d96d0SKevin Wolf     return bdrv_write_compressed(blk_bs(blk), sector_num, buf, nb_sectors);
14451ef01253SMax Reitz }
14461ef01253SMax Reitz 
14471ef01253SMax Reitz int blk_truncate(BlockBackend *blk, int64_t offset)
14481ef01253SMax Reitz {
1449c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1450c09ba36cSMax Reitz         return -ENOMEDIUM;
1451c09ba36cSMax Reitz     }
1452c09ba36cSMax Reitz 
1453f21d96d0SKevin Wolf     return bdrv_truncate(blk_bs(blk), offset);
14541ef01253SMax Reitz }
14551ef01253SMax Reitz 
14561ef01253SMax Reitz int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
14571ef01253SMax Reitz {
1458e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1459e7f7d676SMax Reitz     if (ret < 0) {
1460e7f7d676SMax Reitz         return ret;
1461e7f7d676SMax Reitz     }
1462e7f7d676SMax Reitz 
1463f21d96d0SKevin Wolf     return bdrv_discard(blk_bs(blk), sector_num, nb_sectors);
14641ef01253SMax Reitz }
14651ef01253SMax Reitz 
14661ef01253SMax Reitz int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
14671ef01253SMax Reitz                      int64_t pos, int size)
14681ef01253SMax Reitz {
1469bfd18d1eSKevin Wolf     int ret;
1470bfd18d1eSKevin Wolf 
1471c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1472c09ba36cSMax Reitz         return -ENOMEDIUM;
1473c09ba36cSMax Reitz     }
1474c09ba36cSMax Reitz 
1475bfd18d1eSKevin Wolf     ret = bdrv_save_vmstate(blk_bs(blk), buf, pos, size);
1476bfd18d1eSKevin Wolf     if (ret < 0) {
1477bfd18d1eSKevin Wolf         return ret;
1478bfd18d1eSKevin Wolf     }
1479bfd18d1eSKevin Wolf 
1480bfd18d1eSKevin Wolf     if (ret == size && !blk->enable_write_cache) {
1481bfd18d1eSKevin Wolf         ret = bdrv_flush(blk_bs(blk));
1482bfd18d1eSKevin Wolf     }
1483bfd18d1eSKevin Wolf 
1484bfd18d1eSKevin Wolf     return ret < 0 ? ret : size;
14851ef01253SMax Reitz }
14861ef01253SMax Reitz 
14871ef01253SMax Reitz int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
14881ef01253SMax Reitz {
1489c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1490c09ba36cSMax Reitz         return -ENOMEDIUM;
1491c09ba36cSMax Reitz     }
1492c09ba36cSMax Reitz 
1493f21d96d0SKevin Wolf     return bdrv_load_vmstate(blk_bs(blk), buf, pos, size);
14941ef01253SMax Reitz }
1495f0272c4dSEkaterina Tumanova 
1496f0272c4dSEkaterina Tumanova int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz)
1497f0272c4dSEkaterina Tumanova {
1498c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1499c09ba36cSMax Reitz         return -ENOMEDIUM;
1500c09ba36cSMax Reitz     }
1501c09ba36cSMax Reitz 
1502f21d96d0SKevin Wolf     return bdrv_probe_blocksizes(blk_bs(blk), bsz);
1503f0272c4dSEkaterina Tumanova }
1504f0272c4dSEkaterina Tumanova 
1505f0272c4dSEkaterina Tumanova int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo)
1506f0272c4dSEkaterina Tumanova {
1507c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1508c09ba36cSMax Reitz         return -ENOMEDIUM;
1509c09ba36cSMax Reitz     }
1510c09ba36cSMax Reitz 
1511f21d96d0SKevin Wolf     return bdrv_probe_geometry(blk_bs(blk), geo);
1512f0272c4dSEkaterina Tumanova }
1513281d22d8SMax Reitz 
1514281d22d8SMax Reitz /*
1515281d22d8SMax Reitz  * Updates the BlockBackendRootState object with data from the currently
1516281d22d8SMax Reitz  * attached BlockDriverState.
1517281d22d8SMax Reitz  */
1518281d22d8SMax Reitz void blk_update_root_state(BlockBackend *blk)
1519281d22d8SMax Reitz {
1520f21d96d0SKevin Wolf     assert(blk->root);
1521281d22d8SMax Reitz 
1522f21d96d0SKevin Wolf     blk->root_state.open_flags    = blk->root->bs->open_flags;
1523f21d96d0SKevin Wolf     blk->root_state.read_only     = blk->root->bs->read_only;
1524f21d96d0SKevin Wolf     blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
1525281d22d8SMax Reitz 
1526281d22d8SMax Reitz     if (blk->root_state.throttle_group) {
1527281d22d8SMax Reitz         g_free(blk->root_state.throttle_group);
1528281d22d8SMax Reitz         throttle_group_unref(blk->root_state.throttle_state);
1529281d22d8SMax Reitz     }
1530*27ccdd52SKevin Wolf     if (blk->public.throttle_state) {
153149d2165dSKevin Wolf         const char *name = throttle_group_get_name(blk);
1532281d22d8SMax Reitz         blk->root_state.throttle_group = g_strdup(name);
1533281d22d8SMax Reitz         blk->root_state.throttle_state = throttle_group_incref(name);
1534281d22d8SMax Reitz     } else {
1535281d22d8SMax Reitz         blk->root_state.throttle_group = NULL;
1536281d22d8SMax Reitz         blk->root_state.throttle_state = NULL;
1537281d22d8SMax Reitz     }
1538281d22d8SMax Reitz }
1539281d22d8SMax Reitz 
154038cb18f5SMax Reitz /*
154138cb18f5SMax Reitz  * Applies the information in the root state to the given BlockDriverState. This
154238cb18f5SMax Reitz  * does not include the flags which have to be specified for bdrv_open(), use
154338cb18f5SMax Reitz  * blk_get_open_flags_from_root_state() to inquire them.
154438cb18f5SMax Reitz  */
154538cb18f5SMax Reitz void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs)
154638cb18f5SMax Reitz {
154738cb18f5SMax Reitz     bs->detect_zeroes = blk->root_state.detect_zeroes;
154838cb18f5SMax Reitz     if (blk->root_state.throttle_group) {
154938cb18f5SMax Reitz         bdrv_io_limits_enable(bs, blk->root_state.throttle_group);
155038cb18f5SMax Reitz     }
155138cb18f5SMax Reitz }
155238cb18f5SMax Reitz 
155338cb18f5SMax Reitz /*
155438cb18f5SMax Reitz  * Returns the flags to be used for bdrv_open() of a BlockDriverState which is
155538cb18f5SMax Reitz  * supposed to inherit the root state.
155638cb18f5SMax Reitz  */
155738cb18f5SMax Reitz int blk_get_open_flags_from_root_state(BlockBackend *blk)
155838cb18f5SMax Reitz {
155938cb18f5SMax Reitz     int bs_flags;
156038cb18f5SMax Reitz 
156138cb18f5SMax Reitz     bs_flags = blk->root_state.read_only ? 0 : BDRV_O_RDWR;
156238cb18f5SMax Reitz     bs_flags |= blk->root_state.open_flags & ~BDRV_O_RDWR;
156338cb18f5SMax Reitz 
156438cb18f5SMax Reitz     return bs_flags;
156538cb18f5SMax Reitz }
156638cb18f5SMax Reitz 
1567281d22d8SMax Reitz BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
1568281d22d8SMax Reitz {
1569281d22d8SMax Reitz     return &blk->root_state;
1570281d22d8SMax Reitz }
15711393f212SMax Reitz 
15721393f212SMax Reitz int blk_commit_all(void)
15731393f212SMax Reitz {
1574fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
1575fe1a9cbcSMax Reitz 
1576fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
1577fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
1578fe1a9cbcSMax Reitz 
1579fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
1580f21d96d0SKevin Wolf         if (blk_is_inserted(blk) && blk->root->bs->backing) {
1581f21d96d0SKevin Wolf             int ret = bdrv_commit(blk->root->bs);
1582fe1a9cbcSMax Reitz             if (ret < 0) {
1583fe1a9cbcSMax Reitz                 aio_context_release(aio_context);
1584fe1a9cbcSMax Reitz                 return ret;
1585fe1a9cbcSMax Reitz             }
1586fe1a9cbcSMax Reitz         }
1587fe1a9cbcSMax Reitz         aio_context_release(aio_context);
1588fe1a9cbcSMax Reitz     }
1589fe1a9cbcSMax Reitz     return 0;
1590fe1a9cbcSMax Reitz }
1591fe1a9cbcSMax Reitz 
1592fe1a9cbcSMax Reitz int blk_flush_all(void)
1593fe1a9cbcSMax Reitz {
1594fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
1595fe1a9cbcSMax Reitz     int result = 0;
1596fe1a9cbcSMax Reitz 
1597fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
1598fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
1599fe1a9cbcSMax Reitz         int ret;
1600fe1a9cbcSMax Reitz 
1601fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
1602fe1a9cbcSMax Reitz         if (blk_is_inserted(blk)) {
1603fe1a9cbcSMax Reitz             ret = blk_flush(blk);
1604fe1a9cbcSMax Reitz             if (ret < 0 && !result) {
1605fe1a9cbcSMax Reitz                 result = ret;
1606fe1a9cbcSMax Reitz             }
1607fe1a9cbcSMax Reitz         }
1608fe1a9cbcSMax Reitz         aio_context_release(aio_context);
1609fe1a9cbcSMax Reitz     }
1610fe1a9cbcSMax Reitz 
1611fe1a9cbcSMax Reitz     return result;
16121393f212SMax Reitz }
1613