aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllen Pais <allen.pais@oracle.com>2014-09-19 09:42:26 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-30 17:37:35 -0400
commitde5b73f08468b4fc5e2f6d1505f650262622f78b (patch)
tree816a637bb63a32c37b87b1624b25aa76c4d18d91
parent9bce21828d54a95143f1b74619705c2dd8e88b92 (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.c23
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)
103static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) 102static 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);