diff mbox

[2/3] geometry detection: use HDIO_GETGEO

Message ID 1335448165-26174-3-git-send-email-borntraeger@de.ibm.com
State New
Headers show

Commit Message

Christian Borntraeger April 26, 2012, 1:49 p.m. UTC
From: Einar Lueck <elelueck@de.ibm.com>

This patch uses ioctl HDIO_GETGEO to guess geometry of a disk in
case nothing is specified explicitly.

Signed-off-by: Einar Lueck <elelueck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 block.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

Comments

Alexander Graf April 26, 2012, 2:39 p.m. UTC | #1
On 26.04.2012, at 15:49, Christian Borntraeger wrote:

> From: Einar Lueck <elelueck@de.ibm.com>
> 
> This patch uses ioctl HDIO_GETGEO to guess geometry of a disk in
> case nothing is specified explicitly.
> 
> Signed-off-by: Einar Lueck <elelueck@de.ibm.com>
> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
> block.c |   12 ++++++++++++
> 1 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/block.c b/block.c
> index fe74ddd..8af4d19 100644
> --- a/block.c
> +++ b/block.c
> @@ -32,6 +32,10 @@
> #include "qmp-commands.h"
> #include "qemu-timer.h"
> 
> +#ifdef __linux__
> +#include <linux/hdreg.h>
> +#endif
> +
> #ifdef CONFIG_BSD
> #include <sys/types.h>
> #include <sys/stat.h>
> @@ -2054,6 +2058,7 @@ void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *pse
>     int translation, lba_detected = 0;
>     int cylinders, heads, secs;
>     uint64_t nb_sectors;
> +    struct hd_geometry geo;

This one certainly belongs in the block below, otherwise you get an unused variable warning (== error) on other OSs.


Alex

> 
>     /* if a geometry hint is available, use it */
>     bdrv_get_geometry(bs, &nb_sectors);
> @@ -2063,6 +2068,13 @@ void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *pse
>         *pcyls = cylinders;
>         *pheads = heads;
>         *psecs = secs;
> +#ifdef __linux__
> +    } else if (bdrv_ioctl(bs, HDIO_GETGEO, &geo) == 0) {
> +        *pcyls = geo.cylinders;
> +        *pheads = geo.heads;
> +        *psecs = geo.sectors;
> +        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
> +#endif
>     } else {
>         if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
>             if (heads > 16) {
> -- 
> 1.7.0.1
>
Paolo Bonzini April 27, 2012, 4:12 p.m. UTC | #2
Il 26/04/2012 15:49, Christian Borntraeger ha scritto:
> +#ifdef __linux__
> +    } else if (bdrv_ioctl(bs, HDIO_GETGEO, &geo) == 0) {
> +        *pcyls = geo.cylinders;
> +        *pheads = geo.heads;
> +        *psecs = geo.sectors;
> +        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
> +#endif

Perhaps you could instead move guess_disk_lchs to target-specific code,
adding add this code to the s390-specific implementation and under
#ifdef __s390__.  For x86 it doesn't make much sense, because a disk's
geometry most likely will be a wrong guess for the geometry that a guest
(for guests that care at all about geometries).

Paolo
Christian Borntraeger May 2, 2012, 10:27 a.m. UTC | #3
On 27/04/12 18:12, Paolo Bonzini wrote:
> Il 26/04/2012 15:49, Christian Borntraeger ha scritto:
>> +#ifdef __linux__
>> +    } else if (bdrv_ioctl(bs, HDIO_GETGEO, &geo) == 0) {
>> +        *pcyls = geo.cylinders;
>> +        *pheads = geo.heads;
>> +        *psecs = geo.sectors;
>> +        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
>> +#endif
> 
> Perhaps you could instead move guess_disk_lchs to target-specific code,
> adding add this code to the s390-specific implementation and under
> #ifdef __s390__.  For x86 it doesn't make much sense, because a disk's
> geometry most likely will be a wrong guess for the geometry that a guest
> (for guests that care at all about geometries).

Fine with me. We care about the geometry only for dasd devices, Even for FCP-based
SCSI devices on s390 the geometry is not relevant. So moving that part to 
s390 specific code might make sense if nobody else needs that.
Is that the case?
Alex, would that be ok for you?

Christian
Alexander Graf May 2, 2012, 11:09 a.m. UTC | #4
On 05/02/2012 12:27 PM, Christian Borntraeger wrote:
> On 27/04/12 18:12, Paolo Bonzini wrote:
>> Il 26/04/2012 15:49, Christian Borntraeger ha scritto:
>>> +#ifdef __linux__
>>> +    } else if (bdrv_ioctl(bs, HDIO_GETGEO,&geo) == 0) {
>>> +        *pcyls = geo.cylinders;
>>> +        *pheads = geo.heads;
>>> +        *psecs = geo.sectors;
>>> +        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
>>> +#endif
>> Perhaps you could instead move guess_disk_lchs to target-specific code,
>> adding add this code to the s390-specific implementation and under
>> #ifdef __s390__.  For x86 it doesn't make much sense, because a disk's
>> geometry most likely will be a wrong guess for the geometry that a guest
>> (for guests that care at all about geometries).
> Fine with me. We care about the geometry only for dasd devices, Even for FCP-based
> SCSI devices on s390 the geometry is not relevant. So moving that part to
> s390 specific code might make sense if nobody else needs that.
> Is that the case?
> Alex, would that be ok for you?

As hinted in my other mail, I think the way to go would be to give a 
hint to the geometry code that we're running on a DASD disk. Then we can

   * Ask the host device if it can give us its geometry, if so, use it
   * Guess depending on the logical block size

and everyone should be happy :). I would really like to have as little 
#ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is even worse, as 
it means we won't be able to execise that code path on other architectures.


Alex
Paolo Bonzini May 2, 2012, 11:26 a.m. UTC | #5
> and everyone should be happy :). I would really like to have as
> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is even worse,
> as it means we won't be able to execise that code path on other
> architectures.

