Compare commits
21 Commits
qdev-array
...
qmp-bql-la
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe33d8e072 | ||
|
|
a800b3d01e | ||
|
|
5c2003c4dc | ||
| 4b8fe49d54 | |||
|
|
c78cc95092 | ||
|
|
cb0889a971 | ||
|
|
13372539a9 | ||
|
|
de7e85364a | ||
|
|
7d0fad7309 | ||
|
|
be4827d4b3 | ||
|
|
83979a2599 | ||
|
|
23cbf06c46 | ||
|
|
c7470ec453 | ||
|
|
75754c77a1 | ||
|
|
983dc8c938 | ||
|
|
65ff652e2b | ||
|
|
5baee68874 | ||
|
|
4e781916d2 | ||
|
|
931516de7c | ||
|
|
85739ecf0c | ||
|
|
b1d28fadec |
103
block.c
103
block.c
@@ -2854,7 +2854,7 @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
|
||||
* Replaces the node that a BdrvChild points to without updating permissions.
|
||||
*
|
||||
* If @new_bs is non-NULL, the parent of @child must already be drained through
|
||||
* @child.
|
||||
* @child and the caller must hold the AioContext lock for @new_bs.
|
||||
*/
|
||||
static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
BlockDriverState *new_bs)
|
||||
@@ -2893,7 +2893,7 @@ static void bdrv_replace_child_noperm(BdrvChild *child,
|
||||
}
|
||||
|
||||
/* TODO Pull this up into the callers to avoid polling here */
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock(new_bs);
|
||||
if (old_bs) {
|
||||
if (child->klass->detach) {
|
||||
child->klass->detach(child);
|
||||
@@ -2989,6 +2989,10 @@ static TransactionActionDrv bdrv_attach_child_common_drv = {
|
||||
* Function doesn't update permissions, caller is responsible for this.
|
||||
*
|
||||
* Returns new created child.
|
||||
*
|
||||
* The caller must hold the AioContext lock for @child_bs. Both @parent_bs and
|
||||
* @child_bs can move to a different AioContext in this function. Callers must
|
||||
* make sure that their AioContext locking is still correct after this.
|
||||
*/
|
||||
static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
|
||||
const char *child_name,
|
||||
@@ -2999,7 +3003,7 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
|
||||
Transaction *tran, Error **errp)
|
||||
{
|
||||
BdrvChild *new_child;
|
||||
AioContext *parent_ctx;
|
||||
AioContext *parent_ctx, *new_child_ctx;
|
||||
AioContext *child_ctx = bdrv_get_aio_context(child_bs);
|
||||
|
||||
assert(child_class->get_parent_desc);
|
||||
@@ -3050,6 +3054,12 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
|
||||
}
|
||||
}
|
||||
|
||||
new_child_ctx = bdrv_get_aio_context(child_bs);
|
||||
if (new_child_ctx != child_ctx) {
|
||||
aio_context_release(child_ctx);
|
||||
aio_context_acquire(new_child_ctx);
|
||||
}
|
||||
|
||||
bdrv_ref(child_bs);
|
||||
/*
|
||||
* Let every new BdrvChild start with a drained parent. Inserting the child
|
||||
@@ -3079,11 +3089,20 @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
|
||||
};
|
||||
tran_add(tran, &bdrv_attach_child_common_drv, s);
|
||||
|
||||
if (new_child_ctx != child_ctx) {
|
||||
aio_context_release(new_child_ctx);
|
||||
aio_context_acquire(child_ctx);
|
||||
}
|
||||
|
||||
return new_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function doesn't update permissions, caller is responsible for this.
|
||||
*
|
||||
* The caller must hold the AioContext lock for @child_bs. Both @parent_bs and
|
||||
* @child_bs can move to a different AioContext in this function. Callers must
|
||||
* make sure that their AioContext locking is still correct after this.
|
||||
*/
|
||||
static BdrvChild *bdrv_attach_child_noperm(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
@@ -3347,6 +3366,10 @@ static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
|
||||
* callers which don't need their own reference any more must call bdrv_unref().
|
||||
*
|
||||
* Function doesn't update permissions, caller is responsible for this.
|
||||
*
|
||||
* The caller must hold the AioContext lock for @child_bs. Both @parent_bs and
|
||||
* @child_bs can move to a different AioContext in this function. Callers must
|
||||
* make sure that their AioContext locking is still correct after this.
|
||||
*/
|
||||
static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
@@ -3435,6 +3458,11 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller must hold the AioContext lock for @backing_hd. Both @bs and
|
||||
* @backing_hd can move to a different AioContext in this function. Callers must
|
||||
* make sure that their AioContext locking is still correct after this.
|
||||
*/
|
||||
static int bdrv_set_backing_noperm(BlockDriverState *bs,
|
||||
BlockDriverState *backing_hd,
|
||||
Transaction *tran, Error **errp)
|
||||
@@ -3498,6 +3526,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
int ret = 0;
|
||||
bool implicit_backing = false;
|
||||
BlockDriverState *backing_hd;
|
||||
AioContext *backing_hd_ctx;
|
||||
QDict *options;
|
||||
QDict *tmp_parent_options = NULL;
|
||||
Error *local_err = NULL;
|
||||
@@ -3582,8 +3611,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
|
||||
/* Hook up the backing file link; drop our reference, bs owns the
|
||||
* backing_hd reference now */
|
||||
backing_hd_ctx = bdrv_get_aio_context(backing_hd);
|
||||
aio_context_acquire(backing_hd_ctx);
|
||||
ret = bdrv_set_backing_hd(bs, backing_hd, errp);
|
||||
bdrv_unref(backing_hd);
|
||||
aio_context_release(backing_hd_ctx);
|
||||
|
||||
if (ret < 0) {
|
||||
goto free_exit;
|
||||
}
|
||||
@@ -3654,6 +3687,7 @@ done:
|
||||
*
|
||||
* The BlockdevRef will be removed from the options QDict.
|
||||
*
|
||||
* The caller must hold the lock of the main AioContext and no other AioContext.
|
||||
* @parent can move to a different AioContext in this function. Callers must
|
||||
* make sure that their AioContext locking is still correct after this.
|
||||
*/
|
||||
@@ -3665,6 +3699,8 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
AioContext *ctx;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
@@ -3674,13 +3710,19 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(ctx);
|
||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
aio_context_release(ctx);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
||||
*
|
||||
* The caller must hold the lock of the main AioContext and no other AioContext.
|
||||
* @parent can move to a different AioContext in this function. Callers must
|
||||
* make sure that their AioContext locking is still correct after this.
|
||||
*/
|
||||
@@ -3757,6 +3799,7 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||
int64_t total_size;
|
||||
QemuOpts *opts = NULL;
|
||||
BlockDriverState *bs_snapshot = NULL;
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
int ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
@@ -3765,7 +3808,10 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||
instead of opening 'filename' directly */
|
||||
|
||||
/* Get the required size from the image */
|
||||
aio_context_acquire(ctx);
|
||||
total_size = bdrv_getlength(bs);
|
||||
aio_context_release(ctx);
|
||||
|
||||
if (total_size < 0) {
|
||||
error_setg_errno(errp, -total_size, "Could not get image size");
|
||||
goto out;
|
||||
@@ -3799,7 +3845,10 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
||||
goto out;
|
||||
}
|
||||
|
||||
aio_context_acquire(ctx);
|
||||
ret = bdrv_append(bs_snapshot, bs, errp);
|
||||
aio_context_release(ctx);
|
||||
|
||||
if (ret < 0) {
|
||||
bs_snapshot = NULL;
|
||||
goto out;
|
||||
@@ -3843,6 +3892,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
Error *local_err = NULL;
|
||||
QDict *snapshot_options = NULL;
|
||||
int snapshot_flags = 0;
|
||||
AioContext *ctx = qemu_get_aio_context();
|
||||
|
||||
assert(!child_class || !flags);
|
||||
assert(!child_class == !parent);
|
||||
@@ -3980,9 +4030,13 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
/* Not requesting BLK_PERM_CONSISTENT_READ because we're only
|
||||
* looking at the header to guess the image format. This works even
|
||||
* in cases where a guest would not see a consistent state. */
|
||||
file = blk_new(bdrv_get_aio_context(file_bs), 0, BLK_PERM_ALL);
|
||||
ctx = bdrv_get_aio_context(file_bs);
|
||||
aio_context_acquire(ctx);
|
||||
file = blk_new(ctx, 0, BLK_PERM_ALL);
|
||||
blk_insert_bs(file, file_bs, &local_err);
|
||||
bdrv_unref(file_bs);
|
||||
aio_context_release(ctx);
|
||||
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4028,8 +4082,13 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* The AioContext could have changed during bdrv_open_common() */
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
|
||||
if (file) {
|
||||
aio_context_acquire(ctx);
|
||||
blk_unref(file);
|
||||
aio_context_release(ctx);
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
@@ -4087,13 +4146,16 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
* (snapshot_bs); thus, we have to drop the strong reference to bs
|
||||
* (which we obtained by calling bdrv_new()). bs will not be deleted,
|
||||
* though, because the overlay still has a reference to it. */
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_unref(bs);
|
||||
aio_context_release(ctx);
|
||||
bs = snapshot_bs;
|
||||
}
|
||||
|
||||
return bs;
|
||||
|
||||
fail:
|
||||
aio_context_acquire(ctx);
|
||||
blk_unref(file);
|
||||
qobject_unref(snapshot_options);
|
||||
qobject_unref(bs->explicit_options);
|
||||
@@ -4102,11 +4164,14 @@ fail:
|
||||
bs->options = NULL;
|
||||
bs->explicit_options = NULL;
|
||||
bdrv_unref(bs);
|
||||
aio_context_release(ctx);
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
|
||||
close_and_fail:
|
||||
aio_context_acquire(ctx);
|
||||
bdrv_unref(bs);
|
||||
aio_context_release(ctx);
|
||||
qobject_unref(snapshot_options);
|
||||
qobject_unref(options);
|
||||
error_propagate(errp, local_err);
|
||||
@@ -4578,6 +4643,11 @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
|
||||
* backing BlockDriverState (or NULL).
|
||||
*
|
||||
* Return 0 on success, otherwise return < 0 and set @errp.
|
||||
*
|
||||
* The caller must hold the AioContext lock of @reopen_state->bs.
|
||||
* @reopen_state->bs can move to a different AioContext in this function.
|
||||
* Callers must make sure that their AioContext locking is still correct after
|
||||
* this.
|
||||
*/
|
||||
static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
|
||||
bool is_backing, Transaction *tran,
|
||||
@@ -4590,6 +4660,8 @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
|
||||
const char *child_name = is_backing ? "backing" : "file";
|
||||
QObject *value;
|
||||
const char *str;
|
||||
AioContext *ctx, *old_ctx;
|
||||
int ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
@@ -4654,8 +4726,22 @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
|
||||
reopen_state->old_file_bs = old_child_bs;
|
||||
}
|
||||
|
||||
return bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing,
|
||||
tran, errp);
|
||||
old_ctx = bdrv_get_aio_context(bs);
|
||||
ctx = bdrv_get_aio_context(new_child_bs);
|
||||
if (old_ctx != ctx) {
|
||||
aio_context_release(old_ctx);
|
||||
aio_context_acquire(ctx);
|
||||
}
|
||||
|
||||
ret = bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing,
|
||||
tran, errp);
|
||||
|
||||
if (old_ctx != ctx) {
|
||||
aio_context_release(ctx);
|
||||
aio_context_acquire(old_ctx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4674,6 +4760,7 @@ static int bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
|
||||
* It is the responsibility of the caller to then call the abort() or
|
||||
* commit() for any other BDS that have been left in a prepare() state
|
||||
*
|
||||
* The caller must hold the AioContext lock of @reopen_state->bs.
|
||||
*/
|
||||
static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
BlockReopenQueue *queue,
|
||||
|
||||
@@ -227,6 +227,9 @@ typedef struct RawPosixAIOData {
|
||||
struct {
|
||||
unsigned long op;
|
||||
} zone_mgmt;
|
||||
struct {
|
||||
struct stat *st;
|
||||
} fstat;
|
||||
};
|
||||
} RawPosixAIOData;
|
||||
|
||||
@@ -2614,6 +2617,34 @@ static void raw_close(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_aiocb_fstat(void *opaque)
|
||||
{
|
||||
RawPosixAIOData *aiocb = opaque;
|
||||
|
||||
if (fstat(aiocb->aio_fildes, aiocb->fstat.st) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_fstat(BlockDriverState *bs, struct stat *st)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
RawPosixAIOData acb;
|
||||
|
||||
acb = (RawPosixAIOData) {
|
||||
.bs = bs,
|
||||
.aio_fildes = s->fd,
|
||||
.aio_type = QEMU_AIO_FSTAT,
|
||||
.fstat = {
|
||||
.st = st,
|
||||
},
|
||||
};
|
||||
|
||||
return raw_thread_pool_submit(handle_aiocb_fstat, &acb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the given regular file @fd to @offset and, when growing, fills the
|
||||
* new space according to @prealloc.
|
||||
@@ -2853,11 +2884,14 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs)
|
||||
static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
struct stat st;
|
||||
BDRVRawState *s = bs->opaque;
|
||||
int ret;
|
||||
|
||||
if (fstat(s->fd, &st) < 0) {
|
||||
return -errno;
|
||||
ret = raw_co_fstat(bs, &st);
|
||||
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,8 @@ BdrvGraphLock graph_lock;
|
||||
/* Protects the list of aiocontext and orphaned_reader_count */
|
||||
static QemuMutex aio_context_list_lock;
|
||||
|
||||
#if 0
|
||||
/* Written and read with atomic operations. */
|
||||
static int has_writer;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A reader coroutine could move from an AioContext to another.
|
||||
@@ -90,7 +88,6 @@ void unregister_aiocontext(AioContext *ctx)
|
||||
g_free(ctx->bdrv_graph);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static uint32_t reader_count(void)
|
||||
{
|
||||
BdrvGraphRWlock *brdv_graph;
|
||||
@@ -108,19 +105,27 @@ static uint32_t reader_count(void)
|
||||
assert((int32_t)rd >= 0);
|
||||
return rd;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bdrv_graph_wrlock(void)
|
||||
void bdrv_graph_wrlock(BlockDriverState *bs)
|
||||
{
|
||||
AioContext *ctx = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
/*
|
||||
* TODO Some callers hold an AioContext lock when this is called, which
|
||||
* causes deadlocks. Reenable once the AioContext locking is cleaned up (or
|
||||
* AioContext locks are gone).
|
||||
*/
|
||||
#if 0
|
||||
assert(!qatomic_read(&has_writer));
|
||||
|
||||
/*
|
||||
* Release only non-mainloop AioContext. The mainloop often relies on the
|
||||
* BQL and doesn't lock the main AioContext before doing things.
|
||||
*/
|
||||
if (bs) {
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
if (ctx != qemu_get_aio_context()) {
|
||||
aio_context_release(ctx);
|
||||
} else {
|
||||
ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure that constantly arriving new I/O doesn't cause starvation */
|
||||
bdrv_drain_all_begin_nopoll();
|
||||
|
||||
@@ -149,13 +154,15 @@ void bdrv_graph_wrlock(void)
|
||||
} while (reader_count() >= 1);
|
||||
|
||||
bdrv_drain_all_end();
|
||||
#endif
|
||||
|
||||
if (ctx) {
|
||||
aio_context_acquire(bdrv_get_aio_context(bs));
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_graph_wrunlock(void)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
#if 0
|
||||
QEMU_LOCK_GUARD(&aio_context_list_lock);
|
||||
assert(qatomic_read(&has_writer));
|
||||
|
||||
@@ -167,13 +174,10 @@ void bdrv_graph_wrunlock(void)
|
||||
|
||||
/* Wake up all coroutine that are waiting to read the graph */
|
||||
qemu_co_enter_all(&reader_queue, &aio_context_list_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_graph_co_rdlock(void)
|
||||
{
|
||||
/* TODO Reenable when wrlock is reenabled */
|
||||
#if 0
|
||||
BdrvGraphRWlock *bdrv_graph;
|
||||
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
|
||||
|
||||
@@ -233,12 +237,10 @@ void coroutine_fn bdrv_graph_co_rdlock(void)
|
||||
qemu_co_queue_wait(&reader_queue, &aio_context_list_lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_graph_co_rdunlock(void)
|
||||
{
|
||||
#if 0
|
||||
BdrvGraphRWlock *bdrv_graph;
|
||||
bdrv_graph = qemu_get_current_aio_context()->bdrv_graph;
|
||||
|
||||
@@ -256,7 +258,6 @@ void coroutine_fn bdrv_graph_co_rdunlock(void)
|
||||
if (qatomic_read(&has_writer)) {
|
||||
aio_wait_kick();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void bdrv_graph_rdlock_main_loop(void)
|
||||
@@ -275,18 +276,13 @@ void assert_bdrv_graph_readable(void)
|
||||
{
|
||||
/* reader_count() is slow due to aio_context_list_lock lock contention */
|
||||
/* TODO Reenable when wrlock is reenabled */
|
||||
#if 0
|
||||
#ifdef CONFIG_DEBUG_GRAPH_LOCK
|
||||
assert(qemu_in_main_thread() || reader_count());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void assert_bdrv_graph_writable(void)
|
||||
{
|
||||
assert(qemu_in_main_thread());
|
||||
/* TODO Reenable when wrlock is reenabled */
|
||||
#if 0
|
||||
assert(qatomic_read(&has_writer));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ block_gen_c = custom_target('block-gen.c',
|
||||
'../include/block/dirty-bitmap.h',
|
||||
'../include/block/block_int-io.h',
|
||||
'../include/block/block-global-state.h',
|
||||
'../include/block/qapi.h',
|
||||
'../include/sysemu/block-backend-global-state.h',
|
||||
'../include/sysemu/block-backend-io.h',
|
||||
'coroutines.h'
|
||||
|
||||
@@ -394,7 +394,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
|
||||
bool writable = qdict_get_try_bool(qdict, "writable", false);
|
||||
bool all = qdict_get_try_bool(qdict, "all", false);
|
||||
Error *local_err = NULL;
|
||||
BlockInfoList *block_list, *info;
|
||||
BlockBackend *blk;
|
||||
SocketAddress *addr;
|
||||
NbdServerAddOptions export;
|
||||
|
||||
@@ -419,18 +419,24 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Then try adding all block devices. If one fails, close all and
|
||||
/*
|
||||
* Then try adding all block devices. If one fails, close all and
|
||||
* exit.
|
||||
*/
|
||||
block_list = qmp_query_block(NULL);
|
||||
for (blk = blk_all_next(NULL); blk; blk = blk_all_next(blk)) {
|
||||
BlockDriverState *bs = blk_bs(blk);
|
||||
|
||||
for (info = block_list; info; info = info->next) {
|
||||
if (!info->value->inserted) {
|
||||
if (!*blk_name(blk) && !blk_get_attached_dev(blk)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bs = bdrv_skip_implicit_filters(bs);
|
||||
if (!bs || !bs->drv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
export = (NbdServerAddOptions) {
|
||||
.device = info->value->device,
|
||||
.device = g_strdup(blk_name(blk)),
|
||||
.has_writable = true,
|
||||
.writable = writable,
|
||||
};
|
||||
@@ -443,8 +449,6 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
}
|
||||
|
||||
qapi_free_BlockInfoList(block_list);
|
||||
|
||||
exit:
|
||||
hmp_handle_error(mon, local_err);
|
||||
}
|
||||
@@ -738,7 +742,7 @@ static void print_block_info(Monitor *mon, BlockInfo *info,
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_info_block(Monitor *mon, const QDict *qdict)
|
||||
void coroutine_fn hmp_info_block(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
BlockInfoList *block_list, *info;
|
||||
BlockDeviceInfoList *blockdev_list, *blockdev;
|
||||
|
||||
62
block/qapi.c
62
block/qapi.c
@@ -41,14 +41,14 @@
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
BlockDriverState *bs,
|
||||
bool flat,
|
||||
Error **errp)
|
||||
BlockDeviceInfo *coroutine_fn bdrv_block_device_info(BlockBackend *blk,
|
||||
BlockDriverState *bs,
|
||||
bool flat,
|
||||
Error **errp)
|
||||
{
|
||||
ImageInfo **p_image_info;
|
||||
ImageInfo *backing_info;
|
||||
BlockDriverState *bs0, *backing;
|
||||
BlockDriverState *backing;
|
||||
BlockDeviceInfo *info;
|
||||
ERRP_GUARD();
|
||||
|
||||
@@ -145,7 +145,6 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
|
||||
info->write_threshold = bdrv_write_threshold_get(bs);
|
||||
|
||||
bs0 = bs;
|
||||
p_image_info = &info->image;
|
||||
info->backing_file_depth = 0;
|
||||
|
||||
@@ -153,7 +152,7 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
* Skip automatically inserted nodes that the user isn't aware of for
|
||||
* query-block (blk != NULL), but not for query-named-block-nodes
|
||||
*/
|
||||
bdrv_query_image_info(bs0, p_image_info, flat, blk != NULL, errp);
|
||||
bdrv_query_image_info(bs, p_image_info, flat, blk != NULL, errp);
|
||||
if (*errp) {
|
||||
qapi_free_BlockDeviceInfo(info);
|
||||
return NULL;
|
||||
@@ -236,8 +235,6 @@ static void bdrv_do_query_node_info(BlockDriverState *bs,
|
||||
int ret;
|
||||
Error *err = NULL;
|
||||
|
||||
aio_context_acquire(bdrv_get_aio_context(bs));
|
||||
|
||||
size = bdrv_getlength(bs);
|
||||
if (size < 0) {
|
||||
error_setg_errno(errp, -size, "Can't get image size '%s'",
|
||||
@@ -250,7 +247,9 @@ static void bdrv_do_query_node_info(BlockDriverState *bs,
|
||||
info->filename = g_strdup(bs->filename);
|
||||
info->format = g_strdup(bdrv_get_format_name(bs));
|
||||
info->virtual_size = size;
|
||||
info->actual_size = bdrv_get_allocated_file_size(bs);
|
||||
bdrv_graph_co_rdlock();
|
||||
info->actual_size = bdrv_co_get_allocated_file_size(bs);
|
||||
bdrv_graph_co_rdunlock();
|
||||
info->has_actual_size = info->actual_size >= 0;
|
||||
if (bs->encrypted) {
|
||||
info->encrypted = true;
|
||||
@@ -306,34 +305,7 @@ static void bdrv_do_query_node_info(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
out:
|
||||
aio_context_release(bdrv_get_aio_context(bs));
|
||||
}
|
||||
|
||||
/**
|
||||
* bdrv_query_block_node_info:
|
||||
* @bs: block node to examine
|
||||
* @p_info: location to store node information
|
||||
* @errp: location to store error information
|
||||
*
|
||||
* Store image information about @bs in @p_info.
|
||||
*
|
||||
* @p_info will be set only on success. On error, store error in @errp.
|
||||
*/
|
||||
void bdrv_query_block_node_info(BlockDriverState *bs,
|
||||
BlockNodeInfo **p_info,
|
||||
Error **errp)
|
||||
{
|
||||
BlockNodeInfo *info;
|
||||
ERRP_GUARD();
|
||||
|
||||
info = g_new0(BlockNodeInfo, 1);
|
||||
bdrv_do_query_node_info(bs, info, errp);
|
||||
if (*errp) {
|
||||
qapi_free_BlockNodeInfo(info);
|
||||
return;
|
||||
}
|
||||
|
||||
*p_info = info;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,7 +375,7 @@ fail:
|
||||
}
|
||||
|
||||
/**
|
||||
* bdrv_query_block_graph_info:
|
||||
* bdrv_co_query_block_graph_info:
|
||||
* @bs: root node to start from
|
||||
* @p_info: location to store image information
|
||||
* @errp: location to store error information
|
||||
@@ -412,15 +384,17 @@ fail:
|
||||
*
|
||||
* @p_info will be set only on success. On error, store error in @errp.
|
||||
*/
|
||||
void bdrv_query_block_graph_info(BlockDriverState *bs,
|
||||
BlockGraphInfo **p_info,
|
||||
Error **errp)
|
||||
void coroutine_fn bdrv_co_query_block_graph_info(BlockDriverState *bs,
|
||||
BlockGraphInfo **p_info,
|
||||
Error **errp)
|
||||
{
|
||||
BlockGraphInfo *info;
|
||||
BlockChildInfoList **children_list_tail;
|
||||
BdrvChild *c;
|
||||
ERRP_GUARD();
|
||||
|
||||
assert_bdrv_graph_readable();
|
||||
|
||||
info = g_new0(BlockGraphInfo, 1);
|
||||
bdrv_do_query_node_info(bs, qapi_BlockGraphInfo_base(info), errp);
|
||||
if (*errp) {
|
||||
@@ -436,7 +410,7 @@ void bdrv_query_block_graph_info(BlockDriverState *bs,
|
||||
QAPI_LIST_APPEND(children_list_tail, c_info);
|
||||
|
||||
c_info->name = g_strdup(c->name);
|
||||
bdrv_query_block_graph_info(c->bs, &c_info->info, errp);
|
||||
bdrv_co_query_block_graph_info(c->bs, &c_info->info, errp);
|
||||
if (*errp) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -694,7 +668,7 @@ bdrv_query_bds_stats(BlockDriverState *bs, bool blk_level)
|
||||
return s;
|
||||
}
|
||||
|
||||
BlockInfoList *qmp_query_block(Error **errp)
|
||||
BlockInfoList *coroutine_fn qmp_query_block(Error **errp)
|
||||
{
|
||||
BlockInfoList *head = NULL, **p_next = &head;
|
||||
BlockBackend *blk;
|
||||
|
||||
@@ -2818,9 +2818,9 @@ void qmp_drive_backup(DriveBackup *backup, Error **errp)
|
||||
blockdev_do_action(&action, errp);
|
||||
}
|
||||
|
||||
BlockDeviceInfoList *qmp_query_named_block_nodes(bool has_flat,
|
||||
bool flat,
|
||||
Error **errp)
|
||||
BlockDeviceInfoList *coroutine_fn qmp_query_named_block_nodes(bool has_flat,
|
||||
bool flat,
|
||||
Error **errp)
|
||||
{
|
||||
bool return_flat = has_flat && flat;
|
||||
|
||||
|
||||
17
blockjob.c
17
blockjob.c
@@ -230,20 +230,27 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
|
||||
uint64_t perm, uint64_t shared_perm, Error **errp)
|
||||
{
|
||||
BdrvChild *c;
|
||||
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||
bool need_context_ops;
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bdrv_ref(bs);
|
||||
|
||||
need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context;
|
||||
need_context_ops = ctx != job->job.aio_context;
|
||||
|
||||
if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) {
|
||||
aio_context_release(job->job.aio_context);
|
||||
if (need_context_ops) {
|
||||
if (job->job.aio_context != qemu_get_aio_context()) {
|
||||
aio_context_release(job->job.aio_context);
|
||||
}
|
||||
aio_context_acquire(ctx);
|
||||
}
|
||||
c = bdrv_root_attach_child(bs, name, &child_job, 0, perm, shared_perm, job,
|
||||
errp);
|
||||
if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) {
|
||||
aio_context_acquire(job->job.aio_context);
|
||||
if (need_context_ops) {
|
||||
aio_context_release(ctx);
|
||||
if (job->job.aio_context != qemu_get_aio_context()) {
|
||||
aio_context_acquire(job->job.aio_context);
|
||||
}
|
||||
}
|
||||
if (c == NULL) {
|
||||
return -EPERM;
|
||||
|
||||
@@ -65,6 +65,7 @@ ERST
|
||||
.help = "show info of one block device or all block devices "
|
||||
"(-n: show named nodes; -v: show details)",
|
||||
.cmd = hmp_info_block,
|
||||
.coroutine = true,
|
||||
},
|
||||
|
||||
SRST
|
||||
|
||||
@@ -143,11 +143,15 @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
|
||||
* aware of iothreads require their BlockBackends to be in the main
|
||||
* AioContext.
|
||||
*/
|
||||
ctx = iothread ? bdrv_get_aio_context(bs) : qemu_get_aio_context();
|
||||
blk = blk_new(ctx, 0, BLK_PERM_ALL);
|
||||
ctx = bdrv_get_aio_context(bs);
|
||||
blk = blk_new(iothread ? ctx : qemu_get_aio_context(),
|
||||
0, BLK_PERM_ALL);
|
||||
blk_created = true;
|
||||
|
||||
aio_context_acquire(ctx);
|
||||
ret = blk_insert_bs(blk, bs, errp);
|
||||
aio_context_release(ctx);
|
||||
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void hmp_eject(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_qemu_io(Monitor *mon, const QDict *qdict);
|
||||
|
||||
void hmp_info_block(Monitor *mon, const QDict *qdict);
|
||||
void coroutine_fn hmp_info_block(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_blockstats(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_block_jobs(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
|
||||
|
||||
@@ -111,10 +111,12 @@ void unregister_aiocontext(AioContext *ctx);
|
||||
* The wrlock can only be taken from the main loop, with BQL held, as only the
|
||||
* main loop is allowed to modify the graph.
|
||||
*
|
||||
* If @bs is non-NULL, its AioContext is temporarily released.
|
||||
*
|
||||
* This function polls. Callers must not hold the lock of any AioContext other
|
||||
* than the current one.
|
||||
* than the current one and the one of @bs.
|
||||
*/
|
||||
void bdrv_graph_wrlock(void) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
|
||||
void bdrv_graph_wrlock(BlockDriverState *bs) TSA_ACQUIRE(graph_lock) TSA_NO_TSA;
|
||||
|
||||
/*
|
||||
* bdrv_graph_wrunlock:
|
||||
|
||||
@@ -25,26 +25,27 @@
|
||||
#ifndef BLOCK_QAPI_H
|
||||
#define BLOCK_QAPI_H
|
||||
|
||||
#include "block/block-common.h"
|
||||
#include "block/graph-lock.h"
|
||||
#include "block/snapshot.h"
|
||||
#include "qapi/qapi-types-block-core.h"
|
||||
|
||||
BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
BlockDriverState *bs,
|
||||
bool flat,
|
||||
Error **errp);
|
||||
BlockDeviceInfo *coroutine_fn bdrv_block_device_info(BlockBackend *blk,
|
||||
BlockDriverState *bs,
|
||||
bool flat,
|
||||
Error **errp);
|
||||
int bdrv_query_snapshot_info_list(BlockDriverState *bs,
|
||||
SnapshotInfoList **p_list,
|
||||
Error **errp);
|
||||
void bdrv_query_block_node_info(BlockDriverState *bs,
|
||||
BlockNodeInfo **p_info,
|
||||
Error **errp);
|
||||
void bdrv_query_image_info(BlockDriverState *bs,
|
||||
ImageInfo **p_info,
|
||||
bool flat,
|
||||
bool skip_implicit_filters,
|
||||
Error **errp);
|
||||
void GRAPH_RDLOCK
|
||||
void coroutine_fn GRAPH_RDLOCK
|
||||
bdrv_co_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
|
||||
Error **errp);
|
||||
void co_wrapper_bdrv_rdlock
|
||||
bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
|
||||
Error **errp);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define QEMU_AIO_ZONE_REPORT 0x0100
|
||||
#define QEMU_AIO_ZONE_MGMT 0x0200
|
||||
#define QEMU_AIO_ZONE_APPEND 0x0400
|
||||
#define QEMU_AIO_FSTAT 0x0800
|
||||
#define QEMU_AIO_TYPE_MASK \
|
||||
(QEMU_AIO_READ | \
|
||||
QEMU_AIO_WRITE | \
|
||||
@@ -42,7 +43,8 @@
|
||||
QEMU_AIO_TRUNCATE | \
|
||||
QEMU_AIO_ZONE_REPORT | \
|
||||
QEMU_AIO_ZONE_MGMT | \
|
||||
QEMU_AIO_ZONE_APPEND)
|
||||
QEMU_AIO_ZONE_APPEND | \
|
||||
QEMU_AIO_FSTAT)
|
||||
|
||||
/* AIO flags */
|
||||
#define QEMU_AIO_MISALIGNED 0x1000
|
||||
|
||||
@@ -838,7 +838,7 @@
|
||||
# }
|
||||
##
|
||||
{ 'command': 'query-block', 'returns': ['BlockInfo'],
|
||||
'allow-preconfig': true }
|
||||
'allow-preconfig': true, 'coroutine': true }
|
||||
|
||||
##
|
||||
# @BlockDeviceTimedStats:
|
||||
@@ -1972,7 +1972,8 @@
|
||||
{ 'command': 'query-named-block-nodes',
|
||||
'returns': [ 'BlockDeviceInfo' ],
|
||||
'data': { '*flat': 'bool' },
|
||||
'allow-preconfig': true }
|
||||
'allow-preconfig': true,
|
||||
'coroutine': true}
|
||||
|
||||
##
|
||||
# @XDbgBlockGraphNodeType:
|
||||
|
||||
@@ -2945,9 +2945,7 @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
|
||||
* duplicate the backing chain information that we obtain by walking
|
||||
* the chain manually here.
|
||||
*/
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
bdrv_query_block_graph_info(bs, &info, &err);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
|
||||
@@ -44,6 +44,7 @@ def gen_header():
|
||||
#include "block/block-gen.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/dirty-bitmap.h"
|
||||
#include "block/qapi.h"
|
||||
"""
|
||||
|
||||
|
||||
|
||||
85
tests/qemu-iotests/tests/iothreads-commit-active
Executable file
85
tests/qemu-iotests/tests/iothreads-commit-active
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
# group: rw quick auto
|
||||
#
|
||||
# Copyright (C) 2023 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
|
||||
|
||||
import asyncio
|
||||
import iotests
|
||||
|
||||
iotests.script_initialize(supported_fmts=['qcow2'],
|
||||
supported_platforms=['linux'])
|
||||
iotests.verify_virtio_scsi_pci_or_ccw()
|
||||
|
||||
with iotests.FilePath('disk0.img') as img_path, \
|
||||
iotests.FilePath('disk0-snap.img') as snap_path, \
|
||||
iotests.FilePath('mirror-src.img') as src_path, \
|
||||
iotests.FilePath('mirror-dst.img') as dst_path, \
|
||||
iotests.VM() as vm:
|
||||
|
||||
img_size = '10M'
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, img_path, img_size)
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, '-b', img_path,
|
||||
'-F', iotests.imgfmt, snap_path)
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, src_path, img_size)
|
||||
iotests.qemu_img_create('-f', iotests.imgfmt, dst_path, img_size)
|
||||
|
||||
iotests.qemu_io_log('-c', 'write 0 64k', img_path)
|
||||
iotests.qemu_io_log('-c', 'write 1M 64k', snap_path)
|
||||
iotests.qemu_io_log('-c', 'write 3M 64k', snap_path)
|
||||
|
||||
iotests.qemu_io_log('-c', f'write 0 {img_size}', src_path)
|
||||
|
||||
iotests.log('Launching VM...')
|
||||
vm.add_object('iothread,id=iothread0')
|
||||
vm.add_object('throttle-group,x-bps-write=1048576,id=tg0')
|
||||
vm.add_blockdev(f'file,node-name=disk0-file,filename={img_path}')
|
||||
vm.add_blockdev('qcow2,node-name=disk0-fmt,file=disk0-file')
|
||||
vm.add_drive(snap_path, 'backing=disk0-fmt,node-name=disk0',
|
||||
interface='none')
|
||||
vm.add_device('virtio-scsi,iothread=iothread0')
|
||||
vm.add_device('scsi-hd,drive=drive0')
|
||||
|
||||
vm.add_blockdev(f'file,filename={src_path},node-name=mirror-src-file')
|
||||
vm.add_blockdev('qcow2,file=mirror-src-file,node-name=mirror-src')
|
||||
vm.add_blockdev(f'file,filename={dst_path},node-name=mirror-dst-file')
|
||||
vm.add_blockdev('qcow2,file=mirror-dst-file,node-name=mirror-dst-fmt')
|
||||
vm.add_blockdev('throttle,throttle-group=tg0,file=mirror-dst-fmt,'
|
||||
'node-name=mirror-dst')
|
||||
vm.add_device('scsi-hd,drive=mirror-src')
|
||||
|
||||
vm.launch()
|
||||
|
||||
# The background I/O is created on unrelated nodes (so that they won't be
|
||||
# drained together with the other ones), but on the same iothread
|
||||
iotests.log('Creating some background I/O...')
|
||||
iotests.log(vm.qmp('blockdev-mirror', job_id='job0', sync='full',
|
||||
device='mirror-src', target='mirror-dst',
|
||||
auto_dismiss=False))
|
||||
|
||||
iotests.log('Starting active commit...')
|
||||
iotests.log(vm.qmp('block-commit', device='disk0', job_id='job1',
|
||||
auto_dismiss=False))
|
||||
|
||||
# Should succeed and not time out
|
||||
try:
|
||||
vm.run_job('job1', wait=5.0)
|
||||
vm.shutdown()
|
||||
except asyncio.TimeoutError:
|
||||
# VM may be stuck, kill it
|
||||
vm.kill()
|
||||
raise
|
||||
23
tests/qemu-iotests/tests/iothreads-commit-active.out
Normal file
23
tests/qemu-iotests/tests/iothreads-commit-active.out
Normal file
@@ -0,0 +1,23 @@
|
||||
wrote 65536/65536 bytes at offset 0
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
wrote 65536/65536 bytes at offset 1048576
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
wrote 65536/65536 bytes at offset 3145728
|
||||
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
wrote 10485760/10485760 bytes at offset 0
|
||||
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
|
||||
Launching VM...
|
||||
Creating some background I/O...
|
||||
{"return": {}}
|
||||
Starting active commit...
|
||||
{"return": {}}
|
||||
{"execute": "job-complete", "arguments": {"id": "job1"}}
|
||||
{"return": {}}
|
||||
{"data": {"device": "job1", "len": 131072, "offset": 131072, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"data": {"device": "job1", "len": 131072, "offset": 131072, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
|
||||
{"execute": "job-dismiss", "arguments": {"id": "job1"}}
|
||||
{"return": {}}
|
||||
@@ -825,6 +825,7 @@ static void test_attach_second_node(void)
|
||||
BlockDriverState *bs, *filter;
|
||||
QDict *options;
|
||||
|
||||
aio_context_acquire(main_ctx);
|
||||
blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
|
||||
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
|
||||
blk_insert_bs(blk, bs, &error_abort);
|
||||
@@ -833,7 +834,6 @@ static void test_attach_second_node(void)
|
||||
qdict_put_str(options, "driver", "raw");
|
||||
qdict_put_str(options, "file", "base");
|
||||
|
||||
aio_context_acquire(main_ctx);
|
||||
filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
|
||||
aio_context_release(main_ctx);
|
||||
|
||||
@@ -857,9 +857,11 @@ static void test_attach_preserve_blk_ctx(void)
|
||||
{
|
||||
IOThread *iothread = iothread_new();
|
||||
AioContext *ctx = iothread_get_aio_context(iothread);
|
||||
AioContext *main_ctx = qemu_get_aio_context();
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
|
||||
aio_context_acquire(main_ctx);
|
||||
blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
|
||||
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
|
||||
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
|
||||
@@ -868,6 +870,7 @@ static void test_attach_preserve_blk_ctx(void)
|
||||
blk_insert_bs(blk, bs, &error_abort);
|
||||
g_assert(blk_get_aio_context(blk) == ctx);
|
||||
g_assert(bdrv_get_aio_context(bs) == ctx);
|
||||
aio_context_release(main_ctx);
|
||||
|
||||
/* Remove the node again */
|
||||
aio_context_acquire(ctx);
|
||||
@@ -877,7 +880,9 @@ static void test_attach_preserve_blk_ctx(void)
|
||||
g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context());
|
||||
|
||||
/* Re-attach the node */
|
||||
aio_context_acquire(main_ctx);
|
||||
blk_insert_bs(blk, bs, &error_abort);
|
||||
aio_context_release(main_ctx);
|
||||
g_assert(blk_get_aio_context(blk) == ctx);
|
||||
g_assert(bdrv_get_aio_context(bs) == ctx);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user