@@ -10,6 +10,9 @@
#include "blockdev.h"
#include "hw/block-common.h"
#include "qemu-error.h"
+#ifdef __linux__
+#include <linux/fs.h>
+#endif
void blkconf_serial(BlockConf *conf, char **serial)
{
@@ -24,6 +27,26 @@ void blkconf_serial(BlockConf *conf, char **serial)
}
}
+void blkconf_blocksizes(BlockConf *conf)
+{
+ int block_size;
+
+ if (!conf->physical_block_size) {
+ if (bdrv_ioctl(conf->bs, BLKPBSZGET, &block_size) == 0) {
+ conf->physical_block_size = (uint16_t) block_size;
+ } else {
+ conf->physical_block_size = BLOCK_PROPERTY_STD_BLKSIZE;
+ }
+ }
+ if (!conf->logical_block_size) {
+ if (bdrv_ioctl(conf->bs, BLKSSZGET, &block_size) == 0) {
+ conf->logical_block_size = (uint16_t) block_size;
+ } else {
+ conf->logical_block_size = BLOCK_PROPERTY_STD_BLKSIZE;
+ }
+ }
+}
+
int blkconf_geometry(BlockConf *conf, int *ptrans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max)
{
@@ -40,18 +40,23 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
return exp;
}
-#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
+#define BLOCK_PROPERTY_STD_BLKSIZE 512
+#define DEFINE_BLOCK_PROPERTIES_EXTENDED(_state, _conf, _blksize) \
DEFINE_PROP_DRIVE("drive", _state, _conf.bs), \
DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \
- _conf.logical_block_size, 512), \
+ _conf.logical_block_size, _blksize), \
DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \
- _conf.physical_block_size, 512), \
+ _conf.physical_block_size, _blksize), \
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \
DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1), \
DEFINE_PROP_UINT32("discard_granularity", _state, \
_conf.discard_granularity, 0)
+#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
+ DEFINE_BLOCK_PROPERTIES_EXTENDED(_state, _conf, \
+ BLOCK_PROPERTY_STD_BLKSIZE)
+
#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \
DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \
DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
@@ -60,6 +65,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
/* Configuration helpers */
void blkconf_serial(BlockConf *conf, char **serial);
+void blkconf_blocksizes(BlockConf *conf);
int blkconf_geometry(BlockConf *conf, int *trans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max);
@@ -904,7 +904,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
error_propagate(errp, local_err);
return;
}
- if (value < min || value > max) {
+
+ /* value == 0 indicates that block size should be sensed later on */
+ if ((value < min || value > max) && value > 0) {
error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
dev->id?:"", name, (int64_t)value, min, max);
return;
@@ -401,7 +401,7 @@ static TypeInfo s390_virtio_net = {
};
static Property s390_virtio_blk_properties[] = {
- DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
+ DEFINE_BLOCK_PROPERTIES_EXTENDED(VirtIOS390Device, blk.conf, 0),
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf),
DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
#ifdef __linux__
@@ -600,6 +600,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
}
blkconf_serial(&blk->conf, &blk->serial);
+ blkconf_blocksizes(&blk->conf);
if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
return NULL;
}