True, but how do you exercise that code path with DASD geometry
on !__s390__?

Paolo
Alexander Graf May 2, 2012, 11:35 a.m. UTC | #6
On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
>> and everyone should be happy :). I would really like to have as
>> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is even worse,
>> as it means we won't be able to execise that code path on other
>> architectures.
> True, but how do you exercise that code path with DASD geometry
> on !__s390__?

If we make things a flag for the guessing code, it should work just as 
well with image files, right?


Alex
Paolo Bonzini May 2, 2012, 11:38 a.m. UTC | #7
> On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
> >> and everyone should be happy :). I would really like to have as
> >> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is
> >> even worse,
> >> as it means we won't be able to execise that code path on other
> >> architectures.
> > True, but how do you exercise that code path with DASD geometry
> > on !__s390__?
> 
> If we make things a flag for the guessing code, it should work just
> as well with image files, right?

Only when they're not blank. :)  I was only thinking of #ifdef __s390__
for the call to HDIO_GETGEO.

Paolo
Christian Borntraeger May 2, 2012, 11:56 a.m. UTC | #8
> As hinted in my other mail, I think the way to go would be to give a hint to the geometry code that we're running on a DASD disk..

Just as an idea if we are going that path, 
we might use the BIODASDINFO2 or DASDAPIVER ioctls in qemu to detect if that is a dasd.

Christian
Alexander Graf May 2, 2012, 12:54 p.m. UTC | #9
On 05/02/2012 01:38 PM, Paolo Bonzini wrote:
>> On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
>>>> and everyone should be happy :). I would really like to have as
>>>> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is
>>>> even worse,
>>>> as it means we won't be able to execise that code path on other
>>>> architectures.
>>> True, but how do you exercise that code path with DASD geometry
>>> on !__s390__?
>> If we make things a flag for the guessing code, it should work just
>> as well with image files, right?
> Only when they're not blank. :)  I was only thinking of #ifdef __s390__
> for the call to HDIO_GETGEO.

Well, if guessing is a function

   guess_size(disk_size, block_size)

then we would be able to do the same on an image file. Christian, would 
that work?


Alex
Christian Borntraeger May 2, 2012, 2:27 p.m. UTC | #10
On 02/05/12 14:54, Alexander Graf wrote:
> On 05/02/2012 01:38 PM, Paolo Bonzini wrote:
>>> On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
>>>>> and everyone should be happy :). I would really like to have as
>>>>> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is
>>>>> even worse,
>>>>> as it means we won't be able to execise that code path on other
>>>>> architectures.
>>>> True, but how do you exercise that code path with DASD geometry
>>>> on !__s390__?
>>> If we make things a flag for the guessing code, it should work just
>>> as well with image files, right?
>> Only when they're not blank. :)  I was only thinking of #ifdef __s390__
>> for the call to HDIO_GETGEO.
> 
> Well, if guessing is a function
> 
>   guess_size(disk_size, block_size)
> 
> then we would be able to do the same on an image file. Christian, would that work?

