block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
/*
|
|
|
|
* QEMU Block backends
|
|
|
|
*
|
2016-05-06 19:26:30 +03:00
|
|
|
* Copyright (C) 2014-2016 Red Hat, Inc.
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Markus Armbruster <armbru@redhat.com>,
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2.1
|
|
|
|
* or later. See the COPYING.LIB file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
2016-01-18 21:01:42 +03:00
|
|
|
#include "qemu/osdep.h"
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
#include "sysemu/block-backend.h"
|
|
|
|
#include "block/block_int.h"
|
2015-10-19 18:53:22 +03:00
|
|
|
#include "block/blockjob.h"
|
2021-10-06 16:17:13 +03:00
|
|
|
#include "block/coroutines.h"
|
2015-10-19 18:53:24 +03:00
|
|
|
#include "block/throttle-groups.h"
|
2019-08-12 08:23:37 +03:00
|
|
|
#include "hw/qdev-core.h"
|
2014-10-07 15:59:06 +04:00
|
|
|
#include "sysemu/blockdev.h"
|
2019-08-12 08:23:59 +03:00
|
|
|
#include "sysemu/runstate.h"
|
2019-09-17 14:58:19 +03:00
|
|
|
#include "sysemu/replay.h"
|
2018-02-01 14:18:31 +03:00
|
|
|
#include "qapi/error.h"
|
2018-02-11 12:36:01 +03:00
|
|
|
#include "qapi/qapi-events-block.h"
|
2016-03-20 20:16:19 +03:00
|
|
|
#include "qemu/id.h"
|
Include qemu/main-loop.h less
In my "build everything" tree, changing qemu/main-loop.h triggers a
recompile of some 5600 out of 6600 objects (not counting tests and
objects that don't depend on qemu/osdep.h). It includes block/aio.h,
which in turn includes qemu/event_notifier.h, qemu/notify.h,
qemu/processor.h, qemu/qsp.h, qemu/queue.h, qemu/thread-posix.h,
qemu/thread.h, qemu/timer.h, and a few more.
Include qemu/main-loop.h only where it's needed. Touching it now
recompiles only some 1700 objects. For block/aio.h and
qemu/event_notifier.h, these numbers drop from 5600 to 2800. For the
others, they shrink only slightly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20190812052359.30071-21-armbru@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2019-08-12 08:23:50 +03:00
|
|
|
#include "qemu/main-loop.h"
|
2018-02-01 14:18:46 +03:00
|
|
|
#include "qemu/option.h"
|
2016-04-14 17:40:16 +03:00
|
|
|
#include "trace.h"
|
2017-08-15 16:07:39 +03:00
|
|
|
#include "migration/misc.h"
|
2014-10-07 15:59:25 +04:00
|
|
|
|
|
|
|
/* Number of coroutines to reserve per attached device model */
|
|
|
|
#define COROUTINE_POOL_RESERVATION 64
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
|
2016-03-08 15:47:47 +03:00
|
|
|
#define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
|
|
|
|
|
2018-03-06 23:48:18 +03:00
|
|
|
typedef struct BlockBackendAioNotifier {
|
|
|
|
void (*attached_aio_context)(AioContext *new_context, void *opaque);
|
|
|
|
void (*detach_aio_context)(void *opaque);
|
|
|
|
void *opaque;
|
|
|
|
QLIST_ENTRY(BlockBackendAioNotifier) list;
|
|
|
|
} BlockBackendAioNotifier;
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
struct BlockBackend {
|
|
|
|
char *name;
|
|
|
|
int refcnt;
|
2016-03-08 15:47:46 +03:00
|
|
|
BdrvChild *root;
|
2024-02-02 17:47:54 +03:00
|
|
|
AioContext *ctx; /* access with atomic operations only */
|
2014-10-07 15:59:22 +04:00
|
|
|
DriveInfo *legacy_dinfo; /* null unless created by drive_new() */
|
2016-03-16 21:54:36 +03:00
|
|
|
QTAILQ_ENTRY(BlockBackend) link; /* for block_backends */
|
2016-03-16 21:54:35 +03:00
|
|
|
QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
|
2016-03-21 13:27:04 +03:00
|
|
|
BlockBackendPublic public;
|
2014-10-07 15:59:25 +04:00
|
|
|
|
2019-01-23 11:56:01 +03:00
|
|
|
DeviceState *dev; /* attached device model, if any */
|
2014-10-07 15:59:25 +04:00
|
|
|
const BlockDevOps *dev_ops;
|
|
|
|
void *dev_opaque;
|
2015-10-19 18:53:19 +03:00
|
|
|
|
2015-10-19 18:53:24 +03:00
|
|
|
/* If the BDS tree is removed, some of its options are stored here (which
|
|
|
|
* can be used to restore those options in the new BDS on insert) */
|
|
|
|
BlockBackendRootState root_state;
|
|
|
|
|
2016-03-04 16:28:01 +03:00
|
|
|
bool enable_write_cache;
|
|
|
|
|
2015-10-19 18:53:21 +03:00
|
|
|
/* I/O stats (display with "info blockstats"). */
|
|
|
|
BlockAcctStats stats;
|
2015-10-19 18:53:22 +03:00
|
|
|
|
|
|
|
BlockdevOnError on_read_error, on_write_error;
|
|
|
|
bool iostatus_enabled;
|
|
|
|
BlockDeviceIoStatus iostatus;
|
2016-01-29 18:36:03 +03:00
|
|
|
|
2017-01-20 17:42:39 +03:00
|
|
|
uint64_t perm;
|
|
|
|
uint64_t shared_perm;
|
2017-04-04 18:29:03 +03:00
|
|
|
bool disable_perm;
|
2017-01-20 17:42:39 +03:00
|
|
|
|
2019-05-06 20:18:02 +03:00
|
|
|
bool allow_aio_context_change;
|
2016-03-08 18:39:49 +03:00
|
|
|
bool allow_write_beyond_eof;
|
|
|
|
|
2022-03-03 18:15:52 +03:00
|
|
|
/* Protected by BQL */
|
2016-01-29 18:36:03 +03:00
|
|
|
NotifierList remove_bs_notifiers, insert_bs_notifiers;
|
2018-03-06 23:48:18 +03:00
|
|
|
QLIST_HEAD(, BlockBackendAioNotifier) aio_notifiers;
|
2017-03-17 00:23:50 +03:00
|
|
|
|
2023-03-08 00:04:25 +03:00
|
|
|
int quiesce_counter; /* atomic: written under BQL, read by other threads */
|
2023-03-08 00:04:27 +03:00
|
|
|
QemuMutex queued_requests_lock; /* protects queued_requests */
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
CoQueue queued_requests;
|
2023-03-08 00:04:26 +03:00
|
|
|
bool disable_request_queuing; /* atomic */
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
|
2017-08-15 16:07:39 +03:00
|
|
|
VMChangeStateEntry *vmsh;
|
2017-08-23 16:42:40 +03:00
|
|
|
bool force_allow_inactivate;
|
2018-02-16 19:50:13 +03:00
|
|
|
|
|
|
|
/* Number of in-flight aio requests. BlockDriverState also counts
|
|
|
|
* in-flight requests but aio requests can exist even when blk->root is
|
|
|
|
* NULL, so we cannot rely on its counter for that case.
|
|
|
|
* Accessed with atomic ops.
|
|
|
|
*/
|
|
|
|
unsigned int in_flight;
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
};
|
|
|
|
|
2015-02-05 21:58:23 +03:00
|
|
|
typedef struct BlockBackendAIOCB {
|
|
|
|
BlockAIOCB common;
|
2015-10-19 18:53:18 +03:00
|
|
|
BlockBackend *blk;
|
2015-02-05 21:58:23 +03:00
|
|
|
int ret;
|
|
|
|
} BlockBackendAIOCB;
|
|
|
|
|
|
|
|
static const AIOCBInfo block_backend_aiocb_info = {
|
|
|
|
.aiocb_size = sizeof(BlockBackendAIOCB),
|
|
|
|
};
|
|
|
|
|
2014-10-07 15:59:07 +04:00
|
|
|
static void drive_info_del(DriveInfo *dinfo);
|
2016-03-22 20:58:50 +03:00
|
|
|
static BlockBackend *bdrv_first_blk(BlockDriverState *bs);
|
2014-10-07 15:59:07 +04:00
|
|
|
|
2022-03-03 18:15:52 +03:00
|
|
|
/* All BlockBackends. Protected by BQL. */
|
2016-03-16 21:54:36 +03:00
|
|
|
static QTAILQ_HEAD(, BlockBackend) block_backends =
|
|
|
|
QTAILQ_HEAD_INITIALIZER(block_backends);
|
|
|
|
|
2022-03-03 18:15:52 +03:00
|
|
|
/*
|
|
|
|
* All BlockBackends referenced by the monitor and which are iterated through by
|
|
|
|
* blk_next(). Protected by BQL.
|
|
|
|
*/
|
2016-03-16 21:54:35 +03:00
|
|
|
static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
|
|
|
|
QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
|
2023-09-11 12:46:12 +03:00
|
|
|
static int coroutine_mixed_fn GRAPH_RDLOCK
|
|
|
|
blk_set_perm_locked(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
|
|
|
|
Error **errp);
|
|
|
|
|
2020-05-13 14:05:18 +03:00
|
|
|
static void blk_root_inherit_options(BdrvChildRole role, bool parent_is_format,
|
2020-05-13 14:05:17 +03:00
|
|
|
int *child_flags, QDict *child_options,
|
2016-03-08 15:47:46 +03:00
|
|
|
int parent_flags, QDict *parent_options)
|
|
|
|
{
|
|
|
|
/* We're not supposed to call this function for root nodes */
|
|
|
|
abort();
|
|
|
|
}
|
2016-03-22 14:05:35 +03:00
|
|
|
static void blk_root_drained_begin(BdrvChild *child);
|
2018-09-06 18:43:49 +03:00
|
|
|
static bool blk_root_drained_poll(BdrvChild *child);
|
2022-11-18 20:40:59 +03:00
|
|
|
static void blk_root_drained_end(BdrvChild *child);
|
2016-03-08 15:47:46 +03:00
|
|
|
|
2016-02-24 17:13:35 +03:00
|
|
|
static void blk_root_change_media(BdrvChild *child, bool load);
|
|
|
|
static void blk_root_resize(BdrvChild *child);
|
|
|
|
|
2022-10-25 11:49:48 +03:00
|
|
|
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
|
|
|
|
GHashTable *visited, Transaction *tran,
|
|
|
|
Error **errp);
|
2019-05-06 20:18:01 +03:00
|
|
|
|
2017-01-17 17:56:16 +03:00
|
|
|
static char *blk_root_get_parent_desc(BdrvChild *child)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
2021-06-01 10:52:14 +03:00
|
|
|
g_autofree char *dev_id = NULL;
|
2017-01-17 17:56:16 +03:00
|
|
|
|
|
|
|
if (blk->name) {
|
2021-06-01 10:52:14 +03:00
|
|
|
return g_strdup_printf("block device '%s'", blk->name);
|
2017-01-17 17:56:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
dev_id = blk_get_attached_dev_id(blk);
|
|
|
|
if (*dev_id) {
|
2021-06-01 10:52:14 +03:00
|
|
|
return g_strdup_printf("block device '%s'", dev_id);
|
2017-01-17 17:56:16 +03:00
|
|
|
} else {
|
|
|
|
/* TODO Callback into the BB owner for something more detailed */
|
2021-06-01 10:52:14 +03:00
|
|
|
return g_strdup("an unnamed block device");
|
2017-01-17 17:56:16 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-26 12:22:16 +03:00
|
|
|
static const char *blk_root_get_name(BdrvChild *child)
|
|
|
|
{
|
|
|
|
return blk_name(child->opaque);
|
|
|
|
}
|
|
|
|
|
2021-01-11 18:20:20 +03:00
|
|
|
static void blk_vm_state_changed(void *opaque, bool running, RunState state)
|
2017-08-15 16:07:39 +03:00
|
|
|
{
|
|
|
|
Error *local_err = NULL;
|
|
|
|
BlockBackend *blk = opaque;
|
|
|
|
|
|
|
|
if (state == RUN_STATE_INMIGRATE) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
qemu_del_vm_change_state_handler(blk->vmsh);
|
|
|
|
blk->vmsh = NULL;
|
|
|
|
blk_set_perm(blk, blk->perm, blk->shared_perm, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
error_report_err(local_err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-04 19:52:37 +03:00
|
|
|
/*
|
|
|
|
* Notifies the user of the BlockBackend that migration has completed. qdev
|
|
|
|
* devices can tighten their permissions in response (specifically revoke
|
|
|
|
* shared write permissions that we needed for storage migration).
|
|
|
|
*
|
|
|
|
* If an error is returned, the VM cannot be allowed to be resumed.
|
|
|
|
*/
|
2023-09-11 12:46:12 +03:00
|
|
|
static void GRAPH_RDLOCK blk_root_activate(BdrvChild *child, Error **errp)
|
2017-05-04 19:52:37 +03:00
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
|
|
|
Error *local_err = NULL;
|
2021-11-25 16:53:16 +03:00
|
|
|
uint64_t saved_shared_perm;
|
2017-05-04 19:52:37 +03:00
|
|
|
|
|
|
|
if (!blk->disable_perm) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
blk->disable_perm = false;
|
|
|
|
|
2021-11-25 16:53:16 +03:00
|
|
|
/*
|
|
|
|
* blk->shared_perm contains the permissions we want to share once
|
|
|
|
* migration is really completely done. For now, we need to share
|
|
|
|
* all; but we also need to retain blk->shared_perm, which is
|
|
|
|
* overwritten by a successful blk_set_perm() call. Save it and
|
|
|
|
* restore it below.
|
|
|
|
*/
|
|
|
|
saved_shared_perm = blk->shared_perm;
|
|
|
|
|
2023-09-11 12:46:12 +03:00
|
|
|
blk_set_perm_locked(blk, blk->perm, BLK_PERM_ALL, &local_err);
|
2017-08-15 16:07:39 +03:00
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
blk->disable_perm = true;
|
|
|
|
return;
|
|
|
|
}
|
2021-11-25 16:53:16 +03:00
|
|
|
blk->shared_perm = saved_shared_perm;
|
2017-08-15 16:07:39 +03:00
|
|
|
|
|
|
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
|
|
|
/* Activation can happen when migration process is still active, for
|
|
|
|
* example when nbd_server_add is called during non-shared storage
|
|
|
|
* migration. Defer the shared_perm update to migration completion. */
|
|
|
|
if (!blk->vmsh) {
|
|
|
|
blk->vmsh = qemu_add_vm_change_state_handler(blk_vm_state_changed,
|
|
|
|
blk);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-11 12:46:12 +03:00
|
|
|
blk_set_perm_locked(blk, blk->perm, blk->shared_perm, &local_err);
|
2017-05-04 19:52:37 +03:00
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
blk->disable_perm = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-23 16:42:40 +03:00
|
|
|
void blk_set_force_allow_inactivate(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-08-23 16:42:40 +03:00
|
|
|
blk->force_allow_inactivate = true;
|
|
|
|
}
|
|
|
|
|
2017-08-23 16:42:39 +03:00
|
|
|
static bool blk_can_inactivate(BlockBackend *blk)
|
|
|
|
{
|
2017-08-23 16:42:40 +03:00
|
|
|
/* If it is a guest device, inactivate is ok. */
|
2017-08-23 16:42:39 +03:00
|
|
|
if (blk->dev || blk_name(blk)[0]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-08-23 16:42:40 +03:00
|
|
|
/* Inactivating means no more writes to the image can be done,
|
|
|
|
* even if those writes would be changes invisible to the
|
|
|
|
* guest. For block job BBs that satisfy this, we can just allow
|
|
|
|
* it. This is the case for mirror job source, which is required
|
|
|
|
* by libvirt non-shared block migration. */
|
|
|
|
if (!(blk->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return blk->force_allow_inactivate;
|
2017-08-23 16:42:39 +03:00
|
|
|
}
|
|
|
|
|
2023-09-11 12:46:12 +03:00
|
|
|
static int GRAPH_RDLOCK blk_root_inactivate(BdrvChild *child)
|
2017-05-04 19:52:38 +03:00
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
|
|
|
|
|
|
|
if (blk->disable_perm) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-23 16:42:39 +03:00
|
|
|
if (!blk_can_inactivate(blk)) {
|
2017-05-04 19:52:38 +03:00
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
|
|
|
|
blk->disable_perm = true;
|
|
|
|
if (blk->root) {
|
|
|
|
bdrv_child_try_set_perm(blk->root, 0, BLK_PERM_ALL, &error_abort);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-06 23:48:18 +03:00
|
|
|
static void blk_root_attach(BdrvChild *child)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
|
|
|
BlockBackendAioNotifier *notifier;
|
|
|
|
|
|
|
|
trace_blk_root_attach(child, blk, child->bs);
|
|
|
|
|
|
|
|
QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
|
|
|
|
bdrv_add_aio_context_notifier(child->bs,
|
|
|
|
notifier->attached_aio_context,
|
|
|
|
notifier->detach_aio_context,
|
|
|
|
notifier->opaque);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void blk_root_detach(BdrvChild *child)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
|
|
|
BlockBackendAioNotifier *notifier;
|
|
|
|
|
|
|
|
trace_blk_root_detach(child, blk, child->bs);
|
|
|
|
|
|
|
|
QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
|
|
|
|
bdrv_remove_aio_context_notifier(child->bs,
|
|
|
|
notifier->attached_aio_context,
|
|
|
|
notifier->detach_aio_context,
|
|
|
|
notifier->opaque);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-28 18:17:33 +03:00
|
|
|
static AioContext *blk_root_get_parent_aio_context(BdrvChild *c)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = c->opaque;
|
block: Make bdrv_child_get_parent_aio_context I/O
We want to use bdrv_child_get_parent_aio_context() from
bdrv_parent_drained_{begin,end}_single(), both of which are "I/O or GS"
functions.
Prior to 3ed4f708fe1, all the implementations were I/O code anyway.
3ed4f708fe1 has put block jobs' AioContext field under the job mutex, so
to make child_job_get_parent_aio_context() work in an I/O context, we
need to take that lock there.
Furthermore, blk_root_get_parent_aio_context() is not marked as
anything, but is safe to run in an I/O context, so mark it that way now.
(blk_get_aio_context() is an I/O code function.)
With that done, all implementations explicitly are I/O code, so we can
mark bdrv_child_get_parent_aio_context() as I/O code, too, so callers
know it is safe to run from both GS and I/O contexts.
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20221107151321.211175-2-hreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2022-11-07 18:13:19 +03:00
|
|
|
IO_CODE();
|
2021-04-28 18:17:33 +03:00
|
|
|
|
|
|
|
return blk_get_aio_context(blk);
|
|
|
|
}
|
|
|
|
|
2020-05-13 14:05:13 +03:00
|
|
|
static const BdrvChildClass child_root = {
|
2016-03-22 14:05:35 +03:00
|
|
|
.inherit_options = blk_root_inherit_options,
|
|
|
|
|
2016-02-24 17:13:35 +03:00
|
|
|
.change_media = blk_root_change_media,
|
|
|
|
.resize = blk_root_resize,
|
2016-02-26 12:22:16 +03:00
|
|
|
.get_name = blk_root_get_name,
|
2017-01-17 17:56:16 +03:00
|
|
|
.get_parent_desc = blk_root_get_parent_desc,
|
2016-02-24 17:13:35 +03:00
|
|
|
|
2016-03-22 14:05:35 +03:00
|
|
|
.drained_begin = blk_root_drained_begin,
|
2018-09-06 18:43:49 +03:00
|
|
|
.drained_poll = blk_root_drained_poll,
|
2016-03-22 14:05:35 +03:00
|
|
|
.drained_end = blk_root_drained_end,
|
2017-05-04 19:52:37 +03:00
|
|
|
|
|
|
|
.activate = blk_root_activate,
|
2017-05-04 19:52:38 +03:00
|
|
|
.inactivate = blk_root_inactivate,
|
2018-03-06 23:48:18 +03:00
|
|
|
|
|
|
|
.attach = blk_root_attach,
|
|
|
|
.detach = blk_root_detach,
|
2019-05-06 20:18:01 +03:00
|
|
|
|
2022-10-25 11:49:48 +03:00
|
|
|
.change_aio_ctx = blk_root_change_aio_ctx,
|
2021-04-28 18:17:33 +03:00
|
|
|
|
|
|
|
.get_parent_aio_context = blk_root_get_parent_aio_context,
|
2016-03-08 15:47:46 +03:00
|
|
|
};
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
/*
|
2016-03-16 21:54:38 +03:00
|
|
|
* Create a new BlockBackend with a reference count of one.
|
2017-01-20 19:07:26 +03:00
|
|
|
*
|
|
|
|
* @perm is a bitmasks of BLK_PERM_* constants which describes the permissions
|
|
|
|
* to request for a block driver node that is attached to this BlockBackend.
|
|
|
|
* @shared_perm is a bitmask which describes which permissions may be granted
|
|
|
|
* to other users of the attached node.
|
|
|
|
* Both sets of permissions can be changed later using blk_set_perm().
|
|
|
|
*
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
* Return the new BlockBackend on success, null on failure.
|
|
|
|
*/
|
2019-04-25 15:25:10 +03:00
|
|
|
BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
{
|
|
|
|
BlockBackend *blk;
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
blk = g_new0(BlockBackend, 1);
|
|
|
|
blk->refcnt = 1;
|
2019-04-25 15:25:10 +03:00
|
|
|
blk->ctx = ctx;
|
2017-01-20 19:07:26 +03:00
|
|
|
blk->perm = perm;
|
|
|
|
blk->shared_perm = shared_perm;
|
2016-04-19 18:27:24 +03:00
|
|
|
blk_set_enable_write_cache(blk, true);
|
|
|
|
|
2018-09-28 12:11:50 +03:00
|
|
|
blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT;
|
|
|
|
blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
|
|
|
|
|
2017-06-05 15:39:07 +03:00
|
|
|
block_acct_init(&blk->stats);
|
2016-03-21 14:56:44 +03:00
|
|
|
|
2023-03-08 00:04:27 +03:00
|
|
|
qemu_mutex_init(&blk->queued_requests_lock);
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
qemu_co_queue_init(&blk->queued_requests);
|
2016-01-29 18:36:03 +03:00
|
|
|
notifier_list_init(&blk->remove_bs_notifiers);
|
|
|
|
notifier_list_init(&blk->insert_bs_notifiers);
|
2018-03-06 23:48:18 +03:00
|
|
|
QLIST_INIT(&blk->aio_notifiers);
|
2016-03-21 14:56:44 +03:00
|
|
|
|
2016-03-16 21:54:36 +03:00
|
|
|
QTAILQ_INSERT_TAIL(&block_backends, blk, link);
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
return blk;
|
|
|
|
}
|
|
|
|
|
2020-04-28 22:26:46 +03:00
|
|
|
/*
|
|
|
|
* Create a new BlockBackend connected to an existing BlockDriverState.
|
|
|
|
*
|
|
|
|
* @perm is a bitmasks of BLK_PERM_* constants which describes the
|
|
|
|
* permissions to request for @bs that is attached to this
|
|
|
|
* BlockBackend. @shared_perm is a bitmask which describes which
|
|
|
|
* permissions may be granted to other users of the attached node.
|
|
|
|
* Both sets of permissions can be changed later using blk_set_perm().
|
|
|
|
*
|
|
|
|
* Return the new BlockBackend on success, null on failure.
|
|
|
|
*/
|
|
|
|
BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
|
|
|
|
uint64_t shared_perm, Error **errp)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2020-04-28 22:26:46 +03:00
|
|
|
if (blk_insert_bs(blk, bs, errp) < 0) {
|
|
|
|
blk_unref(blk);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return blk;
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:05 +04:00
|
|
|
/*
|
2016-05-17 17:41:29 +03:00
|
|
|
* Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
|
2023-05-25 15:47:05 +03:00
|
|
|
* By default, the new BlockBackend is in the main AioContext, but if the
|
|
|
|
* parameters connect it with any existing node in a different AioContext, it
|
|
|
|
* may end up there instead.
|
2015-02-05 21:58:11 +03:00
|
|
|
*
|
|
|
|
* Just as with bdrv_open(), after having called this function the reference to
|
|
|
|
* @options belongs to the block layer (even on failure).
|
|
|
|
*
|
|
|
|
* TODO: Remove @filename and @flags; it should be possible to specify a whole
|
|
|
|
* BDS tree just by specifying the @options QDict (or @reference,
|
|
|
|
* alternatively). At the time of adding this function, this is not possible,
|
|
|
|
* though, so callers of this function have to be able to specify @filename and
|
|
|
|
* @flags.
|
|
|
|
*/
|
2016-03-16 21:54:38 +03:00
|
|
|
BlockBackend *blk_new_open(const char *filename, const char *reference,
|
|
|
|
QDict *options, int flags, Error **errp)
|
2015-02-05 21:58:11 +03:00
|
|
|
{
|
|
|
|
BlockBackend *blk;
|
2016-05-17 17:41:29 +03:00
|
|
|
BlockDriverState *bs;
|
2017-11-20 17:02:48 +03:00
|
|
|
uint64_t perm = 0;
|
2021-04-22 19:43:43 +03:00
|
|
|
uint64_t shared = BLK_PERM_ALL;
|
2017-01-13 21:13:00 +03:00
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2021-04-22 19:43:43 +03:00
|
|
|
/*
|
|
|
|
* blk_new_open() is mainly used in .bdrv_create implementations and the
|
|
|
|
* tools where sharing isn't a major concern because the BDS stays private
|
|
|
|
* and the file is generally not supposed to be used by a second process,
|
|
|
|
* so we just request permission according to the flags.
|
2017-01-13 21:13:00 +03:00
|
|
|
*
|
|
|
|
* The exceptions are xen_disk and blockdev_init(); in these cases, the
|
|
|
|
* caller of blk_new_open() doesn't make use of the permissions, but they
|
|
|
|
* shouldn't hurt either. We can still share everything here because the
|
2021-04-22 19:43:43 +03:00
|
|
|
* guest devices will add their own blockers if they can't share.
|
|
|
|
*/
|
2017-11-20 17:02:48 +03:00
|
|
|
if ((flags & BDRV_O_NO_IO) == 0) {
|
|
|
|
perm |= BLK_PERM_CONSISTENT_READ;
|
|
|
|
if (flags & BDRV_O_RDWR) {
|
|
|
|
perm |= BLK_PERM_WRITE;
|
|
|
|
}
|
2017-01-13 21:13:00 +03:00
|
|
|
}
|
|
|
|
if (flags & BDRV_O_RESIZE) {
|
|
|
|
perm |= BLK_PERM_RESIZE;
|
|
|
|
}
|
2021-04-22 19:43:43 +03:00
|
|
|
if (flags & BDRV_O_NO_SHARE) {
|
|
|
|
shared = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
|
|
|
|
}
|
2015-02-05 21:58:11 +03:00
|
|
|
|
2016-05-17 17:41:31 +03:00
|
|
|
bs = bdrv_open(filename, reference, options, flags, errp);
|
|
|
|
if (!bs) {
|
2015-02-05 21:58:11 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-05-25 15:47:05 +03:00
|
|
|
/* bdrv_open() could have moved bs to a different AioContext */
|
|
|
|
blk = blk_new(bdrv_get_aio_context(bs), perm, shared);
|
|
|
|
blk->perm = perm;
|
|
|
|
blk->shared_perm = shared;
|
|
|
|
|
|
|
|
blk_insert_bs(blk, bs, errp);
|
|
|
|
bdrv_unref(bs);
|
|
|
|
|
2017-03-07 14:07:21 +03:00
|
|
|
if (!blk->root) {
|
|
|
|
blk_unref(blk);
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-03-15 16:34:37 +03:00
|
|
|
|
2015-02-05 21:58:11 +03:00
|
|
|
return blk;
|
|
|
|
}
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
static void blk_delete(BlockBackend *blk)
|
|
|
|
{
|
|
|
|
assert(!blk->refcnt);
|
2016-03-16 21:54:37 +03:00
|
|
|
assert(!blk->name);
|
2014-10-07 15:59:25 +04:00
|
|
|
assert(!blk->dev);
|
2017-08-25 16:20:23 +03:00
|
|
|
if (blk->public.throttle_group_member.throttle_state) {
|
throttle: Remove block from group on hot-unplug
When a block device that is part of a throttle group is hot-unplugged,
we forgot to remove it from the throttle group. This leaves stale
memory around, and causes an easily reproducible crash:
$ ./x86_64-softmmu/qemu-system-x86_64 -nodefaults -nographic -qmp stdio \
-device virtio-scsi-pci,bus=pci.0 -drive \
id=drive_image2,if=none,format=raw,file=file2,bps=512000,iops=100,group=foo \
-device scsi-hd,id=image2,drive=drive_image2 -drive \
id=drive_image3,if=none,format=raw,file=file3,bps=512000,iops=100,group=foo \
-device scsi-hd,id=image3,drive=drive_image3
{'execute':'qmp_capabilities'}
{'execute':'device_del','arguments':{'id':'image3'}}
{'execute':'system_reset'}
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1428810
Suggested-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-id: 20170406190847.29347-1-eblake@redhat.com
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
2017-04-06 22:08:47 +03:00
|
|
|
blk_io_limits_disable(blk);
|
|
|
|
}
|
2016-03-08 15:47:46 +03:00
|
|
|
if (blk->root) {
|
2016-01-29 18:36:08 +03:00
|
|
|
blk_remove_bs(blk);
|
2014-10-07 15:59:05 +04:00
|
|
|
}
|
2017-08-15 16:07:39 +03:00
|
|
|
if (blk->vmsh) {
|
|
|
|
qemu_del_vm_change_state_handler(blk->vmsh);
|
|
|
|
blk->vmsh = NULL;
|
|
|
|
}
|
2016-01-29 18:36:03 +03:00
|
|
|
assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
|
|
|
|
assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
|
2018-03-06 23:48:18 +03:00
|
|
|
assert(QLIST_EMPTY(&blk->aio_notifiers));
|
2023-03-08 00:04:27 +03:00
|
|
|
assert(qemu_co_queue_empty(&blk->queued_requests));
|
|
|
|
qemu_mutex_destroy(&blk->queued_requests_lock);
|
2016-03-16 21:54:36 +03:00
|
|
|
QTAILQ_REMOVE(&block_backends, blk, link);
|
2014-10-07 15:59:06 +04:00
|
|
|
drive_info_del(blk->legacy_dinfo);
|
2015-10-28 18:33:05 +03:00
|
|
|
block_acct_cleanup(&blk->stats);
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
g_free(blk);
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:07 +04:00
|
|
|
static void drive_info_del(DriveInfo *dinfo)
|
|
|
|
{
|
|
|
|
if (!dinfo) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
qemu_opts_del(dinfo->opts);
|
|
|
|
g_free(dinfo);
|
|
|
|
}
|
|
|
|
|
2015-11-02 17:51:54 +03:00
|
|
|
int blk_get_refcnt(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-11-02 17:51:54 +03:00
|
|
|
return blk ? blk->refcnt : 0;
|
|
|
|
}
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
/*
|
|
|
|
* Increment @blk's reference count.
|
|
|
|
* @blk must not be null.
|
|
|
|
*/
|
|
|
|
void blk_ref(BlockBackend *blk)
|
|
|
|
{
|
2018-09-07 14:45:54 +03:00
|
|
|
assert(blk->refcnt > 0);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
blk->refcnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Decrement @blk's reference count.
|
|
|
|
* If this drops it to zero, destroy @blk.
|
|
|
|
* For convenience, do nothing if @blk is null.
|
|
|
|
*/
|
|
|
|
void blk_unref(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
if (blk) {
|
|
|
|
assert(blk->refcnt > 0);
|
2018-09-07 14:45:54 +03:00
|
|
|
if (blk->refcnt > 1) {
|
|
|
|
blk->refcnt--;
|
|
|
|
} else {
|
|
|
|
blk_drain(blk);
|
|
|
|
/* blk_drain() cannot resurrect blk, nobody held a reference */
|
|
|
|
assert(blk->refcnt == 1);
|
|
|
|
blk->refcnt = 0;
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
blk_delete(blk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 21:54:36 +03:00
|
|
|
/*
|
|
|
|
* Behaves similarly to blk_next() but iterates over all BlockBackends, even the
|
|
|
|
* ones which are hidden (i.e. are not referenced by the monitor).
|
|
|
|
*/
|
2017-07-11 15:06:04 +03:00
|
|
|
BlockBackend *blk_all_next(BlockBackend *blk)
|
2016-03-16 21:54:36 +03:00
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-16 21:54:36 +03:00
|
|
|
return blk ? QTAILQ_NEXT(blk, link)
|
|
|
|
: QTAILQ_FIRST(&block_backends);
|
|
|
|
}
|
|
|
|
|
2016-01-29 18:36:13 +03:00
|
|
|
void blk_remove_all_bs(void)
|
|
|
|
{
|
2016-03-16 21:54:30 +03:00
|
|
|
BlockBackend *blk = NULL;
|
2016-01-29 18:36:13 +03:00
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2016-03-16 21:54:36 +03:00
|
|
|
while ((blk = blk_all_next(blk)) != NULL) {
|
2016-03-08 15:47:46 +03:00
|
|
|
if (blk->root) {
|
2016-01-29 18:36:13 +03:00
|
|
|
blk_remove_bs(blk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
/*
|
2016-03-16 21:54:35 +03:00
|
|
|
* Return the monitor-owned BlockBackend after @blk.
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
* If @blk is null, return the first one.
|
|
|
|
* Else, return @blk's next sibling, which may be null.
|
|
|
|
*
|
|
|
|
* To iterate over all BlockBackends, do
|
|
|
|
* for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
|
|
|
* ...
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
BlockBackend *blk_next(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-16 21:54:35 +03:00
|
|
|
return blk ? QTAILQ_NEXT(blk, monitor_link)
|
|
|
|
: QTAILQ_FIRST(&monitor_block_backends);
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 20:58:50 +03:00
|
|
|
/* Iterates over all top-level BlockDriverStates, i.e. BDSs that are owned by
|
|
|
|
* the monitor or attached to a BlockBackend */
|
2016-05-20 19:49:07 +03:00
|
|
|
BlockDriverState *bdrv_next(BdrvNextIterator *it)
|
2016-03-22 20:58:50 +03:00
|
|
|
{
|
2017-11-10 20:25:45 +03:00
|
|
|
BlockDriverState *bs, *old_bs;
|
|
|
|
|
|
|
|
/* Must be called from the main loop */
|
|
|
|
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
2016-03-16 21:54:42 +03:00
|
|
|
|
block-backend: fix edge case in bdrv_next() where BDS associated to BB changes
The old_bs variable in bdrv_next() is currently determined by looking
at the old block backend. However, if the block graph changes before
the next bdrv_next() call, it might be that the associated BDS is not
the same that was referenced previously. In that case, the wrong BDS
is unreferenced, leading to an assertion failure later:
> bdrv_unref: Assertion `bs->refcnt > 0' failed.
In particular, this can happen in the context of bdrv_flush_all(),
when polling for bdrv_co_flush() in the generated co-wrapper leads to
a graph change (for example with a stream block job [0]).
A racy reproducer:
> #!/bin/bash
> rm -f /tmp/backing.qcow2
> rm -f /tmp/top.qcow2
> ./qemu-img create /tmp/backing.qcow2 -f qcow2 64M
> ./qemu-io -c "write -P42 0x0 0x1" /tmp/backing.qcow2
> ./qemu-img create /tmp/top.qcow2 -f qcow2 64M -b /tmp/backing.qcow2 -F qcow2
> ./qemu-system-x86_64 --qmp stdio \
> --blockdev qcow2,node-name=node0,file.driver=file,file.filename=/tmp/top.qcow2 \
> <<EOF
> {"execute": "qmp_capabilities"}
> {"execute": "block-stream", "arguments": { "job-id": "stream0", "device": "node0" } }
> {"execute": "quit"}
> EOF
[0]:
> #0 bdrv_replace_child_tran (child=..., new_bs=..., tran=...)
> #1 bdrv_replace_node_noperm (from=..., to=..., auto_skip=..., tran=..., errp=...)
> #2 bdrv_replace_node_common (from=..., to=..., auto_skip=..., detach_subchain=..., errp=...)
> #3 bdrv_drop_filter (bs=..., errp=...)
> #4 bdrv_cor_filter_drop (cor_filter_bs=...)
> #5 stream_prepare (job=...)
> #6 job_prepare_locked (job=...)
> #7 job_txn_apply_locked (fn=..., job=...)
> #8 job_do_finalize_locked (job=...)
> #9 job_exit (opaque=...)
> #10 aio_bh_poll (ctx=...)
> #11 aio_poll (ctx=..., blocking=...)
> #12 bdrv_poll_co (s=...)
> #13 bdrv_flush (bs=...)
> #14 bdrv_flush_all ()
> #15 do_vm_stop (state=..., send_stop=...)
> #16 vm_shutdown ()
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Message-ID: <20240322095009.346989-3-f.ebner@proxmox.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2024-03-22 12:50:07 +03:00
|
|
|
old_bs = it->bs;
|
|
|
|
|
2016-03-22 20:58:50 +03:00
|
|
|
/* First, return all root nodes of BlockBackends. In order to avoid
|
|
|
|
* returning a BDS twice when multiple BBs refer to it, we only return it
|
|
|
|
* if the BB is the first one in the parent list of the BDS. */
|
|
|
|
if (it->phase == BDRV_NEXT_BACKEND_ROOTS) {
|
2017-11-10 20:25:45 +03:00
|
|
|
BlockBackend *old_blk = it->blk;
|
|
|
|
|
2016-03-22 20:58:50 +03:00
|
|
|
do {
|
|
|
|
it->blk = blk_all_next(it->blk);
|
2016-05-20 19:49:07 +03:00
|
|
|
bs = it->blk ? blk_bs(it->blk) : NULL;
|
|
|
|
} while (it->blk && (bs == NULL || bdrv_first_blk(bs) != it->blk));
|
2016-03-22 20:58:50 +03:00
|
|
|
|
2017-11-10 20:25:45 +03:00
|
|
|
if (it->blk) {
|
|
|
|
blk_ref(it->blk);
|
|
|
|
}
|
|
|
|
blk_unref(old_blk);
|
|
|
|
|
2016-05-20 19:49:07 +03:00
|
|
|
if (bs) {
|
2017-11-10 20:25:45 +03:00
|
|
|
bdrv_ref(bs);
|
|
|
|
bdrv_unref(old_bs);
|
block-backend: fix edge case in bdrv_next() where BDS associated to BB changes
The old_bs variable in bdrv_next() is currently determined by looking
at the old block backend. However, if the block graph changes before
the next bdrv_next() call, it might be that the associated BDS is not
the same that was referenced previously. In that case, the wrong BDS
is unreferenced, leading to an assertion failure later:
> bdrv_unref: Assertion `bs->refcnt > 0' failed.
In particular, this can happen in the context of bdrv_flush_all(),
when polling for bdrv_co_flush() in the generated co-wrapper leads to
a graph change (for example with a stream block job [0]).
A racy reproducer:
> #!/bin/bash
> rm -f /tmp/backing.qcow2
> rm -f /tmp/top.qcow2
> ./qemu-img create /tmp/backing.qcow2 -f qcow2 64M
> ./qemu-io -c "write -P42 0x0 0x1" /tmp/backing.qcow2
> ./qemu-img create /tmp/top.qcow2 -f qcow2 64M -b /tmp/backing.qcow2 -F qcow2
> ./qemu-system-x86_64 --qmp stdio \
> --blockdev qcow2,node-name=node0,file.driver=file,file.filename=/tmp/top.qcow2 \
> <<EOF
> {"execute": "qmp_capabilities"}
> {"execute": "block-stream", "arguments": { "job-id": "stream0", "device": "node0" } }
> {"execute": "quit"}
> EOF
[0]:
> #0 bdrv_replace_child_tran (child=..., new_bs=..., tran=...)
> #1 bdrv_replace_node_noperm (from=..., to=..., auto_skip=..., tran=..., errp=...)
> #2 bdrv_replace_node_common (from=..., to=..., auto_skip=..., detach_subchain=..., errp=...)
> #3 bdrv_drop_filter (bs=..., errp=...)
> #4 bdrv_cor_filter_drop (cor_filter_bs=...)
> #5 stream_prepare (job=...)
> #6 job_prepare_locked (job=...)
> #7 job_txn_apply_locked (fn=..., job=...)
> #8 job_do_finalize_locked (job=...)
> #9 job_exit (opaque=...)
> #10 aio_bh_poll (ctx=...)
> #11 aio_poll (ctx=..., blocking=...)
> #12 bdrv_poll_co (s=...)
> #13 bdrv_flush (bs=...)
> #14 bdrv_flush_all ()
> #15 do_vm_stop (state=..., send_stop=...)
> #16 vm_shutdown ()
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Message-ID: <20240322095009.346989-3-f.ebner@proxmox.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2024-03-22 12:50:07 +03:00
|
|
|
it->bs = bs;
|
2016-05-20 19:49:07 +03:00
|
|
|
return bs;
|
2016-03-22 20:58:50 +03:00
|
|
|
}
|
|
|
|
it->phase = BDRV_NEXT_MONITOR_OWNED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Then return the monitor-owned BDSes without a BB attached. Ignore all
|
|
|
|
* BDSes that are attached to a BlockBackend here; they have been handled
|
|
|
|
* by the above block already */
|
2016-03-16 21:54:42 +03:00
|
|
|
do {
|
2016-03-22 20:58:50 +03:00
|
|
|
it->bs = bdrv_next_monitor_owned(it->bs);
|
2016-05-20 19:49:07 +03:00
|
|
|
bs = it->bs;
|
|
|
|
} while (bs && bdrv_has_blk(bs));
|
|
|
|
|
2017-11-10 20:25:45 +03:00
|
|
|
if (bs) {
|
|
|
|
bdrv_ref(bs);
|
|
|
|
}
|
|
|
|
bdrv_unref(old_bs);
|
|
|
|
|
2016-05-20 19:49:07 +03:00
|
|
|
return bs;
|
|
|
|
}
|
|
|
|
|
2017-11-10 20:25:45 +03:00
|
|
|
static void bdrv_next_reset(BdrvNextIterator *it)
|
2016-05-20 19:49:07 +03:00
|
|
|
{
|
|
|
|
*it = (BdrvNextIterator) {
|
|
|
|
.phase = BDRV_NEXT_BACKEND_ROOTS,
|
|
|
|
};
|
2017-11-10 20:25:45 +03:00
|
|
|
}
|
2016-03-16 21:54:42 +03:00
|
|
|
|
2017-11-10 20:25:45 +03:00
|
|
|
BlockDriverState *bdrv_first(BdrvNextIterator *it)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-11-10 20:25:45 +03:00
|
|
|
bdrv_next_reset(it);
|
2016-05-20 19:49:07 +03:00
|
|
|
return bdrv_next(it);
|
2016-03-16 21:54:42 +03:00
|
|
|
}
|
|
|
|
|
2017-11-10 20:25:45 +03:00
|
|
|
/* Must be called when aborting a bdrv_next() iteration before
|
|
|
|
* bdrv_next() returns NULL */
|
|
|
|
void bdrv_next_cleanup(BdrvNextIterator *it)
|
|
|
|
{
|
|
|
|
/* Must be called from the main loop */
|
|
|
|
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
|
|
|
|
2024-03-22 12:50:08 +03:00
|
|
|
bdrv_unref(it->bs);
|
|
|
|
|
|
|
|
if (it->phase == BDRV_NEXT_BACKEND_ROOTS && it->blk) {
|
|
|
|
blk_unref(it->blk);
|
2017-11-10 20:25:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bdrv_next_reset(it);
|
|
|
|
}
|
|
|
|
|
2016-03-16 21:54:37 +03:00
|
|
|
/*
|
|
|
|
* Add a BlockBackend into the list of backends referenced by the monitor, with
|
|
|
|
* the given @name acting as the handle for the monitor.
|
|
|
|
* Strictly for use by blockdev.c.
|
|
|
|
*
|
|
|
|
* @name must not be null or empty.
|
|
|
|
*
|
|
|
|
* Returns true on success and false on failure. In the latter case, an Error
|
|
|
|
* object is returned through @errp.
|
|
|
|
*/
|
|
|
|
bool monitor_add_blk(BlockBackend *blk, const char *name, Error **errp)
|
|
|
|
{
|
|
|
|
assert(!blk->name);
|
|
|
|
assert(name && name[0]);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-16 21:54:37 +03:00
|
|
|
|
|
|
|
if (!id_wellformed(name)) {
|
|
|
|
error_setg(errp, "Invalid device name");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (blk_by_name(name)) {
|
|
|
|
error_setg(errp, "Device with id '%s' already exists", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (bdrv_find_node(name)) {
|
|
|
|
error_setg(errp,
|
|
|
|
"Device name '%s' conflicts with an existing node name",
|
|
|
|
name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
blk->name = g_strdup(name);
|
|
|
|
QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove a BlockBackend from the list of backends referenced by the monitor.
|
|
|
|
* Strictly for use by blockdev.c.
|
|
|
|
*/
|
|
|
|
void monitor_remove_blk(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2016-03-16 21:54:37 +03:00
|
|
|
if (!blk->name) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
|
|
|
|
g_free(blk->name);
|
|
|
|
blk->name = NULL;
|
|
|
|
}
|
|
|
|
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
/*
|
2014-10-07 15:59:05 +04:00
|
|
|
* Return @blk's name, a non-null string.
|
2016-03-16 21:54:37 +03:00
|
|
|
* Returns an empty string iff @blk is not referenced by the monitor.
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
*/
|
2017-03-06 00:44:35 +03:00
|
|
|
const char *blk_name(const BlockBackend *blk)
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-16 21:54:37 +03:00
|
|
|
return blk->name ?: "";
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the BlockBackend with name @name if it exists, else null.
|
|
|
|
* @name must not be null.
|
|
|
|
*/
|
|
|
|
BlockBackend *blk_by_name(const char *name)
|
|
|
|
{
|
2016-03-16 21:54:30 +03:00
|
|
|
BlockBackend *blk = NULL;
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
assert(name);
|
2016-03-16 21:54:30 +03:00
|
|
|
while ((blk = blk_next(blk)) != NULL) {
|
block: New BlockBackend
A block device consists of a frontend device model and a backend.
A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.
We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole. Drawbacks:
* Its API includes both stuff that makes sense only at the block
backend level (root of the tree) and stuff that's only for use
within the block layer. This makes the API bigger and more complex
than necessary. Moreover, it's not obvious which interfaces are
meant for device models, and which really aren't.
* Since device models keep a reference to their backend, the backend
object can't just be destroyed. But for media change, we need to
replace the tree. Our solution is to make the BlockDriverState
generic, with actual driver state in a separate object, pointed to
by member opaque. That lets us replace the tree by deinitializing
and reinitializing its root. This special need of the root makes
the data structure awkward everywhere in the tree.
The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.
Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState. This should let us
clean up both APIs, and the tree data structures.
This commit is a first step. It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed exactly when root
BlockDriverState objects are created and destroyed. "Root" in the
sense of "in bdrv_states". They're not yet used for anything; that'll
come shortly.
A root BlockDriverState is created with bdrv_new_root(), so where to
create a BlockBackend is obvious. Where these roots get destroyed
isn't always as obvious.
It is obvious in qemu-img.c, qemu-io.c and qemu-nbd.c, and in error
paths of blockdev_init(), blk_connect(). That leaves destruction of
objects successfully created by blockdev_init() and blk_connect().
blockdev_init() is used only by drive_new() and qmp_blockdev_add().
Objects created by the latter are currently indestructible (see commit
48f364d "blockdev: Refuse to drive_del something added with
blockdev-add" and commit 2d246f0 "blockdev: Introduce
DriveInfo.enable_auto_del"). Objects created by the former get
destroyed by drive_del().
Objects created by blk_connect() get destroyed by blk_disconnect().
BlockBackend is reference-counted. Its reference count never exceeds
one so far, but that's going to change.
In drive_del(), the BB's reference count is surely one now. The BDS's
reference count is greater than one when something else is holding a
reference, such as a block job. In this case, the BB is destroyed
right away, but the BDS lives on until all extra references get
dropped.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2014-10-07 15:59:04 +04:00
|
|
|
if (!strcmp(name, blk->name)) {
|
|
|
|
return blk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-10-07 15:59:05 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the BlockDriverState attached to @blk if any, else null.
|
|
|
|
*/
|
|
|
|
BlockDriverState *blk_bs(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
return blk->root ? blk->root->bs : NULL;
|
2014-10-07 15:59:05 +04:00
|
|
|
}
|
|
|
|
|
2023-09-29 17:51:39 +03:00
|
|
|
static BlockBackend * GRAPH_RDLOCK bdrv_first_blk(BlockDriverState *bs)
|
2016-02-29 12:50:38 +03:00
|
|
|
{
|
|
|
|
BdrvChild *child;
|
2022-03-03 18:16:02 +03:00
|
|
|
|
|
|
|
GLOBAL_STATE_CODE();
|
2023-09-29 17:51:39 +03:00
|
|
|
assert_bdrv_graph_readable();
|
2022-03-03 18:16:02 +03:00
|
|
|
|
2016-02-29 12:50:38 +03:00
|
|
|
QLIST_FOREACH(child, &bs->parents, next_parent) {
|
2020-05-13 14:05:13 +03:00
|
|
|
if (child->klass == &child_root) {
|
2016-03-22 20:58:50 +03:00
|
|
|
return child->opaque;
|
2016-02-29 12:50:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-22 20:58:50 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns true if @bs has an associated BlockBackend.
|
|
|
|
*/
|
|
|
|
bool bdrv_has_blk(BlockDriverState *bs)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-22 20:58:50 +03:00
|
|
|
return bdrv_first_blk(bs) != NULL;
|
2016-02-29 12:50:38 +03:00
|
|
|
}
|
|
|
|
|
2016-06-23 15:20:24 +03:00
|
|
|
/*
|
|
|
|
* Returns true if @bs has only BlockBackends as parents.
|
|
|
|
*/
|
|
|
|
bool bdrv_is_root_node(BlockDriverState *bs)
|
|
|
|
{
|
|
|
|
BdrvChild *c;
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2023-09-29 17:51:39 +03:00
|
|
|
assert_bdrv_graph_readable();
|
|
|
|
|
2016-06-23 15:20:24 +03:00
|
|
|
QLIST_FOREACH(c, &bs->parents, next_parent) {
|
2020-05-13 14:05:13 +03:00
|
|
|
if (c->klass != &child_root) {
|
2016-06-23 15:20:24 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:06 +04:00
|
|
|
/*
|
|
|
|
* Return @blk's DriveInfo if any, else null.
|
|
|
|
*/
|
|
|
|
DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:16:06 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:06 +04:00
|
|
|
return blk->legacy_dinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set @blk's DriveInfo to @dinfo, and return it.
|
|
|
|
* @blk must not have a DriveInfo set already.
|
|
|
|
* No other BlockBackend may have the same DriveInfo set.
|
|
|
|
*/
|
|
|
|
DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
|
|
|
|
{
|
|
|
|
assert(!blk->legacy_dinfo);
|
2022-03-03 18:16:06 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:06 +04:00
|
|
|
return blk->legacy_dinfo = dinfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the BlockBackend with DriveInfo @dinfo.
|
|
|
|
* It must exist.
|
|
|
|
*/
|
|
|
|
BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
|
|
|
|
{
|
2016-03-16 21:54:30 +03:00
|
|
|
BlockBackend *blk = NULL;
|
2022-03-03 18:16:06 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:06 +04:00
|
|
|
|
2016-03-16 21:54:30 +03:00
|
|
|
while ((blk = blk_next(blk)) != NULL) {
|
2014-10-07 15:59:06 +04:00
|
|
|
if (blk->legacy_dinfo == dinfo) {
|
|
|
|
return blk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2016-03-21 13:27:04 +03:00
|
|
|
/*
|
|
|
|
* Returns a pointer to the publicly accessible fields of @blk.
|
|
|
|
*/
|
|
|
|
BlockBackendPublic *blk_get_public(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-21 13:27:04 +03:00
|
|
|
return &blk->public;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns a BlockBackend given the associated @public fields.
|
|
|
|
*/
|
|
|
|
BlockBackend *blk_by_public(BlockBackendPublic *public)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-21 13:27:04 +03:00
|
|
|
return container_of(public, BlockBackend, public);
|
|
|
|
}
|
|
|
|
|
2015-10-26 23:39:05 +03:00
|
|
|
/*
|
|
|
|
* Disassociates the currently associated BlockDriverState from @blk.
|
|
|
|
*/
|
|
|
|
void blk_remove_bs(BlockBackend *blk)
|
|
|
|
{
|
2017-11-10 21:54:47 +03:00
|
|
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
2020-07-09 16:50:45 +03:00
|
|
|
BdrvChild *root;
|
2017-08-25 16:20:23 +03:00
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2016-01-29 18:36:03 +03:00
|
|
|
notifier_list_notify(&blk->remove_bs_notifiers, blk);
|
2017-11-10 21:54:47 +03:00
|
|
|
if (tgm->throttle_state) {
|
2022-01-11 18:36:12 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Take a ref in case blk_bs() changes across bdrv_drained_begin(), for
|
|
|
|
* example, if a temporary filter node is removed by a blockjob.
|
|
|
|
*/
|
|
|
|
bdrv_ref(bs);
|
2017-10-21 08:34:00 +03:00
|
|
|
bdrv_drained_begin(bs);
|
2017-11-10 21:54:47 +03:00
|
|
|
throttle_group_detach_aio_context(tgm);
|
|
|
|
throttle_group_attach_aio_context(tgm, qemu_get_aio_context());
|
2017-10-21 08:34:00 +03:00
|
|
|
bdrv_drained_end(bs);
|
2022-01-11 18:36:12 +03:00
|
|
|
bdrv_unref(bs);
|
2016-03-21 12:49:51 +03:00
|
|
|
}
|
2015-10-26 23:39:05 +03:00
|
|
|
|
2016-03-22 15:00:08 +03:00
|
|
|
blk_update_root_state(blk);
|
|
|
|
|
2018-05-28 15:03:59 +03:00
|
|
|
/* bdrv_root_unref_child() will cause blk->root to become stale and may
|
|
|
|
* switch to a completion coroutine later on. Let's drain all I/O here
|
|
|
|
* to avoid that and a potential QEMU crash.
|
|
|
|
*/
|
|
|
|
blk_drain(blk);
|
2020-07-09 16:50:45 +03:00
|
|
|
root = blk->root;
|
2016-03-08 15:47:46 +03:00
|
|
|
blk->root = NULL;
|
2023-09-11 12:46:18 +03:00
|
|
|
|
2023-12-05 21:20:02 +03:00
|
|
|
bdrv_graph_wrlock();
|
2020-07-09 16:50:45 +03:00
|
|
|
bdrv_root_unref_child(root);
|
2023-12-05 21:20:02 +03:00
|
|
|
bdrv_graph_wrunlock();
|
2015-10-26 23:39:05 +03:00
|
|
|
}
|
|
|
|
|
2015-10-19 18:53:28 +03:00
|
|
|
/*
|
|
|
|
* Associates a new BlockDriverState with @blk.
|
|
|
|
*/
|
2017-01-13 21:02:32 +03:00
|
|
|
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
2015-10-19 18:53:28 +03:00
|
|
|
{
|
2017-11-10 21:54:47 +03:00
|
|
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
2023-11-15 20:20:10 +03:00
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2019-05-13 16:46:18 +03:00
|
|
|
bdrv_ref(bs);
|
2023-12-05 21:20:02 +03:00
|
|
|
bdrv_graph_wrlock();
|
2020-05-13 14:05:43 +03:00
|
|
|
blk->root = bdrv_root_attach_child(bs, "root", &child_root,
|
|
|
|
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
|
2021-04-28 18:17:34 +03:00
|
|
|
blk->perm, blk->shared_perm,
|
2020-05-13 14:05:43 +03:00
|
|
|
blk, errp);
|
2023-12-05 21:20:02 +03:00
|
|
|
bdrv_graph_wrunlock();
|
2017-01-13 21:02:32 +03:00
|
|
|
if (blk->root == NULL) {
|
|
|
|
return -EPERM;
|
|
|
|
}
|
2016-01-29 18:36:03 +03:00
|
|
|
|
|
|
|
notifier_list_notify(&blk->insert_bs_notifiers, blk);
|
2017-11-10 21:54:47 +03:00
|
|
|
if (tgm->throttle_state) {
|
|
|
|
throttle_group_detach_aio_context(tgm);
|
|
|
|
throttle_group_attach_aio_context(tgm, bdrv_get_aio_context(bs));
|
2016-03-22 15:00:08 +03:00
|
|
|
}
|
2017-01-13 21:02:32 +03:00
|
|
|
|
|
|
|
return 0;
|
2015-10-19 18:53:28 +03:00
|
|
|
}
|
|
|
|
|
2021-08-24 11:38:24 +03:00
|
|
|
/*
|
|
|
|
* Change BlockDriverState associated with @blk.
|
|
|
|
*/
|
|
|
|
int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2021-08-24 11:38:24 +03:00
|
|
|
return bdrv_replace_child_bs(blk->root, new_bs, errp);
|
|
|
|
}
|
|
|
|
|
2017-01-20 17:42:39 +03:00
|
|
|
/*
|
|
|
|
* Sets the permission bitmasks that the user of the BlockBackend needs.
|
|
|
|
*/
|
2023-09-11 12:46:12 +03:00
|
|
|
static int coroutine_mixed_fn GRAPH_RDLOCK
|
|
|
|
blk_set_perm_locked(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
|
|
|
|
Error **errp)
|
2017-01-20 17:42:39 +03:00
|
|
|
{
|
|
|
|
int ret;
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-01-20 17:42:39 +03:00
|
|
|
|
2017-04-04 18:29:03 +03:00
|
|
|
if (blk->root && !blk->disable_perm) {
|
2017-01-20 17:42:39 +03:00
|
|
|
ret = bdrv_child_try_set_perm(blk->root, perm, shared_perm, errp);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
blk->perm = perm;
|
|
|
|
blk->shared_perm = shared_perm;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-09-11 12:46:12 +03:00
|
|
|
int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
|
|
|
|
|
|
|
return blk_set_perm_locked(blk, perm, shared_perm, errp);
|
|
|
|
}
|
|
|
|
|
2017-02-10 18:24:56 +03:00
|
|
|
void blk_get_perm(BlockBackend *blk, uint64_t *perm, uint64_t *shared_perm)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-02-10 18:24:56 +03:00
|
|
|
*perm = blk->perm;
|
|
|
|
*shared_perm = blk->shared_perm;
|
|
|
|
}
|
|
|
|
|
2019-01-23 11:56:01 +03:00
|
|
|
/*
|
|
|
|
* Attach device model @dev to @blk.
|
|
|
|
* Return 0 on success, -EBUSY when a device model is attached already.
|
|
|
|
*/
|
|
|
|
int blk_attach_dev(BlockBackend *blk, DeviceState *dev)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
if (blk->dev) {
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
2017-04-04 18:29:03 +03:00
|
|
|
|
|
|
|
/* While migration is still incoming, we don't need to apply the
|
|
|
|
* permissions of guest device BlockBackends. We might still have a block
|
|
|
|
* job or NBD server writing to the image for storage migration. */
|
|
|
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
|
|
|
blk->disable_perm = true;
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:26 +04:00
|
|
|
blk_ref(blk);
|
2014-10-07 15:59:25 +04:00
|
|
|
blk->dev = dev;
|
2015-10-19 18:53:22 +03:00
|
|
|
blk_iostatus_reset(blk);
|
2017-04-04 18:29:03 +03:00
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
return 0;
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
/*
|
|
|
|
* Detach device model @dev from @blk.
|
|
|
|
* @dev must be currently attached to @blk.
|
|
|
|
*/
|
2019-01-23 11:56:01 +03:00
|
|
|
void blk_detach_dev(BlockBackend *blk, DeviceState *dev)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2014-10-07 15:59:25 +04:00
|
|
|
assert(blk->dev == dev);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
blk->dev = NULL;
|
|
|
|
blk->dev_ops = NULL;
|
|
|
|
blk->dev_opaque = NULL;
|
2017-01-20 17:42:39 +03:00
|
|
|
blk_set_perm(blk, 0, BLK_PERM_ALL, &error_abort);
|
2014-10-07 15:59:26 +04:00
|
|
|
blk_unref(blk);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
/*
|
|
|
|
* Return the device model attached to @blk if any, else null.
|
|
|
|
*/
|
2019-01-23 11:56:01 +03:00
|
|
|
DeviceState *blk_get_attached_dev(BlockBackend *blk)
|
2014-10-07 15:59:25 +04:00
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
return blk->dev;
|
|
|
|
}
|
|
|
|
|
2016-09-29 19:30:53 +03:00
|
|
|
/* Return the qdev ID, or if no ID is assigned the QOM path, of the block
|
|
|
|
* device attached to the BlockBackend. */
|
2017-07-11 14:26:59 +03:00
|
|
|
char *blk_get_attached_dev_id(BlockBackend *blk)
|
2016-09-29 19:30:53 +03:00
|
|
|
{
|
2019-01-23 11:56:01 +03:00
|
|
|
DeviceState *dev = blk->dev;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-09-29 19:30:53 +03:00
|
|
|
|
|
|
|
if (!dev) {
|
|
|
|
return g_strdup("");
|
|
|
|
} else if (dev->id) {
|
|
|
|
return g_strdup(dev->id);
|
|
|
|
}
|
2018-11-06 00:38:36 +03:00
|
|
|
|
|
|
|
return object_get_canonical_path(OBJECT(dev)) ?: g_strdup("");
|
2016-09-29 19:30:53 +03:00
|
|
|
}
|
|
|
|
|
2016-09-20 14:38:40 +03:00
|
|
|
/*
|
|
|
|
* Return the BlockBackend which has the device model @dev attached if it
|
|
|
|
* exists, else null.
|
|
|
|
*
|
|
|
|
* @dev must not be null.
|
|
|
|
*/
|
|
|
|
BlockBackend *blk_by_dev(void *dev)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = NULL;
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2016-09-20 14:38:40 +03:00
|
|
|
assert(dev != NULL);
|
|
|
|
while ((blk = blk_all_next(blk)) != NULL) {
|
|
|
|
if (blk->dev == dev) {
|
|
|
|
return blk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
/*
|
|
|
|
* Set @blk's device model callbacks to @ops.
|
|
|
|
* @opaque is the opaque argument to pass to the callbacks.
|
|
|
|
* This is for use by device models.
|
|
|
|
*/
|
|
|
|
void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
|
|
|
|
void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
blk->dev_ops = ops;
|
|
|
|
blk->dev_opaque = opaque;
|
2017-03-17 00:23:50 +03:00
|
|
|
|
|
|
|
/* Are we currently quiesced? Should we enforce this right now? */
|
2023-03-08 00:04:25 +03:00
|
|
|
if (qatomic_read(&blk->quiesce_counter) && ops && ops->drained_begin) {
|
2017-03-17 00:23:50 +03:00
|
|
|
ops->drained_begin(opaque);
|
|
|
|
}
|
2014-10-07 15:59:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Notify @blk's attached device model of media change.
|
2017-01-24 16:21:41 +03:00
|
|
|
*
|
|
|
|
* If @load is true, notify of media load. This action can fail, meaning that
|
|
|
|
* the medium cannot be loaded. @errp is set then.
|
|
|
|
*
|
|
|
|
* If @load is false, notify of media eject. This can never fail.
|
|
|
|
*
|
2014-10-07 15:59:25 +04:00
|
|
|
* Also send DEVICE_TRAY_MOVED events as appropriate.
|
|
|
|
*/
|
2017-01-24 16:21:41 +03:00
|
|
|
void blk_dev_change_media_cb(BlockBackend *blk, bool load, Error **errp)
|
2014-10-07 15:59:25 +04:00
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
if (blk->dev_ops && blk->dev_ops->change_media_cb) {
|
2015-10-26 23:39:14 +03:00
|
|
|
bool tray_was_open, tray_is_open;
|
2017-01-24 16:21:41 +03:00
|
|
|
Error *local_err = NULL;
|
2014-10-07 15:59:25 +04:00
|
|
|
|
2015-10-26 23:39:14 +03:00
|
|
|
tray_was_open = blk_dev_is_tray_open(blk);
|
2017-01-24 16:21:41 +03:00
|
|
|
blk->dev_ops->change_media_cb(blk->dev_opaque, load, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
assert(load == true);
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
|
|
|
}
|
2015-10-26 23:39:14 +03:00
|
|
|
tray_is_open = blk_dev_is_tray_open(blk);
|
|
|
|
|
|
|
|
if (tray_was_open != tray_is_open) {
|
2016-09-29 19:30:53 +03:00
|
|
|
char *id = blk_get_attached_dev_id(blk);
|
2018-08-15 16:37:37 +03:00
|
|
|
qapi_event_send_device_tray_moved(blk_name(blk), id, tray_is_open);
|
2016-09-29 19:30:53 +03:00
|
|
|
g_free(id);
|
2014-10-07 15:59:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-24 17:13:35 +03:00
|
|
|
static void blk_root_change_media(BdrvChild *child, bool load)
|
|
|
|
{
|
2017-01-24 16:21:41 +03:00
|
|
|
blk_dev_change_media_cb(child->opaque, load, NULL);
|
2016-02-24 17:13:35 +03:00
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
/*
|
|
|
|
* Does @blk's attached device model have removable media?
|
|
|
|
* %true if no device model is attached.
|
|
|
|
*/
|
|
|
|
bool blk_dev_has_removable_media(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:57 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
|
|
|
|
}
|
|
|
|
|
2016-01-29 22:49:10 +03:00
|
|
|
/*
|
|
|
|
* Does @blk's attached device model have a tray?
|
|
|
|
*/
|
|
|
|
bool blk_dev_has_tray(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:58 +03:00
|
|
|
IO_CODE();
|
2016-01-29 22:49:10 +03:00
|
|
|
return blk->dev_ops && blk->dev_ops->is_tray_open;
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
/*
|
|
|
|
* Notify @blk's attached device model of a media eject request.
|
|
|
|
* If @force is true, the medium is about to be yanked out forcefully.
|
|
|
|
*/
|
|
|
|
void blk_dev_eject_request(BlockBackend *blk, bool force)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:15:57 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
if (blk->dev_ops && blk->dev_ops->eject_request_cb) {
|
|
|
|
blk->dev_ops->eject_request_cb(blk->dev_opaque, force);
|
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
/*
|
|
|
|
* Does @blk's attached device model have a tray, and is it open?
|
|
|
|
*/
|
|
|
|
bool blk_dev_is_tray_open(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:15:58 +03:00
|
|
|
IO_CODE();
|
2016-01-29 22:49:10 +03:00
|
|
|
if (blk_dev_has_tray(blk)) {
|
2014-10-07 15:59:25 +04:00
|
|
|
return blk->dev_ops->is_tray_open(blk->dev_opaque);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Does @blk's attached device model have the medium locked?
|
|
|
|
* %false if the device model has no such lock.
|
|
|
|
*/
|
|
|
|
bool blk_dev_is_medium_locked(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:57 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:25 +04:00
|
|
|
if (blk->dev_ops && blk->dev_ops->is_medium_locked) {
|
|
|
|
return blk->dev_ops->is_medium_locked(blk->dev_opaque);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Notify @blk's attached device model of a backend size change.
|
|
|
|
*/
|
2016-02-24 17:13:35 +03:00
|
|
|
static void blk_root_resize(BdrvChild *child)
|
2014-10-07 15:59:25 +04:00
|
|
|
{
|
2016-02-24 17:13:35 +03:00
|
|
|
BlockBackend *blk = child->opaque;
|
|
|
|
|
2014-10-07 15:59:25 +04:00
|
|
|
if (blk->dev_ops && blk->dev_ops->resize_cb) {
|
|
|
|
blk->dev_ops->resize_cb(blk->dev_opaque);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void blk_iostatus_enable(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
blk->iostatus_enabled = true;
|
|
|
|
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The I/O status is only enabled if the drive explicitly
|
|
|
|
* enables it _and_ the VM is configured to stop on errors */
|
|
|
|
bool blk_iostatus_is_enabled(const BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
return (blk->iostatus_enabled &&
|
|
|
|
(blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
|
|
|
|
blk->on_write_error == BLOCKDEV_ON_ERROR_STOP ||
|
|
|
|
blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
return blk->iostatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
void blk_iostatus_disable(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
blk->iostatus_enabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void blk_iostatus_reset(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
if (blk_iostatus_is_enabled(blk)) {
|
|
|
|
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void blk_iostatus_set_err(BlockBackend *blk, int error)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
assert(blk_iostatus_is_enabled(blk));
|
|
|
|
if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
|
|
|
|
blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
|
|
|
|
BLOCK_DEVICE_IO_STATUS_FAILED;
|
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2016-03-08 18:39:49 +03:00
|
|
|
void blk_set_allow_write_beyond_eof(BlockBackend *blk, bool allow)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-08 18:39:49 +03:00
|
|
|
blk->allow_write_beyond_eof = allow;
|
|
|
|
}
|
|
|
|
|
2019-05-06 20:18:02 +03:00
|
|
|
void blk_set_allow_aio_context_change(BlockBackend *blk, bool allow)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2019-05-06 20:18:02 +03:00
|
|
|
blk->allow_aio_context_change = allow;
|
|
|
|
}
|
|
|
|
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
void blk_set_disable_request_queuing(BlockBackend *blk, bool disable)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-03-08 00:04:26 +03:00
|
|
|
qatomic_set(&blk->disable_request_queuing, disable);
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
}
|
|
|
|
|
2023-02-03 18:21:57 +03:00
|
|
|
static int coroutine_fn GRAPH_RDLOCK
|
|
|
|
blk_check_byte_request(BlockBackend *blk, int64_t offset, int64_t bytes)
|
2015-02-05 21:58:23 +03:00
|
|
|
{
|
|
|
|
int64_t len;
|
|
|
|
|
2021-10-06 16:17:18 +03:00
|
|
|
if (bytes < 0) {
|
2015-02-05 21:58:23 +03:00
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
2023-02-03 18:21:57 +03:00
|
|
|
if (!blk_co_is_available(blk)) {
|
2015-02-05 21:58:23 +03:00
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset < 0) {
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
2016-03-08 18:39:49 +03:00
|
|
|
if (!blk->allow_write_beyond_eof) {
|
2023-01-13 23:42:06 +03:00
|
|
|
len = bdrv_co_getlength(blk_bs(blk));
|
2016-03-08 18:39:49 +03:00
|
|
|
if (len < 0) {
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2021-10-06 16:17:07 +03:00
|
|
|
if (offset > len || len - offset < bytes) {
|
2016-03-08 18:39:49 +03:00
|
|
|
return -EIO;
|
|
|
|
}
|
2015-02-05 21:58:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-05-16 22:02:27 +03:00
|
|
|
/* Are we currently in a drained section? */
|
|
|
|
bool blk_in_drain(BlockBackend *blk)
|
|
|
|
{
|
|
|
|
GLOBAL_STATE_CODE(); /* change to IO_OR_GS_CODE(), if necessary */
|
|
|
|
return qatomic_read(&blk->quiesce_counter);
|
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:59 +03:00
|
|
|
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
|
|
|
|
{
|
2020-04-07 15:12:59 +03:00
|
|
|
assert(blk->in_flight > 0);
|
|
|
|
|
2023-03-08 00:04:26 +03:00
|
|
|
if (qatomic_read(&blk->quiesce_counter) &&
|
|
|
|
!qatomic_read(&blk->disable_request_queuing)) {
|
2023-03-08 00:04:27 +03:00
|
|
|
/*
|
|
|
|
* Take lock before decrementing in flight counter so main loop thread
|
|
|
|
* waits for us to enqueue ourselves before it can leave the drained
|
|
|
|
* section.
|
|
|
|
*/
|
|
|
|
qemu_mutex_lock(&blk->queued_requests_lock);
|
2020-04-07 15:12:59 +03:00
|
|
|
blk_dec_in_flight(blk);
|
2023-03-08 00:04:27 +03:00
|
|
|
qemu_co_queue_wait(&blk->queued_requests, &blk->queued_requests_lock);
|
2020-04-07 15:12:59 +03:00
|
|
|
blk_inc_in_flight(blk);
|
2023-03-08 00:04:27 +03:00
|
|
|
qemu_mutex_unlock(&blk->queued_requests_lock);
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:58 +03:00
|
|
|
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
2022-07-05 19:15:16 +03:00
|
|
|
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)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2016-04-14 17:40:16 +03:00
|
|
|
int ret;
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
BlockDriverState *bs;
|
2022-03-03 18:16:09 +03:00
|
|
|
IO_CODE();
|
2016-04-14 17:40:16 +03:00
|
|
|
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
blk_wait_while_drained(blk);
|
2023-02-03 18:21:50 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2016-04-14 17:40:16 +03:00
|
|
|
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
/* Call blk_bs() only after waiting, the graph may have changed */
|
|
|
|
bs = blk_bs(blk);
|
2016-10-27 13:48:52 +03:00
|
|
|
trace_blk_co_preadv(blk, bs, offset, bytes, flags);
|
2016-04-14 17:40:16 +03:00
|
|
|
|
|
|
|
ret = blk_check_byte_request(blk, offset, bytes);
|
2015-02-05 21:58:23 +03:00
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-27 13:48:52 +03:00
|
|
|
bdrv_inc_in_flight(bs);
|
|
|
|
|
2016-03-21 15:30:30 +03:00
|
|
|
/* throttling disk I/O */
|
2017-08-25 16:20:23 +03:00
|
|
|
if (blk->public.throttle_group_member.throttle_state) {
|
|
|
|
throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
|
block/throttle-groups: Use ThrottleDirection instread of bool is_write
'bool is_write' style is obsolete from throttle framework, adapt
block throttle groups to the new style:
- use ThrottleDirection instead of 'bool is_write'. Ex,
schedule_next_request(ThrottleGroupMember *tgm, bool is_write)
-> schedule_next_request(ThrottleGroupMember *tgm, ThrottleDirection direction)
- use THROTTLE_MAX instead of hard code. Ex, ThrottleGroupMember *tokens[2]
-> ThrottleGroupMember *tokens[THROTTLE_MAX]
- use ThrottleDirection instead of hard code on iteration. Ex, (i = 0; i < 2; i++)
-> for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++)
Use a simple python script to test the new style:
#!/usr/bin/python3
import subprocess
import random
import time
commands = ['virsh blkdeviotune jammy vda --write-bytes-sec ', \
'virsh blkdeviotune jammy vda --write-iops-sec ', \
'virsh blkdeviotune jammy vda --read-bytes-sec ', \
'virsh blkdeviotune jammy vda --read-iops-sec ']
for loop in range(1, 1000):
time.sleep(random.randrange(3, 5))
command = commands[random.randrange(0, 3)] + str(random.randrange(0, 1000000))
subprocess.run(command, shell=True, check=True)
This works fine.
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
Message-Id: <20230728022006.1098509-10-pizhenwei@bytedance.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
2023-07-28 05:20:06 +03:00
|
|
|
bytes, THROTTLE_READ);
|
2016-03-21 15:30:30 +03:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:16 +03:00
|
|
|
ret = bdrv_co_preadv_part(blk->root, offset, bytes, qiov, qiov_offset,
|
|
|
|
flags);
|
2016-10-27 13:48:52 +03:00
|
|
|
bdrv_dec_in_flight(bs);
|
|
|
|
return ret;
|
2016-03-08 15:47:47 +03:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:25 +03:00
|
|
|
int coroutine_fn blk_co_pread(BlockBackend *blk, int64_t offset, int64_t bytes,
|
|
|
|
void *buf, BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
|
|
|
IO_OR_GS_CODE();
|
|
|
|
|
|
|
|
assert(bytes <= SIZE_MAX);
|
|
|
|
|
|
|
|
return blk_co_preadv(blk, offset, bytes, &qiov, flags);
|
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:58 +03:00
|
|
|
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
|
2021-10-06 16:17:08 +03:00
|
|
|
int64_t bytes, QEMUIOVector *qiov,
|
2020-04-07 15:12:58 +03:00
|
|
|
BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
int ret;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2020-04-07 15:12:58 +03:00
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
2022-07-05 19:15:16 +03:00
|
|
|
ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, 0, flags);
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
|
|
|
|
int64_t bytes, QEMUIOVector *qiov,
|
|
|
|
size_t qiov_offset, BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
IO_OR_GS_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
|
|
|
ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, qiov_offset, flags);
|
2020-04-07 15:12:58 +03:00
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
2022-07-05 19:15:26 +03:00
|
|
|
static int coroutine_fn
|
2021-10-06 16:17:11 +03:00
|
|
|
blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
|
|
|
|
QEMUIOVector *qiov, size_t qiov_offset,
|
|
|
|
BdrvRequestFlags flags)
|
2016-03-08 15:47:48 +03:00
|
|
|
{
|
2016-03-04 16:28:01 +03:00
|
|
|
int ret;
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
BlockDriverState *bs;
|
2022-03-03 18:16:09 +03:00
|
|
|
IO_CODE();
|
2016-03-04 16:28:01 +03:00
|
|
|
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
blk_wait_while_drained(blk);
|
2023-02-03 18:21:50 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2016-03-04 16:28:01 +03:00
|
|
|
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
/* Call blk_bs() only after waiting, the graph may have changed */
|
|
|
|
bs = blk_bs(blk);
|
2016-10-27 13:48:52 +03:00
|
|
|
trace_blk_co_pwritev(blk, bs, offset, bytes, flags);
|
2016-04-14 17:40:16 +03:00
|
|
|
|
2016-03-04 16:28:01 +03:00
|
|
|
ret = blk_check_byte_request(blk, offset, bytes);
|
2016-03-08 15:47:48 +03:00
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-27 13:48:52 +03:00
|
|
|
bdrv_inc_in_flight(bs);
|
2016-03-21 15:30:30 +03:00
|
|
|
/* throttling disk I/O */
|
2017-08-25 16:20:23 +03:00
|
|
|
if (blk->public.throttle_group_member.throttle_state) {
|
|
|
|
throttle_group_co_io_limits_intercept(&blk->public.throttle_group_member,
|
block/throttle-groups: Use ThrottleDirection instread of bool is_write
'bool is_write' style is obsolete from throttle framework, adapt
block throttle groups to the new style:
- use ThrottleDirection instead of 'bool is_write'. Ex,
schedule_next_request(ThrottleGroupMember *tgm, bool is_write)
-> schedule_next_request(ThrottleGroupMember *tgm, ThrottleDirection direction)
- use THROTTLE_MAX instead of hard code. Ex, ThrottleGroupMember *tokens[2]
-> ThrottleGroupMember *tokens[THROTTLE_MAX]
- use ThrottleDirection instead of hard code on iteration. Ex, (i = 0; i < 2; i++)
-> for (dir = THROTTLE_READ; dir < THROTTLE_MAX; dir++)
Use a simple python script to test the new style:
#!/usr/bin/python3
import subprocess
import random
import time
commands = ['virsh blkdeviotune jammy vda --write-bytes-sec ', \
'virsh blkdeviotune jammy vda --write-iops-sec ', \
'virsh blkdeviotune jammy vda --read-bytes-sec ', \
'virsh blkdeviotune jammy vda --read-iops-sec ']
for loop in range(1, 1000):
time.sleep(random.randrange(3, 5))
command = commands[random.randrange(0, 3)] + str(random.randrange(0, 1000000))
subprocess.run(command, shell=True, check=True)
This works fine.
Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
Message-Id: <20230728022006.1098509-10-pizhenwei@bytedance.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
2023-07-28 05:20:06 +03:00
|
|
|
bytes, THROTTLE_WRITE);
|
2016-03-21 15:30:30 +03:00
|
|
|
}
|
|
|
|
|
2016-03-04 16:28:01 +03:00
|
|
|
if (!blk->enable_write_cache) {
|
|
|
|
flags |= BDRV_REQ_FUA;
|
|
|
|
}
|
|
|
|
|
2019-10-11 12:07:09 +03:00
|
|
|
ret = bdrv_co_pwritev_part(blk->root, offset, bytes, qiov, qiov_offset,
|
|
|
|
flags);
|
2016-10-27 13:48:52 +03:00
|
|
|
bdrv_dec_in_flight(bs);
|
|
|
|
return ret;
|
2016-03-08 15:47:48 +03:00
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:58 +03:00
|
|
|
int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
|
2021-10-06 16:17:09 +03:00
|
|
|
int64_t bytes,
|
2020-04-07 15:12:58 +03:00
|
|
|
QEMUIOVector *qiov, size_t qiov_offset,
|
|
|
|
BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
int ret;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2020-04-07 15:12:58 +03:00
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
2021-10-06 16:17:11 +03:00
|
|
|
ret = blk_co_do_pwritev_part(blk, offset, bytes, qiov, qiov_offset, flags);
|
2020-04-07 15:12:58 +03:00
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:25 +03:00
|
|
|
int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
|
|
|
|
const void *buf, BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
|
|
|
IO_OR_GS_CODE();
|
|
|
|
|
|
|
|
assert(bytes <= SIZE_MAX);
|
|
|
|
|
|
|
|
return blk_co_pwritev(blk, offset, bytes, &qiov, flags);
|
|
|
|
}
|
|
|
|
|
2019-10-11 12:07:09 +03:00
|
|
|
int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
|
2021-10-06 16:17:09 +03:00
|
|
|
int64_t bytes, QEMUIOVector *qiov,
|
2019-10-11 12:07:09 +03:00
|
|
|
BdrvRequestFlags flags)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2019-10-11 12:07:09 +03:00
|
|
|
return blk_co_pwritev_part(blk, offset, bytes, qiov, 0, flags);
|
|
|
|
}
|
|
|
|
|
2022-11-28 17:23:27 +03:00
|
|
|
int coroutine_fn blk_co_block_status_above(BlockBackend *blk,
|
|
|
|
BlockDriverState *base,
|
|
|
|
int64_t offset, int64_t bytes,
|
|
|
|
int64_t *pnum, int64_t *map,
|
|
|
|
BlockDriverState **file)
|
|
|
|
{
|
|
|
|
IO_CODE();
|
2023-02-03 18:21:43 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2022-11-28 17:23:27 +03:00
|
|
|
return bdrv_co_block_status_above(blk_bs(blk), base, offset, bytes, pnum,
|
|
|
|
map, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
int coroutine_fn blk_co_is_allocated_above(BlockBackend *blk,
|
|
|
|
BlockDriverState *base,
|
|
|
|
bool include_base, int64_t offset,
|
|
|
|
int64_t bytes, int64_t *pnum)
|
|
|
|
{
|
|
|
|
IO_CODE();
|
2023-02-03 18:21:43 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2022-11-28 17:23:27 +03:00
|
|
|
return bdrv_co_is_allocated_above(blk_bs(blk), base, include_base, offset,
|
|
|
|
bytes, pnum);
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:47 +03:00
|
|
|
typedef struct BlkRwCo {
|
|
|
|
BlockBackend *blk;
|
|
|
|
int64_t offset;
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
void *iobuf;
|
2016-03-08 15:47:47 +03:00
|
|
|
int ret;
|
|
|
|
BdrvRequestFlags flags;
|
|
|
|
} BlkRwCo;
|
|
|
|
|
2016-06-16 16:13:15 +03:00
|
|
|
int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-06-16 16:13:15 +03:00
|
|
|
return bdrv_make_zero(blk->root, flags);
|
|
|
|
}
|
|
|
|
|
2019-02-14 20:42:44 +03:00
|
|
|
void blk_inc_in_flight(BlockBackend *blk)
|
2018-02-16 19:50:13 +03:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2020-09-23 13:56:46 +03:00
|
|
|
qatomic_inc(&blk->in_flight);
|
2018-02-16 19:50:13 +03:00
|
|
|
}
|
|
|
|
|
2019-02-14 20:42:44 +03:00
|
|
|
void blk_dec_in_flight(BlockBackend *blk)
|
2018-02-16 19:50:13 +03:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2020-09-23 13:56:46 +03:00
|
|
|
qatomic_dec(&blk->in_flight);
|
2018-09-18 18:09:16 +03:00
|
|
|
aio_wait_kick();
|
2018-02-16 19:50:13 +03:00
|
|
|
}
|
|
|
|
|
2015-02-05 21:58:23 +03:00
|
|
|
static void error_callback_bh(void *opaque)
|
|
|
|
{
|
|
|
|
struct BlockBackendAIOCB *acb = opaque;
|
2016-10-27 13:48:52 +03:00
|
|
|
|
2018-02-16 19:50:13 +03:00
|
|
|
blk_dec_in_flight(acb->blk);
|
2015-02-05 21:58:23 +03:00
|
|
|
acb->common.cb(acb->common.opaque, acb->ret);
|
|
|
|
qemu_aio_unref(acb);
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:06:21 +03:00
|
|
|
BlockAIOCB *blk_abort_aio_request(BlockBackend *blk,
|
|
|
|
BlockCompletionFunc *cb,
|
|
|
|
void *opaque, int ret)
|
2015-02-05 21:58:23 +03:00
|
|
|
{
|
|
|
|
struct BlockBackendAIOCB *acb;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-02-05 21:58:23 +03:00
|
|
|
|
2018-02-16 19:50:13 +03:00
|
|
|
blk_inc_in_flight(blk);
|
2015-02-05 21:58:23 +03:00
|
|
|
acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
|
2015-10-19 18:53:18 +03:00
|
|
|
acb->blk = blk;
|
2015-02-05 21:58:23 +03:00
|
|
|
acb->ret = ret;
|
|
|
|
|
2023-09-13 02:10:35 +03:00
|
|
|
replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
|
2019-09-17 14:58:19 +03:00
|
|
|
error_callback_bh, acb);
|
2015-02-05 21:58:23 +03:00
|
|
|
return &acb->common;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:52 +03:00
|
|
|
typedef struct BlkAioEmAIOCB {
|
|
|
|
BlockAIOCB common;
|
|
|
|
BlkRwCo rwco;
|
2021-10-06 16:17:16 +03:00
|
|
|
int64_t bytes;
|
2016-03-08 15:47:52 +03:00
|
|
|
bool has_returned;
|
|
|
|
} BlkAioEmAIOCB;
|
|
|
|
|
|
|
|
static const AIOCBInfo blk_aio_em_aiocb_info = {
|
|
|
|
.aiocb_size = sizeof(BlkAioEmAIOCB),
|
|
|
|
};
|
|
|
|
|
|
|
|
static void blk_aio_complete(BlkAioEmAIOCB *acb)
|
|
|
|
{
|
|
|
|
if (acb->has_returned) {
|
|
|
|
acb->common.cb(acb->common.opaque, acb->rwco.ret);
|
2018-09-06 18:47:22 +03:00
|
|
|
blk_dec_in_flight(acb->rwco.blk);
|
2016-03-08 15:47:52 +03:00
|
|
|
qemu_aio_unref(acb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void blk_aio_complete_bh(void *opaque)
|
|
|
|
{
|
2016-10-03 19:14:16 +03:00
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
assert(acb->has_returned);
|
|
|
|
blk_aio_complete(acb);
|
2016-03-08 15:47:52 +03:00
|
|
|
}
|
|
|
|
|
2021-10-06 16:17:16 +03:00
|
|
|
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset,
|
|
|
|
int64_t bytes,
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
void *iobuf, CoroutineEntry co_entry,
|
2016-03-08 15:47:52 +03:00
|
|
|
BdrvRequestFlags flags,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb;
|
|
|
|
Coroutine *co;
|
|
|
|
|
2018-02-16 19:50:13 +03:00
|
|
|
blk_inc_in_flight(blk);
|
2016-03-08 15:47:52 +03:00
|
|
|
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
|
|
|
|
acb->rwco = (BlkRwCo) {
|
|
|
|
.blk = blk,
|
|
|
|
.offset = offset,
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
.iobuf = iobuf,
|
2016-03-08 15:47:52 +03:00
|
|
|
.flags = flags,
|
|
|
|
.ret = NOT_DONE,
|
|
|
|
};
|
2016-04-13 13:47:08 +03:00
|
|
|
acb->bytes = bytes;
|
2016-03-08 15:47:52 +03:00
|
|
|
acb->has_returned = false;
|
|
|
|
|
coroutine: move entry argument to qemu_coroutine_create
In practice the entry argument is always known at creation time, and
it is confusing that sometimes qemu_coroutine_enter is used with a
non-NULL argument to re-enter a coroutine (this happens in
block/sheepdog.c and tests/test-coroutine.c). So pass the opaque value
at creation time, for consistency with e.g. aio_bh_new.
Mostly done with the following semantic patch:
@ entry1 @
expression entry, arg, co;
@@
- co = qemu_coroutine_create(entry);
+ co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry2 @
expression entry, arg;
identifier co;
@@
- Coroutine *co = qemu_coroutine_create(entry);
+ Coroutine *co = qemu_coroutine_create(entry, arg);
...
- qemu_coroutine_enter(co, arg);
+ qemu_coroutine_enter(co);
@ entry3 @
expression entry, arg;
@@
- qemu_coroutine_enter(qemu_coroutine_create(entry), arg);
+ qemu_coroutine_enter(qemu_coroutine_create(entry, arg));
@ reentry @
expression co;
@@
- qemu_coroutine_enter(co, NULL);
+ qemu_coroutine_enter(co);
except for the aforementioned few places where the semantic patch
stumbled (as expected) and for test_co_queue, which would otherwise
produce an uninitialized variable warning.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2016-07-04 20:10:01 +03:00
|
|
|
co = qemu_coroutine_create(co_entry, acb);
|
2023-09-13 02:10:35 +03:00
|
|
|
aio_co_enter(qemu_get_current_aio_context(), co);
|
2016-03-08 15:47:52 +03:00
|
|
|
|
|
|
|
acb->has_returned = true;
|
|
|
|
if (acb->rwco.ret != NOT_DONE) {
|
2023-09-13 02:10:35 +03:00
|
|
|
replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
|
2019-09-17 14:58:19 +03:00
|
|
|
blk_aio_complete_bh, acb);
|
2016-03-08 15:47:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return &acb->common;
|
|
|
|
}
|
|
|
|
|
2022-09-22 11:49:00 +03:00
|
|
|
static void coroutine_fn blk_aio_read_entry(void *opaque)
|
2016-03-08 15:47:52 +03:00
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
QEMUIOVector *qiov = rwco->iobuf;
|
2016-03-08 15:47:52 +03:00
|
|
|
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
assert(qiov->size == acb->bytes);
|
2022-07-05 19:15:16 +03:00
|
|
|
rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov,
|
|
|
|
0, rwco->flags);
|
2016-03-08 15:47:52 +03:00
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
2022-09-22 11:49:00 +03:00
|
|
|
static void coroutine_fn blk_aio_write_entry(void *opaque)
|
2016-03-08 15:47:52 +03:00
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
QEMUIOVector *qiov = rwco->iobuf;
|
2016-03-08 15:47:52 +03:00
|
|
|
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
assert(!qiov || qiov->size == acb->bytes);
|
2021-10-06 16:17:11 +03:00
|
|
|
rwco->ret = blk_co_do_pwritev_part(rwco->blk, rwco->offset, acb->bytes,
|
|
|
|
qiov, 0, rwco->flags);
|
2016-03-08 15:47:52 +03:00
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
2016-05-25 01:25:20 +03:00
|
|
|
BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
2021-10-06 16:17:16 +03:00
|
|
|
int64_t bytes, BdrvRequestFlags flags,
|
2016-05-25 01:25:20 +03:00
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2021-10-06 16:17:16 +03:00
|
|
|
return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_write_entry,
|
2016-05-06 19:26:29 +03:00
|
|
|
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2023-01-13 23:42:04 +03:00
|
|
|
int64_t coroutine_fn blk_co_getlength(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:57 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2023-01-13 23:42:04 +03:00
|
|
|
|
2023-02-03 18:21:57 +03:00
|
|
|
if (!blk_co_is_available(blk)) {
|
2015-10-19 18:53:26 +03:00
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2023-01-13 23:42:04 +03:00
|
|
|
return bdrv_co_getlength(blk_bs(blk));
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2023-04-07 18:33:02 +03:00
|
|
|
int64_t coroutine_fn blk_co_nb_sectors(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2023-04-07 18:33:01 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
block/export: Fix graph locking in blk_get_geometry() call
blk_get_geometry() eventually calls bdrv_nb_sectors(), which is a
co_wrapper_mixed_bdrv_rdlock. This means that when it is called from
coroutine context, it already assume to have the graph locked.
However, virtio_blk_sect_range_ok() in block/export/virtio-blk-handler.c
(used by vhost-user-blk and VDUSE exports) runs in a coroutine, but
doesn't take the graph lock - blk_*() functions are generally expected
to do that internally. This causes an assertion failure when accessing
an export for the first time if it runs in an iothread.
This is an example of the crash:
$ ./storage-daemon/qemu-storage-daemon --object iothread,id=th0 --blockdev file,filename=/home/kwolf/images/hd.img,node-name=disk --export vhost-user-blk,addr.type=unix,addr.path=/tmp/vhost.sock,node-name=disk,id=exp0,iothread=th0
qemu-storage-daemon: ../block/graph-lock.c:268: void assert_bdrv_graph_readable(void): Assertion `qemu_in_main_thread() || reader_count()' failed.
(gdb) bt
#0 0x00007ffff6eafe5c in __pthread_kill_implementation () from /lib64/libc.so.6
#1 0x00007ffff6e5fa76 in raise () from /lib64/libc.so.6
#2 0x00007ffff6e497fc in abort () from /lib64/libc.so.6
#3 0x00007ffff6e4971b in __assert_fail_base.cold () from /lib64/libc.so.6
#4 0x00007ffff6e58656 in __assert_fail () from /lib64/libc.so.6
#5 0x00005555556337a3 in assert_bdrv_graph_readable () at ../block/graph-lock.c:268
#6 0x00005555555fd5a2 in bdrv_co_nb_sectors (bs=0x5555564c5ef0) at ../block.c:5847
#7 0x00005555555ee949 in bdrv_nb_sectors (bs=0x5555564c5ef0) at block/block-gen.c:256
#8 0x00005555555fd6b9 in bdrv_get_geometry (bs=0x5555564c5ef0, nb_sectors_ptr=0x7fffef7fedd0) at ../block.c:5884
#9 0x000055555562ad6d in blk_get_geometry (blk=0x5555564cb200, nb_sectors_ptr=0x7fffef7fedd0) at ../block/block-backend.c:1624
#10 0x00005555555ddb74 in virtio_blk_sect_range_ok (blk=0x5555564cb200, block_size=512, sector=0, size=512) at ../block/export/virtio-blk-handler.c:44
#11 0x00005555555dd80d in virtio_blk_process_req (handler=0x5555564cbb98, in_iov=0x7fffe8003830, out_iov=0x7fffe8003860, in_num=1, out_num=0) at ../block/export/virtio-blk-handler.c:189
#12 0x00005555555dd546 in vu_blk_virtio_process_req (opaque=0x7fffe8003800) at ../block/export/vhost-user-blk-server.c:66
#13 0x00005555557bf4a1 in coroutine_trampoline (i0=-402635264, i1=32767) at ../util/coroutine-ucontext.c:177
#14 0x00007ffff6e75c20 in ?? () from /lib64/libc.so.6
#15 0x00007fffefffa870 in ?? ()
#16 0x0000000000000000 in ?? ()
Fix this by creating a new blk_co_get_geometry() that takes the lock,
and changing blk_get_geometry() to be a co_wrapper_mixed around it.
To make the resulting code cleaner, virtio-blk-handler.c can directly
call the coroutine version now (though that wouldn't be necessary for
fixing the bug, taking the lock in blk_co_get_geometry() is what fixes
it).
Fixes: 8ab8140a04cf771d63e9754d6ba6c1e676bfe507
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230327113959.60071-1-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2023-03-27 14:39:59 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
|
|
|
|
2023-04-07 18:33:01 +03:00
|
|
|
if (!bs) {
|
2023-04-07 18:33:02 +03:00
|
|
|
return -ENOMEDIUM;
|
2015-10-19 18:53:27 +03:00
|
|
|
} else {
|
2023-04-07 18:33:02 +03:00
|
|
|
return bdrv_co_nb_sectors(bs);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2023-04-07 18:33:03 +03:00
|
|
|
/*
|
|
|
|
* This wrapper is written by hand because this function is in the hot I/O path,
|
|
|
|
* via blk_get_geometry.
|
|
|
|
*/
|
|
|
|
int64_t coroutine_mixed_fn blk_nb_sectors(BlockBackend *blk)
|
|
|
|
{
|
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
if (!bs) {
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
} else {
|
|
|
|
return bdrv_nb_sectors(bs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-07 18:33:02 +03:00
|
|
|
/* return 0 as number of sectors if no device present or error */
|
|
|
|
void coroutine_fn blk_co_get_geometry(BlockBackend *blk,
|
|
|
|
uint64_t *nb_sectors_ptr)
|
2015-02-05 21:58:10 +03:00
|
|
|
{
|
2023-04-07 18:33:02 +03:00
|
|
|
int64_t ret = blk_co_nb_sectors(blk);
|
|
|
|
*nb_sectors_ptr = ret < 0 ? 0 : ret;
|
2015-02-05 21:58:10 +03:00
|
|
|
}
|
|
|
|
|
2023-04-07 18:33:03 +03:00
|
|
|
/*
|
|
|
|
* This wrapper is written by hand because this function is in the hot I/O path.
|
|
|
|
*/
|
|
|
|
void coroutine_mixed_fn blk_get_geometry(BlockBackend *blk,
|
|
|
|
uint64_t *nb_sectors_ptr)
|
|
|
|
{
|
|
|
|
int64_t ret = blk_nb_sectors(blk);
|
|
|
|
*nb_sectors_ptr = ret < 0 ? 0 : ret;
|
|
|
|
}
|
|
|
|
|
2016-05-06 19:26:30 +03:00
|
|
|
BlockAIOCB *blk_aio_preadv(BlockBackend *blk, int64_t offset,
|
|
|
|
QEMUIOVector *qiov, BdrvRequestFlags flags,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2021-10-06 16:17:16 +03:00
|
|
|
assert((uint64_t)qiov->size <= INT64_MAX);
|
2016-05-06 19:26:30 +03:00
|
|
|
return blk_aio_prwv(blk, offset, qiov->size, qiov,
|
|
|
|
blk_aio_read_entry, flags, cb, opaque);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
|
|
|
|
QEMUIOVector *qiov, BdrvRequestFlags flags,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2021-10-26 12:07:45 +03:00
|
|
|
assert((uint64_t)qiov->size <= INT64_MAX);
|
2016-05-06 19:26:30 +03:00
|
|
|
return blk_aio_prwv(blk, offset, qiov->size, qiov,
|
|
|
|
blk_aio_write_entry, flags, cb, opaque);
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:18 +04:00
|
|
|
void blk_aio_cancel(BlockAIOCB *acb)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2014-10-07 15:59:18 +04:00
|
|
|
bdrv_aio_cancel(acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void blk_aio_cancel_async(BlockAIOCB *acb)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2014-10-07 15:59:18 +04:00
|
|
|
bdrv_aio_cancel_async(acb);
|
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:58 +03:00
|
|
|
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
2022-07-05 19:15:23 +03:00
|
|
|
static int coroutine_fn
|
2021-10-06 16:17:11 +03:00
|
|
|
blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:16:09 +03:00
|
|
|
IO_CODE();
|
|
|
|
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
blk_wait_while_drained(blk);
|
2023-02-03 18:21:44 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
|
2023-02-03 18:21:57 +03:00
|
|
|
if (!blk_co_is_available(blk)) {
|
2015-10-19 18:53:26 +03:00
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2016-10-20 13:56:14 +03:00
|
|
|
return bdrv_co_ioctl(blk_bs(blk), req, buf);
|
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:23 +03:00
|
|
|
int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
|
|
|
|
void *buf)
|
2016-10-20 13:56:14 +03:00
|
|
|
{
|
2021-10-06 16:17:13 +03:00
|
|
|
int ret;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
|
2021-10-06 16:17:13 +03:00
|
|
|
blk_inc_in_flight(blk);
|
2022-07-05 19:15:23 +03:00
|
|
|
ret = blk_co_do_ioctl(blk, req, buf);
|
2021-10-06 16:17:13 +03:00
|
|
|
blk_dec_in_flight(blk);
|
2016-10-20 13:56:14 +03:00
|
|
|
|
2021-10-06 16:17:13 +03:00
|
|
|
return ret;
|
2016-10-20 13:56:14 +03:00
|
|
|
}
|
|
|
|
|
2022-09-22 11:49:00 +03:00
|
|
|
static void coroutine_fn blk_aio_ioctl_entry(void *opaque)
|
2016-10-20 13:56:14 +03:00
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
|
|
|
|
2021-10-06 16:17:11 +03:00
|
|
|
rwco->ret = blk_co_do_ioctl(rwco->blk, rwco->offset, rwco->iobuf);
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
|
2016-10-20 13:56:14 +03:00
|
|
|
blk_aio_complete(acb);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
block: Fix qemu crash when using scsi-block
Starting qemu with the following arguments causes qemu to segfault:
... -device lsi,id=lsi0 -drive file=iscsi:<...>,format=raw,if=none,node-name=
iscsi1 -device scsi-block,bus=lsi0.0,id=<...>,drive=iscsi1
This patch fixes blk_aio_ioctl() so it does not pass stack addresses to
blk_aio_ioctl_entry() which may be invoked after blk_aio_ioctl() returns. More
details about the bug follow.
blk_aio_ioctl() invokes blk_aio_prwv() with blk_aio_ioctl_entry as the
coroutine parameter. blk_aio_prwv() ultimately calls aio_co_enter().
When blk_aio_ioctl() is executed from within a coroutine context (e.g.
iscsi_bh_cb()), aio_co_enter() adds the coroutine (blk_aio_ioctl_entry) to
the current coroutine's wakeup queue. blk_aio_ioctl() then returns.
When blk_aio_ioctl_entry() executes later, it accesses an invalid pointer:
....
BlkRwCo *rwco = &acb->rwco;
rwco->ret = blk_co_ioctl(rwco->blk, rwco->offset,
rwco->qiov->iov[0].iov_base); <--- qiov is
invalid here
...
In the case when blk_aio_ioctl() is called from a non-coroutine context,
blk_aio_ioctl_entry() executes immediately. But if bdrv_co_ioctl() calls
qemu_coroutine_yield(), blk_aio_ioctl() will return. When the coroutine
execution is complete, control returns to blk_aio_ioctl_entry() after the call
to blk_co_ioctl(). There is no invalid reference after this point, but the
function is still holding on to invalid pointers.
The fix is to change blk_aio_prwv() to accept a void pointer for the IO buffer
rather than a QEMUIOVector. blk_aio_prwv() passes this through in BlkRwCo and the
coroutine function casts it to QEMUIOVector or uses the void pointer directly.
Signed-off-by: Deepa Srinivasan <deepa.srinivasan@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-12-16 03:59:13 +03:00
|
|
|
return blk_aio_prwv(blk, req, 0, buf, blk_aio_ioctl_entry, 0, cb, opaque);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:58 +03:00
|
|
|
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
2022-07-05 19:15:26 +03:00
|
|
|
static int coroutine_fn
|
2021-10-06 16:17:11 +03:00
|
|
|
blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
|
2014-11-18 14:21:14 +03:00
|
|
|
{
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
int ret;
|
2022-03-03 18:16:09 +03:00
|
|
|
IO_CODE();
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
|
|
|
|
blk_wait_while_drained(blk);
|
2023-02-03 18:21:47 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
|
|
|
|
ret = blk_check_byte_request(blk, offset, bytes);
|
2015-02-05 21:58:23 +03:00
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-07-10 09:31:17 +03:00
|
|
|
return bdrv_co_pdiscard(blk->root, offset, bytes);
|
2014-11-18 14:21:14 +03:00
|
|
|
}
|
|
|
|
|
2022-09-22 11:49:00 +03:00
|
|
|
static void coroutine_fn blk_aio_pdiscard_entry(void *opaque)
|
2020-04-07 15:12:57 +03:00
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
|
|
|
|
2021-10-06 16:17:11 +03:00
|
|
|
rwco->ret = blk_co_do_pdiscard(rwco->blk, rwco->offset, acb->bytes);
|
2020-04-07 15:12:57 +03:00
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk,
|
2021-10-06 16:17:16 +03:00
|
|
|
int64_t offset, int64_t bytes,
|
2020-04-07 15:12:57 +03:00
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2020-04-07 15:12:57 +03:00
|
|
|
return blk_aio_prwv(blk, offset, bytes, NULL, blk_aio_pdiscard_entry, 0,
|
|
|
|
cb, opaque);
|
|
|
|
}
|
|
|
|
|
2021-10-06 16:17:10 +03:00
|
|
|
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
|
|
|
|
int64_t bytes)
|
2020-04-07 15:12:58 +03:00
|
|
|
{
|
|
|
|
int ret;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2020-04-07 15:12:58 +03:00
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
2021-10-06 16:17:11 +03:00
|
|
|
ret = blk_co_do_pdiscard(blk, offset, bytes);
|
2020-04-07 15:12:58 +03:00
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
|
2022-07-05 19:15:26 +03:00
|
|
|
static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
|
2014-11-18 14:21:14 +03:00
|
|
|
{
|
2022-03-03 18:16:09 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:46 +03:00
|
|
|
blk_wait_while_drained(blk);
|
|
|
|
GRAPH_RDLOCK_GUARD();
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
|
2023-02-03 18:21:57 +03:00
|
|
|
if (!blk_co_is_available(blk)) {
|
2015-10-19 18:53:26 +03:00
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
return bdrv_co_flush(blk_bs(blk));
|
2014-11-18 14:21:14 +03:00
|
|
|
}
|
|
|
|
|
2022-09-22 11:49:00 +03:00
|
|
|
static void coroutine_fn blk_aio_flush_entry(void *opaque)
|
2020-04-07 15:12:57 +03:00
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
|
|
|
|
2021-10-06 16:17:11 +03:00
|
|
|
rwco->ret = blk_co_do_flush(rwco->blk);
|
2020-04-07 15:12:57 +03:00
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_flush(BlockBackend *blk,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2020-04-07 15:12:57 +03:00
|
|
|
return blk_aio_prwv(blk, 0, 0, NULL, blk_aio_flush_entry, 0, cb, opaque);
|
|
|
|
}
|
|
|
|
|
2020-04-07 15:12:58 +03:00
|
|
|
int coroutine_fn blk_co_flush(BlockBackend *blk)
|
|
|
|
{
|
|
|
|
int ret;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2020-04-07 15:12:58 +03:00
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
2021-10-06 16:17:11 +03:00
|
|
|
ret = blk_co_do_flush(blk);
|
2020-04-07 15:12:58 +03:00
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only
for zoned host block devices. By adding zone management operations to the
host_block_device BlockDriver, users can use the new block layer APIs
including Report Zone and four zone management operations
(open, close, finish, reset, reset_all).
Qemu-io uses the new APIs to perform zoned storage commands of the device:
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
zone_finish(zf).
For example, to test zone_report, use following command:
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
-c "zrp offset nr_zones"
Signed-off-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20230508045533.175575-4-faithilikerun@gmail.com
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
<philmd@linaro.org> and remove spurious ret = -errno in
raw_co_zone_mgmt().
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-05-08 07:55:28 +03:00
|
|
|
static void coroutine_fn blk_aio_zone_report_entry(void *opaque)
|
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
|
|
|
|
|
|
|
rwco->ret = blk_co_zone_report(rwco->blk, rwco->offset,
|
|
|
|
(unsigned int*)(uintptr_t)acb->bytes,
|
|
|
|
rwco->iobuf);
|
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_zone_report(BlockBackend *blk, int64_t offset,
|
|
|
|
unsigned int *nr_zones,
|
|
|
|
BlockZoneDescriptor *zones,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb;
|
|
|
|
Coroutine *co;
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
|
|
|
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
|
|
|
|
acb->rwco = (BlkRwCo) {
|
|
|
|
.blk = blk,
|
|
|
|
.offset = offset,
|
|
|
|
.iobuf = zones,
|
|
|
|
.ret = NOT_DONE,
|
|
|
|
};
|
|
|
|
acb->bytes = (int64_t)(uintptr_t)nr_zones,
|
|
|
|
acb->has_returned = false;
|
|
|
|
|
|
|
|
co = qemu_coroutine_create(blk_aio_zone_report_entry, acb);
|
2023-09-13 02:10:36 +03:00
|
|
|
aio_co_enter(qemu_get_current_aio_context(), co);
|
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only
for zoned host block devices. By adding zone management operations to the
host_block_device BlockDriver, users can use the new block layer APIs
including Report Zone and four zone management operations
(open, close, finish, reset, reset_all).
Qemu-io uses the new APIs to perform zoned storage commands of the device:
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
zone_finish(zf).
For example, to test zone_report, use following command:
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
-c "zrp offset nr_zones"
Signed-off-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20230508045533.175575-4-faithilikerun@gmail.com
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
<philmd@linaro.org> and remove spurious ret = -errno in
raw_co_zone_mgmt().
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-05-08 07:55:28 +03:00
|
|
|
|
|
|
|
acb->has_returned = true;
|
|
|
|
if (acb->rwco.ret != NOT_DONE) {
|
2023-09-13 02:10:36 +03:00
|
|
|
replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
|
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only
for zoned host block devices. By adding zone management operations to the
host_block_device BlockDriver, users can use the new block layer APIs
including Report Zone and four zone management operations
(open, close, finish, reset, reset_all).
Qemu-io uses the new APIs to perform zoned storage commands of the device:
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
zone_finish(zf).
For example, to test zone_report, use following command:
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
-c "zrp offset nr_zones"
Signed-off-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20230508045533.175575-4-faithilikerun@gmail.com
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
<philmd@linaro.org> and remove spurious ret = -errno in
raw_co_zone_mgmt().
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-05-08 07:55:28 +03:00
|
|
|
blk_aio_complete_bh, acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return &acb->common;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void coroutine_fn blk_aio_zone_mgmt_entry(void *opaque)
|
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
|
|
|
|
|
|
|
rwco->ret = blk_co_zone_mgmt(rwco->blk,
|
|
|
|
(BlockZoneOp)(uintptr_t)rwco->iobuf,
|
|
|
|
rwco->offset, acb->bytes);
|
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
|
|
|
|
int64_t offset, int64_t len,
|
|
|
|
BlockCompletionFunc *cb, void *opaque) {
|
|
|
|
BlkAioEmAIOCB *acb;
|
|
|
|
Coroutine *co;
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
|
|
|
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
|
|
|
|
acb->rwco = (BlkRwCo) {
|
|
|
|
.blk = blk,
|
|
|
|
.offset = offset,
|
|
|
|
.iobuf = (void *)(uintptr_t)op,
|
|
|
|
.ret = NOT_DONE,
|
|
|
|
};
|
|
|
|
acb->bytes = len;
|
|
|
|
acb->has_returned = false;
|
|
|
|
|
|
|
|
co = qemu_coroutine_create(blk_aio_zone_mgmt_entry, acb);
|
2023-09-13 02:10:36 +03:00
|
|
|
aio_co_enter(qemu_get_current_aio_context(), co);
|
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only
for zoned host block devices. By adding zone management operations to the
host_block_device BlockDriver, users can use the new block layer APIs
including Report Zone and four zone management operations
(open, close, finish, reset, reset_all).
Qemu-io uses the new APIs to perform zoned storage commands of the device:
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
zone_finish(zf).
For example, to test zone_report, use following command:
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
-c "zrp offset nr_zones"
Signed-off-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20230508045533.175575-4-faithilikerun@gmail.com
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
<philmd@linaro.org> and remove spurious ret = -errno in
raw_co_zone_mgmt().
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-05-08 07:55:28 +03:00
|
|
|
|
|
|
|
acb->has_returned = true;
|
|
|
|
if (acb->rwco.ret != NOT_DONE) {
|
2023-09-13 02:10:36 +03:00
|
|
|
replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
|
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only
for zoned host block devices. By adding zone management operations to the
host_block_device BlockDriver, users can use the new block layer APIs
including Report Zone and four zone management operations
(open, close, finish, reset, reset_all).
Qemu-io uses the new APIs to perform zoned storage commands of the device:
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
zone_finish(zf).
For example, to test zone_report, use following command:
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
-c "zrp offset nr_zones"
Signed-off-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20230508045533.175575-4-faithilikerun@gmail.com
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
<philmd@linaro.org> and remove spurious ret = -errno in
raw_co_zone_mgmt().
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-05-08 07:55:28 +03:00
|
|
|
blk_aio_complete_bh, acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return &acb->common;
|
|
|
|
}
|
|
|
|
|
2023-05-08 08:15:08 +03:00
|
|
|
static void coroutine_fn blk_aio_zone_append_entry(void *opaque)
|
|
|
|
{
|
|
|
|
BlkAioEmAIOCB *acb = opaque;
|
|
|
|
BlkRwCo *rwco = &acb->rwco;
|
|
|
|
|
|
|
|
rwco->ret = blk_co_zone_append(rwco->blk, (int64_t *)(uintptr_t)acb->bytes,
|
|
|
|
rwco->iobuf, rwco->flags);
|
|
|
|
blk_aio_complete(acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockAIOCB *blk_aio_zone_append(BlockBackend *blk, int64_t *offset,
|
|
|
|
QEMUIOVector *qiov, BdrvRequestFlags flags,
|
|
|
|
BlockCompletionFunc *cb, void *opaque) {
|
|
|
|
BlkAioEmAIOCB *acb;
|
|
|
|
Coroutine *co;
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
|
|
|
acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
|
|
|
|
acb->rwco = (BlkRwCo) {
|
|
|
|
.blk = blk,
|
|
|
|
.ret = NOT_DONE,
|
|
|
|
.flags = flags,
|
|
|
|
.iobuf = qiov,
|
|
|
|
};
|
|
|
|
acb->bytes = (int64_t)(uintptr_t)offset;
|
|
|
|
acb->has_returned = false;
|
|
|
|
|
|
|
|
co = qemu_coroutine_create(blk_aio_zone_append_entry, acb);
|
2023-09-13 02:10:36 +03:00
|
|
|
aio_co_enter(qemu_get_current_aio_context(), co);
|
2023-05-08 08:15:08 +03:00
|
|
|
acb->has_returned = true;
|
|
|
|
if (acb->rwco.ret != NOT_DONE) {
|
2023-09-13 02:10:36 +03:00
|
|
|
replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(),
|
2023-05-08 08:15:08 +03:00
|
|
|
blk_aio_complete_bh, acb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return &acb->common;
|
|
|
|
}
|
|
|
|
|
block/block-backend: add block layer APIs resembling Linux ZonedBlockDevice ioctls
Add zoned device option to host_device BlockDriver. It will be presented only
for zoned host block devices. By adding zone management operations to the
host_block_device BlockDriver, users can use the new block layer APIs
including Report Zone and four zone management operations
(open, close, finish, reset, reset_all).
Qemu-io uses the new APIs to perform zoned storage commands of the device:
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
zone_finish(zf).
For example, to test zone_report, use following command:
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
-c "zrp offset nr_zones"
Signed-off-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20230508045533.175575-4-faithilikerun@gmail.com
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
<philmd@linaro.org> and remove spurious ret = -errno in
raw_co_zone_mgmt().
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2023-05-08 07:55:28 +03:00
|
|
|
/*
|
|
|
|
* Send a zone_report command.
|
|
|
|
* offset is a byte offset from the start of the device. No alignment
|
|
|
|
* required for offset.
|
|
|
|
* nr_zones represents IN maximum and OUT actual.
|
|
|
|
*/
|
|
|
|
int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
|
|
|
|
unsigned int *nr_zones,
|
|
|
|
BlockZoneDescriptor *zones)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk); /* increase before waiting */
|
|
|
|
blk_wait_while_drained(blk);
|
|
|
|
GRAPH_RDLOCK_GUARD();
|
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
ret = bdrv_co_zone_report(blk_bs(blk), offset, nr_zones, zones);
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send a zone_management command.
|
|
|
|
* op is the zone operation;
|
|
|
|
* offset is the byte offset from the start of the zoned device;
|
|
|
|
* len is the maximum number of bytes the command should operate on. It
|
|
|
|
* should be aligned with the device zone size.
|
|
|
|
*/
|
|
|
|
int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
|
|
|
|
int64_t offset, int64_t len)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
|
|
|
blk_wait_while_drained(blk);
|
|
|
|
GRAPH_RDLOCK_GUARD();
|
|
|
|
|
|
|
|
ret = blk_check_byte_request(blk, offset, len);
|
|
|
|
if (ret < 0) {
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = bdrv_co_zone_mgmt(blk_bs(blk), op, offset, len);
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-05-08 08:15:08 +03:00
|
|
|
/*
|
|
|
|
* Send a zone_append command.
|
|
|
|
*/
|
|
|
|
int coroutine_fn blk_co_zone_append(BlockBackend *blk, int64_t *offset,
|
|
|
|
QEMUIOVector *qiov, BdrvRequestFlags flags)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
IO_CODE();
|
|
|
|
|
|
|
|
blk_inc_in_flight(blk);
|
|
|
|
blk_wait_while_drained(blk);
|
|
|
|
GRAPH_RDLOCK_GUARD();
|
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = bdrv_co_zone_append(blk_bs(blk), offset, qiov, flags);
|
|
|
|
blk_dec_in_flight(blk);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-17 13:37:19 +03:00
|
|
|
void blk_drain(BlockBackend *blk)
|
|
|
|
{
|
2018-02-16 19:50:13 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2018-02-16 19:50:13 +03:00
|
|
|
|
|
|
|
if (bs) {
|
2022-01-11 18:36:12 +03:00
|
|
|
bdrv_ref(bs);
|
2018-02-16 19:50:13 +03:00
|
|
|
bdrv_drained_begin(bs);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We may have -ENOMEDIUM completions in flight */
|
2018-09-18 18:09:16 +03:00
|
|
|
AIO_WAIT_WHILE(blk_get_aio_context(blk),
|
2023-03-03 13:02:34 +03:00
|
|
|
qatomic_read(&blk->in_flight) > 0);
|
2018-02-16 19:50:13 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
bdrv_drained_end(bs);
|
2022-01-11 18:36:12 +03:00
|
|
|
bdrv_unref(bs);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2015-06-17 13:37:19 +03:00
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:18 +04:00
|
|
|
void blk_drain_all(void)
|
|
|
|
{
|
2018-02-16 19:50:13 +03:00
|
|
|
BlockBackend *blk = NULL;
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2018-02-16 19:50:13 +03:00
|
|
|
bdrv_drain_all_begin();
|
|
|
|
|
|
|
|
while ((blk = blk_all_next(blk)) != NULL) {
|
|
|
|
/* We may have -ENOMEDIUM completions in flight */
|
2023-03-09 22:08:50 +03:00
|
|
|
AIO_WAIT_WHILE_UNLOCKED(NULL, qatomic_read(&blk->in_flight) > 0);
|
2018-02-16 19:50:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bdrv_drain_all_end();
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2015-10-19 18:53:22 +03:00
|
|
|
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
|
|
|
BlockdevOnError on_write_error)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
blk->on_read_error = on_read_error;
|
|
|
|
blk->on_write_error = on_write_error;
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:18 +04:00
|
|
|
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
return is_read ? blk->on_read_error : blk->on_write_error;
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
|
|
|
|
int error)
|
|
|
|
{
|
2015-10-19 18:53:22 +03:00
|
|
|
BlockdevOnError on_err = blk_get_on_error(blk, is_read);
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
|
|
|
|
switch (on_err) {
|
|
|
|
case BLOCKDEV_ON_ERROR_ENOSPC:
|
|
|
|
return (error == ENOSPC) ?
|
|
|
|
BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
|
|
|
|
case BLOCKDEV_ON_ERROR_STOP:
|
|
|
|
return BLOCK_ERROR_ACTION_STOP;
|
|
|
|
case BLOCKDEV_ON_ERROR_REPORT:
|
|
|
|
return BLOCK_ERROR_ACTION_REPORT;
|
|
|
|
case BLOCKDEV_ON_ERROR_IGNORE:
|
|
|
|
return BLOCK_ERROR_ACTION_IGNORE;
|
2016-06-29 18:41:35 +03:00
|
|
|
case BLOCKDEV_ON_ERROR_AUTO:
|
2015-10-19 18:53:22 +03:00
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2015-10-19 18:53:22 +03:00
|
|
|
static void send_qmp_error_event(BlockBackend *blk,
|
|
|
|
BlockErrorAction action,
|
|
|
|
bool is_read, int error)
|
|
|
|
{
|
|
|
|
IoOperationType optype;
|
2018-03-05 17:59:35 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2015-10-19 18:53:22 +03:00
|
|
|
|
|
|
|
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
|
2022-11-04 19:06:52 +03:00
|
|
|
qapi_event_send_block_io_error(blk_name(blk),
|
2018-03-05 17:59:35 +03:00
|
|
|
bs ? bdrv_get_node_name(bs) : NULL, optype,
|
2016-09-29 17:47:58 +03:00
|
|
|
action, blk_iostatus_is_enabled(blk),
|
2018-08-15 16:37:37 +03:00
|
|
|
error == ENOSPC, strerror(error));
|
2015-10-19 18:53:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This is done by device models because, while the block layer knows
|
|
|
|
* about the error, it does not know whether an operation comes from
|
|
|
|
* the device or the block layer (from a job, for example).
|
|
|
|
*/
|
2014-10-07 15:59:18 +04:00
|
|
|
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
|
|
|
|
bool is_read, int error)
|
|
|
|
{
|
2015-10-19 18:53:22 +03:00
|
|
|
assert(error >= 0);
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-10-19 18:53:22 +03:00
|
|
|
|
|
|
|
if (action == BLOCK_ERROR_ACTION_STOP) {
|
|
|
|
/* First set the iostatus, so that "info block" returns an iostatus
|
|
|
|
* that matches the events raised so far (an additional error iostatus
|
|
|
|
* is fine, but not a lost one).
|
|
|
|
*/
|
|
|
|
blk_iostatus_set_err(blk, error);
|
|
|
|
|
|
|
|
/* Then raise the request to stop the VM and the event.
|
|
|
|
* qemu_system_vmstop_request_prepare has two effects. First,
|
|
|
|
* it ensures that the STOP event always comes after the
|
|
|
|
* BLOCK_IO_ERROR event. Second, it ensures that even if management
|
|
|
|
* can observe the STOP event and do a "cont" before the STOP
|
|
|
|
* event is issued, the VM will not stop. In this case, vm_start()
|
|
|
|
* also ensures that the STOP/RESUME pair of events is emitted.
|
|
|
|
*/
|
|
|
|
qemu_system_vmstop_request_prepare();
|
|
|
|
send_qmp_error_event(blk, action, is_read, error);
|
|
|
|
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
|
|
|
|
} else {
|
|
|
|
send_qmp_error_event(blk, action, is_read, error);
|
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2021-01-18 15:34:47 +03:00
|
|
|
/*
|
|
|
|
* Returns true if the BlockBackend can support taking write permissions
|
|
|
|
* (because its root node is not read-only).
|
|
|
|
*/
|
|
|
|
bool blk_supports_write_perm(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
2021-01-18 15:34:47 +03:00
|
|
|
return !bdrv_is_read_only(bs);
|
2015-10-19 18:53:25 +03:00
|
|
|
} else {
|
2021-05-27 18:40:56 +03:00
|
|
|
return blk->root_state.open_flags & BDRV_O_RDWR;
|
2015-10-19 18:53:25 +03:00
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2021-01-18 15:34:47 +03:00
|
|
|
/*
|
|
|
|
* Returns true if the BlockBackend can be written to in its current
|
|
|
|
* configuration (i.e. if write permission have been requested)
|
|
|
|
*/
|
|
|
|
bool blk_is_writable(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2021-01-18 15:34:47 +03:00
|
|
|
return blk->perm & BLK_PERM_WRITE;
|
|
|
|
}
|
|
|
|
|
2018-10-13 11:52:31 +03:00
|
|
|
bool blk_is_sg(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (!bs) {
|
2018-10-13 11:52:31 +03:00
|
|
|
return false;
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
return bdrv_is_sg(bs);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2018-10-13 11:52:31 +03:00
|
|
|
bool blk_enable_write_cache(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-04 16:28:01 +03:00
|
|
|
return blk->enable_write_cache;
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
|
|
|
|
{
|
block/block-backend: blk_set_enable_write_cache is IO_CODE
blk_set_enable_write_cache() is defined as GLOBAL_STATE_CODE
but can be invoked from iothreads when handling scsi requests.
This triggers an assertion failure:
0x00007fd6c3515ce1 in raise () from /lib/x86_64-linux-gnu/libc.so.6
0x00007fd6c34ff537 in abort () from /lib/x86_64-linux-gnu/libc.so.6
0x00007fd6c34ff40f in ?? () from /lib/x86_64-linux-gnu/libc.so.6
0x00007fd6c350e662 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
0x000056149e2cea03 in blk_set_enable_write_cache (wce=true, blk=0x5614a01c27f0)
at ../src/block/block-backend.c:1949
0x000056149e2d0a67 in blk_set_enable_write_cache (blk=0x5614a01c27f0,
wce=<optimized out>) at ../src/block/block-backend.c:1951
0x000056149dfe9c59 in scsi_disk_apply_mode_select (p=0x7fd6b400c00e "\004",
page=<optimized out>, s=<optimized out>) at ../src/hw/scsi/scsi-disk.c:1520
mode_select_pages (change=true, len=18, p=0x7fd6b400c00e "\004", r=0x7fd6b4001ff0)
at ../src/hw/scsi/scsi-disk.c:1570
scsi_disk_emulate_mode_select (inbuf=<optimized out>, r=0x7fd6b4001ff0) at
../src/hw/scsi/scsi-disk.c:1640
scsi_disk_emulate_write_data (req=0x7fd6b4001ff0) at ../src/hw/scsi/scsi-disk.c:1934
0x000056149e18ff16 in virtio_scsi_handle_cmd_req_submit (req=<optimized out>,
req=<optimized out>, s=0x5614a12f16b0) at ../src/hw/scsi/virtio-scsi.c:719
virtio_scsi_handle_cmd_vq (vq=0x7fd6bab92140, s=0x5614a12f16b0) at
../src/hw/scsi/virtio-scsi.c:761
virtio_scsi_handle_cmd (vq=<optimized out>, vdev=<optimized out>) at
../src/hw/scsi/virtio-scsi.c:775
virtio_scsi_handle_cmd (vdev=0x5614a12f16b0, vq=0x7fd6bab92140) at
../src/hw/scsi/virtio-scsi.c:765
0x000056149e1a8aa6 in virtio_queue_notify_vq (vq=0x7fd6bab92140) at
../src/hw/virtio/virtio.c:2365
0x000056149e3ccea5 in aio_dispatch_handler (ctx=ctx@entry=0x5614a01babe0,
node=<optimized out>) at ../src/util/aio-posix.c:369
0x000056149e3cd868 in aio_dispatch_ready_handlers (ready_list=0x7fd6c09b2680,
ctx=0x5614a01babe0) at ../src/util/aio-posix.c:399
aio_poll (ctx=0x5614a01babe0, blocking=blocking@entry=true) at
../src/util/aio-posix.c:713
0x000056149e2a7796 in iothread_run (opaque=opaque@entry=0x56149ffde500) at
../src/iothread.c:67
0x000056149e3d0859 in qemu_thread_start (args=0x7fd6c09b26f0) at
../src/util/qemu-thread-posix.c:504
0x00007fd6c36b9ea7 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
0x00007fd6c35d9aef in clone () from /lib/x86_64-linux-gnu/libc.so.6
Changing GLOBAL_STATE_CODE in IO_CODE is allowed, since GSC callers are
allowed to call IO_CODE.
Resolves: #1272
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Message-Id: <20221027072726.2681500-1-eesposit@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
Tested-by: Antoine Damhet <antoine.damhet@shadow.tech>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2022-10-27 10:27:26 +03:00
|
|
|
IO_CODE();
|
2016-03-04 16:28:01 +03:00
|
|
|
blk->enable_write_cache = wce;
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2022-02-09 13:54:51 +03:00
|
|
|
void blk_activate(BlockBackend *blk, Error **errp)
|
2014-11-18 14:21:14 +03:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (!bs) {
|
2015-10-19 18:53:26 +03:00
|
|
|
error_setg(errp, "Device '%s' has no medium", blk->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-04 14:57:32 +03:00
|
|
|
/*
|
|
|
|
* Migration code can call this function in coroutine context, so leave
|
|
|
|
* coroutine context if necessary.
|
|
|
|
*/
|
|
|
|
if (qemu_in_coroutine()) {
|
|
|
|
bdrv_co_activate(bs, errp);
|
|
|
|
} else {
|
2023-09-29 17:51:39 +03:00
|
|
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
2023-05-04 14:57:32 +03:00
|
|
|
bdrv_activate(bs, errp);
|
|
|
|
}
|
2014-11-18 14:21:14 +03:00
|
|
|
}
|
|
|
|
|
2023-01-13 23:42:02 +03:00
|
|
|
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:57 +03:00
|
|
|
assert_bdrv_graph_readable();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
2023-01-13 23:42:02 +03:00
|
|
|
return bs && bdrv_co_is_inserted(bs);
|
2015-10-19 18:53:12 +03:00
|
|
|
}
|
|
|
|
|
2023-02-03 18:21:57 +03:00
|
|
|
bool coroutine_fn blk_co_is_available(BlockBackend *blk)
|
2015-10-19 18:53:12 +03:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:57 +03:00
|
|
|
return blk_co_is_inserted(blk) && !blk_dev_is_tray_open(blk);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2023-01-13 23:42:10 +03:00
|
|
|
void coroutine_fn blk_co_lock_medium(BlockBackend *blk, bool locked)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:58 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
2023-01-13 23:42:10 +03:00
|
|
|
bdrv_co_lock_medium(bs, locked);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2023-01-13 23:42:09 +03:00
|
|
|
void coroutine_fn blk_co_eject(BlockBackend *blk, bool eject_flag)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2016-09-29 19:30:53 +03:00
|
|
|
char *id;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:58 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2016-09-29 19:30:53 +03:00
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
if (bs) {
|
2023-01-13 23:42:09 +03:00
|
|
|
bdrv_co_eject(bs, eject_flag);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2016-11-14 19:15:54 +03:00
|
|
|
|
|
|
|
/* Whether or not we ejected on the backend,
|
|
|
|
* the frontend experienced a tray event. */
|
|
|
|
id = blk_get_attached_dev_id(blk);
|
|
|
|
qapi_event_send_device_tray_moved(blk_name(blk), id,
|
2018-08-15 16:37:37 +03:00
|
|
|
eject_flag);
|
2016-11-14 19:15:54 +03:00
|
|
|
g_free(id);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int blk_get_flags(BlockBackend *blk)
|
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
return bdrv_get_flags(bs);
|
2015-10-19 18:53:25 +03:00
|
|
|
} else {
|
|
|
|
return blk->root_state.open_flags;
|
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2019-03-29 07:27:49 +03:00
|
|
|
/* Returns the minimum request alignment, in bytes; guaranteed nonzero */
|
|
|
|
uint32_t blk_get_request_alignment(BlockBackend *blk)
|
|
|
|
{
|
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2019-03-29 07:27:49 +03:00
|
|
|
return bs ? bs->bl.request_alignment : BDRV_SECTOR_SIZE;
|
|
|
|
}
|
|
|
|
|
2021-06-03 11:34:23 +03:00
|
|
|
/* Returns the maximum hardware transfer length, in bytes; guaranteed nonzero */
|
|
|
|
uint64_t blk_get_max_hw_transfer(BlockBackend *blk)
|
|
|
|
{
|
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
uint64_t max = INT_MAX;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2021-06-03 11:34:23 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
max = MIN_NON_ZERO(max, bs->bl.max_hw_transfer);
|
|
|
|
max = MIN_NON_ZERO(max, bs->bl.max_transfer);
|
|
|
|
}
|
|
|
|
return ROUND_DOWN(max, blk_get_request_alignment(blk));
|
|
|
|
}
|
|
|
|
|
2016-06-24 01:37:19 +03:00
|
|
|
/* Returns the maximum transfer length, in bytes; guaranteed nonzero */
|
|
|
|
uint32_t blk_get_max_transfer(BlockBackend *blk)
|
2015-02-02 16:52:20 +03:00
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2021-06-16 16:13:49 +03:00
|
|
|
uint32_t max = INT_MAX;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
2021-06-16 16:13:49 +03:00
|
|
|
max = MIN_NON_ZERO(max, bs->bl.max_transfer);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2021-06-16 16:13:49 +03:00
|
|
|
return ROUND_DOWN(max, blk_get_request_alignment(blk));
|
2015-02-02 16:52:20 +03:00
|
|
|
}
|
|
|
|
|
2021-09-23 16:04:36 +03:00
|
|
|
int blk_get_max_hw_iov(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2021-09-23 16:04:36 +03:00
|
|
|
return MIN_NON_ZERO(blk->root->bs->bl.max_hw_iov,
|
|
|
|
blk->root->bs->bl.max_iov);
|
|
|
|
}
|
|
|
|
|
2015-07-09 12:56:45 +03:00
|
|
|
int blk_get_max_iov(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
return blk->root->bs->bl.max_iov;
|
2015-07-09 12:56:45 +03:00
|
|
|
}
|
|
|
|
|
2016-01-07 16:34:13 +03:00
|
|
|
void *blk_try_blockalign(BlockBackend *blk, size_t size)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
return qemu_try_blockalign(blk ? blk_bs(blk) : NULL, size);
|
2016-01-07 16:34:13 +03:00
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:18 +04:00
|
|
|
void *blk_blockalign(BlockBackend *blk, size_t size)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
return qemu_blockalign(blk ? blk_bs(blk) : NULL, size);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
|
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2023-09-29 17:51:52 +03:00
|
|
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (!bs) {
|
2015-10-19 18:53:27 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
return bdrv_op_is_blocked(bs, op, errp);
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
|
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
bdrv_op_unblock(bs, op, reason);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_op_block_all(BlockBackend *blk, Error *reason)
|
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
bdrv_op_block_all(bs, reason);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_op_unblock_all(BlockBackend *blk, Error *reason)
|
|
|
|
{
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
bdrv_op_unblock_all(bs, reason);
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
2024-02-02 17:47:54 +03:00
|
|
|
/**
|
|
|
|
* Return BB's current AioContext. Note that this context may change
|
|
|
|
* concurrently at any time, with one exception: If the BB has a root node
|
|
|
|
* attached, its context will only change through bdrv_try_change_aio_context(),
|
|
|
|
* which creates a drained section. Therefore, incrementing such a BB's
|
|
|
|
* in-flight counter will prevent its context from changing.
|
|
|
|
*/
|
2014-10-07 15:59:18 +04:00
|
|
|
AioContext *blk_get_aio_context(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2019-04-25 15:25:10 +03:00
|
|
|
|
2023-05-25 15:47:02 +03:00
|
|
|
if (!blk) {
|
|
|
|
return qemu_get_aio_context();
|
|
|
|
}
|
|
|
|
|
2024-02-02 17:47:54 +03:00
|
|
|
return qatomic_read(&blk->ctx);
|
2015-10-19 18:53:18 +03:00
|
|
|
}
|
|
|
|
|
2023-05-16 22:02:19 +03:00
|
|
|
int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
|
|
|
|
Error **errp)
|
2014-10-07 15:59:18 +04:00
|
|
|
{
|
2023-05-16 22:02:19 +03:00
|
|
|
bool old_allow_change;
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2019-05-02 12:10:59 +03:00
|
|
|
int ret;
|
2016-03-08 15:47:46 +03:00
|
|
|
|
2023-05-16 22:02:19 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2022-01-11 18:36:12 +03:00
|
|
|
|
2023-05-16 22:02:19 +03:00
|
|
|
if (!bs) {
|
2024-02-02 17:47:54 +03:00
|
|
|
qatomic_set(&blk->ctx, new_context);
|
2023-05-16 22:02:19 +03:00
|
|
|
return 0;
|
2015-10-19 18:53:27 +03:00
|
|
|
}
|
2019-05-02 12:10:59 +03:00
|
|
|
|
2023-05-16 22:02:19 +03:00
|
|
|
bdrv_ref(bs);
|
2014-10-07 15:59:18 +04:00
|
|
|
|
2023-05-16 22:02:19 +03:00
|
|
|
old_allow_change = blk->allow_aio_context_change;
|
|
|
|
blk->allow_aio_context_change = true;
|
|
|
|
|
|
|
|
ret = bdrv_try_change_aio_context(bs, new_context, NULL, errp);
|
|
|
|
|
|
|
|
blk->allow_aio_context_change = old_allow_change;
|
|
|
|
|
|
|
|
bdrv_unref(bs);
|
|
|
|
return ret;
|
2019-05-06 20:18:01 +03:00
|
|
|
}
|
|
|
|
|
2022-10-25 11:49:48 +03:00
|
|
|
typedef struct BdrvStateBlkRootContext {
|
|
|
|
AioContext *new_ctx;
|
|
|
|
BlockBackend *blk;
|
|
|
|
} BdrvStateBlkRootContext;
|
|
|
|
|
|
|
|
static void blk_root_set_aio_ctx_commit(void *opaque)
|
|
|
|
{
|
|
|
|
BdrvStateBlkRootContext *s = opaque;
|
|
|
|
BlockBackend *blk = s->blk;
|
2023-05-16 22:02:19 +03:00
|
|
|
AioContext *new_context = s->new_ctx;
|
|
|
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
2022-10-25 11:49:48 +03:00
|
|
|
|
2024-02-02 17:47:54 +03:00
|
|
|
qatomic_set(&blk->ctx, new_context);
|
2023-05-16 22:02:19 +03:00
|
|
|
if (tgm->throttle_state) {
|
|
|
|
throttle_group_detach_aio_context(tgm);
|
|
|
|
throttle_group_attach_aio_context(tgm, new_context);
|
|
|
|
}
|
2022-10-25 11:49:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static TransactionActionDrv set_blk_root_context = {
|
|
|
|
.commit = blk_root_set_aio_ctx_commit,
|
|
|
|
.clean = g_free,
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
|
|
|
|
GHashTable *visited, Transaction *tran,
|
|
|
|
Error **errp)
|
2019-05-06 20:18:01 +03:00
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
2022-10-25 11:49:48 +03:00
|
|
|
BdrvStateBlkRootContext *s;
|
2019-05-06 20:18:01 +03:00
|
|
|
|
2022-10-25 11:49:48 +03:00
|
|
|
if (!blk->allow_aio_context_change) {
|
|
|
|
/*
|
|
|
|
* Manually created BlockBackends (those with a name) that are not
|
|
|
|
* attached to anything can change their AioContext without updating
|
|
|
|
* their user; return an error for others.
|
|
|
|
*/
|
|
|
|
if (!blk->name || blk->dev) {
|
|
|
|
/* TODO Add BB name/QOM path */
|
|
|
|
error_setg(errp, "Cannot change iothread of active block backend");
|
|
|
|
return false;
|
|
|
|
}
|
2019-05-06 20:18:02 +03:00
|
|
|
}
|
|
|
|
|
2022-10-25 11:49:48 +03:00
|
|
|
s = g_new(BdrvStateBlkRootContext, 1);
|
|
|
|
*s = (BdrvStateBlkRootContext) {
|
|
|
|
.new_ctx = ctx,
|
|
|
|
.blk = blk,
|
|
|
|
};
|
2019-05-06 20:18:01 +03:00
|
|
|
|
2022-10-25 11:49:48 +03:00
|
|
|
tran_add(tran, &set_blk_root_context, s);
|
2019-05-06 20:18:01 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-11-18 14:21:15 +03:00
|
|
|
void blk_add_aio_context_notifier(BlockBackend *blk,
|
|
|
|
void (*attached_aio_context)(AioContext *new_context, void *opaque),
|
|
|
|
void (*detach_aio_context)(void *opaque), void *opaque)
|
|
|
|
{
|
2018-03-06 23:48:18 +03:00
|
|
|
BlockBackendAioNotifier *notifier;
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
|
2018-03-06 23:48:18 +03:00
|
|
|
notifier = g_new(BlockBackendAioNotifier, 1);
|
|
|
|
notifier->attached_aio_context = attached_aio_context;
|
|
|
|
notifier->detach_aio_context = detach_aio_context;
|
|
|
|
notifier->opaque = opaque;
|
|
|
|
QLIST_INSERT_HEAD(&blk->aio_notifiers, notifier, list);
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
if (bs) {
|
|
|
|
bdrv_add_aio_context_notifier(bs, attached_aio_context,
|
2015-10-19 18:53:27 +03:00
|
|
|
detach_aio_context, opaque);
|
|
|
|
}
|
2014-11-18 14:21:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_remove_aio_context_notifier(BlockBackend *blk,
|
|
|
|
void (*attached_aio_context)(AioContext *,
|
|
|
|
void *),
|
|
|
|
void (*detach_aio_context)(void *),
|
|
|
|
void *opaque)
|
|
|
|
{
|
2018-03-06 23:48:18 +03:00
|
|
|
BlockBackendAioNotifier *notifier;
|
2016-03-08 15:47:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
if (bs) {
|
|
|
|
bdrv_remove_aio_context_notifier(bs, attached_aio_context,
|
2015-10-19 18:53:27 +03:00
|
|
|
detach_aio_context, opaque);
|
|
|
|
}
|
2018-03-06 23:48:18 +03:00
|
|
|
|
|
|
|
QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
|
|
|
|
if (notifier->attached_aio_context == attached_aio_context &&
|
|
|
|
notifier->detach_aio_context == detach_aio_context &&
|
|
|
|
notifier->opaque == opaque) {
|
|
|
|
QLIST_REMOVE(notifier, list);
|
|
|
|
g_free(notifier);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abort();
|
2014-11-18 14:21:15 +03:00
|
|
|
}
|
|
|
|
|
2016-01-29 18:36:03 +03:00
|
|
|
void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-01-29 18:36:03 +03:00
|
|
|
notifier_list_add(&blk->remove_bs_notifiers, notify);
|
|
|
|
}
|
|
|
|
|
|
|
|
void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-01-29 18:36:03 +03:00
|
|
|
notifier_list_add(&blk->insert_bs_notifiers, notify);
|
|
|
|
}
|
|
|
|
|
2014-10-07 15:59:18 +04:00
|
|
|
BlockAcctStats *blk_get_stats(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2015-10-19 18:53:21 +03:00
|
|
|
return &blk->stats;
|
2014-10-07 15:59:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
|
|
|
|
BlockCompletionFunc *cb, void *opaque)
|
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2014-10-07 15:59:18 +04:00
|
|
|
return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
|
|
|
|
}
|
2015-02-05 21:58:10 +03:00
|
|
|
|
2016-05-25 01:25:20 +03:00
|
|
|
int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
|
2021-10-06 16:17:09 +03:00
|
|
|
int64_t bytes, BdrvRequestFlags flags)
|
2015-02-05 21:58:10 +03:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2017-06-09 13:18:08 +03:00
|
|
|
return blk_co_pwritev(blk, offset, bytes, NULL,
|
2016-04-15 11:21:04 +03:00
|
|
|
flags | BDRV_REQ_ZERO_WRITE);
|
2015-02-05 21:58:10 +03:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:19 +03:00
|
|
|
int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
|
|
|
|
int64_t bytes, const void *buf)
|
2015-02-05 21:58:10 +03:00
|
|
|
{
|
2021-10-06 16:17:14 +03:00
|
|
|
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2022-07-05 19:15:19 +03:00
|
|
|
return blk_co_pwritev_part(blk, offset, bytes, &qiov, 0,
|
|
|
|
BDRV_REQ_WRITE_COMPRESSED);
|
2015-02-05 21:58:10 +03:00
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:24 +03:00
|
|
|
int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
|
|
|
|
PreallocMode prealloc, BdrvRequestFlags flags,
|
|
|
|
Error **errp)
|
2015-02-05 21:58:10 +03:00
|
|
|
{
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_OR_GS_CODE();
|
2023-02-03 18:21:42 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2023-02-03 18:21:57 +03:00
|
|
|
if (!blk_co_is_available(blk)) {
|
2017-03-28 23:51:27 +03:00
|
|
|
error_setg(errp, "No medium inserted");
|
2015-10-19 18:53:26 +03:00
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2022-07-05 19:15:24 +03:00
|
|
|
return bdrv_co_truncate(blk->root, offset, exact, prealloc, flags, errp);
|
2015-02-05 21:58:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
|
|
|
|
int64_t pos, int size)
|
|
|
|
{
|
2016-03-04 16:28:01 +03:00
|
|
|
int ret;
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-04 16:28:01 +03:00
|
|
|
|
2015-10-19 18:53:26 +03:00
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2016-03-04 16:28:01 +03:00
|
|
|
ret = bdrv_save_vmstate(blk_bs(blk), buf, pos, size);
|
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == size && !blk->enable_write_cache) {
|
|
|
|
ret = bdrv_flush(blk_bs(blk));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret < 0 ? ret : size;
|
2015-02-05 21:58:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:26 +03:00
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
return bdrv_load_vmstate(blk_bs(blk), buf, pos, size);
|
2015-02-05 21:58:10 +03:00
|
|
|
}
|
2015-02-16 14:47:57 +03:00
|
|
|
|
|
|
|
int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2023-10-27 18:53:10 +03:00
|
|
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
|
|
|
|
2015-10-19 18:53:26 +03:00
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
return bdrv_probe_blocksizes(blk_bs(blk), bsz);
|
2015-02-16 14:47:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:26 +03:00
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
return bdrv_probe_geometry(blk_bs(blk), geo);
|
2015-02-16 14:47:57 +03:00
|
|
|
}
|
2015-10-19 18:53:24 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Updates the BlockBackendRootState object with data from the currently
|
|
|
|
* attached BlockDriverState.
|
|
|
|
*/
|
|
|
|
void blk_update_root_state(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-08 15:47:46 +03:00
|
|
|
assert(blk->root);
|
2015-10-19 18:53:24 +03:00
|
|
|
|
2016-03-08 15:47:46 +03:00
|
|
|
blk->root_state.open_flags = blk->root->bs->open_flags;
|
|
|
|
blk->root_state.detect_zeroes = blk->root->bs->detect_zeroes;
|
2015-10-19 18:53:24 +03:00
|
|
|
}
|
|
|
|
|
2015-10-26 23:39:07 +03:00
|
|
|
/*
|
2016-09-12 20:08:31 +03:00
|
|
|
* Returns the detect-zeroes setting to be used for bdrv_open() of a
|
|
|
|
* BlockDriverState which is supposed to inherit the root state.
|
2015-10-26 23:39:07 +03:00
|
|
|
*/
|
2016-09-12 20:08:31 +03:00
|
|
|
bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk)
|
2015-10-26 23:39:07 +03:00
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-09-12 20:08:31 +03:00
|
|
|
return blk->root_state.detect_zeroes;
|
2015-10-26 23:39:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the flags to be used for bdrv_open() of a BlockDriverState which is
|
|
|
|
* supposed to inherit the root state.
|
|
|
|
*/
|
|
|
|
int blk_get_open_flags_from_root_state(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2021-05-27 18:40:56 +03:00
|
|
|
return blk->root_state.open_flags;
|
2015-10-26 23:39:07 +03:00
|
|
|
}
|
|
|
|
|
2015-10-19 18:53:24 +03:00
|
|
|
BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2015-10-19 18:53:24 +03:00
|
|
|
return &blk->root_state;
|
|
|
|
}
|
2016-03-16 21:54:31 +03:00
|
|
|
|
|
|
|
int blk_commit_all(void)
|
|
|
|
{
|
2016-03-16 21:54:40 +03:00
|
|
|
BlockBackend *blk = NULL;
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2023-10-27 18:53:17 +03:00
|
|
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
2016-03-16 21:54:40 +03:00
|
|
|
|
|
|
|
while ((blk = blk_all_next(blk)) != NULL) {
|
2019-06-12 18:47:37 +03:00
|
|
|
BlockDriverState *unfiltered_bs = bdrv_skip_filters(blk_bs(blk));
|
2016-03-16 21:54:40 +03:00
|
|
|
|
2019-06-12 18:47:37 +03:00
|
|
|
if (blk_is_inserted(blk) && bdrv_cow_child(unfiltered_bs)) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = bdrv_commit(unfiltered_bs);
|
2016-03-16 21:54:40 +03:00
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-21 15:53:52 +03:00
|
|
|
|
|
|
|
/* throttling disk I/O limits */
|
|
|
|
void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-08-25 16:20:23 +03:00
|
|
|
throttle_group_config(&blk->public.throttle_group_member, cfg);
|
2016-03-21 15:53:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_io_limits_disable(BlockBackend *blk)
|
|
|
|
{
|
2017-11-10 21:54:46 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
|
|
|
assert(tgm->throttle_state);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-11-10 21:54:46 +03:00
|
|
|
if (bs) {
|
2022-01-11 18:36:12 +03:00
|
|
|
bdrv_ref(bs);
|
2017-11-10 21:54:46 +03:00
|
|
|
bdrv_drained_begin(bs);
|
|
|
|
}
|
|
|
|
throttle_group_unregister_tgm(tgm);
|
|
|
|
if (bs) {
|
|
|
|
bdrv_drained_end(bs);
|
2022-01-11 18:36:12 +03:00
|
|
|
bdrv_unref(bs);
|
2017-11-10 21:54:46 +03:00
|
|
|
}
|
2016-03-21 15:53:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* should be called before blk_set_io_limits if a limit is set */
|
|
|
|
void blk_io_limits_enable(BlockBackend *blk, const char *group)
|
|
|
|
{
|
2017-08-25 16:20:23 +03:00
|
|
|
assert(!blk->public.throttle_group_member.throttle_state);
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2017-08-25 16:20:24 +03:00
|
|
|
throttle_group_register_tgm(&blk->public.throttle_group_member,
|
|
|
|
group, blk_get_aio_context(blk));
|
2016-03-21 15:53:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void blk_io_limits_update_group(BlockBackend *blk, const char *group)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2016-03-21 15:53:52 +03:00
|
|
|
/* this BB is not part of any group */
|
2017-08-25 16:20:23 +03:00
|
|
|
if (!blk->public.throttle_group_member.throttle_state) {
|
2016-03-21 15:53:52 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this BB is a part of the same group than the one we want */
|
2017-08-25 16:20:23 +03:00
|
|
|
if (!g_strcmp0(throttle_group_get_name(&blk->public.throttle_group_member),
|
|
|
|
group)) {
|
2016-03-21 15:53:52 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* need to change the group this bs belong to */
|
|
|
|
blk_io_limits_disable(blk);
|
|
|
|
blk_io_limits_enable(blk, group);
|
|
|
|
}
|
2016-03-22 14:05:35 +03:00
|
|
|
|
|
|
|
static void blk_root_drained_begin(BdrvChild *child)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
2020-09-23 13:56:46 +03:00
|
|
|
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
2016-03-22 14:05:35 +03:00
|
|
|
|
2023-03-08 00:04:25 +03:00
|
|
|
if (qatomic_fetch_inc(&blk->quiesce_counter) == 0) {
|
2017-03-17 00:23:50 +03:00
|
|
|
if (blk->dev_ops && blk->dev_ops->drained_begin) {
|
|
|
|
blk->dev_ops->drained_begin(blk->dev_opaque);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-17 15:51:55 +03:00
|
|
|
/* Note that blk->root may not be accessible here yet if we are just
|
|
|
|
* attaching to a BlockDriverState that is drained. Use child instead. */
|
|
|
|
|
2020-09-23 13:56:46 +03:00
|
|
|
if (qatomic_fetch_inc(&tgm->io_limits_disabled) == 0) {
|
|
|
|
throttle_group_restart_tgm(tgm);
|
2016-03-22 14:05:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 18:43:49 +03:00
|
|
|
static bool blk_root_drained_poll(BdrvChild *child)
|
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
2021-06-02 09:05:51 +03:00
|
|
|
bool busy = false;
|
2023-03-08 00:04:25 +03:00
|
|
|
assert(qatomic_read(&blk->quiesce_counter));
|
2021-06-02 09:05:51 +03:00
|
|
|
|
|
|
|
if (blk->dev_ops && blk->dev_ops->drained_poll) {
|
|
|
|
busy = blk->dev_ops->drained_poll(blk->dev_opaque);
|
|
|
|
}
|
|
|
|
return busy || !!blk->in_flight;
|
2018-09-06 18:43:49 +03:00
|
|
|
}
|
|
|
|
|
2022-11-18 20:40:59 +03:00
|
|
|
static void blk_root_drained_end(BdrvChild *child)
|
2016-03-22 14:05:35 +03:00
|
|
|
{
|
|
|
|
BlockBackend *blk = child->opaque;
|
2023-03-08 00:04:25 +03:00
|
|
|
assert(qatomic_read(&blk->quiesce_counter));
|
2016-03-22 14:05:35 +03:00
|
|
|
|
2017-08-25 16:20:23 +03:00
|
|
|
assert(blk->public.throttle_group_member.io_limits_disabled);
|
2020-09-23 13:56:46 +03:00
|
|
|
qatomic_dec(&blk->public.throttle_group_member.io_limits_disabled);
|
2017-03-17 00:23:50 +03:00
|
|
|
|
2023-03-08 00:04:25 +03:00
|
|
|
if (qatomic_fetch_dec(&blk->quiesce_counter) == 1) {
|
2017-03-17 00:23:50 +03:00
|
|
|
if (blk->dev_ops && blk->dev_ops->drained_end) {
|
|
|
|
blk->dev_ops->drained_end(blk->dev_opaque);
|
|
|
|
}
|
2023-03-08 00:04:27 +03:00
|
|
|
qemu_mutex_lock(&blk->queued_requests_lock);
|
|
|
|
while (qemu_co_enter_next(&blk->queued_requests,
|
|
|
|
&blk->queued_requests_lock)) {
|
block-backend: Queue requests while drained
This fixes devices like IDE that can still start new requests from I/O
handlers in the CPU thread while the block backend is drained.
The basic assumption is that in a drain section, no new requests should
be allowed through a BlockBackend (blk_drained_begin/end don't exist,
we get drain sections only on the node level). However, there are two
special cases where requests should not be queued:
1. Block jobs: We already make sure that block jobs are paused in a
drain section, so they won't start new requests. However, if the
drain_begin is called on the job's BlockBackend first, it can happen
that we deadlock because the job stays busy until it reaches a pause
point - which it can't if its requests aren't processed any more.
The proper solution here would be to make all requests through the
job's filter node instead of using a BlockBackend. For now, just
disabling request queuing on the job BlockBackend is simpler.
2. In test cases where making requests through bdrv_* would be
cumbersome because we'd need a BdrvChild. As we already got the
functionality to disable request queuing from 1., use it in tests,
too, for convenience.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
2019-07-22 18:46:23 +03:00
|
|
|
/* Resume all queued requests */
|
|
|
|
}
|
2023-03-08 00:04:27 +03:00
|
|
|
qemu_mutex_unlock(&blk->queued_requests_lock);
|
2017-03-17 00:23:50 +03:00
|
|
|
}
|
2016-03-22 14:05:35 +03:00
|
|
|
}
|
2018-01-16 09:08:56 +03:00
|
|
|
|
2022-10-13 21:59:02 +03:00
|
|
|
bool blk_register_buf(BlockBackend *blk, void *host, size_t size, Error **errp)
|
2018-01-16 09:08:56 +03:00
|
|
|
{
|
2022-11-22 00:19:23 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2022-11-22 00:19:23 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
return bdrv_register_buf(bs, host, size, errp);
|
|
|
|
}
|
|
|
|
return true;
|
2018-01-16 09:08:56 +03:00
|
|
|
}
|
|
|
|
|
2022-10-13 21:58:59 +03:00
|
|
|
void blk_unregister_buf(BlockBackend *blk, void *host, size_t size)
|
2018-01-16 09:08:56 +03:00
|
|
|
{
|
2022-11-22 00:19:23 +03:00
|
|
|
BlockDriverState *bs = blk_bs(blk);
|
|
|
|
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2022-11-22 00:19:23 +03:00
|
|
|
|
|
|
|
if (bs) {
|
|
|
|
bdrv_unregister_buf(bs, host, size);
|
|
|
|
}
|
2018-01-16 09:08:56 +03:00
|
|
|
}
|
2018-06-01 12:26:47 +03:00
|
|
|
|
|
|
|
int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
|
|
|
|
BlockBackend *blk_out, int64_t off_out,
|
2021-10-06 16:17:15 +03:00
|
|
|
int64_t bytes, BdrvRequestFlags read_flags,
|
2018-07-09 19:37:17 +03:00
|
|
|
BdrvRequestFlags write_flags)
|
2018-06-01 12:26:47 +03:00
|
|
|
{
|
|
|
|
int r;
|
2022-03-03 18:15:54 +03:00
|
|
|
IO_CODE();
|
2023-02-03 18:21:57 +03:00
|
|
|
GRAPH_RDLOCK_GUARD();
|
2022-03-03 18:15:54 +03:00
|
|
|
|
2018-06-01 12:26:47 +03:00
|
|
|
r = blk_check_byte_request(blk_in, off_in, bytes);
|
|
|
|
if (r) {
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
r = blk_check_byte_request(blk_out, off_out, bytes);
|
|
|
|
if (r) {
|
|
|
|
return r;
|
|
|
|
}
|
2023-02-03 18:21:53 +03:00
|
|
|
|
2018-06-01 12:26:47 +03:00
|
|
|
return bdrv_co_copy_range(blk_in->root, off_in,
|
|
|
|
blk_out->root, off_out,
|
2018-07-09 19:37:17 +03:00
|
|
|
bytes, read_flags, write_flags);
|
2018-06-01 12:26:47 +03:00
|
|
|
}
|
2018-12-21 20:09:07 +03:00
|
|
|
|
|
|
|
const BdrvChild *blk_root(BlockBackend *blk)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2018-12-21 20:09:07 +03:00
|
|
|
return blk->root;
|
|
|
|
}
|
2020-04-29 17:11:25 +03:00
|
|
|
|
|
|
|
int blk_make_empty(BlockBackend *blk, Error **errp)
|
|
|
|
{
|
2022-03-03 18:15:53 +03:00
|
|
|
GLOBAL_STATE_CODE();
|
2023-09-29 17:51:49 +03:00
|
|
|
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
|
|
|
|
2020-04-29 17:11:25 +03:00
|
|
|
if (!blk_is_available(blk)) {
|
|
|
|
error_setg(errp, "No medium inserted");
|
|
|
|
return -ENOMEDIUM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bdrv_make_empty(blk->root, errp);
|
|
|
|
}
|