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----- 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>
This commit is contained in:
		
						commit
						0eb8f90ede
					
				
							
								
								
									
										114
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								block.c
									
									
									
									
									
								
							| @ -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, | ||||
|  | ||||
| @ -203,7 +203,8 @@ static void bochs_refresh_limits(BlockDriverState *bs, Error **errp) | ||||
|     bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */ | ||||
| } | ||||
| 
 | ||||
| static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) | ||||
| static int64_t coroutine_fn GRAPH_RDLOCK | ||||
| seek_to_sector(BlockDriverState *bs, int64_t sector_num) | ||||
| { | ||||
|     BDRVBochsState *s = bs->opaque; | ||||
|     uint64_t offset = sector_num * 512; | ||||
| @ -224,8 +225,8 @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num) | ||||
|         (s->extent_blocks + s->bitmap_blocks)); | ||||
| 
 | ||||
|     /* read in bitmap for current extent */ | ||||
|     ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8), 1, | ||||
|                      &bitmap_entry, 0); | ||||
|     ret = bdrv_co_pread(bs->file, bitmap_offset + (extent_offset / 8), 1, | ||||
|                         &bitmap_entry, 0); | ||||
|     if (ret < 0) { | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
| @ -212,7 +212,8 @@ static void cloop_refresh_limits(BlockDriverState *bs, Error **errp) | ||||
|     bs->bl.request_alignment = BDRV_SECTOR_SIZE; /* No sub-sector I/O */ | ||||
| } | ||||
| 
 | ||||
| static inline int cloop_read_block(BlockDriverState *bs, int block_num) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| cloop_read_block(BlockDriverState *bs, int block_num) | ||||
| { | ||||
|     BDRVCloopState *s = bs->opaque; | ||||
| 
 | ||||
| @ -220,8 +221,8 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num) | ||||
|         int ret; | ||||
|         uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num]; | ||||
| 
 | ||||
|         ret = bdrv_pread(bs->file, s->offsets[block_num], bytes, | ||||
|                          s->compressed_block, 0); | ||||
|         ret = bdrv_co_pread(bs->file, s->offsets[block_num], bytes, | ||||
|                             s->compressed_block, 0); | ||||
|         if (ret < 0) { | ||||
|             return -1; | ||||
|         } | ||||
| @ -244,7 +245,7 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num) | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int coroutine_fn | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| cloop_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|                 QEMUIOVector *qiov, BdrvRequestFlags flags) | ||||
| { | ||||
|  | ||||
							
								
								
									
										21
									
								
								block/dmg.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								block/dmg.c
									
									
									
									
									
								
							| @ -616,7 +616,8 @@ err: | ||||
|     return s->n_chunks; /* error */ | ||||
| } | ||||
| 
 | ||||
| static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
| { | ||||
|     BDRVDMGState *s = bs->opaque; | ||||
| 
 | ||||
| @ -633,8 +634,8 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
|         case UDZO: { /* zlib compressed */ | ||||
|             /* we need to buffer, because only the chunk as whole can be
 | ||||
|              * inflated. */ | ||||
|             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                              s->compressed_chunk, 0); | ||||
|             ret = bdrv_co_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                                 s->compressed_chunk, 0); | ||||
|             if (ret < 0) { | ||||
|                 return -1; | ||||
|             } | ||||
| @ -659,8 +660,8 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
|             } | ||||
|             /* we need to buffer, because only the chunk as whole can be
 | ||||
|              * inflated. */ | ||||
|             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                              s->compressed_chunk, 0); | ||||
|             ret = bdrv_co_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                                 s->compressed_chunk, 0); | ||||
|             if (ret < 0) { | ||||
|                 return -1; | ||||
|             } | ||||
| @ -680,8 +681,8 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
|             } | ||||
|             /* we need to buffer, because only the chunk as whole can be
 | ||||
|              * inflated. */ | ||||
|             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                              s->compressed_chunk, 0); | ||||
|             ret = bdrv_co_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                                 s->compressed_chunk, 0); | ||||
|             if (ret < 0) { | ||||
|                 return -1; | ||||
|             } | ||||
| @ -696,8 +697,8 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
|             } | ||||
|             break; | ||||
|         case UDRW: /* copy */ | ||||
|             ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                              s->uncompressed_chunk, 0); | ||||
|             ret = bdrv_co_pread(bs->file, s->offsets[chunk], s->lengths[chunk], | ||||
|                                 s->uncompressed_chunk, 0); | ||||
|             if (ret < 0) { | ||||
|                 return -1; | ||||
|             } | ||||
| @ -713,7 +714,7 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int coroutine_fn | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| dmg_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|               QEMUIOVector *qiov, BdrvRequestFlags flags) | ||||
| { | ||||
|  | ||||
| @ -193,7 +193,7 @@ static int fd_open(BlockDriverState *bs) | ||||
|     return -EIO; | ||||
| } | ||||
| 
 | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs); | ||||
| static int64_t raw_getlength(BlockDriverState *bs); | ||||
| 
 | ||||
| typedef struct RawPosixAIOData { | ||||
|     BlockDriverState *bs; | ||||
| @ -1974,7 +1974,7 @@ static int handle_aiocb_write_zeroes(void *opaque) | ||||
| #ifdef CONFIG_FALLOCATE | ||||
|     /* Last resort: we are trying to extend the file with zeroed data. This
 | ||||
|      * can be done via fallocate(fd, 0) */ | ||||
|     len = raw_co_getlength(aiocb->bs); | ||||
|     len = raw_getlength(aiocb->bs); | ||||
|     if (s->has_fallocate && len >= 0 && aiocb->aio_offset >= len) { | ||||
|         int ret = do_fallocate(s->fd, 0, aiocb->aio_offset, aiocb->aio_nbytes); | ||||
|         if (ret == 0 || ret != -ENOTSUP) { | ||||
| @ -2666,7 +2666,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, | ||||
|     } | ||||
| 
 | ||||
|     if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { | ||||
|         int64_t cur_length = raw_co_getlength(bs); | ||||
|         int64_t cur_length = raw_getlength(bs); | ||||
| 
 | ||||
|         if (offset != cur_length && exact) { | ||||
|             error_setg(errp, "Cannot resize device files"); | ||||
| @ -2684,7 +2684,7 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, | ||||
| } | ||||
| 
 | ||||
| #ifdef __OpenBSD__ | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| static int64_t raw_getlength(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVRawState *s = bs->opaque; | ||||
|     int fd = s->fd; | ||||
| @ -2703,7 +2703,7 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
|         return st.st_size; | ||||
| } | ||||
| #elif defined(__NetBSD__) | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| static int64_t raw_getlength(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVRawState *s = bs->opaque; | ||||
|     int fd = s->fd; | ||||
| @ -2728,7 +2728,7 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
|         return st.st_size; | ||||
| } | ||||
| #elif defined(__sun__) | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| static int64_t raw_getlength(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVRawState *s = bs->opaque; | ||||
|     struct dk_minfo minfo; | ||||
| @ -2759,7 +2759,7 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
|     return size; | ||||
| } | ||||
| #elif defined(CONFIG_BSD) | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| static int64_t raw_getlength(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVRawState *s = bs->opaque; | ||||
|     int fd = s->fd; | ||||
| @ -2831,7 +2831,7 @@ again: | ||||
|     return size; | ||||
| } | ||||
| #else | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| static int64_t raw_getlength(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVRawState *s = bs->opaque; | ||||
|     int ret; | ||||
| @ -2850,6 +2850,11 @@ static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int64_t coroutine_fn raw_co_getlength(BlockDriverState *bs) | ||||
| { | ||||
|     return raw_getlength(bs); | ||||
| } | ||||
| 
 | ||||