I think that the geometry values can not always be guessed correctly based on
block_size and disk_size.

Stefan, can you clarify that?

If we cannot reliably guess the geometry based on blocksize and size, I still think
that we should use the host values, e.g. after checking that BIODASDINFO2 returns 
successfully.

Christian
Alexander Graf May 2, 2012, 3:05 p.m. UTC | #11
On 02.05.2012, at 16:27, Christian Borntraeger <borntraeger@de.ibm.com> wrote:

> On 02/05/12 14:54, Alexander Graf wrote:
>> On 05/02/2012 01:38 PM, Paolo Bonzini wrote:
>>>> On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
>>>>>> and everyone should be happy :). I would really like to have as
>>>>>> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is
>>>>>> even worse,
>>>>>> as it means we won't be able to execise that code path on other
>>>>>> architectures.
>>>>> True, but how do you exercise that code path with DASD geometry
>>>>> on !__s390__?
>>>> If we make things a flag for the guessing code, it should work just
>>>> as well with image files, right?
>>> Only when they're not blank. :)  I was only thinking of #ifdef __s390__
>>> for the call to HDIO_GETGEO.
>> 
>> Well, if guessing is a function
>> 
>>  guess_size(disk_size, block_size)
>> 
>> then we would be able to do the same on an image file. Christian, would that work?
> 
> I think that the geometry values can not always be guessed correctly based on
> block_size and disk_size.
> 
> Stefan, can you clarify that?
> 
> If we cannot reliably guess the geometry based on blocksize and size, I still think
> that we should use the host values, e.g. after checking that BIODASDINFO2 returns 
> successfully.

Yeah, but only if it's always possible to force a specific geometry through the command line - otherwise reproducability suffers.


Alex
Stefan Weinhuber May 2, 2012, 3:57 p.m. UTC | #12
On 2012-05-02 16:27, Christian Borntraeger wrote:
> On 02/05/12 14:54, Alexander Graf wrote:
>> On 05/02/2012 01:38 PM, Paolo Bonzini wrote:
>>>> On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
>>>>>> and everyone should be happy :). I would really like to have as
>>>>>> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is
>>>>>> even worse,
>>>>>> as it means we won't be able to execise that code path on other
>>>>>> architectures.
>>>>> True, but how do you exercise that code path with DASD geometry
>>>>> on !__s390__?
>>>> If we make things a flag for the guessing code, it should work just
>>>> as well with image files, right?
>>> Only when they're not blank. :)  I was only thinking of #ifdef __s390__
>>> for the call to HDIO_GETGEO.
>>
>> Well, if guessing is a function
>>
>>    guess_size(disk_size, block_size)
>>
>> then we would be able to do the same on an image file. Christian, would that work?
>
> I think that the geometry values can not always be guessed correctly based on
> block_size and disk_size.
>
> Stefan, can you clarify that?
>
> If we cannot reliably guess the geometry based on blocksize and size, I still think
> that we should use the host values, e.g. after checking that BIODASDINFO2 returns
> successfully.

If we know the device type (e.g. 3390) and the block_size, then we can 
compute the number of blocks per track. The number of tracks per 
cylinder is a given (15) and the number of cylinders can be computed 
from these numbers and the disk_size.

How do we get the device type? I think we could get away with 
restricting ECKD DASDs to type 3390, but even then, how would we 
distinguish an ECKD DASD from anything else, e.g. a SCSI device?

We could simply attempt the above cylinder calculation for every device 
and if we get a result without a remainder we just assume that we have a 
DASD. This could lead to false positives, but maybe that is acceptable?

Stefan Weinhuber
Alexander Graf May 2, 2012, 6:39 p.m. UTC | #13
On 02.05.2012, at 17:57, Stefan Weinhuber <wein@linux.vnet.ibm.com> wrote:

