This is going to be used in the subsequent commit as requests alignment
(in particular, during copy-on-read). This value only makes sense for
the formats which support subclusters (currently QCOW2 only). If this
field isn't set by driver's own bdrv_get_info() implementation, we
simply set it equal to the cluster size thus treating each cluster as having
a single subcluster.
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
block.c | 7 +++++++
block/qcow2.c | 1 +
include/block/block-common.h | 5 +++++
3 files changed, 13 insertions(+)
diff --git a/block.c b/block.c
index 0637265c26..4fe1743cfb 100644
--- a/block.c
+++ b/block.c
@@ -6392,6 +6392,13 @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
}
memset(bdi, 0, sizeof(*bdi));
ret = drv->bdrv_co_get_info(bs, bdi);
+ if (bdi->subcluster_size == 0) {
+ /*
+ * If the driver left this unset, subclusters either not supported.
+ * Then it is safe to treat each cluster as having only one subcluster.
+ */
+ bdi->subcluster_size = bdi->cluster_size;
+ }
if (ret < 0) {
return ret;
}
diff --git a/block/qcow2.c b/block/qcow2.c
index e23edd48c2..94b8d0e1c2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -5197,6 +5197,7 @@ qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcow2State *s = bs->opaque;
bdi->cluster_size = s->cluster_size;
+ bdi->subcluster_size = s->subcluster_size;
bdi->vm_state_offset = qcow2_vm_state_offset(s);
bdi->is_dirty = s->incompatible_features & QCOW2_INCOMPAT_DIRTY;
return 0;
diff --git a/include/block/block-common.h b/include/block/block-common.h
index e15395f2cb..df5ffc8d09 100644
--- a/include/block/block-common.h
+++ b/include/block/block-common.h
@@ -132,6 +132,11 @@ typedef struct BlockZoneWps {
typedef struct BlockDriverInfo {
/* in bytes, 0 if irrelevant */
int cluster_size;
+ /*
+ * A fraction of cluster_size, if supported (currently QCOW2 only); if
+ * disabled or unsupported, set equal to cluster_size.
+ */
+ int subcluster_size;
/* offset at which the VM state can be saved (0 if not possible) */
int64_t vm_state_offset;
bool is_dirty;
--
2.39.3
On 6/26/23 18:08, Andrey Drobyshev wrote:
> This is going to be used in the subsequent commit as requests alignment
> (in particular, during copy-on-read). This value only makes sense for
> the formats which support subclusters (currently QCOW2 only). If this
> field isn't set by driver's own bdrv_get_info() implementation, we
> simply set it equal to the cluster size thus treating each cluster as having
> a single subcluster.
>
> Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
> ---
> block.c | 7 +++++++
> block/qcow2.c | 1 +
> include/block/block-common.h | 5 +++++
> 3 files changed, 13 insertions(+)
>
> diff --git a/block.c b/block.c
> index 0637265c26..4fe1743cfb 100644
> --- a/block.c
> +++ b/block.c
> @@ -6392,6 +6392,13 @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
> }
> memset(bdi, 0, sizeof(*bdi));
> ret = drv->bdrv_co_get_info(bs, bdi);
> + if (bdi->subcluster_size == 0) {
> + /*
> + * If the driver left this unset, subclusters either not supported.
> + * Then it is safe to treat each cluster as having only one subcluster.
> + */
> + bdi->subcluster_size = bdi->cluster_size;
> + }
> if (ret < 0) {
> return ret;
> }
> diff --git a/block/qcow2.c b/block/qcow2.c
> index e23edd48c2..94b8d0e1c2 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -5197,6 +5197,7 @@ qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
> {
> BDRVQcow2State *s = bs->opaque;
> bdi->cluster_size = s->cluster_size;
> + bdi->subcluster_size = s->subcluster_size;
> bdi->vm_state_offset = qcow2_vm_state_offset(s);
> bdi->is_dirty = s->incompatible_features & QCOW2_INCOMPAT_DIRTY;
> return 0;
> diff --git a/include/block/block-common.h b/include/block/block-common.h
> index e15395f2cb..df5ffc8d09 100644
> --- a/include/block/block-common.h
> +++ b/include/block/block-common.h
> @@ -132,6 +132,11 @@ typedef struct BlockZoneWps {
> typedef struct BlockDriverInfo {
> /* in bytes, 0 if irrelevant */
> int cluster_size;
> + /*
> + * A fraction of cluster_size, if supported (currently QCOW2 only); if
> + * disabled or unsupported, set equal to cluster_size.
> + */
> + int subcluster_size;
> /* offset at which the VM state can be saved (0 if not possible) */
> int64_t vm_state_offset;
> bool is_dirty;
Reviewed-by: Denis V. Lunev <den@openvz.org>
On Mon, Jun 26, 2023 at 07:08:32PM +0300, Andrey Drobyshev via wrote:
> This is going to be used in the subsequent commit as requests alignment
> (in particular, during copy-on-read). This value only makes sense for
> the formats which support subclusters (currently QCOW2 only). If this
> field isn't set by driver's own bdrv_get_info() implementation, we
> simply set it equal to the cluster size thus treating each cluster as having
> a single subcluster.
>
> Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
> ---
> block.c | 7 +++++++
> block/qcow2.c | 1 +
> include/block/block-common.h | 5 +++++
> 3 files changed, 13 insertions(+)
>
> diff --git a/block.c b/block.c
> index 0637265c26..4fe1743cfb 100644
> --- a/block.c
> +++ b/block.c
> @@ -6392,6 +6392,13 @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
> }
> memset(bdi, 0, sizeof(*bdi));
> ret = drv->bdrv_co_get_info(bs, bdi);
> + if (bdi->subcluster_size == 0) {
> + /*
> + * If the driver left this unset, subclusters either not supported.
s/either/are/
> + * Then it is safe to treat each cluster as having only one subcluster.
> + */
> + bdi->subcluster_size = bdi->cluster_size;
> + }
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
© 2016 - 2025 Red Hat, Inc.