| static int64_t coroutine_fn raw_co_get_allocated_file_size(BlockDriverState *bs) | ||||
| { | ||||
|     struct stat st; | ||||
| @ -3215,7 +3220,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, | ||||
|          * round up if necessary. | ||||
|          */ | ||||
|         if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) { | ||||
|             int64_t file_length = raw_co_getlength(bs); | ||||
|             int64_t file_length = raw_getlength(bs); | ||||
|             if (file_length > 0) { | ||||
|                 /* Ignore errors, this is just a safeguard */ | ||||
|                 assert(hole == file_length); | ||||
| @ -3237,7 +3242,7 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, | ||||
| 
 | ||||
| #if defined(__linux__) | ||||
| /* Verify that the file is not in the page cache */ | ||||
| static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp) | ||||
| static void check_cache_dropped(BlockDriverState *bs, Error **errp) | ||||
| { | ||||
|     const size_t window_size = 128 * 1024 * 1024; | ||||
|     BDRVRawState *s = bs->opaque; | ||||
| @ -3252,7 +3257,7 @@ static void coroutine_fn check_cache_dropped(BlockDriverState *bs, Error **errp) | ||||
|     page_size = sysconf(_SC_PAGESIZE); | ||||
|     vec = g_malloc(DIV_ROUND_UP(window_size, page_size)); | ||||
| 
 | ||||
|     end = raw_co_getlength(bs); | ||||
|     end = raw_getlength(bs); | ||||
| 
 | ||||
|     for (offset = 0; offset < end; offset += window_size) { | ||||
|         void *new_window; | ||||
| @ -4468,7 +4473,7 @@ static int cdrom_reopen(BlockDriverState *bs) | ||||
| 
 | ||||
| static bool coroutine_fn cdrom_co_is_inserted(BlockDriverState *bs) | ||||
| { | ||||
|     return raw_co_getlength(bs) > 0; | ||||
|     return raw_getlength(bs) > 0; | ||||
| } | ||||
| 
 | ||||
| static void coroutine_fn cdrom_co_eject(BlockDriverState *bs, bool eject_flag) | ||||
|  | ||||
| @ -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) | ||||
| @ -274,19 +275,13 @@ void bdrv_graph_rdunlock_main_loop(void) | ||||
| 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 | ||||
| } | ||||
|  | ||||
							
								
								
									
										14
									
								
								block/io.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								block/io.c
									
									
									
									
									
								
							| @ -1379,7 +1379,7 @@ bdrv_aligned_preadv(BdrvChild *child, BdrvTrackedRequest *req, | ||||
|     } | ||||
| 
 | ||||
|     /* Forward the request to the BlockDriver, possibly fragmenting it */ | ||||
|     total_bytes = bdrv_getlength(bs); | ||||
|     total_bytes = bdrv_co_getlength(bs); | ||||
|     if (total_bytes < 0) { | ||||
|         ret = total_bytes; | ||||
|         goto out; | ||||
| @ -2388,7 +2388,7 @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero, | ||||
|     assert(pnum); | ||||
|     assert_bdrv_graph_readable(); | ||||
|     *pnum = 0; | ||||
|     total_size = bdrv_getlength(bs); | ||||
|     total_size = bdrv_co_getlength(bs); | ||||
|     if (total_size < 0) { | ||||
|         ret = total_size; | ||||
|         goto early_out; | ||||
| @ -2408,7 +2408,7 @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero, | ||||
|         bytes = n; | ||||
|     } | ||||
| 
 | ||||
|     /* Must be non-NULL or bdrv_getlength() would have failed */ | ||||
|     /* Must be non-NULL or bdrv_co_getlength() would have failed */ | ||||
|     assert(bs->drv); | ||||
|     has_filtered_child = bdrv_filter_child(bs); | ||||
|     if (!bs->drv->bdrv_co_block_status && !has_filtered_child) { | ||||
| @ -2546,7 +2546,7 @@ bdrv_co_block_status(BlockDriverState *bs, bool want_zero, | ||||
|         if (!cow_bs) { | ||||
|             ret |= BDRV_BLOCK_ZERO; | ||||
|         } else if (want_zero) { | ||||
|             int64_t size2 = bdrv_getlength(cow_bs); | ||||
|             int64_t size2 = bdrv_co_getlength(cow_bs); | ||||
| 
 | ||||
|             if (size2 >= 0 && offset >= size2) { | ||||
|                 ret |= BDRV_BLOCK_ZERO; | ||||
| @ -3011,7 +3011,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) | ||||
|     } | ||||
| 
 | ||||
|     /* Write back cached data to the OS even with cache=unsafe */ | ||||
|     BLKDBG_EVENT(primary_child, BLKDBG_FLUSH_TO_OS); | ||||
|     BLKDBG_CO_EVENT(primary_child, BLKDBG_FLUSH_TO_OS); | ||||
|     if (bs->drv->bdrv_co_flush_to_os) { | ||||
|         ret = bs->drv->bdrv_co_flush_to_os(bs); | ||||
|         if (ret < 0) { | ||||
| @ -3029,7 +3029,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs) | ||||
|         goto flush_children; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(primary_child, BLKDBG_FLUSH_TO_DISK); | ||||
|     BLKDBG_CO_EVENT(primary_child, BLKDBG_FLUSH_TO_DISK); | ||||
|     if (!bs->drv) { | ||||
|         /* bs->drv->bdrv_co_flush() might have ejected the BDS
 | ||||
|          * (even in case of apparent success) */ | ||||
| @ -3592,7 +3592,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact, | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     old_size = bdrv_getlength(bs); | ||||
|     old_size = bdrv_co_getlength(bs); | ||||
|     if (old_size < 0) { | ||||
|         error_setg_errno(errp, -old_size, "Failed to get old image size"); | ||||
|         return old_size; | ||||
|  | ||||
| @ -200,7 +200,7 @@ allocate_clusters(BlockDriverState *bs, int64_t sector_num, | ||||
|     assert(idx < s->bat_size && idx + to_allocate <= s->bat_size); | ||||
| 
 | ||||
|     space = to_allocate * s->tracks; | ||||
|     len = bdrv_getlength(bs->file->bs); | ||||
|     len = bdrv_co_getlength(bs->file->bs); | ||||
|     if (len < 0) { | ||||
|         return len; | ||||
|     } | ||||
| @ -448,7 +448,7 @@ parallels_check_outside_image(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|     uint32_t i; | ||||
|     int64_t off, high_off, size; | ||||
| 
 | ||||
|     size = bdrv_getlength(bs->file->bs); | ||||
|     size = bdrv_co_getlength(bs->file->bs); | ||||
|     if (size < 0) { | ||||
|         res->check_errors++; | ||||
|         return size; | ||||
|  | ||||
							
								
								
									
										30
									
								
								block/qcow.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								block/qcow.c
									
									
									
									
									
								
							| @ -370,7 +370,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|         if (!allocate) | ||||
|             return 0; | ||||
|         /* allocate a new l2 entry */ | ||||
|         l2_offset = bdrv_getlength(bs->file->bs); | ||||
|         l2_offset = bdrv_co_getlength(bs->file->bs); | ||||
|         if (l2_offset < 0) { | ||||
|             return l2_offset; | ||||
|         } | ||||
| @ -379,7 +379,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|         /* update the L1 entry */ | ||||
|         s->l1_table[l1_index] = l2_offset; | ||||
|         tmp = cpu_to_be64(l2_offset); | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_L1_UPDATE); | ||||
|         ret = bdrv_co_pwrite_sync(bs->file, | ||||
|                                   s->l1_table_offset + l1_index * sizeof(tmp), | ||||
|                                   sizeof(tmp), &tmp, 0); | ||||
| @ -410,7 +410,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|         } | ||||
|     } | ||||
|     l2_table = s->l2_cache + (min_index << s->l2_bits); | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_L2_LOAD); | ||||
|     if (new_l2_table) { | ||||
|         memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); | ||||
|         ret = bdrv_co_pwrite_sync(bs->file, l2_offset, | ||||
| @ -434,7 +434,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|         ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) { | ||||
|         if (!allocate) | ||||
|             return 0; | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC); | ||||
|         assert(QEMU_IS_ALIGNED(n_start | n_end, BDRV_SECTOR_SIZE)); | ||||
|         /* allocate a new cluster */ | ||||
|         if ((cluster_offset & QCOW_OFLAG_COMPRESSED) && | ||||
| @ -445,20 +445,20 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|             if (decompress_cluster(bs, cluster_offset) < 0) { | ||||
|                 return -EIO; | ||||
|             } | ||||
|             cluster_offset = bdrv_getlength(bs->file->bs); | ||||
|             cluster_offset = bdrv_co_getlength(bs->file->bs); | ||||
|             if ((int64_t) cluster_offset < 0) { | ||||
|                 return cluster_offset; | ||||
|             } | ||||
|             cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size); | ||||
|             /* write the cluster content */ | ||||
|             BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|             BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|             ret = bdrv_co_pwrite(bs->file, cluster_offset, s->cluster_size, | ||||
|                                  s->cluster_cache, 0); | ||||
|             if (ret < 0) { | ||||
|                 return ret; | ||||
|             } | ||||
|         } else { | ||||
|             cluster_offset = bdrv_getlength(bs->file->bs); | ||||
|             cluster_offset = bdrv_co_getlength(bs->file->bs); | ||||
|             if ((int64_t) cluster_offset < 0) { | ||||
|                 return cluster_offset; | ||||
|             } | ||||
| @ -491,7 +491,7 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|                                                       NULL) < 0) { | ||||
|                                 return -EIO; | ||||
|                             } | ||||
|                             BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|                             BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|                             ret = bdrv_co_pwrite(bs->file, cluster_offset + i, | ||||
|                                                  BDRV_SECTOR_SIZE, | ||||
|                                                  s->cluster_data, 0); | ||||
| @ -510,9 +510,9 @@ get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate, | ||||
|         tmp = cpu_to_be64(cluster_offset); | ||||
|         l2_table[l2_index] = tmp; | ||||
|         if (allocate == 2) { | ||||
|             BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); | ||||
|             BLKDBG_CO_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); | ||||
|         } else { | ||||
|             BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); | ||||
|             BLKDBG_CO_EVENT(bs->file, BLKDBG_L2_UPDATE); | ||||
|         } | ||||
|         ret = bdrv_co_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp), | ||||
|                                   sizeof(tmp), &tmp, 0); | ||||
| @ -595,7 +595,7 @@ decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) | ||||
|     if (s->cluster_cache_offset != coffset) { | ||||
|         csize = cluster_offset >> (63 - s->cluster_bits); | ||||
|         csize &= (s->cluster_size - 1); | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_COMPRESSED); | ||||
|         ret = bdrv_co_pread(bs->file, coffset, csize, s->cluster_data, 0); | ||||
|         if (ret < 0) | ||||
|             return -1; | ||||
| @ -657,7 +657,7 @@ qcow_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|                 /* read from the base image */ | ||||
|                 qemu_co_mutex_unlock(&s->lock); | ||||
|                 /* qcow2 emits this on bs->file instead of bs->backing */ | ||||
|                 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|                 BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|                 ret = bdrv_co_pread(bs->backing, offset, n, buf, 0); | ||||
|                 qemu_co_mutex_lock(&s->lock); | ||||
|                 if (ret < 0) { | ||||
| @ -680,7 +680,7 @@ qcow_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|                 break; | ||||
|             } | ||||
|             qemu_co_mutex_unlock(&s->lock); | ||||
|             BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|             BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|             ret = bdrv_co_pread(bs->file, cluster_offset + offset_in_cluster, | ||||
|                                 n, buf, 0); | ||||
|             qemu_co_mutex_lock(&s->lock); | ||||
| @ -765,7 +765,7 @@ qcow_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|         } | ||||
| 
 | ||||