> On 2012-05-02 16:27, Christian Borntraeger wrote:
>> On 02/05/12 14:54, Alexander Graf wrote:
>>> On 05/02/2012 01:38 PM, Paolo Bonzini wrote:
>>>>> On 05/02/2012 01:26 PM, Paolo Bonzini wrote:
>>>>>>> and everyone should be happy :). I would really like to have as
>>>>>>> little #ifdef TARGET_S390 code in QEMU. And #ifdef __s390__ is
>>>>>>> even worse,
>>>>>>> as it means we won't be able to execise that code path on other
>>>>>>> architectures.
>>>>>> True, but how do you exercise that code path with DASD geometry
>>>>>> on !__s390__?
>>>>> If we make things a flag for the guessing code, it should work just
>>>>> as well with image files, right?
>>>> Only when they're not blank. :)  I was only thinking of #ifdef __s390__
>>>> for the call to HDIO_GETGEO.
>>> 
>>> Well, if guessing is a function
>>> 
>>>   guess_size(disk_size, block_size)
>>> 
>>> then we would be able to do the same on an image file. Christian, would that work?
>> 
>> I think that the geometry values can not always be guessed correctly based on
>> block_size and disk_size.
>> 
>> Stefan, can you clarify that?
>> 
>> If we cannot reliably guess the geometry based on blocksize and size, I still think
>> that we should use the host values, e.g. after checking that BIODASDINFO2 returns
>> successfully.
> 
> If we know the device type (e.g. 3390) and the block_size, then we can compute the number of blocks per track. The number of tracks per cylinder is a given (15) and the number of cylinders can be computed from these numbers and the disk_size.
> 
> How do we get the device type? I think we could get away with restricting ECKD DASDs to type 3390, but even then, how would we distinguish an ECKD DASD from anything else, e.g. a SCSI device?
> 
> We could simply attempt the above cylinder calculation for every device and if we get a result without a remainder we just assume that we have a DASD. This could lead to false positives, but maybe that is acceptable?

We could add a parameter to the disk configuration like type=dasd (default would be type=auto) which tells the geometry detection code to assume a 3390. If type == auto, we try a dasd ioctl and if that works use type=dasd.

That way you could easily create a dump of the disk and get it working with a simple type=dasd. Later we could even add dasd disk label detection code which defaults type=auto to dasd if it finds one.

That way disk images should be as easy to use as real dasd devices :).


Alex
Christian Borntraeger May 2, 2012, 6:49 p.m. UTC | #14
>>> Well, if guessing is a function
>>>
>>>  guess_size(disk_size, block_size)
>>>
>>> then we would be able to do the same on an image file. Christian, would that work?
>>
>> I think that the geometry values can not always be guessed correctly based on
>> block_size and disk_size.
>>
>> Stefan, can you clarify that?
>>
>> If we cannot reliably guess the geometry based on blocksize and size, I still think
>> that we should use the host values, e.g. after checking that BIODASDINFO2 returns 
>> successfully.
> 
> Yeah, but only if it's always possible to force a specific geometry through the command line - otherwise reproducability suffers.

That is already possible, with the exception of the sector part of the geometry (see the other
patch :-) )

Christian
diff mbox

Patch

diff --git a/block.c b/block.c
index fe74ddd..8af4d19 100644
--- a/block.c
+++ b/block.c
@@ -32,6 +32,10 @@ 
 #include "qmp-commands.h"
 #include "qemu-timer.h"
 
+#ifdef __linux__
+#include <linux/hdreg.h>
+#endif
+
 #ifdef CONFIG_BSD
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -2054,6 +2058,7 @@  void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *pse
     int translation, lba_detected = 0;
     int cylinders, heads, secs;
     uint64_t nb_sectors;
+    struct hd_geometry geo;
 
     /* if a geometry hint is available, use it */
     bdrv_get_geometry(bs, &nb_sectors);
@@ -2063,6 +2068,13 @@  void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *pse
         *pcyls = cylinders;
         *pheads = heads;
         *psecs = secs;
+#ifdef __linux__
+    } else if (bdrv_ioctl(bs, HDIO_GETGEO, &geo) == 0) {
+        *pcyls = geo.cylinders;
+        *pheads = geo.heads;
+        *psecs = geo.sectors;
+        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
+#endif
     } else {
         if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
             if (heads > 16) {