mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
Block layer patches - file-posix: Fix aio=threads performance regression after enablign FUA - QMP query-block/query-named-block-nodes: Include child references - Graph locking cleanups and fixes around making drain GRAPH_UNLOCKED - qemu-img: Overhaul option handling and --help - iotests: add test for changing the 'drive' property via 'qom-set' # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCgAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmh2pZkRHGt3b2xmQHJl # ZGhhdC5jb20ACgkQfwmycsiPL9aloBAAkbT2DpdcPb5v6Jc02bDTjBBi//R03cTy # 0jjU3zvEEjukeA8d7lsQnvD2YwQgvIoOgH/MeNjdYizYh6sLIofTKukbKWMWiBpt # ygs67IrlsmEqrb+i/xeLdRA1o7jzpJCutU/cQeWV/fUur9ovhjnIJvwiw2Z3uhBR # QajjPAZcGALwNMauweMhqTX7U1+EpAe/OdtAfc2UgyJIFCyLN9onuQleZ1lCbxSt # PCAUT/M8zcId2Tcb9Bw3p0mzDNG2AI2FYqGIKNoaWwFfK/SgS8NCUvgpIWGghoxs # bMbmKMqJpZamsbO7bmEEGjj1Vs14vYVMbqys6N2Gux74RXCBGDleGAR3HNvV+3jR # 98AuoTOWZxb3Sfu0e+9xNE/+kWcJ0vmsy3sxkpZ6hkPz6fmrrJJYy8Kv2tcCAOCi # qIJ4hwNx052f1tnyxvARHj+Hj1Q4PSeQl/MAISVeQNAQXoinxzCP/hGLF3PkdpgD # 6m/xwQ+qMnnblgn4s2ICPXOJAaWLTeB6Y6F34MG+Wgi/7sfKGwxDgRSLMnlNICsm # PpbSlRy3n7tBTUq4gF3kbknxKeEPGUGw3sakX8fc0DJshs6nz/nKL4Ftwgiuuo3F # HWR8icj1giifohJOF0KJEa1Q2H9jR6hYwcNpjd9d/OEz1q/3HtuYAiEM3CUygVad # 2cyZBHjNWLE= # =A4ZH # -----END PGP SIGNATURE----- # gpg: Signature made Tue 15 Jul 2025 15:01:45 EDT # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (57 commits) qemu-img: extend cvtnum() and use it in more places qemu-img: implement short --help, remove global help() function qemu-img: measure: refresh options/--help qemu-img: dd: refresh options/--help qemu-img: bitmap: refresh options/--help qemu-img: bench: refresh options/--help qemu-img: amend: refresh options/--help qemu-img: resize: refresh options/--help qemu-img: resize: do not always eat last argument qemu-img: rebase: refresh options/--help (short option change) qemu-img: snapshot: refresh options/--help qemu-img: snapshot: make -l (list) the default, simplify option handling qemu-img: snapshot: allow specifying -f fmt qemu-img: map: refresh options/--help qemu-img: info: refresh options/--help qemu-img: convert: refresh options/--help (short option change) qemu-img: compare: refresh options/--help qemu-img: compare: use helper function for --object qemu-img: commit: refresh options/--help qemu-img: simplify --repair error message ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -431,7 +431,7 @@ BlockDriverState *bdrv_new(void)
|
||||
bs->block_status_cache = g_new0(BdrvBlockStatusCache, 1);
|
||||
|
||||
for (i = 0; i < bdrv_drain_all_count; i++) {
|
||||
bdrv_drained_begin(bs);
|
||||
bdrv_do_drained_begin_quiesce(bs, NULL);
|
||||
}
|
||||
|
||||
QTAILQ_INSERT_TAIL(&all_bdrv_states, bs, bs_list);
|
||||
@@ -1721,14 +1721,12 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
|
||||
open_failed:
|
||||
bs->drv = NULL;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
if (bs->file != NULL) {
|
||||
bdrv_unref_child(bs, bs->file);
|
||||
assert(!bs->file);
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
g_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
@@ -3572,9 +3570,8 @@ out:
|
||||
*
|
||||
* All block nodes must be drained.
|
||||
*/
|
||||
int bdrv_set_backing_hd_drained(BlockDriverState *bs,
|
||||
BlockDriverState *backing_hd,
|
||||
Error **errp)
|
||||
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
Transaction *tran = tran_new();
|
||||
@@ -3596,21 +3593,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens the backing file for a BlockDriverState if not yet open
|
||||
*
|
||||
@@ -3636,7 +3618,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
Error *local_err = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
if (bs->backing != NULL) {
|
||||
goto free_exit;
|
||||
@@ -3717,7 +3700,11 @@ 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 */
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock_drained();
|
||||
ret = bdrv_set_backing_hd(bs, backing_hd, errp);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
bdrv_unref(backing_hd);
|
||||
|
||||
if (ret < 0) {
|
||||
@@ -3729,6 +3716,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
free_exit:
|
||||
g_free(backing_filename);
|
||||
qobject_unref(tmp_parent_options);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3778,13 +3766,12 @@ done:
|
||||
return bs;
|
||||
}
|
||||
|
||||
static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, bool parse_filename,
|
||||
Error **errp)
|
||||
static BdrvChild * GRAPH_UNLOCKED
|
||||
bdrv_open_child_common(const char *filename, QDict *options,
|
||||
const char *bdref_key, BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role, bool allow_none,
|
||||
bool parse_filename, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BdrvChild *child;
|
||||
@@ -3797,12 +3784,10 @@ static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
errp);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
return child;
|
||||
}
|
||||
@@ -5160,7 +5145,7 @@ static void GRAPH_UNLOCKED bdrv_reopen_abort(BDRVReopenState *reopen_state)
|
||||
}
|
||||
|
||||
|
||||
static void bdrv_close(BlockDriverState *bs)
|
||||
static void GRAPH_UNLOCKED bdrv_close(BlockDriverState *bs)
|
||||
{
|
||||
BdrvAioNotifier *ban, *ban_next;
|
||||
BdrvChild *child, *next;
|
||||
@@ -5180,8 +5165,7 @@ static void bdrv_close(BlockDriverState *bs)
|
||||
bs->drv = NULL;
|
||||
}
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
|
||||
bdrv_unref_child(bs, child);
|
||||
}
|
||||
@@ -5189,7 +5173,6 @@ static void bdrv_close(BlockDriverState *bs)
|
||||
assert(!bs->backing);
|
||||
assert(!bs->file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
g_free(bs->opaque);
|
||||
bs->opaque = NULL;
|
||||
@@ -5515,8 +5498,7 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
|
||||
assert(!bs_new->backing);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
|
||||
child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
|
||||
&child_of_bds, bdrv_backing_role(bs_new),
|
||||
@@ -5537,7 +5519,6 @@ out:
|
||||
|
||||
bdrv_refresh_limits(bs_top, NULL, NULL);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -7076,31 +7057,25 @@ bdrv_inactivate_recurse(BlockDriverState *bs, bool top_level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* All block nodes must be drained. */
|
||||
int bdrv_inactivate(BlockDriverState *bs, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
if (bdrv_has_bds_parent(bs, true)) {
|
||||
error_setg(errp, "Node has active parent node");
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ret = bdrv_inactivate_recurse(bs, true);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to inactivate node");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
out:
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_end();
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdrv_inactivate_all(void)
|
||||
|
||||
+1
-3
@@ -498,12 +498,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||
block_copy_set_speed(bcs, speed);
|
||||
|
||||
/* Required permissions are taken by copy-before-write filter target */
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
|
||||
&error_abort);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
return &job->common;
|
||||
|
||||
|
||||
@@ -281,11 +281,9 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
ret = 0;
|
||||
fail_log:
|
||||
if (ret < 0) {
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, s->log_file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
s->log_file = NULL;
|
||||
qemu_mutex_destroy(&s->mutex);
|
||||
}
|
||||
@@ -298,12 +296,10 @@ static void blk_log_writes_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkLogWritesState *s = bs->opaque;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, s->log_file);
|
||||
s->log_file = NULL;
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
qemu_mutex_destroy(&s->mutex);
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -151,12 +151,10 @@ static void blkverify_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, s->test_file);
|
||||
s->test_file = NULL;
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn GRAPH_RDLOCK
|
||||
|
||||
@@ -889,11 +889,9 @@ void blk_remove_bs(BlockBackend *blk)
|
||||
root = blk->root;
|
||||
blk->root = NULL;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_root_unref_child(root);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -906,8 +904,7 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
bdrv_ref(bs);
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
|
||||
if ((bs->open_flags & BDRV_O_INACTIVE) && blk_can_inactivate(blk)) {
|
||||
blk->disable_perm = true;
|
||||
@@ -922,7 +919,6 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
|
||||
perm, shared_perm, blk, errp);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
if (blk->root == NULL) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
+24
-10
@@ -68,7 +68,7 @@ static int commit_prepare(Job *job)
|
||||
s->backing_mask_protocol);
|
||||
}
|
||||
|
||||
static void commit_abort(Job *job)
|
||||
static void GRAPH_UNLOCKED commit_abort(Job *job)
|
||||
{
|
||||
CommitBlockJob *s = container_of(job, CommitBlockJob, common.job);
|
||||
BlockDriverState *top_bs = blk_bs(s->top);
|
||||
@@ -392,8 +392,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
* this is the responsibility of the interface (i.e. whoever calls
|
||||
* commit_start()).
|
||||
*/
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
s->base_overlay = bdrv_find_overlay(top, base);
|
||||
assert(s->base_overlay);
|
||||
|
||||
@@ -425,21 +424,18 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||
iter_shared_perms, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
s->chain_frozen = true;
|
||||
|
||||
ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
@@ -518,28 +514,32 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
Error *local_err = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
backing_file_bs = bdrv_cow_bs(bs);
|
||||
|
||||
if (!backing_file_bs) {
|
||||
return -ENOTSUP;
|
||||
ret = -ENOTSUP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, NULL) ||
|
||||
bdrv_op_is_blocked(backing_file_bs, BLOCK_OP_TYPE_COMMIT_TARGET, NULL))
|
||||
{
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ro = bdrv_is_read_only(backing_file_bs);
|
||||
|
||||
if (ro) {
|
||||
if (bdrv_reopen_set_read_only(backing_file_bs, false, NULL)) {
|
||||
return -EACCES;
|
||||
ret = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -563,8 +563,14 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_set_backing_hd(commit_top_bs, backing_file_bs, &error_abort);
|
||||
bdrv_set_backing_hd(bs, commit_top_bs, &error_abort);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
ret = blk_insert_bs(backing, backing_file_bs, &local_err);
|
||||
if (ret < 0) {
|
||||
@@ -639,9 +645,14 @@ int bdrv_commit(BlockDriverState *bs)
|
||||
ret = 0;
|
||||
ro_cleanup:
|
||||
blk_unref(backing);
|
||||
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_graph_wrlock_drained();
|
||||
if (bdrv_cow_bs(bs) != backing_file_bs) {
|
||||
bdrv_set_backing_hd(bs, backing_file_bs, &error_abort);
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
bdrv_unref(commit_top_bs);
|
||||
blk_unref(src);
|
||||
|
||||
@@ -650,5 +661,8 @@ ro_cleanup:
|
||||
bdrv_reopen_set_read_only(backing_file_bs, true, NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+15
-14
@@ -2564,9 +2564,9 @@ static inline bool raw_check_linux_aio(BDRVRawState *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int coroutine_fn raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr,
|
||||
uint64_t bytes, QEMUIOVector *qiov, int type,
|
||||
int flags)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr, uint64_t bytes,
|
||||
QEMUIOVector *qiov, int type, int flags)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
RawPosixAIOData acb;
|
||||
@@ -2625,7 +2625,7 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr,
|
||||
ret = raw_thread_pool_submit(handle_aiocb_rw, &acb);
|
||||
if (ret == 0 && (flags & BDRV_REQ_FUA)) {
|
||||
/* TODO Use pwritev2() instead if it's available */
|
||||
ret = raw_co_flush_to_disk(bs);
|
||||
ret = bdrv_co_flush(bs);
|
||||
}
|
||||
goto out; /* Avoid the compiler err of unused label */
|
||||
|
||||
@@ -2660,16 +2660,16 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags)
|
||||
{
|
||||
return raw_co_prw(bs, &offset, bytes, qiov, QEMU_AIO_READ, flags);
|
||||
}
|
||||
|
||||
static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, int64_t offset,
|
||||
int64_t bytes, QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags)
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
QEMUIOVector *qiov, BdrvRequestFlags flags)
|
||||
{
|
||||
return raw_co_prw(bs, &offset, bytes, qiov, QEMU_AIO_WRITE, flags);
|
||||
}
|
||||
@@ -3606,10 +3606,11 @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BLKZONED)
|
||||
static int coroutine_fn raw_co_zone_append(BlockDriverState *bs,
|
||||
int64_t *offset,
|
||||
QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags) {
|
||||
static int coroutine_fn GRAPH_RDLOCK
|
||||
raw_co_zone_append(BlockDriverState *bs,
|
||||
int64_t *offset,
|
||||
QEMUIOVector *qiov,
|
||||
BdrvRequestFlags flags) {
|
||||
assert(flags == 0);
|
||||
int64_t zone_size_mask = bs->bl.zone_size - 1;
|
||||
int64_t iov_len = 0;
|
||||
|
||||
+37
-3
@@ -33,6 +33,17 @@ static QemuMutex aio_context_list_lock;
|
||||
/* Written and read with atomic operations. */
|
||||
static int has_writer;
|
||||
|
||||
/*
|
||||
* Many write-locked sections are also drained sections. There is a convenience
|
||||
* wrapper bdrv_graph_wrlock_drained() which begins a drained section before
|
||||
* acquiring the lock. This variable here is used so bdrv_graph_wrunlock() knows
|
||||
* if it also needs to end such a drained section. It needs to be a counter,
|
||||
* because the aio_poll() call in bdrv_graph_wrlock() might re-enter
|
||||
* bdrv_graph_wrlock_drained(). And note that aio_bh_poll() in
|
||||
* bdrv_graph_wrunlock() might also re-enter a write-locked section.
|
||||
*/
|
||||
static int wrlock_quiesced_counter;
|
||||
|
||||
/*
|
||||
* A reader coroutine could move from an AioContext to another.
|
||||
* If this happens, there is no problem from the point of view of
|
||||
@@ -112,8 +123,14 @@ void no_coroutine_fn bdrv_graph_wrlock(void)
|
||||
assert(!qatomic_read(&has_writer));
|
||||
assert(!qemu_in_coroutine());
|
||||
|
||||
/* Make sure that constantly arriving new I/O doesn't cause starvation */
|
||||
bdrv_drain_all_begin_nopoll();
|
||||
bool need_drain = wrlock_quiesced_counter == 0;
|
||||
|
||||
if (need_drain) {
|
||||
/*
|
||||
* Make sure that constantly arriving new I/O doesn't cause starvation
|
||||
*/
|
||||
bdrv_drain_all_begin_nopoll();
|
||||
}
|
||||
|
||||
/*
|
||||
* reader_count == 0: this means writer will read has_reader as 1
|
||||
@@ -139,7 +156,18 @@ void no_coroutine_fn bdrv_graph_wrlock(void)
|
||||
smp_mb();
|
||||
} while (reader_count() >= 1);
|
||||
|
||||
bdrv_drain_all_end();
|
||||
if (need_drain) {
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
}
|
||||
|
||||
void no_coroutine_fn bdrv_graph_wrlock_drained(void)
|
||||
{
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
wrlock_quiesced_counter++;
|
||||
bdrv_graph_wrlock();
|
||||
}
|
||||
|
||||
void no_coroutine_fn bdrv_graph_wrunlock(void)
|
||||
@@ -168,6 +196,12 @@ void no_coroutine_fn bdrv_graph_wrunlock(void)
|
||||
* progress.
|
||||
*/
|
||||
aio_bh_poll(qemu_get_aio_context());
|
||||
|
||||
if (wrlock_quiesced_counter > 0) {
|
||||
bdrv_drain_all_end();
|
||||
wrlock_quiesced_counter--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void coroutine_fn bdrv_graph_co_rdlock(void)
|
||||
|
||||
+2
-5
@@ -361,7 +361,7 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, BdrvChild *parent,
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
/* Stop things in parent-to-child order */
|
||||
if (qatomic_fetch_inc(&bs->quiesce_counter) == 0) {
|
||||
if (bs->quiesce_counter++ == 0) {
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
bdrv_parent_drained_begin(bs, parent);
|
||||
if (bs->drv && bs->drv->bdrv_drain_begin) {
|
||||
@@ -401,8 +401,6 @@ bdrv_drained_begin(BlockDriverState *bs)
|
||||
*/
|
||||
static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
|
||||
{
|
||||
int old_quiesce_counter;
|
||||
|
||||
IO_OR_GS_CODE();
|
||||
|
||||
if (qemu_in_coroutine()) {
|
||||
@@ -415,8 +413,7 @@ static void bdrv_do_drained_end(BlockDriverState *bs, BdrvChild *parent)
|
||||
assert(bs->quiesce_counter > 0);
|
||||
|
||||
/* Re-enable things in child-to-parent order */
|
||||
old_quiesce_counter = qatomic_fetch_dec(&bs->quiesce_counter);
|
||||
if (old_quiesce_counter == 1) {
|
||||
if (--bs->quiesce_counter == 0) {
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
if (bs->drv && bs->drv->bdrv_drain_end) {
|
||||
bs->drv->bdrv_drain_end(bs);
|
||||
|
||||
+9
-8
@@ -761,10 +761,14 @@ static int mirror_exit_common(Job *job)
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing,
|
||||
&error_abort);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
if (!abort && s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
|
||||
BlockDriverState *backing;
|
||||
BlockDriverState *unfiltered_target = bdrv_skip_filters(target_bs);
|
||||
BlockDriverState *unfiltered_target;
|
||||
|
||||
bdrv_graph_wrlock_drained();
|
||||
unfiltered_target = bdrv_skip_filters(target_bs);
|
||||
|
||||
backing = s->sync_mode == MIRROR_SYNC_MODE_NONE ? src : s->base;
|
||||
if (bdrv_cow_bs(unfiltered_target) != backing) {
|
||||
@@ -775,16 +779,18 @@ static int mirror_exit_common(Job *job)
|
||||
ret = -EPERM;
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
} else if (!abort && s->backing_mode == MIRROR_OPEN_BACKING_CHAIN) {
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
assert(!bdrv_backing_chain_next(target_bs));
|
||||
ret = bdrv_open_backing_file(bdrv_skip_filters(target_bs), NULL,
|
||||
"backing", &local_err);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
if (ret < 0) {
|
||||
error_report_err(local_err);
|
||||
local_err = NULL;
|
||||
}
|
||||
}
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
if (s->should_complete && !abort) {
|
||||
BlockDriverState *to_replace = s->to_replace ?: src;
|
||||
@@ -2014,15 +2020,13 @@ static BlockJob *mirror_start_job(
|
||||
*/
|
||||
bdrv_disable_dirty_bitmap(s->dirty_bitmap);
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
ret = block_job_add_bdrv(&s->common, "source", bs, 0,
|
||||
BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE |
|
||||
BLK_PERM_CONSISTENT_READ,
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -2068,19 +2072,16 @@ static BlockJob *mirror_start_job(
|
||||
iter_shared_perms, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
QTAILQ_INIT(&s->ops_in_flight);
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
||||
Error *local_err = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
bs = bdrv_find_node(id);
|
||||
if (bs) {
|
||||
@@ -152,29 +152,31 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
}
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
blk = blk_by_name(id);
|
||||
if (!blk) {
|
||||
error_report("Device '%s' not found", id);
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!blk_legacy_dinfo(blk)) {
|
||||
error_report("Deleting device added with blockdev-add"
|
||||
" is not supported");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
bs = blk_bs(blk);
|
||||
if (bs) {
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_DRIVE_DEL, &local_err)) {
|
||||
error_report_err(local_err);
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
blk_remove_bs(blk);
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
}
|
||||
|
||||
/* Make the BlockBackend and the attached BlockDriverState anonymous */
|
||||
@@ -191,6 +193,9 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
||||
} else {
|
||||
blk_unref(blk);
|
||||
}
|
||||
|
||||
unlock:
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
}
|
||||
|
||||
void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||
|
||||
+10
-2
@@ -51,6 +51,8 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
ImageInfo *backing_info;
|
||||
BlockDriverState *backing;
|
||||
BlockDeviceInfo *info;
|
||||
BlockdevChildList **children_list_tail;
|
||||
BdrvChild *child;
|
||||
|
||||
if (!bs->drv) {
|
||||
error_setg(errp, "Block device %s is ejected", bs->node_name);
|
||||
@@ -73,8 +75,14 @@ BlockDeviceInfo *bdrv_block_device_info(BlockBackend *blk,
|
||||
.no_flush = !!(bs->open_flags & BDRV_O_NO_FLUSH),
|
||||
};
|
||||
|
||||
if (bs->node_name[0]) {
|
||||
info->node_name = g_strdup(bs->node_name);
|
||||
info->node_name = g_strdup(bs->node_name);
|
||||
|
||||
children_list_tail = &info->children;
|
||||
QLIST_FOREACH(child, &bs->children, next) {
|
||||
BlockdevChild *child_ref = g_new0(BlockdevChild, 1);
|
||||
child_ref->child = g_strdup(child->name);
|
||||
child_ref->node_name = g_strdup(child->bs->node_name);
|
||||
QAPI_LIST_APPEND(children_list_tail, child_ref);
|
||||
}
|
||||
|
||||
backing = bdrv_cow_bs(bs);
|
||||
|
||||
+1
-3
@@ -2823,11 +2823,9 @@ qcow2_do_close(BlockDriverState *bs, bool close_data_file)
|
||||
if (close_data_file && has_data_file(bs)) {
|
||||
GLOBAL_STATE_CODE();
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, s->data_file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
s->data_file = NULL;
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
}
|
||||
|
||||
+2
-6
@@ -1037,8 +1037,7 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
close_exit:
|
||||
/* cleanup on error */
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
if (!opened[i]) {
|
||||
continue;
|
||||
@@ -1046,7 +1045,6 @@ close_exit:
|
||||
bdrv_unref_child(bs, s->children[i]);
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
g_free(s->children);
|
||||
g_free(opened);
|
||||
exit:
|
||||
@@ -1059,13 +1057,11 @@ static void quorum_close(BlockDriverState *bs)
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_unref_child(bs, s->children[i]);
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
g_free(s->children);
|
||||
}
|
||||
|
||||
+4
-10
@@ -364,14 +364,15 @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
|
||||
BlockReopenQueue *reopen_queue = NULL;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
/*
|
||||
* s->hidden_disk and s->secondary_disk may not be set yet, as they will
|
||||
* only be set after the children are writable.
|
||||
*/
|
||||
hidden_disk = bs->file->bs->backing;
|
||||
secondary_disk = hidden_disk->bs->backing;
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
|
||||
if (writable) {
|
||||
s->orig_hidden_read_only = bdrv_is_read_only(hidden_disk->bs);
|
||||
@@ -540,8 +541,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
return;
|
||||
}
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
|
||||
bdrv_ref(hidden_disk->bs);
|
||||
s->hidden_disk = bdrv_attach_child(bs, hidden_disk->bs, "hidden disk",
|
||||
@@ -550,7 +550,6 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -561,7 +560,6 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -574,14 +572,12 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode,
|
||||
!check_top_bs(top_bs, bs)) {
|
||||
error_setg(errp, "No top_bs or it is invalid");
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
reopen_backing_file(bs, false, NULL);
|
||||
return;
|
||||
}
|
||||
bdrv_op_block_all(top_bs, s->blocker);
|
||||
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
s->backup_job = backup_job_create(
|
||||
NULL, s->secondary_disk->bs, s->hidden_disk->bs,
|
||||
@@ -656,14 +652,12 @@ static void replication_done(void *opaque, int ret)
|
||||
if (ret == 0) {
|
||||
s->stage = BLOCK_REPLICATION_DONE;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, s->secondary_disk);
|
||||
s->secondary_disk = NULL;
|
||||
bdrv_unref_child(bs, s->hidden_disk);
|
||||
s->hidden_disk = NULL;
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
s->error = 0;
|
||||
} else {
|
||||
|
||||
+1
-3
@@ -291,11 +291,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
/* .bdrv_open() will re-attach it */
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, fallback);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
|
||||
memset(bs->opaque, 0, drv->instance_size);
|
||||
|
||||
+8
-13
@@ -51,7 +51,7 @@ static int coroutine_fn stream_populate(BlockBackend *blk,
|
||||
return blk_co_preadv(blk, offset, bytes, NULL, BDRV_REQ_PREFETCH);
|
||||
}
|
||||
|
||||
static int stream_prepare(Job *job)
|
||||
static int GRAPH_UNLOCKED stream_prepare(Job *job)
|
||||
{
|
||||
StreamBlockJob *s = container_of(job, StreamBlockJob, common.job);
|
||||
BlockDriverState *unfiltered_bs;
|
||||
@@ -73,12 +73,11 @@ static int stream_prepare(Job *job)
|
||||
s->cor_filter_bs = NULL;
|
||||
|
||||
/*
|
||||
* bdrv_set_backing_hd() requires that the unfiltered_bs and the COW child
|
||||
* of unfiltered_bs is drained. Drain already here and use
|
||||
* bdrv_set_backing_hd_drained() instead because the polling during
|
||||
* drained_begin() might change the graph, and if we do this only later, we
|
||||
* may end up working with the wrong base node (or it might even have gone
|
||||
* away by the time we want to use it).
|
||||
* bdrv_set_backing_hd() requires that all block nodes are drained. Drain
|
||||
* already here, because the polling during drained_begin() might change the
|
||||
* graph, and if we do this only later, we may end up working with the wrong
|
||||
* base node (or it might even have gone away by the time we want to use
|
||||
* it).
|
||||
*/
|
||||
if (unfiltered_bs_cow) {
|
||||
bdrv_ref(unfiltered_bs_cow);
|
||||
@@ -105,7 +104,7 @@ static int stream_prepare(Job *job)
|
||||
}
|
||||
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err);
|
||||
bdrv_set_backing_hd(unfiltered_bs, base, &local_err);
|
||||
bdrv_graph_wrunlock();
|
||||
|
||||
/*
|
||||
@@ -371,12 +370,10 @@ void stream_start(const char *job_id, BlockDriverState *bs,
|
||||
* already have our own plans. Also don't allow resize as the image size is
|
||||
* queried only at the job start and then cached.
|
||||
*/
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
if (block_job_add_bdrv(&s->common, "active node", bs, 0,
|
||||
basic_flags | BLK_PERM_WRITE, errp)) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -397,12 +394,10 @@ void stream_start(const char *job_id, BlockDriverState *bs,
|
||||
basic_flags, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
s->base_overlay = base_overlay;
|
||||
s->above_base = above_base;
|
||||
|
||||
+9
-17
@@ -271,8 +271,7 @@ static void vmdk_free_extents(BlockDriverState *bs)
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
VmdkExtent *e;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
for (i = 0; i < s->num_extents; i++) {
|
||||
e = &s->extents[i];
|
||||
g_free(e->l1_table);
|
||||
@@ -284,7 +283,6 @@ static void vmdk_free_extents(BlockDriverState *bs)
|
||||
}
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
|
||||
g_free(s->extents);
|
||||
}
|
||||
@@ -1231,9 +1229,11 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
extent_role |= BDRV_CHILD_METADATA;
|
||||
}
|
||||
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,
|
||||
bs, &child_of_bds, extent_role, false,
|
||||
&local_err);
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
g_free(extent_path);
|
||||
if (!extent_file) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -1249,11 +1249,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
0, 0, 0, 0, 0, &extent, errp);
|
||||
if (ret < 0) {
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
goto out;
|
||||
}
|
||||
@@ -1270,11 +1268,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
g_free(buf);
|
||||
if (ret) {
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
goto out;
|
||||
}
|
||||
@@ -1283,11 +1279,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp);
|
||||
if (ret) {
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
goto out;
|
||||
}
|
||||
@@ -1295,11 +1289,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options,
|
||||
} else {
|
||||
error_setg(errp, "Unsupported extent type '%s'", type);
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
bdrv_unref_child(bs, extent_file);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
ret = -ENOTSUP;
|
||||
goto out;
|
||||
@@ -1362,13 +1354,13 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
uint32_t magic;
|
||||
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
buf = vmdk_read_desc(bs->file, 0, errp);
|
||||
if (!buf) {
|
||||
return -EINVAL;
|
||||
|
||||
+64
-40
@@ -1421,7 +1421,7 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
/* Paired with .clean() */
|
||||
bdrv_drained_begin(state->old_bs);
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
/* Make sure the associated bs did not change with the drain. */
|
||||
check_bs = bdrv_lookup_bs(device, node_name, errp);
|
||||
@@ -1430,18 +1430,18 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
error_setg(errp, "Block node of device '%s' unexpectedly changed",
|
||||
device);
|
||||
} /* else errp is already set */
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!bdrv_is_inserted(state->old_bs)) {
|
||||
error_setg(errp, "Device '%s' has no medium",
|
||||
bdrv_get_device_or_node_name(state->old_bs));
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(state->old_bs,
|
||||
BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!bdrv_is_read_only(state->old_bs)) {
|
||||
@@ -1449,7 +1449,7 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Write to node '%s' failed",
|
||||
bdrv_get_device_or_node_name(state->old_bs));
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1461,13 +1461,13 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
|
||||
if (node_name && !snapshot_node_name) {
|
||||
error_setg(errp, "New overlay node-name missing");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (snapshot_node_name &&
|
||||
bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) {
|
||||
error_setg(errp, "New overlay node-name already in use");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
flags = state->old_bs->open_flags;
|
||||
@@ -1480,7 +1480,7 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
int64_t size = bdrv_getlength(state->old_bs);
|
||||
if (size < 0) {
|
||||
error_setg_errno(errp, -size, "bdrv_getlength failed");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
bdrv_refresh_filename(state->old_bs);
|
||||
|
||||
@@ -1491,7 +1491,7 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1507,7 +1507,7 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
|
||||
/* We will manually add the backing_hd field to the bs later */
|
||||
if (!state->new_bs) {
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1518,22 +1518,22 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
bdrv_get_cumulative_perm(state->new_bs, &perm, &shared);
|
||||
if (perm & BLK_PERM_CONSISTENT_READ) {
|
||||
error_setg(errp, "The overlay is already in use");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (state->new_bs->drv->is_filter) {
|
||||
error_setg(errp, "Filters cannot be used as overlays");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (bdrv_cow_child(state->new_bs)) {
|
||||
error_setg(errp, "The overlay already has a backing image");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (!state->new_bs->drv->supports_backing) {
|
||||
error_setg(errp, "The overlay does not support backing images");
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1546,17 +1546,23 @@ static void external_snapshot_action(TransactionAction *action,
|
||||
* to keep this working.
|
||||
*/
|
||||
if (bdrv_is_inactive(state->old_bs) && !bdrv_is_inactive(state->new_bs)) {
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
ret = bdrv_inactivate(state->new_bs, errp);
|
||||
bdrv_drain_all_end();
|
||||
if (ret < 0) {
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
ret = bdrv_append(state->new_bs, state->old_bs, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
goto unlock;
|
||||
}
|
||||
state->overlay_appended = true;
|
||||
unlock:
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
}
|
||||
|
||||
static void external_snapshot_commit(void *opaque)
|
||||
@@ -1580,10 +1586,18 @@ static void external_snapshot_abort(void *opaque)
|
||||
AioContext *tmp_context;
|
||||
int ret;
|
||||
|
||||
bdrv_graph_wrlock_drained();
|
||||
|
||||
aio_context = bdrv_get_aio_context(state->old_bs);
|
||||
|
||||
bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd()
|
||||
close state->old_bs; we need it */
|
||||
/*
|
||||
* Note that state->old_bs would not disappear during the
|
||||
* write-locked section, because the unref from
|
||||
* bdrv_set_backing_hd() only happens at the end of the write-locked
|
||||
* section. However, just be explicit about keeping a reference and
|
||||
* don't rely on that implicit detail.
|
||||
*/
|
||||
bdrv_ref(state->old_bs);
|
||||
bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
|
||||
|
||||
/*
|
||||
@@ -1593,16 +1607,14 @@ static void external_snapshot_abort(void *opaque)
|
||||
*/
|
||||
tmp_context = bdrv_get_aio_context(state->old_bs);
|
||||
if (aio_context != tmp_context) {
|
||||
ret = bdrv_try_change_aio_context(state->old_bs,
|
||||
aio_context, NULL, NULL);
|
||||
ret = bdrv_try_change_aio_context_locked(state->old_bs,
|
||||
aio_context, NULL,
|
||||
NULL);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
bdrv_drained_begin(state->new_bs);
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drained_end(state->new_bs);
|
||||
|
||||
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
|
||||
}
|
||||
@@ -1770,7 +1782,10 @@ static void drive_backup_action(DriveBackup *backup,
|
||||
}
|
||||
|
||||
if (set_backing_hd) {
|
||||
if (bdrv_set_backing_hd(target_bs, source, errp) < 0) {
|
||||
bdrv_graph_wrlock_drained();
|
||||
ret = bdrv_set_backing_hd(target_bs, source, errp);
|
||||
bdrv_graph_wrunlock();
|
||||
if (ret < 0) {
|
||||
goto unref;
|
||||
}
|
||||
}
|
||||
@@ -3511,10 +3526,10 @@ void qmp_blockdev_del(const char *node_name, Error **errp)
|
||||
|
||||
void qmp_blockdev_set_active(const char *node_name, bool active, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
int ret;
|
||||
|
||||
GLOBAL_STATE_CODE();
|
||||
GRAPH_RDLOCK_GUARD_MAINLOOP();
|
||||
|
||||
if (!node_name) {
|
||||
if (active) {
|
||||
@@ -3525,19 +3540,30 @@ void qmp_blockdev_set_active(const char *node_name, bool active, Error **errp)
|
||||
error_setg_errno(errp, -ret, "Failed to inactivate all nodes");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BlockDriverState *bs = bdrv_find_node(node_name);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Failed to find node with node-name='%s'",
|
||||
node_name);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (active) {
|
||||
bdrv_activate(bs, errp);
|
||||
} else {
|
||||
bdrv_inactivate(bs, errp);
|
||||
}
|
||||
if (!active) {
|
||||
bdrv_drain_all_begin();
|
||||
}
|
||||
bdrv_graph_rdlock_main_loop();
|
||||
|
||||
bs = bdrv_find_node(node_name);
|
||||
if (!bs) {
|
||||
error_setg(errp, "Failed to find node with node-name='%s'",
|
||||
node_name);
|
||||
goto unlock;
|
||||
}
|
||||
if (active) {
|
||||
bdrv_activate(bs, errp);
|
||||
} else {
|
||||
bdrv_inactivate(bs, errp);
|
||||
}
|
||||
|
||||
unlock:
|
||||
bdrv_graph_rdunlock_main_loop();
|
||||
if (!active) {
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3561,8 +3587,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child,
|
||||
BlockDriverState *parent_bs, *new_bs = NULL;
|
||||
BdrvChild *p_child;
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
|
||||
parent_bs = bdrv_lookup_bs(parent, parent, errp);
|
||||
if (!parent_bs) {
|
||||
@@ -3599,7 +3624,6 @@ void qmp_x_blockdev_change(const char *parent, const char *child,
|
||||
|
||||
out:
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
|
||||
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
|
||||
|
||||
+2
-8
@@ -198,8 +198,7 @@ void block_job_remove_all_bdrv(BlockJob *job)
|
||||
* one to make sure that such a concurrent access does not attempt
|
||||
* to process an already freed BdrvChild.
|
||||
*/
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
while (job->nodes) {
|
||||
GSList *l = job->nodes;
|
||||
BdrvChild *c = l->data;
|
||||
@@ -212,7 +211,6 @@ void block_job_remove_all_bdrv(BlockJob *job)
|
||||
g_slist_free_1(l);
|
||||
}
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
}
|
||||
|
||||
bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs)
|
||||
@@ -498,8 +496,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
int ret;
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
bdrv_drain_all_begin();
|
||||
bdrv_graph_wrlock();
|
||||
bdrv_graph_wrlock_drained();
|
||||
|
||||
if (job_id == NULL && !(flags & JOB_INTERNAL)) {
|
||||
job_id = bdrv_get_device_name(bs);
|
||||
@@ -509,7 +506,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
flags, cb, opaque, errp);
|
||||
if (job == NULL) {
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -548,12 +544,10 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||
}
|
||||
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
return job;
|
||||
|
||||
fail:
|
||||
bdrv_graph_wrunlock();
|
||||
bdrv_drain_all_end();
|
||||
job_early_fail(&job->job);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user