|         qemu_co_mutex_unlock(&s->lock); | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|         ret = bdrv_co_pwrite(bs->file, cluster_offset + offset_in_cluster, | ||||
|                              n, buf, 0); | ||||
|         qemu_co_mutex_lock(&s->lock); | ||||
| @ -1114,7 +1114,7 @@ qcow_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|     } | ||||
|     cluster_offset &= s->cluster_offset_mask; | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED); | ||||
|     ret = bdrv_co_pwrite(bs->file, cluster_offset, out_len, out_buf, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
|  | ||||
| @ -283,10 +283,9 @@ static int free_bitmap_clusters(BlockDriverState *bs, Qcow2BitmapTable *tb) | ||||
| /* load_bitmap_data
 | ||||
|  * @bitmap_table entries must satisfy specification constraints. | ||||
|  * @bitmap must be cleared */ | ||||
| static int load_bitmap_data(BlockDriverState *bs, | ||||
|                             const uint64_t *bitmap_table, | ||||
|                             uint32_t bitmap_table_size, | ||||
|                             BdrvDirtyBitmap *bitmap) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| load_bitmap_data(BlockDriverState *bs, const uint64_t *bitmap_table, | ||||
|                  uint32_t bitmap_table_size, BdrvDirtyBitmap *bitmap) | ||||
| { | ||||
|     int ret = 0; | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
| @ -319,7 +318,7 @@ static int load_bitmap_data(BlockDriverState *bs, | ||||
|                  * already cleared */ | ||||
|             } | ||||
|         } else { | ||||
|             ret = bdrv_pread(bs->file, data_offset, s->cluster_size, buf, 0); | ||||
|             ret = bdrv_co_pread(bs->file, data_offset, s->cluster_size, buf, 0); | ||||
|             if (ret < 0) { | ||||
|                 goto finish; | ||||
|             } | ||||
| @ -337,8 +336,9 @@ finish: | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs, | ||||
|                                     Qcow2Bitmap *bm, Error **errp) | ||||
| static coroutine_fn GRAPH_RDLOCK | ||||
| BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs, | ||||
|                              Qcow2Bitmap *bm, Error **errp) | ||||
| { | ||||
|     int ret; | ||||
|     uint64_t *bitmap_table = NULL; | ||||
| @ -649,9 +649,10 @@ fail: | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                                   void **refcount_table, | ||||
|                                   int64_t *refcount_table_size) | ||||
| int coroutine_fn | ||||
| qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                               void **refcount_table, | ||||
|                               int64_t *refcount_table_size) | ||||
| { | ||||
|     int ret; | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
| @ -957,8 +958,9 @@ static void set_readonly_helper(gpointer bitmap, gpointer value) | ||||
|  * If header_updated is not NULL then it is set appropriately regardless of | ||||
|  * the return value. | ||||
|  */ | ||||
| bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs, | ||||
|                                            bool *header_updated, Error **errp) | ||||
| bool coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_load_dirty_bitmaps(BlockDriverState *bs, | ||||
|                          bool *header_updated, Error **errp) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     Qcow2BitmapList *bm_list; | ||||
|  | ||||
| @ -48,7 +48,7 @@ int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, | ||||
|     fprintf(stderr, "shrink l1_table from %d to %d\n", s->l1_size, new_l1_size); | ||||
| #endif | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE); | ||||
|     ret = bdrv_co_pwrite_zeroes(bs->file, | ||||
|                                 s->l1_table_offset + new_l1_size * L1E_SIZE, | ||||
|                                 (s->l1_size - new_l1_size) * L1E_SIZE, 0); | ||||
| @ -61,7 +61,7 @@ int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, | ||||
|         goto fail; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_FREE_L2_CLUSTERS); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_L1_SHRINK_FREE_L2_CLUSTERS); | ||||
|     for (i = s->l1_size - 1; i > new_l1_size - 1; i--) { | ||||
|         if ((s->l1_table[i] & L1E_OFFSET_MASK) == 0) { | ||||
|             continue; | ||||
| @ -501,7 +501,7 @@ do_perform_cow_read(BlockDriverState *bs, uint64_t src_cluster_offset, | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_COW_READ); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_COW_READ); | ||||
| 
 | ||||
|     if (!bs->drv) { | ||||
|         return -ENOMEDIUM; | ||||
| @ -551,7 +551,7 @@ do_perform_cow_write(BlockDriverState *bs, uint64_t cluster_offset, | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_COW_WRITE); | ||||
|     ret = bdrv_co_pwritev(s->data_file, cluster_offset + offset_in_cluster, | ||||
|                           qiov->size, qiov, 0); | ||||
|     if (ret < 0) { | ||||
| @ -823,10 +823,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, | ||||
|  * | ||||
|  * Return 0 on success and -errno in error cases | ||||
|  */ | ||||
| int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, | ||||
|                                                        uint64_t offset, | ||||
|                                                        int compressed_size, | ||||
|                                                        uint64_t *host_offset) | ||||
| int coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, | ||||
|                                       int compressed_size, uint64_t *host_offset) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int l2_index, ret; | ||||
| @ -872,7 +871,7 @@ int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, | ||||
| 
 | ||||
|     /* compressed clusters never have the copied flag */ | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED); | ||||
|     qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice); | ||||
|     set_l2_entry(s, l2_slice, l2_index, cluster_offset); | ||||
|     if (has_subclusters(s)) { | ||||
| @ -992,7 +991,7 @@ perform_cow(BlockDriverState *bs, QCowL2Meta *m) | ||||
|         /* NOTE: we have a write_aio blkdebug event here followed by
 | ||||
|          * a cow_write one in do_perform_cow_write(), but there's only | ||||
|          * one single I/O operation */ | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|         ret = do_perform_cow_write(bs, m->alloc_offset, start->offset, &qiov); | ||||
|     } else { | ||||
|         /* If there's no guest data then write both COW regions separately */ | ||||
| @ -2038,8 +2037,9 @@ fail: | ||||
|  * all clusters in the same L2 slice) and returns the number of zeroed | ||||
|  * clusters. | ||||
|  */ | ||||
| static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, | ||||
|                             uint64_t nb_clusters, int flags) | ||||
| static int coroutine_fn | ||||
| zero_in_l2_slice(BlockDriverState *bs, uint64_t offset, | ||||
|                  uint64_t nb_clusters, int flags) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     uint64_t *l2_slice; | ||||
|  | ||||
| @ -118,7 +118,7 @@ int coroutine_fn qcow2_refcount_init(BlockDriverState *bs) | ||||
|             ret = -ENOMEM; | ||||
|             goto fail; | ||||
|         } | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_REFTABLE_LOAD); | ||||
|         ret = bdrv_co_pread(bs->file, s->refcount_table_offset, | ||||
|                             refcount_table_size2, s->refcount_table, 0); | ||||
|         if (ret < 0) { | ||||
| @ -1069,14 +1069,14 @@ int64_t coroutine_fn qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offs | ||||
| 
 | ||||
| /* only used to allocate compressed sectors. We try to allocate
 | ||||
|    contiguous sectors. size must be <= cluster_size */ | ||||
| int64_t coroutine_fn qcow2_alloc_bytes(BlockDriverState *bs, int size) | ||||
| int64_t coroutine_fn GRAPH_RDLOCK qcow2_alloc_bytes(BlockDriverState *bs, int size) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int64_t offset; | ||||
|     size_t free_in_cluster; | ||||
|     int ret; | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES); | ||||
|     assert(size > 0 && size <= s->cluster_size); | ||||
|     assert(!s->free_byte_offset || offset_into_cluster(s, s->free_byte_offset)); | ||||
| 
 | ||||
| @ -1524,10 +1524,11 @@ static int realloc_refcount_array(BDRVQcow2State *s, void **array, | ||||
|  * | ||||
|  * Modifies the number of errors in res. | ||||
|  */ | ||||
| int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                              void **refcount_table, | ||||
|                              int64_t *refcount_table_size, | ||||
|                              int64_t offset, int64_t size) | ||||
| int coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                          void **refcount_table, | ||||
|                          int64_t *refcount_table_size, | ||||
|                          int64_t offset, int64_t size) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     uint64_t start, last, cluster_offset, k, refcount; | ||||
| @ -1538,7 +1539,7 @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     file_len = bdrv_getlength(bs->file->bs); | ||||
|     file_len = bdrv_co_getlength(bs->file->bs); | ||||
|     if (file_len < 0) { | ||||
|         return file_len; | ||||
|     } | ||||
| @ -1600,10 +1601,11 @@ enum { | ||||
|  * | ||||
|  * On failure in-memory @l2_table may be modified. | ||||
|  */ | ||||
| static int fix_l2_entry_by_zero(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                                 uint64_t l2_offset, | ||||
|                                 uint64_t *l2_table, int l2_index, bool active, | ||||
|                                 bool *metadata_overlap) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| fix_l2_entry_by_zero(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                      uint64_t l2_offset, uint64_t *l2_table, | ||||
|                      int l2_index, bool active, | ||||
|                      bool *metadata_overlap) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int ret; | ||||
| @ -1634,8 +1636,8 @@ static int fix_l2_entry_by_zero(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|         goto fail; | ||||
|     } | ||||
| 
 | ||||
|     ret = bdrv_pwrite_sync(bs->file, l2e_offset, l2_entry_size(s), | ||||
|                            &l2_table[idx], 0); | ||||
|     ret = bdrv_co_pwrite_sync(bs->file, l2e_offset, l2_entry_size(s), | ||||
|                               &l2_table[idx], 0); | ||||
|     if (ret < 0) { | ||||
|         fprintf(stderr, "ERROR: Failed to overwrite L2 " | ||||
|                 "table entry: %s\n", strerror(-ret)); | ||||
| @ -1659,10 +1661,11 @@ fail: | ||||
|  * Returns the number of errors found by the checks or -errno if an internal | ||||
|  * error occurred. | ||||
|  */ | ||||
| static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                               void **refcount_table, | ||||
|                               int64_t *refcount_table_size, int64_t l2_offset, | ||||
|                               int flags, BdrvCheckMode fix, bool active) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                    void **refcount_table, | ||||
|                    int64_t *refcount_table_size, int64_t l2_offset, | ||||
|                    int flags, BdrvCheckMode fix, bool active) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     uint64_t l2_entry, l2_bitmap; | ||||
| @ -1673,7 +1676,7 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|     bool metadata_overlap; | ||||
| 
 | ||||
|     /* Read L2 table from disk */ | ||||
|     ret = bdrv_pread(bs->file, l2_offset, l2_size_bytes, l2_table, 0); | ||||
|     ret = bdrv_co_pread(bs->file, l2_offset, l2_size_bytes, l2_table, 0); | ||||
|     if (ret < 0) { | ||||
|         fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n"); | ||||
|         res->check_errors++; | ||||
| @ -1858,12 +1861,11 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|  * Returns the number of errors found by the checks or -errno if an internal | ||||
|  * error occurred. | ||||
|  */ | ||||
| static int check_refcounts_l1(BlockDriverState *bs, | ||||
|                               BdrvCheckResult *res, | ||||
|                               void **refcount_table, | ||||
|                               int64_t *refcount_table_size, | ||||
|                               int64_t l1_table_offset, int l1_size, | ||||
|                               int flags, BdrvCheckMode fix, bool active) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| check_refcounts_l1(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                    void **refcount_table, int64_t *refcount_table_size, | ||||
|                    int64_t l1_table_offset, int l1_size, | ||||
|                    int flags, BdrvCheckMode fix, bool active) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     size_t l1_size_bytes = l1_size * L1E_SIZE; | ||||
| @ -1889,7 +1891,7 @@ static int check_refcounts_l1(BlockDriverState *bs, | ||||
|     } | ||||
| 
 | ||||
|     /* Read L1 table entries from disk */ | ||||
|     ret = bdrv_pread(bs->file, l1_table_offset, l1_size_bytes, l1_table, 0); | ||||
|     ret = bdrv_co_pread(bs->file, l1_table_offset, l1_size_bytes, l1_table, 0); | ||||
|     if (ret < 0) { | ||||
|         fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n"); | ||||
|         res->check_errors++; | ||||
| @ -1949,8 +1951,8 @@ static int check_refcounts_l1(BlockDriverState *bs, | ||||
|  * have been already detected and sufficiently signaled by the calling function | ||||
|  * (qcow2_check_refcounts) by the time this function is called). | ||||
|  */ | ||||
| static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                               BdrvCheckMode fix) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     uint64_t *l2_table = qemu_blockalign(bs, s->cluster_size); | ||||
| @ -2005,8 +2007,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         ret = bdrv_pread(bs->file, l2_offset, s->l2_size * l2_entry_size(s), | ||||
|                          l2_table, 0); | ||||
|         ret = bdrv_co_pread(bs->file, l2_offset, s->l2_size * l2_entry_size(s), | ||||
|                             l2_table, 0); | ||||
|         if (ret < 0) { | ||||
|             fprintf(stderr, "ERROR: Could not read L2 table: %s\n", | ||||
|                     strerror(-ret)); | ||||
| @ -2059,8 +2061,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                 goto fail; | ||||
|             } | ||||
| 
 | ||||
|             ret = bdrv_pwrite(bs->file, l2_offset, s->cluster_size, l2_table, | ||||
|                               0); | ||||
|             ret = bdrv_co_pwrite(bs->file, l2_offset, s->cluster_size, l2_table, 0); | ||||
|             if (ret < 0) { | ||||
|                 fprintf(stderr, "ERROR: Could not write L2 table: %s\n", | ||||
|                         strerror(-ret)); | ||||
| @ -2083,9 +2084,10 @@ fail: | ||||
|  * Checks consistency of refblocks and accounts for each refblock in | ||||
|  * *refcount_table. | ||||
|  */ | ||||
| static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                            BdrvCheckMode fix, bool *rebuild, | ||||
|                            void **refcount_table, int64_t *nb_clusters) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                 BdrvCheckMode fix, bool *rebuild, | ||||
|                 void **refcount_table, int64_t *nb_clusters) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int64_t i, size; | ||||
| @ -2127,13 +2129,13 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                     goto resize_fail; | ||||
|                 } | ||||
| 
 | ||||
