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