From patchwork Mon Aug 13 10:10:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Freimann X-Patchwork-Id: 176900 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 6B99E2C007C for ; Mon, 13 Aug 2012 20:19:55 +1000 (EST) Received: from localhost ([::1]:41581 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T0rkX-0001z8-Df for incoming@patchwork.ozlabs.org; Mon, 13 Aug 2012 06:19:53 -0400 Received: from eggs.gnu.org ([208.118.235.92]:46767) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T0rkN-0001yv-Na for qemu-devel@nongnu.org; Mon, 13 Aug 2012 06:19:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T0rkM-0002gX-6y for qemu-devel@nongnu.org; Mon, 13 Aug 2012 06:19:43 -0400 Received: from e06smtp14.uk.ibm.com ([195.75.94.110]:40262) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T0rkL-0002gR-S5 for qemu-devel@nongnu.org; Mon, 13 Aug 2012 06:19:42 -0400 Received: from /spool/local by e06smtp14.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 13 Aug 2012 11:19:39 +0100 Received: from b06cxnps3074.portsmouth.uk.ibm.com (9.149.109.194) by e06smtp14.uk.ibm.com (192.168.101.144) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 13 Aug 2012 11:19:37 +0100 Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by b06cxnps3074.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q7DAJVfp20971592 for ; Mon, 13 Aug 2012 10:19:31 GMT Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q7DAJZtc002703 for ; Mon, 13 Aug 2012 04:19:36 -0600 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q7DAJY6q002651; Mon, 13 Aug 2012 04:19:35 -0600 Received: by tuxmaker.boeblingen.de.ibm.com (Postfix, from userid 1122) id C4866122443C; Mon, 13 Aug 2012 12:11:05 +0200 (CEST) From: Jens Freimann To: Alexander Graf Date: Mon, 13 Aug 2012 12:10:49 +0200 Message-Id: <1344852649-36981-3-git-send-email-jfrei@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1344852649-36981-1-git-send-email-jfrei@linux.vnet.ibm.com> References: <1344852649-36981-1-git-send-email-jfrei@linux.vnet.ibm.com> x-cbid: 12081310-1948-0000-0000-000002A83F32 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 195.75.94.110 Cc: Heinz Graalfs , qemu-devel , Christian Borntraeger , Jens Freimann , Cornelia Huck , Paolo Bonzini , Stefan Weinhuber , Einar Lueck Subject: [Qemu-devel] [PATCH 2/2] hd-geometry.c: Integrate HDIO_GETGEO in guessing 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 From: Einar Lueck This patch extends the function guess_disk_lchs. If no geo could be derived from reading disk content, HDIO_GETGEO ioctl is issued. If this is not successful (e.g. image files) geometry is derived from the size of the disk (as before). To achieve this, the MSDOS partition table reading logic and the translation computation logic have been moved into a separate function guess_disk_msdosgeo. The HDIO_GETGEO logic is captured in a new function guess_disk_ioctlgeo. guess_disk_lchs then encapsulates both (the overall guessing logic). The new HDIO_GETGEO logic is required for two use cases: a) Support for geometries of Direct Attached Storage Disks (DASD) on s390x configured as backing of virtio block devices. b) Support for FCP attached SCSI disks that do not yet have a partition table. Without this patch, fdisk -l on the host would return different results then fdisk -l in the guest. Signed-off-by: Einar Lueck Signed-off-by: Jens Freimann --- hw/hd-geometry.c | 118 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 37 deletions(-) diff --git a/hw/hd-geometry.c b/hw/hd-geometry.c index 1cdb9fb..fc29075 100644 --- a/hw/hd-geometry.c +++ b/hw/hd-geometry.c @@ -33,6 +33,10 @@ #include "block.h" #include "hw/block-common.h" #include "trace.h" +#ifdef __linux__ +#include +#include +#endif struct partition { uint8_t boot_ind; /* 0x80 - active */ @@ -47,13 +51,59 @@ struct partition { uint32_t nr_sects; /* nr of sectors in partition */ } QEMU_PACKED; +static void guess_chs_for_size(BlockDriverState *bs, + uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs) +{ + uint64_t nb_sectors; + int cylinders; + + bdrv_get_geometry(bs, &nb_sectors); + + cylinders = nb_sectors / (16 * 63); + if (cylinders > 16383) { + cylinders = 16383; + } else if (cylinders < 2) { + cylinders = 2; + } + *pcyls = cylinders; + *pheads = 16; + *psecs = 63; +} + +/* try to get geometry from disk via HDIO_GETGEO ioctl + Return 0 if OK, -1 if ioctl does not work (e.g. image file) */ +static inline int guess_disk_ioctlgeo(BlockDriverState *bs, + uint32_t *pcylinders, uint32_t *pheads, + uint32_t *psectors, int *ptranslation) +{ +#ifdef __linux__ + struct hd_geometry geo; + + if (bdrv_ioctl(bs, HDIO_GETGEO, &geo)) { + return -1; + } + + *pheads = geo.heads; + *psectors = geo.sectors; + *pcylinders = geo.cylinders; + *ptranslation = BIOS_ATA_TRANSLATION_NONE; + trace_hd_geometry_lchs_guess(bs, *pcylinders, *pheads, *psectors); + return 0; +#else + return -1; +#endif +} + + /* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */ -static int guess_disk_lchs(BlockDriverState *bs, - int *pcylinders, int *pheads, int *psectors) +static int guess_disk_msdosgeo(BlockDriverState *bs, + uint32_t *pcylinders, uint32_t *pheads, + uint32_t *psectors, int *ptranslation) { uint8_t buf[BDRV_SECTOR_SIZE]; - int i, heads, sectors, cylinders; + int i, translation; + uint32_t heads, sectors, cylinders; struct partition *p; uint32_t nr_sects; uint64_t nb_sectors; @@ -87,9 +137,26 @@ static int guess_disk_lchs(BlockDriverState *bs, if (cylinders < 1 || cylinders > 16383) { continue; } + + if (heads > 16) { + /* LCHS guess with heads > 16 means that a BIOS LBA + translation was active, so a standard physical disk + geometry is OK */ + guess_chs_for_size(bs, &cylinders, &heads, §ors); + translation = cylinders * heads <= 131072 + ? BIOS_ATA_TRANSLATION_LARGE + : BIOS_ATA_TRANSLATION_LBA; + } else { + /* LCHS guess with heads <= 16: use as physical geometry */ + /* disable any translation to be in sync with + the logical geometry */ + translation = BIOS_ATA_TRANSLATION_NONE; + } *pheads = heads; *psectors = sectors; *pcylinders = cylinders; + *ptranslation = translation; + trace_hd_geometry_lchs_guess(bs, cylinders, heads, sectors); return 0; } @@ -97,51 +164,28 @@ static int guess_disk_lchs(BlockDriverState *bs, return -1; } -static void guess_chs_for_size(BlockDriverState *bs, - uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs) -{ - uint64_t nb_sectors; - int cylinders; - - bdrv_get_geometry(bs, &nb_sectors); - - cylinders = nb_sectors / (16 * 63); - if (cylinders > 16383) { - cylinders = 16383; - } else if (cylinders < 2) { - cylinders = 2; +/* try to guess the disk logical geometry + Return 0 if OK, -1 if could not guess */ +static int guess_disk_lchs(BlockDriverState *bs, + uint32_t *pcylinders, uint32_t *pheads, + uint32_t *psectors, int *ptranslation) { + if (!guess_disk_msdosgeo(bs, pcylinders, pheads, psectors, ptranslation)) { + return 0; } - *pcyls = cylinders; - *pheads = 16; - *psecs = 63; + + return guess_disk_ioctlgeo(bs, pcylinders, pheads, psectors, ptranslation); } void hd_geometry_guess(BlockDriverState *bs, uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs, int *ptrans) { - int cylinders, heads, secs, translation; + int translation; - if (guess_disk_lchs(bs, &cylinders, &heads, &secs) < 0) { + if (guess_disk_lchs(bs, pcyls, pheads, psecs, &translation) < 0) { /* no LCHS guess: use a standard physical disk geometry */ guess_chs_for_size(bs, pcyls, pheads, psecs); translation = hd_bios_chs_auto_trans(*pcyls, *pheads, *psecs); - } else if (heads > 16) { - /* LCHS guess with heads > 16 means that a BIOS LBA - translation was active, so a standard physical disk - geometry is OK */ - guess_chs_for_size(bs, pcyls, pheads, psecs); - translation = *pcyls * *pheads <= 131072 - ? BIOS_ATA_TRANSLATION_LARGE - : BIOS_ATA_TRANSLATION_LBA; - } else { - /* LCHS guess with heads <= 16: use as physical geometry */ - *pcyls = cylinders; - *pheads = heads; - *psecs = secs; - /* disable any translation to be in sync with - the logical geometry */ - translation = BIOS_ATA_TRANSLATION_NONE; } if (ptrans) { *ptrans = translation;