|                 ret = bdrv_truncate(bs->file, offset + s->cluster_size, false, | ||||
|                                     PREALLOC_MODE_OFF, 0, &local_err); | ||||
|                 ret = bdrv_co_truncate(bs->file, offset + s->cluster_size, false, | ||||
|                                        PREALLOC_MODE_OFF, 0, &local_err); | ||||
|                 if (ret < 0) { | ||||
|                     error_report_err(local_err); | ||||
|                     goto resize_fail; | ||||
|                 } | ||||
|                 size = bdrv_getlength(bs->file->bs); | ||||
|                 size = bdrv_co_getlength(bs->file->bs); | ||||
|                 if (size < 0) { | ||||
|                     ret = size; | ||||
|                     goto resize_fail; | ||||
| @ -2197,9 +2199,10 @@ resize_fail: | ||||
| /*
 | ||||
|  * Calculates an in-memory refcount table. | ||||
|  */ | ||||
| static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                                BdrvCheckMode fix, bool *rebuild, | ||||
|                                void **refcount_table, int64_t *nb_clusters) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                     BdrvCheckMode fix, bool *rebuild, | ||||
|                     void **refcount_table, int64_t *nb_clusters) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int64_t i; | ||||
| @ -2299,10 +2302,11 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|  * Compares the actual reference count for each cluster in the image against the | ||||
|  * refcount as reported by the refcount structures on-disk. | ||||
|  */ | ||||
| static void compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                               BdrvCheckMode fix, bool *rebuild, | ||||
|                               int64_t *highest_cluster, | ||||
|                               void *refcount_table, int64_t nb_clusters) | ||||
| static void coroutine_fn | ||||
| compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                   BdrvCheckMode fix, bool *rebuild, | ||||
|                   int64_t *highest_cluster, | ||||
|                   void *refcount_table, int64_t nb_clusters) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int64_t i; | ||||
| @ -2463,7 +2467,8 @@ static int64_t alloc_clusters_imrt(BlockDriverState *bs, | ||||
|  * Return whether the on-disk reftable array was resized (true/false), | ||||
|  * or -errno on error. | ||||
|  */ | ||||
| static int rebuild_refcounts_write_refblocks( | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| rebuild_refcounts_write_refblocks( | ||||
|         BlockDriverState *bs, void **refcount_table, int64_t *nb_clusters, | ||||
|         int64_t first_cluster, int64_t end_cluster, | ||||
|         uint64_t **on_disk_reftable_ptr, uint32_t *on_disk_reftable_entries_ptr, | ||||
| @ -2578,8 +2583,8 @@ static int rebuild_refcounts_write_refblocks( | ||||
|         on_disk_refblock = (void *)((char *) *refcount_table + | ||||
|                                     refblock_index * s->cluster_size); | ||||
| 
 | ||||
|         ret = bdrv_pwrite(bs->file, refblock_offset, s->cluster_size, | ||||
|                           on_disk_refblock, 0); | ||||
|         ret = bdrv_co_pwrite(bs->file, refblock_offset, s->cluster_size, | ||||
|                              on_disk_refblock, 0); | ||||
|         if (ret < 0) { | ||||
|             error_setg_errno(errp, -ret, "ERROR writing refblock"); | ||||
|             return ret; | ||||
| @ -2601,11 +2606,10 @@ static int rebuild_refcounts_write_refblocks( | ||||
|  * On success, the old refcount structure is leaked (it will be covered by the | ||||
|  * new refcount structure). | ||||
|  */ | ||||
| static int rebuild_refcount_structure(BlockDriverState *bs, | ||||
|                                       BdrvCheckResult *res, | ||||
|                                       void **refcount_table, | ||||
|                                       int64_t *nb_clusters, | ||||
|                                       Error **errp) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| rebuild_refcount_structure(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                            void **refcount_table, int64_t *nb_clusters, | ||||
|                            Error **errp) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int64_t reftable_offset = -1; | ||||
| @ -2734,8 +2738,8 @@ static int rebuild_refcount_structure(BlockDriverState *bs, | ||||
|     } | ||||
| 
 | ||||
|     assert(reftable_length < INT_MAX); | ||||
|     ret = bdrv_pwrite(bs->file, reftable_offset, reftable_length, | ||||
|                       on_disk_reftable, 0); | ||||
|     ret = bdrv_co_pwrite(bs->file, reftable_offset, reftable_length, | ||||
|                          on_disk_reftable, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg_errno(errp, -ret, "ERROR writing reftable"); | ||||
|         goto fail; | ||||
| @ -2745,10 +2749,10 @@ static int rebuild_refcount_structure(BlockDriverState *bs, | ||||
|     reftable_offset_and_clusters.reftable_offset = cpu_to_be64(reftable_offset); | ||||
|     reftable_offset_and_clusters.reftable_clusters = | ||||
|         cpu_to_be32(reftable_clusters); | ||||
|     ret = bdrv_pwrite_sync(bs->file, | ||||
|                            offsetof(QCowHeader, refcount_table_offset), | ||||
|                            sizeof(reftable_offset_and_clusters), | ||||
|                            &reftable_offset_and_clusters, 0); | ||||
|     ret = bdrv_co_pwrite_sync(bs->file, | ||||
|                               offsetof(QCowHeader, refcount_table_offset), | ||||
|                               sizeof(reftable_offset_and_clusters), | ||||
|                               &reftable_offset_and_clusters, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg_errno(errp, -ret, "ERROR setting reftable"); | ||||
|         goto fail; | ||||
| @ -2777,8 +2781,8 @@ fail: | ||||
|  * Returns 0 if no errors are found, the number of errors in case the image is | ||||
|  * detected as corrupted, and -errno when an internal error occurred. | ||||
|  */ | ||||
| int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                           BdrvCheckMode fix) | ||||
| int coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     BdrvCheckResult pre_compare_res; | ||||
| @ -2787,7 +2791,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|     bool rebuild = false; | ||||
|     int ret; | ||||
| 
 | ||||
|     size = bdrv_getlength(bs->file->bs); | ||||
|     size = bdrv_co_getlength(bs->file->bs); | ||||
|     if (size < 0) { | ||||
|         res->check_errors++; | ||||
|         return size; | ||||
| @ -3541,7 +3545,8 @@ done: | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int64_t get_refblock_offset(BlockDriverState *bs, uint64_t offset) | ||||
| static int64_t coroutine_fn get_refblock_offset(BlockDriverState *bs, | ||||
|                                                 uint64_t offset) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     uint32_t index = offset_to_reftable_index(s, offset); | ||||
| @ -3707,7 +3712,8 @@ int64_t coroutine_fn qcow2_get_last_cluster(BlockDriverState *bs, int64_t size) | ||||
|     return -EIO; | ||||
| } | ||||
| 
 | ||||
| int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs) | ||||
| int coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_detect_metadata_preallocation(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
|     int64_t i, end_cluster, cluster_count = 0, threshold; | ||||
|  | ||||
| @ -570,7 +570,7 @@ int qcow2_mark_corrupt(BlockDriverState *bs) | ||||
|  * Marks the image as consistent, i.e., unsets the corrupt bit, and flushes | ||||
|  * before if necessary. | ||||
|  */ | ||||
| int qcow2_mark_consistent(BlockDriverState *bs) | ||||
| static int coroutine_fn qcow2_mark_consistent(BlockDriverState *bs) | ||||
| { | ||||
|     BDRVQcow2State *s = bs->opaque; | ||||
| 
 | ||||
| @ -2225,7 +2225,7 @@ qcow2_co_preadv_encrypted(BlockDriverState *bs, | ||||
|         return -ENOMEM; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|     ret = bdrv_co_pread(s->data_file, host_offset, bytes, buf, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
| @ -2315,7 +2315,7 @@ qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type, | ||||
|     case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: | ||||
|         assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */ | ||||
| 
 | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|         return bdrv_co_preadv_part(bs->backing, offset, bytes, | ||||
|                                    qiov, qiov_offset, 0); | ||||
| 
 | ||||
| @ -2329,7 +2329,7 @@ qcow2_co_preadv_task(BlockDriverState *bs, QCow2SubclusterType subc_type, | ||||
|                                              offset, bytes, qiov, qiov_offset); | ||||
|         } | ||||
| 
 | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|         return bdrv_co_preadv_part(s->data_file, host_offset, | ||||
|                                    bytes, qiov, qiov_offset, 0); | ||||
| 
 | ||||
| @ -2539,7 +2539,7 @@ handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) | ||||
|             return ret; | ||||
|         } | ||||
| 
 | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE); | ||||
|         ret = bdrv_co_pwrite_zeroes(s->data_file, start_offset, nb_bytes, | ||||
|                                     BDRV_REQ_NO_FALLBACK); | ||||
|         if (ret < 0) { | ||||
| @ -2604,7 +2604,7 @@ int qcow2_co_pwritev_task(BlockDriverState *bs, uint64_t host_offset, | ||||
|      * guest data now. | ||||
|      */ | ||||
|     if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) { | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|         trace_qcow2_writev_data(qemu_coroutine_self(), host_offset); | ||||
|         ret = bdrv_co_pwritev_part(s->data_file, host_offset, | ||||
|                                    bytes, qiov, qiov_offset, 0); | ||||
| @ -4678,7 +4678,7 @@ qcow2_co_pwritev_compressed_task(BlockDriverState *bs, | ||||
|         goto fail; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(s->data_file, BLKDBG_WRITE_COMPRESSED); | ||||
|     BLKDBG_CO_EVENT(s->data_file, BLKDBG_WRITE_COMPRESSED); | ||||
|     ret = bdrv_co_pwrite(s->data_file, cluster_offset, out_len, out_buf, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
| @ -4797,7 +4797,7 @@ qcow2_co_preadv_compressed(BlockDriverState *bs, | ||||
| 
 | ||||
|     out_buf = qemu_blockalign(bs, s->cluster_size); | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_COMPRESSED); | ||||
|     ret = bdrv_co_pread(bs->file, coffset, csize, buf, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
| @ -5344,7 +5344,7 @@ qcow2_co_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) | ||||
|         return offset; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_VMSTATE_SAVE); | ||||
|     return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0); | ||||
| } | ||||
| 
 | ||||
| @ -5356,7 +5356,7 @@ qcow2_co_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos) | ||||
|         return offset; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_VMSTATE_LOAD); | ||||
|     return bs->drv->bdrv_co_preadv_part(bs, offset, qiov->size, qiov, 0, 0); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -836,7 +836,6 @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size, | ||||
| 
 | ||||
| int qcow2_mark_dirty(BlockDriverState *bs); | ||||
| int qcow2_mark_corrupt(BlockDriverState *bs); | ||||
| int qcow2_mark_consistent(BlockDriverState *bs); | ||||
| int qcow2_update_header(BlockDriverState *bs); | ||||
| 
 | ||||
| void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, | ||||
| @ -867,7 +866,7 @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t offset, | ||||
| int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size); | ||||
| int64_t coroutine_fn qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, | ||||
|                                              int64_t nb_clusters); | ||||
| int64_t coroutine_fn qcow2_alloc_bytes(BlockDriverState *bs, int size); | ||||
| int64_t coroutine_fn GRAPH_RDLOCK qcow2_alloc_bytes(BlockDriverState *bs, int size); | ||||
| void qcow2_free_clusters(BlockDriverState *bs, | ||||
|                           int64_t offset, int64_t size, | ||||
|                           enum qcow2_discard_type type); | ||||
| @ -879,8 +878,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, | ||||
| 
 | ||||
| int qcow2_flush_caches(BlockDriverState *bs); | ||||
| int qcow2_write_caches(BlockDriverState *bs); | ||||
| int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                           BdrvCheckMode fix); | ||||
| int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                                        BdrvCheckMode fix); | ||||
| 
 | ||||
| void qcow2_process_discards(BlockDriverState *bs, int ret); | ||||
| 
 | ||||
| @ -888,10 +887,10 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, | ||||
|                                  int64_t size); | ||||
| int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, | ||||
|                                   int64_t size, bool data_file); | ||||
| int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                              void **refcount_table, | ||||
|                              int64_t *refcount_table_size, | ||||
|                              int64_t offset, int64_t size); | ||||
| int coroutine_fn qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                                           void **refcount_table, | ||||
|                                           int64_t *refcount_table_size, | ||||
|                                           int64_t offset, int64_t size); | ||||
| 
 | ||||
