diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-06-28 17:29:53 +0200 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-06-28 17:29:53 +0200 |
commit | 0eb8f90edebc11022a42abb211b026fac2e276f5 (patch) | |
tree | e28526854f07253dd89bd7c5f08d34e0f2b948c1 /block.c | |
parent | 47d183b7a8db1693e9cb342fb66b61809765872b (diff) | |
parent | 17362398ee1a7f04e8006a46333145d8b707fd35 (diff) | |
download | qemu-0eb8f90edebc11022a42abb211b026fac2e276f5.zip qemu-0eb8f90edebc11022a42abb211b026fac2e276f5.tar.gz qemu-0eb8f90edebc11022a42abb211b026fac2e276f5.tar.bz2 |
Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging
Block layer patches
- Re-enable the graph lock
- More fixes to coroutine_fn marking
# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmScQCQRHGt3b2xmQHJl
# ZGhhdC5jb20ACgkQfwmycsiPL9bNSA//WIzPT45rFhl2U9QgyOJu26ho6ahsgwgI
# Z3QM5kCDB1dAN9USRPxhGboLGo8CyY7eeSwSrR7RtwBGYrWrAoJfGp5gK/7d9s5Q
# o0AGgRPnJGhFkBhRRMytsDsewM6Kk4IRmk4HMK3cOH3rsSM8RHs6KmDSBKesllu0
# QVGf3qW4u8LHyZyGM5OlPVUbtuDuK6/52FGhpXBp+x4oyNegOhjwO4mGOvTG+xIk
# Q5zwWZaPfjxaEDkvW8iahB6/D7Tpt64BmMf1Ydhxcd5eKEp932CiBI36aAlNKoRD
# Al5wztRx1GEh12ekN39jIi7Ypp3JX26keJcieKU0q656pT551UFRYjU0Rk08/Cca
# qv2oiQDu6bHgQ9zCQ1nMfa9+K2MyBwx0b5qfYkvs2RzgCTl8ImgBQANHfw8tz6Bq
# HUo1zsFBXCaK0boUB5iFwdf3rlx3t9UTEuDej/RaHqZjZD5xeG/smCcOlSfHaKUa
# wXfYxvm8ZfefJn1D6io1A+7M956uvIQNtmh13cU44clgFX9Y/bBNMg/5lMRsJKo8
# xxjvqCAyxo/pPfUsVWx4pc8AXbfVa85gyoSiaLEYZnqP54sJ2lFccqykCsTy58Lo
# VDcoPnoSc+LNqBOvtzxXgQbEWFCXU6fe0+TZgVYUvExWFIAOImeDWg2GD1JVrwsX
# e9QrPhL3DXg=
# =ZQcP
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 28 Jun 2023 04:13:56 PM CEST
# gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6
# gpg: issuer "kwolf@redhat.com"
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full]
* tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (23 commits)
block: use bdrv_co_debug_event in coroutine context
block: use bdrv_co_getlength in coroutine context
qcow2: mark more functions as coroutine_fns and GRAPH_RDLOCK
vhdx: mark more functions as coroutine_fns and GRAPH_RDLOCK
vmdk: mark more functions as coroutine_fns and GRAPH_RDLOCK
dmg: mark more functions as coroutine_fns and GRAPH_RDLOCK
cloop: mark more functions as coroutine_fns and GRAPH_RDLOCK
block: mark another function as coroutine_fns and GRAPH_UNLOCKED
bochs: mark more functions as coroutine_fns and GRAPH_RDLOCK
vpc: mark more functions as coroutine_fns and GRAPH_RDLOCK
qed: mark more functions as coroutine_fns and GRAPH_RDLOCK
file-posix: remove incorrect coroutine_fn calls
Revert "graph-lock: Disable locking for now"
graph-lock: Unlock the AioContext while polling
blockjob: Fix AioContext locking in block_job_add_bdrv()
block: Fix AioContext locking in bdrv_open_backing_file()
block: Fix AioContext locking in bdrv_open_inherit()
block: Fix AioContext locking in bdrv_reopen_parse_file_or_backing()
block: Fix AioContext locking in bdrv_attach_child_common()
block: Fix AioContext locking in bdrv_open_child()
...
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 114 |
1 files changed, 101 insertions, 13 deletions
@@ -555,8 +555,9 @@ int coroutine_fn bdrv_co_create(BlockDriver *drv, const char *filename, * On success, return @blk's actual length. * Otherwise, return -errno. */ -static int64_t create_file_fallback_truncate(BlockBackend *blk, - int64_t minimum_size, Error **errp) +static int64_t coroutine_fn GRAPH_UNLOCKED +create_file_fallback_truncate(BlockBackend *blk, int64_t minimum_size, + Error **errp) { Error *local_err = NULL; int64_t size; @@ -564,14 +565,14 @@ static int64_t create_file_fallback_truncate(BlockBackend *blk, GLOBAL_STATE_CODE(); - ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0, - &local_err); + ret = blk_co_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0, + &local_err); if (ret < 0 && ret != -ENOTSUP) { error_propagate(errp, local_err); return ret; } - size = blk_getlength(blk); + size = blk_co_getlength(blk); if (size < 0) { error_free(local_err); error_setg_errno(errp, -size, @@ -2854,7 +2855,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 +2894,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 +2990,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 +3004,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 +3055,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 +3090,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 +3367,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 +3459,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 +3527,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 +3612,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 +3688,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 +3700,8 @@ BdrvChild *bdrv_open_child(const char *filename, bool allow_none, Error **errp) { BlockDriverState *bs; + BdrvChild *child; + AioContext *ctx; GLOBAL_STATE_CODE(); @@ -3674,13 +3711,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 +3800,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 +3809,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 +3846,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 +3893,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 +4031,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 +4083,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 +4147,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 +4165,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 +4644,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 +4661,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 +4727,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 +4761,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, |