diff options
author | Allen Pais <allen.pais@oracle.com> | 2014-09-19 17:42:26 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-01 01:37:35 +0400 |
commit | de5b73f08468b4fc5e2f6d1505f650262622f78b (patch) | |
tree | 816a637bb63a32c37b87b1624b25aa76c4d18d91 /drivers/block/sunvdc.c | |
parent | 9bce21828d54a95143f1b74619705c2dd8e88b92 (diff) | |
download | linux-de5b73f08468b4fc5e2f6d1505f650262622f78b.tar.xz |
sunvdc: compute vdisk geometry from capacity
The LDom diskserver doesn't return reliable geometry data. In addition,
the types for all fields in the vio_disk_geom are u16, which were being
truncated in the cast into the u8's of the Linux struct hd_geometry.
Modify vdc_getgeo() to compute the geometry from the disk's capacity in a
manner consistent with xen-blkfront::blkif_getgeo().
Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/block/sunvdc.c')
-rw-r--r-- | drivers/block/sunvdc.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 66ddf704ad7f..1616ad091a5e 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -70,7 +70,6 @@ struct vdc_port { char disk_name[32]; - struct vio_disk_geom geom; struct vio_disk_vtoc label; }; @@ -103,11 +102,15 @@ static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr) static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) { struct gendisk *disk = bdev->bd_disk; - struct vdc_port *port = disk->private_data; + sector_t nsect = get_capacity(disk); + sector_t cylinders = nsect; - geo->heads = (u8) port->geom.num_hd; - geo->sectors = (u8) port->geom.num_sec; - geo->cylinders = port->geom.num_cyl; + geo->heads = 0xff; + geo->sectors = 0x3f; + sector_div(cylinders, geo->heads * geo->sectors); + geo->cylinders = cylinders; + if ((sector_t)(geo->cylinders + 1) * geo->heads * geo->sectors < nsect) + geo->cylinders = 0xffff; return 0; } @@ -714,16 +717,18 @@ static int probe_disk(struct vdc_port *port) if (port->vdisk_size == -1) return -ENODEV; } else { + struct vio_disk_geom geom; + err = generic_request(port, VD_OP_GET_DISKGEOM, - &port->geom, sizeof(port->geom)); + &geom, sizeof(geom)); if (err < 0) { printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " "error %d\n", err); return err; } - port->vdisk_size = ((u64)port->geom.num_cyl * - (u64)port->geom.num_hd * - (u64)port->geom.num_sec); + port->vdisk_size = ((u64)geom.num_cyl * + (u64)geom.num_hd * + (u64)geom.num_sec); } q = blk_init_queue(do_vdc_request, &port->vio.lock); |