| int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, | ||||
|                                 BlockDriverAmendStatusCB *status_cb, | ||||
| @ -919,10 +918,9 @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, | ||||
| int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, | ||||
|                                          unsigned int *bytes, | ||||
|                                          uint64_t *host_offset, QCowL2Meta **m); | ||||
| int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, | ||||
|                                                        uint64_t offset, | ||||
|                                                        int compressed_size, | ||||
|                                                        uint64_t *host_offset); | ||||
| int coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, | ||||
|                                       int compressed_size, uint64_t *host_offset); | ||||
| void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry, | ||||
|                                      uint64_t *coffset, int *csize); | ||||
| 
 | ||||
| @ -992,11 +990,12 @@ void *qcow2_cache_is_table_offset(Qcow2Cache *c, uint64_t offset); | ||||
| void qcow2_cache_discard(Qcow2Cache *c, void *table); | ||||
| 
 | ||||
| /* qcow2-bitmap.c functions */ | ||||
| int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                                   void **refcount_table, | ||||
|                                   int64_t *refcount_table_size); | ||||
| bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs, | ||||
|                                            bool *header_updated, Error **errp); | ||||
| int coroutine_fn | ||||
| qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, | ||||
|                               void **refcount_table, | ||||
|                               int64_t *refcount_table_size); | ||||
| bool coroutine_fn GRAPH_RDLOCK | ||||
| qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error **errp); | ||||
| bool qcow2_get_bitmap_info_list(BlockDriverState *bs, | ||||
|                                 Qcow2BitmapInfoList **info_list, Error **errp); | ||||
| int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp); | ||||
|  | ||||
| @ -200,7 +200,8 @@ static void qed_check_for_leaks(QEDCheck *check) | ||||
| /**
 | ||||
|  * Mark an image clean once it passes check or has been repaired | ||||
|  */ | ||||
| static void qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result) | ||||
| static void coroutine_fn GRAPH_RDLOCK | ||||
| qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result) | ||||
| { | ||||
|     /* Skip if there were unfixable corruptions or I/O errors */ | ||||
|     if (result->corruptions > 0 || result->check_errors > 0) { | ||||
| @ -213,7 +214,7 @@ static void qed_check_mark_clean(BDRVQEDState *s, BdrvCheckResult *result) | ||||
|     } | ||||
| 
 | ||||
|     /* Ensure fixes reach storage before clearing check bit */ | ||||
|     bdrv_flush(s->bs); | ||||
|     bdrv_co_flush(s->bs); | ||||
| 
 | ||||
|     s->header.features &= ~QED_F_NEED_CHECK; | ||||
|     qed_write_header_sync(s); | ||||
|  | ||||
| @ -122,7 +122,7 @@ int coroutine_fn qed_read_l1_table_sync(BDRVQEDState *s) | ||||
| int coroutine_fn qed_write_l1_table(BDRVQEDState *s, unsigned int index, | ||||
|                                     unsigned int n) | ||||
| { | ||||
|     BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE); | ||||
|     BLKDBG_CO_EVENT(s->bs->file, BLKDBG_L1_UPDATE); | ||||
|     return qed_write_table(s, s->header.l1_table_offset, | ||||
|                            s->l1_table, index, n, false); | ||||
| } | ||||
| @ -150,7 +150,7 @@ int coroutine_fn qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, | ||||
|     request->l2_table = qed_alloc_l2_cache_entry(&s->l2_cache); | ||||
|     request->l2_table->table = qed_alloc_table(s); | ||||
| 
 | ||||
|     BLKDBG_EVENT(s->bs->file, BLKDBG_L2_LOAD); | ||||
|     BLKDBG_CO_EVENT(s->bs->file, BLKDBG_L2_LOAD); | ||||
|     ret = qed_read_table(s, offset, request->l2_table->table); | ||||
| 
 | ||||
|     if (ret) { | ||||
| @ -183,7 +183,7 @@ int coroutine_fn qed_write_l2_table(BDRVQEDState *s, QEDRequest *request, | ||||
|                                     unsigned int index, unsigned int n, | ||||
|                                     bool flush) | ||||
| { | ||||
|     BLKDBG_EVENT(s->bs->file, BLKDBG_L2_UPDATE); | ||||
|     BLKDBG_CO_EVENT(s->bs->file, BLKDBG_L2_UPDATE); | ||||
|     return qed_write_table(s, request->l2_table->offset, | ||||
|                            request->l2_table->table, index, n, flush); | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								block/qed.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								block/qed.c
									
									
									
									
									
								
							| @ -195,14 +195,15 @@ static bool qed_is_image_size_valid(uint64_t image_size, uint32_t cluster_size, | ||||
|  * | ||||
|  * The string is NUL-terminated. | ||||
|  */ | ||||
| static int qed_read_string(BdrvChild *file, uint64_t offset, size_t n, | ||||
|                            char *buf, size_t buflen) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| qed_read_string(BdrvChild *file, uint64_t offset, | ||||
|                 size_t n, char *buf, size_t buflen) | ||||
| { | ||||
|     int ret; | ||||
|     if (n >= buflen) { | ||||
|         return -EINVAL; | ||||
|     } | ||||
|     ret = bdrv_pread(file, offset, n, buf, 0); | ||||
|     ret = bdrv_co_pread(file, offset, n, buf, 0); | ||||
|     if (ret < 0) { | ||||
|         return ret; | ||||
|     } | ||||
| @ -882,7 +883,7 @@ static int coroutine_fn GRAPH_RDLOCK | ||||
| qed_read_backing_file(BDRVQEDState *s, uint64_t pos, QEMUIOVector *qiov) | ||||
| { | ||||
|     if (s->bs->backing) { | ||||
|         BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|         BLKDBG_CO_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|         return bdrv_co_preadv(s->bs->backing, pos, qiov->size, qiov, 0); | ||||
|     } | ||||
|     qemu_iovec_memset(qiov, 0, 0, qiov->size); | ||||
| @ -917,7 +918,7 @@ qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos, uint64_t len, | ||||
|         goto out; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(s->bs->file, BLKDBG_COW_WRITE); | ||||
|     BLKDBG_CO_EVENT(s->bs->file, BLKDBG_COW_WRITE); | ||||
|     ret = bdrv_co_pwritev(s->bs->file, offset, qiov.size, &qiov, 0); | ||||
|     if (ret < 0) { | ||||
|         goto out; | ||||
| @ -1069,7 +1070,7 @@ static int coroutine_fn GRAPH_RDLOCK qed_aio_write_main(QEDAIOCB *acb) | ||||
| 
 | ||||
|     trace_qed_aio_write_main(s, acb, 0, offset, acb->cur_qiov.size); | ||||
| 
 | ||||
|     BLKDBG_EVENT(s->bs->file, BLKDBG_WRITE_AIO); | ||||
|     BLKDBG_CO_EVENT(s->bs->file, BLKDBG_WRITE_AIO); | ||||
|     return bdrv_co_pwritev(s->bs->file, offset, acb->cur_qiov.size, | ||||
|                            &acb->cur_qiov, 0); | ||||
| } | ||||
| @ -1323,7 +1324,7 @@ qed_aio_read_data(void *opaque, int ret, uint64_t offset, size_t len) | ||||
|     } else if (ret != QED_CLUSTER_FOUND) { | ||||
|         r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov); | ||||
|     } else { | ||||
|         BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|         BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|         r = bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size, | ||||
|                            &acb->cur_qiov, 0); | ||||
|     } | ||||
|  | ||||
| @ -214,7 +214,7 @@ raw_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_AIO); | ||||
|     return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); | ||||
| } | ||||
| 
 | ||||
| @ -268,7 +268,7 @@ raw_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|         goto fail; | ||||
|     } | ||||
| 
 | ||||
|     BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|     BLKDBG_CO_EVENT(bs->file, BLKDBG_WRITE_AIO); | ||||
|     ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); | ||||
| 
 | ||||
