aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2023-04-07 17:32:56 +0200
committerKevin Wolf <kwolf@redhat.com>2023-04-11 16:38:34 +0200
commit160a29e2f8b2d100246ab446813409f72d1e0767 (patch)
tree1b9ca64dcf78e2c9fde51d72e59a435ce7a67753
parent2b1f8fcb847f8cc7a214e14cbbdf99b354a4f8e3 (diff)
downloadqemu-160a29e2f8b2d100246ab446813409f72d1e0767.zip
qemu-160a29e2f8b2d100246ab446813409f72d1e0767.tar.gz
qemu-160a29e2f8b2d100246ab446813409f72d1e0767.tar.bz2
block: move has_variable_length to BlockLimits
At the protocol level, has_variable_length only needs to be true in the very special case of host CD-ROM drives, so that they do not need an explicit monitor command to read the new size when a disc is loaded in the tray. However, at the format level has_variable_length has to be true for all raw blockdevs and for all filters, even though in practice the length depends on the underlying file and thus will not change except in the case of host CD-ROM drives. As a first step towards computing an accurate value of has_variable_length, add the value into the BlockLimits structure and initialize the field from the BlockDriver. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20230407153303.391121-2-pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r--block.c2
-rw-r--r--block/io.c6
-rw-r--r--include/block/block_int-common.h8
3 files changed, 15 insertions, 1 deletions
diff --git a/block.c b/block.c
index e0c6c64..6a805ff 100644
--- a/block.c
+++ b/block.c
@@ -5849,7 +5849,7 @@ int64_t coroutine_fn bdrv_co_nb_sectors(BlockDriverState *bs)
if (!drv)
return -ENOMEDIUM;
- if (drv->has_variable_length) {
+ if (bs->bl.has_variable_length) {
int ret = bdrv_co_refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
return ret;
diff --git a/block/io.c b/block/io.c
index 8974d46..932aeb5 100644
--- a/block/io.c
+++ b/block/io.c
@@ -182,6 +182,8 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
drv->bdrv_aio_preadv ||
drv->bdrv_co_preadv_part) ? 1 : 512;
+ bs->bl.has_variable_length = drv->has_variable_length;
+
/* Take some limits from the children as a default */
have_limits = false;
QLIST_FOREACH(c, &bs->children, next) {
@@ -190,6 +192,10 @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
bdrv_merge_limits(&bs->bl, &c->bs->bl);
have_limits = true;
}
+
+ if (c->role & BDRV_CHILD_FILTERED) {
+ bs->bl.has_variable_length |= c->bs->bl.has_variable_length;
+ }
}
if (!have_limits) {
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
index d419017..a6d271f 100644
--- a/include/block/block_int-common.h
+++ b/include/block/block_int-common.h
@@ -855,6 +855,14 @@ typedef struct BlockLimits {
/* maximum number of iovec elements */
int max_iov;
+
+ /*
+ * true if the length of the underlying file can change, and QEMU
+ * is expected to adjust automatically. Mostly for CD-ROM drives,
+ * whose length is zero when the tray is empty (they don't need
+ * an explicit monitor command to load the disk inside the guest).
+ */
+ bool has_variable_length;
} BlockLimits;
typedef struct BdrvOpBlocker BdrvOpBlocker;