From patchwork Wed Aug 13 17:21:10 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Snow X-Patchwork-Id: 379699 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id EF85A140087 for ; Thu, 14 Aug 2014 03:22:08 +1000 (EST) Received: from localhost ([::1]:49008 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHcFT-0000vj-11 for incoming@patchwork.ozlabs.org; Wed, 13 Aug 2014 13:22:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59285) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHcEy-0000NO-Hw for qemu-devel@nongnu.org; Wed, 13 Aug 2014 13:21:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XHcEr-0007dd-QB for qemu-devel@nongnu.org; Wed, 13 Aug 2014 13:21:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36477) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHcEr-0007dG-H4 for qemu-devel@nongnu.org; Wed, 13 Aug 2014 13:21:29 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s7DHLS57024103 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Wed, 13 Aug 2014 13:21:28 -0400 Received: from dhcp-17-12.bos.redhat.com ([10.18.17.175]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s7DHLRFo018985; Wed, 13 Aug 2014 13:21:27 -0400 From: John Snow To: qemu-devel@nongnu.org Date: Wed, 13 Aug 2014 13:21:10 -0400 Message-Id: <1407950470-26183-1-git-send-email-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, jsnow@redhat.com, armbru@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [PATCH v2] ide: Add resize callback to ide/core X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 that updates the IDENTIFY data buffer in order to correct this. 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 --- V2: - Do not attempt to update geometry values, to avoid clobbering user-specified values, if they exist. - Do not regenerate the entire IDENTIFY buffer to avoid losing any settings that occurred during normal operation. hw/ide/core.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/hw/ide/core.c b/hw/ide/core.c index db191a6..ba5e3ad 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2099,6 +2099,33 @@ static bool ide_cd_is_medium_locked(void *opaque) return ((IDEState *)opaque)->tray_locked; } +static void ide_resize_cb(void *opaque) +{ + IDEState *s = opaque; + uint16_t *p = (uint16_t *)s->identify_data; + uint64_t nb_sectors; + + if (!s->identify_set) { + return; + } + + bdrv_get_geometry(s->bs, &nb_sectors); + s->nb_sectors = nb_sectors; + + /* Update the identify buffer. Note, this is not called for ATAPI. */ + if (s->drive_kind != IDE_CFATA) { + put_le16(p + 60, s->nb_sectors); + put_le16(p + 61, s->nb_sectors >> 16); + put_le16(p + 100, s->nb_sectors); + put_le16(p + 101, s->nb_sectors >> 16); + put_le16(p + 102, s->nb_sectors >> 32); + put_le16(p + 103, s->nb_sectors >> 48); + } else { + put_le16(p + 7, s->nb_sectors >> 16); + put_le16(p + 8, s->nb_sectors); + } +} + static const BlockDevOps ide_cd_block_ops = { .change_media_cb = ide_cd_change_cb, .eject_request_cb = ide_cd_eject_request_cb, @@ -2106,6 +2133,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 +2173,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);