| fail: | ||||
|  | ||||
| @ -169,9 +169,10 @@ exit: | ||||
|  * It is assumed that 'buffer' is at least 4096*num_sectors large. | ||||
|  * | ||||
|  * 0 is returned on success, -errno otherwise */ | ||||
| static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log, | ||||
|                                   uint32_t *sectors_written, void *buffer, | ||||
|                                   uint32_t num_sectors) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log, | ||||
|                        uint32_t *sectors_written, void *buffer, | ||||
|                        uint32_t num_sectors) | ||||
| { | ||||
|     int ret = 0; | ||||
|     uint64_t offset; | ||||
| @ -195,8 +196,7 @@ static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log, | ||||
|             /* full */ | ||||
|             break; | ||||
|         } | ||||
|         ret = bdrv_pwrite(bs->file, offset, VHDX_LOG_SECTOR_SIZE, buffer_tmp, | ||||
|                           0); | ||||
|         ret = bdrv_co_pwrite(bs->file, offset, VHDX_LOG_SECTOR_SIZE, buffer_tmp, 0); | ||||
|         if (ret < 0) { | ||||
|             goto exit; | ||||
|         } | ||||
| @ -853,8 +853,9 @@ static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                           void *data, uint32_t length, uint64_t offset) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                void *data, uint32_t length, uint64_t offset) | ||||
| { | ||||
|     int ret = 0; | ||||
|     void *buffer = NULL; | ||||
| @ -924,7 +925,7 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s, | ||||
| 
 | ||||
|     sectors += partial_sectors; | ||||
| 
 | ||||
|     file_length = bdrv_getlength(bs->file->bs); | ||||
|     file_length = bdrv_co_getlength(bs->file->bs); | ||||
|     if (file_length < 0) { | ||||
|         ret = file_length; | ||||
|         goto exit; | ||||
| @ -971,8 +972,8 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s, | ||||
| 
 | ||||
|         if (i == 0 && leading_length) { | ||||
|             /* partial sector at the front of the buffer */ | ||||
|             ret = bdrv_pread(bs->file, file_offset, VHDX_LOG_SECTOR_SIZE, | ||||
|                              merged_sector, 0); | ||||
|             ret = bdrv_co_pread(bs->file, file_offset, VHDX_LOG_SECTOR_SIZE, | ||||
|                                 merged_sector, 0); | ||||
|             if (ret < 0) { | ||||
|                 goto exit; | ||||
|             } | ||||
| @ -981,9 +982,9 @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|             sector_write = merged_sector; | ||||
|         } else if (i == sectors - 1 && trailing_length) { | ||||
|             /* partial sector at the end of the buffer */ | ||||
|             ret = bdrv_pread(bs->file, file_offset + trailing_length, | ||||
|                              VHDX_LOG_SECTOR_SIZE - trailing_length, | ||||
|                              merged_sector + trailing_length, 0); | ||||
|             ret = bdrv_co_pread(bs->file, file_offset + trailing_length, | ||||
|                                 VHDX_LOG_SECTOR_SIZE - trailing_length, | ||||
|                                 merged_sector + trailing_length, 0); | ||||
|             if (ret < 0) { | ||||
|                 goto exit; | ||||
|             } | ||||
| @ -1036,8 +1037,9 @@ exit: | ||||
| } | ||||
| 
 | ||||
| /* Perform a log write, and then immediately flush the entire log */ | ||||
| int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                              void *data, uint32_t length, uint64_t offset) | ||||
| int coroutine_fn | ||||
| vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                          void *data, uint32_t length, uint64_t offset) | ||||
| { | ||||
|     int ret = 0; | ||||
|     VHDXLogSequence logs = { .valid = true, | ||||
| @ -1047,7 +1049,7 @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s, | ||||
| 
 | ||||
|     /* Make sure data written (new and/or changed blocks) is stable
 | ||||
|      * on disk, before creating log entry */ | ||||
|     ret = bdrv_flush(bs); | ||||
|     ret = bdrv_co_flush(bs); | ||||
|     if (ret < 0) { | ||||
|         goto exit; | ||||
|     } | ||||
| @ -1059,7 +1061,7 @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|     logs.log = s->log; | ||||
| 
 | ||||
|     /* Make sure log is stable on disk */ | ||||
|     ret = bdrv_flush(bs); | ||||
|     ret = bdrv_co_flush(bs); | ||||
|     if (ret < 0) { | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
							
								
								
									
										73
									
								
								block/vhdx.c
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								block/vhdx.c
									
									
									
									
									
								
							| @ -1250,12 +1250,13 @@ exit: | ||||
|  * | ||||
|  * Returns the file offset start of the new payload block | ||||
|  */ | ||||
| static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                                uint64_t *new_offset, bool *need_zero) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                     uint64_t *new_offset, bool *need_zero) | ||||
| { | ||||
|     int64_t current_len; | ||||
| 
 | ||||
|     current_len = bdrv_getlength(bs->file->bs); | ||||
|     current_len = bdrv_co_getlength(bs->file->bs); | ||||
|     if (current_len < 0) { | ||||
|         return current_len; | ||||
|     } | ||||
| @ -1271,16 +1272,16 @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|     if (*need_zero) { | ||||
|         int ret; | ||||
| 
 | ||||
|         ret = bdrv_truncate(bs->file, *new_offset + s->block_size, false, | ||||
|                             PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, NULL); | ||||
|         ret = bdrv_co_truncate(bs->file, *new_offset + s->block_size, false, | ||||
|                                PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, NULL); | ||||
|         if (ret != -ENOTSUP) { | ||||
|             *need_zero = false; | ||||
|             return ret; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return bdrv_truncate(bs->file, *new_offset + s->block_size, false, | ||||
|                          PREALLOC_MODE_OFF, 0, NULL); | ||||
|     return bdrv_co_truncate(bs->file, *new_offset + s->block_size, false, | ||||
|                             PREALLOC_MODE_OFF, 0, NULL); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -1572,12 +1573,10 @@ exit: | ||||
|  * The first 64KB of the Metadata section is reserved for the metadata | ||||
|  * header and entries; beyond that, the metadata items themselves reside. | ||||
|  */ | ||||
| static int vhdx_create_new_metadata(BlockBackend *blk, | ||||
|                                     uint64_t image_size, | ||||
|                                     uint32_t block_size, | ||||
|                                     uint32_t sector_size, | ||||
|                                     uint64_t metadata_offset, | ||||
|                                     VHDXImageType type) | ||||
| static int coroutine_fn | ||||
| vhdx_create_new_metadata(BlockBackend *blk, uint64_t image_size, | ||||
|                          uint32_t block_size, uint32_t sector_size, | ||||
|                          uint64_t metadata_offset, VHDXImageType type) | ||||
| { | ||||
|     int ret = 0; | ||||
|     uint32_t offset = 0; | ||||
| @ -1668,13 +1667,13 @@ static int vhdx_create_new_metadata(BlockBackend *blk, | ||||
|                                    VHDX_META_FLAGS_IS_VIRTUAL_DISK; | ||||
|     vhdx_metadata_entry_le_export(&md_table_entry[4]); | ||||
| 
 | ||||
|     ret = blk_pwrite(blk, metadata_offset, VHDX_HEADER_BLOCK_SIZE, buffer, 0); | ||||
|     ret = blk_co_pwrite(blk, metadata_offset, VHDX_HEADER_BLOCK_SIZE, buffer, 0); | ||||
|     if (ret < 0) { | ||||
|         goto exit; | ||||
|     } | ||||
| 
 | ||||
|     ret = blk_pwrite(blk, metadata_offset + (64 * KiB), | ||||
|                      VHDX_METADATA_ENTRY_BUFFER_SIZE, entry_buffer, 0); | ||||
|     ret = blk_co_pwrite(blk, metadata_offset + (64 * KiB), | ||||
|                         VHDX_METADATA_ENTRY_BUFFER_SIZE, entry_buffer, 0); | ||||
|     if (ret < 0) { | ||||
|         goto exit; | ||||
|     } | ||||
| @ -1694,10 +1693,11 @@ exit: | ||||
|  *  Fixed images: default state of the BAT is fully populated, with | ||||
|  *                file offsets and state PAYLOAD_BLOCK_FULLY_PRESENT. | ||||
|  */ | ||||
| static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, | ||||
|                            uint64_t image_size, VHDXImageType type, | ||||
|                            bool use_zero_blocks, uint64_t file_offset, | ||||
|                            uint32_t length, Error **errp) | ||||
| static int coroutine_fn | ||||
| vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, | ||||
|                 uint64_t image_size, VHDXImageType type, | ||||
|                 bool use_zero_blocks, uint64_t file_offset, | ||||
|                 uint32_t length, Error **errp) | ||||
| { | ||||
|     int ret = 0; | ||||
|     uint64_t data_file_offset; | ||||
| @ -1718,14 +1718,14 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, | ||||
|     if (type == VHDX_TYPE_DYNAMIC) { | ||||
|         /* All zeroes, so we can just extend the file - the end of the BAT
 | ||||
|          * is the furthest thing we have written yet */ | ||||
|         ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF, | ||||
|                            0, errp); | ||||
|         ret = blk_co_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF, | ||||
|                               0, errp); | ||||
|         if (ret < 0) { | ||||
|             goto exit; | ||||
|         } | ||||
|     } else if (type == VHDX_TYPE_FIXED) { | ||||
|         ret = blk_truncate(blk, data_file_offset + image_size, false, | ||||
|                            PREALLOC_MODE_OFF, 0, errp); | ||||
|         ret = blk_co_truncate(blk, data_file_offset + image_size, false, | ||||
|                               PREALLOC_MODE_OFF, 0, errp); | ||||
|         if (ret < 0) { | ||||
|             goto exit; | ||||
|         } | ||||
| @ -1759,7 +1759,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s, | ||||
|             s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]); | ||||
|             sector_num += s->sectors_per_block; | ||||
|         } | ||||
|         ret = blk_pwrite(blk, file_offset, length, s->bat, 0); | ||||
|         ret = blk_co_pwrite(blk, file_offset, length, s->bat, 0); | ||||
|         if (ret < 0) { | ||||
|             error_setg_errno(errp, -ret, "Failed to write the BAT"); | ||||
|             goto exit; | ||||
| @ -1780,15 +1780,12 @@ exit: | ||||
|  * to create the BAT itself, we will also cause the BAT to be | ||||
|  * created. | ||||
|  */ | ||||
| static int vhdx_create_new_region_table(BlockBackend *blk, | ||||
|                                         uint64_t image_size, | ||||
|                                         uint32_t block_size, | ||||
|                                         uint32_t sector_size, | ||||
|                                         uint32_t log_size, | ||||
|                                         bool use_zero_blocks, | ||||
|                                         VHDXImageType type, | ||||
|                                         uint64_t *metadata_offset, | ||||
|                                         Error **errp) | ||||
| static int coroutine_fn | ||||
| vhdx_create_new_region_table(BlockBackend *blk, uint64_t image_size, | ||||
|                              uint32_t block_size, uint32_t sector_size, | ||||
|                              uint32_t log_size, bool use_zero_blocks, | ||||
|                              VHDXImageType type, uint64_t *metadata_offset, | ||||
|                              Error **errp) | ||||
| { | ||||
|     int ret = 0; | ||||
|     uint32_t offset = 0; | ||||
| @ -1863,15 +1860,15 @@ static int vhdx_create_new_region_table(BlockBackend *blk, | ||||
|     } | ||||
| 
 | ||||
|     /* Now write out the region headers to disk */ | ||||
|     ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, VHDX_HEADER_BLOCK_SIZE, | ||||
|                      buffer, 0); | ||||
|     ret = blk_co_pwrite(blk, VHDX_REGION_TABLE_OFFSET, VHDX_HEADER_BLOCK_SIZE, | ||||
|                         buffer, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg_errno(errp, -ret, "Failed to write first region table"); | ||||
|         goto exit; | ||||
|     } | ||||
| 
 | ||||
|     ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, VHDX_HEADER_BLOCK_SIZE, | ||||
|                      buffer, 0); | ||||
|     ret = blk_co_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, VHDX_HEADER_BLOCK_SIZE, | ||||
|                         buffer, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg_errno(errp, -ret, "Failed to write second region table"); | ||||
|         goto exit; | ||||
|  | ||||
| @ -413,8 +413,9 @@ bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset); | ||||
| int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed, | ||||
|                    Error **errp); | ||||
| 
 | ||||
