mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches # gpg: Signature made Fri 22 Dec 2017 14:09:01 GMT # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (35 commits) block: Keep nodes drained between reopen_queue/multiple commit: Simplify reopen of base test-bdrv-drain: Test graph changes in drained section block: Allow graph changes in subtree drained section test-bdrv-drain: Recursive draining with multiple parents test-bdrv-drain: Test behaviour in coroutine context test-bdrv-drain: Tests for bdrv_subtree_drain block: Add bdrv_subtree_drained_begin/end() block: Don't notify parents in drain call chain test-bdrv-drain: Test nested drain sections block: Nested drain_end must still call callbacks block: Don't block_job_pause_all() in bdrv_drain_all() test-bdrv-drain: Test drain vs. block jobs blockjob: Pause job on draining any job BDS test-bdrv-drain: Test bs->quiesce_counter test-bdrv-drain: Test callback for bdrv_drain block: Make bdrv_drain() driver callbacks non-recursive block: Assert drain_all is only called from main AioContext block: Remove unused bdrv_requests_pending block: Mention -drive cyls/heads/secs/trans/serial/addr in deprecation chapter ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -822,6 +822,18 @@ static void bdrv_child_cb_drained_end(BdrvChild *child)
|
||||
bdrv_drained_end(bs);
|
||||
}
|
||||
|
||||
static void bdrv_child_cb_attach(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
bdrv_apply_subtree_drain(child, bs);
|
||||
}
|
||||
|
||||
static void bdrv_child_cb_detach(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
bdrv_unapply_subtree_drain(child, bs);
|
||||
}
|
||||
|
||||
static int bdrv_child_cb_inactivate(BdrvChild *child)
|
||||
{
|
||||
BlockDriverState *bs = child->opaque;
|
||||
@@ -889,6 +901,8 @@ const BdrvChildRole child_file = {
|
||||
.inherit_options = bdrv_inherited_options,
|
||||
.drained_begin = bdrv_child_cb_drained_begin,
|
||||
.drained_end = bdrv_child_cb_drained_end,
|
||||
.attach = bdrv_child_cb_attach,
|
||||
.detach = bdrv_child_cb_detach,
|
||||
.inactivate = bdrv_child_cb_inactivate,
|
||||
};
|
||||
|
||||
@@ -911,6 +925,8 @@ const BdrvChildRole child_format = {
|
||||
.inherit_options = bdrv_inherited_fmt_options,
|
||||
.drained_begin = bdrv_child_cb_drained_begin,
|
||||
.drained_end = bdrv_child_cb_drained_end,
|
||||
.attach = bdrv_child_cb_attach,
|
||||
.detach = bdrv_child_cb_detach,
|
||||
.inactivate = bdrv_child_cb_inactivate,
|
||||
};
|
||||
|
||||
@@ -953,6 +969,8 @@ static void bdrv_backing_attach(BdrvChild *c)
|
||||
parent->backing_blocker);
|
||||
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
|
||||
parent->backing_blocker);
|
||||
|
||||
bdrv_child_cb_attach(c);
|
||||
}
|
||||
|
||||
static void bdrv_backing_detach(BdrvChild *c)
|
||||
@@ -963,6 +981,8 @@ static void bdrv_backing_detach(BdrvChild *c)
|
||||
bdrv_op_unblock_all(c->bs, parent->backing_blocker);
|
||||
error_free(parent->backing_blocker);
|
||||
parent->backing_blocker = NULL;
|
||||
|
||||
bdrv_child_cb_detach(c);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1924,6 +1944,8 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
|
||||
assert(role == &child_backing || role == &child_file);
|
||||
|
||||
if (!backing) {
|
||||
int flags = bdrv_reopen_get_flags(reopen_queue, bs);
|
||||
|
||||
/* Apart from the modifications below, the same permissions are
|
||||
* forwarded and left alone as for filters */
|
||||
bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
|
||||
@@ -1936,7 +1958,9 @@ void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
|
||||
|
||||
/* bs->file always needs to be consistent because of the metadata. We
|
||||
* can never allow other users to resize or write to it. */
|
||||
perm |= BLK_PERM_CONSISTENT_READ;
|
||||
if (!(flags & BDRV_O_NO_IO)) {
|
||||
perm |= BLK_PERM_CONSISTENT_READ;
|
||||
}
|
||||
shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
|
||||
} else {
|
||||
/* We want consistent read from backing files if the parent needs it.
|
||||
@@ -1968,17 +1992,23 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
BlockDriverState *new_bs)
|
||||
{
|
||||
BlockDriverState *old_bs = child->bs;
|
||||
int i;
|
||||
|
||||
if (old_bs && new_bs) {
|
||||
assert(bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs));
|
||||
}
|
||||
if (old_bs) {
|
||||
if (old_bs->quiesce_counter && child->role->drained_end) {
|
||||
child->role->drained_end(child);
|
||||
}
|
||||
/* Detach first so that the recursive drain sections coming from @child
|
||||
* are already gone and we only end the drain sections that came from
|
||||
* elsewhere. */
|
||||
if (child->role->detach) {
|
||||
child->role->detach(child);
|
||||
}
|
||||
if (old_bs->quiesce_counter && child->role->drained_end) {
|
||||
for (i = 0; i < old_bs->quiesce_counter; i++) {
|
||||
child->role->drained_end(child);
|
||||
}
|
||||
}
|
||||
QLIST_REMOVE(child, next_parent);
|
||||
}
|
||||
|
||||
@@ -1987,9 +2017,14 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
if (new_bs) {
|
||||
QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent);
|
||||
if (new_bs->quiesce_counter && child->role->drained_begin) {
|
||||
child->role->drained_begin(child);
|
||||
for (i = 0; i < new_bs->quiesce_counter; i++) {
|
||||
child->role->drained_begin(child);
|
||||
}
|
||||
}
|
||||
|
||||
/* Attach only after starting new drained sections, so that recursive
|
||||
* drain sections coming from @child don't get an extra .drained_begin
|
||||
* callback. */
|
||||
if (child->role->attach) {
|
||||
child->role->attach(child);
|
||||
}
|
||||
@@ -2731,6 +2766,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
||||
* returns a pointer to bs_queue, which is either the newly allocated
|
||||
* bs_queue, or the existing bs_queue being used.
|
||||
*
|
||||
* bs must be drained between bdrv_reopen_queue() and bdrv_reopen_multiple().
|
||||
*/
|
||||
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
|
||||
BlockDriverState *bs,
|
||||
@@ -2746,6 +2782,11 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
|
||||
BdrvChild *child;
|
||||
QDict *old_options, *explicit_options;
|
||||
|
||||
/* Make sure that the caller remembered to use a drained section. This is
|
||||
* important to avoid graph changes between the recursive queuing here and
|
||||
* bdrv_reopen_multiple(). */
|
||||
assert(bs->quiesce_counter > 0);
|
||||
|
||||
if (bs_queue == NULL) {
|
||||
bs_queue = g_new0(BlockReopenQueue, 1);
|
||||
QSIMPLEQ_INIT(bs_queue);
|
||||
@@ -2870,6 +2911,8 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
|
||||
* If all devices prepare successfully, then the changes are committed
|
||||
* to all devices.
|
||||
*
|
||||
* All affected nodes must be drained between bdrv_reopen_queue() and
|
||||
* bdrv_reopen_multiple().
|
||||
*/
|
||||
int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp)
|
||||
{
|
||||
@@ -2879,11 +2922,8 @@ int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **er
|
||||
|
||||
assert(bs_queue != NULL);
|
||||
|
||||
aio_context_release(ctx);
|
||||
bdrv_drain_all_begin();
|
||||
aio_context_acquire(ctx);
|
||||
|
||||
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
|
||||
assert(bs_entry->state.bs->quiesce_counter > 0);
|
||||
if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
goto cleanup;
|
||||
@@ -2912,8 +2952,6 @@ cleanup:
|
||||
}
|
||||
g_free(bs_queue);
|
||||
|
||||
bdrv_drain_all_end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2923,12 +2961,18 @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
|
||||
{
|
||||
int ret = -1;
|
||||
Error *local_err = NULL;
|
||||
BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
|
||||
BlockReopenQueue *queue;
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
|
||||
queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
|
||||
ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
bdrv_subtree_drained_end(bs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4601,10 +4645,11 @@ void bdrv_img_create(const char *filename, const char *fmt,
|
||||
back_flags = flags;
|
||||
back_flags &= ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
|
||||
|
||||
backing_options = qdict_new();
|
||||
if (backing_fmt) {
|
||||
backing_options = qdict_new();
|
||||
qdict_put_str(backing_options, "driver", backing_fmt);
|
||||
}
|
||||
qdict_put_bool(backing_options, BDRV_OPT_FORCE_SHARE, true);
|
||||
|
||||
bs = bdrv_open(full_backing, NULL, backing_options, back_flags,
|
||||
&local_err);
|
||||
@@ -4754,7 +4799,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_disable_external(ctx);
|
||||
bdrv_parent_drained_begin(bs);
|
||||
bdrv_parent_drained_begin(bs, NULL);
|
||||
bdrv_drain(bs); /* ensure there are no in-flight requests */
|
||||
|
||||
while (aio_poll(ctx, false)) {
|
||||
@@ -4768,7 +4813,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
|
||||
*/
|
||||
aio_context_acquire(new_context);
|
||||
bdrv_attach_aio_context(bs, new_context);
|
||||
bdrv_parent_drained_end(bs);
|
||||
bdrv_parent_drained_end(bs, NULL);
|
||||
aio_enable_external(ctx);
|
||||
aio_context_release(new_context);
|
||||
}
|
||||
|
||||
+1
-7
@@ -277,7 +277,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
const char *filter_node_name, Error **errp)
|
||||
{
|
||||
CommitBlockJob *s;
|
||||
BlockReopenQueue *reopen_queue = NULL;
|
||||
int orig_base_flags;
|
||||
BlockDriverState *iter;
|
||||
BlockDriverState *commit_top_bs = NULL;
|
||||
@@ -299,12 +298,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
/* convert base to r/w, if necessary */
|
||||
orig_base_flags = bdrv_get_flags(base);
|
||||
if (!(orig_base_flags & BDRV_O_RDWR)) {
|
||||
reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
|
||||
orig_base_flags | BDRV_O_RDWR);
|
||||
}
|
||||
|
||||
if (reopen_queue) {
|
||||
bdrv_reopen_multiple(bdrv_get_aio_context(bs), reopen_queue, &local_err);
|
||||
bdrv_reopen(base, orig_base_flags | BDRV_O_RDWR, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
goto fail;
|
||||
|
||||
+121
-51
@@ -40,22 +40,28 @@
|
||||
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||
int64_t offset, int bytes, BdrvRequestFlags flags);
|
||||
|
||||
void bdrv_parent_drained_begin(BlockDriverState *bs)
|
||||
void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
|
||||
{
|
||||
BdrvChild *c, *next;
|
||||
|
||||
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
|
||||
if (c == ignore) {
|
||||
continue;
|
||||
}
|
||||
if (c->role->drained_begin) {
|
||||
c->role->drained_begin(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_parent_drained_end(BlockDriverState *bs)
|
||||
void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
|
||||
{
|
||||
BdrvChild *c, *next;
|
||||
|
||||
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
|
||||
if (c == ignore) {
|
||||
continue;
|
||||
}
|
||||
if (c->role->drained_end) {
|
||||
c->role->drained_end(c);
|
||||
}
|
||||
@@ -134,29 +140,13 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
|
||||
assert(old >= 1);
|
||||
}
|
||||
|
||||
/* Check if any requests are in-flight (including throttled requests) */
|
||||
bool bdrv_requests_pending(BlockDriverState *bs)
|
||||
{
|
||||
BdrvChild *child;
|
||||
|
||||
if (atomic_read(&bs->in_flight)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
if (bdrv_requests_pending(child->bs)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Coroutine *co;
|
||||
BlockDriverState *bs;
|
||||
bool done;
|
||||
bool begin;
|
||||
bool recursive;
|
||||
BdrvChild *parent;
|
||||
} BdrvCoDrainData;
|
||||
|
||||
static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
|
||||
@@ -175,8 +165,10 @@ static void coroutine_fn bdrv_drain_invoke_entry(void *opaque)
|
||||
bdrv_wakeup(bs);
|
||||
}
|
||||
|
||||
static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
|
||||
/* Recursively call BlockDriver.bdrv_co_drain_begin/end callbacks */
|
||||
static void bdrv_drain_invoke(BlockDriverState *bs, bool begin, bool recursive)
|
||||
{
|
||||
BdrvChild *child, *tmp;
|
||||
BdrvCoDrainData data = { .bs = bs, .done = false, .begin = begin};
|
||||
|
||||
if (!bs->drv || (begin && !bs->drv->bdrv_co_drain_begin) ||
|
||||
@@ -187,16 +179,19 @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
|
||||
data.co = qemu_coroutine_create(bdrv_drain_invoke_entry, &data);
|
||||
bdrv_coroutine_enter(bs, data.co);
|
||||
BDRV_POLL_WHILE(bs, !data.done);
|
||||
|
||||
if (recursive) {
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, tmp) {
|
||||
bdrv_drain_invoke(child->bs, begin, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
|
||||
static bool bdrv_drain_recurse(BlockDriverState *bs)
|
||||
{
|
||||
BdrvChild *child, *tmp;
|
||||
bool waited;
|
||||
|
||||
/* Ensure any pending metadata writes are submitted to bs->file. */
|
||||
bdrv_drain_invoke(bs, begin);
|
||||
|
||||
/* Wait for drained requests to finish */
|
||||
waited = BDRV_POLL_WHILE(bs, atomic_read(&bs->in_flight) > 0);
|
||||
|
||||
@@ -215,7 +210,7 @@ static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
|
||||
*/
|
||||
bdrv_ref(bs);
|
||||
}
|
||||
waited |= bdrv_drain_recurse(bs, begin);
|
||||
waited |= bdrv_drain_recurse(bs);
|
||||
if (in_main_loop) {
|
||||
bdrv_unref(bs);
|
||||
}
|
||||
@@ -224,6 +219,11 @@ static bool bdrv_drain_recurse(BlockDriverState *bs, bool begin)
|
||||
return waited;
|
||||
}
|
||||
|
||||
static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent);
|
||||
static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent);
|
||||
|
||||
static void bdrv_co_drain_bh_cb(void *opaque)
|
||||
{
|
||||
BdrvCoDrainData *data = opaque;
|
||||
@@ -232,9 +232,9 @@ static void bdrv_co_drain_bh_cb(void *opaque)
|
||||
|
||||
bdrv_dec_in_flight(bs);
|
||||
if (data->begin) {
|
||||
bdrv_drained_begin(bs);
|
||||
bdrv_do_drained_begin(bs, data->recursive, data->parent);
|
||||
} else {
|
||||
bdrv_drained_end(bs);
|
||||
bdrv_do_drained_end(bs, data->recursive, data->parent);
|
||||
}
|
||||
|
||||
data->done = true;
|
||||
@@ -242,7 +242,8 @@ static void bdrv_co_drain_bh_cb(void *opaque)
|
||||
}
|
||||
|
||||
static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
||||
bool begin)
|
||||
bool begin, bool recursive,
|
||||
BdrvChild *parent)
|
||||
{
|
||||
BdrvCoDrainData data;
|
||||
|
||||
@@ -256,6 +257,8 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
||||
.bs = bs,
|
||||
.done = false,
|
||||
.begin = begin,
|
||||
.recursive = recursive,
|
||||
.parent = parent,
|
||||
};
|
||||
bdrv_inc_in_flight(bs);
|
||||
aio_bh_schedule_oneshot(bdrv_get_aio_context(bs),
|
||||
@@ -267,35 +270,97 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
|
||||
assert(data.done);
|
||||
}
|
||||
|
||||
void bdrv_drained_begin(BlockDriverState *bs)
|
||||
void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent)
|
||||
{
|
||||
BdrvChild *child, *next;
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_yield_to_drain(bs, true);
|
||||
bdrv_co_yield_to_drain(bs, true, recursive, parent);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stop things in parent-to-child order */
|
||||
if (atomic_fetch_inc(&bs->quiesce_counter) == 0) {
|
||||
aio_disable_external(bdrv_get_aio_context(bs));
|
||||
bdrv_parent_drained_begin(bs);
|
||||
}
|
||||
|
||||
bdrv_drain_recurse(bs, true);
|
||||
bdrv_parent_drained_begin(bs, parent);
|
||||
bdrv_drain_invoke(bs, true, false);
|
||||
bdrv_drain_recurse(bs);
|
||||
|
||||
if (recursive) {
|
||||
bs->recursive_quiesce_counter++;
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
||||
bdrv_do_drained_begin(child->bs, true, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_drained_begin(BlockDriverState *bs)
|
||||
{
|
||||
bdrv_do_drained_begin(bs, false, NULL);
|
||||
}
|
||||
|
||||
void bdrv_subtree_drained_begin(BlockDriverState *bs)
|
||||
{
|
||||
bdrv_do_drained_begin(bs, true, NULL);
|
||||
}
|
||||
|
||||
void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
|
||||
BdrvChild *parent)
|
||||
{
|
||||
BdrvChild *child, *next;
|
||||
int old_quiesce_counter;
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_yield_to_drain(bs, false, recursive, parent);
|
||||
return;
|
||||
}
|
||||
assert(bs->quiesce_counter > 0);
|
||||
old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
|
||||
|
||||
/* Re-enable things in child-to-parent order */
|
||||
bdrv_drain_invoke(bs, false, false);
|
||||
bdrv_parent_drained_end(bs, parent);
|
||||
if (old_quiesce_counter == 1) {
|
||||
aio_enable_external(bdrv_get_aio_context(bs));
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
bs->recursive_quiesce_counter--;
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
||||
bdrv_do_drained_end(child->bs, true, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_drained_end(BlockDriverState *bs)
|
||||
{
|
||||
if (qemu_in_coroutine()) {
|
||||
bdrv_co_yield_to_drain(bs, false);
|
||||
return;
|
||||
}
|
||||
assert(bs->quiesce_counter > 0);
|
||||
if (atomic_fetch_dec(&bs->quiesce_counter) > 1) {
|
||||
return;
|
||||
}
|
||||
bdrv_do_drained_end(bs, false, NULL);
|
||||
}
|
||||
|
||||
bdrv_parent_drained_end(bs);
|
||||
bdrv_drain_recurse(bs, false);
|
||||
aio_enable_external(bdrv_get_aio_context(bs));
|
||||
void bdrv_subtree_drained_end(BlockDriverState *bs)
|
||||
{
|
||||
bdrv_do_drained_end(bs, true, NULL);
|
||||
}
|
||||
|
||||
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < new_parent->recursive_quiesce_counter; i++) {
|
||||
bdrv_do_drained_begin(child->bs, true, child);
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < old_parent->recursive_quiesce_counter; i++) {
|
||||
bdrv_do_drained_end(child->bs, true, child);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -342,14 +407,20 @@ void bdrv_drain_all_begin(void)
|
||||
BdrvNextIterator it;
|
||||
GSList *aio_ctxs = NULL, *ctx;
|
||||
|
||||
block_job_pause_all();
|
||||
/* BDRV_POLL_WHILE() for a node can only be called from its own I/O thread
|
||||
* or the main loop AioContext. We potentially use BDRV_POLL_WHILE() on
|
||||
* nodes in several different AioContexts, so make sure we're in the main
|
||||
* context. */
|
||||
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
|
||||
|
||||
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
/* Stop things in parent-to-child order */
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_parent_drained_begin(bs);
|
||||
aio_disable_external(aio_context);
|
||||
bdrv_parent_drained_begin(bs, NULL);
|
||||
bdrv_drain_invoke(bs, true, true);
|
||||
aio_context_release(aio_context);
|
||||
|
||||
if (!g_slist_find(aio_ctxs, aio_context)) {
|
||||
@@ -372,7 +443,7 @@ void bdrv_drain_all_begin(void)
|
||||
aio_context_acquire(aio_context);
|
||||
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
if (aio_context == bdrv_get_aio_context(bs)) {
|
||||
waited |= bdrv_drain_recurse(bs, true);
|
||||
waited |= bdrv_drain_recurse(bs);
|
||||
}
|
||||
}
|
||||
aio_context_release(aio_context);
|
||||
@@ -390,14 +461,13 @@ void bdrv_drain_all_end(void)
|
||||
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
|
||||
AioContext *aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
/* Re-enable things in child-to-parent order */
|
||||
aio_context_acquire(aio_context);
|
||||
bdrv_drain_invoke(bs, false, true);
|
||||
bdrv_parent_drained_end(bs, NULL);
|
||||
aio_enable_external(aio_context);
|
||||
bdrv_parent_drained_end(bs);
|
||||
bdrv_drain_recurse(bs, false);
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
block_job_resume_all();
|
||||
}
|
||||
|
||||
void bdrv_drain_all(void)
|
||||
|
||||
+8
-43
@@ -1672,34 +1672,12 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
|
||||
return status;
|
||||
}
|
||||
|
||||
/* handle reading after the end of the backing file */
|
||||
int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
|
||||
int64_t offset, int bytes)
|
||||
{
|
||||
uint64_t bs_size = bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
int n1;
|
||||
|
||||
if ((offset + bytes) <= bs_size) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
if (offset >= bs_size) {
|
||||
n1 = 0;
|
||||
} else {
|
||||
n1 = bs_size - offset;
|
||||
}
|
||||
|
||||
qemu_iovec_memset(qiov, n1, 0, bytes - n1);
|
||||
|
||||
return n1;
|
||||
}
|
||||
|
||||
static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
uint64_t bytes, QEMUIOVector *qiov,
|
||||
int flags)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int offset_in_cluster, n1;
|
||||
int offset_in_cluster;
|
||||
int ret;
|
||||
unsigned int cur_bytes; /* number of bytes in current iteration */
|
||||
uint64_t cluster_offset = 0;
|
||||
@@ -1734,26 +1712,13 @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||
case QCOW2_CLUSTER_UNALLOCATED:
|
||||
|
||||
if (bs->backing) {
|
||||
/* read from the base image */
|
||||
n1 = qcow2_backing_read1(bs->backing->bs, &hd_qiov,
|
||||
offset, cur_bytes);
|
||||
if (n1 > 0) {
|
||||
QEMUIOVector local_qiov;
|
||||
|
||||
qemu_iovec_init(&local_qiov, hd_qiov.niov);
|
||||
qemu_iovec_concat(&local_qiov, &hd_qiov, 0, n1);
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_preadv(bs->backing, offset, n1,
|
||||
&local_qiov, 0);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
|
||||
qemu_iovec_destroy(&local_qiov);
|
||||
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
ret = bdrv_co_preadv(bs->backing, offset, cur_bytes,
|
||||
&hd_qiov, 0);
|
||||
qemu_co_mutex_lock(&s->lock);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
/* Note: in this case, no need to wait */
|
||||
|
||||
@@ -528,9 +528,6 @@ uint32_t offset_to_reftable_index(BDRVQcow2State *s, uint64_t offset)
|
||||
}
|
||||
|
||||
/* qcow2.c functions */
|
||||
int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,
|
||||
int64_t sector_num, int nb_sectors);
|
||||
|
||||
int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size,
|
||||
int refcount_order, bool generous_increase,
|
||||
uint64_t *refblock_count);
|
||||
|
||||
@@ -394,6 +394,9 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
|
||||
new_secondary_flags = s->orig_secondary_flags;
|
||||
}
|
||||
|
||||
bdrv_subtree_drained_begin(s->hidden_disk->bs);
|
||||
bdrv_subtree_drained_begin(s->secondary_disk->bs);
|
||||
|
||||
if (orig_hidden_flags != new_hidden_flags) {
|
||||
reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL,
|
||||
new_hidden_flags);
|
||||
@@ -409,6 +412,9 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
|
||||
reopen_queue, &local_err);
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
bdrv_subtree_drained_end(s->hidden_disk->bs);
|
||||
bdrv_subtree_drained_end(s->secondary_disk->bs);
|
||||
}
|
||||
|
||||
static void backup_job_cleanup(BlockDriverState *bs)
|
||||
|
||||
-11
@@ -734,10 +734,6 @@ QemuOptsList qemu_legacy_drive_opts = {
|
||||
.name = "trans",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "chs translation (auto, lba, none)",
|
||||
},{
|
||||
.name = "boot",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "(deprecated, ignored)",
|
||||
},{
|
||||
.name = "addr",
|
||||
.type = QEMU_OPT_STRING,
|
||||
@@ -873,13 +869,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Deprecated option boot=[on|off] */
|
||||
if (qemu_opt_get(legacy_opts, "boot") != NULL) {
|
||||
fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be "
|
||||
"ignored. Future versions will reject this parameter. Please "
|
||||
"update your scripts.\n");
|
||||
}
|
||||
|
||||
/* Other deprecated options */
|
||||
if (!qtest_enabled()) {
|
||||
for (i = 0; i < ARRAY_SIZE(deprecated); i++) {
|
||||
|
||||
+9
-13
@@ -234,26 +234,23 @@ static char *child_job_get_parent_desc(BdrvChild *c)
|
||||
job->id);
|
||||
}
|
||||
|
||||
static const BdrvChildRole child_job = {
|
||||
.get_parent_desc = child_job_get_parent_desc,
|
||||
.stay_at_node = true,
|
||||
};
|
||||
|
||||
static void block_job_drained_begin(void *opaque)
|
||||
static void child_job_drained_begin(BdrvChild *c)
|
||||
{
|
||||
BlockJob *job = opaque;
|
||||
BlockJob *job = c->opaque;
|
||||
block_job_pause(job);
|
||||
}
|
||||
|
||||
static void block_job_drained_end(void *opaque)
|
||||
static void child_job_drained_end(BdrvChild *c)
|
||||
{
|
||||
BlockJob *job = opaque;
|
||||
BlockJob *job = c->opaque;
|
||||
block_job_resume(job);
|
||||
}
|
||||
|
||||
static const BlockDevOps block_job_dev_ops = {
|
||||
.drained_begin = block_job_drained_begin,
|
||||
.drained_end = block_job_drained_end,
|
||||
static const BdrvChildRole child_job = {
|
||||
.get_parent_desc = child_job_get_parent_desc,
|
||||
.drained_begin = child_job_drained_begin,
|
||||
.drained_end = child_job_drained_end,
|
||||
.stay_at_node = true,
|
||||
};
|
||||
|
||||
void block_job_remove_all_bdrv(BlockJob *job)
|
||||
@@ -715,7 +712,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort);
|
||||
bs->job = job;
|
||||
|
||||
blk_set_dev_ops(blk, &block_job_dev_ops, job);
|
||||
bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker);
|
||||
|
||||
QLIST_INSERT_HEAD(&block_jobs, job, job_list);
|
||||
|
||||
@@ -2318,7 +2318,6 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
BlockBackend *local_blk = NULL;
|
||||
AioContext *aio_context;
|
||||
const char* device = qdict_get_str(qdict, "device");
|
||||
const char* command = qdict_get_str(qdict, "command");
|
||||
Error *err = NULL;
|
||||
@@ -2338,9 +2337,6 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
}
|
||||
|
||||
aio_context = blk_get_aio_context(blk);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
/*
|
||||
* Notably absent: Proper permission management. This is sad, but it seems
|
||||
* almost impossible to achieve without changing the semantics and thereby
|
||||
@@ -2368,8 +2364,6 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
||||
*/
|
||||
qemuio_command(blk, command);
|
||||
|
||||
aio_context_release(aio_context);
|
||||
|
||||
fail:
|
||||
blk_unref(local_blk);
|
||||
hmp_handle_error(mon, &err);
|
||||
|
||||
+297
-52
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,99 @@ virtio_blk_submit_multireq(void *vdev, void *mrb, int start, int num_reqs, uint6
|
||||
hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
|
||||
hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d"
|
||||
|
||||
# hw/block/nvme.c
|
||||
# nvme traces for successful events
|
||||
nvme_irq_msix(uint32_t vector) "raising MSI-X IRQ vector %u"
|
||||
nvme_irq_pin(void) "pulsing IRQ pin"
|
||||
nvme_irq_masked(void) "IRQ is masked"
|
||||
nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2=0x%"PRIx64""
|
||||
nvme_rw(char const *verb, uint32_t blk_count, uint64_t byte_count, uint64_t lba) "%s %"PRIu32" blocks (%"PRIu64" bytes) from LBA %"PRIu64""
|
||||
nvme_create_sq(uint64_t addr, uint16_t sqid, uint16_t cqid, uint16_t qsize, uint16_t qflags) "create submission queue, addr=0x%"PRIx64", sqid=%"PRIu16", cqid=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16""
|
||||
nvme_create_cq(uint64_t addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t qflags, int ien) "create completion queue, addr=0x%"PRIx64", cqid=%"PRIu16", vector=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16", ien=%d"
|
||||
nvme_del_sq(uint16_t qid) "deleting submission queue sqid=%"PRIu16""
|
||||
nvme_del_cq(uint16_t cqid) "deleted completion queue, sqid=%"PRIu16""
|
||||
nvme_identify_ctrl(void) "identify controller"
|
||||
nvme_identify_ns(uint16_t ns) "identify namespace, nsid=%"PRIu16""
|
||||
nvme_identify_nslist(uint16_t ns) "identify namespace list, nsid=%"PRIu16""
|
||||
nvme_getfeat_vwcache(char const* result) "get feature volatile write cache, result=%s"
|
||||
nvme_getfeat_numq(int result) "get feature number of queues, result=%d"
|
||||
nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d"
|
||||
nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64""
|
||||
nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64""
|
||||
nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64""
|
||||
nvme_mmio_aqattr(uint64_t data) "wrote MMIO, admin queue attributes=0x%"PRIx64""
|
||||
nvme_mmio_asqaddr(uint64_t data) "wrote MMIO, admin submission queue address=0x%"PRIx64""
|
||||
nvme_mmio_acqaddr(uint64_t data) "wrote MMIO, admin completion queue address=0x%"PRIx64""
|
||||
nvme_mmio_asqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin submission queue high half=0x%"PRIx64", new_address=0x%"PRIx64""
|
||||
nvme_mmio_acqaddr_hi(uint64_t data, uint64_t new_addr) "wrote MMIO, admin completion queue high half=0x%"PRIx64", new_address=0x%"PRIx64""
|
||||
nvme_mmio_start_success(void) "setting controller enable bit succeeded"
|
||||
nvme_mmio_stopped(void) "cleared controller enable bit"
|
||||
nvme_mmio_shutdown_set(void) "shutdown bit set"
|
||||
nvme_mmio_shutdown_cleared(void) "shutdown bit cleared"
|
||||
|
||||
# nvme traces for error conditions
|
||||
nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size"
|
||||
nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is null or not page aligned: 0x%"PRIx64""
|
||||
nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64""
|
||||
nvme_err_invalid_prp2_missing(void) "PRP2 is null and more data to be transferred"
|
||||
nvme_err_invalid_field(void) "invalid field"
|
||||
nvme_err_invalid_prp(void) "invalid PRP"
|
||||
nvme_err_invalid_sgl(void) "invalid SGL"
|
||||
nvme_err_invalid_ns(uint32_t ns, uint32_t limit) "invalid namespace %u not within 1-%u"
|
||||
nvme_err_invalid_opc(uint8_t opc) "invalid opcode 0x%"PRIx8""
|
||||
nvme_err_invalid_admin_opc(uint8_t opc) "invalid admin opcode 0x%"PRIx8""
|
||||
nvme_err_invalid_lba_range(uint64_t start, uint64_t len, uint64_t limit) "Invalid LBA start=%"PRIu64" len=%"PRIu64" limit=%"PRIu64""
|
||||
nvme_err_invalid_del_sq(uint16_t qid) "invalid submission queue deletion, sid=%"PRIu16""
|
||||
nvme_err_invalid_create_sq_cqid(uint16_t cqid) "failed creating submission queue, invalid cqid=%"PRIu16""
|
||||
nvme_err_invalid_create_sq_sqid(uint16_t sqid) "failed creating submission queue, invalid sqid=%"PRIu16""
|
||||
nvme_err_invalid_create_sq_size(uint16_t qsize) "failed creating submission queue, invalid qsize=%"PRIu16""
|
||||
nvme_err_invalid_create_sq_addr(uint64_t addr) "failed creating submission queue, addr=0x%"PRIx64""
|
||||
nvme_err_invalid_create_sq_qflags(uint16_t qflags) "failed creating submission queue, qflags=%"PRIu16""
|
||||
nvme_err_invalid_del_cq_cqid(uint16_t cqid) "failed deleting completion queue, cqid=%"PRIu16""
|
||||
nvme_err_invalid_del_cq_notempty(uint16_t cqid) "failed deleting completion queue, it is not empty, cqid=%"PRIu16""
|
||||
nvme_err_invalid_create_cq_cqid(uint16_t cqid) "failed creating completion queue, cqid=%"PRIu16""
|
||||
nvme_err_invalid_create_cq_size(uint16_t size) "failed creating completion queue, size=%"PRIu16""
|
||||
nvme_err_invalid_create_cq_addr(uint64_t addr) "failed creating completion queue, addr=0x%"PRIx64""
|
||||
nvme_err_invalid_create_cq_vector(uint16_t vector) "failed creating completion queue, vector=%"PRIu16""
|
||||
nvme_err_invalid_create_cq_qflags(uint16_t qflags) "failed creating completion queue, qflags=%"PRIu16""
|
||||
nvme_err_invalid_identify_cns(uint16_t cns) "identify, invalid cns=0x%"PRIx16""
|
||||
nvme_err_invalid_getfeat(int dw10) "invalid get features, dw10=0x%"PRIx32""
|
||||
nvme_err_invalid_setfeat(uint32_t dw10) "invalid set features, dw10=0x%"PRIx32""
|
||||
nvme_err_startfail_cq(void) "nvme_start_ctrl failed because there are non-admin completion queues"
|
||||
nvme_err_startfail_sq(void) "nvme_start_ctrl failed because there are non-admin submission queues"
|
||||
nvme_err_startfail_nbarasq(void) "nvme_start_ctrl failed because the admin submission queue address is null"
|
||||
nvme_err_startfail_nbaracq(void) "nvme_start_ctrl failed because the admin completion queue address is null"
|
||||
nvme_err_startfail_asq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin submission queue address is misaligned: 0x%"PRIx64""
|
||||
nvme_err_startfail_acq_misaligned(uint64_t addr) "nvme_start_ctrl failed because the admin completion queue address is misaligned: 0x%"PRIx64""
|
||||
nvme_err_startfail_page_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too small: log2size=%u, min=%u"
|
||||
nvme_err_startfail_page_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the page size is too large: log2size=%u, max=%u"
|
||||
nvme_err_startfail_cqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too small: log2size=%u, min=%u"
|
||||
nvme_err_startfail_cqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the completion queue entry size is too large: log2size=%u, max=%u"
|
||||
nvme_err_startfail_sqent_too_small(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too small: log2size=%u, min=%u"
|
||||
nvme_err_startfail_sqent_too_large(uint8_t log2ps, uint8_t maxlog2ps) "nvme_start_ctrl failed because the submission queue entry size is too large: log2size=%u, max=%u"
|
||||
nvme_err_startfail_asqent_sz_zero(void) "nvme_start_ctrl failed because the admin submission queue size is zero"
|
||||
nvme_err_startfail_acqent_sz_zero(void) "nvme_start_ctrl failed because the admin completion queue size is zero"
|
||||
nvme_err_startfail(void) "setting controller enable bit failed"
|
||||
|
||||
# Traces for undefined behavior
|
||||
nvme_ub_mmiowr_misaligned32(uint64_t offset) "MMIO write not 32-bit aligned, offset=0x%"PRIx64""
|
||||
nvme_ub_mmiowr_toosmall(uint64_t offset, unsigned size) "MMIO write smaller than 32 bits, offset=0x%"PRIx64", size=%u"
|
||||
nvme_ub_mmiowr_intmask_with_msix(void) "undefined access to interrupt mask set when MSI-X is enabled"
|
||||
nvme_ub_mmiowr_ro_csts(void) "attempted to set a read only bit of controller status"
|
||||
nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CAP.NSSRS is zero (not supported)"
|
||||
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
|
||||
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
|
||||
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
|
||||
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
|
||||
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
|
||||
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
|
||||
nvme_ub_mmiord_invalid_ofs(uint64_t offset) "MMIO read beyond last register, offset=0x%"PRIx64", returning 0"
|
||||
nvme_ub_db_wr_misaligned(uint64_t offset) "doorbell write not 32-bit aligned, offset=0x%"PRIx64", ignoring"
|
||||
nvme_ub_db_wr_invalid_cq(uint32_t qid) "completion queue doorbell write for nonexistent queue, cqid=%"PRIu32", ignoring"
|
||||
nvme_ub_db_wr_invalid_cqhead(uint32_t qid, uint16_t new_head) "completion queue doorbell write value beyond queue size, cqid=%"PRIu32", new_head=%"PRIu16", ignoring"
|
||||
nvme_ub_db_wr_invalid_sq(uint32_t qid) "submission queue doorbell write for nonexistent queue, sqid=%"PRIu32", ignoring"
|
||||
nvme_ub_db_wr_invalid_sqtail(uint32_t qid, uint16_t new_tail) "submission queue doorbell write value beyond queue size, sqid=%"PRIu32", new_head=%"PRIu16", ignoring"
|
||||
|
||||
# hw/block/xen_disk.c
|
||||
xen_disk_alloc(char *name) "%s"
|
||||
xen_disk_init(char *name) "%s"
|
||||
|
||||
+13
-2
@@ -585,7 +585,7 @@ void bdrv_io_unplug(BlockDriverState *bs);
|
||||
* Begin a quiesced section of all users of @bs. This is part of
|
||||
* bdrv_drained_begin.
|
||||
*/
|
||||
void bdrv_parent_drained_begin(BlockDriverState *bs);
|
||||
void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore);
|
||||
|
||||
/**
|
||||
* bdrv_parent_drained_end:
|
||||
@@ -593,7 +593,7 @@ void bdrv_parent_drained_begin(BlockDriverState *bs);
|
||||
* End a quiesced section of all users of @bs. This is part of
|
||||
* bdrv_drained_end.
|
||||
*/
|
||||
void bdrv_parent_drained_end(BlockDriverState *bs);
|
||||
void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore);
|
||||
|
||||
/**
|
||||
* bdrv_drained_begin:
|
||||
@@ -607,6 +607,12 @@ void bdrv_parent_drained_end(BlockDriverState *bs);
|
||||
*/
|
||||
void bdrv_drained_begin(BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* Like bdrv_drained_begin, but recursively begins a quiesced section for
|
||||
* exclusive access to all child nodes as well.
|
||||
*/
|
||||
void bdrv_subtree_drained_begin(BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* bdrv_drained_end:
|
||||
*
|
||||
@@ -614,6 +620,11 @@ void bdrv_drained_begin(BlockDriverState *bs);
|
||||
*/
|
||||
void bdrv_drained_end(BlockDriverState *bs);
|
||||
|
||||
/**
|
||||
* End a quiescent section started by bdrv_subtree_drained_begin().
|
||||
*/
|
||||
void bdrv_subtree_drained_end(BlockDriverState *bs);
|
||||
|
||||
void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child,
|
||||
Error **errp);
|
||||
void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);
|
||||
|
||||
@@ -717,6 +717,8 @@ struct BlockDriverState {
|
||||
|
||||
/* Accessed with atomic ops. */
|
||||
int quiesce_counter;
|
||||
int recursive_quiesce_counter;
|
||||
|
||||
unsigned int write_gen; /* Current data generation */
|
||||
|
||||
/* Protected by reqs_lock. */
|
||||
@@ -768,6 +770,9 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child,
|
||||
int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags);
|
||||
|
||||
void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent);
|
||||
void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent);
|
||||
|
||||
int get_tmp_filename(char *filename, int size);
|
||||
BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
|
||||
const char *filename);
|
||||
@@ -1045,7 +1050,6 @@ bool blk_dev_is_tray_open(BlockBackend *blk);
|
||||
bool blk_dev_is_medium_locked(BlockBackend *blk);
|
||||
|
||||
void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes);
|
||||
bool bdrv_requests_pending(BlockDriverState *bs);
|
||||
|
||||
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out);
|
||||
void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in);
|
||||
|
||||
@@ -3918,6 +3918,10 @@
|
||||
# does not support all kinds of operations, all kinds of children, nor
|
||||
# all block drivers.
|
||||
#
|
||||
# FIXME Removing children from a quorum node means introducing gaps in the
|
||||
# child indices. This cannot be represented in the 'children' list of
|
||||
# BlockdevOptionsQuorum, as returned by .bdrv_refresh_filename().
|
||||
#
|
||||
# Warning: The data in a new quorum child MUST be consistent with that of
|
||||
# the rest of the array.
|
||||
#
|
||||
|
||||
+15
-14
@@ -2589,12 +2589,6 @@ deprecated.
|
||||
|
||||
@section System emulator command line arguments
|
||||
|
||||
@subsection -drive boot=on|off (since 1.3.0)
|
||||
|
||||
The ``boot=on|off'' option to the ``-drive'' argument is
|
||||
ignored. Applications should use the ``bootindex=N'' parameter
|
||||
to set an absolute ordering between devices instead.
|
||||
|
||||
@subsection -tdf (since 1.3.0)
|
||||
|
||||
The ``-tdf'' argument is ignored. The behaviour implemented
|
||||
@@ -2690,20 +2684,27 @@ longer be directly supported in QEMU.
|
||||
The ``-drive if=scsi'' argument is replaced by the the
|
||||
``-device BUS-TYPE'' argument combined with ``-drive if=none''.
|
||||
|
||||
@subsection -drive cyls=...,heads=...,secs=...,trans=... (since 2.10.0)
|
||||
|
||||
The drive geometry arguments are replaced by the the geometry arguments
|
||||
that can be specified with the ``-device'' parameter.
|
||||
|
||||
@subsection -drive serial=... (since 2.10.0)
|
||||
|
||||
The drive serial argument is replaced by the the serial argument
|
||||
that can be specified with the ``-device'' parameter.
|
||||
|
||||
@subsection -drive addr=... (since 2.10.0)
|
||||
|
||||
The drive addr argument is replaced by the the addr argument
|
||||
that can be specified with the ``-device'' parameter.
|
||||
|
||||
@subsection -net dump (since 2.10.0)
|
||||
|
||||
The ``--net dump'' argument is now replaced with the
|
||||
``-object filter-dump'' argument which works in combination
|
||||
with the modern ``-netdev`` backends instead.
|
||||
|
||||
@subsection -hdachs (since 2.10.0)
|
||||
|
||||
The ``-hdachs'' argument is now a synonym for setting
|
||||
the ``cyls'', ``heads'', ``secs'', and ``trans'' properties
|
||||
on the ``ide-hd'' device using the ``-device'' argument.
|
||||
The new syntax allows different settings to be provided
|
||||
per disk.
|
||||
|
||||
@subsection -usbdevice (since 2.10.0)
|
||||
|
||||
The ``-usbdevice DEV'' argument is now a synonym for setting
|
||||
|
||||
@@ -2013,8 +2013,11 @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
|
||||
opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
|
||||
qemu_opts_reset(&reopen_opts);
|
||||
|
||||
bdrv_subtree_drained_begin(bs);
|
||||
brq = bdrv_reopen_queue(NULL, bs, opts, flags);
|
||||
bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
|
||||
bdrv_subtree_drained_end(bs);
|
||||
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
} else {
|
||||
|
||||
+2
-17
@@ -846,8 +846,8 @@ of available connectors of a given interface type.
|
||||
@item media=@var{media}
|
||||
This option defines the type of the media: disk or cdrom.
|
||||
@item cyls=@var{c},heads=@var{h},secs=@var{s}[,trans=@var{t}]
|
||||
These options have the same definition as they have in @option{-hdachs}.
|
||||
These parameters are deprecated, use the corresponding parameters
|
||||
Force disk physical geometry and the optional BIOS translation (trans=none or
|
||||
lba). These parameters are deprecated, use the corresponding parameters
|
||||
of @code{-device} instead.
|
||||
@item snapshot=@var{snapshot}
|
||||
@var{snapshot} is "on" or "off" and controls snapshot mode for the given drive
|
||||
@@ -1027,21 +1027,6 @@ the raw disk image you use is not written back. You can however force
|
||||
the write back by pressing @key{C-a s} (@pxref{disk_images}).
|
||||
ETEXI
|
||||
|
||||
DEF("hdachs", HAS_ARG, QEMU_OPTION_hdachs, \
|
||||
"-hdachs c,h,s[,t]\n" \
|
||||
" force hard disk 0 physical geometry and the optional BIOS\n" \
|
||||
" translation (t=none or lba) (usually QEMU can guess them)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -hdachs @var{c},@var{h},@var{s},[,@var{t}]
|
||||
@findex -hdachs
|
||||
Force hard disk 0 physical geometry (1 <= @var{c} <= 16383, 1 <=
|
||||
@var{h} <= 16, 1 <= @var{s} <= 63) and optionally force the BIOS
|
||||
translation mode (@var{t}=none, lba or auto). Usually QEMU can guess
|
||||
all those parameters. This option is deprecated, please use
|
||||
@code{-device ide-hd,cyls=c,heads=h,secs=s,...} instead.
|
||||
ETEXI
|
||||
|
||||
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
|
||||
"-fsdev fsdriver,id=id[,path=path,][security_model={mapped-xattr|mapped-file|passthrough|none}]\n"
|
||||
" [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd][,fmode=fmode][,dmode=dmode]\n"
|
||||
|
||||
@@ -80,6 +80,7 @@ gcov-files-test-thread-pool-y = thread-pool.c
|
||||
gcov-files-test-hbitmap-y = util/hbitmap.c
|
||||
check-unit-y += tests/test-hbitmap$(EXESUF)
|
||||
gcov-files-test-hbitmap-y = blockjob.c
|
||||
check-unit-y += tests/test-bdrv-drain$(EXESUF)
|
||||
check-unit-y += tests/test-blockjob$(EXESUF)
|
||||
check-unit-y += tests/test-blockjob-txn$(EXESUF)
|
||||
check-unit-y += tests/test-x86-cpuid$(EXESUF)
|
||||
@@ -595,6 +596,7 @@ tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
|
||||
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
|
||||
tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
|
||||
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
|
||||
tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(test-util-obj-y)
|
||||
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
|
||||
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
|
||||
tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
|
||||
|
||||
@@ -60,6 +60,10 @@ echo '=== Copy-on-read ==='
|
||||
echo
|
||||
|
||||
# Prep the images
|
||||
# VPC rounds image sizes to a specific geometry, force a specific size.
|
||||
if [ "$IMGFMT" = "vpc" ]; then
|
||||
IMGOPTS=$(_optstr_add "$IMGOPTS" "force_size")
|
||||
fi
|
||||
_make_test_img 4G
|
||||
$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
|
||||
IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
|
||||
|
||||
@@ -134,7 +134,8 @@ _filter_img_create()
|
||||
-e "s# log_size=[0-9]\\+##g" \
|
||||
-e "s# refcount_bits=[0-9]\\+##g" \
|
||||
-e "s# key-secret=[a-zA-Z0-9]\\+##g" \
|
||||
-e "s# iter-time=[0-9]\\+##g"
|
||||
-e "s# iter-time=[0-9]\\+##g" \
|
||||
-e "s# force_size=\\(on\\|off\\)##g"
|
||||
}
|
||||
|
||||
_filter_img_info()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user