diff options
author | Allen Pais <allen.pais@oracle.com> | 2014-09-19 09:42:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-30 17:37:35 -0400 |
commit | de5b73f08468b4fc5e2f6d1505f650262622f78b (patch) | |
tree | 816a637bb63a32c37b87b1624b25aa76c4d18d91 | |
parent | 9bce21828d54a95143f1b74619705c2dd8e88b92 (diff) |
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>
-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 { | |||
70 | 70 | ||
71 | char disk_name[32]; | 71 | char disk_name[32]; |
72 | 72 | ||
73 | struct vio_disk_geom geom; | ||
74 | struct vio_disk_vtoc label; | 73 | struct vio_disk_vtoc label; |
75 | }; | 74 | }; |
76 | 75 | ||
@@ -103,11 +102,15 @@ static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr) | |||
103 | static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) | 102 | static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
104 | { | 103 | { |
105 | struct gendisk *disk = bdev->bd_disk; | 104 | struct gendisk *disk = bdev->bd_disk; |
106 | struct vdc_port *port = disk->private_data; | 105 | sector_t nsect = get_capacity(disk); |
106 | sector_t cylinders = nsect; | ||
107 | 107 | ||
108 | geo->heads = (u8) port->geom.num_hd; | 108 | geo->heads = 0xff; |
109 | geo->sectors = (u8) port->geom.num_sec; | 109 | geo->sectors = 0x3f; |
110 | geo->cylinders = port->geom.num_cyl; | 110 | sector_div(cylinders, geo->heads * geo->sectors); |
111 | geo->cylinders = cylinders; | ||
112 | if ((sector_t)(geo->cylinders + 1) * geo->heads * geo->sectors < nsect) | ||
113 | geo->cylinders = 0xffff; | ||
111 | 114 | ||
112 | return 0; | 115 | return 0; |
113 | } | 116 | } |
@@ -714,16 +717,18 @@ static int probe_disk(struct vdc_port *port) | |||
714 | if (port->vdisk_size == -1) | 717 | if (port->vdisk_size == -1) |
715 | return -ENODEV; | 718 | return -ENODEV; |
716 | } else { | 719 | } else { |
720 | struct vio_disk_geom geom; | ||
721 | |||
717 | err = generic_request(port, VD_OP_GET_DISKGEOM, | 722 | err = generic_request(port, VD_OP_GET_DISKGEOM, |
718 | &port->geom, sizeof(port->geom)); | 723 | &geom, sizeof(geom)); |
719 | if (err < 0) { | 724 | if (err < 0) { |
720 | printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " | 725 | printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " |
721 | "error %d\n", err); | 726 | "error %d\n", err); |
722 | return err; | 727 | return err; |
723 | } | 728 | } |
724 | port->vdisk_size = ((u64)port->geom.num_cyl * | 729 | port->vdisk_size = ((u64)geom.num_cyl * |
725 | (u64)port->geom.num_hd * | 730 | (u64)geom.num_hd * |
726 | (u64)port->geom.num_sec); | 731 | (u64)geom.num_sec); |
727 | } | 732 | } |
728 | 733 | ||
729 | q = blk_init_queue(do_vdc_request, &port->vio.lock); | 734 | q = blk_init_queue(do_vdc_request, &port->vio.lock); |