| int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                              void *data, uint32_t length, uint64_t offset); | ||||
| int coroutine_fn GRAPH_RDLOCK | ||||
| vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s, | ||||
|                          void *data, uint32_t length, uint64_t offset); | ||||
| 
 | ||||
| static inline void leguid_to_cpus(MSGUID *guid) | ||||
| { | ||||
|  | ||||
							
								
								
									
										55
									
								
								block/vmdk.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								block/vmdk.c
									
									
									
									
									
								
							| @ -339,7 +339,8 @@ out: | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| vmdk_write_cid(BlockDriverState *bs, uint32_t cid) | ||||
| { | ||||
|     char *desc, *tmp_desc; | ||||
|     char *p_name, *tmp_str; | ||||
| @ -348,7 +349,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) | ||||
| 
 | ||||
|     desc = g_malloc0(DESC_SIZE); | ||||
|     tmp_desc = g_malloc0(DESC_SIZE); | ||||
|     ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); | ||||
|     ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); | ||||
|     if (ret < 0) { | ||||
|         goto out; | ||||
|     } | ||||
| @ -368,7 +369,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) | ||||
|         pstrcat(desc, DESC_SIZE, tmp_desc); | ||||
|     } | ||||
| 
 | ||||
|     ret = bdrv_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0); | ||||
|     ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0); | ||||
| 
 | ||||
| out: | ||||
|     g_free(desc); | ||||
| @ -1437,7 +1438,7 @@ get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, | ||||
|     if (skip_start_bytes > 0) { | ||||
|         if (copy_from_backing) { | ||||
|             /* qcow2 emits this on bs->file instead of bs->backing */ | ||||
|             BLKDBG_EVENT(extent->file, BLKDBG_COW_READ); | ||||
|             BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_READ); | ||||
|             ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes, | ||||
|                                 whole_grain, 0); | ||||
|             if (ret < 0) { | ||||
| @ -1445,7 +1446,7 @@ get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, | ||||
|                 goto exit; | ||||
|             } | ||||
|         } | ||||
|         BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE); | ||||
|         BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_WRITE); | ||||
|         ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes, | ||||
|                              whole_grain, 0); | ||||
|         if (ret < 0) { | ||||
| @ -1457,7 +1458,7 @@ get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, | ||||
|     if (skip_end_bytes < cluster_bytes) { | ||||
|         if (copy_from_backing) { | ||||
|             /* qcow2 emits this on bs->file instead of bs->backing */ | ||||
|             BLKDBG_EVENT(extent->file, BLKDBG_COW_READ); | ||||
|             BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_READ); | ||||
|             ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes, | ||||
|                                 cluster_bytes - skip_end_bytes, | ||||
|                                 whole_grain + skip_end_bytes, 0); | ||||
| @ -1466,7 +1467,7 @@ get_whole_cluster(BlockDriverState *bs, VmdkExtent *extent, | ||||
|                 goto exit; | ||||
|             } | ||||
|         } | ||||
|         BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE); | ||||
|         BLKDBG_CO_EVENT(extent->file, BLKDBG_COW_WRITE); | ||||
|         ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes, | ||||
|                              cluster_bytes - skip_end_bytes, | ||||
|                              whole_grain + skip_end_bytes, 0); | ||||
| @ -1487,7 +1488,7 @@ vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data, uint32_t offset) | ||||
| { | ||||
|     offset = cpu_to_le32(offset); | ||||
|     /* update L2 table */ | ||||
|     BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE); | ||||
|     BLKDBG_CO_EVENT(extent->file, BLKDBG_L2_UPDATE); | ||||
|     if (bdrv_co_pwrite(extent->file, | ||||
|                        ((int64_t)m_data->l2_offset * 512) | ||||
|                            + (m_data->l2_index * sizeof(offset)), | ||||
| @ -1617,7 +1618,7 @@ get_cluster_offset(BlockDriverState *bs, VmdkExtent *extent, | ||||
|         } | ||||
|     } | ||||
|     l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes); | ||||
|     BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD); | ||||
|     BLKDBG_CO_EVENT(extent->file, BLKDBG_L2_LOAD); | ||||
|     if (bdrv_co_pread(extent->file, | ||||
|                 (int64_t)l2_offset * 512, | ||||
|                 l2_size_bytes, | ||||
| @ -1828,12 +1829,12 @@ vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, | ||||
|         n_bytes = buf_len + sizeof(VmdkGrainMarker); | ||||
|         qemu_iovec_init_buf(&local_qiov, data, n_bytes); | ||||
| 
 | ||||
|         BLKDBG_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED); | ||||
|         BLKDBG_CO_EVENT(extent->file, BLKDBG_WRITE_COMPRESSED); | ||||
|     } else { | ||||
|         qemu_iovec_init(&local_qiov, qiov->niov); | ||||
|         qemu_iovec_concat(&local_qiov, qiov, qiov_offset, n_bytes); | ||||
| 
 | ||||
|         BLKDBG_EVENT(extent->file, BLKDBG_WRITE_AIO); | ||||
|         BLKDBG_CO_EVENT(extent->file, BLKDBG_WRITE_AIO); | ||||
|     } | ||||
| 
 | ||||
|     write_offset = cluster_offset + offset_in_cluster; | ||||
| @ -1875,7 +1876,7 @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, | ||||
| 
 | ||||
| 
 | ||||
