On Tue, 08/12 14:44, John Snow wrote: > Currently, if the block device backing the IDE drive is resized, > the information about the device as cached inside of the IDEState > structure is not updated, thus when a guest OS re-queries the drive, > it is unable to see the expanded size. > > This patch adds a resize callback to correct this, and marks the > identify buffer cache as being dirty to force ide_identify to > regenerate this information. This callback also attempts to update > the legacy CHS values, if only to maintain a sense of > informational consistency. > > Lastly, a Linux guest as-is cannot resize a libata drive while in-use, > but it can see the expanded size as part of a bus rescan event. > This patch also allows guests such as Linux to see the new drive size > after a soft reboot event, without having to exit the QEMU process. > > Signed-off-by: John Snow <js...@redhat.com> > --- > hw/ide/core.c | 29 +++++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/hw/ide/core.c b/hw/ide/core.c > index db191a6..6c86e21 100644 > --- a/hw/ide/core.c > +++ b/hw/ide/core.c > @@ -2099,6 +2099,30 @@ static bool ide_cd_is_medium_locked(void *opaque) > return ((IDEState *)opaque)->tray_locked; > } > > +static void ide_resize_cb(void *opaque) > +{ > + IDEState *s = opaque; > + IDEDevice *dev = s->unit ? s->bus->slave : s->bus->master; > + uint64_t nb_sectors; > + > + /* Convince blkconf_geometry to re-determine geometry */ > + dev->conf.cyls = 0; > + dev->conf.heads = 0; > + dev->conf.secs = 0; > + > + blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255);
blkconf_geometry could return -1 for invalid CHS values that but shouldn't hurt as far as I can see: Reviewed-by: Fam Zheng <f...@redhat.com> > + bdrv_get_geometry(s->bs, &nb_sectors); > + > + s->nb_sectors = nb_sectors; > + s->cylinders = dev->conf.cyls; > + s->heads = dev->conf.heads; > + s->sectors = dev->conf.secs; > + s->chs_trans = dev->chs_trans; > + > + /* Let ide_identify() know it needs to regenerate the response. */ > + s->identify_set = 0; > +} > + > static const BlockDevOps ide_cd_block_ops = { > .change_media_cb = ide_cd_change_cb, > .eject_request_cb = ide_cd_eject_request_cb, > @@ -2106,6 +2130,10 @@ static const BlockDevOps ide_cd_block_ops = { > .is_medium_locked = ide_cd_is_medium_locked, > }; > > +static const BlockDevOps ide_hd_block_ops = { > + .resize_cb = ide_resize_cb, > +}; > + > int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, > const char *version, const char *serial, const char > *model, > uint64_t wwn, > @@ -2142,6 +2170,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, > IDEDriveKind kind, > error_report("Can't use a read-only drive"); > return -1; > } > + bdrv_set_dev_ops(bs, &ide_hd_block_ops, s); > } > if (serial) { > pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial); > -- > 1.9.3 > >