From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54228) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHH4J-0007rm-Ni for qemu-devel@nongnu.org; Tue, 12 Aug 2014 14:45:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XHH4C-0003l6-Lh for qemu-devel@nongnu.org; Tue, 12 Aug 2014 14:45:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:7195) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHH4C-0003i0-Eq for qemu-devel@nongnu.org; Tue, 12 Aug 2014 14:45:04 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s7CIj2TQ005258 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 12 Aug 2014 14:45:02 -0400 From: John Snow Date: Tue, 12 Aug 2014 14:44:09 -0400 Message-Id: <1407869049-29178-1-git-send-email-jsnow@redhat.com> Subject: [Qemu-devel] [PATCH] ide: Add resize callback to ide/core List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, jsnow@redhat.com, stefanha@redhat.com 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 --- 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); + 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