summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Bentele2020-10-07 10:51:06 +0200
committerManuel Bentele2022-12-07 15:51:14 +0100
commita1f0676733467957c47b2a18c0c9929fd71b613d (patch)
tree325a95d516d0625e0ae5da4649cc76fa674ea460
parentRevert "hw/loongarch/virt: Add cfi01 pflash device" (diff)
downloadqemu-block_qcow2_cluster_info.tar.gz
qemu-block_qcow2_cluster_info.tar.xz
qemu-block_qcow2_cluster_info.zip
block: Add driver callback to get cluster informationblock_qcow2_cluster_info
Signed-off-by: Manuel Bentele <development@manuel-bentele.de>
-rw-r--r--block.c17
-rw-r--r--block/qcow2.c40
-rw-r--r--block/qcow2.h22
-rw-r--r--include/block/block-io.h3
-rw-r--r--include/block/block_int-common.h8
-rw-r--r--meson.build2
-rw-r--r--meson_options.txt2
-rw-r--r--qemu-io-cmds.c31
-rw-r--r--scripts/meson-buildoptions.sh4
9 files changed, 129 insertions, 0 deletions
diff --git a/block.c b/block.c
index a18f052374..e73b262871 100644
--- a/block.c
+++ b/block.c
@@ -6304,6 +6304,23 @@ BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
return drv->bdrv_get_specific_stats(bs);
}
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+int bdrv_get_cluster_info(BlockDriverState *bs, uint64_t offset)
+{
+ BlockDriver *drv = bs->drv;
+
+ if (!drv) {
+ return -ENOMEDIUM;
+ }
+
+ if (drv->bdrv_get_cluster_info) {
+ return drv->bdrv_get_cluster_info(bs, offset);
+ }
+
+ return -ENOTSUP;
+}
+#endif
+
void bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event)
{
IO_CODE();
diff --git a/block/qcow2.c b/block/qcow2.c
index 4d6666d3ff..a97f7b431a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5925,6 +5925,42 @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
s->signaled_corruption = true;
}
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+int qcow2_get_cluster_info(BlockDriverState *bs, uint64_t offset)
+{
+ BDRVQcow2State *s = bs->opaque;
+ uint64_t host_offset;
+ uint64_t coffset;
+ unsigned int bytes;
+ QCow2SubclusterType type;
+ int ret = 0, csize, nb_csectors;
+
+ /* only get information for one byte */
+ bytes = 1;
+
+ ret = qcow2_get_host_offset(bs, offset, &bytes, &host_offset, &type);
+ if (ret < 0) {
+ return ret;
+ }
+
+ printf("cluster type: %s\n", qcow2_get_subcluster_name(type));
+ printf("cluster offset host: %ld\n", host_offset);
+ printf("cluster offset guest: %ld\n", offset);
+ printf("cluster offset in-cluster: %ld\n", offset_into_cluster(s, offset));
+
+ if (type == QCOW2_SUBCLUSTER_COMPRESSED) {
+ qcow2_parse_compressed_l2_entry(bs, host_offset, &coffset, &csize);
+ nb_csectors = ((host_offset >> s->csize_shift) & s->csize_mask) + 1;
+
+ printf("cluster compressed offset: %ld\n", coffset);
+ printf("cluster compressed sectors: %d\n", nb_csectors);
+ printf("cluster compressed size: %d\n", csize);
+ }
+
+ return ret;
+}
+#endif
+
#define QCOW_COMMON_OPTIONS \
{ \
.name = BLOCK_OPT_SIZE, \
@@ -6108,6 +6144,10 @@ BlockDriver bdrv_qcow2 = {
.bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap,
.bdrv_co_remove_persistent_dirty_bitmap =
qcow2_co_remove_persistent_dirty_bitmap,
+
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+ .bdrv_get_cluster_info = qcow2_get_cluster_info,
+#endif
};
static void bdrv_qcow2_init(void)
diff --git a/block/qcow2.h b/block/qcow2.h
index 2285f18a73..ac30e48ee6 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -793,6 +793,24 @@ QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs,
}
}
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+static inline const char *qcow2_get_subcluster_name(
+ const QCow2SubclusterType type)
+{
+ static const char *subcluster_names[] = {
+ "QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN",
+ "QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC",
+ "QCOW2_SUBCLUSTER_ZERO_PLAIN",
+ "QCOW2_SUBCLUSTER_ZERO_ALLOC",
+ "QCOW2_SUBCLUSTER_NORMAL",
+ "QCOW2_SUBCLUSTER_COMPRESSED",
+ "QCOW2_SUBCLUSTER_INVALID"
+ };
+
+ return subcluster_names[type];
+}
+#endif
+
static inline bool qcow2_cluster_is_allocated(QCow2ClusterType type)
{
return (type == QCOW2_CLUSTER_COMPRESSED || type == QCOW2_CLUSTER_NORMAL ||
@@ -840,6 +858,10 @@ void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset,
int64_t size, const char *message_format, ...)
G_GNUC_PRINTF(5, 6);
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+int qcow2_get_cluster_info(BlockDriverState *bs, uint64_t offset);
+#endif
+
int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
uint64_t entries, size_t entry_len,
int64_t max_size_bytes, const char *table_name,
diff --git a/include/block/block-io.h b/include/block/block-io.h
index b099d7db45..8866258282 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -126,6 +126,9 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
Error **errp);
BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs);
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+ int bdrv_get_cluster_info(BlockDriverState *bs, uint64_t offset);
+#endif
void bdrv_round_to_clusters(BlockDriverState *bs,
int64_t offset, int64_t bytes,
int64_t *cluster_offset,
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index 31ae91e56e..2546500ab0 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -638,6 +638,14 @@ struct BlockDriver {
int coroutine_fn (*bdrv_co_pdiscard_snapshot)(BlockDriverState *bs,
int64_t offset, int64_t bytes);
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+ /*
+ * Returns information about the mapping between the guest cluster
+ * and the host cluster for a specific guest block address.
+ */
+ int (*bdrv_get_cluster_info)(BlockDriverState *bs, uint64_t offset);
+#endif
+
/*
* Invalidate any cached meta-data.
*/
diff --git a/meson.build b/meson.build
index 5c6b5a1c75..1b671e04ff 100644
--- a/meson.build
+++ b/meson.build
@@ -1821,6 +1821,7 @@ endif
config_host_data.set('CONFIG_MODULE_UPGRADES', get_option('module_upgrades'))
config_host_data.set('CONFIG_ATTR', libattr.found())
+config_host_data.set('CONFIG_BDRV_CLUSTER_INFO', get_option('block_drv_cluster_info'))
config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', get_option('block_drv_whitelist_in_tools'))
config_host_data.set('CONFIG_BRLAPI', brlapi.found())
config_host_data.set('CONFIG_COCOA', cocoa.found())
@@ -3854,6 +3855,7 @@ summary_info += {'coroutine pool': have_coroutine_pool}
if have_block
summary_info += {'Block whitelist (rw)': get_option('block_drv_rw_whitelist')}
summary_info += {'Block whitelist (ro)': get_option('block_drv_ro_whitelist')}
+ summary_info += {'Block cluster info support': get_option('block_drv_cluster_info')}
summary_info += {'Use block whitelist in tools': get_option('block_drv_whitelist_in_tools')}
summary_info += {'VirtFS support': have_virtfs}
summary_info += {'build virtiofs daemon': have_virtiofsd}
diff --git a/meson_options.txt b/meson_options.txt
index 4b749ca549..ea5b11c596 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -27,6 +27,8 @@ option('block_drv_rw_whitelist', type : 'string', value : '',
description: 'set block driver read-write whitelist (by default affects only QEMU, not tools like qemu-img)')
option('block_drv_ro_whitelist', type : 'string', value : '',
description: 'set block driver read-only whitelist (by default affects only QEMU, not tools like qemu-img)')
+option('block_drv_cluster_info', type: 'boolean', value: false,
+ description: 'block driver cluster info support')
option('interp_prefix', type : 'string', value : '/usr/gnemul/qemu-%M',
description: 'where to find shared libraries etc., use %M for cpu name')
option('fuzzing_engine', type : 'string', value : '',
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 952dc940f1..c288c2ab30 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -2405,6 +2405,34 @@ static const cmdinfo_t sleep_cmd = {
.oneline = "waits for the given value in milliseconds",
};
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+static int cluster_info_f(BlockBackend *blk, int argc, char **argv)
+{
+ BlockDriverState *bs = blk_bs(blk);
+ char *endptr;
+ long offset;
+
+ offset = strtol(argv[1], &endptr, 0);
+ if (offset < 0 || *endptr != '\0' ||
+ offset > (bs->total_sectors * BDRV_SECTOR_SIZE)) {
+ printf("%s is not a valid number\n", argv[1]);
+ return -EINVAL;
+ }
+
+ return bdrv_get_cluster_info(bs, offset);
+}
+
+static const cmdinfo_t cluster_info_cmd = {
+ .name = "cluster_info",
+ .argmin = 1,
+ .argmax = 1,
+ .cfunc = cluster_info_f,
+ .args = "offset",
+ .oneline = "returns information about the mapping between guest \
+ and host cluster type for a specific guest address",
+};
+#endif
+
static void help_oneline(const char *cmd, const cmdinfo_t *ct)
{
printf("%s ", cmd);
@@ -2517,5 +2545,8 @@ static void __attribute((constructor)) init_qemuio_commands(void)
qemuio_add_command(&wait_break_cmd);
qemuio_add_command(&abort_cmd);
qemuio_add_command(&sleep_cmd);
+#ifdef CONFIG_BDRV_CLUSTER_INFO
+ qemuio_add_command(&cluster_info_cmd);
+#endif
qemuio_add_command(&sigraise_cmd);
}
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index aa6e30ea91..ff0764b866 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -13,6 +13,8 @@ meson_options_help() {
printf "%s\n" ' --disable-install-blobs install provided firmware blobs'
printf "%s\n" ' --docdir=VALUE Base directory for documentation installation'
printf "%s\n" ' (can be empty) [share/doc]'
+ printf "%s\n" ' --enable-block-drv-cluster-info'
+ printf "%s\n" ' block driver cluster info support'
printf "%s\n" ' --enable-block-drv-whitelist-in-tools'
printf "%s\n" ' use block whitelist also in tools instead of only'
printf "%s\n" ' QEMU'
@@ -204,6 +206,8 @@ _meson_option_parse() {
--disable-blkio) printf "%s" -Dblkio=disabled ;;
--block-drv-ro-whitelist=*) quote_sh "-Dblock_drv_ro_whitelist=$2" ;;
--block-drv-rw-whitelist=*) quote_sh "-Dblock_drv_rw_whitelist=$2" ;;
+ --enable-block-drv-cluster-info) printf "%s" -Dblock_drv_cluster_info=true ;;
+ --disable-block-drv-cluster-info) printf "%s" -Dblock_drv_cluster_info=false ;;
--enable-block-drv-whitelist-in-tools) printf "%s" -Dblock_drv_whitelist_in_tools=true ;;
--disable-block-drv-whitelist-in-tools) printf "%s" -Dblock_drv_whitelist_in_tools=false ;;
--enable-bochs) printf "%s" -Dbochs=enabled ;;