xref: /openbmc/qemu/block/block-backend.c (revision 22aa8b24)
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;
11027ccdd52SKevin Wolf     qemu_co_queue_init(&blk->public.throttled_reqs[0]);
11127ccdd52SKevin Wolf     qemu_co_queue_init(&blk->public.throttled_reqs[1]);
11227ccdd52SKevin Wolf 
1133301f6c6SMax Reitz     notifier_list_init(&blk->remove_bs_notifiers);
1143301f6c6SMax Reitz     notifier_list_init(&blk->insert_bs_notifiers);
11527ccdd52SKevin 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);
136*22aa8b24SKevin Wolf     blk->root->opaque = blk;
1377e7d56d9SMarkus Armbruster     bs->blk = blk;
1387e7d56d9SMarkus Armbruster     return blk;
1397e7d56d9SMarkus Armbruster }
1407e7d56d9SMarkus Armbruster 
141ca49a4fdSMax Reitz /*
142ca49a4fdSMax Reitz  * Calls blk_new_with_bs() and then calls bdrv_open() on the BlockDriverState.
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;
157ca49a4fdSMax Reitz     int ret;
158ca49a4fdSMax Reitz 
159efaa7c4eSMax Reitz     blk = blk_new_with_bs(errp);
160ca49a4fdSMax Reitz     if (!blk) {
161ca49a4fdSMax Reitz         QDECREF(options);
162ca49a4fdSMax Reitz         return NULL;
163ca49a4fdSMax Reitz     }
164ca49a4fdSMax Reitz 
165f21d96d0SKevin Wolf     ret = bdrv_open(&blk->root->bs, filename, reference, options, flags, errp);
166ca49a4fdSMax Reitz     if (ret < 0) {
167ca49a4fdSMax Reitz         blk_unref(blk);
168ca49a4fdSMax Reitz         return NULL;
169ca49a4fdSMax Reitz     }
170ca49a4fdSMax Reitz 
17172e775c7SKevin Wolf     blk_set_enable_write_cache(blk, true);
17272e775c7SKevin Wolf 
173ca49a4fdSMax Reitz     return blk;
174ca49a4fdSMax Reitz }
175ca49a4fdSMax Reitz 
17626f54e9aSMarkus Armbruster static void blk_delete(BlockBackend *blk)
17726f54e9aSMarkus Armbruster {
17826f54e9aSMarkus Armbruster     assert(!blk->refcnt);
179e5e78550SMax Reitz     assert(!blk->name);
180a7f53e26SMarkus Armbruster     assert(!blk->dev);
181f21d96d0SKevin Wolf     if (blk->root) {
18213855c6bSMax Reitz         blk_remove_bs(blk);
1837e7d56d9SMarkus Armbruster     }
1843301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
1853301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
186281d22d8SMax Reitz     if (blk->root_state.throttle_state) {
187281d22d8SMax Reitz         g_free(blk->root_state.throttle_group);
188281d22d8SMax Reitz         throttle_group_unref(blk->root_state.throttle_state);
189281d22d8SMax Reitz     }
1902cf22d6aSMax Reitz     QTAILQ_REMOVE(&block_backends, blk, link);
19118e46a03SMarkus Armbruster     drive_info_del(blk->legacy_dinfo);
192979e9b03SAlberto Garcia     block_acct_cleanup(&blk->stats);
19326f54e9aSMarkus Armbruster     g_free(blk);
19426f54e9aSMarkus Armbruster }
19526f54e9aSMarkus Armbruster 
1968fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo)
1978fb3c76cSMarkus Armbruster {
1988fb3c76cSMarkus Armbruster     if (!dinfo) {
1998fb3c76cSMarkus Armbruster         return;
2008fb3c76cSMarkus Armbruster     }
2018fb3c76cSMarkus Armbruster     qemu_opts_del(dinfo->opts);
2028fb3c76cSMarkus Armbruster     g_free(dinfo->serial);
2038fb3c76cSMarkus Armbruster     g_free(dinfo);
2048fb3c76cSMarkus Armbruster }
2058fb3c76cSMarkus Armbruster 
206f636ae85SAlberto Garcia int blk_get_refcnt(BlockBackend *blk)
207f636ae85SAlberto Garcia {
208f636ae85SAlberto Garcia     return blk ? blk->refcnt : 0;
209f636ae85SAlberto Garcia }
210f636ae85SAlberto Garcia 
21126f54e9aSMarkus Armbruster /*
21226f54e9aSMarkus Armbruster  * Increment @blk's reference count.
21326f54e9aSMarkus Armbruster  * @blk must not be null.
21426f54e9aSMarkus Armbruster  */
21526f54e9aSMarkus Armbruster void blk_ref(BlockBackend *blk)
21626f54e9aSMarkus Armbruster {
21726f54e9aSMarkus Armbruster     blk->refcnt++;
21826f54e9aSMarkus Armbruster }
21926f54e9aSMarkus Armbruster 
22026f54e9aSMarkus Armbruster /*
22126f54e9aSMarkus Armbruster  * Decrement @blk's reference count.
22226f54e9aSMarkus Armbruster  * If this drops it to zero, destroy @blk.
22326f54e9aSMarkus Armbruster  * For convenience, do nothing if @blk is null.
22426f54e9aSMarkus Armbruster  */
22526f54e9aSMarkus Armbruster void blk_unref(BlockBackend *blk)
22626f54e9aSMarkus Armbruster {
22726f54e9aSMarkus Armbruster     if (blk) {
22826f54e9aSMarkus Armbruster         assert(blk->refcnt > 0);
22926f54e9aSMarkus Armbruster         if (!--blk->refcnt) {
23026f54e9aSMarkus Armbruster             blk_delete(blk);
23126f54e9aSMarkus Armbruster         }
23226f54e9aSMarkus Armbruster     }
23326f54e9aSMarkus Armbruster }
23426f54e9aSMarkus Armbruster 
2352cf22d6aSMax Reitz /*
2362cf22d6aSMax Reitz  * Behaves similarly to blk_next() but iterates over all BlockBackends, even the
2372cf22d6aSMax Reitz  * ones which are hidden (i.e. are not referenced by the monitor).
2382cf22d6aSMax Reitz  */
2392cf22d6aSMax Reitz static BlockBackend *blk_all_next(BlockBackend *blk)
2402cf22d6aSMax Reitz {
2412cf22d6aSMax Reitz     return blk ? QTAILQ_NEXT(blk, link)
2422cf22d6aSMax Reitz                : QTAILQ_FIRST(&block_backends);
2432cf22d6aSMax Reitz }
2442cf22d6aSMax Reitz 
245d8da3cefSMax Reitz void blk_remove_all_bs(void)
246d8da3cefSMax Reitz {
24774d1b8fcSMax Reitz     BlockBackend *blk = NULL;
248d8da3cefSMax Reitz 
2492cf22d6aSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
250d8da3cefSMax Reitz         AioContext *ctx = blk_get_aio_context(blk);
251d8da3cefSMax Reitz 
252d8da3cefSMax Reitz         aio_context_acquire(ctx);
253f21d96d0SKevin Wolf         if (blk->root) {
254d8da3cefSMax Reitz             blk_remove_bs(blk);
255d8da3cefSMax Reitz         }
256d8da3cefSMax Reitz         aio_context_release(ctx);
257d8da3cefSMax Reitz     }
258d8da3cefSMax Reitz }
259d8da3cefSMax Reitz 
26026f54e9aSMarkus Armbruster /*
2619492b0b9SMax Reitz  * Return the monitor-owned BlockBackend after @blk.
26226f54e9aSMarkus Armbruster  * If @blk is null, return the first one.
26326f54e9aSMarkus Armbruster  * Else, return @blk's next sibling, which may be null.
26426f54e9aSMarkus Armbruster  *
26526f54e9aSMarkus Armbruster  * To iterate over all BlockBackends, do
26626f54e9aSMarkus Armbruster  * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
26726f54e9aSMarkus Armbruster  *     ...
26826f54e9aSMarkus Armbruster  * }
26926f54e9aSMarkus Armbruster  */
27026f54e9aSMarkus Armbruster BlockBackend *blk_next(BlockBackend *blk)
27126f54e9aSMarkus Armbruster {
2729492b0b9SMax Reitz     return blk ? QTAILQ_NEXT(blk, monitor_link)
2739492b0b9SMax Reitz                : QTAILQ_FIRST(&monitor_block_backends);
27426f54e9aSMarkus Armbruster }
27526f54e9aSMarkus Armbruster 
27626f54e9aSMarkus Armbruster /*
277981f4f57SMax Reitz  * Iterates over all BlockDriverStates which are attached to a BlockBackend.
278981f4f57SMax Reitz  * This function is for use by bdrv_next().
279981f4f57SMax Reitz  *
280981f4f57SMax Reitz  * @bs must be NULL or a BDS that is attached to a BB.
281981f4f57SMax Reitz  */
282981f4f57SMax Reitz BlockDriverState *blk_next_root_bs(BlockDriverState *bs)
283981f4f57SMax Reitz {
284981f4f57SMax Reitz     BlockBackend *blk;
285981f4f57SMax Reitz 
286981f4f57SMax Reitz     if (bs) {
287981f4f57SMax Reitz         assert(bs->blk);
288981f4f57SMax Reitz         blk = bs->blk;
289981f4f57SMax Reitz     } else {
290981f4f57SMax Reitz         blk = NULL;
291981f4f57SMax Reitz     }
292981f4f57SMax Reitz 
293981f4f57SMax Reitz     do {
294981f4f57SMax Reitz         blk = blk_all_next(blk);
295f21d96d0SKevin Wolf     } while (blk && !blk->root);
296981f4f57SMax Reitz 
297f21d96d0SKevin Wolf     return blk ? blk->root->bs : NULL;
298981f4f57SMax Reitz }
299981f4f57SMax Reitz 
300981f4f57SMax Reitz /*
301e5e78550SMax Reitz  * Add a BlockBackend into the list of backends referenced by the monitor, with
302e5e78550SMax Reitz  * the given @name acting as the handle for the monitor.
303e5e78550SMax Reitz  * Strictly for use by blockdev.c.
304e5e78550SMax Reitz  *
305e5e78550SMax Reitz  * @name must not be null or empty.
306e5e78550SMax Reitz  *
307e5e78550SMax Reitz  * Returns true on success and false on failure. In the latter case, an Error
308e5e78550SMax Reitz  * object is returned through @errp.
309e5e78550SMax Reitz  */
310e5e78550SMax Reitz bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
311e5e78550SMax Reitz {
312e5e78550SMax Reitz     assert(!blk->name);
313e5e78550SMax Reitz     assert(name && name[0]);
314e5e78550SMax Reitz 
315e5e78550SMax Reitz     if (!id_wellformed(name)) {
316e5e78550SMax Reitz         error_setg(errp, "Invalid device name");
317e5e78550SMax Reitz         return false;
318e5e78550SMax Reitz     }
319e5e78550SMax Reitz     if (blk_by_name(name)) {
320e5e78550SMax Reitz         error_setg(errp, "Device with id '%s' already exists", name);
321e5e78550SMax Reitz         return false;
322e5e78550SMax Reitz     }
323e5e78550SMax Reitz     if (bdrv_find_node(name)) {
324e5e78550SMax Reitz         error_setg(errp,
325e5e78550SMax Reitz                    "Device name '%s' conflicts with an existing node name",
326e5e78550SMax Reitz                    name);
327e5e78550SMax Reitz         return false;
328e5e78550SMax Reitz     }
329e5e78550SMax Reitz 
330e5e78550SMax Reitz     blk->name = g_strdup(name);
331e5e78550SMax Reitz     QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
332e5e78550SMax Reitz     return true;
333e5e78550SMax Reitz }
334e5e78550SMax Reitz 
335e5e78550SMax Reitz /*
336e5e78550SMax Reitz  * Remove a BlockBackend from the list of backends referenced by the monitor.
337e5e78550SMax Reitz  * Strictly for use by blockdev.c.
338e5e78550SMax Reitz  */
339e5e78550SMax Reitz void monitor_remove_blk(BlockBackend *blk)
340e5e78550SMax Reitz {
341e5e78550SMax Reitz     if (!blk->name) {
342e5e78550SMax Reitz         return;
343e5e78550SMax Reitz     }
344e5e78550SMax Reitz 
345e5e78550SMax Reitz     QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
346e5e78550SMax Reitz     g_free(blk->name);
347e5e78550SMax Reitz     blk->name = NULL;
348e5e78550SMax Reitz }
349e5e78550SMax Reitz 
350e5e78550SMax Reitz /*
3517e7d56d9SMarkus Armbruster  * Return @blk's name, a non-null string.
352e5e78550SMax Reitz  * Returns an empty string iff @blk is not referenced by the monitor.
35326f54e9aSMarkus Armbruster  */
35426f54e9aSMarkus Armbruster const char *blk_name(BlockBackend *blk)
35526f54e9aSMarkus Armbruster {
356e5e78550SMax Reitz     return blk->name ?: "";
35726f54e9aSMarkus Armbruster }
35826f54e9aSMarkus Armbruster 
35926f54e9aSMarkus Armbruster /*
36026f54e9aSMarkus Armbruster  * Return the BlockBackend with name @name if it exists, else null.
36126f54e9aSMarkus Armbruster  * @name must not be null.
36226f54e9aSMarkus Armbruster  */
36326f54e9aSMarkus Armbruster BlockBackend *blk_by_name(const char *name)
36426f54e9aSMarkus Armbruster {
36574d1b8fcSMax Reitz     BlockBackend *blk = NULL;
36626f54e9aSMarkus Armbruster 
36726f54e9aSMarkus Armbruster     assert(name);
36874d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
36926f54e9aSMarkus Armbruster         if (!strcmp(name, blk->name)) {
37026f54e9aSMarkus Armbruster             return blk;
37126f54e9aSMarkus Armbruster         }
37226f54e9aSMarkus Armbruster     }
37326f54e9aSMarkus Armbruster     return NULL;
37426f54e9aSMarkus Armbruster }
3757e7d56d9SMarkus Armbruster 
3767e7d56d9SMarkus Armbruster /*
3777e7d56d9SMarkus Armbruster  * Return the BlockDriverState attached to @blk if any, else null.
3787e7d56d9SMarkus Armbruster  */
3797e7d56d9SMarkus Armbruster BlockDriverState *blk_bs(BlockBackend *blk)
3807e7d56d9SMarkus Armbruster {
381f21d96d0SKevin Wolf     return blk->root ? blk->root->bs : NULL;
3827e7d56d9SMarkus Armbruster }
3837e7d56d9SMarkus Armbruster 
3847e7d56d9SMarkus Armbruster /*
38518e46a03SMarkus Armbruster  * Return @blk's DriveInfo if any, else null.
38618e46a03SMarkus Armbruster  */
38718e46a03SMarkus Armbruster DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
38818e46a03SMarkus Armbruster {
38918e46a03SMarkus Armbruster     return blk->legacy_dinfo;
39018e46a03SMarkus Armbruster }
39118e46a03SMarkus Armbruster 
39218e46a03SMarkus Armbruster /*
39318e46a03SMarkus Armbruster  * Set @blk's DriveInfo to @dinfo, and return it.
39418e46a03SMarkus Armbruster  * @blk must not have a DriveInfo set already.
39518e46a03SMarkus Armbruster  * No other BlockBackend may have the same DriveInfo set.
39618e46a03SMarkus Armbruster  */
39718e46a03SMarkus Armbruster DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
39818e46a03SMarkus Armbruster {
39918e46a03SMarkus Armbruster     assert(!blk->legacy_dinfo);
40018e46a03SMarkus Armbruster     return blk->legacy_dinfo = dinfo;
40118e46a03SMarkus Armbruster }
40218e46a03SMarkus Armbruster 
40318e46a03SMarkus Armbruster /*
40418e46a03SMarkus Armbruster  * Return the BlockBackend with DriveInfo @dinfo.
40518e46a03SMarkus Armbruster  * It must exist.
40618e46a03SMarkus Armbruster  */
40718e46a03SMarkus Armbruster BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
40818e46a03SMarkus Armbruster {
40974d1b8fcSMax Reitz     BlockBackend *blk = NULL;
41018e46a03SMarkus Armbruster 
41174d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
41218e46a03SMarkus Armbruster         if (blk->legacy_dinfo == dinfo) {
41318e46a03SMarkus Armbruster             return blk;
41418e46a03SMarkus Armbruster         }
41518e46a03SMarkus Armbruster     }
41618e46a03SMarkus Armbruster     abort();
41718e46a03SMarkus Armbruster }
41818e46a03SMarkus Armbruster 
41918e46a03SMarkus Armbruster /*
420f2cd875dSKevin Wolf  * Returns a pointer to the publicly accessible fields of @blk.
421f2cd875dSKevin Wolf  */
422f2cd875dSKevin Wolf BlockBackendPublic *blk_get_public(BlockBackend *blk)
423f2cd875dSKevin Wolf {
424f2cd875dSKevin Wolf     return &blk->public;
425f2cd875dSKevin Wolf }
426f2cd875dSKevin Wolf 
427f2cd875dSKevin Wolf /*
428f2cd875dSKevin Wolf  * Returns a BlockBackend given the associated @public fields.
429f2cd875dSKevin Wolf  */
430f2cd875dSKevin Wolf BlockBackend *blk_by_public(BlockBackendPublic *public)
431f2cd875dSKevin Wolf {
432f2cd875dSKevin Wolf     return container_of(public, BlockBackend, public);
433f2cd875dSKevin Wolf }
434f2cd875dSKevin Wolf 
435f2cd875dSKevin Wolf /*
4361c95f7e1SMax Reitz  * Disassociates the currently associated BlockDriverState from @blk.
4371c95f7e1SMax Reitz  */
4381c95f7e1SMax Reitz void blk_remove_bs(BlockBackend *blk)
4391c95f7e1SMax Reitz {
440f21d96d0SKevin Wolf     assert(blk->root->bs->blk == blk);
44113855c6bSMax Reitz 
4423301f6c6SMax Reitz     notifier_list_notify(&blk->remove_bs_notifiers, blk);
4433301f6c6SMax Reitz 
4441c95f7e1SMax Reitz     blk_update_root_state(blk);
44527ccdd52SKevin Wolf     if (blk->public.throttle_state) {
44697148076SKevin Wolf         blk_io_limits_disable(blk);
447a5614993SKevin Wolf     }
4481c95f7e1SMax Reitz 
449f21d96d0SKevin Wolf     blk->root->bs->blk = NULL;
450f21d96d0SKevin Wolf     bdrv_root_unref_child(blk->root);
451f21d96d0SKevin Wolf     blk->root = NULL;
4521c95f7e1SMax Reitz }
4531c95f7e1SMax Reitz 
4541c95f7e1SMax Reitz /*
4550c3c36d6SMax Reitz  * Associates a new BlockDriverState with @blk.
4560c3c36d6SMax Reitz  */
4570c3c36d6SMax Reitz void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
4580c3c36d6SMax Reitz {
459f21d96d0SKevin Wolf     assert(!blk->root && !bs->blk);
4600c3c36d6SMax Reitz     bdrv_ref(bs);
461f21d96d0SKevin Wolf     blk->root = bdrv_root_attach_child(bs, "root", &child_root);
462*22aa8b24SKevin Wolf     blk->root->opaque = blk;
4630c3c36d6SMax Reitz     bs->blk = blk;
4643301f6c6SMax Reitz 
4653301f6c6SMax Reitz     notifier_list_notify(&blk->insert_bs_notifiers, blk);
4660c3c36d6SMax Reitz }
4670c3c36d6SMax Reitz 
4680c3c36d6SMax Reitz /*
469a7f53e26SMarkus Armbruster  * Attach device model @dev to @blk.
470a7f53e26SMarkus Armbruster  * Return 0 on success, -EBUSY when a device model is attached already.
471a7f53e26SMarkus Armbruster  */
472a7f53e26SMarkus Armbruster int blk_attach_dev(BlockBackend *blk, void *dev)
473a7f53e26SMarkus Armbruster /* TODO change to DeviceState *dev when all users are qdevified */
474a7f53e26SMarkus Armbruster {
475a7f53e26SMarkus Armbruster     if (blk->dev) {
476a7f53e26SMarkus Armbruster         return -EBUSY;
477a7f53e26SMarkus Armbruster     }
47884ebe375SMarkus Armbruster     blk_ref(blk);
479a7f53e26SMarkus Armbruster     blk->dev = dev;
480373340b2SMax Reitz     blk_iostatus_reset(blk);
481a7f53e26SMarkus Armbruster     return 0;
482a7f53e26SMarkus Armbruster }
483a7f53e26SMarkus Armbruster 
484a7f53e26SMarkus Armbruster /*
485a7f53e26SMarkus Armbruster  * Attach device model @dev to @blk.
486a7f53e26SMarkus Armbruster  * @blk must not have a device model attached already.
487a7f53e26SMarkus Armbruster  * TODO qdevified devices don't use this, remove when devices are qdevified
488a7f53e26SMarkus Armbruster  */
489a7f53e26SMarkus Armbruster void blk_attach_dev_nofail(BlockBackend *blk, void *dev)
490a7f53e26SMarkus Armbruster {
491a7f53e26SMarkus Armbruster     if (blk_attach_dev(blk, dev) < 0) {
492a7f53e26SMarkus Armbruster         abort();
493a7f53e26SMarkus Armbruster     }
494a7f53e26SMarkus Armbruster }
495a7f53e26SMarkus Armbruster 
496a7f53e26SMarkus Armbruster /*
497a7f53e26SMarkus Armbruster  * Detach device model @dev from @blk.
498a7f53e26SMarkus Armbruster  * @dev must be currently attached to @blk.
499a7f53e26SMarkus Armbruster  */
500a7f53e26SMarkus Armbruster void blk_detach_dev(BlockBackend *blk, void *dev)
501a7f53e26SMarkus Armbruster /* TODO change to DeviceState *dev when all users are qdevified */
502a7f53e26SMarkus Armbruster {
503a7f53e26SMarkus Armbruster     assert(blk->dev == dev);
504a7f53e26SMarkus Armbruster     blk->dev = NULL;
505a7f53e26SMarkus Armbruster     blk->dev_ops = NULL;
506a7f53e26SMarkus Armbruster     blk->dev_opaque = NULL;
50768e9ec01SMax Reitz     blk->guest_block_size = 512;
50884ebe375SMarkus Armbruster     blk_unref(blk);
509a7f53e26SMarkus Armbruster }
510a7f53e26SMarkus Armbruster 
511a7f53e26SMarkus Armbruster /*
512a7f53e26SMarkus Armbruster  * Return the device model attached to @blk if any, else null.
513a7f53e26SMarkus Armbruster  */
514a7f53e26SMarkus Armbruster void *blk_get_attached_dev(BlockBackend *blk)
515a7f53e26SMarkus Armbruster /* TODO change to return DeviceState * when all users are qdevified */
516a7f53e26SMarkus Armbruster {
517a7f53e26SMarkus Armbruster     return blk->dev;
518a7f53e26SMarkus Armbruster }
519a7f53e26SMarkus Armbruster 
520a7f53e26SMarkus Armbruster /*
521a7f53e26SMarkus Armbruster  * Set @blk's device model callbacks to @ops.
522a7f53e26SMarkus Armbruster  * @opaque is the opaque argument to pass to the callbacks.
523a7f53e26SMarkus Armbruster  * This is for use by device models.
524a7f53e26SMarkus Armbruster  */
525a7f53e26SMarkus Armbruster void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
526a7f53e26SMarkus Armbruster                      void *opaque)
527a7f53e26SMarkus Armbruster {
528a7f53e26SMarkus Armbruster     blk->dev_ops = ops;
529a7f53e26SMarkus Armbruster     blk->dev_opaque = opaque;
530a7f53e26SMarkus Armbruster }
531a7f53e26SMarkus Armbruster 
532a7f53e26SMarkus Armbruster /*
533a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of media change.
534a7f53e26SMarkus Armbruster  * If @load is true, notify of media load.
535a7f53e26SMarkus Armbruster  * Else, notify of media eject.
536a7f53e26SMarkus Armbruster  * Also send DEVICE_TRAY_MOVED events as appropriate.
537a7f53e26SMarkus Armbruster  */
538a7f53e26SMarkus Armbruster void blk_dev_change_media_cb(BlockBackend *blk, bool load)
539a7f53e26SMarkus Armbruster {
540a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->change_media_cb) {
541f1f57066SMax Reitz         bool tray_was_open, tray_is_open;
542a7f53e26SMarkus Armbruster 
543f1f57066SMax Reitz         tray_was_open = blk_dev_is_tray_open(blk);
544a7f53e26SMarkus Armbruster         blk->dev_ops->change_media_cb(blk->dev_opaque, load);
545f1f57066SMax Reitz         tray_is_open = blk_dev_is_tray_open(blk);
546f1f57066SMax Reitz 
547f1f57066SMax Reitz         if (tray_was_open != tray_is_open) {
548f1f57066SMax Reitz             qapi_event_send_device_tray_moved(blk_name(blk), tray_is_open,
549f1f57066SMax Reitz                                               &error_abort);
550a7f53e26SMarkus Armbruster         }
551a7f53e26SMarkus Armbruster     }
552a7f53e26SMarkus Armbruster }
553a7f53e26SMarkus Armbruster 
554a7f53e26SMarkus Armbruster /*
555a7f53e26SMarkus Armbruster  * Does @blk's attached device model have removable media?
556a7f53e26SMarkus Armbruster  * %true if no device model is attached.
557a7f53e26SMarkus Armbruster  */
558a7f53e26SMarkus Armbruster bool blk_dev_has_removable_media(BlockBackend *blk)
559a7f53e26SMarkus Armbruster {
560a7f53e26SMarkus Armbruster     return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
561a7f53e26SMarkus Armbruster }
562a7f53e26SMarkus Armbruster 
563a7f53e26SMarkus Armbruster /*
5648f3a73bcSMax Reitz  * Does @blk's attached device model have a tray?
5658f3a73bcSMax Reitz  */
5668f3a73bcSMax Reitz bool blk_dev_has_tray(BlockBackend *blk)
5678f3a73bcSMax Reitz {
5688f3a73bcSMax Reitz     return blk->dev_ops && blk->dev_ops->is_tray_open;
5698f3a73bcSMax Reitz }
5708f3a73bcSMax Reitz 
5718f3a73bcSMax Reitz /*
572a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a media eject request.
573a7f53e26SMarkus Armbruster  * If @force is true, the medium is about to be yanked out forcefully.
574a7f53e26SMarkus Armbruster  */
575a7f53e26SMarkus Armbruster void blk_dev_eject_request(BlockBackend *blk, bool force)
576a7f53e26SMarkus Armbruster {
577a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->eject_request_cb) {
578a7f53e26SMarkus Armbruster         blk->dev_ops->eject_request_cb(blk->dev_opaque, force);
579a7f53e26SMarkus Armbruster     }
580a7f53e26SMarkus Armbruster }
581a7f53e26SMarkus Armbruster 
582a7f53e26SMarkus Armbruster /*
583a7f53e26SMarkus Armbruster  * Does @blk's attached device model have a tray, and is it open?
584a7f53e26SMarkus Armbruster  */
585a7f53e26SMarkus Armbruster bool blk_dev_is_tray_open(BlockBackend *blk)
586a7f53e26SMarkus Armbruster {
5878f3a73bcSMax Reitz     if (blk_dev_has_tray(blk)) {
588a7f53e26SMarkus Armbruster         return blk->dev_ops->is_tray_open(blk->dev_opaque);
589a7f53e26SMarkus Armbruster     }
590a7f53e26SMarkus Armbruster     return false;
591a7f53e26SMarkus Armbruster }
592a7f53e26SMarkus Armbruster 
593a7f53e26SMarkus Armbruster /*
594a7f53e26SMarkus Armbruster  * Does @blk's attached device model have the medium locked?
595a7f53e26SMarkus Armbruster  * %false if the device model has no such lock.
596a7f53e26SMarkus Armbruster  */
597a7f53e26SMarkus Armbruster bool blk_dev_is_medium_locked(BlockBackend *blk)
598a7f53e26SMarkus Armbruster {
599a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->is_medium_locked) {
600a7f53e26SMarkus Armbruster         return blk->dev_ops->is_medium_locked(blk->dev_opaque);
601a7f53e26SMarkus Armbruster     }
602a7f53e26SMarkus Armbruster     return false;
603a7f53e26SMarkus Armbruster }
604a7f53e26SMarkus Armbruster 
605a7f53e26SMarkus Armbruster /*
606a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a backend size change.
607a7f53e26SMarkus Armbruster  */
608a7f53e26SMarkus Armbruster void blk_dev_resize_cb(BlockBackend *blk)
609a7f53e26SMarkus Armbruster {
610a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->resize_cb) {
611a7f53e26SMarkus Armbruster         blk->dev_ops->resize_cb(blk->dev_opaque);
612a7f53e26SMarkus Armbruster     }
613a7f53e26SMarkus Armbruster }
614a7f53e26SMarkus Armbruster 
6154be74634SMarkus Armbruster void blk_iostatus_enable(BlockBackend *blk)
6164be74634SMarkus Armbruster {
617373340b2SMax Reitz     blk->iostatus_enabled = true;
618373340b2SMax Reitz     blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
619373340b2SMax Reitz }
620373340b2SMax Reitz 
621373340b2SMax Reitz /* The I/O status is only enabled if the drive explicitly
622373340b2SMax Reitz  * enables it _and_ the VM is configured to stop on errors */
623373340b2SMax Reitz bool blk_iostatus_is_enabled(const BlockBackend *blk)
624373340b2SMax Reitz {
625373340b2SMax Reitz     return (blk->iostatus_enabled &&
626373340b2SMax Reitz            (blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
627373340b2SMax Reitz             blk->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
628373340b2SMax Reitz             blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
629373340b2SMax Reitz }
630373340b2SMax Reitz 
631373340b2SMax Reitz BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
632373340b2SMax Reitz {
633373340b2SMax Reitz     return blk->iostatus;
634373340b2SMax Reitz }
635373340b2SMax Reitz 
636373340b2SMax Reitz void blk_iostatus_disable(BlockBackend *blk)
637373340b2SMax Reitz {
638373340b2SMax Reitz     blk->iostatus_enabled = false;
639373340b2SMax Reitz }
640373340b2SMax Reitz 
641373340b2SMax Reitz void blk_iostatus_reset(BlockBackend *blk)
642373340b2SMax Reitz {
643373340b2SMax Reitz     if (blk_iostatus_is_enabled(blk)) {
644f21d96d0SKevin Wolf         BlockDriverState *bs = blk_bs(blk);
645373340b2SMax Reitz         blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
646f21d96d0SKevin Wolf         if (bs && bs->job) {
647f21d96d0SKevin Wolf             block_job_iostatus_reset(bs->job);
648373340b2SMax Reitz         }
649373340b2SMax Reitz     }
650373340b2SMax Reitz }
651373340b2SMax Reitz 
652373340b2SMax Reitz void blk_iostatus_set_err(BlockBackend *blk, int error)
653373340b2SMax Reitz {
654373340b2SMax Reitz     assert(blk_iostatus_is_enabled(blk));
655373340b2SMax Reitz     if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
656373340b2SMax Reitz         blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
657373340b2SMax Reitz                                           BLOCK_DEVICE_IO_STATUS_FAILED;
658373340b2SMax Reitz     }
6594be74634SMarkus Armbruster }
6604be74634SMarkus Armbruster 
661c10c9d96SKevin Wolf void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow)
662c10c9d96SKevin Wolf {
663c10c9d96SKevin Wolf     blk->allow_write_beyond_eof = allow;
664c10c9d96SKevin Wolf }
665c10c9d96SKevin Wolf 
666e7f7d676SMax Reitz static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
667e7f7d676SMax Reitz                                   size_t size)
668e7f7d676SMax Reitz {
669e7f7d676SMax Reitz     int64_t len;
670e7f7d676SMax Reitz 
671e7f7d676SMax Reitz     if (size > INT_MAX) {
672e7f7d676SMax Reitz         return -EIO;
673e7f7d676SMax Reitz     }
674e7f7d676SMax Reitz 
675c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
676e7f7d676SMax Reitz         return -ENOMEDIUM;
677e7f7d676SMax Reitz     }
678e7f7d676SMax Reitz 
679c10c9d96SKevin Wolf     if (offset < 0) {
680c10c9d96SKevin Wolf         return -EIO;
681c10c9d96SKevin Wolf     }
682c10c9d96SKevin Wolf 
683c10c9d96SKevin Wolf     if (!blk->allow_write_beyond_eof) {
684e7f7d676SMax Reitz         len = blk_getlength(blk);
685e7f7d676SMax Reitz         if (len < 0) {
686e7f7d676SMax Reitz             return len;
687e7f7d676SMax Reitz         }
688e7f7d676SMax Reitz 
689e7f7d676SMax Reitz         if (offset > len || len - offset < size) {
690e7f7d676SMax Reitz             return -EIO;
691e7f7d676SMax Reitz         }
692c10c9d96SKevin Wolf     }
693e7f7d676SMax Reitz 
694e7f7d676SMax Reitz     return 0;
695e7f7d676SMax Reitz }
696e7f7d676SMax Reitz 
697e7f7d676SMax Reitz static int blk_check_request(BlockBackend *blk, int64_t sector_num,
698e7f7d676SMax Reitz                              int nb_sectors)
699e7f7d676SMax Reitz {
700e7f7d676SMax Reitz     if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
701e7f7d676SMax Reitz         return -EIO;
702e7f7d676SMax Reitz     }
703e7f7d676SMax Reitz 
704e7f7d676SMax Reitz     if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
705e7f7d676SMax Reitz         return -EIO;
706e7f7d676SMax Reitz     }
707e7f7d676SMax Reitz 
708e7f7d676SMax Reitz     return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
709e7f7d676SMax Reitz                                   nb_sectors * BDRV_SECTOR_SIZE);
710e7f7d676SMax Reitz }
711e7f7d676SMax Reitz 
7121bf1cbc9SKevin Wolf static int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
7131bf1cbc9SKevin Wolf                                       unsigned int bytes, QEMUIOVector *qiov,
7141bf1cbc9SKevin Wolf                                       BdrvRequestFlags flags)
7154be74634SMarkus Armbruster {
7161bf1cbc9SKevin Wolf     int ret = blk_check_byte_request(blk, offset, bytes);
717e7f7d676SMax Reitz     if (ret < 0) {
718e7f7d676SMax Reitz         return ret;
719e7f7d676SMax Reitz     }
720e7f7d676SMax Reitz 
721441565b2SKevin Wolf     /* throttling disk I/O */
722441565b2SKevin Wolf     if (blk->public.throttle_state) {
723441565b2SKevin Wolf         throttle_group_co_io_limits_intercept(blk, bytes, false);
724441565b2SKevin Wolf     }
725441565b2SKevin Wolf 
726cab3a356SKevin Wolf     return bdrv_co_preadv(blk_bs(blk), offset, bytes, qiov, flags);
7271bf1cbc9SKevin Wolf }
7281bf1cbc9SKevin Wolf 
729a8823a3bSKevin Wolf static int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
730a8823a3bSKevin Wolf                                       unsigned int bytes, QEMUIOVector *qiov,
731a8823a3bSKevin Wolf                                       BdrvRequestFlags flags)
732a8823a3bSKevin Wolf {
733bfd18d1eSKevin Wolf     int ret;
734bfd18d1eSKevin Wolf 
735bfd18d1eSKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
736a8823a3bSKevin Wolf     if (ret < 0) {
737a8823a3bSKevin Wolf         return ret;
738a8823a3bSKevin Wolf     }
739a8823a3bSKevin Wolf 
740441565b2SKevin Wolf     /* throttling disk I/O */
741441565b2SKevin Wolf     if (blk->public.throttle_state) {
742441565b2SKevin Wolf         throttle_group_co_io_limits_intercept(blk, bytes, true);
743441565b2SKevin Wolf     }
744441565b2SKevin Wolf 
745bfd18d1eSKevin Wolf     if (!blk->enable_write_cache) {
746bfd18d1eSKevin Wolf         flags |= BDRV_REQ_FUA;
747bfd18d1eSKevin Wolf     }
748bfd18d1eSKevin Wolf 
749cab3a356SKevin Wolf     return bdrv_co_pwritev(blk_bs(blk), offset, bytes, qiov, flags);
750a8823a3bSKevin Wolf }
751a8823a3bSKevin Wolf 
7521bf1cbc9SKevin Wolf typedef struct BlkRwCo {
7531bf1cbc9SKevin Wolf     BlockBackend *blk;
7541bf1cbc9SKevin Wolf     int64_t offset;
7551bf1cbc9SKevin Wolf     QEMUIOVector *qiov;
7561bf1cbc9SKevin Wolf     int ret;
7571bf1cbc9SKevin Wolf     BdrvRequestFlags flags;
7581bf1cbc9SKevin Wolf } BlkRwCo;
7591bf1cbc9SKevin Wolf 
7601bf1cbc9SKevin Wolf static void blk_read_entry(void *opaque)
7611bf1cbc9SKevin Wolf {
7621bf1cbc9SKevin Wolf     BlkRwCo *rwco = opaque;
7631bf1cbc9SKevin Wolf 
7641bf1cbc9SKevin Wolf     rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, rwco->qiov->size,
7651bf1cbc9SKevin Wolf                               rwco->qiov, rwco->flags);
7661bf1cbc9SKevin Wolf }
7671bf1cbc9SKevin Wolf 
768a8823a3bSKevin Wolf static void blk_write_entry(void *opaque)
769a8823a3bSKevin Wolf {
770a8823a3bSKevin Wolf     BlkRwCo *rwco = opaque;
771a8823a3bSKevin Wolf 
772a8823a3bSKevin Wolf     rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, rwco->qiov->size,
773a8823a3bSKevin Wolf                                rwco->qiov, rwco->flags);
774a8823a3bSKevin Wolf }
775a8823a3bSKevin Wolf 
776a55d3fbaSKevin Wolf static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
777a55d3fbaSKevin Wolf                    int64_t bytes, CoroutineEntry co_entry,
778fc1453cdSKevin Wolf                    BdrvRequestFlags flags)
7791bf1cbc9SKevin Wolf {
7801bf1cbc9SKevin Wolf     AioContext *aio_context;
7811bf1cbc9SKevin Wolf     QEMUIOVector qiov;
7821bf1cbc9SKevin Wolf     struct iovec iov;
7831bf1cbc9SKevin Wolf     Coroutine *co;
7841bf1cbc9SKevin Wolf     BlkRwCo rwco;
7851bf1cbc9SKevin Wolf 
7861bf1cbc9SKevin Wolf     iov = (struct iovec) {
7871bf1cbc9SKevin Wolf         .iov_base = buf,
788a55d3fbaSKevin Wolf         .iov_len = bytes,
7891bf1cbc9SKevin Wolf     };
7901bf1cbc9SKevin Wolf     qemu_iovec_init_external(&qiov, &iov, 1);
7911bf1cbc9SKevin Wolf 
7921bf1cbc9SKevin Wolf     rwco = (BlkRwCo) {
7931bf1cbc9SKevin Wolf         .blk    = blk,
794a55d3fbaSKevin Wolf         .offset = offset,
7951bf1cbc9SKevin Wolf         .qiov   = &qiov,
796fc1453cdSKevin Wolf         .flags  = flags,
7971bf1cbc9SKevin Wolf         .ret    = NOT_DONE,
7981bf1cbc9SKevin Wolf     };
7991bf1cbc9SKevin Wolf 
800a8823a3bSKevin Wolf     co = qemu_coroutine_create(co_entry);
8011bf1cbc9SKevin Wolf     qemu_coroutine_enter(co, &rwco);
8021bf1cbc9SKevin Wolf 
8031bf1cbc9SKevin Wolf     aio_context = blk_get_aio_context(blk);
8041bf1cbc9SKevin Wolf     while (rwco.ret == NOT_DONE) {
8051bf1cbc9SKevin Wolf         aio_poll(aio_context, true);
8061bf1cbc9SKevin Wolf     }
8071bf1cbc9SKevin Wolf 
8081bf1cbc9SKevin Wolf     return rwco.ret;
8094be74634SMarkus Armbruster }
8104be74634SMarkus Armbruster 
811b7d17f9fSEric Blake int blk_pread_unthrottled(BlockBackend *blk, int64_t offset, uint8_t *buf,
812b7d17f9fSEric Blake                           int count)
8134be74634SMarkus Armbruster {
8145bd51196SKevin Wolf     int ret;
8155bd51196SKevin Wolf 
816b7d17f9fSEric Blake     ret = blk_check_byte_request(blk, offset, count);
817e7f7d676SMax Reitz     if (ret < 0) {
818e7f7d676SMax Reitz         return ret;
819e7f7d676SMax Reitz     }
820e7f7d676SMax Reitz 
82127ccdd52SKevin Wolf     bdrv_no_throttling_begin(blk_bs(blk));
822b7d17f9fSEric Blake     ret = blk_pread(blk, offset, buf, count);
82327ccdd52SKevin Wolf     bdrv_no_throttling_end(blk_bs(blk));
8245bd51196SKevin Wolf     return ret;
8254be74634SMarkus Armbruster }
8264be74634SMarkus Armbruster 
827983a1600SEric Blake int blk_write_zeroes(BlockBackend *blk, int64_t offset,
828983a1600SEric Blake                      int count, BdrvRequestFlags flags)
8290df89e8eSKevin Wolf {
830983a1600SEric Blake     return blk_prw(blk, offset, NULL, count, blk_write_entry,
83116aaf975SKevin Wolf                    flags | BDRV_REQ_ZERO_WRITE);
8320df89e8eSKevin Wolf }
8330df89e8eSKevin Wolf 
834e7f7d676SMax Reitz static void error_callback_bh(void *opaque)
835e7f7d676SMax Reitz {
836e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb = opaque;
837e7f7d676SMax Reitz     qemu_bh_delete(acb->bh);
838e7f7d676SMax Reitz     acb->common.cb(acb->common.opaque, acb->ret);
839e7f7d676SMax Reitz     qemu_aio_unref(acb);
840e7f7d676SMax Reitz }
841e7f7d676SMax Reitz 
842ca78ecfaSPeter Lieven BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
843ca78ecfaSPeter Lieven                                   BlockCompletionFunc *cb,
844e7f7d676SMax Reitz                                   void *opaque, int ret)
845e7f7d676SMax Reitz {
846e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb;
847e7f7d676SMax Reitz     QEMUBH *bh;
848e7f7d676SMax Reitz 
849e7f7d676SMax Reitz     acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
8504981bdecSMax Reitz     acb->blk = blk;
851e7f7d676SMax Reitz     acb->ret = ret;
852e7f7d676SMax Reitz 
853e7f7d676SMax Reitz     bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb);
854e7f7d676SMax Reitz     acb->bh = bh;
855e7f7d676SMax Reitz     qemu_bh_schedule(bh);
856e7f7d676SMax Reitz 
857e7f7d676SMax Reitz     return &acb->common;
858e7f7d676SMax Reitz }
859e7f7d676SMax Reitz 
86057d6a428SKevin Wolf typedef struct BlkAioEmAIOCB {
86157d6a428SKevin Wolf     BlockAIOCB common;
86257d6a428SKevin Wolf     BlkRwCo rwco;
8637fa84cd8SKevin Wolf     int bytes;
86457d6a428SKevin Wolf     bool has_returned;
86557d6a428SKevin Wolf     QEMUBH* bh;
86657d6a428SKevin Wolf } BlkAioEmAIOCB;
86757d6a428SKevin Wolf 
86857d6a428SKevin Wolf static const AIOCBInfo blk_aio_em_aiocb_info = {
86957d6a428SKevin Wolf     .aiocb_size         = sizeof(BlkAioEmAIOCB),
87057d6a428SKevin Wolf };
87157d6a428SKevin Wolf 
87257d6a428SKevin Wolf static void blk_aio_complete(BlkAioEmAIOCB *acb)
87357d6a428SKevin Wolf {
87457d6a428SKevin Wolf     if (acb->bh) {
87557d6a428SKevin Wolf         assert(acb->has_returned);
87657d6a428SKevin Wolf         qemu_bh_delete(acb->bh);
87757d6a428SKevin Wolf     }
87857d6a428SKevin Wolf     if (acb->has_returned) {
87957d6a428SKevin Wolf         acb->common.cb(acb->common.opaque, acb->rwco.ret);
88057d6a428SKevin Wolf         qemu_aio_unref(acb);
88157d6a428SKevin Wolf     }
88257d6a428SKevin Wolf }
88357d6a428SKevin Wolf 
88457d6a428SKevin Wolf static void blk_aio_complete_bh(void *opaque)
88557d6a428SKevin Wolf {
88657d6a428SKevin Wolf     blk_aio_complete(opaque);
88757d6a428SKevin Wolf }
88857d6a428SKevin Wolf 
8897fa84cd8SKevin Wolf static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
89057d6a428SKevin Wolf                                 QEMUIOVector *qiov, CoroutineEntry co_entry,
89157d6a428SKevin Wolf                                 BdrvRequestFlags flags,
89257d6a428SKevin Wolf                                 BlockCompletionFunc *cb, void *opaque)
89357d6a428SKevin Wolf {
89457d6a428SKevin Wolf     BlkAioEmAIOCB *acb;
89557d6a428SKevin Wolf     Coroutine *co;
89657d6a428SKevin Wolf 
89757d6a428SKevin Wolf     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
89857d6a428SKevin Wolf     acb->rwco = (BlkRwCo) {
89957d6a428SKevin Wolf         .blk    = blk,
90057d6a428SKevin Wolf         .offset = offset,
90157d6a428SKevin Wolf         .qiov   = qiov,
90257d6a428SKevin Wolf         .flags  = flags,
90357d6a428SKevin Wolf         .ret    = NOT_DONE,
90457d6a428SKevin Wolf     };
9057fa84cd8SKevin Wolf     acb->bytes = bytes;
90657d6a428SKevin Wolf     acb->bh = NULL;
90757d6a428SKevin Wolf     acb->has_returned = false;
90857d6a428SKevin Wolf 
90957d6a428SKevin Wolf     co = qemu_coroutine_create(co_entry);
91057d6a428SKevin Wolf     qemu_coroutine_enter(co, acb);
91157d6a428SKevin Wolf 
91257d6a428SKevin Wolf     acb->has_returned = true;
91357d6a428SKevin Wolf     if (acb->rwco.ret != NOT_DONE) {
91457d6a428SKevin Wolf         acb->bh = aio_bh_new(blk_get_aio_context(blk), blk_aio_complete_bh, acb);
91557d6a428SKevin Wolf         qemu_bh_schedule(acb->bh);
91657d6a428SKevin Wolf     }
91757d6a428SKevin Wolf 
91857d6a428SKevin Wolf     return &acb->common;
91957d6a428SKevin Wolf }
92057d6a428SKevin Wolf 
92157d6a428SKevin Wolf static void blk_aio_read_entry(void *opaque)
92257d6a428SKevin Wolf {
92357d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
92457d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
92557d6a428SKevin Wolf 
9267fa84cd8SKevin Wolf     assert(rwco->qiov->size == acb->bytes);
9277fa84cd8SKevin Wolf     rwco->ret = blk_co_preadv(rwco->blk, rwco->offset, acb->bytes,
92857d6a428SKevin Wolf                               rwco->qiov, rwco->flags);
92957d6a428SKevin Wolf     blk_aio_complete(acb);
93057d6a428SKevin Wolf }
93157d6a428SKevin Wolf 
93257d6a428SKevin Wolf static void blk_aio_write_entry(void *opaque)
93357d6a428SKevin Wolf {
93457d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
93557d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
93657d6a428SKevin Wolf 
9377fa84cd8SKevin Wolf     assert(!rwco->qiov || rwco->qiov->size == acb->bytes);
9387fa84cd8SKevin Wolf     rwco->ret = blk_co_pwritev(rwco->blk, rwco->offset, acb->bytes,
93957d6a428SKevin Wolf                                rwco->qiov, rwco->flags);
94057d6a428SKevin Wolf     blk_aio_complete(acb);
94157d6a428SKevin Wolf }
94257d6a428SKevin Wolf 
943983a1600SEric Blake BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t offset,
944983a1600SEric Blake                                  int count, BdrvRequestFlags flags,
9454be74634SMarkus Armbruster                                  BlockCompletionFunc *cb, void *opaque)
9464be74634SMarkus Armbruster {
947983a1600SEric Blake     return blk_aio_prwv(blk, offset, count, NULL, blk_aio_write_entry,
948983a1600SEric Blake                         flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
9494be74634SMarkus Armbruster }
9504be74634SMarkus Armbruster 
9514be74634SMarkus Armbruster int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
9524be74634SMarkus Armbruster {
953a55d3fbaSKevin Wolf     int ret = blk_prw(blk, offset, buf, count, blk_read_entry, 0);
954e7f7d676SMax Reitz     if (ret < 0) {
955e7f7d676SMax Reitz         return ret;
956e7f7d676SMax Reitz     }
957a55d3fbaSKevin Wolf     return count;
9584be74634SMarkus Armbruster }
9594be74634SMarkus Armbruster 
9608341f00dSEric Blake int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count,
9618341f00dSEric Blake                BdrvRequestFlags flags)
9624be74634SMarkus Armbruster {
9638341f00dSEric Blake     int ret = blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
9648341f00dSEric Blake                       flags);
965e7f7d676SMax Reitz     if (ret < 0) {
966e7f7d676SMax Reitz         return ret;
967e7f7d676SMax Reitz     }
968a55d3fbaSKevin Wolf     return count;
9694be74634SMarkus Armbruster }
9704be74634SMarkus Armbruster 
9714be74634SMarkus Armbruster int64_t blk_getlength(BlockBackend *blk)
9724be74634SMarkus Armbruster {
973c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
974c09ba36cSMax Reitz         return -ENOMEDIUM;
975c09ba36cSMax Reitz     }
976c09ba36cSMax Reitz 
977f21d96d0SKevin Wolf     return bdrv_getlength(blk_bs(blk));
9784be74634SMarkus Armbruster }
9794be74634SMarkus Armbruster 
9804be74634SMarkus Armbruster void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
9814be74634SMarkus Armbruster {
982f21d96d0SKevin Wolf     if (!blk_bs(blk)) {
983a46fc9c9SMax Reitz         *nb_sectors_ptr = 0;
984a46fc9c9SMax Reitz     } else {
985f21d96d0SKevin Wolf         bdrv_get_geometry(blk_bs(blk), nb_sectors_ptr);
9864be74634SMarkus Armbruster     }
987a46fc9c9SMax Reitz }
9884be74634SMarkus Armbruster 
9891ef01253SMax Reitz int64_t blk_nb_sectors(BlockBackend *blk)
9901ef01253SMax Reitz {
991c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
992c09ba36cSMax Reitz         return -ENOMEDIUM;
993c09ba36cSMax Reitz     }
994c09ba36cSMax Reitz 
995f21d96d0SKevin Wolf     return bdrv_nb_sectors(blk_bs(blk));
9961ef01253SMax Reitz }
9971ef01253SMax Reitz 
99860cb2fa7SEric Blake BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
99960cb2fa7SEric Blake                            QEMUIOVector *qiov, BdrvRequestFlags flags,
100060cb2fa7SEric Blake                            BlockCompletionFunc *cb, void *opaque)
100160cb2fa7SEric Blake {
100260cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
100360cb2fa7SEric Blake                         blk_aio_read_entry, flags, cb, opaque);
100460cb2fa7SEric Blake }
100560cb2fa7SEric Blake 
100660cb2fa7SEric Blake BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
100760cb2fa7SEric Blake                             QEMUIOVector *qiov, BdrvRequestFlags flags,
100860cb2fa7SEric Blake                             BlockCompletionFunc *cb, void *opaque)
100960cb2fa7SEric Blake {
101060cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
101160cb2fa7SEric Blake                         blk_aio_write_entry, flags, cb, opaque);
101260cb2fa7SEric Blake }
101360cb2fa7SEric Blake 
10144be74634SMarkus Armbruster BlockAIOCB *blk_aio_flush(BlockBackend *blk,
10154be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
10164be74634SMarkus Armbruster {
1017c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1018ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
1019c09ba36cSMax Reitz     }
1020c09ba36cSMax Reitz 
1021f21d96d0SKevin Wolf     return bdrv_aio_flush(blk_bs(blk), cb, opaque);
10224be74634SMarkus Armbruster }
10234be74634SMarkus Armbruster 
10244be74634SMarkus Armbruster BlockAIOCB *blk_aio_discard(BlockBackend *blk,
10254be74634SMarkus Armbruster                             int64_t sector_num, int nb_sectors,
10264be74634SMarkus Armbruster                             BlockCompletionFunc *cb, void *opaque)
10274be74634SMarkus Armbruster {
1028e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1029e7f7d676SMax Reitz     if (ret < 0) {
1030ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, ret);
1031e7f7d676SMax Reitz     }
1032e7f7d676SMax Reitz 
1033f21d96d0SKevin Wolf     return bdrv_aio_discard(blk_bs(blk), sector_num, nb_sectors, cb, opaque);
10344be74634SMarkus Armbruster }
10354be74634SMarkus Armbruster 
10364be74634SMarkus Armbruster void blk_aio_cancel(BlockAIOCB *acb)
10374be74634SMarkus Armbruster {
10384be74634SMarkus Armbruster     bdrv_aio_cancel(acb);
10394be74634SMarkus Armbruster }
10404be74634SMarkus Armbruster 
10414be74634SMarkus Armbruster void blk_aio_cancel_async(BlockAIOCB *acb)
10424be74634SMarkus Armbruster {
10434be74634SMarkus Armbruster     bdrv_aio_cancel_async(acb);
10444be74634SMarkus Armbruster }
10454be74634SMarkus Armbruster 
10464be74634SMarkus Armbruster int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs)
10474be74634SMarkus Armbruster {
1048e7f7d676SMax Reitz     int i, ret;
1049e7f7d676SMax Reitz 
1050e7f7d676SMax Reitz     for (i = 0; i < num_reqs; i++) {
1051e7f7d676SMax Reitz         ret = blk_check_request(blk, reqs[i].sector, reqs[i].nb_sectors);
1052e7f7d676SMax Reitz         if (ret < 0) {
1053e7f7d676SMax Reitz             return ret;
1054e7f7d676SMax Reitz         }
1055e7f7d676SMax Reitz     }
1056e7f7d676SMax Reitz 
1057f21d96d0SKevin Wolf     return bdrv_aio_multiwrite(blk_bs(blk), reqs, num_reqs);
10584be74634SMarkus Armbruster }
10594be74634SMarkus Armbruster 
10604be74634SMarkus Armbruster int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
10614be74634SMarkus Armbruster {
1062c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1063c09ba36cSMax Reitz         return -ENOMEDIUM;
1064c09ba36cSMax Reitz     }
1065c09ba36cSMax Reitz 
1066f21d96d0SKevin Wolf     return bdrv_ioctl(blk_bs(blk), req, buf);
10674be74634SMarkus Armbruster }
10684be74634SMarkus Armbruster 
10694be74634SMarkus Armbruster BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
10704be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
10714be74634SMarkus Armbruster {
1072c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1073ca78ecfaSPeter Lieven         return blk_abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
1074c09ba36cSMax Reitz     }
1075c09ba36cSMax Reitz 
1076f21d96d0SKevin Wolf     return bdrv_aio_ioctl(blk_bs(blk), req, buf, cb, opaque);
10774be74634SMarkus Armbruster }
10784be74634SMarkus Armbruster 
10792bb0dce7SMax Reitz int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
10802bb0dce7SMax Reitz {
1081e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1082e7f7d676SMax Reitz     if (ret < 0) {
1083e7f7d676SMax Reitz         return ret;
1084e7f7d676SMax Reitz     }
1085e7f7d676SMax Reitz 
1086f21d96d0SKevin Wolf     return bdrv_co_discard(blk_bs(blk), sector_num, nb_sectors);
10872bb0dce7SMax Reitz }
10882bb0dce7SMax Reitz 
10892bb0dce7SMax Reitz int blk_co_flush(BlockBackend *blk)
10902bb0dce7SMax Reitz {
1091c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1092c09ba36cSMax Reitz         return -ENOMEDIUM;
1093c09ba36cSMax Reitz     }
1094c09ba36cSMax Reitz 
1095f21d96d0SKevin Wolf     return bdrv_co_flush(blk_bs(blk));
10962bb0dce7SMax Reitz }
10972bb0dce7SMax Reitz 
10984be74634SMarkus Armbruster int blk_flush(BlockBackend *blk)
10994be74634SMarkus Armbruster {
1100c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1101c09ba36cSMax Reitz         return -ENOMEDIUM;
1102c09ba36cSMax Reitz     }
1103c09ba36cSMax Reitz 
1104f21d96d0SKevin Wolf     return bdrv_flush(blk_bs(blk));
11054be74634SMarkus Armbruster }
11064be74634SMarkus Armbruster 
110797b0385aSAlexander Yarygin void blk_drain(BlockBackend *blk)
110897b0385aSAlexander Yarygin {
1109f21d96d0SKevin Wolf     if (blk_bs(blk)) {
1110f21d96d0SKevin Wolf         bdrv_drain(blk_bs(blk));
111197b0385aSAlexander Yarygin     }
1112a46fc9c9SMax Reitz }
111397b0385aSAlexander Yarygin 
11144be74634SMarkus Armbruster void blk_drain_all(void)
11154be74634SMarkus Armbruster {
11164be74634SMarkus Armbruster     bdrv_drain_all();
11174be74634SMarkus Armbruster }
11184be74634SMarkus Armbruster 
1119373340b2SMax Reitz void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
1120373340b2SMax Reitz                       BlockdevOnError on_write_error)
1121373340b2SMax Reitz {
1122373340b2SMax Reitz     blk->on_read_error = on_read_error;
1123373340b2SMax Reitz     blk->on_write_error = on_write_error;
1124373340b2SMax Reitz }
1125373340b2SMax Reitz 
11264be74634SMarkus Armbruster BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
11274be74634SMarkus Armbruster {
1128373340b2SMax Reitz     return is_read ? blk->on_read_error : blk->on_write_error;
11294be74634SMarkus Armbruster }
11304be74634SMarkus Armbruster 
11314be74634SMarkus Armbruster BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
11324be74634SMarkus Armbruster                                       int error)
11334be74634SMarkus Armbruster {
1134373340b2SMax Reitz     BlockdevOnError on_err = blk_get_on_error(blk, is_read);
1135373340b2SMax Reitz 
1136373340b2SMax Reitz     switch (on_err) {
1137373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_ENOSPC:
1138373340b2SMax Reitz         return (error == ENOSPC) ?
1139373340b2SMax Reitz                BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
1140373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_STOP:
1141373340b2SMax Reitz         return BLOCK_ERROR_ACTION_STOP;
1142373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_REPORT:
1143373340b2SMax Reitz         return BLOCK_ERROR_ACTION_REPORT;
1144373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_IGNORE:
1145373340b2SMax Reitz         return BLOCK_ERROR_ACTION_IGNORE;
1146373340b2SMax Reitz     default:
1147373340b2SMax Reitz         abort();
1148373340b2SMax Reitz     }
11494be74634SMarkus Armbruster }
11504be74634SMarkus Armbruster 
1151373340b2SMax Reitz static void send_qmp_error_event(BlockBackend *blk,
1152373340b2SMax Reitz                                  BlockErrorAction action,
1153373340b2SMax Reitz                                  bool is_read, int error)
1154373340b2SMax Reitz {
1155373340b2SMax Reitz     IoOperationType optype;
1156373340b2SMax Reitz 
1157373340b2SMax Reitz     optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
1158373340b2SMax Reitz     qapi_event_send_block_io_error(blk_name(blk), optype, action,
1159373340b2SMax Reitz                                    blk_iostatus_is_enabled(blk),
1160373340b2SMax Reitz                                    error == ENOSPC, strerror(error),
1161373340b2SMax Reitz                                    &error_abort);
1162373340b2SMax Reitz }
1163373340b2SMax Reitz 
1164373340b2SMax Reitz /* This is done by device models because, while the block layer knows
1165373340b2SMax Reitz  * about the error, it does not know whether an operation comes from
1166373340b2SMax Reitz  * the device or the block layer (from a job, for example).
1167373340b2SMax Reitz  */
11684be74634SMarkus Armbruster void blk_error_action(BlockBackend *blk, BlockErrorAction action,
11694be74634SMarkus Armbruster                       bool is_read, int error)
11704be74634SMarkus Armbruster {
1171373340b2SMax Reitz     assert(error >= 0);
1172373340b2SMax Reitz 
1173373340b2SMax Reitz     if (action == BLOCK_ERROR_ACTION_STOP) {
1174373340b2SMax Reitz         /* First set the iostatus, so that "info block" returns an iostatus
1175373340b2SMax Reitz          * that matches the events raised so far (an additional error iostatus
1176373340b2SMax Reitz          * is fine, but not a lost one).
1177373340b2SMax Reitz          */
1178373340b2SMax Reitz         blk_iostatus_set_err(blk, error);
1179373340b2SMax Reitz 
1180373340b2SMax Reitz         /* Then raise the request to stop the VM and the event.
1181373340b2SMax Reitz          * qemu_system_vmstop_request_prepare has two effects.  First,
1182373340b2SMax Reitz          * it ensures that the STOP event always comes after the
1183373340b2SMax Reitz          * BLOCK_IO_ERROR event.  Second, it ensures that even if management
1184373340b2SMax Reitz          * can observe the STOP event and do a "cont" before the STOP
1185373340b2SMax Reitz          * event is issued, the VM will not stop.  In this case, vm_start()
1186373340b2SMax Reitz          * also ensures that the STOP/RESUME pair of events is emitted.
1187373340b2SMax Reitz          */
1188373340b2SMax Reitz         qemu_system_vmstop_request_prepare();
1189373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
1190373340b2SMax Reitz         qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
1191373340b2SMax Reitz     } else {
1192373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
1193373340b2SMax Reitz     }
11944be74634SMarkus Armbruster }
11954be74634SMarkus Armbruster 
11964be74634SMarkus Armbruster int blk_is_read_only(BlockBackend *blk)
11974be74634SMarkus Armbruster {
1198f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1199f21d96d0SKevin Wolf 
1200f21d96d0SKevin Wolf     if (bs) {
1201f21d96d0SKevin Wolf         return bdrv_is_read_only(bs);
1202061959e8SMax Reitz     } else {
1203061959e8SMax Reitz         return blk->root_state.read_only;
1204061959e8SMax Reitz     }
12054be74634SMarkus Armbruster }
12064be74634SMarkus Armbruster 
12074be74634SMarkus Armbruster int blk_is_sg(BlockBackend *blk)
12084be74634SMarkus Armbruster {
1209f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1210f21d96d0SKevin Wolf 
1211f21d96d0SKevin Wolf     if (!bs) {
1212a46fc9c9SMax Reitz         return 0;
1213a46fc9c9SMax Reitz     }
1214a46fc9c9SMax Reitz 
1215f21d96d0SKevin Wolf     return bdrv_is_sg(bs);
12164be74634SMarkus Armbruster }
12174be74634SMarkus Armbruster 
12184be74634SMarkus Armbruster int blk_enable_write_cache(BlockBackend *blk)
12194be74634SMarkus Armbruster {
1220bfd18d1eSKevin Wolf     return blk->enable_write_cache;
12214be74634SMarkus Armbruster }
12224be74634SMarkus Armbruster 
12234be74634SMarkus Armbruster void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
12244be74634SMarkus Armbruster {
1225bfd18d1eSKevin Wolf     blk->enable_write_cache = wce;
12264be74634SMarkus Armbruster }
12274be74634SMarkus Armbruster 
12282bb0dce7SMax Reitz void blk_invalidate_cache(BlockBackend *blk, Error **errp)
12292bb0dce7SMax Reitz {
1230f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1231f21d96d0SKevin Wolf 
1232f21d96d0SKevin Wolf     if (!bs) {
1233c09ba36cSMax Reitz         error_setg(errp, "Device '%s' has no medium", blk->name);
1234c09ba36cSMax Reitz         return;
1235c09ba36cSMax Reitz     }
1236c09ba36cSMax Reitz 
1237f21d96d0SKevin Wolf     bdrv_invalidate_cache(bs, errp);
12382bb0dce7SMax Reitz }
12392bb0dce7SMax Reitz 
1240e031f750SMax Reitz bool blk_is_inserted(BlockBackend *blk)
12414be74634SMarkus Armbruster {
1242f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1243f21d96d0SKevin Wolf 
1244f21d96d0SKevin Wolf     return bs && bdrv_is_inserted(bs);
1245db0284f8SMax Reitz }
1246db0284f8SMax Reitz 
1247db0284f8SMax Reitz bool blk_is_available(BlockBackend *blk)
1248db0284f8SMax Reitz {
1249db0284f8SMax Reitz     return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
12504be74634SMarkus Armbruster }
12514be74634SMarkus Armbruster 
12524be74634SMarkus Armbruster void blk_lock_medium(BlockBackend *blk, bool locked)
12534be74634SMarkus Armbruster {
1254f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1255f21d96d0SKevin Wolf 
1256f21d96d0SKevin Wolf     if (bs) {
1257f21d96d0SKevin Wolf         bdrv_lock_medium(bs, locked);
12584be74634SMarkus Armbruster     }
1259a46fc9c9SMax Reitz }
12604be74634SMarkus Armbruster 
12614be74634SMarkus Armbruster void blk_eject(BlockBackend *blk, bool eject_flag)
12624be74634SMarkus Armbruster {
1263f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1264f21d96d0SKevin Wolf 
1265f21d96d0SKevin Wolf     if (bs) {
1266f21d96d0SKevin Wolf         bdrv_eject(bs, eject_flag);
12674be74634SMarkus Armbruster     }
1268a46fc9c9SMax Reitz }
12694be74634SMarkus Armbruster 
12704be74634SMarkus Armbruster int blk_get_flags(BlockBackend *blk)
12714be74634SMarkus Armbruster {
1272f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1273f21d96d0SKevin Wolf 
1274f21d96d0SKevin Wolf     if (bs) {
1275f21d96d0SKevin Wolf         return bdrv_get_flags(bs);
1276061959e8SMax Reitz     } else {
1277061959e8SMax Reitz         return blk->root_state.open_flags;
1278061959e8SMax Reitz     }
12794be74634SMarkus Armbruster }
12804be74634SMarkus Armbruster 
1281454057b7SPeter Lieven int blk_get_max_transfer_length(BlockBackend *blk)
1282454057b7SPeter Lieven {
1283f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1284f21d96d0SKevin Wolf 
1285f21d96d0SKevin Wolf     if (bs) {
1286f21d96d0SKevin Wolf         return bs->bl.max_transfer_length;
1287a46fc9c9SMax Reitz     } else {
1288a46fc9c9SMax Reitz         return 0;
1289a46fc9c9SMax Reitz     }
1290454057b7SPeter Lieven }
1291454057b7SPeter Lieven 
1292648296e0SStefan Hajnoczi int blk_get_max_iov(BlockBackend *blk)
1293648296e0SStefan Hajnoczi {
1294f21d96d0SKevin Wolf     return blk->root->bs->bl.max_iov;
1295648296e0SStefan Hajnoczi }
1296648296e0SStefan Hajnoczi 
12974be74634SMarkus Armbruster void blk_set_guest_block_size(BlockBackend *blk, int align)
12984be74634SMarkus Armbruster {
129968e9ec01SMax Reitz     blk->guest_block_size = align;
13004be74634SMarkus Armbruster }
13014be74634SMarkus Armbruster 
1302f1c17521SPaolo Bonzini void *blk_try_blockalign(BlockBackend *blk, size_t size)
1303f1c17521SPaolo Bonzini {
1304f21d96d0SKevin Wolf     return qemu_try_blockalign(blk ? blk_bs(blk) : NULL, size);
1305f1c17521SPaolo Bonzini }
1306f1c17521SPaolo Bonzini 
13074be74634SMarkus Armbruster void *blk_blockalign(BlockBackend *blk, size_t size)
13084be74634SMarkus Armbruster {
1309f21d96d0SKevin Wolf     return qemu_blockalign(blk ? blk_bs(blk) : NULL, size);
13104be74634SMarkus Armbruster }
13114be74634SMarkus Armbruster 
13124be74634SMarkus Armbruster bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
13134be74634SMarkus Armbruster {
1314f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1315f21d96d0SKevin Wolf 
1316f21d96d0SKevin Wolf     if (!bs) {
1317a46fc9c9SMax Reitz         return false;
1318a46fc9c9SMax Reitz     }
1319a46fc9c9SMax Reitz 
1320f21d96d0SKevin Wolf     return bdrv_op_is_blocked(bs, op, errp);
13214be74634SMarkus Armbruster }
13224be74634SMarkus Armbruster 
13234be74634SMarkus Armbruster void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
13244be74634SMarkus Armbruster {
1325f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1326f21d96d0SKevin Wolf 
1327f21d96d0SKevin Wolf     if (bs) {
1328f21d96d0SKevin Wolf         bdrv_op_unblock(bs, op, reason);
13294be74634SMarkus Armbruster     }
1330a46fc9c9SMax Reitz }
13314be74634SMarkus Armbruster 
13324be74634SMarkus Armbruster void blk_op_block_all(BlockBackend *blk, Error *reason)
13334be74634SMarkus Armbruster {
1334f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1335f21d96d0SKevin Wolf 
1336f21d96d0SKevin Wolf     if (bs) {
1337f21d96d0SKevin Wolf         bdrv_op_block_all(bs, reason);
13384be74634SMarkus Armbruster     }
1339a46fc9c9SMax Reitz }
13404be74634SMarkus Armbruster 
13414be74634SMarkus Armbruster void blk_op_unblock_all(BlockBackend *blk, Error *reason)
13424be74634SMarkus Armbruster {
1343f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1344f21d96d0SKevin Wolf 
1345f21d96d0SKevin Wolf     if (bs) {
1346f21d96d0SKevin Wolf         bdrv_op_unblock_all(bs, reason);
13474be74634SMarkus Armbruster     }
1348a46fc9c9SMax Reitz }
13494be74634SMarkus Armbruster 
13504be74634SMarkus Armbruster AioContext *blk_get_aio_context(BlockBackend *blk)
13514be74634SMarkus Armbruster {
1352f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1353f21d96d0SKevin Wolf 
1354f21d96d0SKevin Wolf     if (bs) {
1355f21d96d0SKevin Wolf         return bdrv_get_aio_context(bs);
13564981bdecSMax Reitz     } else {
13574981bdecSMax Reitz         return qemu_get_aio_context();
13584981bdecSMax Reitz     }
13594981bdecSMax Reitz }
13604981bdecSMax Reitz 
13614981bdecSMax Reitz static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
13624981bdecSMax Reitz {
13634981bdecSMax Reitz     BlockBackendAIOCB *blk_acb = DO_UPCAST(BlockBackendAIOCB, common, acb);
13644981bdecSMax Reitz     return blk_get_aio_context(blk_acb->blk);
13654be74634SMarkus Armbruster }
13664be74634SMarkus Armbruster 
13674be74634SMarkus Armbruster void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
13684be74634SMarkus Armbruster {
1369f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1370f21d96d0SKevin Wolf 
1371f21d96d0SKevin Wolf     if (bs) {
1372f21d96d0SKevin Wolf         bdrv_set_aio_context(bs, new_context);
13734be74634SMarkus Armbruster     }
1374a46fc9c9SMax Reitz }
13754be74634SMarkus Armbruster 
13762019ba0aSMax Reitz void blk_add_aio_context_notifier(BlockBackend *blk,
13772019ba0aSMax Reitz         void (*attached_aio_context)(AioContext *new_context, void *opaque),
13782019ba0aSMax Reitz         void (*detach_aio_context)(void *opaque), void *opaque)
13792019ba0aSMax Reitz {
1380f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1381f21d96d0SKevin Wolf 
1382f21d96d0SKevin Wolf     if (bs) {
1383f21d96d0SKevin Wolf         bdrv_add_aio_context_notifier(bs, attached_aio_context,
13842019ba0aSMax Reitz                                       detach_aio_context, opaque);
13852019ba0aSMax Reitz     }
1386a46fc9c9SMax Reitz }
13872019ba0aSMax Reitz 
13882019ba0aSMax Reitz void blk_remove_aio_context_notifier(BlockBackend *blk,
13892019ba0aSMax Reitz                                      void (*attached_aio_context)(AioContext *,
13902019ba0aSMax Reitz                                                                   void *),
13912019ba0aSMax Reitz                                      void (*detach_aio_context)(void *),
13922019ba0aSMax Reitz                                      void *opaque)
13932019ba0aSMax Reitz {
1394f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1395f21d96d0SKevin Wolf 
1396f21d96d0SKevin Wolf     if (bs) {
1397f21d96d0SKevin Wolf         bdrv_remove_aio_context_notifier(bs, attached_aio_context,
13982019ba0aSMax Reitz                                          detach_aio_context, opaque);
13992019ba0aSMax Reitz     }
1400a46fc9c9SMax Reitz }
14012019ba0aSMax Reitz 
14023301f6c6SMax Reitz void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
14033301f6c6SMax Reitz {
14043301f6c6SMax Reitz     notifier_list_add(&blk->remove_bs_notifiers, notify);
14053301f6c6SMax Reitz }
14063301f6c6SMax Reitz 
14073301f6c6SMax Reitz void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
14083301f6c6SMax Reitz {
14093301f6c6SMax Reitz     notifier_list_add(&blk->insert_bs_notifiers, notify);
14103301f6c6SMax Reitz }
14113301f6c6SMax Reitz 
14124be74634SMarkus Armbruster void blk_io_plug(BlockBackend *blk)
14134be74634SMarkus Armbruster {
1414f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1415f21d96d0SKevin Wolf 
1416f21d96d0SKevin Wolf     if (bs) {
1417f21d96d0SKevin Wolf         bdrv_io_plug(bs);
14184be74634SMarkus Armbruster     }
1419a46fc9c9SMax Reitz }
14204be74634SMarkus Armbruster 
14214be74634SMarkus Armbruster void blk_io_unplug(BlockBackend *blk)
14224be74634SMarkus Armbruster {
1423f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
1424f21d96d0SKevin Wolf 
1425f21d96d0SKevin Wolf     if (bs) {
1426f21d96d0SKevin Wolf         bdrv_io_unplug(bs);
14274be74634SMarkus Armbruster     }
1428a46fc9c9SMax Reitz }
14294be74634SMarkus Armbruster 
14304be74634SMarkus Armbruster BlockAcctStats *blk_get_stats(BlockBackend *blk)
14314be74634SMarkus Armbruster {
14327f0e9da6SMax Reitz     return &blk->stats;
14334be74634SMarkus Armbruster }
14344be74634SMarkus Armbruster 
14354be74634SMarkus Armbruster void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
14364be74634SMarkus Armbruster                   BlockCompletionFunc *cb, void *opaque)
14374be74634SMarkus Armbruster {
14384be74634SMarkus Armbruster     return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
14394be74634SMarkus Armbruster }
14401ef01253SMax Reitz 
1441983a1600SEric Blake int coroutine_fn blk_co_write_zeroes(BlockBackend *blk, int64_t offset,
1442983a1600SEric Blake                                      int count, BdrvRequestFlags flags)
14431ef01253SMax Reitz {
1444983a1600SEric Blake     return blk_co_pwritev(blk, offset, count, NULL,
144516aaf975SKevin Wolf                           flags | BDRV_REQ_ZERO_WRITE);
14461ef01253SMax Reitz }
14471ef01253SMax Reitz 
14481ef01253SMax Reitz int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
14491ef01253SMax Reitz                          const uint8_t *buf, int nb_sectors)
14501ef01253SMax Reitz {
1451e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1452e7f7d676SMax Reitz     if (ret < 0) {
1453e7f7d676SMax Reitz         return ret;
1454e7f7d676SMax Reitz     }
1455e7f7d676SMax Reitz 
1456f21d96d0SKevin Wolf     return bdrv_write_compressed(blk_bs(blk), sector_num, buf, nb_sectors);
14571ef01253SMax Reitz }
14581ef01253SMax Reitz 
14591ef01253SMax Reitz int blk_truncate(BlockBackend *blk, int64_t offset)
14601ef01253SMax Reitz {
1461c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1462c09ba36cSMax Reitz         return -ENOMEDIUM;
1463c09ba36cSMax Reitz     }
1464c09ba36cSMax Reitz 
1465f21d96d0SKevin Wolf     return bdrv_truncate(blk_bs(blk), offset);
14661ef01253SMax Reitz }
14671ef01253SMax Reitz 
14681ef01253SMax Reitz int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
14691ef01253SMax Reitz {
1470e7f7d676SMax Reitz     int ret = blk_check_request(blk, sector_num, nb_sectors);
1471e7f7d676SMax Reitz     if (ret < 0) {
1472e7f7d676SMax Reitz         return ret;
1473e7f7d676SMax Reitz     }
1474e7f7d676SMax Reitz 
1475f21d96d0SKevin Wolf     return bdrv_discard(blk_bs(blk), sector_num, nb_sectors);
14761ef01253SMax Reitz }
14771ef01253SMax Reitz 
14781ef01253SMax Reitz int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
14791ef01253SMax Reitz                      int64_t pos, int size)
14801ef01253SMax Reitz {
1481bfd18d1eSKevin Wolf     int ret;
1482bfd18d1eSKevin Wolf 
1483c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1484c09ba36cSMax Reitz         return -ENOMEDIUM;
1485c09ba36cSMax Reitz     }
1486c09ba36cSMax Reitz 
1487bfd18d1eSKevin Wolf     ret = bdrv_save_vmstate(blk_bs(blk), buf, pos, size);
1488bfd18d1eSKevin Wolf     if (ret < 0) {
1489bfd18d1eSKevin Wolf         return ret;
1490bfd18d1eSKevin Wolf     }
1491bfd18d1eSKevin Wolf 
1492bfd18d1eSKevin Wolf     if (ret == size && !blk->enable_write_cache) {
1493bfd18d1eSKevin Wolf         ret = bdrv_flush(blk_bs(blk));
1494bfd18d1eSKevin Wolf     }
1495bfd18d1eSKevin Wolf 
1496bfd18d1eSKevin Wolf     return ret < 0 ? ret : size;
14971ef01253SMax Reitz }
14981ef01253SMax Reitz 
14991ef01253SMax Reitz int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
15001ef01253SMax Reitz {
1501c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1502c09ba36cSMax Reitz         return -ENOMEDIUM;
1503c09ba36cSMax Reitz     }
1504c09ba36cSMax Reitz 
1505f21d96d0SKevin Wolf     return bdrv_load_vmstate(blk_bs(blk), buf, pos, size);
15061ef01253SMax Reitz }
1507f0272c4dSEkaterina Tumanova 
1508f0272c4dSEkaterina Tumanova int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz)
1509f0272c4dSEkaterina Tumanova {
1510c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1511c09ba36cSMax Reitz         return -ENOMEDIUM;
1512c09ba36cSMax Reitz     }
1513c09ba36cSMax Reitz 
1514f21d96d0SKevin Wolf     return bdrv_probe_blocksizes(blk_bs(blk), bsz);
1515f0272c4dSEkaterina Tumanova }
1516f0272c4dSEkaterina Tumanova 
1517f0272c4dSEkaterina Tumanova int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo)
1518f0272c4dSEkaterina Tumanova {
1519c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
1520c09ba36cSMax Reitz         return -ENOMEDIUM;
1521c09ba36cSMax Reitz     }
1522c09ba36cSMax Reitz 
1523f21d96d0SKevin Wolf     return bdrv_probe_geometry(blk_bs(blk), geo);
1524f0272c4dSEkaterina Tumanova }
1525281d22d8SMax Reitz 
1526281d22d8SMax Reitz /*
1527281d22d8SMax Reitz  * Updates the BlockBackendRootState object with data from the currently
1528281d22d8SMax Reitz  * attached BlockDriverState.
1529281d22d8SMax Reitz  */
1530281d22d8SMax Reitz void blk_update_root_state(BlockBackend *blk)
1531281d22d8SMax Reitz {
1532f21d96d0SKevin Wolf     assert(blk->root);
1533281d22d8SMax Reitz 
1534f21d96d0SKevin Wolf     blk->root_state.open_flags    = blk->root->bs->open_flags;
1535f21d96d0SKevin Wolf     blk->root_state.read_only     = blk->root->bs->read_only;
1536f21d96d0SKevin Wolf     blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
1537281d22d8SMax Reitz 
1538281d22d8SMax Reitz     if (blk->root_state.throttle_group) {
1539281d22d8SMax Reitz         g_free(blk->root_state.throttle_group);
1540281d22d8SMax Reitz         throttle_group_unref(blk->root_state.throttle_state);
1541281d22d8SMax Reitz     }
154227ccdd52SKevin Wolf     if (blk->public.throttle_state) {
154349d2165dSKevin Wolf         const char *name = throttle_group_get_name(blk);
1544281d22d8SMax Reitz         blk->root_state.throttle_group = g_strdup(name);
1545281d22d8SMax Reitz         blk->root_state.throttle_state = throttle_group_incref(name);
1546281d22d8SMax Reitz     } else {
1547281d22d8SMax Reitz         blk->root_state.throttle_group = NULL;
1548281d22d8SMax Reitz         blk->root_state.throttle_state = NULL;
1549281d22d8SMax Reitz     }
1550281d22d8SMax Reitz }
1551281d22d8SMax Reitz 
155238cb18f5SMax Reitz /*
155338cb18f5SMax Reitz  * Applies the information in the root state to the given BlockDriverState. This
155438cb18f5SMax Reitz  * does not include the flags which have to be specified for bdrv_open(), use
155538cb18f5SMax Reitz  * blk_get_open_flags_from_root_state() to inquire them.
155638cb18f5SMax Reitz  */
155738cb18f5SMax Reitz void blk_apply_root_state(BlockBackend *blk, BlockDriverState *bs)
155838cb18f5SMax Reitz {
155938cb18f5SMax Reitz     bs->detect_zeroes = blk->root_state.detect_zeroes;
156038cb18f5SMax Reitz     if (blk->root_state.throttle_group) {
156197148076SKevin Wolf         blk_io_limits_enable(blk, blk->root_state.throttle_group);
156238cb18f5SMax Reitz     }
156338cb18f5SMax Reitz }
156438cb18f5SMax Reitz 
156538cb18f5SMax Reitz /*
156638cb18f5SMax Reitz  * Returns the flags to be used for bdrv_open() of a BlockDriverState which is
156738cb18f5SMax Reitz  * supposed to inherit the root state.
156838cb18f5SMax Reitz  */
156938cb18f5SMax Reitz int blk_get_open_flags_from_root_state(BlockBackend *blk)
157038cb18f5SMax Reitz {
157138cb18f5SMax Reitz     int bs_flags;
157238cb18f5SMax Reitz 
157338cb18f5SMax Reitz     bs_flags = blk->root_state.read_only ? 0 : BDRV_O_RDWR;
157438cb18f5SMax Reitz     bs_flags |= blk->root_state.open_flags & ~BDRV_O_RDWR;
157538cb18f5SMax Reitz 
157638cb18f5SMax Reitz     return bs_flags;
157738cb18f5SMax Reitz }
157838cb18f5SMax Reitz 
1579281d22d8SMax Reitz BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
1580281d22d8SMax Reitz {
1581281d22d8SMax Reitz     return &blk->root_state;
1582281d22d8SMax Reitz }
15831393f212SMax Reitz 
15841393f212SMax Reitz int blk_commit_all(void)
15851393f212SMax Reitz {
1586fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
1587fe1a9cbcSMax Reitz 
1588fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
1589fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
1590fe1a9cbcSMax Reitz 
1591fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
1592f21d96d0SKevin Wolf         if (blk_is_inserted(blk) && blk->root->bs->backing) {
1593f21d96d0SKevin Wolf             int ret = bdrv_commit(blk->root->bs);
1594fe1a9cbcSMax Reitz             if (ret < 0) {
1595fe1a9cbcSMax Reitz                 aio_context_release(aio_context);
1596fe1a9cbcSMax Reitz                 return ret;
1597fe1a9cbcSMax Reitz             }
1598fe1a9cbcSMax Reitz         }
1599fe1a9cbcSMax Reitz         aio_context_release(aio_context);
1600fe1a9cbcSMax Reitz     }
1601fe1a9cbcSMax Reitz     return 0;
1602fe1a9cbcSMax Reitz }
1603fe1a9cbcSMax Reitz 
1604fe1a9cbcSMax Reitz int blk_flush_all(void)
1605fe1a9cbcSMax Reitz {
1606fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
1607fe1a9cbcSMax Reitz     int result = 0;
1608fe1a9cbcSMax Reitz 
1609fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
1610fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
1611fe1a9cbcSMax Reitz         int ret;
1612fe1a9cbcSMax Reitz 
1613fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
1614fe1a9cbcSMax Reitz         if (blk_is_inserted(blk)) {
1615fe1a9cbcSMax Reitz             ret = blk_flush(blk);
1616fe1a9cbcSMax Reitz             if (ret < 0 && !result) {
1617fe1a9cbcSMax Reitz                 result = ret;
1618fe1a9cbcSMax Reitz             }
1619fe1a9cbcSMax Reitz         }
1620fe1a9cbcSMax Reitz         aio_context_release(aio_context);
1621fe1a9cbcSMax Reitz     }
1622fe1a9cbcSMax Reitz 
1623fe1a9cbcSMax Reitz     return result;
16241393f212SMax Reitz }
162597148076SKevin Wolf 
162697148076SKevin Wolf 
162797148076SKevin Wolf /* throttling disk I/O limits */
162897148076SKevin Wolf void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
162997148076SKevin Wolf {
163097148076SKevin Wolf     throttle_group_config(blk, cfg);
163197148076SKevin Wolf }
163297148076SKevin Wolf 
163397148076SKevin Wolf void blk_io_limits_disable(BlockBackend *blk)
163497148076SKevin Wolf {
163597148076SKevin Wolf     assert(blk->public.throttle_state);
163697148076SKevin Wolf     bdrv_no_throttling_begin(blk_bs(blk));
163797148076SKevin Wolf     throttle_group_unregister_blk(blk);
163897148076SKevin Wolf     bdrv_no_throttling_end(blk_bs(blk));
163997148076SKevin Wolf }
164097148076SKevin Wolf 
164197148076SKevin Wolf /* should be called before blk_set_io_limits if a limit is set */
164297148076SKevin Wolf void blk_io_limits_enable(BlockBackend *blk, const char *group)
164397148076SKevin Wolf {
164497148076SKevin Wolf     assert(!blk->public.throttle_state);
164597148076SKevin Wolf     throttle_group_register_blk(blk, group);
164697148076SKevin Wolf }
164797148076SKevin Wolf 
164897148076SKevin Wolf void blk_io_limits_update_group(BlockBackend *blk, const char *group)
164997148076SKevin Wolf {
165097148076SKevin Wolf     /* this BB is not part of any group */
165197148076SKevin Wolf     if (!blk->public.throttle_state) {
165297148076SKevin Wolf         return;
165397148076SKevin Wolf     }
165497148076SKevin Wolf 
165597148076SKevin Wolf     /* this BB is a part of the same group than the one we want */
165697148076SKevin Wolf     if (!g_strcmp0(throttle_group_get_name(blk), group)) {
165797148076SKevin Wolf         return;
165897148076SKevin Wolf     }
165997148076SKevin Wolf 
166097148076SKevin Wolf     /* need to change the group this bs belong to */
166197148076SKevin Wolf     blk_io_limits_disable(blk);
166297148076SKevin Wolf     blk_io_limits_enable(blk, group);
166397148076SKevin Wolf }
1664