xref: /openbmc/qemu/block/block-backend.c (revision 6bc0bcc8)
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"
1716d36e29SVladimir Sementsov-Ogievskiy #include "block/coroutines.h"
18281d22d8SMax Reitz #include "block/throttle-groups.h"
1913d4ff07SMarkus Armbruster #include "hw/qdev-core.h"
2018e46a03SMarkus Armbruster #include "sysemu/blockdev.h"
2154d31236SMarkus Armbruster #include "sysemu/runstate.h"
22e4ec5ad4SPavel Dovgalyuk #include "sysemu/replay.h"
23e688df6bSMarkus Armbruster #include "qapi/error.h"
249af23989SMarkus Armbruster #include "qapi/qapi-events-block.h"
25f348b6d1SVeronia Bahaa #include "qemu/id.h"
26db725815SMarkus Armbruster #include "qemu/main-loop.h"
27922a01a0SMarkus Armbruster #include "qemu/option.h"
281e98fefdSKevin Wolf #include "trace.h"
295f7772c4SFam Zheng #include "migration/misc.h"
30a7f53e26SMarkus Armbruster 
31a7f53e26SMarkus Armbruster /* Number of coroutines to reserve per attached device model */
32a7f53e26SMarkus Armbruster #define COROUTINE_POOL_RESERVATION 64
3326f54e9aSMarkus Armbruster 
341bf1cbc9SKevin Wolf #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
351bf1cbc9SKevin Wolf 
36d03654eaSStefan Hajnoczi typedef struct BlockBackendAioNotifier {
37d03654eaSStefan Hajnoczi     void (*attached_aio_context)(AioContext *new_context, void *opaque);
38d03654eaSStefan Hajnoczi     void (*detach_aio_context)(void *opaque);
39d03654eaSStefan Hajnoczi     void *opaque;
40d03654eaSStefan Hajnoczi     QLIST_ENTRY(BlockBackendAioNotifier) list;
41d03654eaSStefan Hajnoczi } BlockBackendAioNotifier;
42d03654eaSStefan Hajnoczi 
4326f54e9aSMarkus Armbruster struct BlockBackend {
4426f54e9aSMarkus Armbruster     char *name;
4526f54e9aSMarkus Armbruster     int refcnt;
46f21d96d0SKevin Wolf     BdrvChild *root;
47d861ab3aSKevin Wolf     AioContext *ctx;
4826f8b3a8SMarkus Armbruster     DriveInfo *legacy_dinfo;    /* null unless created by drive_new() */
492cf22d6aSMax Reitz     QTAILQ_ENTRY(BlockBackend) link;         /* for block_backends */
509492b0b9SMax Reitz     QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
51f2cd875dSKevin Wolf     BlockBackendPublic public;
52a7f53e26SMarkus Armbruster 
53d09ea2d2SThomas Huth     DeviceState *dev;           /* attached device model, if any */
54a7f53e26SMarkus Armbruster     const BlockDevOps *dev_ops;
55a7f53e26SMarkus Armbruster     void *dev_opaque;
5668e9ec01SMax Reitz 
57281d22d8SMax Reitz     /* If the BDS tree is removed, some of its options are stored here (which
58281d22d8SMax Reitz      * can be used to restore those options in the new BDS on insert) */
59281d22d8SMax Reitz     BlockBackendRootState root_state;
60281d22d8SMax Reitz 
61bfd18d1eSKevin Wolf     bool enable_write_cache;
62bfd18d1eSKevin Wolf 
637f0e9da6SMax Reitz     /* I/O stats (display with "info blockstats"). */
647f0e9da6SMax Reitz     BlockAcctStats stats;
65373340b2SMax Reitz 
66373340b2SMax Reitz     BlockdevOnError on_read_error, on_write_error;
67373340b2SMax Reitz     bool iostatus_enabled;
68373340b2SMax Reitz     BlockDeviceIoStatus iostatus;
693301f6c6SMax Reitz 
70981776b3SKevin Wolf     uint64_t perm;
71981776b3SKevin Wolf     uint64_t shared_perm;
72d35ff5e6SKevin Wolf     bool disable_perm;
73981776b3SKevin Wolf 
74980b0f94SKevin Wolf     bool allow_aio_context_change;
75c10c9d96SKevin Wolf     bool allow_write_beyond_eof;
76c10c9d96SKevin Wolf 
77a2c4c3b1SEmanuele Giuseppe Esposito     /* Protected by BQL */
783301f6c6SMax Reitz     NotifierList remove_bs_notifiers, insert_bs_notifiers;
79d03654eaSStefan Hajnoczi     QLIST_HEAD(, BlockBackendAioNotifier) aio_notifiers;
80f4d9cc88SJohn Snow 
81c4d5bf99SStefan Hajnoczi     int quiesce_counter; /* atomic: written under BQL, read by other threads */
82407ae2aeSStefan Hajnoczi     QemuMutex queued_requests_lock; /* protects queued_requests */
83cf312932SKevin Wolf     CoQueue queued_requests;
84ef80ec50SStefan Hajnoczi     bool disable_request_queuing; /* atomic */
85cf312932SKevin Wolf 
865f7772c4SFam Zheng     VMChangeStateEntry *vmsh;
87ca2e2144SFam Zheng     bool force_allow_inactivate;
8833f2a757SStefan Hajnoczi 
8933f2a757SStefan Hajnoczi     /* Number of in-flight aio requests.  BlockDriverState also counts
9033f2a757SStefan Hajnoczi      * in-flight requests but aio requests can exist even when blk->root is
9133f2a757SStefan Hajnoczi      * NULL, so we cannot rely on its counter for that case.
9233f2a757SStefan Hajnoczi      * Accessed with atomic ops.
9333f2a757SStefan Hajnoczi      */
9433f2a757SStefan Hajnoczi     unsigned int in_flight;
9526f54e9aSMarkus Armbruster };
9626f54e9aSMarkus Armbruster 
97e7f7d676SMax Reitz typedef struct BlockBackendAIOCB {
98e7f7d676SMax Reitz     BlockAIOCB common;
994981bdecSMax Reitz     BlockBackend *blk;
100e7f7d676SMax Reitz     int ret;
101e7f7d676SMax Reitz } BlockBackendAIOCB;
102e7f7d676SMax Reitz 
103e7f7d676SMax Reitz static const AIOCBInfo block_backend_aiocb_info = {
104e7f7d676SMax Reitz     .aiocb_size = sizeof(BlockBackendAIOCB),
105e7f7d676SMax Reitz };
106e7f7d676SMax Reitz 
1078fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo);
1087c8eece4SKevin Wolf static BlockBackend *bdrv_first_blk(BlockDriverState *bs);
1098fb3c76cSMarkus Armbruster 
110a2c4c3b1SEmanuele Giuseppe Esposito /* All BlockBackends. Protected by BQL. */
1112cf22d6aSMax Reitz static QTAILQ_HEAD(, BlockBackend) block_backends =
1122cf22d6aSMax Reitz     QTAILQ_HEAD_INITIALIZER(block_backends);
1132cf22d6aSMax Reitz 
114a2c4c3b1SEmanuele Giuseppe Esposito /*
115a2c4c3b1SEmanuele Giuseppe Esposito  * All BlockBackends referenced by the monitor and which are iterated through by
116a2c4c3b1SEmanuele Giuseppe Esposito  * blk_next(). Protected by BQL.
117a2c4c3b1SEmanuele Giuseppe Esposito  */
1189492b0b9SMax Reitz static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
1199492b0b9SMax Reitz     QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
12026f54e9aSMarkus Armbruster 
1213804e3cfSKevin Wolf static int coroutine_mixed_fn GRAPH_RDLOCK
1223804e3cfSKevin Wolf blk_set_perm_locked(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
1233804e3cfSKevin Wolf                     Error **errp);
1243804e3cfSKevin Wolf 
blk_root_inherit_options(BdrvChildRole role,bool parent_is_format,int * child_flags,QDict * child_options,int parent_flags,QDict * parent_options)1253cdc69d3SMax Reitz static void blk_root_inherit_options(BdrvChildRole role, bool parent_is_format,
126272c02eaSMax Reitz                                      int *child_flags, QDict *child_options,
127f21d96d0SKevin Wolf                                      int parent_flags, QDict *parent_options)
128f21d96d0SKevin Wolf {
129f21d96d0SKevin Wolf     /* We're not supposed to call this function for root nodes */
130f21d96d0SKevin Wolf     abort();
131f21d96d0SKevin Wolf }
132c2066af0SKevin Wolf static void blk_root_drained_begin(BdrvChild *child);
133fe5258a5SKevin Wolf static bool blk_root_drained_poll(BdrvChild *child);
1342f65df6eSKevin Wolf static void blk_root_drained_end(BdrvChild *child);
135f21d96d0SKevin Wolf 
1365c8cab48SKevin Wolf static void blk_root_change_media(BdrvChild *child, bool load);
1375c8cab48SKevin Wolf static void blk_root_resize(BdrvChild *child);
1385c8cab48SKevin Wolf 
13933949396SEmanuele Giuseppe Esposito static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
14033949396SEmanuele Giuseppe Esposito                                     GHashTable *visited, Transaction *tran,
14133949396SEmanuele Giuseppe Esposito                                     Error **errp);
14238475269SKevin Wolf 
blk_root_get_parent_desc(BdrvChild * child)143b5411555SKevin Wolf static char *blk_root_get_parent_desc(BdrvChild *child)
144b5411555SKevin Wolf {
145b5411555SKevin Wolf     BlockBackend *blk = child->opaque;
146fd240a18SVladimir Sementsov-Ogievskiy     g_autofree char *dev_id = NULL;
147b5411555SKevin Wolf 
148b5411555SKevin Wolf     if (blk->name) {
149fd240a18SVladimir Sementsov-Ogievskiy         return g_strdup_printf("block device '%s'", blk->name);
150b5411555SKevin Wolf     }
151b5411555SKevin Wolf 
152b5411555SKevin Wolf     dev_id = blk_get_attached_dev_id(blk);
153b5411555SKevin Wolf     if (*dev_id) {
154fd240a18SVladimir Sementsov-Ogievskiy         return g_strdup_printf("block device '%s'", dev_id);
155b5411555SKevin Wolf     } else {
156b5411555SKevin Wolf         /* TODO Callback into the BB owner for something more detailed */
157fd240a18SVladimir Sementsov-Ogievskiy         return g_strdup("an unnamed block device");
158b5411555SKevin Wolf     }
159b5411555SKevin Wolf }
160b5411555SKevin Wolf 
blk_root_get_name(BdrvChild * child)1614c265bf9SKevin Wolf static const char *blk_root_get_name(BdrvChild *child)
1624c265bf9SKevin Wolf {
1634c265bf9SKevin Wolf     return blk_name(child->opaque);
1644c265bf9SKevin Wolf }
1654c265bf9SKevin Wolf 
blk_vm_state_changed(void * opaque,bool running,RunState state)166538f0497SPhilippe Mathieu-Daudé static void blk_vm_state_changed(void *opaque, bool running, RunState state)
1675f7772c4SFam Zheng {
1685f7772c4SFam Zheng     Error *local_err = NULL;
1695f7772c4SFam Zheng     BlockBackend *blk = opaque;
1705f7772c4SFam Zheng 
1715f7772c4SFam Zheng     if (state == RUN_STATE_INMIGRATE) {
1725f7772c4SFam Zheng         return;
1735f7772c4SFam Zheng     }
1745f7772c4SFam Zheng 
1755f7772c4SFam Zheng     qemu_del_vm_change_state_handler(blk->vmsh);
1765f7772c4SFam Zheng     blk->vmsh = NULL;
1775f7772c4SFam Zheng     blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
1785f7772c4SFam Zheng     if (local_err) {
1795f7772c4SFam Zheng         error_report_err(local_err);
1805f7772c4SFam Zheng     }
1815f7772c4SFam Zheng }
1825f7772c4SFam Zheng 
1834417ab7aSKevin Wolf /*
1844417ab7aSKevin Wolf  * Notifies the user of the BlockBackend that migration has completed. qdev
1854417ab7aSKevin Wolf  * devices can tighten their permissions in response (specifically revoke
1864417ab7aSKevin Wolf  * shared write permissions that we needed for storage migration).
1874417ab7aSKevin Wolf  *
1884417ab7aSKevin Wolf  * If an error is returned, the VM cannot be allowed to be resumed.
1894417ab7aSKevin Wolf  */
blk_root_activate(BdrvChild * child,Error ** errp)1903804e3cfSKevin Wolf static void GRAPH_RDLOCK blk_root_activate(BdrvChild *child, Error **errp)
1914417ab7aSKevin Wolf {
1924417ab7aSKevin Wolf     BlockBackend *blk = child->opaque;
1934417ab7aSKevin Wolf     Error *local_err = NULL;
194492a1196SHanna Reitz     uint64_t saved_shared_perm;
1954417ab7aSKevin Wolf 
1964417ab7aSKevin Wolf     if (!blk->disable_perm) {
1974417ab7aSKevin Wolf         return;
1984417ab7aSKevin Wolf     }
1994417ab7aSKevin Wolf 
2004417ab7aSKevin Wolf     blk->disable_perm = false;
2014417ab7aSKevin Wolf 
202492a1196SHanna Reitz     /*
203492a1196SHanna Reitz      * blk->shared_perm contains the permissions we want to share once
204492a1196SHanna Reitz      * migration is really completely done.  For now, we need to share
205492a1196SHanna Reitz      * all; but we also need to retain blk->shared_perm, which is
206492a1196SHanna Reitz      * overwritten by a successful blk_set_perm() call.  Save it and
207492a1196SHanna Reitz      * restore it below.
208492a1196SHanna Reitz      */
209492a1196SHanna Reitz     saved_shared_perm = blk->shared_perm;
210492a1196SHanna Reitz 
2113804e3cfSKevin Wolf     blk_set_perm_locked(blk, blk->perm, BLK_PERM_ALL, &local_err);
2125f7772c4SFam Zheng     if (local_err) {
2135f7772c4SFam Zheng         error_propagate(errp, local_err);
2145f7772c4SFam Zheng         blk->disable_perm = true;
2155f7772c4SFam Zheng         return;
2165f7772c4SFam Zheng     }
217492a1196SHanna Reitz     blk->shared_perm = saved_shared_perm;
2185f7772c4SFam Zheng 
2195f7772c4SFam Zheng     if (runstate_check(RUN_STATE_INMIGRATE)) {
2205f7772c4SFam Zheng         /* Activation can happen when migration process is still active, for
2215f7772c4SFam Zheng          * example when nbd_server_add is called during non-shared storage
2225f7772c4SFam Zheng          * migration. Defer the shared_perm update to migration completion. */
2235f7772c4SFam Zheng         if (!blk->vmsh) {
2245f7772c4SFam Zheng             blk->vmsh = qemu_add_vm_change_state_handler(blk_vm_state_changed,
2255f7772c4SFam Zheng                                                          blk);
2265f7772c4SFam Zheng         }
2275f7772c4SFam Zheng         return;
2285f7772c4SFam Zheng     }
2295f7772c4SFam Zheng 
2303804e3cfSKevin Wolf     blk_set_perm_locked(blk, blk->perm, blk->shared_perm, &local_err);
2314417ab7aSKevin Wolf     if (local_err) {
2324417ab7aSKevin Wolf         error_propagate(errp, local_err);
2334417ab7aSKevin Wolf         blk->disable_perm = true;
2344417ab7aSKevin Wolf         return;
2354417ab7aSKevin Wolf     }
2364417ab7aSKevin Wolf }
2374417ab7aSKevin Wolf 
blk_set_force_allow_inactivate(BlockBackend * blk)238ca2e2144SFam Zheng void blk_set_force_allow_inactivate(BlockBackend *blk)
239ca2e2144SFam Zheng {
2400439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
241ca2e2144SFam Zheng     blk->force_allow_inactivate = true;
242ca2e2144SFam Zheng }
243ca2e2144SFam Zheng 
blk_can_inactivate(BlockBackend * blk)244c16de8f5SFam Zheng static bool blk_can_inactivate(BlockBackend *blk)
245c16de8f5SFam Zheng {
246ca2e2144SFam Zheng     /* If it is a guest device, inactivate is ok. */
247c16de8f5SFam Zheng     if (blk->dev || blk_name(blk)[0]) {
248c16de8f5SFam Zheng         return true;
249c16de8f5SFam Zheng     }
250c16de8f5SFam Zheng 
251ca2e2144SFam Zheng     /* Inactivating means no more writes to the image can be done,
252ca2e2144SFam Zheng      * even if those writes would be changes invisible to the
253ca2e2144SFam Zheng      * guest.  For block job BBs that satisfy this, we can just allow
254ca2e2144SFam Zheng      * it.  This is the case for mirror job source, which is required
255ca2e2144SFam Zheng      * by libvirt non-shared block migration. */
256ca2e2144SFam Zheng     if (!(blk->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED))) {
257ca2e2144SFam Zheng         return true;
258ca2e2144SFam Zheng     }
259ca2e2144SFam Zheng 
260ca2e2144SFam Zheng     return blk->force_allow_inactivate;
261c16de8f5SFam Zheng }
262c16de8f5SFam Zheng 
blk_root_inactivate(BdrvChild * child)2633804e3cfSKevin Wolf static int GRAPH_RDLOCK blk_root_inactivate(BdrvChild *child)
264cfa1a572SKevin Wolf {
265cfa1a572SKevin Wolf     BlockBackend *blk = child->opaque;
266cfa1a572SKevin Wolf 
267cfa1a572SKevin Wolf     if (blk->disable_perm) {
268cfa1a572SKevin Wolf         return 0;
269cfa1a572SKevin Wolf     }
270cfa1a572SKevin Wolf 
271c16de8f5SFam Zheng     if (!blk_can_inactivate(blk)) {
272cfa1a572SKevin Wolf         return -EPERM;
273cfa1a572SKevin Wolf     }
274cfa1a572SKevin Wolf 
275cfa1a572SKevin Wolf     blk->disable_perm = true;
276cfa1a572SKevin Wolf     if (blk->root) {
277cfa1a572SKevin Wolf         bdrv_child_try_set_perm(blk->root, 0, BLK_PERM_ALL, &error_abort);
278cfa1a572SKevin Wolf     }
279cfa1a572SKevin Wolf 
280cfa1a572SKevin Wolf     return 0;
281cfa1a572SKevin Wolf }
282cfa1a572SKevin Wolf 
blk_root_attach(BdrvChild * child)283d03654eaSStefan Hajnoczi static void blk_root_attach(BdrvChild *child)
284d03654eaSStefan Hajnoczi {
285d03654eaSStefan Hajnoczi     BlockBackend *blk = child->opaque;
286d03654eaSStefan Hajnoczi     BlockBackendAioNotifier *notifier;
287d03654eaSStefan Hajnoczi 
288d03654eaSStefan Hajnoczi     trace_blk_root_attach(child, blk, child->bs);
289d03654eaSStefan Hajnoczi 
290d03654eaSStefan Hajnoczi     QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
291d03654eaSStefan Hajnoczi         bdrv_add_aio_context_notifier(child->bs,
292d03654eaSStefan Hajnoczi                 notifier->attached_aio_context,
293d03654eaSStefan Hajnoczi                 notifier->detach_aio_context,
294d03654eaSStefan Hajnoczi                 notifier->opaque);
295d03654eaSStefan Hajnoczi     }
296d03654eaSStefan Hajnoczi }
297d03654eaSStefan Hajnoczi 
blk_root_detach(BdrvChild * child)298d03654eaSStefan Hajnoczi static void blk_root_detach(BdrvChild *child)
299d03654eaSStefan Hajnoczi {
300d03654eaSStefan Hajnoczi     BlockBackend *blk = child->opaque;
301d03654eaSStefan Hajnoczi     BlockBackendAioNotifier *notifier;
302d03654eaSStefan Hajnoczi 
303d03654eaSStefan Hajnoczi     trace_blk_root_detach(child, blk, child->bs);
304d03654eaSStefan Hajnoczi 
305d03654eaSStefan Hajnoczi     QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
306d03654eaSStefan Hajnoczi         bdrv_remove_aio_context_notifier(child->bs,
307d03654eaSStefan Hajnoczi                 notifier->attached_aio_context,
308d03654eaSStefan Hajnoczi                 notifier->detach_aio_context,
309d03654eaSStefan Hajnoczi                 notifier->opaque);
310d03654eaSStefan Hajnoczi     }
311d03654eaSStefan Hajnoczi }
312d03654eaSStefan Hajnoczi 
blk_root_get_parent_aio_context(BdrvChild * c)3133ca1f322SVladimir Sementsov-Ogievskiy static AioContext *blk_root_get_parent_aio_context(BdrvChild *c)
3143ca1f322SVladimir Sementsov-Ogievskiy {
3153ca1f322SVladimir Sementsov-Ogievskiy     BlockBackend *blk = c->opaque;
316d5f8d79cSHanna Reitz     IO_CODE();
3173ca1f322SVladimir Sementsov-Ogievskiy 
3183ca1f322SVladimir Sementsov-Ogievskiy     return blk_get_aio_context(blk);
3193ca1f322SVladimir Sementsov-Ogievskiy }
3203ca1f322SVladimir Sementsov-Ogievskiy 
321bd86fb99SMax Reitz static const BdrvChildClass child_root = {
322f21d96d0SKevin Wolf     .inherit_options    = blk_root_inherit_options,
323c2066af0SKevin Wolf 
3245c8cab48SKevin Wolf     .change_media       = blk_root_change_media,
3255c8cab48SKevin Wolf     .resize             = blk_root_resize,
3264c265bf9SKevin Wolf     .get_name           = blk_root_get_name,
327b5411555SKevin Wolf     .get_parent_desc    = blk_root_get_parent_desc,
3285c8cab48SKevin Wolf 
329c2066af0SKevin Wolf     .drained_begin      = blk_root_drained_begin,
330fe5258a5SKevin Wolf     .drained_poll       = blk_root_drained_poll,
331c2066af0SKevin Wolf     .drained_end        = blk_root_drained_end,
3324417ab7aSKevin Wolf 
3334417ab7aSKevin Wolf     .activate           = blk_root_activate,
334cfa1a572SKevin Wolf     .inactivate         = blk_root_inactivate,
335d03654eaSStefan Hajnoczi 
336d03654eaSStefan Hajnoczi     .attach             = blk_root_attach,
337d03654eaSStefan Hajnoczi     .detach             = blk_root_detach,
33838475269SKevin Wolf 
33933949396SEmanuele Giuseppe Esposito     .change_aio_ctx     = blk_root_change_aio_ctx,
3403ca1f322SVladimir Sementsov-Ogievskiy 
3413ca1f322SVladimir Sementsov-Ogievskiy     .get_parent_aio_context = blk_root_get_parent_aio_context,
342f21d96d0SKevin Wolf };
343f21d96d0SKevin Wolf 
34426f54e9aSMarkus Armbruster /*
345efaa7c4eSMax Reitz  * Create a new BlockBackend with a reference count of one.
3466d0eb64dSKevin Wolf  *
3476d0eb64dSKevin Wolf  * @perm is a bitmasks of BLK_PERM_* constants which describes the permissions
3486d0eb64dSKevin Wolf  * to request for a block driver node that is attached to this BlockBackend.
3496d0eb64dSKevin Wolf  * @shared_perm is a bitmask which describes which permissions may be granted
3506d0eb64dSKevin Wolf  * to other users of the attached node.
3516d0eb64dSKevin Wolf  * Both sets of permissions can be changed later using blk_set_perm().
3526d0eb64dSKevin Wolf  *
35326f54e9aSMarkus Armbruster  * Return the new BlockBackend on success, null on failure.
35426f54e9aSMarkus Armbruster  */
blk_new(AioContext * ctx,uint64_t perm,uint64_t shared_perm)355d861ab3aSKevin Wolf BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
35626f54e9aSMarkus Armbruster {
35726f54e9aSMarkus Armbruster     BlockBackend *blk;
35826f54e9aSMarkus Armbruster 
3590439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
3600439c5a4SEmanuele Giuseppe Esposito 
36126f54e9aSMarkus Armbruster     blk = g_new0(BlockBackend, 1);
36226f54e9aSMarkus Armbruster     blk->refcnt = 1;
363d861ab3aSKevin Wolf     blk->ctx = ctx;
3646d0eb64dSKevin Wolf     blk->perm = perm;
3656d0eb64dSKevin Wolf     blk->shared_perm = shared_perm;
3660c3169dfSKevin Wolf     blk_set_enable_write_cache(blk, true);
3670c3169dfSKevin Wolf 
368cb53460bSKevin Wolf     blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT;
369cb53460bSKevin Wolf     blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
370cb53460bSKevin Wolf 
3719caa6f3dSPaolo Bonzini     block_acct_init(&blk->stats);
37227ccdd52SKevin Wolf 
373407ae2aeSStefan Hajnoczi     qemu_mutex_init(&blk->queued_requests_lock);
374cf312932SKevin Wolf     qemu_co_queue_init(&blk->queued_requests);
3753301f6c6SMax Reitz     notifier_list_init(&blk->remove_bs_notifiers);
3763301f6c6SMax Reitz     notifier_list_init(&blk->insert_bs_notifiers);
377d03654eaSStefan Hajnoczi     QLIST_INIT(&blk->aio_notifiers);
37827ccdd52SKevin Wolf 
3792cf22d6aSMax Reitz     QTAILQ_INSERT_TAIL(&block_backends, blk, link);
38026f54e9aSMarkus Armbruster     return blk;
38126f54e9aSMarkus Armbruster }
38226f54e9aSMarkus Armbruster 
3837e7d56d9SMarkus Armbruster /*
384a3aeeab5SEric Blake  * Create a new BlockBackend connected to an existing BlockDriverState.
385a3aeeab5SEric Blake  *
386a3aeeab5SEric Blake  * @perm is a bitmasks of BLK_PERM_* constants which describes the
387a3aeeab5SEric Blake  * permissions to request for @bs that is attached to this
388a3aeeab5SEric Blake  * BlockBackend.  @shared_perm is a bitmask which describes which
389a3aeeab5SEric Blake  * permissions may be granted to other users of the attached node.
390a3aeeab5SEric Blake  * Both sets of permissions can be changed later using blk_set_perm().
391a3aeeab5SEric Blake  *
392a3aeeab5SEric Blake  * Return the new BlockBackend on success, null on failure.
3934c20dd24SKevin Wolf  *
3944c20dd24SKevin Wolf  * Callers must hold the AioContext lock of @bs.
395a3aeeab5SEric Blake  */
blk_new_with_bs(BlockDriverState * bs,uint64_t perm,uint64_t shared_perm,Error ** errp)396a3aeeab5SEric Blake BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
397a3aeeab5SEric Blake                               uint64_t shared_perm, Error **errp)
398a3aeeab5SEric Blake {
399a3aeeab5SEric Blake     BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
400a3aeeab5SEric Blake 
4010439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
4020439c5a4SEmanuele Giuseppe Esposito 
403a3aeeab5SEric Blake     if (blk_insert_bs(blk, bs, errp) < 0) {
404a3aeeab5SEric Blake         blk_unref(blk);
405a3aeeab5SEric Blake         return NULL;
406a3aeeab5SEric Blake     }
407a3aeeab5SEric Blake     return blk;
408a3aeeab5SEric Blake }
409a3aeeab5SEric Blake 
410a3aeeab5SEric Blake /*
41128eb9b12SMax Reitz  * Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
4124c20dd24SKevin Wolf  * By default, the new BlockBackend is in the main AioContext, but if the
4134c20dd24SKevin Wolf  * parameters connect it with any existing node in a different AioContext, it
4144c20dd24SKevin Wolf  * may end up there instead.
415ca49a4fdSMax Reitz  *
416ca49a4fdSMax Reitz  * Just as with bdrv_open(), after having called this function the reference to
417ca49a4fdSMax Reitz  * @options belongs to the block layer (even on failure).
418ca49a4fdSMax Reitz  *
4194c20dd24SKevin Wolf  * Called without holding an AioContext lock.
4204c20dd24SKevin Wolf  *
421ca49a4fdSMax Reitz  * TODO: Remove @filename and @flags; it should be possible to specify a whole
422ca49a4fdSMax Reitz  * BDS tree just by specifying the @options QDict (or @reference,
423ca49a4fdSMax Reitz  * alternatively). At the time of adding this function, this is not possible,
424ca49a4fdSMax Reitz  * though, so callers of this function have to be able to specify @filename and
425ca49a4fdSMax Reitz  * @flags.
426ca49a4fdSMax Reitz  */
blk_new_open(const char * filename,const char * reference,QDict * options,int flags,Error ** errp)427efaa7c4eSMax Reitz BlockBackend *blk_new_open(const char *filename, const char *reference,
428efaa7c4eSMax Reitz                            QDict *options, int flags, Error **errp)
429ca49a4fdSMax Reitz {
430ca49a4fdSMax Reitz     BlockBackend *blk;
43128eb9b12SMax Reitz     BlockDriverState *bs;
4324c20dd24SKevin Wolf     AioContext *ctx;
4331f4ad7d3SKevin Wolf     uint64_t perm = 0;
43435b7f4abSKevin Wolf     uint64_t shared = BLK_PERM_ALL;
435ca49a4fdSMax Reitz 
4360439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
4370439c5a4SEmanuele Giuseppe Esposito 
43835b7f4abSKevin Wolf     /*
43935b7f4abSKevin Wolf      * blk_new_open() is mainly used in .bdrv_create implementations and the
44035b7f4abSKevin Wolf      * tools where sharing isn't a major concern because the BDS stays private
44135b7f4abSKevin Wolf      * and the file is generally not supposed to be used by a second process,
44235b7f4abSKevin Wolf      * so we just request permission according to the flags.
443c62d32f5SKevin Wolf      *
444c62d32f5SKevin Wolf      * The exceptions are xen_disk and blockdev_init(); in these cases, the
445c62d32f5SKevin Wolf      * caller of blk_new_open() doesn't make use of the permissions, but they
446c62d32f5SKevin Wolf      * shouldn't hurt either. We can still share everything here because the
44735b7f4abSKevin Wolf      * guest devices will add their own blockers if they can't share.
44835b7f4abSKevin Wolf      */
4491f4ad7d3SKevin Wolf     if ((flags & BDRV_O_NO_IO) == 0) {
4501f4ad7d3SKevin Wolf         perm |= BLK_PERM_CONSISTENT_READ;
451c62d32f5SKevin Wolf         if (flags & BDRV_O_RDWR) {
452c62d32f5SKevin Wolf             perm |= BLK_PERM_WRITE;
453c62d32f5SKevin Wolf         }
4541f4ad7d3SKevin Wolf     }
455c62d32f5SKevin Wolf     if (flags & BDRV_O_RESIZE) {
456c62d32f5SKevin Wolf         perm |= BLK_PERM_RESIZE;
457c62d32f5SKevin Wolf     }
45835b7f4abSKevin Wolf     if (flags & BDRV_O_NO_SHARE) {
45935b7f4abSKevin Wolf         shared = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
46035b7f4abSKevin Wolf     }
461c62d32f5SKevin Wolf 
462c6e0a6deSKevin Wolf     aio_context_acquire(qemu_get_aio_context());
4635b363937SMax Reitz     bs = bdrv_open(filename, reference, options, flags, errp);
464c6e0a6deSKevin Wolf     aio_context_release(qemu_get_aio_context());
4655b363937SMax Reitz     if (!bs) {
466ca49a4fdSMax Reitz         return NULL;
467ca49a4fdSMax Reitz     }
468ca49a4fdSMax Reitz 
4694c20dd24SKevin Wolf     /* bdrv_open() could have moved bs to a different AioContext */
4704c20dd24SKevin Wolf     ctx = bdrv_get_aio_context(bs);
4714c20dd24SKevin Wolf     blk = blk_new(bdrv_get_aio_context(bs), perm, shared);
4724c20dd24SKevin Wolf     blk->perm = perm;
4734c20dd24SKevin Wolf     blk->shared_perm = shared;
4744c20dd24SKevin Wolf 
4754c20dd24SKevin Wolf     aio_context_acquire(ctx);
4764c20dd24SKevin Wolf     blk_insert_bs(blk, bs, errp);
4774c20dd24SKevin Wolf     bdrv_unref(bs);
4784c20dd24SKevin Wolf     aio_context_release(ctx);
4794c20dd24SKevin Wolf 
48050bfbe93SFam Zheng     if (!blk->root) {
48150bfbe93SFam Zheng         blk_unref(blk);
48250bfbe93SFam Zheng         return NULL;
48350bfbe93SFam Zheng     }
48472e775c7SKevin Wolf 
485ca49a4fdSMax Reitz     return blk;
486ca49a4fdSMax Reitz }
487ca49a4fdSMax Reitz 
blk_delete(BlockBackend * blk)48826f54e9aSMarkus Armbruster static void blk_delete(BlockBackend *blk)
48926f54e9aSMarkus Armbruster {
49026f54e9aSMarkus Armbruster     assert(!blk->refcnt);
491e5e78550SMax Reitz     assert(!blk->name);
492a7f53e26SMarkus Armbruster     assert(!blk->dev);
493022cdc9fSManos Pitsidianakis     if (blk->public.throttle_group_member.throttle_state) {
4941606e4cfSEric Blake         blk_io_limits_disable(blk);
4951606e4cfSEric Blake     }
496f21d96d0SKevin Wolf     if (blk->root) {
49713855c6bSMax Reitz         blk_remove_bs(blk);
4987e7d56d9SMarkus Armbruster     }
4995f7772c4SFam Zheng     if (blk->vmsh) {
5005f7772c4SFam Zheng         qemu_del_vm_change_state_handler(blk->vmsh);
5015f7772c4SFam Zheng         blk->vmsh = NULL;
5025f7772c4SFam Zheng     }
5033301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
5043301f6c6SMax Reitz     assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
505d03654eaSStefan Hajnoczi     assert(QLIST_EMPTY(&blk->aio_notifiers));
506407ae2aeSStefan Hajnoczi     assert(qemu_co_queue_empty(&blk->queued_requests));
507407ae2aeSStefan Hajnoczi     qemu_mutex_destroy(&blk->queued_requests_lock);
5082cf22d6aSMax Reitz     QTAILQ_REMOVE(&block_backends, blk, link);
50918e46a03SMarkus Armbruster     drive_info_del(blk->legacy_dinfo);
510979e9b03SAlberto Garcia     block_acct_cleanup(&blk->stats);
51126f54e9aSMarkus Armbruster     g_free(blk);
51226f54e9aSMarkus Armbruster }
51326f54e9aSMarkus Armbruster 
drive_info_del(DriveInfo * dinfo)5148fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo)
5158fb3c76cSMarkus Armbruster {
5168fb3c76cSMarkus Armbruster     if (!dinfo) {
5178fb3c76cSMarkus Armbruster         return;
5188fb3c76cSMarkus Armbruster     }
5198fb3c76cSMarkus Armbruster     qemu_opts_del(dinfo->opts);
5208fb3c76cSMarkus Armbruster     g_free(dinfo);
5218fb3c76cSMarkus Armbruster }
5228fb3c76cSMarkus Armbruster 
blk_get_refcnt(BlockBackend * blk)523f636ae85SAlberto Garcia int blk_get_refcnt(BlockBackend *blk)
524f636ae85SAlberto Garcia {
5250439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
526f636ae85SAlberto Garcia     return blk ? blk->refcnt : 0;
527f636ae85SAlberto Garcia }
528f636ae85SAlberto Garcia 
52926f54e9aSMarkus Armbruster /*
53026f54e9aSMarkus Armbruster  * Increment @blk's reference count.
53126f54e9aSMarkus Armbruster  * @blk must not be null.
53226f54e9aSMarkus Armbruster  */
blk_ref(BlockBackend * blk)53326f54e9aSMarkus Armbruster void blk_ref(BlockBackend *blk)
53426f54e9aSMarkus Armbruster {
5355ca9d21bSKevin Wolf     assert(blk->refcnt > 0);
5360439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
53726f54e9aSMarkus Armbruster     blk->refcnt++;
53826f54e9aSMarkus Armbruster }
53926f54e9aSMarkus Armbruster 
54026f54e9aSMarkus Armbruster /*
54126f54e9aSMarkus Armbruster  * Decrement @blk's reference count.
54226f54e9aSMarkus Armbruster  * If this drops it to zero, destroy @blk.
54326f54e9aSMarkus Armbruster  * For convenience, do nothing if @blk is null.
54426f54e9aSMarkus Armbruster  */
blk_unref(BlockBackend * blk)54526f54e9aSMarkus Armbruster void blk_unref(BlockBackend *blk)
54626f54e9aSMarkus Armbruster {
5470439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
54826f54e9aSMarkus Armbruster     if (blk) {
54926f54e9aSMarkus Armbruster         assert(blk->refcnt > 0);
5505ca9d21bSKevin Wolf         if (blk->refcnt > 1) {
5515ca9d21bSKevin Wolf             blk->refcnt--;
5525ca9d21bSKevin Wolf         } else {
5535ca9d21bSKevin Wolf             blk_drain(blk);
5545ca9d21bSKevin Wolf             /* blk_drain() cannot resurrect blk, nobody held a reference */
5555ca9d21bSKevin Wolf             assert(blk->refcnt == 1);
5565ca9d21bSKevin Wolf             blk->refcnt = 0;
55726f54e9aSMarkus Armbruster             blk_delete(blk);
55826f54e9aSMarkus Armbruster         }
55926f54e9aSMarkus Armbruster     }
56026f54e9aSMarkus Armbruster }
56126f54e9aSMarkus Armbruster 
5622cf22d6aSMax Reitz /*
5632cf22d6aSMax Reitz  * Behaves similarly to blk_next() but iterates over all BlockBackends, even the
5642cf22d6aSMax Reitz  * ones which are hidden (i.e. are not referenced by the monitor).
5652cf22d6aSMax Reitz  */
blk_all_next(BlockBackend * blk)566a429b9b5SKevin Wolf BlockBackend *blk_all_next(BlockBackend *blk)
5672cf22d6aSMax Reitz {
5680439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
5692cf22d6aSMax Reitz     return blk ? QTAILQ_NEXT(blk, link)
5702cf22d6aSMax Reitz                : QTAILQ_FIRST(&block_backends);
5712cf22d6aSMax Reitz }
5722cf22d6aSMax Reitz 
blk_remove_all_bs(void)573d8da3cefSMax Reitz void blk_remove_all_bs(void)
574d8da3cefSMax Reitz {
57574d1b8fcSMax Reitz     BlockBackend *blk = NULL;
576d8da3cefSMax Reitz 
5770439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
5780439c5a4SEmanuele Giuseppe Esposito 
5792cf22d6aSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
580d8da3cefSMax Reitz         AioContext *ctx = blk_get_aio_context(blk);
581d8da3cefSMax Reitz 
582d8da3cefSMax Reitz         aio_context_acquire(ctx);
583f21d96d0SKevin Wolf         if (blk->root) {
584d8da3cefSMax Reitz             blk_remove_bs(blk);
585d8da3cefSMax Reitz         }
586d8da3cefSMax Reitz         aio_context_release(ctx);
587d8da3cefSMax Reitz     }
588d8da3cefSMax Reitz }
589d8da3cefSMax Reitz 
59026f54e9aSMarkus Armbruster /*
5919492b0b9SMax Reitz  * Return the monitor-owned BlockBackend after @blk.
59226f54e9aSMarkus Armbruster  * If @blk is null, return the first one.
59326f54e9aSMarkus Armbruster  * Else, return @blk's next sibling, which may be null.
59426f54e9aSMarkus Armbruster  *
59526f54e9aSMarkus Armbruster  * To iterate over all BlockBackends, do
59626f54e9aSMarkus Armbruster  * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
59726f54e9aSMarkus Armbruster  *     ...
59826f54e9aSMarkus Armbruster  * }
59926f54e9aSMarkus Armbruster  */
blk_next(BlockBackend * blk)60026f54e9aSMarkus Armbruster BlockBackend *blk_next(BlockBackend *blk)
60126f54e9aSMarkus Armbruster {
6020439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
6039492b0b9SMax Reitz     return blk ? QTAILQ_NEXT(blk, monitor_link)
6049492b0b9SMax Reitz                : QTAILQ_FIRST(&monitor_block_backends);
60526f54e9aSMarkus Armbruster }
60626f54e9aSMarkus Armbruster 
6077c8eece4SKevin Wolf /* Iterates over all top-level BlockDriverStates, i.e. BDSs that are owned by
6087c8eece4SKevin Wolf  * the monitor or attached to a BlockBackend */
bdrv_next(BdrvNextIterator * it)60988be7b4bSKevin Wolf BlockDriverState *bdrv_next(BdrvNextIterator *it)
6107c8eece4SKevin Wolf {
6115e003f17SMax Reitz     BlockDriverState *bs, *old_bs;
6125e003f17SMax Reitz 
6135e003f17SMax Reitz     /* Must be called from the main loop */
6145e003f17SMax Reitz     assert(qemu_get_current_aio_context() == qemu_get_aio_context());
615981f4f57SMax Reitz 
6167c8eece4SKevin Wolf     /* First, return all root nodes of BlockBackends. In order to avoid
6177c8eece4SKevin Wolf      * returning a BDS twice when multiple BBs refer to it, we only return it
6187c8eece4SKevin Wolf      * if the BB is the first one in the parent list of the BDS. */
6197c8eece4SKevin Wolf     if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
6205e003f17SMax Reitz         BlockBackend *old_blk = it->blk;
6215e003f17SMax Reitz 
6225e003f17SMax Reitz         old_bs = old_blk ? blk_bs(old_blk) : NULL;
6235e003f17SMax Reitz 
624981f4f57SMax Reitz         do {
6257c8eece4SKevin Wolf             it->blk = blk_all_next(it->blk);
62688be7b4bSKevin Wolf             bs = it->blk ? blk_bs(it->blk) : NULL;
62788be7b4bSKevin Wolf         } while (it->blk && (bs == NULL || bdrv_first_blk(bs) != it->blk));
628981f4f57SMax Reitz 
6295e003f17SMax Reitz         if (it->blk) {
6305e003f17SMax Reitz             blk_ref(it->blk);
6315e003f17SMax Reitz         }
6325e003f17SMax Reitz         blk_unref(old_blk);
6335e003f17SMax Reitz 
63488be7b4bSKevin Wolf         if (bs) {
6355e003f17SMax Reitz             bdrv_ref(bs);
6365e003f17SMax Reitz             bdrv_unref(old_bs);
63788be7b4bSKevin Wolf             return bs;
6387c8eece4SKevin Wolf         }
6397c8eece4SKevin Wolf         it->phase = BDRV_NEXT_MONITOR_OWNED;
6405e003f17SMax Reitz     } else {
6415e003f17SMax Reitz         old_bs = it->bs;
6427c8eece4SKevin Wolf     }
6437c8eece4SKevin Wolf 
6447c8eece4SKevin Wolf     /* Then return the monitor-owned BDSes without a BB attached. Ignore all
6457c8eece4SKevin Wolf      * BDSes that are attached to a BlockBackend here; they have been handled
6467c8eece4SKevin Wolf      * by the above block already */
6477c8eece4SKevin Wolf     do {
6487c8eece4SKevin Wolf         it->bs = bdrv_next_monitor_owned(it->bs);
64988be7b4bSKevin Wolf         bs = it->bs;
65088be7b4bSKevin Wolf     } while (bs && bdrv_has_blk(bs));
6517c8eece4SKevin Wolf 
6525e003f17SMax Reitz     if (bs) {
6535e003f17SMax Reitz         bdrv_ref(bs);
6545e003f17SMax Reitz     }
6555e003f17SMax Reitz     bdrv_unref(old_bs);
6565e003f17SMax Reitz 
65788be7b4bSKevin Wolf     return bs;
65888be7b4bSKevin Wolf }
65988be7b4bSKevin Wolf 
bdrv_next_reset(BdrvNextIterator * it)6605e003f17SMax Reitz static void bdrv_next_reset(BdrvNextIterator *it)
66188be7b4bSKevin Wolf {
66288be7b4bSKevin Wolf     *it = (BdrvNextIterator) {
66388be7b4bSKevin Wolf         .phase = BDRV_NEXT_BACKEND_ROOTS,
66488be7b4bSKevin Wolf     };
6655e003f17SMax Reitz }
66688be7b4bSKevin Wolf 
bdrv_first(BdrvNextIterator * it)6675e003f17SMax Reitz BlockDriverState *bdrv_first(BdrvNextIterator *it)
6685e003f17SMax Reitz {
6690439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
6705e003f17SMax Reitz     bdrv_next_reset(it);
67188be7b4bSKevin Wolf     return bdrv_next(it);
672981f4f57SMax Reitz }
673981f4f57SMax Reitz 
6745e003f17SMax Reitz /* Must be called when aborting a bdrv_next() iteration before
6755e003f17SMax Reitz  * bdrv_next() returns NULL */
bdrv_next_cleanup(BdrvNextIterator * it)6765e003f17SMax Reitz void bdrv_next_cleanup(BdrvNextIterator *it)
6775e003f17SMax Reitz {
6785e003f17SMax Reitz     /* Must be called from the main loop */
6795e003f17SMax Reitz     assert(qemu_get_current_aio_context() == qemu_get_aio_context());
6805e003f17SMax Reitz 
6815e003f17SMax Reitz     if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
6825e003f17SMax Reitz         if (it->blk) {
6835e003f17SMax Reitz             bdrv_unref(blk_bs(it->blk));
6845e003f17SMax Reitz             blk_unref(it->blk);
6855e003f17SMax Reitz         }
6865e003f17SMax Reitz     } else {
6875e003f17SMax Reitz         bdrv_unref(it->bs);
6885e003f17SMax Reitz     }
6895e003f17SMax Reitz 
6905e003f17SMax Reitz     bdrv_next_reset(it);
6915e003f17SMax Reitz }
6925e003f17SMax Reitz 
693981f4f57SMax Reitz /*
694e5e78550SMax Reitz  * Add a BlockBackend into the list of backends referenced by the monitor, with
695e5e78550SMax Reitz  * the given @name acting as the handle for the monitor.
696e5e78550SMax Reitz  * Strictly for use by blockdev.c.
697e5e78550SMax Reitz  *
698e5e78550SMax Reitz  * @name must not be null or empty.
699e5e78550SMax Reitz  *
700e5e78550SMax Reitz  * Returns true on success and false on failure. In the latter case, an Error
701e5e78550SMax Reitz  * object is returned through @errp.
702e5e78550SMax Reitz  */
monitor_add_blk(BlockBackend * blk,const char * name,Error ** errp)703e5e78550SMax Reitz bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
704e5e78550SMax Reitz {
705e5e78550SMax Reitz     assert(!blk->name);
706e5e78550SMax Reitz     assert(name && name[0]);
7070439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
708e5e78550SMax Reitz 
709e5e78550SMax Reitz     if (!id_wellformed(name)) {
710e5e78550SMax Reitz         error_setg(errp, "Invalid device name");
711e5e78550SMax Reitz         return false;
712e5e78550SMax Reitz     }
713e5e78550SMax Reitz     if (blk_by_name(name)) {
714e5e78550SMax Reitz         error_setg(errp, "Device with id '%s' already exists", name);
715e5e78550SMax Reitz         return false;
716e5e78550SMax Reitz     }
717e5e78550SMax Reitz     if (bdrv_find_node(name)) {
718e5e78550SMax Reitz         error_setg(errp,
719e5e78550SMax Reitz                    "Device name '%s' conflicts with an existing node name",
720e5e78550SMax Reitz                    name);
721e5e78550SMax Reitz         return false;
722e5e78550SMax Reitz     }
723e5e78550SMax Reitz 
724e5e78550SMax Reitz     blk->name = g_strdup(name);
725e5e78550SMax Reitz     QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
726e5e78550SMax Reitz     return true;
727e5e78550SMax Reitz }
728e5e78550SMax Reitz 
729e5e78550SMax Reitz /*
730e5e78550SMax Reitz  * Remove a BlockBackend from the list of backends referenced by the monitor.
731e5e78550SMax Reitz  * Strictly for use by blockdev.c.
732e5e78550SMax Reitz  */
monitor_remove_blk(BlockBackend * blk)733e5e78550SMax Reitz void monitor_remove_blk(BlockBackend *blk)
734e5e78550SMax Reitz {
7350439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
7360439c5a4SEmanuele Giuseppe Esposito 
737e5e78550SMax Reitz     if (!blk->name) {
738e5e78550SMax Reitz         return;
739e5e78550SMax Reitz     }
740e5e78550SMax Reitz 
741e5e78550SMax Reitz     QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
742e5e78550SMax Reitz     g_free(blk->name);
743e5e78550SMax Reitz     blk->name = NULL;
744e5e78550SMax Reitz }
745e5e78550SMax Reitz 
746e5e78550SMax Reitz /*
7477e7d56d9SMarkus Armbruster  * Return @blk's name, a non-null string.
748e5e78550SMax Reitz  * Returns an empty string iff @blk is not referenced by the monitor.
74926f54e9aSMarkus Armbruster  */
blk_name(const BlockBackend * blk)7500731a50fSKrzysztof Kozlowski const char *blk_name(const BlockBackend *blk)
75126f54e9aSMarkus Armbruster {
75237868b2aSEmanuele Giuseppe Esposito     IO_CODE();
753e5e78550SMax Reitz     return blk->name ?: "";
75426f54e9aSMarkus Armbruster }
75526f54e9aSMarkus Armbruster 
75626f54e9aSMarkus Armbruster /*
75726f54e9aSMarkus Armbruster  * Return the BlockBackend with name @name if it exists, else null.
75826f54e9aSMarkus Armbruster  * @name must not be null.
75926f54e9aSMarkus Armbruster  */
blk_by_name(const char * name)76026f54e9aSMarkus Armbruster BlockBackend *blk_by_name(const char *name)
76126f54e9aSMarkus Armbruster {
76274d1b8fcSMax Reitz     BlockBackend *blk = NULL;
76326f54e9aSMarkus Armbruster 
7640439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
76526f54e9aSMarkus Armbruster     assert(name);
76674d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
76726f54e9aSMarkus Armbruster         if (!strcmp(name, blk->name)) {
76826f54e9aSMarkus Armbruster             return blk;
76926f54e9aSMarkus Armbruster         }
77026f54e9aSMarkus Armbruster     }
77126f54e9aSMarkus Armbruster     return NULL;
77226f54e9aSMarkus Armbruster }
7737e7d56d9SMarkus Armbruster 
7747e7d56d9SMarkus Armbruster /*
7757e7d56d9SMarkus Armbruster  * Return the BlockDriverState attached to @blk if any, else null.
7767e7d56d9SMarkus Armbruster  */
blk_bs(BlockBackend * blk)7777e7d56d9SMarkus Armbruster BlockDriverState *blk_bs(BlockBackend *blk)
7787e7d56d9SMarkus Armbruster {
77937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
780f21d96d0SKevin Wolf     return blk->root ? blk->root->bs : NULL;
7817e7d56d9SMarkus Armbruster }
7827e7d56d9SMarkus Armbruster 
bdrv_first_blk(BlockDriverState * bs)7832b3912f1SKevin Wolf static BlockBackend * GRAPH_RDLOCK bdrv_first_blk(BlockDriverState *bs)
784dde33812SKevin Wolf {
785dde33812SKevin Wolf     BdrvChild *child;
786bdb73476SEmanuele Giuseppe Esposito 
787bdb73476SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
7882b3912f1SKevin Wolf     assert_bdrv_graph_readable();
789bdb73476SEmanuele Giuseppe Esposito 
790dde33812SKevin Wolf     QLIST_FOREACH(child, &bs->parents, next_parent) {
791bd86fb99SMax Reitz         if (child->klass == &child_root) {
7927c8eece4SKevin Wolf             return child->opaque;
793dde33812SKevin Wolf         }
794dde33812SKevin Wolf     }
795dde33812SKevin Wolf 
7967c8eece4SKevin Wolf     return NULL;
7977c8eece4SKevin Wolf }
7987c8eece4SKevin Wolf 
7997c8eece4SKevin Wolf /*
8007c8eece4SKevin Wolf  * Returns true if @bs has an associated BlockBackend.
8017c8eece4SKevin Wolf  */
bdrv_has_blk(BlockDriverState * bs)8027c8eece4SKevin Wolf bool bdrv_has_blk(BlockDriverState *bs)
8037c8eece4SKevin Wolf {
8040439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
8057c8eece4SKevin Wolf     return bdrv_first_blk(bs) != NULL;
806dde33812SKevin Wolf }
807dde33812SKevin Wolf 
808dde33812SKevin Wolf /*
809b6c1bae5SKevin Wolf  * Returns true if @bs has only BlockBackends as parents.
810b6c1bae5SKevin Wolf  */
bdrv_is_root_node(BlockDriverState * bs)811b6c1bae5SKevin Wolf bool bdrv_is_root_node(BlockDriverState *bs)
812b6c1bae5SKevin Wolf {
813b6c1bae5SKevin Wolf     BdrvChild *c;
814b6c1bae5SKevin Wolf 
8150439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
8162b3912f1SKevin Wolf     assert_bdrv_graph_readable();
8172b3912f1SKevin Wolf 
818b6c1bae5SKevin Wolf     QLIST_FOREACH(c, &bs->parents, next_parent) {
819bd86fb99SMax Reitz         if (c->klass != &child_root) {
820b6c1bae5SKevin Wolf             return false;
821b6c1bae5SKevin Wolf         }
822b6c1bae5SKevin Wolf     }
823b6c1bae5SKevin Wolf 
824b6c1bae5SKevin Wolf     return true;
825b6c1bae5SKevin Wolf }
826b6c1bae5SKevin Wolf 
827b6c1bae5SKevin Wolf /*
82818e46a03SMarkus Armbruster  * Return @blk's DriveInfo if any, else null.
82918e46a03SMarkus Armbruster  */
blk_legacy_dinfo(BlockBackend * blk)83018e46a03SMarkus Armbruster DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
83118e46a03SMarkus Armbruster {
832c5be7445SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
83318e46a03SMarkus Armbruster     return blk->legacy_dinfo;
83418e46a03SMarkus Armbruster }
83518e46a03SMarkus Armbruster 
83618e46a03SMarkus Armbruster /*
83718e46a03SMarkus Armbruster  * Set @blk's DriveInfo to @dinfo, and return it.
83818e46a03SMarkus Armbruster  * @blk must not have a DriveInfo set already.
83918e46a03SMarkus Armbruster  * No other BlockBackend may have the same DriveInfo set.
84018e46a03SMarkus Armbruster  */
blk_set_legacy_dinfo(BlockBackend * blk,DriveInfo * dinfo)84118e46a03SMarkus Armbruster DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
84218e46a03SMarkus Armbruster {
84318e46a03SMarkus Armbruster     assert(!blk->legacy_dinfo);
844c5be7445SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
84518e46a03SMarkus Armbruster     return blk->legacy_dinfo = dinfo;
84618e46a03SMarkus Armbruster }
84718e46a03SMarkus Armbruster 
84818e46a03SMarkus Armbruster /*
84918e46a03SMarkus Armbruster  * Return the BlockBackend with DriveInfo @dinfo.
85018e46a03SMarkus Armbruster  * It must exist.
85118e46a03SMarkus Armbruster  */
blk_by_legacy_dinfo(DriveInfo * dinfo)85218e46a03SMarkus Armbruster BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
85318e46a03SMarkus Armbruster {
85474d1b8fcSMax Reitz     BlockBackend *blk = NULL;
855c5be7445SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
85618e46a03SMarkus Armbruster 
85774d1b8fcSMax Reitz     while ((blk = blk_next(blk)) != NULL) {
85818e46a03SMarkus Armbruster         if (blk->legacy_dinfo == dinfo) {
85918e46a03SMarkus Armbruster             return blk;
86018e46a03SMarkus Armbruster         }
86118e46a03SMarkus Armbruster     }
86218e46a03SMarkus Armbruster     abort();
86318e46a03SMarkus Armbruster }
86418e46a03SMarkus Armbruster 
86518e46a03SMarkus Armbruster /*
866f2cd875dSKevin Wolf  * Returns a pointer to the publicly accessible fields of @blk.
867f2cd875dSKevin Wolf  */
blk_get_public(BlockBackend * blk)868f2cd875dSKevin Wolf BlockBackendPublic *blk_get_public(BlockBackend *blk)
869f2cd875dSKevin Wolf {
8700439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
871f2cd875dSKevin Wolf     return &blk->public;
872f2cd875dSKevin Wolf }
873f2cd875dSKevin Wolf 
874f2cd875dSKevin Wolf /*
875f2cd875dSKevin Wolf  * Returns a BlockBackend given the associated @public fields.
876f2cd875dSKevin Wolf  */
blk_by_public(BlockBackendPublic * public)877f2cd875dSKevin Wolf BlockBackend *blk_by_public(BlockBackendPublic *public)
878f2cd875dSKevin Wolf {
8790439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
880f2cd875dSKevin Wolf     return container_of(public, BlockBackend, public);
881f2cd875dSKevin Wolf }
882f2cd875dSKevin Wolf 
883f2cd875dSKevin Wolf /*
8841c95f7e1SMax Reitz  * Disassociates the currently associated BlockDriverState from @blk.
885bb092d6dSKevin Wolf  *
886bb092d6dSKevin Wolf  * The caller must hold the AioContext lock for the BlockBackend.
8871c95f7e1SMax Reitz  */
blk_remove_bs(BlockBackend * blk)8881c95f7e1SMax Reitz void blk_remove_bs(BlockBackend *blk)
8891c95f7e1SMax Reitz {
890c89bcf3aSAlberto Garcia     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
891e6cada92SGreg Kurz     BdrvChild *root;
892*6bc0bcc8SKevin Wolf     AioContext *ctx;
893022cdc9fSManos Pitsidianakis 
8940439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
8950439c5a4SEmanuele Giuseppe Esposito 
8963301f6c6SMax Reitz     notifier_list_notify(&blk->remove_bs_notifiers, blk);
897c89bcf3aSAlberto Garcia     if (tgm->throttle_state) {
8981e3552dbSStefan Hajnoczi         BlockDriverState *bs = blk_bs(blk);
8991e3552dbSStefan Hajnoczi 
9001e3552dbSStefan Hajnoczi         /*
9011e3552dbSStefan Hajnoczi          * Take a ref in case blk_bs() changes across bdrv_drained_begin(), for
9021e3552dbSStefan Hajnoczi          * example, if a temporary filter node is removed by a blockjob.
9031e3552dbSStefan Hajnoczi          */
9041e3552dbSStefan Hajnoczi         bdrv_ref(bs);
905632a7735SZhengui         bdrv_drained_begin(bs);
906c89bcf3aSAlberto Garcia         throttle_group_detach_aio_context(tgm);
907c89bcf3aSAlberto Garcia         throttle_group_attach_aio_context(tgm, qemu_get_aio_context());
908632a7735SZhengui         bdrv_drained_end(bs);
9091e3552dbSStefan Hajnoczi         bdrv_unref(bs);
9107ca7f0f6SKevin Wolf     }
9113301f6c6SMax Reitz 
9121c95f7e1SMax Reitz     blk_update_root_state(blk);
9131c95f7e1SMax Reitz 
914f45280cbSGreg Kurz     /* bdrv_root_unref_child() will cause blk->root to become stale and may
915f45280cbSGreg Kurz      * switch to a completion coroutine later on. Let's drain all I/O here
916f45280cbSGreg Kurz      * to avoid that and a potential QEMU crash.
917f45280cbSGreg Kurz      */
918f45280cbSGreg Kurz     blk_drain(blk);
919e6cada92SGreg Kurz     root = blk->root;
920f21d96d0SKevin Wolf     blk->root = NULL;
921ede01e46SKevin Wolf 
922*6bc0bcc8SKevin Wolf     ctx = bdrv_get_aio_context(root->bs);
923bb092d6dSKevin Wolf     bdrv_graph_wrlock(root->bs);
924e6cada92SGreg Kurz     bdrv_root_unref_child(root);
925*6bc0bcc8SKevin Wolf     bdrv_graph_wrunlock_ctx(ctx);
9261c95f7e1SMax Reitz }
9271c95f7e1SMax Reitz 
9281c95f7e1SMax Reitz /*
9290c3c36d6SMax Reitz  * Associates a new BlockDriverState with @blk.
9304c20dd24SKevin Wolf  *
9314c20dd24SKevin Wolf  * Callers must hold the AioContext lock of @bs.
9320c3c36d6SMax Reitz  */
blk_insert_bs(BlockBackend * blk,BlockDriverState * bs,Error ** errp)933d7086422SKevin Wolf int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
9340c3c36d6SMax Reitz {
935c89bcf3aSAlberto Garcia     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
936*6bc0bcc8SKevin Wolf     AioContext *ctx = bdrv_get_aio_context(bs);
937*6bc0bcc8SKevin Wolf 
9380439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
939b441dc71SAlberto Garcia     bdrv_ref(bs);
94003b9eacaSKevin Wolf     bdrv_graph_wrlock(bs);
9411f38f04eSMax Reitz     blk->root = bdrv_root_attach_child(bs, "root", &child_root,
9421f38f04eSMax Reitz                                        BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
943228ca37eSVladimir Sementsov-Ogievskiy                                        blk->perm, blk->shared_perm,
9441f38f04eSMax Reitz                                        blk, errp);
945*6bc0bcc8SKevin Wolf     bdrv_graph_wrunlock_ctx(ctx);
946d7086422SKevin Wolf     if (blk->root == NULL) {
947d7086422SKevin Wolf         return -EPERM;
948d7086422SKevin Wolf     }
9493301f6c6SMax Reitz 
9503301f6c6SMax Reitz     notifier_list_notify(&blk->insert_bs_notifiers, blk);
951c89bcf3aSAlberto Garcia     if (tgm->throttle_state) {
952c89bcf3aSAlberto Garcia         throttle_group_detach_aio_context(tgm);
953c89bcf3aSAlberto Garcia         throttle_group_attach_aio_context(tgm, bdrv_get_aio_context(bs));
9547ca7f0f6SKevin Wolf     }
955d7086422SKevin Wolf 
956d7086422SKevin Wolf     return 0;
9570c3c36d6SMax Reitz }
9580c3c36d6SMax Reitz 
959981776b3SKevin Wolf /*
960ed089506SVladimir Sementsov-Ogievskiy  * Change BlockDriverState associated with @blk.
961ed089506SVladimir Sementsov-Ogievskiy  */
blk_replace_bs(BlockBackend * blk,BlockDriverState * new_bs,Error ** errp)962ed089506SVladimir Sementsov-Ogievskiy int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp)
963ed089506SVladimir Sementsov-Ogievskiy {
9640439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
965ed089506SVladimir Sementsov-Ogievskiy     return bdrv_replace_child_bs(blk->root, new_bs, errp);
966ed089506SVladimir Sementsov-Ogievskiy }
967ed089506SVladimir Sementsov-Ogievskiy 
968ed089506SVladimir Sementsov-Ogievskiy /*
969981776b3SKevin Wolf  * Sets the permission bitmasks that the user of the BlockBackend needs.
970981776b3SKevin Wolf  */
9713804e3cfSKevin Wolf static int coroutine_mixed_fn GRAPH_RDLOCK
blk_set_perm_locked(BlockBackend * blk,uint64_t perm,uint64_t shared_perm,Error ** errp)9723804e3cfSKevin Wolf blk_set_perm_locked(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
973981776b3SKevin Wolf                     Error **errp)
974981776b3SKevin Wolf {
975981776b3SKevin Wolf     int ret;
9760439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
977981776b3SKevin Wolf 
978d35ff5e6SKevin Wolf     if (blk->root && !blk->disable_perm) {
979981776b3SKevin Wolf         ret = bdrv_child_try_set_perm(blk->root, perm, shared_perm, errp);
980981776b3SKevin Wolf         if (ret < 0) {
981981776b3SKevin Wolf             return ret;
982981776b3SKevin Wolf         }
983981776b3SKevin Wolf     }
984981776b3SKevin Wolf 
985981776b3SKevin Wolf     blk->perm = perm;
986981776b3SKevin Wolf     blk->shared_perm = shared_perm;
987981776b3SKevin Wolf 
988981776b3SKevin Wolf     return 0;
989981776b3SKevin Wolf }
990981776b3SKevin Wolf 
blk_set_perm(BlockBackend * blk,uint64_t perm,uint64_t shared_perm,Error ** errp)9913804e3cfSKevin Wolf int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
9923804e3cfSKevin Wolf                  Error **errp)
9933804e3cfSKevin Wolf {
9943804e3cfSKevin Wolf     GLOBAL_STATE_CODE();
9953804e3cfSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
9963804e3cfSKevin Wolf 
9973804e3cfSKevin Wolf     return blk_set_perm_locked(blk, perm, shared_perm, errp);
9983804e3cfSKevin Wolf }
9993804e3cfSKevin Wolf 
blk_get_perm(BlockBackend * blk,uint64_t * perm,uint64_t * shared_perm)1000887354bdSKevin Wolf void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
1001887354bdSKevin Wolf {
10020439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1003887354bdSKevin Wolf     *perm = blk->perm;
1004887354bdSKevin Wolf     *shared_perm = blk->shared_perm;
1005887354bdSKevin Wolf }
1006887354bdSKevin Wolf 
1007d09ea2d2SThomas Huth /*
1008d09ea2d2SThomas Huth  * Attach device model @dev to @blk.
1009d09ea2d2SThomas Huth  * Return 0 on success, -EBUSY when a device model is attached already.
1010d09ea2d2SThomas Huth  */
blk_attach_dev(BlockBackend * blk,DeviceState * dev)1011d09ea2d2SThomas Huth int blk_attach_dev(BlockBackend *blk, DeviceState *dev)
1012a7f53e26SMarkus Armbruster {
10130439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1014a7f53e26SMarkus Armbruster     if (blk->dev) {
1015a7f53e26SMarkus Armbruster         return -EBUSY;
1016a7f53e26SMarkus Armbruster     }
1017d35ff5e6SKevin Wolf 
1018d35ff5e6SKevin Wolf     /* While migration is still incoming, we don't need to apply the
1019d35ff5e6SKevin Wolf      * permissions of guest device BlockBackends. We might still have a block
1020d35ff5e6SKevin Wolf      * job or NBD server writing to the image for storage migration. */
1021d35ff5e6SKevin Wolf     if (runstate_check(RUN_STATE_INMIGRATE)) {
1022d35ff5e6SKevin Wolf         blk->disable_perm = true;
1023d35ff5e6SKevin Wolf     }
1024d35ff5e6SKevin Wolf 
102584ebe375SMarkus Armbruster     blk_ref(blk);
1026a7f53e26SMarkus Armbruster     blk->dev = dev;
1027373340b2SMax Reitz     blk_iostatus_reset(blk);
1028d35ff5e6SKevin Wolf 
1029a7f53e26SMarkus Armbruster     return 0;
1030a7f53e26SMarkus Armbruster }
1031a7f53e26SMarkus Armbruster 
1032a7f53e26SMarkus Armbruster /*
1033a7f53e26SMarkus Armbruster  * Detach device model @dev from @blk.
1034a7f53e26SMarkus Armbruster  * @dev must be currently attached to @blk.
1035a7f53e26SMarkus Armbruster  */
blk_detach_dev(BlockBackend * blk,DeviceState * dev)1036d09ea2d2SThomas Huth void blk_detach_dev(BlockBackend *blk, DeviceState *dev)
1037a7f53e26SMarkus Armbruster {
1038a7f53e26SMarkus Armbruster     assert(blk->dev == dev);
10390439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1040a7f53e26SMarkus Armbruster     blk->dev = NULL;
1041a7f53e26SMarkus Armbruster     blk->dev_ops = NULL;
1042a7f53e26SMarkus Armbruster     blk->dev_opaque = NULL;
1043981776b3SKevin Wolf     blk_set_perm(blk, 0, BLK_PERM_ALL, &error_abort);
104484ebe375SMarkus Armbruster     blk_unref(blk);
1045a7f53e26SMarkus Armbruster }
1046a7f53e26SMarkus Armbruster 
1047a7f53e26SMarkus Armbruster /*
1048a7f53e26SMarkus Armbruster  * Return the device model attached to @blk if any, else null.
1049a7f53e26SMarkus Armbruster  */
blk_get_attached_dev(BlockBackend * blk)1050d09ea2d2SThomas Huth DeviceState *blk_get_attached_dev(BlockBackend *blk)
1051a7f53e26SMarkus Armbruster {
10520439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1053a7f53e26SMarkus Armbruster     return blk->dev;
1054a7f53e26SMarkus Armbruster }
1055a7f53e26SMarkus Armbruster 
10562d76e724SKevin Wolf /* Return the qdev ID, or if no ID is assigned the QOM path, of the block
10572d76e724SKevin Wolf  * device attached to the BlockBackend. */
blk_get_attached_dev_id(BlockBackend * blk)105877beef83SKevin Wolf char *blk_get_attached_dev_id(BlockBackend *blk)
10592d76e724SKevin Wolf {
1060d09ea2d2SThomas Huth     DeviceState *dev = blk->dev;
106137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
10622d76e724SKevin Wolf 
10632d76e724SKevin Wolf     if (!dev) {
10642d76e724SKevin Wolf         return g_strdup("");
10652d76e724SKevin Wolf     } else if (dev->id) {
10662d76e724SKevin Wolf         return g_strdup(dev->id);
10672d76e724SKevin Wolf     }
1068602414d1SLiam Merwick 
1069602414d1SLiam Merwick     return object_get_canonical_path(OBJECT(dev)) ?: g_strdup("");
10702d76e724SKevin Wolf }
10712d76e724SKevin Wolf 
1072a7f53e26SMarkus Armbruster /*
10731c89e1faSKevin Wolf  * Return the BlockBackend which has the device model @dev attached if it
10741c89e1faSKevin Wolf  * exists, else null.
10751c89e1faSKevin Wolf  *
10761c89e1faSKevin Wolf  * @dev must not be null.
10771c89e1faSKevin Wolf  */
blk_by_dev(void * dev)10781c89e1faSKevin Wolf BlockBackend *blk_by_dev(void *dev)
10791c89e1faSKevin Wolf {
10801c89e1faSKevin Wolf     BlockBackend *blk = NULL;
10811c89e1faSKevin Wolf 
10820439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
10830439c5a4SEmanuele Giuseppe Esposito 
10841c89e1faSKevin Wolf     assert(dev != NULL);
10851c89e1faSKevin Wolf     while ((blk = blk_all_next(blk)) != NULL) {
10861c89e1faSKevin Wolf         if (blk->dev == dev) {
10871c89e1faSKevin Wolf             return blk;
10881c89e1faSKevin Wolf         }
10891c89e1faSKevin Wolf     }
10901c89e1faSKevin Wolf     return NULL;
10911c89e1faSKevin Wolf }
10921c89e1faSKevin Wolf 
10931c89e1faSKevin Wolf /*
1094a7f53e26SMarkus Armbruster  * Set @blk's device model callbacks to @ops.
1095a7f53e26SMarkus Armbruster  * @opaque is the opaque argument to pass to the callbacks.
1096a7f53e26SMarkus Armbruster  * This is for use by device models.
1097a7f53e26SMarkus Armbruster  */
blk_set_dev_ops(BlockBackend * blk,const BlockDevOps * ops,void * opaque)1098a7f53e26SMarkus Armbruster void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
1099a7f53e26SMarkus Armbruster                      void *opaque)
1100a7f53e26SMarkus Armbruster {
11010439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1102a7f53e26SMarkus Armbruster     blk->dev_ops = ops;
1103a7f53e26SMarkus Armbruster     blk->dev_opaque = opaque;
1104f4d9cc88SJohn Snow 
1105f4d9cc88SJohn Snow     /* Are we currently quiesced? Should we enforce this right now? */
1106c4d5bf99SStefan Hajnoczi     if (qatomic_read(&blk->quiesce_counter) && ops && ops->drained_begin) {
1107f4d9cc88SJohn Snow         ops->drained_begin(opaque);
1108f4d9cc88SJohn Snow     }
1109a7f53e26SMarkus Armbruster }
1110a7f53e26SMarkus Armbruster 
1111a7f53e26SMarkus Armbruster /*
1112a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of media change.
111339829a01SKevin Wolf  *
111439829a01SKevin Wolf  * If @load is true, notify of media load. This action can fail, meaning that
111539829a01SKevin Wolf  * the medium cannot be loaded. @errp is set then.
111639829a01SKevin Wolf  *
111739829a01SKevin Wolf  * If @load is false, notify of media eject. This can never fail.
111839829a01SKevin Wolf  *
1119a7f53e26SMarkus Armbruster  * Also send DEVICE_TRAY_MOVED events as appropriate.
1120a7f53e26SMarkus Armbruster  */
blk_dev_change_media_cb(BlockBackend * blk,bool load,Error ** errp)112139829a01SKevin Wolf void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp)
1122a7f53e26SMarkus Armbruster {
11230439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1124a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->change_media_cb) {
1125f1f57066SMax Reitz         bool tray_was_open, tray_is_open;
112639829a01SKevin Wolf         Error *local_err = NULL;
1127a7f53e26SMarkus Armbruster 
1128f1f57066SMax Reitz         tray_was_open = blk_dev_is_tray_open(blk);
112939829a01SKevin Wolf         blk->dev_ops->change_media_cb(blk->dev_opaque, load, &local_err);
113039829a01SKevin Wolf         if (local_err) {
113139829a01SKevin Wolf             assert(load == true);
113239829a01SKevin Wolf             error_propagate(errp, local_err);
113339829a01SKevin Wolf             return;
113439829a01SKevin Wolf         }
1135f1f57066SMax Reitz         tray_is_open = blk_dev_is_tray_open(blk);
1136f1f57066SMax Reitz 
1137f1f57066SMax Reitz         if (tray_was_open != tray_is_open) {
11382d76e724SKevin Wolf             char *id = blk_get_attached_dev_id(blk);
11393ab72385SPeter Xu             qapi_event_send_device_tray_moved(blk_name(blk), id, tray_is_open);
11402d76e724SKevin Wolf             g_free(id);
1141a7f53e26SMarkus Armbruster         }
1142a7f53e26SMarkus Armbruster     }
1143a7f53e26SMarkus Armbruster }
1144a7f53e26SMarkus Armbruster 
blk_root_change_media(BdrvChild * child,bool load)11455c8cab48SKevin Wolf static void blk_root_change_media(BdrvChild *child, bool load)
11465c8cab48SKevin Wolf {
114739829a01SKevin Wolf     blk_dev_change_media_cb(child->opaque, load, NULL);
11485c8cab48SKevin Wolf }
11495c8cab48SKevin Wolf 
1150a7f53e26SMarkus Armbruster /*
1151a7f53e26SMarkus Armbruster  * Does @blk's attached device model have removable media?
1152a7f53e26SMarkus Armbruster  * %true if no device model is attached.
1153a7f53e26SMarkus Armbruster  */
blk_dev_has_removable_media(BlockBackend * blk)1154a7f53e26SMarkus Armbruster bool blk_dev_has_removable_media(BlockBackend *blk)
1155a7f53e26SMarkus Armbruster {
1156b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1157a7f53e26SMarkus Armbruster     return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
1158a7f53e26SMarkus Armbruster }
1159a7f53e26SMarkus Armbruster 
1160a7f53e26SMarkus Armbruster /*
11618f3a73bcSMax Reitz  * Does @blk's attached device model have a tray?
11628f3a73bcSMax Reitz  */
blk_dev_has_tray(BlockBackend * blk)11638f3a73bcSMax Reitz bool blk_dev_has_tray(BlockBackend *blk)
11648f3a73bcSMax Reitz {
1165967d7905SEmanuele Giuseppe Esposito     IO_CODE();
11668f3a73bcSMax Reitz     return blk->dev_ops && blk->dev_ops->is_tray_open;
11678f3a73bcSMax Reitz }
11688f3a73bcSMax Reitz 
11698f3a73bcSMax Reitz /*
1170a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a media eject request.
1171a7f53e26SMarkus Armbruster  * If @force is true, the medium is about to be yanked out forcefully.
1172a7f53e26SMarkus Armbruster  */
blk_dev_eject_request(BlockBackend * blk,bool force)1173a7f53e26SMarkus Armbruster void blk_dev_eject_request(BlockBackend *blk, bool force)
1174a7f53e26SMarkus Armbruster {
1175b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1176a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->eject_request_cb) {
1177a7f53e26SMarkus Armbruster         blk->dev_ops->eject_request_cb(blk->dev_opaque, force);
1178a7f53e26SMarkus Armbruster     }
1179a7f53e26SMarkus Armbruster }
1180a7f53e26SMarkus Armbruster 
1181a7f53e26SMarkus Armbruster /*
1182a7f53e26SMarkus Armbruster  * Does @blk's attached device model have a tray, and is it open?
1183a7f53e26SMarkus Armbruster  */
blk_dev_is_tray_open(BlockBackend * blk)1184a7f53e26SMarkus Armbruster bool blk_dev_is_tray_open(BlockBackend *blk)
1185a7f53e26SMarkus Armbruster {
1186967d7905SEmanuele Giuseppe Esposito     IO_CODE();
11878f3a73bcSMax Reitz     if (blk_dev_has_tray(blk)) {
1188a7f53e26SMarkus Armbruster         return blk->dev_ops->is_tray_open(blk->dev_opaque);
1189a7f53e26SMarkus Armbruster     }
1190a7f53e26SMarkus Armbruster     return false;
1191a7f53e26SMarkus Armbruster }
1192a7f53e26SMarkus Armbruster 
1193a7f53e26SMarkus Armbruster /*
1194a7f53e26SMarkus Armbruster  * Does @blk's attached device model have the medium locked?
1195a7f53e26SMarkus Armbruster  * %false if the device model has no such lock.
1196a7f53e26SMarkus Armbruster  */
blk_dev_is_medium_locked(BlockBackend * blk)1197a7f53e26SMarkus Armbruster bool blk_dev_is_medium_locked(BlockBackend *blk)
1198a7f53e26SMarkus Armbruster {
1199b4ad82aaSEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1200a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->is_medium_locked) {
1201a7f53e26SMarkus Armbruster         return blk->dev_ops->is_medium_locked(blk->dev_opaque);
1202a7f53e26SMarkus Armbruster     }
1203a7f53e26SMarkus Armbruster     return false;
1204a7f53e26SMarkus Armbruster }
1205a7f53e26SMarkus Armbruster 
1206a7f53e26SMarkus Armbruster /*
1207a7f53e26SMarkus Armbruster  * Notify @blk's attached device model of a backend size change.
1208a7f53e26SMarkus Armbruster  */
blk_root_resize(BdrvChild * child)12095c8cab48SKevin Wolf static void blk_root_resize(BdrvChild *child)
1210a7f53e26SMarkus Armbruster {
12115c8cab48SKevin Wolf     BlockBackend *blk = child->opaque;
12125c8cab48SKevin Wolf 
1213a7f53e26SMarkus Armbruster     if (blk->dev_ops && blk->dev_ops->resize_cb) {
1214a7f53e26SMarkus Armbruster         blk->dev_ops->resize_cb(blk->dev_opaque);
1215a7f53e26SMarkus Armbruster     }
1216a7f53e26SMarkus Armbruster }
1217a7f53e26SMarkus Armbruster 
blk_iostatus_enable(BlockBackend * blk)12184be74634SMarkus Armbruster void blk_iostatus_enable(BlockBackend *blk)
12194be74634SMarkus Armbruster {
12200439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1221373340b2SMax Reitz     blk->iostatus_enabled = true;
1222373340b2SMax Reitz     blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
1223373340b2SMax Reitz }
1224373340b2SMax Reitz 
1225373340b2SMax Reitz /* The I/O status is only enabled if the drive explicitly
1226373340b2SMax Reitz  * enables it _and_ the VM is configured to stop on errors */
blk_iostatus_is_enabled(const BlockBackend * blk)1227373340b2SMax Reitz bool blk_iostatus_is_enabled(const BlockBackend *blk)
1228373340b2SMax Reitz {
122937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1230373340b2SMax Reitz     return (blk->iostatus_enabled &&
1231373340b2SMax Reitz            (blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
1232373340b2SMax Reitz             blk->on_write_error == BLOCKDEV_ON_ERROR_STOP   ||
1233373340b2SMax Reitz             blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
1234373340b2SMax Reitz }
1235373340b2SMax Reitz 
blk_iostatus(const BlockBackend * blk)1236373340b2SMax Reitz BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
1237373340b2SMax Reitz {
12380439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1239373340b2SMax Reitz     return blk->iostatus;
1240373340b2SMax Reitz }
1241373340b2SMax Reitz 
blk_iostatus_disable(BlockBackend * blk)1242373340b2SMax Reitz void blk_iostatus_disable(BlockBackend *blk)
1243373340b2SMax Reitz {
12440439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1245373340b2SMax Reitz     blk->iostatus_enabled = false;
1246373340b2SMax Reitz }
1247373340b2SMax Reitz 
blk_iostatus_reset(BlockBackend * blk)1248373340b2SMax Reitz void blk_iostatus_reset(BlockBackend *blk)
1249373340b2SMax Reitz {
12500439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1251373340b2SMax Reitz     if (blk_iostatus_is_enabled(blk)) {
1252373340b2SMax Reitz         blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
1253373340b2SMax Reitz     }
1254373340b2SMax Reitz }
1255373340b2SMax Reitz 
blk_iostatus_set_err(BlockBackend * blk,int error)1256373340b2SMax Reitz void blk_iostatus_set_err(BlockBackend *blk, int error)
1257373340b2SMax Reitz {
125837868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1259373340b2SMax Reitz     assert(blk_iostatus_is_enabled(blk));
1260373340b2SMax Reitz     if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
1261373340b2SMax Reitz         blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
1262373340b2SMax Reitz                                           BLOCK_DEVICE_IO_STATUS_FAILED;
1263373340b2SMax Reitz     }
12644be74634SMarkus Armbruster }
12654be74634SMarkus Armbruster 
blk_set_allow_write_beyond_eof(BlockBackend * blk,bool allow)1266c10c9d96SKevin Wolf void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow)
1267c10c9d96SKevin Wolf {
126837868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1269c10c9d96SKevin Wolf     blk->allow_write_beyond_eof = allow;
1270c10c9d96SKevin Wolf }
1271c10c9d96SKevin Wolf 
blk_set_allow_aio_context_change(BlockBackend * blk,bool allow)1272980b0f94SKevin Wolf void blk_set_allow_aio_context_change(BlockBackend *blk, bool allow)
1273980b0f94SKevin Wolf {
127437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1275980b0f94SKevin Wolf     blk->allow_aio_context_change = allow;
1276980b0f94SKevin Wolf }
1277980b0f94SKevin Wolf 
blk_set_disable_request_queuing(BlockBackend * blk,bool disable)1278cf312932SKevin Wolf void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
1279cf312932SKevin Wolf {
128037868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1281ef80ec50SStefan Hajnoczi     qatomic_set(&blk->disable_request_queuing, disable);
1282cf312932SKevin Wolf }
1283cf312932SKevin Wolf 
1284c73ff92cSEmanuele Giuseppe Esposito static int coroutine_fn GRAPH_RDLOCK
blk_check_byte_request(BlockBackend * blk,int64_t offset,int64_t bytes)1285c73ff92cSEmanuele Giuseppe Esposito blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes)
1286e7f7d676SMax Reitz {
1287e7f7d676SMax Reitz     int64_t len;
1288e7f7d676SMax Reitz 
1289aa78b825SVladimir Sementsov-Ogievskiy     if (bytes < 0) {
1290e7f7d676SMax Reitz         return -EIO;
1291e7f7d676SMax Reitz     }
1292e7f7d676SMax Reitz 
1293c73ff92cSEmanuele Giuseppe Esposito     if (!blk_co_is_available(blk)) {
1294e7f7d676SMax Reitz         return -ENOMEDIUM;
1295e7f7d676SMax Reitz     }
1296e7f7d676SMax Reitz 
1297c10c9d96SKevin Wolf     if (offset < 0) {
1298c10c9d96SKevin Wolf         return -EIO;
1299c10c9d96SKevin Wolf     }
1300c10c9d96SKevin Wolf 
1301c10c9d96SKevin Wolf     if (!blk->allow_write_beyond_eof) {
1302bd53086eSEmanuele Giuseppe Esposito         len = bdrv_co_getlength(blk_bs(blk));
1303e7f7d676SMax Reitz         if (len < 0) {
1304e7f7d676SMax Reitz             return len;
1305e7f7d676SMax Reitz         }
1306e7f7d676SMax Reitz 
13077242db63SVladimir Sementsov-Ogievskiy         if (offset > len || len - offset < bytes) {
1308e7f7d676SMax Reitz             return -EIO;
1309e7f7d676SMax Reitz         }
1310c10c9d96SKevin Wolf     }
1311e7f7d676SMax Reitz 
1312e7f7d676SMax Reitz     return 0;
1313e7f7d676SMax Reitz }
1314e7f7d676SMax Reitz 
1315ff82b783SStefan Hajnoczi /* Are we currently in a drained section? */
blk_in_drain(BlockBackend * blk)1316ff82b783SStefan Hajnoczi bool blk_in_drain(BlockBackend *blk)
1317ff82b783SStefan Hajnoczi {
1318ff82b783SStefan Hajnoczi     GLOBAL_STATE_CODE(); /* change to IO_OR_GS_CODE(), if necessary */
1319ff82b783SStefan Hajnoczi     return qatomic_read(&blk->quiesce_counter);
1320ff82b783SStefan Hajnoczi }
1321ff82b783SStefan Hajnoczi 
13227f16476fSKevin Wolf /* To be called between exactly one pair of blk_inc/dec_in_flight() */
blk_wait_while_drained(BlockBackend * blk)1323cf312932SKevin Wolf static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
1324cf312932SKevin Wolf {
13257f16476fSKevin Wolf     assert(blk->in_flight > 0);
13267f16476fSKevin Wolf 
1327ef80ec50SStefan Hajnoczi     if (qatomic_read(&blk->quiesce_counter) &&
1328ef80ec50SStefan Hajnoczi         !qatomic_read(&blk->disable_request_queuing)) {
1329407ae2aeSStefan Hajnoczi         /*
1330407ae2aeSStefan Hajnoczi          * Take lock before decrementing in flight counter so main loop thread
1331407ae2aeSStefan Hajnoczi          * waits for us to enqueue ourselves before it can leave the drained
1332407ae2aeSStefan Hajnoczi          * section.
1333407ae2aeSStefan Hajnoczi          */
1334407ae2aeSStefan Hajnoczi         qemu_mutex_lock(&blk->queued_requests_lock);
13357f16476fSKevin Wolf         blk_dec_in_flight(blk);
1336407ae2aeSStefan Hajnoczi         qemu_co_queue_wait(&blk->queued_requests, &blk->queued_requests_lock);
13377f16476fSKevin Wolf         blk_inc_in_flight(blk);
1338407ae2aeSStefan Hajnoczi         qemu_mutex_unlock(&blk->queued_requests_lock);
1339cf312932SKevin Wolf     }
1340cf312932SKevin Wolf }
1341cf312932SKevin Wolf 
1342fbb92b67SKevin Wolf /* To be called between exactly one pair of blk_inc/dec_in_flight() */
1343d1d3fc3dSAlberto Faria static int coroutine_fn
blk_co_do_preadv_part(BlockBackend * blk,int64_t offset,int64_t bytes,QEMUIOVector * qiov,size_t qiov_offset,BdrvRequestFlags flags)1344d1d3fc3dSAlberto Faria blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
1345d1d3fc3dSAlberto Faria                       QEMUIOVector *qiov, size_t qiov_offset,
1346d1d3fc3dSAlberto Faria                       BdrvRequestFlags flags)
13474be74634SMarkus Armbruster {
13481e98fefdSKevin Wolf     int ret;
1349cf312932SKevin Wolf     BlockDriverState *bs;
13501581a70dSEmanuele Giuseppe Esposito     IO_CODE();
13511e98fefdSKevin Wolf 
1352cf312932SKevin Wolf     blk_wait_while_drained(blk);
1353b9b10c35SKevin Wolf     GRAPH_RDLOCK_GUARD();
1354cf312932SKevin Wolf 
1355cf312932SKevin Wolf     /* Call blk_bs() only after waiting, the graph may have changed */
1356cf312932SKevin Wolf     bs = blk_bs(blk);
135799723548SPaolo Bonzini     trace_blk_co_preadv(blk, bs, offset, bytes, flags);
13581e98fefdSKevin Wolf 
13591e98fefdSKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
1360e7f7d676SMax Reitz     if (ret < 0) {
1361e7f7d676SMax Reitz         return ret;
1362e7f7d676SMax Reitz     }
1363e7f7d676SMax Reitz 
136499723548SPaolo Bonzini     bdrv_inc_in_flight(bs);
136599723548SPaolo Bonzini 
1366441565b2SKevin Wolf     /* throttling disk I/O */
1367022cdc9fSManos Pitsidianakis     if (blk->public.throttle_group_member.throttle_state) {
1368022cdc9fSManos Pitsidianakis         throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
13693b2337efSzhenwei pi                 bytes, THROTTLE_READ);
1370441565b2SKevin Wolf     }
1371441565b2SKevin Wolf 
1372d1d3fc3dSAlberto Faria     ret = bdrv_co_preadv_part(blk->root, offset, bytes, qiov, qiov_offset,
1373d1d3fc3dSAlberto Faria                               flags);
137499723548SPaolo Bonzini     bdrv_dec_in_flight(bs);
137599723548SPaolo Bonzini     return ret;
13761bf1cbc9SKevin Wolf }
13771bf1cbc9SKevin Wolf 
blk_co_pread(BlockBackend * blk,int64_t offset,int64_t bytes,void * buf,BdrvRequestFlags flags)13786f675c93SAlberto Faria int coroutine_fn blk_co_pread(BlockBackend *blk, int64_t offset, int64_t bytes,
13796f675c93SAlberto Faria                               void *buf, BdrvRequestFlags flags)
13806f675c93SAlberto Faria {
13816f675c93SAlberto Faria     QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
13826f675c93SAlberto Faria     IO_OR_GS_CODE();
13836f675c93SAlberto Faria 
13846f675c93SAlberto Faria     assert(bytes <= SIZE_MAX);
13856f675c93SAlberto Faria 
13866f675c93SAlberto Faria     return blk_co_preadv(blk, offset, bytes, &qiov, flags);
13876f675c93SAlberto Faria }
13886f675c93SAlberto Faria 
blk_co_preadv(BlockBackend * blk,int64_t offset,int64_t bytes,QEMUIOVector * qiov,BdrvRequestFlags flags)1389fbb92b67SKevin Wolf int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
139095479077SVladimir Sementsov-Ogievskiy                                int64_t bytes, QEMUIOVector *qiov,
1391fbb92b67SKevin Wolf                                BdrvRequestFlags flags)
1392fbb92b67SKevin Wolf {
1393fbb92b67SKevin Wolf     int ret;
139437868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
1395fbb92b67SKevin Wolf 
1396fbb92b67SKevin Wolf     blk_inc_in_flight(blk);
1397d1d3fc3dSAlberto Faria     ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, 0, flags);
1398d1d3fc3dSAlberto Faria     blk_dec_in_flight(blk);
1399d1d3fc3dSAlberto Faria 
1400d1d3fc3dSAlberto Faria     return ret;
1401d1d3fc3dSAlberto Faria }
1402d1d3fc3dSAlberto Faria 
blk_co_preadv_part(BlockBackend * blk,int64_t offset,int64_t bytes,QEMUIOVector * qiov,size_t qiov_offset,BdrvRequestFlags flags)1403d1d3fc3dSAlberto Faria int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
1404d1d3fc3dSAlberto Faria                                     int64_t bytes, QEMUIOVector *qiov,
1405d1d3fc3dSAlberto Faria                                     size_t qiov_offset, BdrvRequestFlags flags)
1406d1d3fc3dSAlberto Faria {
1407d1d3fc3dSAlberto Faria     int ret;
1408d1d3fc3dSAlberto Faria     IO_OR_GS_CODE();
1409d1d3fc3dSAlberto Faria 
1410d1d3fc3dSAlberto Faria     blk_inc_in_flight(blk);
1411d1d3fc3dSAlberto Faria     ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, qiov_offset, flags);
1412fbb92b67SKevin Wolf     blk_dec_in_flight(blk);
1413fbb92b67SKevin Wolf 
1414fbb92b67SKevin Wolf     return ret;
1415fbb92b67SKevin Wolf }
1416fbb92b67SKevin Wolf 
1417fbb92b67SKevin Wolf /* To be called between exactly one pair of blk_inc/dec_in_flight() */
141807a64aa4SAlberto Faria static int coroutine_fn
blk_co_do_pwritev_part(BlockBackend * blk,int64_t offset,int64_t bytes,QEMUIOVector * qiov,size_t qiov_offset,BdrvRequestFlags flags)141970e8775eSVladimir Sementsov-Ogievskiy blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
1420b3016864SVladimir Sementsov-Ogievskiy                        QEMUIOVector *qiov, size_t qiov_offset,
1421a8823a3bSKevin Wolf                        BdrvRequestFlags flags)
1422a8823a3bSKevin Wolf {
1423bfd18d1eSKevin Wolf     int ret;
1424cf312932SKevin Wolf     BlockDriverState *bs;
14251581a70dSEmanuele Giuseppe Esposito     IO_CODE();
1426bfd18d1eSKevin Wolf 
1427cf312932SKevin Wolf     blk_wait_while_drained(blk);
1428b9b10c35SKevin Wolf     GRAPH_RDLOCK_GUARD();
1429cf312932SKevin Wolf 
1430cf312932SKevin Wolf     /* Call blk_bs() only after waiting, the graph may have changed */
1431cf312932SKevin Wolf     bs = blk_bs(blk);
143299723548SPaolo Bonzini     trace_blk_co_pwritev(blk, bs, offset, bytes, flags);
14331e98fefdSKevin Wolf 
1434bfd18d1eSKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
1435a8823a3bSKevin Wolf     if (ret < 0) {
1436a8823a3bSKevin Wolf         return ret;
1437a8823a3bSKevin Wolf     }
1438a8823a3bSKevin Wolf 
143999723548SPaolo Bonzini     bdrv_inc_in_flight(bs);
1440441565b2SKevin Wolf     /* throttling disk I/O */
1441022cdc9fSManos Pitsidianakis     if (blk->public.throttle_group_member.throttle_state) {
1442022cdc9fSManos Pitsidianakis         throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
14433b2337efSzhenwei pi                 bytes, THROTTLE_WRITE);
1444441565b2SKevin Wolf     }
1445441565b2SKevin Wolf 
1446bfd18d1eSKevin Wolf     if (!blk->enable_write_cache) {
1447bfd18d1eSKevin Wolf         flags |= BDRV_REQ_FUA;
1448bfd18d1eSKevin Wolf     }
1449bfd18d1eSKevin Wolf 
1450b3016864SVladimir Sementsov-Ogievskiy     ret = bdrv_co_pwritev_part(blk->root, offset, bytes, qiov, qiov_offset,
1451b3016864SVladimir Sementsov-Ogievskiy                                flags);
145299723548SPaolo Bonzini     bdrv_dec_in_flight(bs);
145399723548SPaolo Bonzini     return ret;
1454a8823a3bSKevin Wolf }
1455a8823a3bSKevin Wolf 
blk_co_pwritev_part(BlockBackend * blk,int64_t offset,int64_t bytes,QEMUIOVector * qiov,size_t qiov_offset,BdrvRequestFlags flags)1456fbb92b67SKevin Wolf int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
145734460febSVladimir Sementsov-Ogievskiy                                      int64_t bytes,
1458fbb92b67SKevin Wolf                                      QEMUIOVector *qiov, size_t qiov_offset,
1459fbb92b67SKevin Wolf                                      BdrvRequestFlags flags)
1460fbb92b67SKevin Wolf {
1461fbb92b67SKevin Wolf     int ret;
146237868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
1463fbb92b67SKevin Wolf 
1464fbb92b67SKevin Wolf     blk_inc_in_flight(blk);
146570e8775eSVladimir Sementsov-Ogievskiy     ret = blk_co_do_pwritev_part(blk, offset, bytes, qiov, qiov_offset, flags);
1466fbb92b67SKevin Wolf     blk_dec_in_flight(blk);
1467fbb92b67SKevin Wolf 
1468fbb92b67SKevin Wolf     return ret;
1469fbb92b67SKevin Wolf }
1470fbb92b67SKevin Wolf 
blk_co_pwrite(BlockBackend * blk,int64_t offset,int64_t bytes,const void * buf,BdrvRequestFlags flags)14716f675c93SAlberto Faria int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
14726f675c93SAlberto Faria                                const void *buf, BdrvRequestFlags flags)
14736f675c93SAlberto Faria {
14746f675c93SAlberto Faria     QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
14756f675c93SAlberto Faria     IO_OR_GS_CODE();
14766f675c93SAlberto Faria 
14776f675c93SAlberto Faria     assert(bytes <= SIZE_MAX);
14786f675c93SAlberto Faria 
14796f675c93SAlberto Faria     return blk_co_pwritev(blk, offset, bytes, &qiov, flags);
14806f675c93SAlberto Faria }
14816f675c93SAlberto Faria 
blk_co_pwritev(BlockBackend * blk,int64_t offset,int64_t bytes,QEMUIOVector * qiov,BdrvRequestFlags flags)1482b3016864SVladimir Sementsov-Ogievskiy int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
148334460febSVladimir Sementsov-Ogievskiy                                 int64_t bytes, QEMUIOVector *qiov,
1484b3016864SVladimir Sementsov-Ogievskiy                                 BdrvRequestFlags flags)
1485b3016864SVladimir Sementsov-Ogievskiy {
148637868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
1487b3016864SVladimir Sementsov-Ogievskiy     return blk_co_pwritev_part(blk, offset, bytes, qiov, 0, flags);
1488b3016864SVladimir Sementsov-Ogievskiy }
1489b3016864SVladimir Sementsov-Ogievskiy 
blk_co_block_status_above(BlockBackend * blk,BlockDriverState * base,int64_t offset,int64_t bytes,int64_t * pnum,int64_t * map,BlockDriverState ** file)1490ff7e261bSEmanuele Giuseppe Esposito int coroutine_fn blk_co_block_status_above(BlockBackend *blk,
1491ff7e261bSEmanuele Giuseppe Esposito                                            BlockDriverState *base,
1492ff7e261bSEmanuele Giuseppe Esposito                                            int64_t offset, int64_t bytes,
1493ff7e261bSEmanuele Giuseppe Esposito                                            int64_t *pnum, int64_t *map,
1494ff7e261bSEmanuele Giuseppe Esposito                                            BlockDriverState **file)
1495ff7e261bSEmanuele Giuseppe Esposito {
1496ff7e261bSEmanuele Giuseppe Esposito     IO_CODE();
14977ff9579eSKevin Wolf     GRAPH_RDLOCK_GUARD();
1498ff7e261bSEmanuele Giuseppe Esposito     return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum,
1499ff7e261bSEmanuele Giuseppe Esposito                                       map, file);
1500ff7e261bSEmanuele Giuseppe Esposito }
1501ff7e261bSEmanuele Giuseppe Esposito 
blk_co_is_allocated_above(BlockBackend * blk,BlockDriverState * base,bool include_base,int64_t offset,int64_t bytes,int64_t * pnum)1502ff7e261bSEmanuele Giuseppe Esposito int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk,
1503ff7e261bSEmanuele Giuseppe Esposito                                            BlockDriverState *base,
1504ff7e261bSEmanuele Giuseppe Esposito                                            bool include_base, int64_t offset,
1505ff7e261bSEmanuele Giuseppe Esposito                                            int64_t bytes, int64_t *pnum)
1506ff7e261bSEmanuele Giuseppe Esposito {
1507ff7e261bSEmanuele Giuseppe Esposito     IO_CODE();
15087ff9579eSKevin Wolf     GRAPH_RDLOCK_GUARD();
1509ff7e261bSEmanuele Giuseppe Esposito     return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset,
1510ff7e261bSEmanuele Giuseppe Esposito                                       bytes, pnum);
1511ff7e261bSEmanuele Giuseppe Esposito }
1512ff7e261bSEmanuele Giuseppe Esposito 
15131bf1cbc9SKevin Wolf typedef struct BlkRwCo {
15141bf1cbc9SKevin Wolf     BlockBackend *blk;
15151bf1cbc9SKevin Wolf     int64_t offset;
1516c060332cSDeepa Srinivasan     void *iobuf;
15171bf1cbc9SKevin Wolf     int ret;
15181bf1cbc9SKevin Wolf     BdrvRequestFlags flags;
15191bf1cbc9SKevin Wolf } BlkRwCo;
15201bf1cbc9SKevin Wolf 
blk_make_zero(BlockBackend * blk,BdrvRequestFlags flags)1521720ff280SKevin Wolf int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
1522720ff280SKevin Wolf {
15230439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
1524720ff280SKevin Wolf     return bdrv_make_zero(blk->root, flags);
1525720ff280SKevin Wolf }
1526720ff280SKevin Wolf 
blk_inc_in_flight(BlockBackend * blk)1527c90e2a9cSKevin Wolf void blk_inc_in_flight(BlockBackend *blk)
152833f2a757SStefan Hajnoczi {
152937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1530d73415a3SStefan Hajnoczi     qatomic_inc(&blk->in_flight);
153133f2a757SStefan Hajnoczi }
153233f2a757SStefan Hajnoczi 
blk_dec_in_flight(BlockBackend * blk)1533c90e2a9cSKevin Wolf void blk_dec_in_flight(BlockBackend *blk)
153433f2a757SStefan Hajnoczi {
153537868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1536d73415a3SStefan Hajnoczi     qatomic_dec(&blk->in_flight);
1537cfe29d82SKevin Wolf     aio_wait_kick();
153833f2a757SStefan Hajnoczi }
153933f2a757SStefan Hajnoczi 
error_callback_bh(void * opaque)1540e7f7d676SMax Reitz static void error_callback_bh(void *opaque)
1541e7f7d676SMax Reitz {
1542e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb = opaque;
154399723548SPaolo Bonzini 
154433f2a757SStefan Hajnoczi     blk_dec_in_flight(acb->blk);
1545e7f7d676SMax Reitz     acb->common.cb(acb->common.opaque, acb->ret);
1546e7f7d676SMax Reitz     qemu_aio_unref(acb);
1547e7f7d676SMax Reitz }
1548e7f7d676SMax Reitz 
blk_abort_aio_request(BlockBackend * blk,BlockCompletionFunc * cb,void * opaque,int ret)1549ca78ecfaSPeter Lieven BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
1550ca78ecfaSPeter Lieven                                   BlockCompletionFunc *cb,
1551e7f7d676SMax Reitz                                   void *opaque, int ret)
1552e7f7d676SMax Reitz {
1553e7f7d676SMax Reitz     struct BlockBackendAIOCB *acb;
155437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1555e7f7d676SMax Reitz 
155633f2a757SStefan Hajnoczi     blk_inc_in_flight(blk);
1557e7f7d676SMax Reitz     acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
15584981bdecSMax Reitz     acb->blk = blk;
1559e7f7d676SMax Reitz     acb->ret = ret;
1560e7f7d676SMax Reitz 
156146eb6e86SStefan Hajnoczi     replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
1562e4ec5ad4SPavel Dovgalyuk                                      error_callback_bh, acb);
1563e7f7d676SMax Reitz     return &acb->common;
1564e7f7d676SMax Reitz }
1565e7f7d676SMax Reitz 
156657d6a428SKevin Wolf typedef struct BlkAioEmAIOCB {
156757d6a428SKevin Wolf     BlockAIOCB common;
156857d6a428SKevin Wolf     BlkRwCo rwco;
1569a93d81c8SVladimir Sementsov-Ogievskiy     int64_t bytes;
157057d6a428SKevin Wolf     bool has_returned;
157157d6a428SKevin Wolf } BlkAioEmAIOCB;
157257d6a428SKevin Wolf 
157357d6a428SKevin Wolf static const AIOCBInfo blk_aio_em_aiocb_info = {
157457d6a428SKevin Wolf     .aiocb_size         = sizeof(BlkAioEmAIOCB),
157557d6a428SKevin Wolf };
157657d6a428SKevin Wolf 
blk_aio_complete(BlkAioEmAIOCB * acb)157757d6a428SKevin Wolf static void blk_aio_complete(BlkAioEmAIOCB *acb)
157857d6a428SKevin Wolf {
157957d6a428SKevin Wolf     if (acb->has_returned) {
158057d6a428SKevin Wolf         acb->common.cb(acb->common.opaque, acb->rwco.ret);
158146aaf2a5SKevin Wolf         blk_dec_in_flight(acb->rwco.blk);
158257d6a428SKevin Wolf         qemu_aio_unref(acb);
158357d6a428SKevin Wolf     }
158457d6a428SKevin Wolf }
158557d6a428SKevin Wolf 
blk_aio_complete_bh(void * opaque)158657d6a428SKevin Wolf static void blk_aio_complete_bh(void *opaque)
158757d6a428SKevin Wolf {
1588fffb6e12SPaolo Bonzini     BlkAioEmAIOCB *acb = opaque;
1589fffb6e12SPaolo Bonzini     assert(acb->has_returned);
1590fffb6e12SPaolo Bonzini     blk_aio_complete(acb);
159157d6a428SKevin Wolf }
159257d6a428SKevin Wolf 
blk_aio_prwv(BlockBackend * blk,int64_t offset,int64_t bytes,void * iobuf,CoroutineEntry co_entry,BdrvRequestFlags flags,BlockCompletionFunc * cb,void * opaque)1593a93d81c8SVladimir Sementsov-Ogievskiy static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
1594a93d81c8SVladimir Sementsov-Ogievskiy                                 int64_t bytes,
1595c060332cSDeepa Srinivasan                                 void *iobuf, CoroutineEntry co_entry,
159657d6a428SKevin Wolf                                 BdrvRequestFlags flags,
159757d6a428SKevin Wolf                                 BlockCompletionFunc *cb, void *opaque)
159857d6a428SKevin Wolf {
159957d6a428SKevin Wolf     BlkAioEmAIOCB *acb;
160057d6a428SKevin Wolf     Coroutine *co;
160157d6a428SKevin Wolf 
160233f2a757SStefan Hajnoczi     blk_inc_in_flight(blk);
160357d6a428SKevin Wolf     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
160457d6a428SKevin Wolf     acb->rwco = (BlkRwCo) {
160557d6a428SKevin Wolf         .blk    = blk,
160657d6a428SKevin Wolf         .offset = offset,
1607c060332cSDeepa Srinivasan         .iobuf  = iobuf,
160857d6a428SKevin Wolf         .flags  = flags,
160957d6a428SKevin Wolf         .ret    = NOT_DONE,
161057d6a428SKevin Wolf     };
16117fa84cd8SKevin Wolf     acb->bytes = bytes;
161257d6a428SKevin Wolf     acb->has_returned = false;
161357d6a428SKevin Wolf 
16140b8b8753SPaolo Bonzini     co = qemu_coroutine_create(co_entry, acb);
161546eb6e86SStefan Hajnoczi     aio_co_enter(qemu_get_current_aio_context(), co);
161657d6a428SKevin Wolf 
161757d6a428SKevin Wolf     acb->has_returned = true;
161857d6a428SKevin Wolf     if (acb->rwco.ret != NOT_DONE) {
161946eb6e86SStefan Hajnoczi         replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
1620fffb6e12SPaolo Bonzini                                          blk_aio_complete_bh, acb);
162157d6a428SKevin Wolf     }
162257d6a428SKevin Wolf 
162357d6a428SKevin Wolf     return &acb->common;
162457d6a428SKevin Wolf }
162557d6a428SKevin Wolf 
blk_aio_read_entry(void * opaque)1626881a4c55SPaolo Bonzini static void coroutine_fn blk_aio_read_entry(void *opaque)
162757d6a428SKevin Wolf {
162857d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
162957d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
1630c060332cSDeepa Srinivasan     QEMUIOVector *qiov = rwco->iobuf;
163157d6a428SKevin Wolf 
1632c060332cSDeepa Srinivasan     assert(qiov->size == acb->bytes);
1633d1d3fc3dSAlberto Faria     rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov,
1634d1d3fc3dSAlberto Faria                                       0, rwco->flags);
163557d6a428SKevin Wolf     blk_aio_complete(acb);
163657d6a428SKevin Wolf }
163757d6a428SKevin Wolf 
blk_aio_write_entry(void * opaque)1638881a4c55SPaolo Bonzini static void coroutine_fn blk_aio_write_entry(void *opaque)
163957d6a428SKevin Wolf {
164057d6a428SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
164157d6a428SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
1642c060332cSDeepa Srinivasan     QEMUIOVector *qiov = rwco->iobuf;
164357d6a428SKevin Wolf 
1644c060332cSDeepa Srinivasan     assert(!qiov || qiov->size == acb->bytes);
164570e8775eSVladimir Sementsov-Ogievskiy     rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes,
1646fbb92b67SKevin Wolf                                        qiov, 0, rwco->flags);
164757d6a428SKevin Wolf     blk_aio_complete(acb);
164857d6a428SKevin Wolf }
164957d6a428SKevin Wolf 
blk_aio_pwrite_zeroes(BlockBackend * blk,int64_t offset,int64_t bytes,BdrvRequestFlags flags,BlockCompletionFunc * cb,void * opaque)1650d004bd52SEric Blake BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
1651a93d81c8SVladimir Sementsov-Ogievskiy                                   int64_t bytes, BdrvRequestFlags flags,
16524be74634SMarkus Armbruster                                   BlockCompletionFunc *cb, void *opaque)
16534be74634SMarkus Armbruster {
165437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1655a93d81c8SVladimir Sementsov-Ogievskiy     return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_write_entry,
1656983a1600SEric Blake                         flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
16574be74634SMarkus Armbruster }
16584be74634SMarkus Armbruster 
blk_co_getlength(BlockBackend * blk)1659c86422c5SEmanuele Giuseppe Esposito int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
16604be74634SMarkus Armbruster {
166137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1662c73ff92cSEmanuele Giuseppe Esposito     GRAPH_RDLOCK_GUARD();
1663c86422c5SEmanuele Giuseppe Esposito 
1664c73ff92cSEmanuele Giuseppe Esposito     if (!blk_co_is_available(blk)) {
1665c09ba36cSMax Reitz         return -ENOMEDIUM;
1666c09ba36cSMax Reitz     }
1667c09ba36cSMax Reitz 
1668c86422c5SEmanuele Giuseppe Esposito     return bdrv_co_getlength(blk_bs(blk));
16694be74634SMarkus Armbruster }
16704be74634SMarkus Armbruster 
blk_co_nb_sectors(BlockBackend * blk)16719ed98caeSPaolo Bonzini int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
16724be74634SMarkus Armbruster {
1673e5203a3bSPaolo Bonzini     BlockDriverState *bs = blk_bs(blk);
1674e5203a3bSPaolo Bonzini 
167537868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1676d8fbf9aaSKevin Wolf     GRAPH_RDLOCK_GUARD();
1677d8fbf9aaSKevin Wolf 
1678e5203a3bSPaolo Bonzini     if (!bs) {
1679c09ba36cSMax Reitz         return -ENOMEDIUM;
16809ed98caeSPaolo Bonzini     } else {
16819ed98caeSPaolo Bonzini         return bdrv_co_nb_sectors(bs);
16829ed98caeSPaolo Bonzini     }
1683c09ba36cSMax Reitz }
1684c09ba36cSMax Reitz 
168581f730d4SPaolo Bonzini /*
168681f730d4SPaolo Bonzini  * This wrapper is written by hand because this function is in the hot I/O path,
168781f730d4SPaolo Bonzini  * via blk_get_geometry.
168881f730d4SPaolo Bonzini  */
blk_nb_sectors(BlockBackend * blk)168981f730d4SPaolo Bonzini int64_t coroutine_mixed_fn blk_nb_sectors(BlockBackend *blk)
169081f730d4SPaolo Bonzini {
169181f730d4SPaolo Bonzini     BlockDriverState *bs = blk_bs(blk);
169281f730d4SPaolo Bonzini 
169381f730d4SPaolo Bonzini     IO_CODE();
169481f730d4SPaolo Bonzini 
169581f730d4SPaolo Bonzini     if (!bs) {
169681f730d4SPaolo Bonzini         return -ENOMEDIUM;
169781f730d4SPaolo Bonzini     } else {
169881f730d4SPaolo Bonzini         return bdrv_nb_sectors(bs);
169981f730d4SPaolo Bonzini     }
170081f730d4SPaolo Bonzini }
170181f730d4SPaolo Bonzini 
17029ed98caeSPaolo Bonzini /* return 0 as number of sectors if no device present or error */
blk_co_get_geometry(BlockBackend * blk,uint64_t * nb_sectors_ptr)17039ed98caeSPaolo Bonzini void coroutine_fn blk_co_get_geometry(BlockBackend *blk,
17049ed98caeSPaolo Bonzini                                       uint64_t *nb_sectors_ptr)
17059ed98caeSPaolo Bonzini {
17069ed98caeSPaolo Bonzini     int64_t ret = blk_co_nb_sectors(blk);
17079ed98caeSPaolo Bonzini     *nb_sectors_ptr = ret < 0 ? 0 : ret;
17081ef01253SMax Reitz }
17091ef01253SMax Reitz 
171081f730d4SPaolo Bonzini /*
171181f730d4SPaolo Bonzini  * This wrapper is written by hand because this function is in the hot I/O path.
171281f730d4SPaolo Bonzini  */
blk_get_geometry(BlockBackend * blk,uint64_t * nb_sectors_ptr)171381f730d4SPaolo Bonzini void coroutine_mixed_fn blk_get_geometry(BlockBackend *blk,
171481f730d4SPaolo Bonzini                                          uint64_t *nb_sectors_ptr)
171581f730d4SPaolo Bonzini {
171681f730d4SPaolo Bonzini     int64_t ret = blk_nb_sectors(blk);
171781f730d4SPaolo Bonzini     *nb_sectors_ptr = ret < 0 ? 0 : ret;
171881f730d4SPaolo Bonzini }
171981f730d4SPaolo Bonzini 
blk_aio_preadv(BlockBackend * blk,int64_t offset,QEMUIOVector * qiov,BdrvRequestFlags flags,BlockCompletionFunc * cb,void * opaque)172060cb2fa7SEric Blake BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
172160cb2fa7SEric Blake                            QEMUIOVector *qiov, BdrvRequestFlags flags,
172260cb2fa7SEric Blake                            BlockCompletionFunc *cb, void *opaque)
172360cb2fa7SEric Blake {
172437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1725a93d81c8SVladimir Sementsov-Ogievskiy     assert((uint64_t)qiov->size <= INT64_MAX);
172660cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
172760cb2fa7SEric Blake                         blk_aio_read_entry, flags, cb, opaque);
172860cb2fa7SEric Blake }
172960cb2fa7SEric Blake 
blk_aio_pwritev(BlockBackend * blk,int64_t offset,QEMUIOVector * qiov,BdrvRequestFlags flags,BlockCompletionFunc * cb,void * opaque)173060cb2fa7SEric Blake BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
173160cb2fa7SEric Blake                             QEMUIOVector *qiov, BdrvRequestFlags flags,
173260cb2fa7SEric Blake                             BlockCompletionFunc *cb, void *opaque)
173360cb2fa7SEric Blake {
173437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
173573d4a113SHanna Reitz     assert((uint64_t)qiov->size <= INT64_MAX);
173660cb2fa7SEric Blake     return blk_aio_prwv(blk, offset, qiov->size, qiov,
173760cb2fa7SEric Blake                         blk_aio_write_entry, flags, cb, opaque);
173860cb2fa7SEric Blake }
173960cb2fa7SEric Blake 
blk_aio_cancel(BlockAIOCB * acb)17404be74634SMarkus Armbruster void blk_aio_cancel(BlockAIOCB *acb)
17414be74634SMarkus Armbruster {
17420439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
17434be74634SMarkus Armbruster     bdrv_aio_cancel(acb);
17444be74634SMarkus Armbruster }
17454be74634SMarkus Armbruster 
blk_aio_cancel_async(BlockAIOCB * acb)17464be74634SMarkus Armbruster void blk_aio_cancel_async(BlockAIOCB *acb)
17474be74634SMarkus Armbruster {
174837868b2aSEmanuele Giuseppe Esposito     IO_CODE();
17494be74634SMarkus Armbruster     bdrv_aio_cancel_async(acb);
17504be74634SMarkus Armbruster }
17514be74634SMarkus Armbruster 
1752fbb92b67SKevin Wolf /* To be called between exactly one pair of blk_inc/dec_in_flight() */
1753df02da00SAlberto Faria static int coroutine_fn
blk_co_do_ioctl(BlockBackend * blk,unsigned long int req,void * buf)175470e8775eSVladimir Sementsov-Ogievskiy blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
17554be74634SMarkus Armbruster {
17561581a70dSEmanuele Giuseppe Esposito     IO_CODE();
17571581a70dSEmanuele Giuseppe Esposito 
1758cf312932SKevin Wolf     blk_wait_while_drained(blk);
175926c518abSKevin Wolf     GRAPH_RDLOCK_GUARD();
1760cf312932SKevin Wolf 
1761c73ff92cSEmanuele Giuseppe Esposito     if (!blk_co_is_available(blk)) {
1762c09ba36cSMax Reitz         return -ENOMEDIUM;
1763c09ba36cSMax Reitz     }
1764c09ba36cSMax Reitz 
176548af776aSKevin Wolf     return bdrv_co_ioctl(blk_bs(blk), req, buf);
176648af776aSKevin Wolf }
176748af776aSKevin Wolf 
blk_co_ioctl(BlockBackend * blk,unsigned long int req,void * buf)1768df02da00SAlberto Faria int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
1769df02da00SAlberto Faria                               void *buf)
177048af776aSKevin Wolf {
177116d36e29SVladimir Sementsov-Ogievskiy     int ret;
177237868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
177316d36e29SVladimir Sementsov-Ogievskiy 
177416d36e29SVladimir Sementsov-Ogievskiy     blk_inc_in_flight(blk);
1775df02da00SAlberto Faria     ret = blk_co_do_ioctl(blk, req, buf);
177616d36e29SVladimir Sementsov-Ogievskiy     blk_dec_in_flight(blk);
177716d36e29SVladimir Sementsov-Ogievskiy 
177816d36e29SVladimir Sementsov-Ogievskiy     return ret;
177948af776aSKevin Wolf }
178048af776aSKevin Wolf 
blk_aio_ioctl_entry(void * opaque)1781881a4c55SPaolo Bonzini static void coroutine_fn blk_aio_ioctl_entry(void *opaque)
178248af776aSKevin Wolf {
178348af776aSKevin Wolf     BlkAioEmAIOCB *acb = opaque;
178448af776aSKevin Wolf     BlkRwCo *rwco = &acb->rwco;
178548af776aSKevin Wolf 
178670e8775eSVladimir Sementsov-Ogievskiy     rwco->ret = blk_co_do_ioctl(rwco->blk, rwco->offset, rwco->iobuf);
1787c060332cSDeepa Srinivasan 
178848af776aSKevin Wolf     blk_aio_complete(acb);
17894be74634SMarkus Armbruster }
17904be74634SMarkus Armbruster 
blk_aio_ioctl(BlockBackend * blk,unsigned long int req,void * buf,BlockCompletionFunc * cb,void * opaque)17914be74634SMarkus Armbruster BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
17924be74634SMarkus Armbruster                           BlockCompletionFunc *cb, void *opaque)
17934be74634SMarkus Armbruster {
179437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1795c060332cSDeepa Srinivasan     return blk_aio_prwv(blk, req, 0, buf, blk_aio_ioctl_entry, 0, cb, opaque);
17964be74634SMarkus Armbruster }
17974be74634SMarkus Armbruster 
1798fbb92b67SKevin Wolf /* To be called between exactly one pair of blk_inc/dec_in_flight() */
179907a64aa4SAlberto Faria static int coroutine_fn
blk_co_do_pdiscard(BlockBackend * blk,int64_t offset,int64_t bytes)180070e8775eSVladimir Sementsov-Ogievskiy blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
18012bb0dce7SMax Reitz {
1802cf312932SKevin Wolf     int ret;
18031581a70dSEmanuele Giuseppe Esposito     IO_CODE();
1804cf312932SKevin Wolf 
1805cf312932SKevin Wolf     blk_wait_while_drained(blk);
18069a5a1c62SEmanuele Giuseppe Esposito     GRAPH_RDLOCK_GUARD();
1807cf312932SKevin Wolf 
1808cf312932SKevin Wolf     ret = blk_check_byte_request(blk, offset, bytes);
1809e7f7d676SMax Reitz     if (ret < 0) {
1810e7f7d676SMax Reitz         return ret;
1811e7f7d676SMax Reitz     }
1812e7f7d676SMax Reitz 
18130b9fd3f4SFam Zheng     return bdrv_co_pdiscard(blk->root, offset, bytes);
18142bb0dce7SMax Reitz }
18152bb0dce7SMax Reitz 
blk_aio_pdiscard_entry(void * opaque)1816881a4c55SPaolo Bonzini static void coroutine_fn blk_aio_pdiscard_entry(void *opaque)
1817564806c5SKevin Wolf {
1818564806c5SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
1819564806c5SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
1820564806c5SKevin Wolf 
182170e8775eSVladimir Sementsov-Ogievskiy     rwco->ret = blk_co_do_pdiscard(rwco->blk, rwco->offset, acb->bytes);
1822564806c5SKevin Wolf     blk_aio_complete(acb);
1823564806c5SKevin Wolf }
1824564806c5SKevin Wolf 
blk_aio_pdiscard(BlockBackend * blk,int64_t offset,int64_t bytes,BlockCompletionFunc * cb,void * opaque)1825564806c5SKevin Wolf BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk,
1826a93d81c8SVladimir Sementsov-Ogievskiy                              int64_t offset, int64_t bytes,
1827564806c5SKevin Wolf                              BlockCompletionFunc *cb, void *opaque)
1828564806c5SKevin Wolf {
182937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1830564806c5SKevin Wolf     return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_pdiscard_entry, 0,
1831564806c5SKevin Wolf                         cb, opaque);
1832564806c5SKevin Wolf }
1833564806c5SKevin Wolf 
blk_co_pdiscard(BlockBackend * blk,int64_t offset,int64_t bytes)18342800637aSVladimir Sementsov-Ogievskiy int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
18352800637aSVladimir Sementsov-Ogievskiy                                  int64_t bytes)
1836fbb92b67SKevin Wolf {
1837fbb92b67SKevin Wolf     int ret;
183837868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
1839fbb92b67SKevin Wolf 
1840fbb92b67SKevin Wolf     blk_inc_in_flight(blk);
184170e8775eSVladimir Sementsov-Ogievskiy     ret = blk_co_do_pdiscard(blk, offset, bytes);
1842fbb92b67SKevin Wolf     blk_dec_in_flight(blk);
1843fbb92b67SKevin Wolf 
1844fbb92b67SKevin Wolf     return ret;
1845fbb92b67SKevin Wolf }
1846fbb92b67SKevin Wolf 
1847fbb92b67SKevin Wolf /* To be called between exactly one pair of blk_inc/dec_in_flight() */
blk_co_do_flush(BlockBackend * blk)184807a64aa4SAlberto Faria static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
18492bb0dce7SMax Reitz {
18501581a70dSEmanuele Giuseppe Esposito     IO_CODE();
185188095349SEmanuele Giuseppe Esposito     blk_wait_while_drained(blk);
185288095349SEmanuele Giuseppe Esposito     GRAPH_RDLOCK_GUARD();
1853cf312932SKevin Wolf 
1854c73ff92cSEmanuele Giuseppe Esposito     if (!blk_co_is_available(blk)) {
1855c09ba36cSMax Reitz         return -ENOMEDIUM;
1856c09ba36cSMax Reitz     }
1857c09ba36cSMax Reitz 
1858f21d96d0SKevin Wolf     return bdrv_co_flush(blk_bs(blk));
18592bb0dce7SMax Reitz }
18602bb0dce7SMax Reitz 
blk_aio_flush_entry(void * opaque)1861881a4c55SPaolo Bonzini static void coroutine_fn blk_aio_flush_entry(void *opaque)
1862564806c5SKevin Wolf {
1863564806c5SKevin Wolf     BlkAioEmAIOCB *acb = opaque;
1864564806c5SKevin Wolf     BlkRwCo *rwco = &acb->rwco;
1865564806c5SKevin Wolf 
186670e8775eSVladimir Sementsov-Ogievskiy     rwco->ret = blk_co_do_flush(rwco->blk);
1867564806c5SKevin Wolf     blk_aio_complete(acb);
1868564806c5SKevin Wolf }
1869564806c5SKevin Wolf 
blk_aio_flush(BlockBackend * blk,BlockCompletionFunc * cb,void * opaque)1870564806c5SKevin Wolf BlockAIOCB *blk_aio_flush(BlockBackend *blk,
1871564806c5SKevin Wolf                           BlockCompletionFunc *cb, void *opaque)
1872564806c5SKevin Wolf {
187337868b2aSEmanuele Giuseppe Esposito     IO_CODE();
1874564806c5SKevin Wolf     return blk_aio_prwv(blk, 0, 0, NULL, blk_aio_flush_entry, 0, cb, opaque);
1875564806c5SKevin Wolf }
1876564806c5SKevin Wolf 
blk_co_flush(BlockBackend * blk)1877fbb92b67SKevin Wolf int coroutine_fn blk_co_flush(BlockBackend *blk)
1878fbb92b67SKevin Wolf {
1879fbb92b67SKevin Wolf     int ret;
188037868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
1881fbb92b67SKevin Wolf 
1882fbb92b67SKevin Wolf     blk_inc_in_flight(blk);
188370e8775eSVladimir Sementsov-Ogievskiy     ret = blk_co_do_flush(blk);
1884fbb92b67SKevin Wolf     blk_dec_in_flight(blk);
1885fbb92b67SKevin Wolf 
1886fbb92b67SKevin Wolf     return ret;
1887fbb92b67SKevin Wolf }
1888fbb92b67SKevin Wolf 
blk_aio_zone_report_entry(void * opaque)18896d43eaa3SSam Li static void coroutine_fn blk_aio_zone_report_entry(void *opaque)
18906d43eaa3SSam Li {
18916d43eaa3SSam Li     BlkAioEmAIOCB *acb = opaque;
18926d43eaa3SSam Li     BlkRwCo *rwco = &acb->rwco;
18936d43eaa3SSam Li 
18946d43eaa3SSam Li     rwco->ret = blk_co_zone_report(rwco->blk, rwco->offset,
18956d43eaa3SSam Li                                    (unsigned int*)(uintptr_t)acb->bytes,
18966d43eaa3SSam Li                                    rwco->iobuf);
18976d43eaa3SSam Li     blk_aio_complete(acb);
18986d43eaa3SSam Li }
18996d43eaa3SSam Li 
blk_aio_zone_report(BlockBackend * blk,int64_t offset,unsigned int * nr_zones,BlockZoneDescriptor * zones,BlockCompletionFunc * cb,void * opaque)19006d43eaa3SSam Li BlockAIOCB *blk_aio_zone_report(BlockBackend *blk, int64_t offset,
19016d43eaa3SSam Li                                 unsigned int *nr_zones,
19026d43eaa3SSam Li                                 BlockZoneDescriptor  *zones,
19036d43eaa3SSam Li                                 BlockCompletionFunc *cb, void *opaque)
19046d43eaa3SSam Li {
19056d43eaa3SSam Li     BlkAioEmAIOCB *acb;
19066d43eaa3SSam Li     Coroutine *co;
19076d43eaa3SSam Li     IO_CODE();
19086d43eaa3SSam Li 
19096d43eaa3SSam Li     blk_inc_in_flight(blk);
19106d43eaa3SSam Li     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
19116d43eaa3SSam Li     acb->rwco = (BlkRwCo) {
19126d43eaa3SSam Li         .blk    = blk,
19136d43eaa3SSam Li         .offset = offset,
19146d43eaa3SSam Li         .iobuf  = zones,
19156d43eaa3SSam Li         .ret    = NOT_DONE,
19166d43eaa3SSam Li     };
19176d43eaa3SSam Li     acb->bytes = (int64_t)(uintptr_t)nr_zones,
19186d43eaa3SSam Li     acb->has_returned = false;
19196d43eaa3SSam Li 
19206d43eaa3SSam Li     co = qemu_coroutine_create(blk_aio_zone_report_entry, acb);
19210f86afdeSStefan Hajnoczi     aio_co_enter(qemu_get_current_aio_context(), co);
19226d43eaa3SSam Li 
19236d43eaa3SSam Li     acb->has_returned = true;
19246d43eaa3SSam Li     if (acb->rwco.ret != NOT_DONE) {
19250f86afdeSStefan Hajnoczi         replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
19266d43eaa3SSam Li                                          blk_aio_complete_bh, acb);
19276d43eaa3SSam Li     }
19286d43eaa3SSam Li 
19296d43eaa3SSam Li     return &acb->common;
19306d43eaa3SSam Li }
19316d43eaa3SSam Li 
blk_aio_zone_mgmt_entry(void * opaque)19326d43eaa3SSam Li static void coroutine_fn blk_aio_zone_mgmt_entry(void *opaque)
19336d43eaa3SSam Li {
19346d43eaa3SSam Li     BlkAioEmAIOCB *acb = opaque;
19356d43eaa3SSam Li     BlkRwCo *rwco = &acb->rwco;
19366d43eaa3SSam Li 
19376d43eaa3SSam Li     rwco->ret = blk_co_zone_mgmt(rwco->blk,
19386d43eaa3SSam Li                                  (BlockZoneOp)(uintptr_t)rwco->iobuf,
19396d43eaa3SSam Li                                  rwco->offset, acb->bytes);
19406d43eaa3SSam Li     blk_aio_complete(acb);
19416d43eaa3SSam Li }
19426d43eaa3SSam Li 
blk_aio_zone_mgmt(BlockBackend * blk,BlockZoneOp op,int64_t offset,int64_t len,BlockCompletionFunc * cb,void * opaque)19436d43eaa3SSam Li BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
19446d43eaa3SSam Li                               int64_t offset, int64_t len,
19456d43eaa3SSam Li                               BlockCompletionFunc *cb, void *opaque) {
19466d43eaa3SSam Li     BlkAioEmAIOCB *acb;
19476d43eaa3SSam Li     Coroutine *co;
19486d43eaa3SSam Li     IO_CODE();
19496d43eaa3SSam Li 
19506d43eaa3SSam Li     blk_inc_in_flight(blk);
19516d43eaa3SSam Li     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
19526d43eaa3SSam Li     acb->rwco = (BlkRwCo) {
19536d43eaa3SSam Li         .blk    = blk,
19546d43eaa3SSam Li         .offset = offset,
19556d43eaa3SSam Li         .iobuf  = (void *)(uintptr_t)op,
19566d43eaa3SSam Li         .ret    = NOT_DONE,
19576d43eaa3SSam Li     };
19586d43eaa3SSam Li     acb->bytes = len;
19596d43eaa3SSam Li     acb->has_returned = false;
19606d43eaa3SSam Li 
19616d43eaa3SSam Li     co = qemu_coroutine_create(blk_aio_zone_mgmt_entry, acb);
19620f86afdeSStefan Hajnoczi     aio_co_enter(qemu_get_current_aio_context(), co);
19636d43eaa3SSam Li 
19646d43eaa3SSam Li     acb->has_returned = true;
19656d43eaa3SSam Li     if (acb->rwco.ret != NOT_DONE) {
19660f86afdeSStefan Hajnoczi         replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
19676d43eaa3SSam Li                                          blk_aio_complete_bh, acb);
19686d43eaa3SSam Li     }
19696d43eaa3SSam Li 
19706d43eaa3SSam Li     return &acb->common;
19716d43eaa3SSam Li }
19726d43eaa3SSam Li 
blk_aio_zone_append_entry(void * opaque)19734751d09aSSam Li static void coroutine_fn blk_aio_zone_append_entry(void *opaque)
19744751d09aSSam Li {
19754751d09aSSam Li     BlkAioEmAIOCB *acb = opaque;
19764751d09aSSam Li     BlkRwCo *rwco = &acb->rwco;
19774751d09aSSam Li 
19784751d09aSSam Li     rwco->ret = blk_co_zone_append(rwco->blk, (int64_t *)(uintptr_t)acb->bytes,
19794751d09aSSam Li                                    rwco->iobuf, rwco->flags);
19804751d09aSSam Li     blk_aio_complete(acb);
19814751d09aSSam Li }
19824751d09aSSam Li 
blk_aio_zone_append(BlockBackend * blk,int64_t * offset,QEMUIOVector * qiov,BdrvRequestFlags flags,BlockCompletionFunc * cb,void * opaque)19834751d09aSSam Li BlockAIOCB *blk_aio_zone_append(BlockBackend *blk, int64_t *offset,
19844751d09aSSam Li                                 QEMUIOVector *qiov, BdrvRequestFlags flags,
19854751d09aSSam Li                                 BlockCompletionFunc *cb, void *opaque) {
19864751d09aSSam Li     BlkAioEmAIOCB *acb;
19874751d09aSSam Li     Coroutine *co;
19884751d09aSSam Li     IO_CODE();
19894751d09aSSam Li 
19904751d09aSSam Li     blk_inc_in_flight(blk);
19914751d09aSSam Li     acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
19924751d09aSSam Li     acb->rwco = (BlkRwCo) {
19934751d09aSSam Li         .blk    = blk,
19944751d09aSSam Li         .ret    = NOT_DONE,
19954751d09aSSam Li         .flags  = flags,
19964751d09aSSam Li         .iobuf  = qiov,
19974751d09aSSam Li     };
19984751d09aSSam Li     acb->bytes = (int64_t)(uintptr_t)offset;
19994751d09aSSam Li     acb->has_returned = false;
20004751d09aSSam Li 
20014751d09aSSam Li     co = qemu_coroutine_create(blk_aio_zone_append_entry, acb);
20020f86afdeSStefan Hajnoczi     aio_co_enter(qemu_get_current_aio_context(), co);
20034751d09aSSam Li     acb->has_returned = true;
20044751d09aSSam Li     if (acb->rwco.ret != NOT_DONE) {
20050f86afdeSStefan Hajnoczi         replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
20064751d09aSSam Li                                          blk_aio_complete_bh, acb);
20074751d09aSSam Li     }
20084751d09aSSam Li 
20094751d09aSSam Li     return &acb->common;
20104751d09aSSam Li }
20114751d09aSSam Li 
20126d43eaa3SSam Li /*
20136d43eaa3SSam Li  * Send a zone_report command.
20146d43eaa3SSam Li  * offset is a byte offset from the start of the device. No alignment
20156d43eaa3SSam Li  * required for offset.
20166d43eaa3SSam Li  * nr_zones represents IN maximum and OUT actual.
20176d43eaa3SSam Li  */
blk_co_zone_report(BlockBackend * blk,int64_t offset,unsigned int * nr_zones,BlockZoneDescriptor * zones)20186d43eaa3SSam Li int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
20196d43eaa3SSam Li                                     unsigned int *nr_zones,
20206d43eaa3SSam Li                                     BlockZoneDescriptor *zones)
20216d43eaa3SSam Li {
20226d43eaa3SSam Li     int ret;
20236d43eaa3SSam Li     IO_CODE();
20246d43eaa3SSam Li 
20256d43eaa3SSam Li     blk_inc_in_flight(blk); /* increase before waiting */
20266d43eaa3SSam Li     blk_wait_while_drained(blk);
20276d43eaa3SSam Li     GRAPH_RDLOCK_GUARD();
20286d43eaa3SSam Li     if (!blk_is_available(blk)) {
20296d43eaa3SSam Li         blk_dec_in_flight(blk);
20306d43eaa3SSam Li         return -ENOMEDIUM;
20316d43eaa3SSam Li     }
20326d43eaa3SSam Li     ret = bdrv_co_zone_report(blk_bs(blk), offset, nr_zones, zones);
20336d43eaa3SSam Li     blk_dec_in_flight(blk);
20346d43eaa3SSam Li     return ret;
20356d43eaa3SSam Li }
20366d43eaa3SSam Li 
20376d43eaa3SSam Li /*
20386d43eaa3SSam Li  * Send a zone_management command.
20396d43eaa3SSam Li  * op is the zone operation;
20406d43eaa3SSam Li  * offset is the byte offset from the start of the zoned device;
20416d43eaa3SSam Li  * len is the maximum number of bytes the command should operate on. It
20426d43eaa3SSam Li  * should be aligned with the device zone size.
20436d43eaa3SSam Li  */
blk_co_zone_mgmt(BlockBackend * blk,BlockZoneOp op,int64_t offset,int64_t len)20446d43eaa3SSam Li int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
20456d43eaa3SSam Li         int64_t offset, int64_t len)
20466d43eaa3SSam Li {
20476d43eaa3SSam Li     int ret;
20486d43eaa3SSam Li     IO_CODE();
20496d43eaa3SSam Li 
20506d43eaa3SSam Li     blk_inc_in_flight(blk);
20516d43eaa3SSam Li     blk_wait_while_drained(blk);
20526d43eaa3SSam Li     GRAPH_RDLOCK_GUARD();
20536d43eaa3SSam Li 
20546d43eaa3SSam Li     ret = blk_check_byte_request(blk, offset, len);
20556d43eaa3SSam Li     if (ret < 0) {
20566d43eaa3SSam Li         blk_dec_in_flight(blk);
20576d43eaa3SSam Li         return ret;
20586d43eaa3SSam Li     }
20596d43eaa3SSam Li 
20606d43eaa3SSam Li     ret = bdrv_co_zone_mgmt(blk_bs(blk), op, offset, len);
20616d43eaa3SSam Li     blk_dec_in_flight(blk);
20626d43eaa3SSam Li     return ret;
20636d43eaa3SSam Li }
20646d43eaa3SSam Li 
20654751d09aSSam Li /*
20664751d09aSSam Li  * Send a zone_append command.
20674751d09aSSam Li  */
blk_co_zone_append(BlockBackend * blk,int64_t * offset,QEMUIOVector * qiov,BdrvRequestFlags flags)20684751d09aSSam Li int coroutine_fn blk_co_zone_append(BlockBackend *blk, int64_t *offset,
20694751d09aSSam Li         QEMUIOVector *qiov, BdrvRequestFlags flags)
20704751d09aSSam Li {
20714751d09aSSam Li     int ret;
20724751d09aSSam Li     IO_CODE();
20734751d09aSSam Li 
20744751d09aSSam Li     blk_inc_in_flight(blk);
20754751d09aSSam Li     blk_wait_while_drained(blk);
20764751d09aSSam Li     GRAPH_RDLOCK_GUARD();
20774751d09aSSam Li     if (!blk_is_available(blk)) {
20784751d09aSSam Li         blk_dec_in_flight(blk);
20794751d09aSSam Li         return -ENOMEDIUM;
20804751d09aSSam Li     }
20814751d09aSSam Li 
20824751d09aSSam Li     ret = bdrv_co_zone_append(blk_bs(blk), offset, qiov, flags);
20834751d09aSSam Li     blk_dec_in_flight(blk);
20844751d09aSSam Li     return ret;
20854751d09aSSam Li }
20864751d09aSSam Li 
blk_drain(BlockBackend * blk)208797b0385aSAlexander Yarygin void blk_drain(BlockBackend *blk)
208897b0385aSAlexander Yarygin {
208933f2a757SStefan Hajnoczi     BlockDriverState *bs = blk_bs(blk);
20900439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
209133f2a757SStefan Hajnoczi 
209233f2a757SStefan Hajnoczi     if (bs) {
20931e3552dbSStefan Hajnoczi         bdrv_ref(bs);
209433f2a757SStefan Hajnoczi         bdrv_drained_begin(bs);
209533f2a757SStefan Hajnoczi     }
209633f2a757SStefan Hajnoczi 
209733f2a757SStefan Hajnoczi     /* We may have -ENOMEDIUM completions in flight */
2098cfe29d82SKevin Wolf     AIO_WAIT_WHILE(blk_get_aio_context(blk),
20996a8a98a0SPaolo Bonzini                    qatomic_read(&blk->in_flight) > 0);
210033f2a757SStefan Hajnoczi 
210133f2a757SStefan Hajnoczi     if (bs) {
210233f2a757SStefan Hajnoczi         bdrv_drained_end(bs);
21031e3552dbSStefan Hajnoczi         bdrv_unref(bs);
210497b0385aSAlexander Yarygin     }
2105a46fc9c9SMax Reitz }
210697b0385aSAlexander Yarygin 
blk_drain_all(void)21074be74634SMarkus Armbruster void blk_drain_all(void)
21084be74634SMarkus Armbruster {
210933f2a757SStefan Hajnoczi     BlockBackend *blk = NULL;
211033f2a757SStefan Hajnoczi 
21110439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
21120439c5a4SEmanuele Giuseppe Esposito 
211333f2a757SStefan Hajnoczi     bdrv_drain_all_begin();
211433f2a757SStefan Hajnoczi 
211533f2a757SStefan Hajnoczi     while ((blk = blk_all_next(blk)) != NULL) {
211633f2a757SStefan Hajnoczi         /* We may have -ENOMEDIUM completions in flight */
2117d5eab432SStefan Hajnoczi         AIO_WAIT_WHILE_UNLOCKED(NULL, qatomic_read(&blk->in_flight) > 0);
211833f2a757SStefan Hajnoczi     }
211933f2a757SStefan Hajnoczi 
212033f2a757SStefan Hajnoczi     bdrv_drain_all_end();
21214be74634SMarkus Armbruster }
21224be74634SMarkus Armbruster 
blk_set_on_error(BlockBackend * blk,BlockdevOnError on_read_error,BlockdevOnError on_write_error)2123373340b2SMax Reitz void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
2124373340b2SMax Reitz                       BlockdevOnError on_write_error)
2125373340b2SMax Reitz {
21260439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2127373340b2SMax Reitz     blk->on_read_error = on_read_error;
2128373340b2SMax Reitz     blk->on_write_error = on_write_error;
2129373340b2SMax Reitz }
2130373340b2SMax Reitz 
blk_get_on_error(BlockBackend * blk,bool is_read)21314be74634SMarkus Armbruster BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
21324be74634SMarkus Armbruster {
213337868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2134373340b2SMax Reitz     return is_read ? blk->on_read_error : blk->on_write_error;
21354be74634SMarkus Armbruster }
21364be74634SMarkus Armbruster 
blk_get_error_action(BlockBackend * blk,bool is_read,int error)21374be74634SMarkus Armbruster BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
21384be74634SMarkus Armbruster                                       int error)
21394be74634SMarkus Armbruster {
2140373340b2SMax Reitz     BlockdevOnError on_err = blk_get_on_error(blk, is_read);
214137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2142373340b2SMax Reitz 
2143373340b2SMax Reitz     switch (on_err) {
2144373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_ENOSPC:
2145373340b2SMax Reitz         return (error == ENOSPC) ?
2146373340b2SMax Reitz                BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
2147373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_STOP:
2148373340b2SMax Reitz         return BLOCK_ERROR_ACTION_STOP;
2149373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_REPORT:
2150373340b2SMax Reitz         return BLOCK_ERROR_ACTION_REPORT;
2151373340b2SMax Reitz     case BLOCKDEV_ON_ERROR_IGNORE:
2152373340b2SMax Reitz         return BLOCK_ERROR_ACTION_IGNORE;
21538c398252SKevin Wolf     case BLOCKDEV_ON_ERROR_AUTO:
2154373340b2SMax Reitz     default:
2155373340b2SMax Reitz         abort();
2156373340b2SMax Reitz     }
21574be74634SMarkus Armbruster }
21584be74634SMarkus Armbruster 
send_qmp_error_event(BlockBackend * blk,BlockErrorAction action,bool is_read,int error)2159373340b2SMax Reitz static void send_qmp_error_event(BlockBackend *blk,
2160373340b2SMax Reitz                                  BlockErrorAction action,
2161373340b2SMax Reitz                                  bool is_read, int error)
2162373340b2SMax Reitz {
2163373340b2SMax Reitz     IoOperationType optype;
2164bfe1a14cSKevin Wolf     BlockDriverState *bs = blk_bs(blk);
2165373340b2SMax Reitz 
2166373340b2SMax Reitz     optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
216754fde4ffSMarkus Armbruster     qapi_event_send_block_io_error(blk_name(blk),
2168bfe1a14cSKevin Wolf                                    bs ? bdrv_get_node_name(bs) : NULL, optype,
21692bf7e10fSKevin Wolf                                    action, blk_iostatus_is_enabled(blk),
21703ab72385SPeter Xu                                    error == ENOSPC, strerror(error));
2171373340b2SMax Reitz }
2172373340b2SMax Reitz 
2173373340b2SMax Reitz /* This is done by device models because, while the block layer knows
2174373340b2SMax Reitz  * about the error, it does not know whether an operation comes from
2175373340b2SMax Reitz  * the device or the block layer (from a job, for example).
2176373340b2SMax Reitz  */
blk_error_action(BlockBackend * blk,BlockErrorAction action,bool is_read,int error)21774be74634SMarkus Armbruster void blk_error_action(BlockBackend *blk, BlockErrorAction action,
21784be74634SMarkus Armbruster                       bool is_read, int error)
21794be74634SMarkus Armbruster {
2180373340b2SMax Reitz     assert(error >= 0);
218137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2182373340b2SMax Reitz 
2183373340b2SMax Reitz     if (action == BLOCK_ERROR_ACTION_STOP) {
2184373340b2SMax Reitz         /* First set the iostatus, so that "info block" returns an iostatus
2185373340b2SMax Reitz          * that matches the events raised so far (an additional error iostatus
2186373340b2SMax Reitz          * is fine, but not a lost one).
2187373340b2SMax Reitz          */
2188373340b2SMax Reitz         blk_iostatus_set_err(blk, error);
2189373340b2SMax Reitz 
2190373340b2SMax Reitz         /* Then raise the request to stop the VM and the event.
2191373340b2SMax Reitz          * qemu_system_vmstop_request_prepare has two effects.  First,
2192373340b2SMax Reitz          * it ensures that the STOP event always comes after the
2193373340b2SMax Reitz          * BLOCK_IO_ERROR event.  Second, it ensures that even if management
2194373340b2SMax Reitz          * can observe the STOP event and do a "cont" before the STOP
2195373340b2SMax Reitz          * event is issued, the VM will not stop.  In this case, vm_start()
2196373340b2SMax Reitz          * also ensures that the STOP/RESUME pair of events is emitted.
2197373340b2SMax Reitz          */
2198373340b2SMax Reitz         qemu_system_vmstop_request_prepare();
2199373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
2200373340b2SMax Reitz         qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
2201373340b2SMax Reitz     } else {
2202373340b2SMax Reitz         send_qmp_error_event(blk, action, is_read, error);
2203373340b2SMax Reitz     }
22044be74634SMarkus Armbruster }
22054be74634SMarkus Armbruster 
220686b1cf32SKevin Wolf /*
220786b1cf32SKevin Wolf  * Returns true if the BlockBackend can support taking write permissions
220886b1cf32SKevin Wolf  * (because its root node is not read-only).
220986b1cf32SKevin Wolf  */
blk_supports_write_perm(BlockBackend * blk)221086b1cf32SKevin Wolf bool blk_supports_write_perm(BlockBackend *blk)
22114be74634SMarkus Armbruster {
2212f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
22130439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2214f21d96d0SKevin Wolf 
2215f21d96d0SKevin Wolf     if (bs) {
221686b1cf32SKevin Wolf         return !bdrv_is_read_only(bs);
2217061959e8SMax Reitz     } else {
2218260242a8SVladimir Sementsov-Ogievskiy         return blk->root_state.open_flags & BDRV_O_RDWR;
2219061959e8SMax Reitz     }
22204be74634SMarkus Armbruster }
22214be74634SMarkus Armbruster 
222286b1cf32SKevin Wolf /*
222386b1cf32SKevin Wolf  * Returns true if the BlockBackend can be written to in its current
222486b1cf32SKevin Wolf  * configuration (i.e. if write permission have been requested)
222586b1cf32SKevin Wolf  */
blk_is_writable(BlockBackend * blk)222686b1cf32SKevin Wolf bool blk_is_writable(BlockBackend *blk)
222786b1cf32SKevin Wolf {
222837868b2aSEmanuele Giuseppe Esposito     IO_CODE();
222986b1cf32SKevin Wolf     return blk->perm & BLK_PERM_WRITE;
223086b1cf32SKevin Wolf }
223186b1cf32SKevin Wolf 
blk_is_sg(BlockBackend * blk)223296710565SLi Qiang bool blk_is_sg(BlockBackend *blk)
22334be74634SMarkus Armbruster {
2234f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
22350439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2236f21d96d0SKevin Wolf 
2237f21d96d0SKevin Wolf     if (!bs) {
223896710565SLi Qiang         return false;
2239a46fc9c9SMax Reitz     }
2240a46fc9c9SMax Reitz 
2241f21d96d0SKevin Wolf     return bdrv_is_sg(bs);
22424be74634SMarkus Armbruster }
22434be74634SMarkus Armbruster 
blk_enable_write_cache(BlockBackend * blk)224496710565SLi Qiang bool blk_enable_write_cache(BlockBackend *blk)
22454be74634SMarkus Armbruster {
224637868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2247bfd18d1eSKevin Wolf     return blk->enable_write_cache;
22484be74634SMarkus Armbruster }
22494be74634SMarkus Armbruster 
blk_set_enable_write_cache(BlockBackend * blk,bool wce)22504be74634SMarkus Armbruster void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
22514be74634SMarkus Armbruster {
2252be8da05bSEmanuele Giuseppe Esposito     IO_CODE();
2253bfd18d1eSKevin Wolf     blk->enable_write_cache = wce;
22544be74634SMarkus Armbruster }
22554be74634SMarkus Armbruster 
blk_activate(BlockBackend * blk,Error ** errp)22563b717194SEmanuele Giuseppe Esposito void blk_activate(BlockBackend *blk, Error **errp)
22572bb0dce7SMax Reitz {
2258f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
22590439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2260f21d96d0SKevin Wolf 
2261f21d96d0SKevin Wolf     if (!bs) {
2262c09ba36cSMax Reitz         error_setg(errp, "Device '%s' has no medium", blk->name);
2263c09ba36cSMax Reitz         return;
2264c09ba36cSMax Reitz     }
2265c09ba36cSMax Reitz 
2266da4afaffSKevin Wolf     /*
2267da4afaffSKevin Wolf      * Migration code can call this function in coroutine context, so leave
2268da4afaffSKevin Wolf      * coroutine context if necessary.
2269da4afaffSKevin Wolf      */
2270da4afaffSKevin Wolf     if (qemu_in_coroutine()) {
2271da4afaffSKevin Wolf         bdrv_co_activate(bs, errp);
2272da4afaffSKevin Wolf     } else {
22732b3912f1SKevin Wolf         GRAPH_RDLOCK_GUARD_MAINLOOP();
2274a94750d9SEmanuele Giuseppe Esposito         bdrv_activate(bs, errp);
22752bb0dce7SMax Reitz     }
2276da4afaffSKevin Wolf }
22772bb0dce7SMax Reitz 
blk_co_is_inserted(BlockBackend * blk)22781e97be91SEmanuele Giuseppe Esposito bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
22794be74634SMarkus Armbruster {
2280f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
228137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2282c73ff92cSEmanuele Giuseppe Esposito     assert_bdrv_graph_readable();
2283f21d96d0SKevin Wolf 
22841e97be91SEmanuele Giuseppe Esposito     return bs && bdrv_co_is_inserted(bs);
2285db0284f8SMax Reitz }
2286db0284f8SMax Reitz 
blk_co_is_available(BlockBackend * blk)2287c73ff92cSEmanuele Giuseppe Esposito bool coroutine_fn blk_co_is_available(BlockBackend *blk)
2288db0284f8SMax Reitz {
228937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2290c73ff92cSEmanuele Giuseppe Esposito     return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk);
22914be74634SMarkus Armbruster }
22924be74634SMarkus Armbruster 
blk_co_lock_medium(BlockBackend * blk,bool locked)22932c75261cSEmanuele Giuseppe Esposito void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
22944be74634SMarkus Armbruster {
2295f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
229637868b2aSEmanuele Giuseppe Esposito     IO_CODE();
229779a292e5SKevin Wolf     GRAPH_RDLOCK_GUARD();
2298f21d96d0SKevin Wolf 
2299f21d96d0SKevin Wolf     if (bs) {
23002c75261cSEmanuele Giuseppe Esposito         bdrv_co_lock_medium(bs, locked);
23014be74634SMarkus Armbruster     }
2302a46fc9c9SMax Reitz }
23034be74634SMarkus Armbruster 
blk_co_eject(BlockBackend * blk,bool eject_flag)23042531b390SEmanuele Giuseppe Esposito void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
23054be74634SMarkus Armbruster {
2306f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
23072d76e724SKevin Wolf     char *id;
230837868b2aSEmanuele Giuseppe Esposito     IO_CODE();
230979a292e5SKevin Wolf     GRAPH_RDLOCK_GUARD();
23102d76e724SKevin Wolf 
2311f21d96d0SKevin Wolf     if (bs) {
23122531b390SEmanuele Giuseppe Esposito         bdrv_co_eject(bs, eject_flag);
2313c47ee043SJohn Snow     }
23142d76e724SKevin Wolf 
2315c47ee043SJohn Snow     /* Whether or not we ejected on the backend,
2316c47ee043SJohn Snow      * the frontend experienced a tray event. */
23172d76e724SKevin Wolf     id = blk_get_attached_dev_id(blk);
23182d76e724SKevin Wolf     qapi_event_send_device_tray_moved(blk_name(blk), id,
23193ab72385SPeter Xu                                       eject_flag);
23202d76e724SKevin Wolf     g_free(id);
2321a46fc9c9SMax Reitz }
23224be74634SMarkus Armbruster 
blk_get_flags(BlockBackend * blk)23234be74634SMarkus Armbruster int blk_get_flags(BlockBackend *blk)
23244be74634SMarkus Armbruster {
2325f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
23260439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2327f21d96d0SKevin Wolf 
2328f21d96d0SKevin Wolf     if (bs) {
2329f21d96d0SKevin Wolf         return bdrv_get_flags(bs);
2330061959e8SMax Reitz     } else {
2331061959e8SMax Reitz         return blk->root_state.open_flags;
2332061959e8SMax Reitz     }
23334be74634SMarkus Armbruster }
23344be74634SMarkus Armbruster 
23354841211eSEric Blake /* Returns the minimum request alignment, in bytes; guaranteed nonzero */
blk_get_request_alignment(BlockBackend * blk)23364841211eSEric Blake uint32_t blk_get_request_alignment(BlockBackend *blk)
23374841211eSEric Blake {
23384841211eSEric Blake     BlockDriverState *bs = blk_bs(blk);
233937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
23404841211eSEric Blake     return bs ? bs->bl.request_alignment : BDRV_SECTOR_SIZE;
23414841211eSEric Blake }
23424841211eSEric Blake 
234324b36e98SPaolo Bonzini /* Returns the maximum hardware transfer length, in bytes; guaranteed nonzero */
blk_get_max_hw_transfer(BlockBackend * blk)234424b36e98SPaolo Bonzini uint64_t blk_get_max_hw_transfer(BlockBackend *blk)
234524b36e98SPaolo Bonzini {
234624b36e98SPaolo Bonzini     BlockDriverState *bs = blk_bs(blk);
234724b36e98SPaolo Bonzini     uint64_t max = INT_MAX;
234837868b2aSEmanuele Giuseppe Esposito     IO_CODE();
234924b36e98SPaolo Bonzini 
235024b36e98SPaolo Bonzini     if (bs) {
235124b36e98SPaolo Bonzini         max = MIN_NON_ZERO(max, bs->bl.max_hw_transfer);
235224b36e98SPaolo Bonzini         max = MIN_NON_ZERO(max, bs->bl.max_transfer);
235324b36e98SPaolo Bonzini     }
235424b36e98SPaolo Bonzini     return ROUND_DOWN(max, blk_get_request_alignment(blk));
235524b36e98SPaolo Bonzini }
235624b36e98SPaolo Bonzini 
23575def6b80SEric Blake /* Returns the maximum transfer length, in bytes; guaranteed nonzero */
blk_get_max_transfer(BlockBackend * blk)23585def6b80SEric Blake uint32_t blk_get_max_transfer(BlockBackend *blk)
2359454057b7SPeter Lieven {
2360f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
2361b99f7fa0SPaolo Bonzini     uint32_t max = INT_MAX;
236237868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2363f21d96d0SKevin Wolf 
2364f21d96d0SKevin Wolf     if (bs) {
2365b99f7fa0SPaolo Bonzini         max = MIN_NON_ZERO(max, bs->bl.max_transfer);
2366a46fc9c9SMax Reitz     }
2367b99f7fa0SPaolo Bonzini     return ROUND_DOWN(max, blk_get_request_alignment(blk));
2368454057b7SPeter Lieven }
2369454057b7SPeter Lieven 
blk_get_max_hw_iov(BlockBackend * blk)2370cc071629SPaolo Bonzini int blk_get_max_hw_iov(BlockBackend *blk)
2371cc071629SPaolo Bonzini {
237237868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2373cc071629SPaolo Bonzini     return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
2374cc071629SPaolo Bonzini                         blk->root->bs->bl.max_iov);
2375cc071629SPaolo Bonzini }
2376cc071629SPaolo Bonzini 
blk_get_max_iov(BlockBackend * blk)2377648296e0SStefan Hajnoczi int blk_get_max_iov(BlockBackend *blk)
2378648296e0SStefan Hajnoczi {
237937868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2380f21d96d0SKevin Wolf     return blk->root->bs->bl.max_iov;
2381648296e0SStefan Hajnoczi }
2382648296e0SStefan Hajnoczi 
blk_try_blockalign(BlockBackend * blk,size_t size)2383f1c17521SPaolo Bonzini void *blk_try_blockalign(BlockBackend *blk, size_t size)
2384f1c17521SPaolo Bonzini {
238537868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2386f21d96d0SKevin Wolf     return qemu_try_blockalign(blk ? blk_bs(blk) : NULL, size);
2387f1c17521SPaolo Bonzini }
2388f1c17521SPaolo Bonzini 
blk_blockalign(BlockBackend * blk,size_t size)23894be74634SMarkus Armbruster void *blk_blockalign(BlockBackend *blk, size_t size)
23904be74634SMarkus Armbruster {
239137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2392f21d96d0SKevin Wolf     return qemu_blockalign(blk ? blk_bs(blk) : NULL, size);
23934be74634SMarkus Armbruster }
23944be74634SMarkus Armbruster 
blk_op_is_blocked(BlockBackend * blk,BlockOpType op,Error ** errp)23954be74634SMarkus Armbruster bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
23964be74634SMarkus Armbruster {
2397f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
23980439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2399277f2007SKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
2400f21d96d0SKevin Wolf 
2401f21d96d0SKevin Wolf     if (!bs) {
2402a46fc9c9SMax Reitz         return false;
2403a46fc9c9SMax Reitz     }
2404a46fc9c9SMax Reitz 
2405f21d96d0SKevin Wolf     return bdrv_op_is_blocked(bs, op, errp);
24064be74634SMarkus Armbruster }
24074be74634SMarkus Armbruster 
blk_op_unblock(BlockBackend * blk,BlockOpType op,Error * reason)24084be74634SMarkus Armbruster void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
24094be74634SMarkus Armbruster {
2410f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
24110439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2412f21d96d0SKevin Wolf 
2413f21d96d0SKevin Wolf     if (bs) {
2414f21d96d0SKevin Wolf         bdrv_op_unblock(bs, op, reason);
24154be74634SMarkus Armbruster     }
2416a46fc9c9SMax Reitz }
24174be74634SMarkus Armbruster 
blk_op_block_all(BlockBackend * blk,Error * reason)24184be74634SMarkus Armbruster void blk_op_block_all(BlockBackend *blk, Error *reason)
24194be74634SMarkus Armbruster {
2420f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
24210439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2422f21d96d0SKevin Wolf 
2423f21d96d0SKevin Wolf     if (bs) {
2424f21d96d0SKevin Wolf         bdrv_op_block_all(bs, reason);
24254be74634SMarkus Armbruster     }
2426a46fc9c9SMax Reitz }
24274be74634SMarkus Armbruster 
blk_op_unblock_all(BlockBackend * blk,Error * reason)24284be74634SMarkus Armbruster void blk_op_unblock_all(BlockBackend *blk, Error *reason)
24294be74634SMarkus Armbruster {
2430f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
24310439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2432f21d96d0SKevin Wolf 
2433f21d96d0SKevin Wolf     if (bs) {
2434f21d96d0SKevin Wolf         bdrv_op_unblock_all(bs, reason);
24354be74634SMarkus Armbruster     }
2436a46fc9c9SMax Reitz }
24374be74634SMarkus Armbruster 
blk_get_aio_context(BlockBackend * blk)24384be74634SMarkus Armbruster AioContext *blk_get_aio_context(BlockBackend *blk)
24394be74634SMarkus Armbruster {
2440dea97c1fSKevin Wolf     BlockDriverState *bs;
244137868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2442d861ab3aSKevin Wolf 
2443dea97c1fSKevin Wolf     if (!blk) {
2444dea97c1fSKevin Wolf         return qemu_get_aio_context();
2445dea97c1fSKevin Wolf     }
2446dea97c1fSKevin Wolf 
2447dea97c1fSKevin Wolf     bs = blk_bs(blk);
2448d861ab3aSKevin Wolf     if (bs) {
2449132ada80SKevin Wolf         AioContext *ctx = bdrv_get_aio_context(blk_bs(blk));
2450132ada80SKevin Wolf         assert(ctx == blk->ctx);
24514981bdecSMax Reitz     }
24524981bdecSMax Reitz 
2453d861ab3aSKevin Wolf     return blk->ctx;
2454d861ab3aSKevin Wolf }
2455d861ab3aSKevin Wolf 
blk_set_aio_context(BlockBackend * blk,AioContext * new_context,Error ** errp)245697896a48SKevin Wolf int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
245797896a48SKevin Wolf                         Error **errp)
245838475269SKevin Wolf {
24592d196295SStefan Hajnoczi     bool old_allow_change;
24602d196295SStefan Hajnoczi     BlockDriverState *bs = blk_bs(blk);
24612d196295SStefan Hajnoczi     int ret;
24622d196295SStefan Hajnoczi 
24630439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
24642d196295SStefan Hajnoczi 
24652d196295SStefan Hajnoczi     if (!bs) {
24662d196295SStefan Hajnoczi         blk->ctx = new_context;
24672d196295SStefan Hajnoczi         return 0;
24682d196295SStefan Hajnoczi     }
24692d196295SStefan Hajnoczi 
24702d196295SStefan Hajnoczi     bdrv_ref(bs);
24712d196295SStefan Hajnoczi 
24722d196295SStefan Hajnoczi     old_allow_change = blk->allow_aio_context_change;
24732d196295SStefan Hajnoczi     blk->allow_aio_context_change = true;
24742d196295SStefan Hajnoczi 
24752d196295SStefan Hajnoczi     ret = bdrv_try_change_aio_context(bs, new_context, NULL, errp);
24762d196295SStefan Hajnoczi 
24772d196295SStefan Hajnoczi     blk->allow_aio_context_change = old_allow_change;
24782d196295SStefan Hajnoczi 
24792d196295SStefan Hajnoczi     bdrv_unref(bs);
24802d196295SStefan Hajnoczi     return ret;
248138475269SKevin Wolf }
248238475269SKevin Wolf 
248333949396SEmanuele Giuseppe Esposito typedef struct BdrvStateBlkRootContext {
248433949396SEmanuele Giuseppe Esposito     AioContext *new_ctx;
248533949396SEmanuele Giuseppe Esposito     BlockBackend *blk;
248633949396SEmanuele Giuseppe Esposito } BdrvStateBlkRootContext;
248738475269SKevin Wolf 
blk_root_set_aio_ctx_commit(void * opaque)248833949396SEmanuele Giuseppe Esposito static void blk_root_set_aio_ctx_commit(void *opaque)
248933949396SEmanuele Giuseppe Esposito {
249033949396SEmanuele Giuseppe Esposito     BdrvStateBlkRootContext *s = opaque;
249133949396SEmanuele Giuseppe Esposito     BlockBackend *blk = s->blk;
24922d196295SStefan Hajnoczi     AioContext *new_context = s->new_ctx;
24932d196295SStefan Hajnoczi     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
249433949396SEmanuele Giuseppe Esposito 
24952d196295SStefan Hajnoczi     blk->ctx = new_context;
24962d196295SStefan Hajnoczi     if (tgm->throttle_state) {
24972d196295SStefan Hajnoczi         throttle_group_detach_aio_context(tgm);
24982d196295SStefan Hajnoczi         throttle_group_attach_aio_context(tgm, new_context);
24992d196295SStefan Hajnoczi     }
2500980b0f94SKevin Wolf }
2501980b0f94SKevin Wolf 
250233949396SEmanuele Giuseppe Esposito static TransactionActionDrv set_blk_root_context = {
250333949396SEmanuele Giuseppe Esposito     .commit = blk_root_set_aio_ctx_commit,
250433949396SEmanuele Giuseppe Esposito     .clean = g_free,
250533949396SEmanuele Giuseppe Esposito };
250633949396SEmanuele Giuseppe Esposito 
blk_root_change_aio_ctx(BdrvChild * child,AioContext * ctx,GHashTable * visited,Transaction * tran,Error ** errp)250733949396SEmanuele Giuseppe Esposito static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
250833949396SEmanuele Giuseppe Esposito                                     GHashTable *visited, Transaction *tran,
250933949396SEmanuele Giuseppe Esposito                                     Error **errp)
251033949396SEmanuele Giuseppe Esposito {
251133949396SEmanuele Giuseppe Esposito     BlockBackend *blk = child->opaque;
251233949396SEmanuele Giuseppe Esposito     BdrvStateBlkRootContext *s;
251333949396SEmanuele Giuseppe Esposito 
251433949396SEmanuele Giuseppe Esposito     if (!blk->allow_aio_context_change) {
251533949396SEmanuele Giuseppe Esposito         /*
251633949396SEmanuele Giuseppe Esposito          * Manually created BlockBackends (those with a name) that are not
251733949396SEmanuele Giuseppe Esposito          * attached to anything can change their AioContext without updating
251833949396SEmanuele Giuseppe Esposito          * their user; return an error for others.
251933949396SEmanuele Giuseppe Esposito          */
252038475269SKevin Wolf         if (!blk->name || blk->dev) {
252138475269SKevin Wolf             /* TODO Add BB name/QOM path */
252238475269SKevin Wolf             error_setg(errp, "Cannot change iothread of active block backend");
252338475269SKevin Wolf             return false;
252438475269SKevin Wolf         }
252538475269SKevin Wolf     }
252638475269SKevin Wolf 
252733949396SEmanuele Giuseppe Esposito     s = g_new(BdrvStateBlkRootContext, 1);
252833949396SEmanuele Giuseppe Esposito     *s = (BdrvStateBlkRootContext) {
252933949396SEmanuele Giuseppe Esposito         .new_ctx = ctx,
253033949396SEmanuele Giuseppe Esposito         .blk = blk,
253133949396SEmanuele Giuseppe Esposito     };
253233949396SEmanuele Giuseppe Esposito 
253333949396SEmanuele Giuseppe Esposito     tran_add(tran, &set_blk_root_context, s);
253433949396SEmanuele Giuseppe Esposito     return true;
253538475269SKevin Wolf }
25364be74634SMarkus Armbruster 
blk_add_aio_context_notifier(BlockBackend * blk,void (* attached_aio_context)(AioContext * new_context,void * opaque),void (* detach_aio_context)(void * opaque),void * opaque)25372019ba0aSMax Reitz void blk_add_aio_context_notifier(BlockBackend *blk,
25382019ba0aSMax Reitz         void (*attached_aio_context)(AioContext *new_context, void *opaque),
25392019ba0aSMax Reitz         void (*detach_aio_context)(void *opaque), void *opaque)
25402019ba0aSMax Reitz {
2541d03654eaSStefan Hajnoczi     BlockBackendAioNotifier *notifier;
2542f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
25430439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2544f21d96d0SKevin Wolf 
2545d03654eaSStefan Hajnoczi     notifier = g_new(BlockBackendAioNotifier, 1);
2546d03654eaSStefan Hajnoczi     notifier->attached_aio_context = attached_aio_context;
2547d03654eaSStefan Hajnoczi     notifier->detach_aio_context = detach_aio_context;
2548d03654eaSStefan Hajnoczi     notifier->opaque = opaque;
2549d03654eaSStefan Hajnoczi     QLIST_INSERT_HEAD(&blk->aio_notifiers, notifier, list);
2550d03654eaSStefan Hajnoczi 
2551f21d96d0SKevin Wolf     if (bs) {
2552f21d96d0SKevin Wolf         bdrv_add_aio_context_notifier(bs, attached_aio_context,
25532019ba0aSMax Reitz                                       detach_aio_context, opaque);
25542019ba0aSMax Reitz     }
2555a46fc9c9SMax Reitz }
25562019ba0aSMax Reitz 
blk_remove_aio_context_notifier(BlockBackend * blk,void (* attached_aio_context)(AioContext *,void *),void (* detach_aio_context)(void *),void * opaque)25572019ba0aSMax Reitz void blk_remove_aio_context_notifier(BlockBackend *blk,
25582019ba0aSMax Reitz                                      void (*attached_aio_context)(AioContext *,
25592019ba0aSMax Reitz                                                                   void *),
25602019ba0aSMax Reitz                                      void (*detach_aio_context)(void *),
25612019ba0aSMax Reitz                                      void *opaque)
25622019ba0aSMax Reitz {
2563d03654eaSStefan Hajnoczi     BlockBackendAioNotifier *notifier;
2564f21d96d0SKevin Wolf     BlockDriverState *bs = blk_bs(blk);
2565f21d96d0SKevin Wolf 
25660439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
25670439c5a4SEmanuele Giuseppe Esposito 
2568f21d96d0SKevin Wolf     if (bs) {
2569f21d96d0SKevin Wolf         bdrv_remove_aio_context_notifier(bs, attached_aio_context,
25702019ba0aSMax Reitz                                          detach_aio_context, opaque);
25712019ba0aSMax Reitz     }
2572d03654eaSStefan Hajnoczi 
2573d03654eaSStefan Hajnoczi     QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
2574d03654eaSStefan Hajnoczi         if (notifier->attached_aio_context == attached_aio_context &&
2575d03654eaSStefan Hajnoczi             notifier->detach_aio_context == detach_aio_context &&
2576d03654eaSStefan Hajnoczi             notifier->opaque == opaque) {
2577d03654eaSStefan Hajnoczi             QLIST_REMOVE(notifier, list);
2578d03654eaSStefan Hajnoczi             g_free(notifier);
2579d03654eaSStefan Hajnoczi             return;
2580d03654eaSStefan Hajnoczi         }
2581d03654eaSStefan Hajnoczi     }
2582d03654eaSStefan Hajnoczi 
2583d03654eaSStefan Hajnoczi     abort();
2584a46fc9c9SMax Reitz }
25852019ba0aSMax Reitz 
blk_add_remove_bs_notifier(BlockBackend * blk,Notifier * notify)25863301f6c6SMax Reitz void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
25873301f6c6SMax Reitz {
25880439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
25893301f6c6SMax Reitz     notifier_list_add(&blk->remove_bs_notifiers, notify);
25903301f6c6SMax Reitz }
25913301f6c6SMax Reitz 
blk_add_insert_bs_notifier(BlockBackend * blk,Notifier * notify)25923301f6c6SMax Reitz void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
25933301f6c6SMax Reitz {
25940439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
25953301f6c6SMax Reitz     notifier_list_add(&blk->insert_bs_notifiers, notify);
25963301f6c6SMax Reitz }
25973301f6c6SMax Reitz 
blk_get_stats(BlockBackend * blk)25984be74634SMarkus Armbruster BlockAcctStats *blk_get_stats(BlockBackend *blk)
25994be74634SMarkus Armbruster {
260037868b2aSEmanuele Giuseppe Esposito     IO_CODE();
26017f0e9da6SMax Reitz     return &blk->stats;
26024be74634SMarkus Armbruster }
26034be74634SMarkus Armbruster 
blk_aio_get(const AIOCBInfo * aiocb_info,BlockBackend * blk,BlockCompletionFunc * cb,void * opaque)26044be74634SMarkus Armbruster void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
26054be74634SMarkus Armbruster                   BlockCompletionFunc *cb, void *opaque)
26064be74634SMarkus Armbruster {
260737868b2aSEmanuele Giuseppe Esposito     IO_CODE();
26084be74634SMarkus Armbruster     return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
26094be74634SMarkus Armbruster }
26101ef01253SMax Reitz 
blk_co_pwrite_zeroes(BlockBackend * blk,int64_t offset,int64_t bytes,BdrvRequestFlags flags)2611d004bd52SEric Blake int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
261234460febSVladimir Sementsov-Ogievskiy                                       int64_t bytes, BdrvRequestFlags flags)
26131ef01253SMax Reitz {
261437868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
2615f5a5ca79SManos Pitsidianakis     return blk_co_pwritev(blk, offset, bytes, NULL,
261616aaf975SKevin Wolf                           flags | BDRV_REQ_ZERO_WRITE);
26171ef01253SMax Reitz }
26181ef01253SMax Reitz 
blk_co_pwrite_compressed(BlockBackend * blk,int64_t offset,int64_t bytes,const void * buf)26192c9715faSAlberto Faria int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
26202c9715faSAlberto Faria                                           int64_t bytes, const void *buf)
26211ef01253SMax Reitz {
262206f0325cSVladimir Sementsov-Ogievskiy     QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
262337868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
26242c9715faSAlberto Faria     return blk_co_pwritev_part(blk, offset, bytes, &qiov, 0,
262535fadca8SPavel Butsykin                                BDRV_REQ_WRITE_COMPRESSED);
26261ef01253SMax Reitz }
26271ef01253SMax Reitz 
blk_co_truncate(BlockBackend * blk,int64_t offset,bool exact,PreallocMode prealloc,BdrvRequestFlags flags,Error ** errp)2628015ed252SAlberto Faria int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
2629015ed252SAlberto Faria                                  PreallocMode prealloc, BdrvRequestFlags flags,
2630015ed252SAlberto Faria                                  Error **errp)
26311ef01253SMax Reitz {
263237868b2aSEmanuele Giuseppe Esposito     IO_OR_GS_CODE();
2633c2b8e315SKevin Wolf     GRAPH_RDLOCK_GUARD();
2634c73ff92cSEmanuele Giuseppe Esposito     if (!blk_co_is_available(blk)) {
2635ed3d2ec9SMax Reitz         error_setg(errp, "No medium inserted");
2636c09ba36cSMax Reitz         return -ENOMEDIUM;
2637c09ba36cSMax Reitz     }
2638c09ba36cSMax Reitz 
2639015ed252SAlberto Faria     return bdrv_co_truncate(blk->root, offset, exact, prealloc, flags, errp);
26401ef01253SMax Reitz }
26411ef01253SMax Reitz 
blk_save_vmstate(BlockBackend * blk,const uint8_t * buf,int64_t pos,int size)26421ef01253SMax Reitz int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
26431ef01253SMax Reitz                      int64_t pos, int size)
26441ef01253SMax Reitz {
2645bfd18d1eSKevin Wolf     int ret;
26460439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2647bfd18d1eSKevin Wolf 
2648c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
2649c09ba36cSMax Reitz         return -ENOMEDIUM;
2650c09ba36cSMax Reitz     }
2651c09ba36cSMax Reitz 
2652bfd18d1eSKevin Wolf     ret = bdrv_save_vmstate(blk_bs(blk), buf, pos, size);
2653bfd18d1eSKevin Wolf     if (ret < 0) {
2654bfd18d1eSKevin Wolf         return ret;
2655bfd18d1eSKevin Wolf     }
2656bfd18d1eSKevin Wolf 
2657bfd18d1eSKevin Wolf     if (ret == size && !blk->enable_write_cache) {
2658bfd18d1eSKevin Wolf         ret = bdrv_flush(blk_bs(blk));
2659bfd18d1eSKevin Wolf     }
2660bfd18d1eSKevin Wolf 
2661bfd18d1eSKevin Wolf     return ret < 0 ? ret : size;
26621ef01253SMax Reitz }
26631ef01253SMax Reitz 
blk_load_vmstate(BlockBackend * blk,uint8_t * buf,int64_t pos,int size)26641ef01253SMax Reitz int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
26651ef01253SMax Reitz {
26660439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2667c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
2668c09ba36cSMax Reitz         return -ENOMEDIUM;
2669c09ba36cSMax Reitz     }
2670c09ba36cSMax Reitz 
2671f21d96d0SKevin Wolf     return bdrv_load_vmstate(blk_bs(blk), buf, pos, size);
26721ef01253SMax Reitz }
2673f0272c4dSEkaterina Tumanova 
blk_probe_blocksizes(BlockBackend * blk,BlockSizes * bsz)2674f0272c4dSEkaterina Tumanova int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz)
2675f0272c4dSEkaterina Tumanova {
26760439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2677221caadcSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
2678221caadcSKevin Wolf 
2679c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
2680c09ba36cSMax Reitz         return -ENOMEDIUM;
2681c09ba36cSMax Reitz     }
2682c09ba36cSMax Reitz 
2683f21d96d0SKevin Wolf     return bdrv_probe_blocksizes(blk_bs(blk), bsz);
2684f0272c4dSEkaterina Tumanova }
2685f0272c4dSEkaterina Tumanova 
blk_probe_geometry(BlockBackend * blk,HDGeometry * geo)2686f0272c4dSEkaterina Tumanova int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo)
2687f0272c4dSEkaterina Tumanova {
26880439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2689c09ba36cSMax Reitz     if (!blk_is_available(blk)) {
2690c09ba36cSMax Reitz         return -ENOMEDIUM;
2691c09ba36cSMax Reitz     }
2692c09ba36cSMax Reitz 
2693f21d96d0SKevin Wolf     return bdrv_probe_geometry(blk_bs(blk), geo);
2694f0272c4dSEkaterina Tumanova }
2695281d22d8SMax Reitz 
2696281d22d8SMax Reitz /*
2697281d22d8SMax Reitz  * Updates the BlockBackendRootState object with data from the currently
2698281d22d8SMax Reitz  * attached BlockDriverState.
2699281d22d8SMax Reitz  */
blk_update_root_state(BlockBackend * blk)2700281d22d8SMax Reitz void blk_update_root_state(BlockBackend *blk)
2701281d22d8SMax Reitz {
27020439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2703f21d96d0SKevin Wolf     assert(blk->root);
2704281d22d8SMax Reitz 
2705f21d96d0SKevin Wolf     blk->root_state.open_flags    = blk->root->bs->open_flags;
2706f21d96d0SKevin Wolf     blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
2707281d22d8SMax Reitz }
2708281d22d8SMax Reitz 
270938cb18f5SMax Reitz /*
2710b85114f8SKevin Wolf  * Returns the detect-zeroes setting to be used for bdrv_open() of a
2711b85114f8SKevin Wolf  * BlockDriverState which is supposed to inherit the root state.
271238cb18f5SMax Reitz  */
blk_get_detect_zeroes_from_root_state(BlockBackend * blk)2713b85114f8SKevin Wolf bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk)
271438cb18f5SMax Reitz {
27150439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2716b85114f8SKevin Wolf     return blk->root_state.detect_zeroes;
271738cb18f5SMax Reitz }
271838cb18f5SMax Reitz 
271938cb18f5SMax Reitz /*
272038cb18f5SMax Reitz  * Returns the flags to be used for bdrv_open() of a BlockDriverState which is
272138cb18f5SMax Reitz  * supposed to inherit the root state.
272238cb18f5SMax Reitz  */
blk_get_open_flags_from_root_state(BlockBackend * blk)272338cb18f5SMax Reitz int blk_get_open_flags_from_root_state(BlockBackend *blk)
272438cb18f5SMax Reitz {
27250439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2726260242a8SVladimir Sementsov-Ogievskiy     return blk->root_state.open_flags;
272738cb18f5SMax Reitz }
272838cb18f5SMax Reitz 
blk_get_root_state(BlockBackend * blk)2729281d22d8SMax Reitz BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
2730281d22d8SMax Reitz {
27310439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2732281d22d8SMax Reitz     return &blk->root_state;
2733281d22d8SMax Reitz }
27341393f212SMax Reitz 
blk_commit_all(void)27351393f212SMax Reitz int blk_commit_all(void)
27361393f212SMax Reitz {
2737fe1a9cbcSMax Reitz     BlockBackend *blk = NULL;
27380439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2739ad74751fSKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
2740fe1a9cbcSMax Reitz 
2741fe1a9cbcSMax Reitz     while ((blk = blk_all_next(blk)) != NULL) {
2742fe1a9cbcSMax Reitz         AioContext *aio_context = blk_get_aio_context(blk);
27439a71b9deSMax Reitz         BlockDriverState *unfiltered_bs = bdrv_skip_filters(blk_bs(blk));
2744fe1a9cbcSMax Reitz 
2745fe1a9cbcSMax Reitz         aio_context_acquire(aio_context);
27469a71b9deSMax Reitz         if (blk_is_inserted(blk) && bdrv_cow_child(unfiltered_bs)) {
27479a71b9deSMax Reitz             int ret;
27489a71b9deSMax Reitz 
27499a71b9deSMax Reitz             ret = bdrv_commit(unfiltered_bs);
2750fe1a9cbcSMax Reitz             if (ret < 0) {
2751fe1a9cbcSMax Reitz                 aio_context_release(aio_context);
2752fe1a9cbcSMax Reitz                 return ret;
2753fe1a9cbcSMax Reitz             }
2754fe1a9cbcSMax Reitz         }
2755fe1a9cbcSMax Reitz         aio_context_release(aio_context);
2756fe1a9cbcSMax Reitz     }
2757fe1a9cbcSMax Reitz     return 0;
2758fe1a9cbcSMax Reitz }
2759fe1a9cbcSMax Reitz 
276097148076SKevin Wolf 
276197148076SKevin Wolf /* throttling disk I/O limits */
blk_set_io_limits(BlockBackend * blk,ThrottleConfig * cfg)276297148076SKevin Wolf void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
276397148076SKevin Wolf {
27640439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2765022cdc9fSManos Pitsidianakis     throttle_group_config(&blk->public.throttle_group_member, cfg);
276697148076SKevin Wolf }
276797148076SKevin Wolf 
blk_io_limits_disable(BlockBackend * blk)276897148076SKevin Wolf void blk_io_limits_disable(BlockBackend *blk)
276997148076SKevin Wolf {
277048bf7ea8SAlberto Garcia     BlockDriverState *bs = blk_bs(blk);
277148bf7ea8SAlberto Garcia     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
277248bf7ea8SAlberto Garcia     assert(tgm->throttle_state);
27730439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
277448bf7ea8SAlberto Garcia     if (bs) {
27751e3552dbSStefan Hajnoczi         bdrv_ref(bs);
277648bf7ea8SAlberto Garcia         bdrv_drained_begin(bs);
277748bf7ea8SAlberto Garcia     }
277848bf7ea8SAlberto Garcia     throttle_group_unregister_tgm(tgm);
277948bf7ea8SAlberto Garcia     if (bs) {
278048bf7ea8SAlberto Garcia         bdrv_drained_end(bs);
27811e3552dbSStefan Hajnoczi         bdrv_unref(bs);
278248bf7ea8SAlberto Garcia     }
278397148076SKevin Wolf }
278497148076SKevin Wolf 
278597148076SKevin Wolf /* should be called before blk_set_io_limits if a limit is set */
blk_io_limits_enable(BlockBackend * blk,const char * group)278697148076SKevin Wolf void blk_io_limits_enable(BlockBackend *blk, const char *group)
278797148076SKevin Wolf {
2788022cdc9fSManos Pitsidianakis     assert(!blk->public.throttle_group_member.throttle_state);
27890439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
2790c61791fcSManos Pitsidianakis     throttle_group_register_tgm(&blk->public.throttle_group_member,
2791c61791fcSManos Pitsidianakis                                 group, blk_get_aio_context(blk));
279297148076SKevin Wolf }
279397148076SKevin Wolf 
blk_io_limits_update_group(BlockBackend * blk,const char * group)279497148076SKevin Wolf void blk_io_limits_update_group(BlockBackend *blk, const char *group)
279597148076SKevin Wolf {
27960439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
279797148076SKevin Wolf     /* this BB is not part of any group */
2798022cdc9fSManos Pitsidianakis     if (!blk->public.throttle_group_member.throttle_state) {
279997148076SKevin Wolf         return;
280097148076SKevin Wolf     }
280197148076SKevin Wolf 
280297148076SKevin Wolf     /* this BB is a part of the same group than the one we want */
2803022cdc9fSManos Pitsidianakis     if (!g_strcmp0(throttle_group_get_name(&blk->public.throttle_group_member),
2804022cdc9fSManos Pitsidianakis                 group)) {
280597148076SKevin Wolf         return;
280697148076SKevin Wolf     }
280797148076SKevin Wolf 
280897148076SKevin Wolf     /* need to change the group this bs belong to */
280997148076SKevin Wolf     blk_io_limits_disable(blk);
281097148076SKevin Wolf     blk_io_limits_enable(blk, group);
281197148076SKevin Wolf }
2812c2066af0SKevin Wolf 
blk_root_drained_begin(BdrvChild * child)2813c2066af0SKevin Wolf static void blk_root_drained_begin(BdrvChild *child)
2814c2066af0SKevin Wolf {
2815c2066af0SKevin Wolf     BlockBackend *blk = child->opaque;
2816d73415a3SStefan Hajnoczi     ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
2817c2066af0SKevin Wolf 
2818c4d5bf99SStefan Hajnoczi     if (qatomic_fetch_inc(&blk->quiesce_counter) == 0) {
2819f4d9cc88SJohn Snow         if (blk->dev_ops && blk->dev_ops->drained_begin) {
2820f4d9cc88SJohn Snow             blk->dev_ops->drained_begin(blk->dev_opaque);
2821f4d9cc88SJohn Snow         }
2822f4d9cc88SJohn Snow     }
2823f4d9cc88SJohn Snow 
282436fe1331SKevin Wolf     /* Note that blk->root may not be accessible here yet if we are just
282536fe1331SKevin Wolf      * attaching to a BlockDriverState that is drained. Use child instead. */
282636fe1331SKevin Wolf 
2827d73415a3SStefan Hajnoczi     if (qatomic_fetch_inc(&tgm->io_limits_disabled) == 0) {
2828d73415a3SStefan Hajnoczi         throttle_group_restart_tgm(tgm);
2829c2066af0SKevin Wolf     }
2830c2066af0SKevin Wolf }
2831c2066af0SKevin Wolf 
blk_root_drained_poll(BdrvChild * child)2832fe5258a5SKevin Wolf static bool blk_root_drained_poll(BdrvChild *child)
2833fe5258a5SKevin Wolf {
2834fe5258a5SKevin Wolf     BlockBackend *blk = child->opaque;
2835095cc4d0SSergio Lopez     bool busy = false;
2836c4d5bf99SStefan Hajnoczi     assert(qatomic_read(&blk->quiesce_counter));
2837095cc4d0SSergio Lopez 
2838095cc4d0SSergio Lopez     if (blk->dev_ops && blk->dev_ops->drained_poll) {
2839095cc4d0SSergio Lopez         busy = blk->dev_ops->drained_poll(blk->dev_opaque);
2840095cc4d0SSergio Lopez     }
2841095cc4d0SSergio Lopez     return busy || !!blk->in_flight;
2842fe5258a5SKevin Wolf }
2843fe5258a5SKevin Wolf 
blk_root_drained_end(BdrvChild * child)28442f65df6eSKevin Wolf static void blk_root_drained_end(BdrvChild *child)
2845c2066af0SKevin Wolf {
2846c2066af0SKevin Wolf     BlockBackend *blk = child->opaque;
2847c4d5bf99SStefan Hajnoczi     assert(qatomic_read(&blk->quiesce_counter));
2848c2066af0SKevin Wolf 
2849022cdc9fSManos Pitsidianakis     assert(blk->public.throttle_group_member.io_limits_disabled);
2850d73415a3SStefan Hajnoczi     qatomic_dec(&blk->public.throttle_group_member.io_limits_disabled);
2851f4d9cc88SJohn Snow 
2852c4d5bf99SStefan Hajnoczi     if (qatomic_fetch_dec(&blk->quiesce_counter) == 1) {
2853f4d9cc88SJohn Snow         if (blk->dev_ops && blk->dev_ops->drained_end) {
2854f4d9cc88SJohn Snow             blk->dev_ops->drained_end(blk->dev_opaque);
2855f4d9cc88SJohn Snow         }
2856407ae2aeSStefan Hajnoczi         qemu_mutex_lock(&blk->queued_requests_lock);
2857407ae2aeSStefan Hajnoczi         while (qemu_co_enter_next(&blk->queued_requests,
2858407ae2aeSStefan Hajnoczi                                   &blk->queued_requests_lock)) {
2859cf312932SKevin Wolf             /* Resume all queued requests */
2860cf312932SKevin Wolf         }
2861407ae2aeSStefan Hajnoczi         qemu_mutex_unlock(&blk->queued_requests_lock);
2862f4d9cc88SJohn Snow     }
2863c2066af0SKevin Wolf }
286423d0ba93SFam Zheng 
blk_register_buf(BlockBackend * blk,void * host,size_t size,Error ** errp)2865f4ec04baSStefan Hajnoczi bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp)
286623d0ba93SFam Zheng {
286771038951SStefan Hajnoczi     BlockDriverState *bs = blk_bs(blk);
286871038951SStefan Hajnoczi 
28690439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
287071038951SStefan Hajnoczi 
287171038951SStefan Hajnoczi     if (bs) {
287271038951SStefan Hajnoczi         return bdrv_register_buf(bs, host, size, errp);
287371038951SStefan Hajnoczi     }
287471038951SStefan Hajnoczi     return true;
287523d0ba93SFam Zheng }
287623d0ba93SFam Zheng 
blk_unregister_buf(BlockBackend * blk,void * host,size_t size)28774f384011SStefan Hajnoczi void blk_unregister_buf(BlockBackend *blk, void *host, size_t size)
287823d0ba93SFam Zheng {
287971038951SStefan Hajnoczi     BlockDriverState *bs = blk_bs(blk);
288071038951SStefan Hajnoczi 
28810439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
288271038951SStefan Hajnoczi 
288371038951SStefan Hajnoczi     if (bs) {
288471038951SStefan Hajnoczi         bdrv_unregister_buf(bs, host, size);
288571038951SStefan Hajnoczi     }
288623d0ba93SFam Zheng }
2887b5679fa4SFam Zheng 
blk_co_copy_range(BlockBackend * blk_in,int64_t off_in,BlockBackend * blk_out,int64_t off_out,int64_t bytes,BdrvRequestFlags read_flags,BdrvRequestFlags write_flags)2888b5679fa4SFam Zheng int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
2889b5679fa4SFam Zheng                                    BlockBackend *blk_out, int64_t off_out,
2890e192179bSVladimir Sementsov-Ogievskiy                                    int64_t bytes, BdrvRequestFlags read_flags,
289167b51fb9SVladimir Sementsov-Ogievskiy                                    BdrvRequestFlags write_flags)
2892b5679fa4SFam Zheng {
2893b5679fa4SFam Zheng     int r;
289437868b2aSEmanuele Giuseppe Esposito     IO_CODE();
2895c73ff92cSEmanuele Giuseppe Esposito     GRAPH_RDLOCK_GUARD();
289637868b2aSEmanuele Giuseppe Esposito 
2897b5679fa4SFam Zheng     r = blk_check_byte_request(blk_in, off_in, bytes);
2898b5679fa4SFam Zheng     if (r) {
2899b5679fa4SFam Zheng         return r;
2900b5679fa4SFam Zheng     }
2901b5679fa4SFam Zheng     r = blk_check_byte_request(blk_out, off_out, bytes);
2902b5679fa4SFam Zheng     if (r) {
2903b5679fa4SFam Zheng         return r;
2904b5679fa4SFam Zheng     }
2905742bf09bSEmanuele Giuseppe Esposito 
2906b5679fa4SFam Zheng     return bdrv_co_copy_range(blk_in->root, off_in,
2907b5679fa4SFam Zheng                               blk_out->root, off_out,
290867b51fb9SVladimir Sementsov-Ogievskiy                               bytes, read_flags, write_flags);
2909b5679fa4SFam Zheng }
29105d3b4e99SVladimir Sementsov-Ogievskiy 
blk_root(BlockBackend * blk)29115d3b4e99SVladimir Sementsov-Ogievskiy const BdrvChild *blk_root(BlockBackend *blk)
29125d3b4e99SVladimir Sementsov-Ogievskiy {
29130439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
29145d3b4e99SVladimir Sementsov-Ogievskiy     return blk->root;
29155d3b4e99SVladimir Sementsov-Ogievskiy }
29162b7bbdbdSMax Reitz 
blk_make_empty(BlockBackend * blk,Error ** errp)29172b7bbdbdSMax Reitz int blk_make_empty(BlockBackend *blk, Error **errp)
29182b7bbdbdSMax Reitz {
29190439c5a4SEmanuele Giuseppe Esposito     GLOBAL_STATE_CODE();
29200bb79c97SKevin Wolf     GRAPH_RDLOCK_GUARD_MAINLOOP();
29210bb79c97SKevin Wolf 
29222b7bbdbdSMax Reitz     if (!blk_is_available(blk)) {
29232b7bbdbdSMax Reitz         error_setg(errp, "No medium inserted");
29242b7bbdbdSMax Reitz         return -ENOMEDIUM;
29252b7bbdbdSMax Reitz     }
29262b7bbdbdSMax Reitz 
29272b7bbdbdSMax Reitz     return bdrv_make_empty(blk->root, errp);
29282b7bbdbdSMax Reitz }
2929