aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-01-08 04:02:50 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-08 23:13:54 -0500
commita885c8c4316e1c1d2d2c8755da3f3d14f852528d (patch)
treee4f4e7a7657c0944d11c259f8f17ffcd6b2da0f5
parent5b0ed2c64d8fdafb5fcfb3baabdd288628b1ff9b (diff)
[PATCH] Add block_device_operations.getgeo block device method
HDIO_GETGEO is implemented in most block drivers, and all of them have to duplicate the code to copy the structure to userspace, as well as getting the start sector. This patch moves that to common code [1] and adds a ->getgeo method to fill out the raw kernel hd_geometry structure. For many drivers this means ->ioctl can go away now. [1] the s390 block drivers are odd in this respect. xpram sets ->start to 4 always which seems more than odd, and the dasd driver shifts the start offset around, probably because of it's non-standard sector size. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Jens Axboe <axboe@suse.de> Cc: <mike.miller@hp.com> Cc: Jeff Dike <jdike@addtoit.com> Cc: Paolo Giarrusso <blaisorblade@yahoo.it> Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl> Cc: Neil Brown <neilb@cse.unsw.edu.au> Cc: Markus Lidel <Markus.Lidel@shadowconnect.com> Cc: Russell King <rmk@arm.linux.org.uk> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: James Bottomley <James.Bottomley@steeleye.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/um/drivers/ubd_kern.c21
-rw-r--r--block/ioctl.c22
-rw-r--r--drivers/acorn/block/mfmhd.c36
-rw-r--r--drivers/block/DAC960.c35
-rw-r--r--drivers/block/acsi.c26
-rw-r--r--drivers/block/amiflop.c23
-rw-r--r--drivers/block/aoe/aoeblk.c26
-rw-r--r--drivers/block/cciss.c31
-rw-r--r--drivers/block/cpqarray.c36
-rw-r--r--drivers/block/floppy.c35
-rw-r--r--drivers/block/paride/pd.c34
-rw-r--r--drivers/block/paride/pf.c50
-rw-r--r--drivers/block/ps2esdi.c25
-rw-r--r--drivers/block/sx8.c35
-rw-r--r--drivers/block/umem.c41
-rw-r--r--drivers/block/viodasd.c44
-rw-r--r--drivers/block/xd.c25
-rw-r--r--drivers/ide/ide-disk.c12
-rw-r--r--drivers/ide/ide-floppy.c12
-rw-r--r--drivers/ide/ide.c13
-rw-r--r--drivers/ide/legacy/hd.c24
-rw-r--r--drivers/md/md.c30
-rw-r--r--drivers/message/i2o/i2o_block.c18
-rw-r--r--drivers/mmc/mmc_block.c25
-rw-r--r--drivers/mtd/mtd_blkdevs.c25
-rw-r--r--drivers/s390/block/dasd.c23
-rw-r--r--drivers/s390/block/dasd_ioctl.c28
-rw-r--r--drivers/s390/block/xpram.c18
-rw-r--r--drivers/scsi/sd.c21
-rw-r--r--include/linux/fs.h2
30 files changed, 340 insertions, 456 deletions
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 73f9652b2ee9..3a93c6f772fa 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -117,6 +117,7 @@ static int ubd_open(struct inode * inode, struct file * filp);
117static int ubd_release(struct inode * inode, struct file * file); 117static int ubd_release(struct inode * inode, struct file * file);
118static int ubd_ioctl(struct inode * inode, struct file * file, 118static int ubd_ioctl(struct inode * inode, struct file * file,
119 unsigned int cmd, unsigned long arg); 119 unsigned int cmd, unsigned long arg);
120static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
120 121
121#define MAX_DEV (8) 122#define MAX_DEV (8)
122 123
@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
125 .open = ubd_open, 126 .open = ubd_open,
126 .release = ubd_release, 127 .release = ubd_release,
127 .ioctl = ubd_ioctl, 128 .ioctl = ubd_ioctl,
129 .getgeo = ubd_getgeo,
128}; 130};
129 131
130/* Protected by the queue_lock */ 132/* Protected by the queue_lock */
@@ -1058,6 +1060,16 @@ static void do_ubd_request(request_queue_t *q)
1058 } 1060 }
1059} 1061}
1060 1062
1063static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1064{
1065 struct ubd *dev = bdev->bd_disk->private_data;
1066
1067 geo->heads = 128;
1068 geo->sectors = 32;
1069 geo->cylinders = dev->size / (128 * 32 * 512);
1070 return 0;
1071}
1072
1061static int ubd_ioctl(struct inode * inode, struct file * file, 1073static int ubd_ioctl(struct inode * inode, struct file * file,
1062 unsigned int cmd, unsigned long arg) 1074 unsigned int cmd, unsigned long arg)
1063{ 1075{
@@ -1070,16 +1082,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
1070 }; 1082 };
1071 1083
1072 switch (cmd) { 1084 switch (cmd) {
1073 struct hd_geometry g;
1074 struct cdrom_volctrl volume; 1085 struct cdrom_volctrl volume;
1075 case HDIO_GETGEO:
1076 if(!loc) return(-EINVAL);
1077 g.heads = 128;
1078 g.sectors = 32;
1079 g.cylinders = dev->size / (128 * 32 * 512);
1080 g.start = get_start_sect(inode->i_bdev);
1081 return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
1082
1083 case HDIO_GET_IDENTITY: 1086 case HDIO_GET_IDENTITY:
1084 ubd_id.cyls = dev->size / (128 * 32 * 512); 1087 ubd_id.cyls = dev->size / (128 * 32 * 512);
1085 if(copy_to_user((char __user *) arg, (char *) &ubd_id, 1088 if(copy_to_user((char __user *) arg, (char *) &ubd_id,
diff --git a/block/ioctl.c b/block/ioctl.c
index 6e278474f9a8..82030e1dfd63 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -1,6 +1,7 @@
1#include <linux/sched.h> /* for capable() */ 1#include <linux/sched.h> /* for capable() */
2#include <linux/blkdev.h> 2#include <linux/blkdev.h>
3#include <linux/blkpg.h> 3#include <linux/blkpg.h>
4#include <linux/hdreg.h>
4#include <linux/backing-dev.h> 5#include <linux/backing-dev.h>
5#include <linux/buffer_head.h> 6#include <linux/buffer_head.h>
6#include <linux/smp_lock.h> 7#include <linux/smp_lock.h>
@@ -245,6 +246,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
245 set_device_ro(bdev, n); 246 set_device_ro(bdev, n);
246 unlock_kernel(); 247 unlock_kernel();
247 return 0; 248 return 0;
249 case HDIO_GETGEO: {
250 struct hd_geometry geo;
251
252 if (!arg)
253 return -EINVAL;
254 if (!disk->fops->getgeo)
255 return -ENOTTY;
256
257 /*
258 * We need to set the startsect first, the driver may
259 * want to override it.
260 */
261 geo.start = get_start_sect(bdev);
262 ret = disk->fops->getgeo(bdev, &geo);
263 if (ret)
264 return ret;
265 if (copy_to_user((struct hd_geometry __user *)arg, &geo,
266 sizeof(geo)))
267 return -EFAULT;
268 return 0;
269 }
248 } 270 }
249 271
250 lock_kernel(); 272 lock_kernel();
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 4b65f74d66b1..ce074f6f3369 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock);
129#define MAJOR_NR MFM_ACORN_MAJOR 129#define MAJOR_NR MFM_ACORN_MAJOR
130#define QUEUE (mfm_queue) 130#define QUEUE (mfm_queue)
131#define CURRENT elv_next_request(mfm_queue) 131#define CURRENT elv_next_request(mfm_queue)
132/*
133 * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
134 */
135#ifndef HDIO_GETGEO
136#define HDIO_GETGEO 0x301
137struct hd_geometry {
138 unsigned char heads;
139 unsigned char sectors;
140 unsigned short cylinders;
141 unsigned long start;
142};
143#endif
144
145 132
146/* 133/*
147 * Configuration section 134 * Configuration section
@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void)
1153 * The 'front' end of the mfm driver follows... 1140 * The 'front' end of the mfm driver follows...
1154 */ 1141 */
1155 1142
1156static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) 1143static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1157{ 1144{
1158 struct mfm_info *p = inode->i_bdev->bd_disk->private_data; 1145 struct mfm_info *p = bdev->bd_disk->private_data;
1159 struct hd_geometry *geo = (struct hd_geometry *) arg; 1146
1160 if (cmd != HDIO_GETGEO) 1147 geo->heads = p->heads;
1161 return -EINVAL; 1148 geo->sectors = p->sectors;
1162 if (!arg) 1149 geo->cylinders = p->cylinders;
1163 return -EINVAL;
1164 if (put_user (p->heads, &geo->heads))
1165 return -EFAULT;
1166 if (put_user (p->sectors, &geo->sectors))
1167 return -EFAULT;
1168 if (put_user (p->cylinders, &geo->cylinders))
1169 return -EFAULT;
1170 if (put_user (get_start_sect(inode->i_bdev), &geo->start))
1171 return -EFAULT;
1172 return 0; 1150 return 0;
1173} 1151}
1174 1152
@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
1219static struct block_device_operations mfm_fops = 1197static struct block_device_operations mfm_fops =
1220{ 1198{
1221 .owner = THIS_MODULE, 1199 .owner = THIS_MODULE,
1222 .ioctl = mfm_ioctl, 1200 .getgeo = mfm_getgeo,
1223}; 1201};
1224 1202
1225/* 1203/*
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 21097a39a057..179c68a3cef3 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
92 return 0; 92 return 0;
93} 93}
94 94
95static int DAC960_ioctl(struct inode *inode, struct file *file, 95static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
96 unsigned int cmd, unsigned long arg)
97{ 96{
98 struct gendisk *disk = inode->i_bdev->bd_disk; 97 struct gendisk *disk = bdev->bd_disk;
99 DAC960_Controller_T *p = disk->queue->queuedata; 98 DAC960_Controller_T *p = disk->queue->queuedata;
100 int drive_nr = (long)disk->private_data; 99 int drive_nr = (long)disk->private_data;
101 struct hd_geometry g;
102 struct hd_geometry __user *loc = (struct hd_geometry __user *)arg;
103
104 if (cmd != HDIO_GETGEO || !loc)
105 return -EINVAL;
106 100
107 if (p->FirmwareType == DAC960_V1_Controller) { 101 if (p->FirmwareType == DAC960_V1_Controller) {
108 g.heads = p->V1.GeometryTranslationHeads; 102 geo->heads = p->V1.GeometryTranslationHeads;
109 g.sectors = p->V1.GeometryTranslationSectors; 103 geo->sectors = p->V1.GeometryTranslationSectors;
110 g.cylinders = p->V1.LogicalDriveInformation[drive_nr]. 104 geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
111 LogicalDriveSize / (g.heads * g.sectors); 105 LogicalDriveSize / (geo->heads * geo->sectors);
112 } else { 106 } else {
113 DAC960_V2_LogicalDeviceInfo_T *i = 107 DAC960_V2_LogicalDeviceInfo_T *i =
114 p->V2.LogicalDeviceInformation[drive_nr]; 108 p->V2.LogicalDeviceInformation[drive_nr];
115 switch (i->DriveGeometry) { 109 switch (i->DriveGeometry) {
116 case DAC960_V2_Geometry_128_32: 110 case DAC960_V2_Geometry_128_32:
117 g.heads = 128; 111 geo->heads = 128;
118 g.sectors = 32; 112 geo->sectors = 32;
119 break; 113 break;
120 case DAC960_V2_Geometry_255_63: 114 case DAC960_V2_Geometry_255_63:
121 g.heads = 255; 115 geo->heads = 255;
122 g.sectors = 63; 116 geo->sectors = 63;
123 break; 117 break;
124 default: 118 default:
125 DAC960_Error("Illegal Logical Device Geometry %d\n", 119 DAC960_Error("Illegal Logical Device Geometry %d\n",
@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
127 return -EINVAL; 121 return -EINVAL;
128 } 122 }
129 123
130 g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors); 124 geo->cylinders = i->ConfigurableDeviceSize /
125 (geo->heads * geo->sectors);
131 } 126 }
132 127
133 g.start = get_start_sect(inode->i_bdev); 128 return 0;
134
135 return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
136} 129}
137 130
138static int DAC960_media_changed(struct gendisk *disk) 131static int DAC960_media_changed(struct gendisk *disk)
@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
157static struct block_device_operations DAC960_BlockDeviceOperations = { 150static struct block_device_operations DAC960_BlockDeviceOperations = {
158 .owner = THIS_MODULE, 151 .owner = THIS_MODULE,
159 .open = DAC960_open, 152 .open = DAC960_open,
160 .ioctl = DAC960_ioctl, 153 .getgeo = DAC960_getgeo,
161 .media_changed = DAC960_media_changed, 154 .media_changed = DAC960_media_changed,
162 .revalidate_disk = DAC960_revalidate_disk, 155 .revalidate_disk = DAC960_revalidate_disk,
163}; 156};
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 5d2d649f7e8d..196c0ec9cd54 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void )
1079 * 1079 *
1080 ***********************************************************************/ 1080 ***********************************************************************/
1081 1081
1082static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1083{
1084 struct acsi_info_struct *aip = bdev->bd_disk->private_data;
1085
1086 /*
1087 * Just fake some geometry here, it's nonsense anyway
1088 * To make it easy, use Adaptec's usual 64/32 mapping
1089 */
1090 geo->heads = 64;
1091 geo->sectors = 32;
1092 geo->cylinders = aip->size >> 11;
1093 return 0;
1094}
1082 1095
1083static int acsi_ioctl( struct inode *inode, struct file *file, 1096static int acsi_ioctl( struct inode *inode, struct file *file,
1084 unsigned int cmd, unsigned long arg ) 1097 unsigned int cmd, unsigned long arg )
@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
1086 struct gendisk *disk = inode->i_bdev->bd_disk; 1099 struct gendisk *disk = inode->i_bdev->bd_disk;
1087 struct acsi_info_struct *aip = disk->private_data; 1100 struct acsi_info_struct *aip = disk->private_data;
1088 switch (cmd) { 1101 switch (cmd) {
1089 case HDIO_GETGEO:
1090 /* HDIO_GETGEO is supported more for getting the partition's
1091 * start sector... */
1092 { struct hd_geometry *geo = (struct hd_geometry *)arg;
1093 /* just fake some geometry here, it's nonsense anyway; to make it
1094 * easy, use Adaptec's usual 64/32 mapping */
1095 put_user( 64, &geo->heads );
1096 put_user( 32, &geo->sectors );
1097 put_user( aip->size >> 11, &geo->cylinders );
1098 put_user(get_start_sect(inode->i_bdev), &geo->start);
1099 return 0;
1100 }
1101 case SCSI_IOCTL_GET_IDLUN: 1102 case SCSI_IOCTL_GET_IDLUN:
1102 /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */ 1103 /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
1103 put_user( aip->target | (aip->lun << 8), 1104 put_user( aip->target | (aip->lun << 8),
@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = {
1592 .open = acsi_open, 1593 .open = acsi_open,
1593 .release = acsi_release, 1594 .release = acsi_release,
1594 .ioctl = acsi_ioctl, 1595 .ioctl = acsi_ioctl,
1596 .getgeo = acsi_getgeo,
1595 .media_changed = acsi_media_change, 1597 .media_changed = acsi_media_change,
1596 .revalidate_disk= acsi_revalidate, 1598 .revalidate_disk= acsi_revalidate,
1597}; 1599};
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 0acbfff8ad28..cb2a545e57dc 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1424,6 +1424,16 @@ static void do_fd_request(request_queue_t * q)
1424 redo_fd_request(); 1424 redo_fd_request();
1425} 1425}
1426 1426
1427static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1428{
1429 int drive = MINOR(bdev->bd_dev) & 3;
1430
1431 geo->heads = unit[drive].type->heads;
1432 geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
1433 geo->cylinders = unit[drive].type->tracks;
1434 return 0;
1435}
1436
1427static int fd_ioctl(struct inode *inode, struct file *filp, 1437static int fd_ioctl(struct inode *inode, struct file *filp,
1428 unsigned int cmd, unsigned long param) 1438 unsigned int cmd, unsigned long param)
1429{ 1439{
@@ -1431,18 +1441,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
1431 static struct floppy_struct getprm; 1441 static struct floppy_struct getprm;
1432 1442
1433 switch(cmd){ 1443 switch(cmd){
1434 case HDIO_GETGEO:
1435 {
1436 struct hd_geometry loc;
1437 loc.heads = unit[drive].type->heads;
1438 loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
1439 loc.cylinders = unit[drive].type->tracks;
1440 loc.start = 0;
1441 if (copy_to_user((void *)param, (void *)&loc,
1442 sizeof(struct hd_geometry)))
1443 return -EFAULT;
1444 break;
1445 }
1446 case FDFMTBEG: 1444 case FDFMTBEG:
1447 get_fdc(drive); 1445 get_fdc(drive);
1448 if (fd_ref[drive] > 1) { 1446 if (fd_ref[drive] > 1) {
@@ -1652,6 +1650,7 @@ static struct block_device_operations floppy_fops = {
1652 .open = floppy_open, 1650 .open = floppy_open,
1653 .release = floppy_release, 1651 .release = floppy_release,
1654 .ioctl = fd_ioctl, 1652 .ioctl = fd_ioctl,
1653 .getgeo = fd_getgeo,
1655 .media_changed = amiga_floppy_change, 1654 .media_changed = amiga_floppy_change,
1656}; 1655};
1657 1656
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 0e97fcb9f3a1..c05ee8bffd97 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
169 return 0; 169 return 0;
170} 170}
171 171
172/* This ioctl implementation expects userland to have the device node
173 * permissions set so that only priviledged users can open an aoe
174 * block device directly.
175 */
176static int 172static int
177aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg) 173aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
178{ 174{
179 struct aoedev *d; 175 struct aoedev *d = bdev->bd_disk->private_data;
180
181 if (!arg)
182 return -EINVAL;
183 176
184 d = inode->i_bdev->bd_disk->private_data;
185 if ((d->flags & DEVFL_UP) == 0) { 177 if ((d->flags & DEVFL_UP) == 0) {
186 printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); 178 printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
187 return -ENODEV; 179 return -ENODEV;
188 } 180 }
189 181
190 if (cmd == HDIO_GETGEO) { 182 geo->cylinders = d->geo.cylinders;
191 d->geo.start = get_start_sect(inode->i_bdev); 183 geo->heads = d->geo.heads;
192 if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo)) 184 geo->sectors = d->geo.sectors;
193 return 0; 185 return 0;
194 return -EFAULT;
195 }
196 printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
197 return -EINVAL;
198} 186}
199 187
200static struct block_device_operations aoe_bdops = { 188static struct block_device_operations aoe_bdops = {
201 .open = aoeblk_open, 189 .open = aoeblk_open,
202 .release = aoeblk_release, 190 .release = aoeblk_release,
203 .ioctl = aoeblk_ioctl, 191 .getgeo = aoeblk_getgeo,
204 .owner = THIS_MODULE, 192 .owner = THIS_MODULE,
205}; 193};
206 194
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index d2815b7a9150..bdb9c2717d40 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep);
153static int cciss_release(struct inode *inode, struct file *filep); 153static int cciss_release(struct inode *inode, struct file *filep);
154static int cciss_ioctl(struct inode *inode, struct file *filep, 154static int cciss_ioctl(struct inode *inode, struct file *filep,
155 unsigned int cmd, unsigned long arg); 155 unsigned int cmd, unsigned long arg);
156static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
156 157
157static int revalidate_allvol(ctlr_info_t *host); 158static int revalidate_allvol(ctlr_info_t *host);
158static int cciss_revalidate(struct gendisk *disk); 159static int cciss_revalidate(struct gendisk *disk);
@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = {
194 .open = cciss_open, 195 .open = cciss_open,
195 .release = cciss_release, 196 .release = cciss_release,
196 .ioctl = cciss_ioctl, 197 .ioctl = cciss_ioctl,
198 .getgeo = cciss_getgeo,
197#ifdef CONFIG_COMPAT 199#ifdef CONFIG_COMPAT
198 .compat_ioctl = cciss_compat_ioctl, 200 .compat_ioctl = cciss_compat_ioctl,
199#endif 201#endif
@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
633 return err; 635 return err;
634} 636}
635#endif 637#endif
638
639static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
640{
641 drive_info_struct *drv = get_drv(bdev->bd_disk);
642
643 if (!drv->cylinders)
644 return -ENXIO;
645
646 geo->heads = drv->heads;
647 geo->sectors = drv->sectors;
648 geo->cylinders = drv->cylinders;
649 return 0;
650}
651
636/* 652/*
637 * ioctl 653 * ioctl
638 */ 654 */
@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
651#endif /* CCISS_DEBUG */ 667#endif /* CCISS_DEBUG */
652 668
653 switch(cmd) { 669 switch(cmd) {
654 case HDIO_GETGEO:
655 {
656 struct hd_geometry driver_geo;
657 if (drv->cylinders) {
658 driver_geo.heads = drv->heads;
659 driver_geo.sectors = drv->sectors;
660 driver_geo.cylinders = drv->cylinders;
661 } else
662 return -ENXIO;
663 driver_geo.start= get_start_sect(inode->i_bdev);
664 if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry)))
665 return -EFAULT;
666 return(0);
667 }
668
669 case CCISS_GETPCIINFO: 670 case CCISS_GETPCIINFO:
670 { 671 {
671 cciss_pci_info_struct pciinfo; 672 cciss_pci_info_struct pciinfo;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 9bddb6874873..9f0664dd3800 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -160,6 +160,7 @@ static int sendcmd(
160static int ida_open(struct inode *inode, struct file *filep); 160static int ida_open(struct inode *inode, struct file *filep);
161static int ida_release(struct inode *inode, struct file *filep); 161static int ida_release(struct inode *inode, struct file *filep);
162static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); 162static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
163static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
163static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io); 164static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
164 165
165static void do_ida_request(request_queue_t *q); 166static void do_ida_request(request_queue_t *q);
@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = {
199 .open = ida_open, 200 .open = ida_open,
200 .release = ida_release, 201 .release = ida_release,
201 .ioctl = ida_ioctl, 202 .ioctl = ida_ioctl,
203 .getgeo = ida_getgeo,
202 .revalidate_disk= ida_revalidate, 204 .revalidate_disk= ida_revalidate,
203}; 205};
204 206
@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata)
1124 h->misc_tflags = 0; 1126 h->misc_tflags = 0;
1125} 1127}
1126 1128
1129static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1130{
1131 drv_info_t *drv = get_drv(bdev->bd_disk);
1132
1133 if (drv->cylinders) {
1134 geo->heads = drv->heads;
1135 geo->sectors = drv->sectors;
1136 geo->cylinders = drv->cylinders;
1137 } else {
1138 geo->heads = 0xff;
1139 geo->sectors = 0x3f;
1140 geo->cylinders = drv->nr_blks / (0xff*0x3f);
1141 }
1142
1143 return 0;
1144}
1145
1127/* 1146/*
1128 * ida_ioctl does some miscellaneous stuff like reporting drive geometry, 1147 * ida_ioctl does some miscellaneous stuff like reporting drive geometry,
1129 * setting readahead and submitting commands from userspace to the controller. 1148 * setting readahead and submitting commands from userspace to the controller.
@@ -1133,27 +1152,10 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
1133 drv_info_t *drv = get_drv(inode->i_bdev->bd_disk); 1152 drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
1134 ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); 1153 ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
1135 int error; 1154 int error;
1136 int diskinfo[4];
1137 struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
1138 ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg; 1155 ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
1139 ida_ioctl_t *my_io; 1156 ida_ioctl_t *my_io;
1140 1157
1141 switch(cmd) { 1158 switch(cmd) {
1142 case HDIO_GETGEO:
1143 if (drv->cylinders) {
1144 diskinfo[0] = drv->heads;
1145 diskinfo[1] = drv->sectors;
1146 diskinfo[2] = drv->cylinders;
1147 } else {
1148 diskinfo[0] = 0xff;
1149 diskinfo[1] = 0x3f;
1150 diskinfo[2] = drv->nr_blks / (0xff*0x3f);
1151 }
1152 put_user(diskinfo[0], &geo->heads);
1153 put_user(diskinfo[1], &geo->sectors);
1154 put_user(diskinfo[2], &geo->cylinders);
1155 put_user(get_start_sect(inode->i_bdev), &geo->start);
1156 return 0;
1157 case IDAGETDRVINFO: 1159 case IDAGETDRVINFO:
1158 if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t))) 1160 if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
1159 return -EFAULT; 1161 return -EFAULT;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index a5b857c5c4b8..b86613b21cf1 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3445,6 +3445,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
3445 return 0; 3445 return 0;
3446} 3446}
3447 3447
3448static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3449{
3450 int drive = (long)bdev->bd_disk->private_data;
3451 int type = ITYPE(drive_state[drive].fd_device);
3452 struct floppy_struct *g;
3453 int ret;
3454
3455 ret = get_floppy_geometry(drive, type, &g);
3456 if (ret)
3457 return ret;
3458
3459 geo->heads = g->head;
3460 geo->sectors = g->sect;
3461 geo->cylinders = g->track;
3462 return 0;
3463}
3464
3448static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 3465static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
3449 unsigned long param) 3466 unsigned long param)
3450{ 3467{
@@ -3474,23 +3491,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
3474 cmd = FDEJECT; 3491 cmd = FDEJECT;
3475 } 3492 }
3476 3493
3477 /* generic block device ioctls */
3478 switch (cmd) {
3479 /* the following have been inspired by the corresponding
3480 * code for other block devices. */
3481 struct floppy_struct *g;
3482 case HDIO_GETGEO:
3483 {
3484 struct hd_geometry loc;
3485 ECALL(get_floppy_geometry(drive, type, &g));
3486 loc.heads = g->head;
3487 loc.sectors = g->sect;
3488 loc.cylinders = g->track;
3489 loc.start = 0;
3490 return _COPYOUT(loc);
3491 }
3492 }
3493
3494 /* convert the old style command into a new style command */ 3494 /* convert the old style command into a new style command */
3495 if ((cmd & 0xff00) == 0x0200) { 3495 if ((cmd & 0xff00) == 0x0200) {
3496 ECALL(normalize_ioctl(&cmd, &size)); 3496 ECALL(normalize_ioctl(&cmd, &size));
@@ -3938,6 +3938,7 @@ static struct block_device_operations floppy_fops = {
3938 .open = floppy_open, 3938 .open = floppy_open,
3939 .release = floppy_release, 3939 .release = floppy_release,
3940 .ioctl = fd_ioctl, 3940 .ioctl = fd_ioctl,
3941 .getgeo = fd_getgeo,
3941 .media_changed = check_floppy_change, 3942 .media_changed = check_floppy_change,
3942 .revalidate_disk = floppy_revalidate, 3943 .revalidate_disk = floppy_revalidate,
3943}; 3944};
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index fa49d62626ba..62d2464c12f2 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file)
747 return 0; 747 return 0;
748} 748}
749 749
750static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
751{
752 struct pd_unit *disk = bdev->bd_disk->private_data;
753
754 if (disk->alt_geom) {
755 geo->heads = PD_LOG_HEADS;
756 geo->sectors = PD_LOG_SECTS;
757 geo->cylinders = disk->capacity / (geo->heads * geo->sectors);
758 } else {
759 geo->heads = disk->heads;
760 geo->sectors = disk->sectors;
761 geo->cylinders = disk->cylinders;
762 }
763
764 return 0;
765}
766
750static int pd_ioctl(struct inode *inode, struct file *file, 767static int pd_ioctl(struct inode *inode, struct file *file,
751 unsigned int cmd, unsigned long arg) 768 unsigned int cmd, unsigned long arg)
752{ 769{
753 struct pd_unit *disk = inode->i_bdev->bd_disk->private_data; 770 struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
754 struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
755 struct hd_geometry g;
756 771
757 switch (cmd) { 772 switch (cmd) {
758 case CDROMEJECT: 773 case CDROMEJECT:
759 if (disk->access == 1) 774 if (disk->access == 1)
760 pd_special_command(disk, pd_eject); 775 pd_special_command(disk, pd_eject);
761 return 0; 776 return 0;
762 case HDIO_GETGEO:
763 if (disk->alt_geom) {
764 g.heads = PD_LOG_HEADS;
765 g.sectors = PD_LOG_SECTS;
766 g.cylinders = disk->capacity / (g.heads * g.sectors);
767 } else {
768 g.heads = disk->heads;
769 g.sectors = disk->sectors;
770 g.cylinders = disk->cylinders;
771 }
772 g.start = get_start_sect(inode->i_bdev);
773 if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
774 return -EFAULT;
775 return 0;
776 default: 777 default:
777 return -EINVAL; 778 return -EINVAL;
778 } 779 }
@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = {
815 .open = pd_open, 816 .open = pd_open,
816 .release = pd_release, 817 .release = pd_release,
817 .ioctl = pd_ioctl, 818 .ioctl = pd_ioctl,
819 .getgeo = pd_getgeo,
818 .media_changed = pd_check_media, 820 .media_changed = pd_check_media,
819 .revalidate_disk= pd_revalidate 821 .revalidate_disk= pd_revalidate
820}; 822};
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index e9746af29b9f..852b564e903a 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file);
205static void do_pf_request(request_queue_t * q); 205static void do_pf_request(request_queue_t * q);
206static int pf_ioctl(struct inode *inode, struct file *file, 206static int pf_ioctl(struct inode *inode, struct file *file,
207 unsigned int cmd, unsigned long arg); 207 unsigned int cmd, unsigned long arg);
208static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
208 209
209static int pf_release(struct inode *inode, struct file *file); 210static int pf_release(struct inode *inode, struct file *file);
210 211
@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = {
266 .open = pf_open, 267 .open = pf_open,
267 .release = pf_release, 268 .release = pf_release,
268 .ioctl = pf_ioctl, 269 .ioctl = pf_ioctl,
270 .getgeo = pf_getgeo,
269 .media_changed = pf_check_media, 271 .media_changed = pf_check_media,
270}; 272};
271 273
@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file)
313 return 0; 315 return 0;
314} 316}
315 317
316static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 318static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
317{ 319{
318 struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; 320 struct pf_unit *pf = bdev->bd_disk->private_data;
319 struct hd_geometry __user *geo = (struct hd_geometry __user *) arg; 321 sector_t capacity = get_capacity(pf->disk);
320 struct hd_geometry g; 322
321 sector_t capacity;
322
323 if (cmd == CDROMEJECT) {
324 if (pf->access == 1) {
325 pf_eject(pf);
326 return 0;
327 }
328 return -EBUSY;
329 }
330 if (cmd != HDIO_GETGEO)
331 return -EINVAL;
332 capacity = get_capacity(pf->disk);
333 if (capacity < PF_FD_MAX) { 323 if (capacity < PF_FD_MAX) {
334 g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); 324 geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
335 g.heads = PF_FD_HDS; 325 geo->heads = PF_FD_HDS;
336 g.sectors = PF_FD_SPT; 326 geo->sectors = PF_FD_SPT;
337 } else { 327 } else {
338 g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); 328 geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
339 g.heads = PF_HD_HDS; 329 geo->heads = PF_HD_HDS;
340 g.sectors = PF_HD_SPT; 330 geo->sectors = PF_HD_SPT;
341 } 331 }
342 if (copy_to_user(geo, &g, sizeof(g))) 332
343 return -EFAULT; 333 return 0;
334}
335
336static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
337{
338 struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
339
340 if (cmd != CDROMEJECT)
341 return -EINVAL;
342
343 if (pf->access != 1)
344 return -EBUSY;
345 pf_eject(pf);
344 return 0; 346 return 0;
345} 347}
346 348
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 29d1518be72a..43415f69839f 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -81,8 +81,7 @@ static void (*current_int_handler) (u_int) = NULL;
81static void ps2esdi_normal_interrupt_handler(u_int); 81static void ps2esdi_normal_interrupt_handler(u_int);
82static void ps2esdi_initial_reset_int_handler(u_int); 82static void ps2esdi_initial_reset_int_handler(u_int);
83static void ps2esdi_geometry_int_handler(u_int); 83static void ps2esdi_geometry_int_handler(u_int);
84static int ps2esdi_ioctl(struct inode *inode, struct file *file, 84static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
85 u_int cmd, u_long arg);
86 85
87static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); 86static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
88 87
@@ -132,7 +131,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
132static struct block_device_operations ps2esdi_fops = 131static struct block_device_operations ps2esdi_fops =
133{ 132{
134 .owner = THIS_MODULE, 133 .owner = THIS_MODULE,
135 .ioctl = ps2esdi_ioctl, 134 .getgeo = ps2esdi_getgeo,
136}; 135};
137 136
138static struct gendisk *ps2esdi_gendisk[2]; 137static struct gendisk *ps2esdi_gendisk[2];
@@ -1058,21 +1057,13 @@ static void dump_cmd_complete_status(u_int int_ret_code)
1058 1057
1059} 1058}
1060 1059
1061static int ps2esdi_ioctl(struct inode *inode, 1060static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1062 struct file *file, u_int cmd, u_long arg)
1063{ 1061{
1064 struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data; 1062 struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
1065 struct ps2esdi_geometry geom; 1063
1066 1064 geo->heads = p->head;
1067 if (cmd != HDIO_GETGEO) 1065 geo->sectors = p->sect;
1068 return -EINVAL; 1066 geo->cylinders = p->cyl;
1069 memset(&geom, 0, sizeof(geom));
1070 geom.heads = p->head;
1071 geom.sectors = p->sect;
1072 geom.cylinders = p->cyl;
1073 geom.start = get_start_sect(inode->i_bdev);
1074 if (copy_to_user((void __user *)arg, &geom, sizeof(geom)))
1075 return -EFAULT;
1076 return 0; 1067 return 0;
1077} 1068}
1078 1069
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 9251f4131b53..c0cdc182a8b0 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -407,8 +407,7 @@ struct carm_array_info {
407 407
408static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); 408static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
409static void carm_remove_one (struct pci_dev *pdev); 409static void carm_remove_one (struct pci_dev *pdev);
410static int carm_bdev_ioctl(struct inode *ino, struct file *fil, 410static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo);
411 unsigned int cmd, unsigned long arg);
412 411
413static struct pci_device_id carm_pci_tbl[] = { 412static struct pci_device_id carm_pci_tbl[] = {
414 { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, 413 { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = {
426 425
427static struct block_device_operations carm_bd_ops = { 426static struct block_device_operations carm_bd_ops = {
428 .owner = THIS_MODULE, 427 .owner = THIS_MODULE,
429 .ioctl = carm_bdev_ioctl, 428 .getgeo = carm_bdev_getgeo,
430}; 429};
431 430
432static unsigned int carm_host_id; 431static unsigned int carm_host_id;
@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc;
434 433
435 434
436 435
437static int carm_bdev_ioctl(struct inode *ino, struct file *fil, 436static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
438 unsigned int cmd, unsigned long arg)
439{ 437{
440 void __user *usermem = (void __user *) arg; 438 struct carm_port *port = bdev->bd_disk->private_data;
441 struct carm_port *port = ino->i_bdev->bd_disk->private_data;
442 struct hd_geometry geom;
443 439
444 switch (cmd) { 440 geo->heads = (u8) port->dev_geom_head;
445 case HDIO_GETGEO: 441 geo->sectors = (u8) port->dev_geom_sect;
446 if (!usermem) 442 geo->cylinders = port->dev_geom_cyl;
447 return -EINVAL; 443 return 0;
448
449 geom.heads = (u8) port->dev_geom_head;
450 geom.sectors = (u8) port->dev_geom_sect;
451 geom.cylinders = port->dev_geom_cyl;
452 geom.start = get_start_sect(ino->i_bdev);
453
454 if (copy_to_user(usermem, &geom, sizeof(geom)))
455 return -EFAULT;
456 return 0;
457
458 default:
459 break;
460 }
461
462 return -EOPNOTSUPP;
463} 444}
464 445
465static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE }; 446static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 0f48301342da..15299e7a1ade 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk)
809 set_capacity(disk, card->mm_size << 1); 809 set_capacity(disk, card->mm_size << 1);
810 return 0; 810 return 0;
811} 811}
812/* 812
813----------------------------------------------------------------------------------- 813static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
814-- mm_ioctl
815-----------------------------------------------------------------------------------
816*/
817static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
818{ 814{
819 if (cmd == HDIO_GETGEO) { 815 struct cardinfo *card = bdev->bd_disk->private_data;
820 struct cardinfo *card = i->i_bdev->bd_disk->private_data; 816 int size = card->mm_size * (1024 / MM_HARDSECT);
821 int size = card->mm_size * (1024 / MM_HARDSECT);
822 struct hd_geometry geo;
823 /*
824 * get geometry: we have to fake one... trim the size to a
825 * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
826 * whatever cylinders.
827 */
828 geo.heads = 64;
829 geo.sectors = 32;
830 geo.start = get_start_sect(i->i_bdev);
831 geo.cylinders = size / (geo.heads * geo.sectors);
832
833 if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
834 return -EFAULT;
835 return 0;
836 }
837 817
838 return -EINVAL; 818 /*
819 * get geometry: we have to fake one... trim the size to a
820 * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
821 * whatever cylinders.
822 */
823 geo->heads = 64;
824 geo->sectors = 32;
825 geo->cylinders = size / (geo->heads * geo->sectors);
826 return 0;
839} 827}
828
840/* 829/*
841----------------------------------------------------------------------------------- 830-----------------------------------------------------------------------------------
842-- mm_check_change 831-- mm_check_change
@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk)
855*/ 844*/
856static struct block_device_operations mm_fops = { 845static struct block_device_operations mm_fops = {
857 .owner = THIS_MODULE, 846 .owner = THIS_MODULE,
858 .ioctl = mm_ioctl, 847 .getgeo = mm_getgeo,
859 .revalidate_disk= mm_revalidate, 848 .revalidate_disk= mm_revalidate,
860 .media_changed = mm_check_change, 849 .media_changed = mm_check_change,
861}; 850};
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 063f0304a163..d1aaf31bd97e 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil)
247 247
248/* External ioctl entry point. 248/* External ioctl entry point.
249 */ 249 */
250static int viodasd_ioctl(struct inode *ino, struct file *fil, 250static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
251 unsigned int cmd, unsigned long arg)
252{ 251{
253 unsigned char sectors; 252 struct gendisk *disk = bdev->bd_disk;
254 unsigned char heads; 253 struct viodasd_device *d = disk->private_data;
255 unsigned short cylinders;
256 struct hd_geometry *geo;
257 struct gendisk *gendisk;
258 struct viodasd_device *d;
259 254
260 switch (cmd) { 255 geo->sectors = d->sectors ? d->sectors : 0;
261 case HDIO_GETGEO: 256 geo->heads = d->tracks ? d->tracks : 64;
262 geo = (struct hd_geometry *)arg; 257 geo->cylinders = d->cylinders ? d->cylinders :
263 if (geo == NULL) 258 get_capacity(disk) / (geo->cylinders * geo->heads);
264 return -EINVAL;
265 if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo)))
266 return -EFAULT;
267 gendisk = ino->i_bdev->bd_disk;
268 d = gendisk->private_data;
269 sectors = d->sectors;
270 if (sectors == 0)
271 sectors = 32;
272 heads = d->tracks;
273 if (heads == 0)
274 heads = 64;
275 cylinders = d->cylinders;
276 if (cylinders == 0)
277 cylinders = get_capacity(gendisk) / (sectors * heads);
278 if (__put_user(sectors, &geo->sectors) ||
279 __put_user(heads, &geo->heads) ||
280 __put_user(cylinders, &geo->cylinders) ||
281 __put_user(get_start_sect(ino->i_bdev), &geo->start))
282 return -EFAULT;
283 return 0;
284 }
285 259
286 return -EINVAL; 260 return 0;
287} 261}
288 262
289/* 263/*
@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = {
293 .owner = THIS_MODULE, 267 .owner = THIS_MODULE,
294 .open = viodasd_open, 268 .open = viodasd_open,
295 .release = viodasd_release, 269 .release = viodasd_release,
296 .ioctl = viodasd_ioctl, 270 .getgeo = viodasd_getgeo,
297}; 271};
298 272
299/* 273/*
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 68b6d7b154cf..97f5dab24b5a 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock);
128 128
129static struct gendisk *xd_gendisk[2]; 129static struct gendisk *xd_gendisk[2];
130 130
131static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
132
131static struct block_device_operations xd_fops = { 133static struct block_device_operations xd_fops = {
132 .owner = THIS_MODULE, 134 .owner = THIS_MODULE,
133 .ioctl = xd_ioctl, 135 .ioctl = xd_ioctl,
136 .getgeo = xd_getgeo,
134}; 137};
135static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); 138static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
136static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors; 139static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
@@ -330,22 +333,20 @@ static void do_xd_request (request_queue_t * q)
330 } 333 }
331} 334}
332 335
336static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
337{
338 XD_INFO *p = bdev->bd_disk->private_data;
339
340 geo->heads = p->heads;
341 geo->sectors = p->sectors;
342 geo->cylinders = p->cylinders;
343 return 0;
344}
345
333/* xd_ioctl: handle device ioctl's */ 346/* xd_ioctl: handle device ioctl's */
334static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) 347static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
335{ 348{
336 XD_INFO *p = inode->i_bdev->bd_disk->private_data;
337
338 switch (cmd) { 349 switch (cmd) {
339 case HDIO_GETGEO:
340 {
341 struct hd_geometry g;
342 struct hd_geometry __user *geom= (void __user *)arg;
343 g.heads = p->heads;
344 g.sectors = p->sectors;
345 g.cylinders = p->cylinders;
346 g.start = get_start_sect(inode->i_bdev);
347 return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0;
348 }
349 case HDIO_SET_DMA: 350 case HDIO_SET_DMA:
350 if (!capable(CAP_SYS_ADMIN)) return -EACCES; 351 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
351 if (xdc_busy) return -EBUSY; 352 if (xdc_busy) return -EBUSY;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 4b441720b6ba..cab362ea0336 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1130,6 +1130,17 @@ static int idedisk_release(struct inode *inode, struct file *filp)
1130 return 0; 1130 return 0;
1131} 1131}
1132 1132
1133static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1134{
1135 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1136 ide_drive_t *drive = idkp->drive;
1137
1138 geo->heads = drive->bios_head;
1139 geo->sectors = drive->bios_sect;
1140 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
1141 return 0;
1142}
1143
1133static int idedisk_ioctl(struct inode *inode, struct file *file, 1144static int idedisk_ioctl(struct inode *inode, struct file *file,
1134 unsigned int cmd, unsigned long arg) 1145 unsigned int cmd, unsigned long arg)
1135{ 1146{
@@ -1164,6 +1175,7 @@ static struct block_device_operations idedisk_ops = {
1164 .open = idedisk_open, 1175 .open = idedisk_open,
1165 .release = idedisk_release, 1176 .release = idedisk_release,
1166 .ioctl = idedisk_ioctl, 1177 .ioctl = idedisk_ioctl,
1178 .getgeo = idedisk_getgeo,
1167 .media_changed = idedisk_media_changed, 1179 .media_changed = idedisk_media_changed,
1168 .revalidate_disk= idedisk_revalidate_disk 1180 .revalidate_disk= idedisk_revalidate_disk
1169}; 1181};
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index fba3fffc2d66..5945f551aaaa 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2031,6 +2031,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
2031 return 0; 2031 return 0;
2032} 2032}
2033 2033
2034static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
2035{
2036 struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
2037 ide_drive_t *drive = floppy->drive;
2038
2039 geo->heads = drive->bios_head;
2040 geo->sectors = drive->bios_sect;
2041 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
2042 return 0;
2043}
2044
2034static int idefloppy_ioctl(struct inode *inode, struct file *file, 2045static int idefloppy_ioctl(struct inode *inode, struct file *file,
2035 unsigned int cmd, unsigned long arg) 2046 unsigned int cmd, unsigned long arg)
2036{ 2047{
@@ -2120,6 +2131,7 @@ static struct block_device_operations idefloppy_ops = {
2120 .open = idefloppy_open, 2131 .open = idefloppy_open,
2121 .release = idefloppy_release, 2132 .release = idefloppy_release,
2122 .ioctl = idefloppy_ioctl, 2133 .ioctl = idefloppy_ioctl,
2134 .getgeo = idefloppy_getgeo,
2123 .media_changed = idefloppy_media_changed, 2135 .media_changed = idefloppy_media_changed,
2124 .revalidate_disk= idefloppy_revalidate_disk 2136 .revalidate_disk= idefloppy_revalidate_disk
2125}; 2137};
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 4b524f6b3ecd..b069b13b75a7 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
1278 up(&ide_setting_sem); 1278 up(&ide_setting_sem);
1279 1279
1280 switch (cmd) { 1280 switch (cmd) {
1281 case HDIO_GETGEO:
1282 {
1283 struct hd_geometry geom;
1284 if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
1285 geom.heads = drive->bios_head;
1286 geom.sectors = drive->bios_sect;
1287 geom.cylinders = (u16)drive->bios_cyl; /* truncate */
1288 geom.start = get_start_sect(bdev);
1289 if (copy_to_user(p, &geom, sizeof(struct hd_geometry)))
1290 return -EFAULT;
1291 return 0;
1292 }
1293
1294 case HDIO_OBSOLETE_IDENTITY: 1281 case HDIO_OBSOLETE_IDENTITY:
1295 case HDIO_GET_IDENTITY: 1282 case HDIO_GET_IDENTITY:
1296 if (bdev != bdev->bd_contains) 1283 if (bdev != bdev->bd_contains)
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 242029c9c0ca..6439dec66881 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q)
658 enable_irq(HD_IRQ); 658 enable_irq(HD_IRQ);
659} 659}
660 660
661static int hd_ioctl(struct inode * inode, struct file * file, 661static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
662 unsigned int cmd, unsigned long arg)
663{ 662{
664 struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; 663 struct hd_i_struct *disk = bdev->bd_disk->private_data;
665 struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; 664
666 struct hd_geometry g; 665 geo->heads = disk->head;
667 666 geo->sectors = disk->sect;
668 if (cmd != HDIO_GETGEO) 667 geo->cylinders = disk->cyl;
669 return -EINVAL; 668 return 0;
670 if (!loc)
671 return -EINVAL;
672 g.heads = disk->head;
673 g.sectors = disk->sect;
674 g.cylinders = disk->cyl;
675 g.start = get_start_sect(inode->i_bdev);
676 return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
677} 669}
678 670
679/* 671/*
@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
695} 687}
696 688
697static struct block_device_operations hd_fops = { 689static struct block_device_operations hd_fops = {
698 .ioctl = hd_ioctl, 690 .getgeo = hd_getgeo,
699}; 691};
700 692
701/* 693/*
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1b76fb29fb70..e423a16ba3c9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3598,12 +3598,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
3598 return 0; 3598 return 0;
3599} 3599}
3600 3600
3601static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3602{
3603 mddev_t *mddev = bdev->bd_disk->private_data;
3604
3605 geo->heads = 2;
3606 geo->sectors = 4;
3607 geo->cylinders = get_capacity(mddev->gendisk) / 8;
3608 return 0;
3609}
3610
3601static int md_ioctl(struct inode *inode, struct file *file, 3611static int md_ioctl(struct inode *inode, struct file *file,
3602 unsigned int cmd, unsigned long arg) 3612 unsigned int cmd, unsigned long arg)
3603{ 3613{
3604 int err = 0; 3614 int err = 0;
3605 void __user *argp = (void __user *)arg; 3615 void __user *argp = (void __user *)arg;
3606 struct hd_geometry __user *loc = argp;
3607 mddev_t *mddev = NULL; 3616 mddev_t *mddev = NULL;
3608 3617
3609 if (!capable(CAP_SYS_ADMIN)) 3618 if (!capable(CAP_SYS_ADMIN))
@@ -3765,24 +3774,6 @@ static int md_ioctl(struct inode *inode, struct file *file,
3765 * 4 sectors (with a BIG number of cylinders...). This drives 3774 * 4 sectors (with a BIG number of cylinders...). This drives
3766 * dosfs just mad... ;-) 3775 * dosfs just mad... ;-)
3767 */ 3776 */
3768 case HDIO_GETGEO:
3769 if (!loc) {
3770 err = -EINVAL;
3771 goto abort_unlock;
3772 }
3773 err = put_user (2, (char __user *) &loc->heads);
3774 if (err)
3775 goto abort_unlock;
3776 err = put_user (4, (char __user *) &loc->sectors);
3777 if (err)
3778 goto abort_unlock;
3779 err = put_user(get_capacity(mddev->gendisk)/8,
3780 (short __user *) &loc->cylinders);
3781 if (err)
3782 goto abort_unlock;
3783 err = put_user (get_start_sect(inode->i_bdev),
3784 (long __user *) &loc->start);
3785 goto done_unlock;
3786 } 3777 }
3787 3778
3788 /* 3779 /*
@@ -3911,6 +3902,7 @@ static struct block_device_operations md_fops =
3911 .open = md_open, 3902 .open = md_open,
3912 .release = md_release, 3903 .release = md_release,
3913 .ioctl = md_ioctl, 3904 .ioctl = md_ioctl,
3905 .getgeo = md_getgeo,
3914 .media_changed = md_media_changed, 3906 .media_changed = md_media_changed,
3915 .revalidate_disk= md_revalidate, 3907 .revalidate_disk= md_revalidate,
3916}; 3908};
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 5b1febed3133..b09fb6307153 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -662,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file)
662 return 0; 662 return 0;
663} 663}
664 664
665static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
666{
667 i2o_block_biosparam(get_capacity(bdev->bd_disk),
668 &geo->cylinders, &geo->heads, &geo->sectors);
669 return 0;
670}
671
665/** 672/**
666 * i2o_block_ioctl - Issue device specific ioctl calls. 673 * i2o_block_ioctl - Issue device specific ioctl calls.
667 * @cmd: ioctl command 674 * @cmd: ioctl command
@@ -676,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
676{ 683{
677 struct gendisk *disk = inode->i_bdev->bd_disk; 684 struct gendisk *disk = inode->i_bdev->bd_disk;
678 struct i2o_block_device *dev = disk->private_data; 685 struct i2o_block_device *dev = disk->private_data;
679 void __user *argp = (void __user *)arg;
680 686
681 /* Anyone capable of this syscall can do *real bad* things */ 687 /* Anyone capable of this syscall can do *real bad* things */
682 688
@@ -684,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
684 return -EPERM; 690 return -EPERM;
685 691
686 switch (cmd) { 692 switch (cmd) {
687 case HDIO_GETGEO:
688 {
689 struct hd_geometry g;
690 i2o_block_biosparam(get_capacity(disk),
691 &g.cylinders, &g.heads, &g.sectors);
692 g.start = get_start_sect(inode->i_bdev);
693 return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
694 }
695
696 case BLKI2OGRSTRAT: 693 case BLKI2OGRSTRAT:
697 return put_user(dev->rcache, (int __user *)arg); 694 return put_user(dev->rcache, (int __user *)arg);
698 case BLKI2OGWSTRAT: 695 case BLKI2OGWSTRAT:
@@ -962,6 +959,7 @@ static struct block_device_operations i2o_block_fops = {
962 .open = i2o_block_open, 959 .open = i2o_block_open,
963 .release = i2o_block_release, 960 .release = i2o_block_release,
964 .ioctl = i2o_block_ioctl, 961 .ioctl = i2o_block_ioctl,
962 .getgeo = i2o_block_getgeo,
965 .media_changed = i2o_block_media_changed 963 .media_changed = i2o_block_media_changed
966}; 964};
967 965
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 198561d21710..d5f28981596b 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -113,31 +113,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp)
113} 113}
114 114
115static int 115static int
116mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 116mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
117{ 117{
118 struct block_device *bdev = inode->i_bdev; 118 geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
119 119 geo->heads = 4;
120 if (cmd == HDIO_GETGEO) { 120 geo->sectors = 16;
121 struct hd_geometry geo; 121 return 0;
122
123 memset(&geo, 0, sizeof(struct hd_geometry));
124
125 geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
126 geo.heads = 4;
127 geo.sectors = 16;
128 geo.start = get_start_sect(bdev);
129
130 return copy_to_user((void __user *)arg, &geo, sizeof(geo))
131 ? -EFAULT : 0;
132 }
133
134 return -ENOTTY;
135} 122}
136 123
137static struct block_device_operations mmc_bdops = { 124static struct block_device_operations mmc_bdops = {
138 .open = mmc_blk_open, 125 .open = mmc_blk_open,
139 .release = mmc_blk_release, 126 .release = mmc_blk_release,
140 .ioctl = mmc_blk_ioctl, 127 .getgeo = mmc_blk_getgeo,
141 .owner = THIS_MODULE, 128 .owner = THIS_MODULE,
142}; 129};
143 130
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 339cb1218eaa..7f3ff500b68e 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f)
194 return ret; 194 return ret;
195} 195}
196 196
197static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
198{
199 struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
200
201 if (dev->tr->getgeo)
202 return dev->tr->getgeo(dev, geo);
203 return -ENOTTY;
204}
197 205
198static int blktrans_ioctl(struct inode *inode, struct file *file, 206static int blktrans_ioctl(struct inode *inode, struct file *file,
199 unsigned int cmd, unsigned long arg) 207 unsigned int cmd, unsigned long arg)
@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
207 return tr->flush(dev); 215 return tr->flush(dev);
208 /* The core code did the work, we had nothing to do. */ 216 /* The core code did the work, we had nothing to do. */
209 return 0; 217 return 0;
210
211 case HDIO_GETGEO:
212 if (tr->getgeo) {
213 struct hd_geometry g;
214 int ret;
215
216 memset(&g, 0, sizeof(g));
217 ret = tr->getgeo(dev, &g);
218 if (ret)
219 return ret;
220
221 g.start = get_start_sect(inode->i_bdev);
222 if (copy_to_user((void __user *)arg, &g, sizeof(g)))
223 return -EFAULT;
224 return 0;
225 } /* else */
226 default: 218 default:
227 return -ENOTTY; 219 return -ENOTTY;
228 } 220 }
@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = {
233 .open = blktrans_open, 225 .open = blktrans_open,
234 .release = blktrans_release, 226 .release = blktrans_release,
235 .ioctl = blktrans_ioctl, 227 .ioctl = blktrans_ioctl,
228 .getgeo = blktrans_getgeo,
236}; 229};
237 230
238int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) 231int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index f779f674dfa0..2472fa1a1be1 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -18,6 +18,7 @@
18#include <linux/major.h> 18#include <linux/major.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/buffer_head.h> 20#include <linux/buffer_head.h>
21#include <linux/hdreg.h>
21 22
22#include <asm/ccwdev.h> 23#include <asm/ccwdev.h>
23#include <asm/ebcdic.h> 24#include <asm/ebcdic.h>
@@ -1723,12 +1724,34 @@ dasd_release(struct inode *inp, struct file *filp)
1723 return 0; 1724 return 0;
1724} 1725}
1725 1726
1727/*
1728 * Return disk geometry.
1729 */
1730static int
1731dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1732{
1733 struct dasd_device *device;
1734
1735 device = bdev->bd_disk->private_data;
1736 if (!device)
1737 return -ENODEV;
1738
1739 if (!device->discipline ||
1740 !device->discipline->fill_geometry)
1741 return -EINVAL;
1742
1743 device->discipline->fill_geometry(device, geo);
1744 geo->start = get_start_sect(bdev) >> device->s2b_shift;
1745 return 0;
1746}
1747
1726struct block_device_operations 1748struct block_device_operations
1727dasd_device_operations = { 1749dasd_device_operations = {
1728 .owner = THIS_MODULE, 1750 .owner = THIS_MODULE,
1729 .open = dasd_open, 1751 .open = dasd_open,
1730 .release = dasd_release, 1752 .release = dasd_release,
1731 .ioctl = dasd_ioctl, 1753 .ioctl = dasd_ioctl,
1754 .getgeo = dasd_getgeo,
1732}; 1755};
1733 1756
1734 1757
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 044b75371990..8e4dcd58599e 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -486,33 +486,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
486} 486}
487 487
488/* 488/*
489 * Return disk geometry.
490 */
491static int
492dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
493{
494 struct hd_geometry geo = { 0, };
495 struct dasd_device *device;
496
497 device = bdev->bd_disk->private_data;
498 if (device == NULL)
499 return -ENODEV;
500
501 if (device == NULL || device->discipline == NULL ||
502 device->discipline->fill_geometry == NULL)
503 return -EINVAL;
504
505 geo = (struct hd_geometry) {};
506 device->discipline->fill_geometry(device, &geo);
507 geo.start = get_start_sect(bdev) >> device->s2b_shift;
508 if (copy_to_user((struct hd_geometry __user *) args, &geo,
509 sizeof (struct hd_geometry)))
510 return -EFAULT;
511
512 return 0;
513}
514
515/*
516 * List of static ioctls. 489 * List of static ioctls.
517 */ 490 */
518static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = 491static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
@@ -528,7 +501,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
528 { BIODASDPRRST, dasd_ioctl_reset_profile }, 501 { BIODASDPRRST, dasd_ioctl_reset_profile },
529 { BLKROSET, dasd_ioctl_set_ro }, 502 { BLKROSET, dasd_ioctl_set_ro },
530 { DASDAPIVER, dasd_ioctl_api_version }, 503 { DASDAPIVER, dasd_ioctl_api_version },
531 { HDIO_GETGEO, dasd_ioctl_getgeo },
532 { -1, NULL } 504 { -1, NULL }
533}; 505};
534 506
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index bf3a67c3cc5e..54ecd548c318 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -328,31 +328,27 @@ fail:
328 return 0; 328 return 0;
329} 329}
330 330
331static int xpram_ioctl (struct inode *inode, struct file *filp, 331static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
332 unsigned int cmd, unsigned long arg)
333{ 332{
334 struct hd_geometry __user *geo;
335 unsigned long size; 333 unsigned long size;
336 if (cmd != HDIO_GETGEO) 334
337 return -EINVAL;
338 /* 335 /*
339 * get geometry: we have to fake one... trim the size to a 336 * get geometry: we have to fake one... trim the size to a
340 * multiple of 64 (32k): tell we have 16 sectors, 4 heads, 337 * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
341 * whatever cylinders. Tell also that data starts at sector. 4. 338 * whatever cylinders. Tell also that data starts at sector. 4.
342 */ 339 */
343 geo = (struct hd_geometry __user *) arg;
344 size = (xpram_pages * 8) & ~0x3f; 340 size = (xpram_pages * 8) & ~0x3f;
345 put_user(size >> 6, &geo->cylinders); 341 geo->cylinders = size >> 6;
346 put_user(4, &geo->heads); 342 geo->heads = 4;
347 put_user(16, &geo->sectors); 343 geo->sectors = 16;
348 put_user(4, &geo->start); 344 geo->start = 4;
349 return 0; 345 return 0;
350} 346}
351 347
352static struct block_device_operations xpram_devops = 348static struct block_device_operations xpram_devops =
353{ 349{
354 .owner = THIS_MODULE, 350 .owner = THIS_MODULE,
355 .ioctl = xpram_ioctl, 351 .getgeo = xpram_getgeo,
356}; 352};
357 353
358/* 354/*
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 32d4d8d7b9f3..4c5127ed379c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -527,7 +527,7 @@ static int sd_release(struct inode *inode, struct file *filp)
527 return 0; 527 return 0;
528} 528}
529 529
530static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc) 530static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
531{ 531{
532 struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); 532 struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
533 struct scsi_device *sdp = sdkp->device; 533 struct scsi_device *sdp = sdkp->device;
@@ -545,15 +545,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *
545 else 545 else
546 scsicam_bios_param(bdev, sdkp->capacity, diskinfo); 546 scsicam_bios_param(bdev, sdkp->capacity, diskinfo);
547 547
548 if (put_user(diskinfo[0], &loc->heads)) 548 geo->heads = diskinfo[0];
549 return -EFAULT; 549 geo->sectors = diskinfo[1];
550 if (put_user(diskinfo[1], &loc->sectors)) 550 geo->cylinders = diskinfo[2];
551 return -EFAULT;
552 if (put_user(diskinfo[2], &loc->cylinders))
553 return -EFAULT;
554 if (put_user((unsigned)get_start_sect(bdev),
555 (unsigned long __user *)&loc->start))
556 return -EFAULT;
557 return 0; 551 return 0;
558} 552}
559 553
@@ -593,12 +587,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
593 if (!scsi_block_when_processing_errors(sdp) || !error) 587 if (!scsi_block_when_processing_errors(sdp) || !error)
594 return error; 588 return error;
595 589
596 if (cmd == HDIO_GETGEO) {
597 if (!arg)
598 return -EINVAL;
599 return sd_hdio_getgeo(bdev, p);
600 }
601
602 /* 590 /*
603 * Send SCSI addressing ioctls directly to mid level, send other 591 * Send SCSI addressing ioctls directly to mid level, send other
604 * ioctls to block level and then onto mid level if they can't be 592 * ioctls to block level and then onto mid level if they can't be
@@ -800,6 +788,7 @@ static struct block_device_operations sd_fops = {
800 .open = sd_open, 788 .open = sd_open,
801 .release = sd_release, 789 .release = sd_release,
802 .ioctl = sd_ioctl, 790 .ioctl = sd_ioctl,
791 .getgeo = sd_getgeo,
803#ifdef CONFIG_COMPAT 792#ifdef CONFIG_COMPAT
804 .compat_ioctl = sd_compat_ioctl, 793 .compat_ioctl = sd_compat_ioctl,
805#endif 794#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 74c01aabd4ab..7f140480c6a8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -224,6 +224,7 @@ extern int dir_notify_enable;
224#include <asm/semaphore.h> 224#include <asm/semaphore.h>
225#include <asm/byteorder.h> 225#include <asm/byteorder.h>
226 226
227struct hd_geometry;
227struct iovec; 228struct iovec;
228struct nameidata; 229struct nameidata;
229struct kiocb; 230struct kiocb;
@@ -962,6 +963,7 @@ struct block_device_operations {
962 int (*direct_access) (struct block_device *, sector_t, unsigned long *); 963 int (*direct_access) (struct block_device *, sector_t, unsigned long *);
963 int (*media_changed) (struct gendisk *); 964 int (*media_changed) (struct gendisk *);
964 int (*revalidate_disk) (struct gendisk *); 965 int (*revalidate_disk) (struct gendisk *);
966 int (*getgeo)(struct block_device *, struct hd_geometry *);
965 struct module *owner; 967 struct module *owner;
966}; 968};
967 969