From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:59694) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tthz4-0007i7-5k for qemu-devel@nongnu.org; Fri, 11 Jan 2013 12:01:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tthyx-00008R-6H for qemu-devel@nongnu.org; Fri, 11 Jan 2013 12:01:34 -0500 Received: from e06smtp18.uk.ibm.com ([195.75.94.114]:50652) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tthyw-00008J-Um for qemu-devel@nongnu.org; Fri, 11 Jan 2013 12:01:27 -0500 Received: from /spool/local by e06smtp18.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 11 Jan 2013 17:00:21 -0000 Received: from d06av08.portsmouth.uk.ibm.com (d06av08.portsmouth.uk.ibm.com [9.149.37.249]) by b06cxnps4074.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r0BH1ELl917916 for ; Fri, 11 Jan 2013 17:01:14 GMT Received: from d06av08.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av08.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r0BH1MQ5013391 for ; Fri, 11 Jan 2013 10:01:22 -0700 From: Einar Lueck Date: Fri, 11 Jan 2013 18:01:00 +0100 Message-Id: <1357923660-35202-2-git-send-email-elelueck@linux.vnet.ibm.com> In-Reply-To: <1357923660-35202-1-git-send-email-elelueck@linux.vnet.ibm.com> References: <1357923660-35202-1-git-send-email-elelueck@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH V2] hd-geometry.c: Integrate HDIO_GETGEO in guessing List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: kwolf@redhat.com, stefanha@gmail.com Cc: aliguori@us.ibm.com, agraf@suse.de, qemu-devel@nongnu.org, Christian Borntraeger , Jens Freimann , cornelia.huck@de.ibm.com, pbonzini@redhat.com, Einar Lueck This patch extends the function hd_geometry_guess. If no geo could be guessed via guess_disk_lchs, a new function called guess_disk_pchs is called. The latter utilizes HDIO_GET_GEO ioctl to ask the underlying disk for geometry. If this is not successful (e.g. image files) geometry is derived from the size of the disk (as before). 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 Reviewed-by: Carsten Otte Signed-off-by: Christian Borntraeger --- hw/hd-geometry.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/hw/hd-geometry.c b/hw/hd-geometry.c index c305143..d35e25f 100644 --- a/hw/hd-geometry.c +++ b/hw/hd-geometry.c @@ -33,6 +33,10 @@ #include "block/block.h" #include "hw/block-common.h" #include "trace.h" +#ifdef __linux__ +#include +#include +#endif struct partition { uint8_t boot_ind; /* 0x80 - active */ @@ -47,6 +51,39 @@ 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); + +/* 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_pchs(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; + } + + /* HDIO_GETGEO may return success even though geo contains zeros + (e.g. certain multipath setups) */ + if (!geo.heads || !geo.sectors || !geo.cylinders) { + return -1; + } + + *pheads = geo.heads; + *psectors = geo.sectors; + *pcylinders = geo.cylinders; + *ptranslation = BIOS_ATA_TRANSLATION_NONE; + 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, @@ -123,9 +160,11 @@ void hd_geometry_guess(BlockDriverState *bs, int cylinders, heads, secs, translation; if (guess_disk_lchs(bs, &cylinders, &heads, &secs) < 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); + if (guess_disk_pchs(bs, pcyls, pheads, psecs, &translation) < 0) { + /* no LCHS and no PCHS 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 -- 1.7.12.4