virtio-blk: qdev properties for disk geometry

Geometry needs to be qdev properties, because it belongs to the
disk's guest part.

Maintain backward compatibility exactly like for serial: fall back to
DriveInfo's geometry, set with -drive cyls=...

Bonus: info qtree now shows the geometry.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Markus Armbruster 2012-07-10 11:12:43 +02:00 committed by Kevin Wolf
parent d252df4898
commit e63e7fde24
3 changed files with 34 additions and 9 deletions

View File

@ -402,6 +402,7 @@ static TypeInfo s390_virtio_net = {
static Property s390_virtio_blk_properties[] = { static Property s390_virtio_blk_properties[] = {
DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf), DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf),
DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial), DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
#ifdef __linux__ #ifdef __linux__
DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true), DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),

View File

@ -479,19 +479,17 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
VirtIOBlock *s = to_virtio_blk(vdev); VirtIOBlock *s = to_virtio_blk(vdev);
struct virtio_blk_config blkcfg; struct virtio_blk_config blkcfg;
uint64_t capacity; uint64_t capacity;
int cylinders, heads, secs;
int blk_size = s->conf->logical_block_size; int blk_size = s->conf->logical_block_size;
bdrv_get_geometry(s->bs, &capacity); bdrv_get_geometry(s->bs, &capacity);
bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
memset(&blkcfg, 0, sizeof(blkcfg)); memset(&blkcfg, 0, sizeof(blkcfg));
stq_raw(&blkcfg.capacity, capacity); stq_raw(&blkcfg.capacity, capacity);
stl_raw(&blkcfg.seg_max, 128 - 2); stl_raw(&blkcfg.seg_max, 128 - 2);
stw_raw(&blkcfg.cylinders, cylinders); stw_raw(&blkcfg.cylinders, s->conf->cyls);
stl_raw(&blkcfg.blk_size, blk_size); stl_raw(&blkcfg.blk_size, blk_size);
stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size); stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
blkcfg.heads = heads; blkcfg.heads = s->conf->heads;
/* /*
* We must ensure that the block device capacity is a multiple of * We must ensure that the block device capacity is a multiple of
* the logical block size. If that is not the case, lets use * the logical block size. If that is not the case, lets use
@ -503,10 +501,10 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
* divided by 512 - instead it is the amount of blk_size blocks * divided by 512 - instead it is the amount of blk_size blocks
* per track (cylinder). * per track (cylinder).
*/ */
if (bdrv_getlength(s->bs) / heads / secs % blk_size) { if (bdrv_getlength(s->bs) / s->conf->heads / s->conf->secs % blk_size) {
blkcfg.sectors = secs & ~s->sector_mask; blkcfg.sectors = s->conf->secs & ~s->sector_mask;
} else { } else {
blkcfg.sectors = secs; blkcfg.sectors = s->conf->secs;
} }
blkcfg.size_max = 0; blkcfg.size_max = 0;
blkcfg.physical_block_exp = get_physical_block_exp(s->conf); blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
@ -590,7 +588,6 @@ static const BlockDevOps virtio_block_ops = {
VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk) VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
{ {
VirtIOBlock *s; VirtIOBlock *s;
uint32_t cylinders, heads, secs;
static int virtio_blk_id; static int virtio_blk_id;
DriveInfo *dinfo; DriveInfo *dinfo;
@ -623,7 +620,33 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
s->blk = blk; s->blk = blk;
s->rq = NULL; s->rq = NULL;
s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
hd_geometry_guess(s->bs, &cylinders, &heads, &secs, NULL);
if (!blk->conf.cyls && !blk->conf.heads && !blk->conf.secs) {
/* try to fall back to value set with legacy -drive cyls=... */
dinfo = drive_get_by_blockdev(blk->conf.bs);
blk->conf.cyls = dinfo->cyls;
blk->conf.heads = dinfo->heads;
blk->conf.secs = dinfo->secs;
}
if (!blk->conf.cyls && !blk->conf.heads && !blk->conf.secs) {
hd_geometry_guess(s->bs,
&blk->conf.cyls, &blk->conf.heads, &blk->conf.secs,
NULL);
}
if (blk->conf.cyls || blk->conf.heads || blk->conf.secs) {
if (blk->conf.cyls < 1 || blk->conf.cyls > 65535) {
error_report("cyls must be between 1 and 65535");
return NULL;
}
if (blk->conf.heads < 1 || blk->conf.heads > 255) {
error_report("heads must be between 1 and 255");
return NULL;
}
if (blk->conf.secs < 1 || blk->conf.secs > 255) {
error_report("secs must be between 1 and 255");
return NULL;
}
}
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output); s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);

View File

@ -936,6 +936,7 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
static Property virtio_blk_properties[] = { static Property virtio_blk_properties[] = {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf), DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
DEFINE_BLOCK_CHS_PROPERTIES(VirtIOPCIProxy, blk.conf),
DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial), DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
#ifdef __linux__ #ifdef __linux__
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true), DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),