diff --git a/block.c b/block.c index e0c6c648b1..6a805ff0ea 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 8974d46941..932aeb5844 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 d419017328..a6d271f25d 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;