|     if (!extent->compressed) { | ||||
|         BLKDBG_EVENT(extent->file, BLKDBG_READ_AIO); | ||||
|         BLKDBG_CO_EVENT(extent->file, BLKDBG_READ_AIO); | ||||
|         ret = bdrv_co_preadv(extent->file, | ||||
|                              cluster_offset + offset_in_cluster, bytes, | ||||
|                              qiov, 0); | ||||
| @ -1889,7 +1890,7 @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, | ||||
|     buf_bytes = cluster_bytes * 2; | ||||
|     cluster_buf = g_malloc(buf_bytes); | ||||
|     uncomp_buf = g_malloc(cluster_bytes); | ||||
|     BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED); | ||||
|     BLKDBG_CO_EVENT(extent->file, BLKDBG_READ_COMPRESSED); | ||||
|     ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, | ||||
|                         0); | ||||
|     if (ret < 0) { | ||||
| @ -1967,7 +1968,7 @@ vmdk_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|                 qemu_iovec_concat(&local_qiov, qiov, bytes_done, n_bytes); | ||||
| 
 | ||||
|                 /* qcow2 emits this on bs->file instead of bs->backing */ | ||||
|                 BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|                 BLKDBG_CO_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); | ||||
|                 ret = bdrv_co_preadv(bs->backing, offset, n_bytes, | ||||
|                                      &local_qiov, 0); | ||||
|                 if (ret < 0) { | ||||
| @ -2131,7 +2132,7 @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|         int64_t length; | ||||
| 
 | ||||
|         for (i = 0; i < s->num_extents; i++) { | ||||
|             length = bdrv_getlength(s->extents[i].file->bs); | ||||
|             length = bdrv_co_getlength(s->extents[i].file->bs); | ||||
|             if (length < 0) { | ||||
|                 return length; | ||||
|             } | ||||
| @ -2165,7 +2166,7 @@ vmdk_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes, | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int GRAPH_UNLOCKED | ||||
| static int coroutine_fn GRAPH_UNLOCKED | ||||
| vmdk_init_extent(BlockBackend *blk, int64_t filesize, bool flat, bool compress, | ||||
|                  bool zeroed_grain, Error **errp) | ||||
| { | ||||
| @ -2176,7 +2177,7 @@ vmdk_init_extent(BlockBackend *blk, int64_t filesize, bool flat, bool compress, | ||||
|     int gd_buf_size; | ||||
| 
 | ||||
|     if (flat) { | ||||
|         ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp); | ||||
|         ret = blk_co_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp); | ||||
|         goto exit; | ||||
|     } | ||||
|     magic = cpu_to_be32(VMDK4_MAGIC); | ||||
| @ -2228,19 +2229,19 @@ vmdk_init_extent(BlockBackend *blk, int64_t filesize, bool flat, bool compress, | ||||
|     header.check_bytes[3] = 0xa; | ||||
| 
 | ||||
|     /* write all the data */ | ||||
|     ret = blk_pwrite(blk, 0, sizeof(magic), &magic, 0); | ||||
|     ret = blk_co_pwrite(blk, 0, sizeof(magic), &magic, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg(errp, QERR_IO_ERROR); | ||||
|         goto exit; | ||||
|     } | ||||
|     ret = blk_pwrite(blk, sizeof(magic), sizeof(header), &header, 0); | ||||
|     ret = blk_co_pwrite(blk, sizeof(magic), sizeof(header), &header, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg(errp, QERR_IO_ERROR); | ||||
|         goto exit; | ||||
|     } | ||||
| 
 | ||||
|     ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false, | ||||
|                        PREALLOC_MODE_OFF, 0, errp); | ||||
|     ret = blk_co_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false, | ||||
|                           PREALLOC_MODE_OFF, 0, errp); | ||||
|     if (ret < 0) { | ||||
|         goto exit; | ||||
|     } | ||||
| @ -2252,8 +2253,8 @@ vmdk_init_extent(BlockBackend *blk, int64_t filesize, bool flat, bool compress, | ||||
|          i < gt_count; i++, tmp += gt_size) { | ||||
|         gd_buf[i] = cpu_to_le32(tmp); | ||||
|     } | ||||
|     ret = blk_pwrite(blk, le64_to_cpu(header.rgd_offset) * BDRV_SECTOR_SIZE, | ||||
|                      gd_buf_size, gd_buf, 0); | ||||
|     ret = blk_co_pwrite(blk, le64_to_cpu(header.rgd_offset) * BDRV_SECTOR_SIZE, | ||||
|                         gd_buf_size, gd_buf, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg(errp, QERR_IO_ERROR); | ||||
|         goto exit; | ||||
| @ -2264,8 +2265,8 @@ vmdk_init_extent(BlockBackend *blk, int64_t filesize, bool flat, bool compress, | ||||
|          i < gt_count; i++, tmp += gt_size) { | ||||
|         gd_buf[i] = cpu_to_le32(tmp); | ||||
|     } | ||||
|     ret = blk_pwrite(blk, le64_to_cpu(header.gd_offset) * BDRV_SECTOR_SIZE, | ||||
|                      gd_buf_size, gd_buf, 0); | ||||
|     ret = blk_co_pwrite(blk, le64_to_cpu(header.gd_offset) * BDRV_SECTOR_SIZE, | ||||
|                         gd_buf_size, gd_buf, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg(errp, QERR_IO_ERROR); | ||||
|     } | ||||
| @ -2908,7 +2909,7 @@ vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix) | ||||
|     BDRVVmdkState *s = bs->opaque; | ||||
|     VmdkExtent *extent = NULL; | ||||
|     int64_t sector_num = 0; | ||||
|     int64_t total_sectors = bdrv_nb_sectors(bs); | ||||
|     int64_t total_sectors = bdrv_co_nb_sectors(bs); | ||||
|     int ret; | ||||
|     uint64_t cluster_offset; | ||||
| 
 | ||||
| @ -2938,7 +2939,7 @@ vmdk_co_check(BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix) | ||||
|             break; | ||||
|         } | ||||
|         if (ret == VMDK_OK) { | ||||
|             int64_t extent_len = bdrv_getlength(extent->file->bs); | ||||
|             int64_t extent_len = bdrv_co_getlength(extent->file->bs); | ||||
|             if (extent_len < 0) { | ||||
|                 fprintf(stderr, | ||||
|                         "ERROR: could not get extent file length for sector %" | ||||
|  | ||||
							
								
								
									
										52
									
								
								block/vpc.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								block/vpc.c
									
									
									
									
									
								
							| @ -486,8 +486,8 @@ static int vpc_reopen_prepare(BDRVReopenState *state, | ||||
|  * operation (the block bitmaps is updated then), 0 otherwise. | ||||
|  * If write is true then err must not be NULL. | ||||
|  */ | ||||
| static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, | ||||
|                                        bool write, int *err) | ||||
| static int64_t coroutine_fn GRAPH_RDLOCK | ||||
| get_image_offset(BlockDriverState *bs, uint64_t offset, bool write, int *err) | ||||
| { | ||||
|     BDRVVPCState *s = bs->opaque; | ||||
|     uint64_t bitmap_offset, block_offset; | ||||
| @ -515,8 +515,7 @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, | ||||
| 
 | ||||
|         s->last_bitmap_offset = bitmap_offset; | ||||
|         memset(bitmap, 0xff, s->bitmap_size); | ||||
|         r = bdrv_pwrite_sync(bs->file, bitmap_offset, s->bitmap_size, bitmap, | ||||
|                              0); | ||||
|         r = bdrv_co_pwrite_sync(bs->file, bitmap_offset, s->bitmap_size, bitmap, 0); | ||||
|         if (r < 0) { | ||||
|             *err = r; | ||||
|             return -2; | ||||
| @ -532,13 +531,13 @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset, | ||||
|  * | ||||
|  * Returns 0 on success and < 0 on error | ||||
|  */ | ||||
| static int rewrite_footer(BlockDriverState *bs) | ||||
| static int coroutine_fn GRAPH_RDLOCK rewrite_footer(BlockDriverState *bs) | ||||
| { | ||||
|     int ret; | ||||
|     BDRVVPCState *s = bs->opaque; | ||||
|     int64_t offset = s->free_data_block_offset; | ||||
| 
 | ||||
|     ret = bdrv_pwrite_sync(bs->file, offset, sizeof(s->footer), &s->footer, 0); | ||||
|     ret = bdrv_co_pwrite_sync(bs->file, offset, sizeof(s->footer), &s->footer, 0); | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
| 
 | ||||
| @ -552,7 +551,8 @@ static int rewrite_footer(BlockDriverState *bs) | ||||
|  * | ||||
|  * Returns the sectors' offset in the image file on success and < 0 on error | ||||
|  */ | ||||
| static int64_t alloc_block(BlockDriverState *bs, int64_t offset) | ||||
| static int64_t coroutine_fn GRAPH_RDLOCK | ||||
| alloc_block(BlockDriverState *bs, int64_t offset) | ||||
| { | ||||
|     BDRVVPCState *s = bs->opaque; | ||||
|     int64_t bat_offset; | ||||
| @ -572,8 +572,8 @@ static int64_t alloc_block(BlockDriverState *bs, int64_t offset) | ||||
| 
 | ||||
|     /* Initialize the block's bitmap */ | ||||
|     memset(bitmap, 0xff, s->bitmap_size); | ||||
|     ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, | ||||
|                            s->bitmap_size, bitmap, 0); | ||||
|     ret = bdrv_co_pwrite_sync(bs->file, s->free_data_block_offset, | ||||
|                               s->bitmap_size, bitmap, 0); | ||||
|     if (ret < 0) { | ||||
|         return ret; | ||||
|     } | ||||
| @ -587,7 +587,7 @@ static int64_t alloc_block(BlockDriverState *bs, int64_t offset) | ||||
|     /* Write BAT entry to disk */ | ||||
|     bat_offset = s->bat_offset + (4 * index); | ||||
|     bat_value = cpu_to_be32(s->pagetable[index]); | ||||
|     ret = bdrv_pwrite_sync(bs->file, bat_offset, 4, &bat_value, 0); | ||||
|     ret = bdrv_co_pwrite_sync(bs->file, bat_offset, 4, &bat_value, 0); | ||||
|     if (ret < 0) | ||||
|         goto fail; | ||||
| 
 | ||||
| @ -718,11 +718,11 @@ fail: | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int coroutine_fn vpc_co_block_status(BlockDriverState *bs, | ||||
|                                             bool want_zero, | ||||
|                                             int64_t offset, int64_t bytes, | ||||
|                                             int64_t *pnum, int64_t *map, | ||||
|                                             BlockDriverState **file) | ||||
| static int coroutine_fn GRAPH_RDLOCK | ||||
| vpc_co_block_status(BlockDriverState *bs, bool want_zero, | ||||
|                     int64_t offset, int64_t bytes, | ||||
|                     int64_t *pnum, int64_t *map, | ||||
|                     BlockDriverState **file) | ||||
| { | ||||
|     BDRVVPCState *s = bs->opaque; | ||||
|     int64_t image_offset; | ||||
| @ -820,8 +820,8 @@ static int calculate_geometry(int64_t total_sectors, uint16_t *cyls, | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|                                int64_t total_sectors) | ||||
| static int coroutine_fn create_dynamic_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|                                             int64_t total_sectors) | ||||
| { | ||||
|     VHDDynDiskHeader dyndisk_header; | ||||
|     uint8_t bat_sector[512]; | ||||
| @ -834,13 +834,13 @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|     block_size = 0x200000; | ||||
|     num_bat_entries = DIV_ROUND_UP(total_sectors, block_size / 512); | ||||
| 
 | ||||
|     ret = blk_pwrite(blk, offset, sizeof(*footer), footer, 0); | ||||
|     ret = blk_co_pwrite(blk, offset, sizeof(*footer), footer, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
|     } | ||||
| 
 | ||||
|     offset = 1536 + ((num_bat_entries * 4 + 511) & ~511); | ||||
|     ret = blk_pwrite(blk, offset, sizeof(*footer), footer, 0); | ||||
|     ret = blk_co_pwrite(blk, offset, sizeof(*footer), footer, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
|     } | ||||
| @ -850,7 +850,7 @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer, | ||||
| 
 | ||||
|     memset(bat_sector, 0xFF, 512); | ||||
|     for (i = 0; i < DIV_ROUND_UP(num_bat_entries * 4, 512); i++) { | ||||
|         ret = blk_pwrite(blk, offset, 512, bat_sector, 0); | ||||
|         ret = blk_co_pwrite(blk, offset, 512, bat_sector, 0); | ||||
|         if (ret < 0) { | ||||
|             goto fail; | ||||
|         } | ||||
| @ -878,7 +878,7 @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|     /* Write the header */ | ||||
|     offset = 512; | ||||
| 
 | ||||
|     ret = blk_pwrite(blk, offset, sizeof(dyndisk_header), &dyndisk_header, 0); | ||||
|     ret = blk_co_pwrite(blk, offset, sizeof(dyndisk_header), &dyndisk_header, 0); | ||||
|     if (ret < 0) { | ||||
|         goto fail; | ||||
|     } | ||||
| @ -888,21 +888,21 @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int create_fixed_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|                              int64_t total_size, Error **errp) | ||||
| static int coroutine_fn create_fixed_disk(BlockBackend *blk, VHDFooter *footer, | ||||
|                                           int64_t total_size, Error **errp) | ||||
| { | ||||
|     int ret; | ||||
| 
 | ||||
|     /* Add footer to total size */ | ||||
|     total_size += sizeof(*footer); | ||||
| 
 | ||||
|     ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp); | ||||
|     ret = blk_co_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp); | ||||
|     if (ret < 0) { | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     ret = blk_pwrite(blk, total_size - sizeof(*footer), sizeof(*footer), | ||||
|                      footer, 0); | ||||
|     ret = blk_co_pwrite(blk, total_size - sizeof(*footer), sizeof(*footer), | ||||
|                         footer, 0); | ||||
|     if (ret < 0) { | ||||
|         error_setg_errno(errp, -ret, "Unable to write VHD header"); | ||||
|         return ret; | ||||
|  | ||||
							
								
								
									
										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; | ||||
|  | ||||
| @ -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; | ||||
|             } | ||||
|  | ||||
| @ -224,6 +224,13 @@ bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event); | ||||
| void co_wrapper_mixed_bdrv_rdlock | ||||
| bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event); | ||||
| 
 | ||||
| #define BLKDBG_CO_EVENT(child, evt) \ | ||||
|     do { \ | ||||
|         if (child) { \ | ||||
|             bdrv_co_debug_event(child->bs, evt); \ | ||||
|         } \ | ||||
|     } while (0) | ||||
| 
 | ||||
| #define BLKDBG_EVENT(child, evt) \ | ||||
|     do { \ | ||||
|         if (child) { \ | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
							
								
								
									
										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); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Richard Henderson
						Richard Henderson