The bdrv_refresh_limits() function and driver implementations are called with the graph lock held. The implementation for the 'compress' filter calls bdrv_get_info(), which is a generated coroutine wrapper and thus polls. This can lead to a deadlock when issuing a blockdev-snapshot QMP command, when bdrv_refresh_limits() is called in bdrv_append() while the graph lock is held exclusively. This deadlock was introduced with commit 5661a00d40 ("block: Call transaction callbacks with lock held").
As a solution, this reverts commit 3d47eb0a2a ("block: Convert bdrv_get_info() to co_wrapper_mixed"). To do this, it is necessary to have callers of bdrv_get_info() take the graph lock themselves. None of the driver implementations rely on being run in coroutine context and none of the callers rely on the function being a coroutine. All callers except one either already hold the graph lock or can claim the graph lock via bdrv_graph_rdlock_main_loop(). As part of this, bdrv_get_default_bitmap_granularity() is annotated with GRAPH_RDLOCK and its callers adapted where necessary. The single exception is the caller nvme_ns_init_format(), which can run as a callback in an IO thread, but can also be reached via the QOM realize handler nvme_ns_realize(). For this caller, a bdrv_get_info_unlocked() coroutine wrapper is introduced that must be called with the graph unlocked. Signed-off-by: Fiona Ebner <f.eb...@proxmox.com> --- The test added by the following patch exhibits the issue mentioned above. Telling from a quick search, iothread support for nvme devices has not been merged [0]. So currently, doing the following in nvme_ns_init_format() might also be an option to avoid the need for the wrapper: if (qemu_in_coroutine()) { bdrv_graph_co_rdlock(); } else { bdrv_graph_rdlock_main_loop() } But that doesn't seem future-proof. [0]: https://lore.kernel.org/qemu-devel/20220827091258.3589230-1-fanjinhao...@ict.ac.cn/ block.c | 14 ++++++++++---- block/blkio.c | 5 ++--- block/crypto.c | 8 ++++---- block/file-posix.c | 7 +++---- block/io.c | 4 ++-- block/iscsi.c | 7 +++---- block/mirror.c | 5 +++-- block/monitor/bitmap-qmp-cmds.c | 2 ++ block/qcow.c | 5 ++--- block/qcow2.c | 5 ++--- block/qed.c | 5 ++--- block/raw-format.c | 7 +++---- block/rbd.c | 5 ++--- block/vdi.c | 11 ++++++----- block/vhdx.c | 5 ++--- block/vmdk.c | 5 ++--- block/vpc.c | 5 ++--- hw/nvme/ns.c | 2 +- include/block/block-io.h | 9 +++++---- include/block/block_int-common.h | 4 ++-- include/block/dirty-bitmap.h | 2 +- qemu-img.c | 6 ++++++ 22 files changed, 67 insertions(+), 61 deletions(-) diff --git a/block.c b/block.c index f222e1a50a..c23550ae42 100644 --- a/block.c +++ b/block.c @@ -6570,7 +6570,13 @@ void bdrv_get_backing_filename(BlockDriverState *bs, pstrcpy(filename, filename_size, bs->backing_file); } -int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +int coroutine_fn GRAPH_RDLOCK +bdrv_co_get_info_unlocked(BlockDriverState *bs, BlockDriverInfo *bdi) +{ + return bdrv_get_info(bs, bdi); +} + +int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { int ret; BlockDriver *drv = bs->drv; @@ -6581,15 +6587,15 @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) if (!drv) { return -ENOMEDIUM; } - if (!drv->bdrv_co_get_info) { + if (!drv->bdrv_get_info) { BlockDriverState *filtered = bdrv_filter_bs(bs); if (filtered) { - return bdrv_co_get_info(filtered, bdi); + return bdrv_get_info(filtered, bdi); } return -ENOTSUP; } memset(bdi, 0, sizeof(*bdi)); - ret = drv->bdrv_co_get_info(bs, bdi); + ret = drv->bdrv_get_info(bs, bdi); if (bdi->subcluster_size == 0) { /* * If the driver left this unset, subclusters are not supported. diff --git a/block/blkio.c b/block/blkio.c index 4142673984..4b04d530e2 100644 --- a/block/blkio.c +++ b/block/blkio.c @@ -972,8 +972,7 @@ static int coroutine_fn blkio_truncate(BlockDriverState *bs, int64_t offset, return 0; } -static int coroutine_fn -blkio_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int blkio_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { return 0; } @@ -1094,7 +1093,7 @@ static void blkio_refresh_limits(BlockDriverState *bs, Error **errp) .bdrv_close = blkio_close, \ .bdrv_co_getlength = blkio_co_getlength, \ .bdrv_co_truncate = blkio_truncate, \ - .bdrv_co_get_info = blkio_co_get_info, \ + .bdrv_get_info = blkio_get_info, \ .bdrv_attach_aio_context = blkio_attach_aio_context, \ .bdrv_detach_aio_context = blkio_detach_aio_context, \ .bdrv_co_pdiscard = blkio_co_pdiscard, \ diff --git a/block/crypto.c b/block/crypto.c index d4226cc68a..3c19848db0 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -862,13 +862,13 @@ fail: return ret; } -static int coroutine_fn GRAPH_RDLOCK -block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi) +static int GRAPH_RDLOCK +block_crypto_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi) { BlockDriverInfo subbdi; int ret; - ret = bdrv_co_get_info(bs->file->bs, &subbdi); + ret = bdrv_get_info(bs->file->bs, &subbdi); if (ret != 0) { return ret; } @@ -1080,7 +1080,7 @@ static BlockDriver bdrv_crypto_luks = { .bdrv_co_pwritev = block_crypto_co_pwritev, .bdrv_co_getlength = block_crypto_co_getlength, .bdrv_measure = block_crypto_measure, - .bdrv_co_get_info = block_crypto_co_get_info_luks, + .bdrv_get_info = block_crypto_get_info_luks, .bdrv_get_specific_info = block_crypto_get_specific_info_luks, .bdrv_amend_options = block_crypto_amend_options_luks, .bdrv_co_amend = block_crypto_co_amend_luks, diff --git a/block/file-posix.c b/block/file-posix.c index 9b5f08ccb2..e14d8c9213 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -3743,8 +3743,7 @@ static int coroutine_fn raw_co_pwrite_zeroes( return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false); } -static int coroutine_fn -raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { return 0; } @@ -4003,7 +4002,7 @@ BlockDriver bdrv_file = { .bdrv_co_truncate = raw_co_truncate, .bdrv_co_getlength = raw_co_getlength, - .bdrv_co_get_info = raw_co_get_info, + .bdrv_get_info = raw_get_info, .bdrv_get_specific_info = raw_get_specific_info, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, .bdrv_get_specific_stats = raw_get_specific_stats, @@ -4461,7 +4460,7 @@ static BlockDriver bdrv_host_device = { .bdrv_co_truncate = raw_co_truncate, .bdrv_co_getlength = raw_co_getlength, - .bdrv_co_get_info = raw_co_get_info, + .bdrv_get_info = raw_get_info, .bdrv_get_specific_info = raw_get_specific_info, .bdrv_co_get_allocated_file_size = raw_co_get_allocated_file_size, .bdrv_get_specific_stats = hdev_get_specific_stats, diff --git a/block/io.c b/block/io.c index 4fd7768f9c..43cd7b7507 100644 --- a/block/io.c +++ b/block/io.c @@ -743,7 +743,7 @@ bdrv_round_to_subclusters(BlockDriverState *bs, int64_t offset, int64_t bytes, { BlockDriverInfo bdi; IO_CODE(); - if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.subcluster_size == 0) { + if (bdrv_get_info(bs, &bdi) < 0 || bdi.subcluster_size == 0) { *align_offset = offset; *align_bytes = bytes; } else { @@ -758,7 +758,7 @@ static int coroutine_fn GRAPH_RDLOCK bdrv_get_cluster_size(BlockDriverState *bs) BlockDriverInfo bdi; int ret; - ret = bdrv_co_get_info(bs, &bdi); + ret = bdrv_get_info(bs, &bdi); if (ret < 0 || bdi.cluster_size == 0) { return bs->bl.request_alignment; } else { diff --git a/block/iscsi.c b/block/iscsi.c index 15b96ee880..4b000df117 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2177,8 +2177,7 @@ static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset, return 0; } -static int coroutine_fn -iscsi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { IscsiLun *iscsilun = bs->opaque; bdi->cluster_size = iscsilun->cluster_size; @@ -2438,7 +2437,7 @@ static BlockDriver bdrv_iscsi = { .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, .bdrv_co_getlength = iscsi_co_getlength, - .bdrv_co_get_info = iscsi_co_get_info, + .bdrv_get_info = iscsi_get_info, .bdrv_co_truncate = iscsi_co_truncate, .bdrv_refresh_limits = iscsi_refresh_limits, @@ -2477,7 +2476,7 @@ static BlockDriver bdrv_iser = { .bdrv_co_invalidate_cache = iscsi_co_invalidate_cache, .bdrv_co_getlength = iscsi_co_getlength, - .bdrv_co_get_info = iscsi_co_get_info, + .bdrv_get_info = iscsi_get_info, .bdrv_co_truncate = iscsi_co_truncate, .bdrv_refresh_limits = iscsi_refresh_limits, diff --git a/block/mirror.c b/block/mirror.c index c2c5099c95..ea32861db1 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1082,7 +1082,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) bdrv_get_backing_filename(target_bs, backing_filename, sizeof(backing_filename)); bdrv_graph_co_rdlock(); - if (!bdrv_co_get_info(target_bs, &bdi) && bdi.cluster_size) { + if (!bdrv_get_info(target_bs, &bdi) && bdi.cluster_size) { s->target_cluster_size = bdi.cluster_size; } else { s->target_cluster_size = BDRV_SECTOR_SIZE; @@ -1844,6 +1844,7 @@ static BlockJob *mirror_start_job( GLOBAL_STATE_CODE(); + bdrv_graph_rdlock_main_loop(); if (granularity == 0) { granularity = bdrv_get_default_bitmap_granularity(target); } @@ -1852,6 +1853,7 @@ static BlockJob *mirror_start_job( if (buf_size < 0) { error_setg(errp, "Invalid parameter 'buf-size'"); + bdrv_graph_rdunlock_main_loop(); return NULL; } @@ -1859,7 +1861,6 @@ static BlockJob *mirror_start_job( buf_size = DEFAULT_MIRROR_BUF_SIZE; } - bdrv_graph_rdlock_main_loop(); if (bdrv_skip_filters(bs) == bdrv_skip_filters(target)) { error_setg(errp, "Can't mirror node into itself"); bdrv_graph_rdunlock_main_loop(); diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c index a738e7bbf7..27fd5c12f2 100644 --- a/block/monitor/bitmap-qmp-cmds.c +++ b/block/monitor/bitmap-qmp-cmds.c @@ -114,7 +114,9 @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name, } } else { /* Default to cluster size, if available: */ + bdrv_graph_rdlock_main_loop(); granularity = bdrv_get_default_bitmap_granularity(bs); + bdrv_graph_rdunlock_main_loop(); } if (!has_persistent) { diff --git a/block/qcow.c b/block/qcow.c index 8a3e7591a9..1e70c943cb 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -1134,8 +1134,7 @@ fail: return ret; } -static int coroutine_fn -qcow_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcowState *s = bs->opaque; bdi->cluster_size = s->cluster_size; @@ -1204,7 +1203,7 @@ static BlockDriver bdrv_qcow = { .bdrv_make_empty = qcow_make_empty, .bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed, - .bdrv_co_get_info = qcow_co_get_info, + .bdrv_get_info = qcow_get_info, .create_opts = &qcow_create_opts, .strong_runtime_opts = qcow_strong_runtime_opts, diff --git a/block/qcow2.c b/block/qcow2.c index 66fba89b41..9af9eea15d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -5236,8 +5236,7 @@ err: return NULL; } -static int coroutine_fn -qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcow2State *s = bs->opaque; bdi->cluster_size = s->cluster_size; @@ -6174,7 +6173,7 @@ BlockDriver bdrv_qcow2 = { .bdrv_snapshot_list = qcow2_snapshot_list, .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, .bdrv_measure = qcow2_measure, - .bdrv_co_get_info = qcow2_co_get_info, + .bdrv_get_info = qcow2_get_info, .bdrv_get_specific_info = qcow2_get_specific_info, .bdrv_co_save_vmstate = qcow2_co_save_vmstate, diff --git a/block/qed.c b/block/qed.c index 4a36fb3929..11bb508f39 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1494,8 +1494,7 @@ static int64_t coroutine_fn bdrv_qed_co_getlength(BlockDriverState *bs) return s->header.image_size; } -static int coroutine_fn -bdrv_qed_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int bdrv_qed_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQEDState *s = bs->opaque; @@ -1664,7 +1663,7 @@ static BlockDriver bdrv_qed = { .bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes, .bdrv_co_truncate = bdrv_qed_co_truncate, .bdrv_co_getlength = bdrv_qed_co_getlength, - .bdrv_co_get_info = bdrv_qed_co_get_info, + .bdrv_get_info = bdrv_qed_get_info, .bdrv_refresh_limits = bdrv_qed_refresh_limits, .bdrv_co_change_backing_file = bdrv_qed_co_change_backing_file, .bdrv_co_invalidate_cache = bdrv_qed_co_invalidate_cache, diff --git a/block/raw-format.c b/block/raw-format.c index df16ac1ea2..473c1a6df4 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -393,10 +393,9 @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs, return info; } -static int coroutine_fn GRAPH_RDLOCK -raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int GRAPH_RDLOCK raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { - return bdrv_co_get_info(bs->file->bs, bdi); + return bdrv_get_info(bs->file->bs, bdi); } static void GRAPH_RDLOCK raw_refresh_limits(BlockDriverState *bs, Error **errp) @@ -660,7 +659,7 @@ BlockDriver bdrv_raw = { .bdrv_co_getlength = &raw_co_getlength, .is_format = true, .bdrv_measure = &raw_measure, - .bdrv_co_get_info = &raw_co_get_info, + .bdrv_get_info = &raw_get_info, .bdrv_refresh_limits = &raw_refresh_limits, .bdrv_probe_blocksizes = &raw_probe_blocksizes, .bdrv_probe_geometry = &raw_probe_geometry, diff --git a/block/rbd.c b/block/rbd.c index 951cd63f9a..cf9670480e 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1399,8 +1399,7 @@ coroutine_fn qemu_rbd_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, } #endif -static int coroutine_fn -qemu_rbd_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVRBDState *s = bs->opaque; bdi->cluster_size = s->object_size; @@ -1822,7 +1821,7 @@ static BlockDriver bdrv_rbd = { .bdrv_co_create = qemu_rbd_co_create, .bdrv_co_create_opts = qemu_rbd_co_create_opts, .bdrv_has_zero_init = bdrv_has_zero_init_1, - .bdrv_co_get_info = qemu_rbd_co_get_info, + .bdrv_get_info = qemu_rbd_getinfo, .bdrv_get_specific_info = qemu_rbd_get_specific_info, .create_opts = &qemu_rbd_create_opts, .bdrv_co_getlength = qemu_rbd_co_getlength, diff --git a/block/vdi.c b/block/vdi.c index 3ddc62a569..e68455cc4d 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -329,11 +329,12 @@ static int coroutine_fn vdi_co_check(BlockDriverState *bs, BdrvCheckResult *res, return 0; } -static int coroutine_fn -vdi_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int vdi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { - /* TODO: vdi_co_get_info would be needed for machine snapshots. - vm_state_offset is still missing. */ + /* + * TODO: vdi_get_info would be needed for machine snapshots. + * vm_state_offset is still missing. + */ BDRVVdiState *s = (BDRVVdiState *)bs->opaque; logout("\n"); bdi->cluster_size = s->block_size; @@ -1052,7 +1053,7 @@ static BlockDriver bdrv_vdi = { .bdrv_co_pwritev = vdi_co_pwritev, #endif - .bdrv_co_get_info = vdi_co_get_info, + .bdrv_get_info = vdi_get_info, .is_format = true, .create_opts = &vdi_create_opts, diff --git a/block/vhdx.c b/block/vhdx.c index b2a4b813a0..e4d7527bca 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1167,8 +1167,7 @@ static void vhdx_block_translate(BDRVVHDXState *s, int64_t sector_num, } -static int coroutine_fn -vhdx_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int vhdx_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVVHDXState *s = bs->opaque; @@ -2257,7 +2256,7 @@ static BlockDriver bdrv_vhdx = { .bdrv_co_writev = vhdx_co_writev, .bdrv_co_create = vhdx_co_create, .bdrv_co_create_opts = vhdx_co_create_opts, - .bdrv_co_get_info = vhdx_co_get_info, + .bdrv_get_info = vhdx_get_info, .bdrv_co_check = vhdx_co_check, .bdrv_has_zero_init = vhdx_has_zero_init, diff --git a/block/vmdk.c b/block/vmdk.c index 9c7ab037e1..3c5885ba62 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -3047,8 +3047,7 @@ static bool vmdk_extents_type_eq(const VmdkExtent *a, const VmdkExtent *b) (a->flat || a->cluster_sectors == b->cluster_sectors); } -static int coroutine_fn -vmdk_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { int i; BDRVVmdkState *s = bs->opaque; @@ -3166,7 +3165,7 @@ static BlockDriver bdrv_vmdk = { .bdrv_has_zero_init = vmdk_has_zero_init, .bdrv_get_specific_info = vmdk_get_specific_info, .bdrv_refresh_limits = vmdk_refresh_limits, - .bdrv_co_get_info = vmdk_co_get_info, + .bdrv_get_info = vmdk_get_info, .bdrv_gather_child_options = vmdk_gather_child_options, .is_format = true, diff --git a/block/vpc.c b/block/vpc.c index 801ff5793f..6e98a57bda 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -605,8 +605,7 @@ fail: return ret; } -static int coroutine_fn -vpc_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) +static int vpc_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVVPCState *s = (BDRVVPCState *)bs->opaque; @@ -1246,7 +1245,7 @@ static BlockDriver bdrv_vpc = { .bdrv_co_pwritev = vpc_co_pwritev, .bdrv_co_block_status = vpc_co_block_status, - .bdrv_co_get_info = vpc_co_get_info, + .bdrv_get_info = vpc_get_info, .is_format = true, .create_opts = &vpc_create_opts, diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 6df2e8e7c5..ee3eabb1aa 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -50,7 +50,7 @@ void nvme_ns_init_format(NvmeNamespace *ns) npdg = ns->blkconf.discard_granularity / ns->lbasz; - ret = bdrv_get_info(blk_bs(ns->blkconf.blk), &bdi); + ret = bdrv_get_info_unlocked(blk_bs(ns->blkconf.blk), &bdi); if (ret >= 0 && bdi.cluster_size > ns->blkconf.discard_granularity) { npdg = bdi.cluster_size / ns->lbasz; } diff --git a/include/block/block-io.h b/include/block/block-io.h index b99cc98d26..eb29a04d29 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -193,11 +193,12 @@ bdrv_get_device_name(const BlockDriverState *bs); const char * GRAPH_RDLOCK bdrv_get_device_or_node_name(const BlockDriverState *bs); +/* The coroutine is called 'unlocked' because the wrapper is. */ int coroutine_fn GRAPH_RDLOCK -bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); - -int co_wrapper_mixed_bdrv_rdlock -bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); +bdrv_co_get_info_unlocked(BlockDriverState *bs, BlockDriverInfo *bdi); +int co_wrapper_bdrv_rdlock +bdrv_get_info_unlocked(BlockDriverState *bs, BlockDriverInfo *bdi); +int GRAPH_RDLOCK bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); ImageInfoSpecific * GRAPH_RDLOCK bdrv_get_specific_info(BlockDriverState *bs, Error **errp); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 2982dd3118..22c03c0c40 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -722,8 +722,8 @@ struct BlockDriver { BlockDriverState *bs, int64_t offset, int64_t bytes, QEMUIOVector *qiov, size_t qiov_offset); - int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_get_info)( - BlockDriverState *bs, BlockDriverInfo *bdi); + int GRAPH_RDLOCK_PTR (*bdrv_get_info)(BlockDriverState *bs, + BlockDriverInfo *bdi); ImageInfoSpecific * GRAPH_RDLOCK_PTR (*bdrv_get_specific_info)( BlockDriverState *bs, Error **errp); diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index fa956debfb..4f5b45d7d7 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -47,7 +47,7 @@ void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap); BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs); -uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs); +uint32_t GRAPH_RDLOCK bdrv_get_default_bitmap_granularity(BlockDriverState *bs); uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap); diff --git a/qemu-img.c b/qemu-img.c index 139eeb5039..8c24956f39 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2506,10 +2506,12 @@ static int img_convert(int argc, char **argv) src_bs = blk_bs(s.src[bs_i]); s.src_alignment[bs_i] = DIV_ROUND_UP(src_bs->bl.request_alignment, BDRV_SECTOR_SIZE); + bdrv_graph_rdlock_main_loop(); if (!bdrv_get_info(src_bs, &bdi)) { s.src_alignment[bs_i] = MAX(s.src_alignment[bs_i], bdi.cluster_size / BDRV_SECTOR_SIZE); } + bdrv_graph_rdunlock_main_loop(); s.total_sectors += s.src_sectors[bs_i]; } @@ -2768,7 +2770,9 @@ static int img_convert(int argc, char **argv) s.target_backing_sectors = -1; } + bdrv_graph_rdlock_main_loop(); ret = bdrv_get_info(out_bs, &bdi); + bdrv_graph_rdunlock_main_loop(); if (ret < 0) { if (s.compressed) { error_report("could not get block driver info"); @@ -3694,7 +3698,9 @@ static int img_rebase(int argc, char **argv) * We need overlay subcluster size (or cluster size in case writes are * compressed) to make sure write requests are aligned. */ + bdrv_graph_rdlock_main_loop(); ret = bdrv_get_info(unfiltered_bs, &bdi); + bdrv_graph_rdunlock_main_loop(); if (ret < 0) { error_report("could not get block driver info"); goto out; -- 2.39.5