@@ -2835,3 +2835,25 @@ void bdrv_unregister_buf(BlockDriverState *bs, void *host)
bdrv_unregister_buf(child->bs, host);
}
}
+
+void bdrv_apply_blkconf(BlockDriverState *bs, BlockConf *conf)
+{
+ BlockDriver *drv = bs->drv;
+
+ if (!drv) {
+ return;
+ }
+
+ if (drv->bdrv_apply_blkconf) {
+ drv->bdrv_apply_blkconf(bs, conf);
+ return;
+ }
+
+ if (bs->file && bs->file->bs) {
+ bdrv_apply_blkconf(bs->file->bs, conf);
+ }
+
+ if (bs->drv->supports_backing && backing_bs(bs)) {
+ bdrv_apply_blkconf(backing_bs(bs), conf);
+ }
+}
@@ -38,7 +38,7 @@ void blkconf_blocksizes(BlockConf *conf)
/* fill in detected values if they are not defined via qemu command line */
if (!conf->physical_block_size) {
if (!backend_ret) {
- conf->physical_block_size = blocksizes.phys;
+ conf->physical_block_size = blocksizes.phys;
} else {
conf->physical_block_size = BDRV_SECTOR_SIZE;
}
@@ -52,6 +52,16 @@ void blkconf_blocksizes(BlockConf *conf)
}
}
+void blkconf_apply_to_blkdrv(BlockConf *conf)
+{
+ BlockBackend *blk = conf->blk;
+ BlockDriverState *bs = blk_bs(blk);
+
+ if (bs) {
+ bdrv_apply_blkconf(bs, conf);
+ }
+}
+
bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
bool resizable, Error **errp)
{
@@ -10,6 +10,7 @@
#include "block/dirty-bitmap.h"
#include "block/blockjob.h"
#include "qemu/hbitmap.h"
+#include "hw/block/block.h"
/* block.c */
typedef struct BlockDriver BlockDriver;
@@ -618,4 +619,13 @@ bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
*/
void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size);
void bdrv_unregister_buf(BlockDriverState *bs, void *host);
+
+/**
+ * bdrv_apply_blkconf:
+ *
+ * Recursively finds the highest-level block drivers among the files and
+ * backing files that accept a block configuration and applies the given block
+ * configuration to them.
+ */
+void bdrv_apply_blkconf(BlockDriverState *bs, BlockConf *conf);
#endif
@@ -433,6 +433,15 @@ struct BlockDriver {
void (*bdrv_abort_perm_update)(BlockDriverState *bs);
/**
+ * Called to inform the driver of the block configuration of the virtual
+ * block device.
+ *
+ * This function is called by a block device realization function if the
+ * device wants to inform the block driver of its block configuration.
+ */
+ void (*bdrv_apply_blkconf)(BlockDriverState *bs, BlockConf *conf);
+
+ /**
* Returns in @nperm and @nshared the permissions that the driver for @bs
* needs on its child @c, based on the cumulative permissions requested by
* the parents in @parent_perm and @parent_shared.
@@ -77,6 +77,7 @@ bool blkconf_geometry(BlockConf *conf, int *trans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
Error **errp);
void blkconf_blocksizes(BlockConf *conf);
+void blkconf_apply_to_blkdrv(BlockConf *conf);
bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
bool resizable, Error **errp);
A block driver may need to know about the block configuration, most critically the sector sizes, of a block backend for alignment purposes or for some other reason. It doesn't seem like qemu has an existing mechanism for a block backend to convey the required information to the relevant block driver when it is being realized. The need for this mechanism rises from the fact that a drive may not have a backend at the time it is created, as devices are created after drives during qemu startup. Therefore, a driver requiring information about the block configuration can get this information when a backend is created for it at the earliest. The most natural place for this to take place seems to be in the realization functions of the various block device drivers, such as scsi-hd. The interface proposed here allows the block driver to receive information about the block configuration and the associated backend through a new callback. Signed-off-by: Ari Sundholm <ari@tuxera.com> --- block/io.c | 22 ++++++++++++++++++++++ hw/block/block.c | 12 +++++++++++- include/block/block.h | 10 ++++++++++ include/block/block_int.h | 9 +++++++++ include/hw/block/block.h | 1 + 5 files changed, 53 insertions(+), 1 deletion(-)