[PATCH] Add block_device_operations.getgeo block device method
authorChristoph Hellwig <hch@lst.de>
Sun, 8 Jan 2006 09:02:50 +0000 (01:02 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 9 Jan 2006 04:13:54 +0000 (20:13 -0800)
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>
30 files changed:
arch/um/drivers/ubd_kern.c
block/ioctl.c
drivers/acorn/block/mfmhd.c
drivers/block/DAC960.c
drivers/block/acsi.c
drivers/block/amiflop.c
drivers/block/aoe/aoeblk.c
drivers/block/cciss.c
drivers/block/cpqarray.c
drivers/block/floppy.c
drivers/block/paride/pd.c
drivers/block/paride/pf.c
drivers/block/ps2esdi.c
drivers/block/sx8.c
drivers/block/umem.c
drivers/block/viodasd.c
drivers/block/xd.c
drivers/ide/ide-disk.c
drivers/ide/ide-floppy.c
drivers/ide/ide.c
drivers/ide/legacy/hd.c
drivers/md/md.c
drivers/message/i2o/i2o_block.c
drivers/mmc/mmc_block.c
drivers/mtd/mtd_blkdevs.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/xpram.c
drivers/scsi/sd.c
include/linux/fs.h

index 73f9652b2ee9000aab4243c50db4650d7974ea67..3a93c6f772fa3aa0bac0de3d6f3ec977dc545a3b 100644 (file)
@@ -117,6 +117,7 @@ static int ubd_open(struct inode * inode, struct file * filp);
 static int ubd_release(struct inode * inode, struct file * file);
 static int ubd_ioctl(struct inode * inode, struct file * file,
                     unsigned int cmd, unsigned long arg);
+static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 #define MAX_DEV (8)
 
@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
         .open          = ubd_open,
         .release       = ubd_release,
         .ioctl         = ubd_ioctl,
+       .getgeo         = ubd_getgeo,
 };
 
 /* Protected by the queue_lock */
@@ -1058,6 +1060,16 @@ static void do_ubd_request(request_queue_t *q)
        }
 }
 
+static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct ubd *dev = bdev->bd_disk->private_data;
+
+       geo->heads = 128;
+       geo->sectors = 32;
+       geo->cylinders = dev->size / (128 * 32 * 512);
+       return 0;
+}
+
 static int ubd_ioctl(struct inode * inode, struct file * file,
                     unsigned int cmd, unsigned long arg)
 {
@@ -1070,16 +1082,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
        };
 
        switch (cmd) {
-               struct hd_geometry g;
                struct cdrom_volctrl volume;
-       case HDIO_GETGEO:
-               if(!loc) return(-EINVAL);
-               g.heads = 128;
-               g.sectors = 32;
-               g.cylinders = dev->size / (128 * 32 * 512);
-               g.start = get_start_sect(inode->i_bdev);
-               return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
-
        case HDIO_GET_IDENTITY:
                ubd_id.cyls = dev->size / (128 * 32 * 512);
                if(copy_to_user((char __user *) arg, (char *) &ubd_id,
index 6e278474f9a8c1f0dcb70a560031fac870eb3220..82030e1dfd631b1495f87ebe632f30ed6f1086fa 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/sched.h>               /* for capable() */
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
+#include <linux/hdreg.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
@@ -245,6 +246,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
                set_device_ro(bdev, n);
                unlock_kernel();
                return 0;
+       case HDIO_GETGEO: {
+               struct hd_geometry geo;
+
+               if (!arg)
+                       return -EINVAL;
+               if (!disk->fops->getgeo)
+                       return -ENOTTY;
+
+               /*
+                * We need to set the startsect first, the driver may
+                * want to override it.
+                */
+               geo.start = get_start_sect(bdev);
+               ret = disk->fops->getgeo(bdev, &geo);
+               if (ret)
+                       return ret;
+               if (copy_to_user((struct hd_geometry __user *)arg, &geo,
+                                       sizeof(geo)))
+                       return -EFAULT;
+               return 0;
+       }
        }
 
        lock_kernel();
index 4b65f74d66b1a2465798618a347424260833c4cd..ce074f6f3369c338e16828fde64f0864cc8a00d2 100644 (file)
@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock);
 #define MAJOR_NR       MFM_ACORN_MAJOR
 #define QUEUE (mfm_queue)
 #define CURRENT elv_next_request(mfm_queue)
-/*
- * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
- */
-#ifndef HDIO_GETGEO
-#define HDIO_GETGEO 0x301
-struct hd_geometry {
-       unsigned char heads;
-       unsigned char sectors;
-       unsigned short cylinders;
-       unsigned long start;
-};
-#endif
-
 
 /*
  * Configuration section
@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void)
  * The 'front' end of the mfm driver follows...
  */
 
-static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
+static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
-       struct hd_geometry *geo = (struct hd_geometry *) arg;
-       if (cmd != HDIO_GETGEO)
-               return -EINVAL;
-       if (!arg)
-               return -EINVAL;
-       if (put_user (p->heads, &geo->heads))
-               return -EFAULT;
-       if (put_user (p->sectors, &geo->sectors))
-               return -EFAULT;
-       if (put_user (p->cylinders, &geo->cylinders))
-               return -EFAULT;
-       if (put_user (get_start_sect(inode->i_bdev), &geo->start))
-               return -EFAULT;
+       struct mfm_info *p = bdev->bd_disk->private_data;
+
+       geo->heads = p->heads;
+       geo->sectors = p->sectors;
+       geo->cylinders = p->cylinders;
        return 0;
 }
 
@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
 static struct block_device_operations mfm_fops =
 {
        .owner          = THIS_MODULE,
-       .ioctl          = mfm_ioctl,
+       .getgeo         = mfm_getgeo,
 };
 
 /*
index 21097a39a057e83e6d495f031cdf4ab23881ed48..179c68a3cef37a37fb2d449e1d9d5139601dbf6d 100644 (file)
@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int DAC960_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct gendisk *disk = bdev->bd_disk;
        DAC960_Controller_T *p = disk->queue->queuedata;
        int drive_nr = (long)disk->private_data;
-       struct hd_geometry g;
-       struct hd_geometry __user *loc = (struct hd_geometry __user *)arg;
-
-       if (cmd != HDIO_GETGEO || !loc)
-               return -EINVAL;
 
        if (p->FirmwareType == DAC960_V1_Controller) {
-               g.heads = p->V1.GeometryTranslationHeads;
-               g.sectors = p->V1.GeometryTranslationSectors;
-               g.cylinders = p->V1.LogicalDriveInformation[drive_nr].
-                       LogicalDriveSize / (g.heads * g.sectors);
+               geo->heads = p->V1.GeometryTranslationHeads;
+               geo->sectors = p->V1.GeometryTranslationSectors;
+               geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
+                       LogicalDriveSize / (geo->heads * geo->sectors);
        } else {
                DAC960_V2_LogicalDeviceInfo_T *i =
                        p->V2.LogicalDeviceInformation[drive_nr];
                switch (i->DriveGeometry) {
                case DAC960_V2_Geometry_128_32:
-                       g.heads = 128;
-                       g.sectors = 32;
+                       geo->heads = 128;
+                       geo->sectors = 32;
                        break;
                case DAC960_V2_Geometry_255_63:
-                       g.heads = 255;
-                       g.sectors = 63;
+                       geo->heads = 255;
+                       geo->sectors = 63;
                        break;
                default:
                        DAC960_Error("Illegal Logical Device Geometry %d\n",
@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
                        return -EINVAL;
                }
 
-               g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors);
+               geo->cylinders = i->ConfigurableDeviceSize /
+                       (geo->heads * geo->sectors);
        }
        
-       g.start = get_start_sect(inode->i_bdev);
-
-       return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+       return 0;
 }
 
 static int DAC960_media_changed(struct gendisk *disk)
@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
 static struct block_device_operations DAC960_BlockDeviceOperations = {
        .owner                  = THIS_MODULE,
        .open                   = DAC960_open,
-       .ioctl                  = DAC960_ioctl,
+       .getgeo                 = DAC960_getgeo,
        .media_changed          = DAC960_media_changed,
        .revalidate_disk        = DAC960_revalidate_disk,
 };
index 5d2d649f7e8d517f950ce01a99a2395ef4533f30..196c0ec9cd5421da1c1f278d15fc66e5d474b8f4 100644 (file)
@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void )
  *
  ***********************************************************************/
 
+static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct acsi_info_struct *aip = bdev->bd_disk->private_data;
+
+       /*
+        * Just fake some geometry here, it's nonsense anyway
+        * To make it easy, use Adaptec's usual 64/32 mapping
+        */
+       geo->heads = 64;
+       geo->sectors = 32;
+       geo->cylinders = aip->size >> 11;
+       return 0;
+}
 
 static int acsi_ioctl( struct inode *inode, struct file *file,
                                           unsigned int cmd, unsigned long arg )
@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct acsi_info_struct *aip = disk->private_data;
        switch (cmd) {
-         case HDIO_GETGEO:
-               /* HDIO_GETGEO is supported more for getting the partition's
-                * start sector... */
-         { struct hd_geometry *geo = (struct hd_geometry *)arg;
-           /* just fake some geometry here, it's nonsense anyway; to make it
-                * easy, use Adaptec's usual 64/32 mapping */
-           put_user( 64, &geo->heads );
-           put_user( 32, &geo->sectors );
-           put_user( aip->size >> 11, &geo->cylinders );
-               put_user(get_start_sect(inode->i_bdev), &geo->start);
-               return 0;
-         }
          case SCSI_IOCTL_GET_IDLUN:
                /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
                put_user( aip->target | (aip->lun << 8),
@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = {
        .open           = acsi_open,
        .release        = acsi_release,
        .ioctl          = acsi_ioctl,
+       .getgeo         = acsi_getgeo,
        .media_changed  = acsi_media_change,
        .revalidate_disk= acsi_revalidate,
 };
index 0acbfff8ad284ecb0d7adb7c57f32787f6e071c2..cb2a545e57dcbcdb75258cea1888952fee5d4df5 100644 (file)
@@ -1424,6 +1424,16 @@ static void do_fd_request(request_queue_t * q)
        redo_fd_request();
 }
 
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       int drive = MINOR(bdev->bd_dev) & 3;
+
+       geo->heads = unit[drive].type->heads;
+       geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
+       geo->cylinders = unit[drive].type->tracks;
+       return 0;
+}
+
 static int fd_ioctl(struct inode *inode, struct file *filp,
                    unsigned int cmd, unsigned long param)
 {
@@ -1431,18 +1441,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
        static struct floppy_struct getprm;
 
        switch(cmd){
-       case HDIO_GETGEO:
-       {
-               struct hd_geometry loc;
-               loc.heads = unit[drive].type->heads;
-               loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
-               loc.cylinders = unit[drive].type->tracks;
-               loc.start = 0;
-               if (copy_to_user((void *)param, (void *)&loc,
-                                sizeof(struct hd_geometry)))
-                       return -EFAULT;
-               break;
-       }
        case FDFMTBEG:
                get_fdc(drive);
                if (fd_ref[drive] > 1) {
@@ -1652,6 +1650,7 @@ static struct block_device_operations floppy_fops = {
        .open           = floppy_open,
        .release        = floppy_release,
        .ioctl          = fd_ioctl,
+       .getgeo         = fd_getgeo,
        .media_changed  = amiga_floppy_change,
 };
 
index 0e97fcb9f3a15b3bbe5b4a0bb8bd085c20e05b2b..c05ee8bffd97921dcd44438a9ade85e6b4a1f789 100644 (file)
@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
        return 0;
 }
 
-/* This ioctl implementation expects userland to have the device node
- * permissions set so that only priviledged users can open an aoe
- * block device directly.
- */
 static int
-aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg)
+aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct aoedev *d;
-
-       if (!arg)
-               return -EINVAL;
+       struct aoedev *d = bdev->bd_disk->private_data;
 
-       d = inode->i_bdev->bd_disk->private_data;
        if ((d->flags & DEVFL_UP) == 0) {
                printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
                return -ENODEV;
        }
 
-       if (cmd == HDIO_GETGEO) {
-               d->geo.start = get_start_sect(inode->i_bdev);
-               if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo))
-                       return 0;
-               return -EFAULT;
-       }
-       printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
-       return -EINVAL;
+       geo->cylinders = d->geo.cylinders;
+       geo->heads = d->geo.heads;
+       geo->sectors = d->geo.sectors;
+       return 0;
 }
 
 static struct block_device_operations aoe_bdops = {
        .open = aoeblk_open,
        .release = aoeblk_release,
-       .ioctl = aoeblk_ioctl,
+       .getgeo = aoeblk_getgeo,
        .owner = THIS_MODULE,
 };
 
index d2815b7a9150dbf9d0fb417b8dc3acadd8315b40..bdb9c2717d40dad04f7b4ca3ad7e2205a701351f 100644 (file)
@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep);
 static int cciss_release(struct inode *inode, struct file *filep);
 static int cciss_ioctl(struct inode *inode, struct file *filep, 
                unsigned int cmd, unsigned long arg);
+static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 static int revalidate_allvol(ctlr_info_t *host);
 static int cciss_revalidate(struct gendisk *disk);
@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops  = {
        .open           = cciss_open, 
        .release        = cciss_release,
         .ioctl         = cciss_ioctl,
+        .getgeo                = cciss_getgeo,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = cciss_compat_ioctl,
 #endif
@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
        return err;
 }
 #endif
+
+static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       drive_info_struct *drv = get_drv(bdev->bd_disk);
+
+       if (!drv->cylinders)
+               return -ENXIO;
+
+       geo->heads = drv->heads;
+       geo->sectors = drv->sectors;
+       geo->cylinders = drv->cylinders;
+       return 0;
+}
+
 /*
  * ioctl 
  */
@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 #endif /* CCISS_DEBUG */ 
        
        switch(cmd) {
-       case HDIO_GETGEO:
-       {
-                struct hd_geometry driver_geo;
-                if (drv->cylinders) {
-                        driver_geo.heads = drv->heads;
-                        driver_geo.sectors = drv->sectors;
-                        driver_geo.cylinders = drv->cylinders;
-                } else
-                       return -ENXIO;
-                driver_geo.start= get_start_sect(inode->i_bdev);
-                if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry)))
-                        return  -EFAULT;
-                return(0);
-       }
-
        case CCISS_GETPCIINFO:
        {
                cciss_pci_info_struct pciinfo;
index 9bddb687487375f3e0428813afa5509816b5b693..9f0664dd38005a6595ad4d4bc51719579580b9b8 100644 (file)
@@ -160,6 +160,7 @@ static int sendcmd(
 static int ida_open(struct inode *inode, struct file *filep);
 static int ida_release(struct inode *inode, struct file *filep);
 static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
+static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
 
 static void do_ida_request(request_queue_t *q);
@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops  = {
        .open           = ida_open,
        .release        = ida_release,
        .ioctl          = ida_ioctl,
+       .getgeo         = ida_getgeo,
        .revalidate_disk= ida_revalidate,
 };
 
@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata)
        h->misc_tflags = 0;
 }
 
+static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       drv_info_t *drv = get_drv(bdev->bd_disk);
+
+       if (drv->cylinders) {
+               geo->heads = drv->heads;
+               geo->sectors = drv->sectors;
+               geo->cylinders = drv->cylinders;
+       } else {
+               geo->heads = 0xff;
+               geo->sectors = 0x3f;
+               geo->cylinders = drv->nr_blks / (0xff*0x3f);
+       }
+
+       return 0;
+}
+
 /*
  *  ida_ioctl does some miscellaneous stuff like reporting drive geometry,
  *  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,
        drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
        ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
        int error;
-       int diskinfo[4];
-       struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
        ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
        ida_ioctl_t *my_io;
 
        switch(cmd) {
-       case HDIO_GETGEO:
-               if (drv->cylinders) {
-                       diskinfo[0] = drv->heads;
-                       diskinfo[1] = drv->sectors;
-                       diskinfo[2] = drv->cylinders;
-               } else {
-                       diskinfo[0] = 0xff;
-                       diskinfo[1] = 0x3f;
-                       diskinfo[2] = drv->nr_blks / (0xff*0x3f);
-               }
-               put_user(diskinfo[0], &geo->heads);
-               put_user(diskinfo[1], &geo->sectors);
-               put_user(diskinfo[2], &geo->cylinders);
-               put_user(get_start_sect(inode->i_bdev), &geo->start);
-               return 0;
        case IDAGETDRVINFO:
                if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
                        return -EFAULT;
index a5b857c5c4b8c18c3cbd897912e854bd919a6e57..b86613b21cf18668d91af603107e904900cc3b05 100644 (file)
@@ -3445,6 +3445,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
        return 0;
 }
 
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       int drive = (long)bdev->bd_disk->private_data;
+       int type = ITYPE(drive_state[drive].fd_device);
+       struct floppy_struct *g;
+       int ret;
+
+       ret = get_floppy_geometry(drive, type, &g);
+       if (ret)
+               return ret;
+
+       geo->heads = g->head;
+       geo->sectors = g->sect;
+       geo->cylinders = g->track;
+       return 0;
+}
+
 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                    unsigned long param)
 {
@@ -3474,23 +3491,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                cmd = FDEJECT;
        }
 
-       /* generic block device ioctls */
-       switch (cmd) {
-               /* the following have been inspired by the corresponding
-                * code for other block devices. */
-               struct floppy_struct *g;
-       case HDIO_GETGEO:
-               {
-                       struct hd_geometry loc;
-                       ECALL(get_floppy_geometry(drive, type, &g));
-                       loc.heads = g->head;
-                       loc.sectors = g->sect;
-                       loc.cylinders = g->track;
-                       loc.start = 0;
-                       return _COPYOUT(loc);
-               }
-       }
-
        /* convert the old style command into a new style command */
        if ((cmd & 0xff00) == 0x0200) {
                ECALL(normalize_ioctl(&cmd, &size));
@@ -3938,6 +3938,7 @@ static struct block_device_operations floppy_fops = {
        .open           = floppy_open,
        .release        = floppy_release,
        .ioctl          = fd_ioctl,
+       .getgeo         = fd_getgeo,
        .media_changed  = check_floppy_change,
        .revalidate_disk = floppy_revalidate,
 };
index fa49d62626ba12d1e8647993f48a4fa6e655d660..62d2464c12f2001017077dadb883e0a18264be84 100644 (file)
@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file)
        return 0;
 }
 
+static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct pd_unit *disk = bdev->bd_disk->private_data;
+
+       if (disk->alt_geom) {
+               geo->heads = PD_LOG_HEADS;
+               geo->sectors = PD_LOG_SECTS;
+               geo->cylinders = disk->capacity / (geo->heads * geo->sectors);
+       } else {
+               geo->heads = disk->heads;
+               geo->sectors = disk->sectors;
+               geo->cylinders = disk->cylinders;
+       }
+
+       return 0;
+}
+
 static int pd_ioctl(struct inode *inode, struct file *file,
         unsigned int cmd, unsigned long arg)
 {
        struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
-       struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
-       struct hd_geometry g;
 
        switch (cmd) {
        case CDROMEJECT:
                if (disk->access == 1)
                        pd_special_command(disk, pd_eject);
                return 0;
-       case HDIO_GETGEO:
-               if (disk->alt_geom) {
-                       g.heads = PD_LOG_HEADS;
-                       g.sectors = PD_LOG_SECTS;
-                       g.cylinders = disk->capacity / (g.heads * g.sectors);
-               } else {
-                       g.heads = disk->heads;
-                       g.sectors = disk->sectors;
-                       g.cylinders = disk->cylinders;
-               }
-               g.start = get_start_sect(inode->i_bdev);
-               if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
-                       return -EFAULT;
-               return 0;
        default:
                return -EINVAL;
        }
@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = {
        .open           = pd_open,
        .release        = pd_release,
        .ioctl          = pd_ioctl,
+       .getgeo         = pd_getgeo,
        .media_changed  = pd_check_media,
        .revalidate_disk= pd_revalidate
 };
index e9746af29b9f0299f03261667e43fb86f8f7063d..852b564e903a69566a1f3b82d3a339d884db9b98 100644 (file)
@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file);
 static void do_pf_request(request_queue_t * q);
 static int pf_ioctl(struct inode *inode, struct file *file,
                    unsigned int cmd, unsigned long arg);
+static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 static int pf_release(struct inode *inode, struct file *file);
 
@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = {
        .open           = pf_open,
        .release        = pf_release,
        .ioctl          = pf_ioctl,
+       .getgeo         = pf_getgeo,
        .media_changed  = pf_check_media,
 };
 
@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
-       struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
-       struct hd_geometry g;
-       sector_t capacity;
-
-       if (cmd == CDROMEJECT) {
-               if (pf->access == 1) {
-                       pf_eject(pf);
-                       return 0;
-               }
-               return -EBUSY;
-       }
-       if (cmd != HDIO_GETGEO)
-               return -EINVAL;
-       capacity = get_capacity(pf->disk);
+       struct pf_unit *pf = bdev->bd_disk->private_data;
+       sector_t capacity = get_capacity(pf->disk);
+
        if (capacity < PF_FD_MAX) {
-               g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
-               g.heads = PF_FD_HDS;
-               g.sectors = PF_FD_SPT;
+               geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
+               geo->heads = PF_FD_HDS;
+               geo->sectors = PF_FD_SPT;
        } else {
-               g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
-               g.heads = PF_HD_HDS;
-               g.sectors = PF_HD_SPT;
+               geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
+               geo->heads = PF_HD_HDS;
+               geo->sectors = PF_HD_SPT;
        }
-       if (copy_to_user(geo, &g, sizeof(g)))
-               return -EFAULT;
+
+       return 0;
+}
+
+static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
+
+       if (cmd != CDROMEJECT)
+               return -EINVAL;
+
+       if (pf->access != 1)
+               return -EBUSY;
+       pf_eject(pf);
        return 0;
 }
 
index 29d1518be72a16ba980e71eb829a671208e1fbdf..43415f69839f7d0946354d0c824390955e996cbb 100644 (file)
@@ -81,8 +81,7 @@ static void (*current_int_handler) (u_int) = NULL;
 static void ps2esdi_normal_interrupt_handler(u_int);
 static void ps2esdi_initial_reset_int_handler(u_int);
 static void ps2esdi_geometry_int_handler(u_int);
-static int ps2esdi_ioctl(struct inode *inode, struct file *file,
-                        u_int cmd, u_long arg);
+static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
 
@@ -132,7 +131,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
 static struct block_device_operations ps2esdi_fops =
 {
        .owner          = THIS_MODULE,
-       .ioctl          = ps2esdi_ioctl,
+       .getgeo         = ps2esdi_getgeo,
 };
 
 static struct gendisk *ps2esdi_gendisk[2];
@@ -1058,21 +1057,13 @@ static void dump_cmd_complete_status(u_int int_ret_code)
 
 }
 
-static int ps2esdi_ioctl(struct inode *inode,
-                        struct file *file, u_int cmd, u_long arg)
+static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
-       struct ps2esdi_geometry geom;
-
-       if (cmd != HDIO_GETGEO)
-               return -EINVAL;
-       memset(&geom, 0, sizeof(geom));
-       geom.heads = p->head;
-       geom.sectors = p->sect;
-       geom.cylinders = p->cyl;
-       geom.start = get_start_sect(inode->i_bdev);
-       if (copy_to_user((void __user *)arg, &geom, sizeof(geom)))
-               return -EFAULT;
+       struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
+
+       geo->heads = p->head;
+       geo->sectors = p->sect;
+       geo->cylinders = p->cyl;
        return 0;
 }
 
index 9251f4131b5307e548fe98863ae8eb9ca5c9cf04..c0cdc182a8b0b4fcd619ee97100d53ff4f4538db 100644 (file)
@@ -407,8 +407,7 @@ struct carm_array_info {
 
 static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static void carm_remove_one (struct pci_dev *pdev);
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
-                          unsigned int cmd, unsigned long arg);
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 static struct pci_device_id carm_pci_tbl[] = {
        { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = {
 
 static struct block_device_operations carm_bd_ops = {
        .owner          = THIS_MODULE,
-       .ioctl          = carm_bdev_ioctl,
+       .getgeo         = carm_bdev_getgeo,
 };
 
 static unsigned int carm_host_id;
@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc;
 
 
 
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
-                          unsigned int cmd, unsigned long arg)
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       void __user *usermem = (void __user *) arg;
-       struct carm_port *port = ino->i_bdev->bd_disk->private_data;
-       struct hd_geometry geom;
+       struct carm_port *port = bdev->bd_disk->private_data;
 
-       switch (cmd) {
-       case HDIO_GETGEO:
-               if (!usermem)
-                       return -EINVAL;
-
-               geom.heads = (u8) port->dev_geom_head;
-               geom.sectors = (u8) port->dev_geom_sect;
-               geom.cylinders = port->dev_geom_cyl;
-               geom.start = get_start_sect(ino->i_bdev);
-
-               if (copy_to_user(usermem, &geom, sizeof(geom)))
-                       return -EFAULT;
-               return 0;
-
-       default:
-               break;
-       }
-
-       return -EOPNOTSUPP;
+       geo->heads = (u8) port->dev_geom_head;
+       geo->sectors = (u8) port->dev_geom_sect;
+       geo->cylinders = port->dev_geom_cyl;
+       return 0;
 }
 
 static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
index 0f48301342da4e2e0a13a23bed85821e06efb79b..15299e7a1ade64a23bc6d7c11781bbc89c71f69a 100644 (file)
@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk)
        set_capacity(disk, card->mm_size << 1);
        return 0;
 }
-/*
------------------------------------------------------------------------------------
---                            mm_ioctl
------------------------------------------------------------------------------------
-*/
-static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
+
+static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       if (cmd == HDIO_GETGEO) {
-               struct cardinfo *card = i->i_bdev->bd_disk->private_data;
-               int size = card->mm_size * (1024 / MM_HARDSECT);
-               struct hd_geometry geo;
-               /*
-                * get geometry: we have to fake one...  trim the size to a
-                * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
-                * whatever cylinders.
-                */
-               geo.heads     = 64;
-               geo.sectors   = 32;
-               geo.start     = get_start_sect(i->i_bdev);
-               geo.cylinders = size / (geo.heads * geo.sectors);
-
-               if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
-                       return -EFAULT;
-               return 0;
-       }
+       struct cardinfo *card = bdev->bd_disk->private_data;
+       int size = card->mm_size * (1024 / MM_HARDSECT);
 
-       return -EINVAL;
+       /*
+        * get geometry: we have to fake one...  trim the size to a
+        * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
+        * whatever cylinders.
+        */
+       geo->heads     = 64;
+       geo->sectors   = 32;
+       geo->cylinders = size / (geo->heads * geo->sectors);
+       return 0;
 }
+
 /*
 -----------------------------------------------------------------------------------
 --                                mm_check_change
@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk)
 */
 static struct block_device_operations mm_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = mm_ioctl,
+       .getgeo         = mm_getgeo,
        .revalidate_disk= mm_revalidate,
        .media_changed  = mm_check_change,
 };
index 063f0304a1630e20af9fbf0866bbcfb8c6c731fd..d1aaf31bd97e85e762c33e2aa50b65748c45f0af 100644 (file)
@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil)
 
 /* External ioctl entry point.
  */
-static int viodasd_ioctl(struct inode *ino, struct file *fil,
-                        unsigned int cmd, unsigned long arg)
+static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       unsigned char sectors;
-       unsigned char heads;
-       unsigned short cylinders;
-       struct hd_geometry *geo;
-       struct gendisk *gendisk;
-       struct viodasd_device *d;
+       struct gendisk *disk = bdev->bd_disk;
+       struct viodasd_device *d = disk->private_data;
 
-       switch (cmd) {
-       case HDIO_GETGEO:
-               geo = (struct hd_geometry *)arg;
-               if (geo == NULL)
-                       return -EINVAL;
-               if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo)))
-                       return -EFAULT;
-               gendisk = ino->i_bdev->bd_disk;
-               d = gendisk->private_data;
-               sectors = d->sectors;
-               if (sectors == 0)
-                       sectors = 32;
-               heads = d->tracks;
-               if (heads == 0)
-                       heads = 64;
-               cylinders = d->cylinders;
-               if (cylinders == 0)
-                       cylinders = get_capacity(gendisk) / (sectors * heads);
-               if (__put_user(sectors, &geo->sectors) ||
-                   __put_user(heads, &geo->heads) ||
-                   __put_user(cylinders, &geo->cylinders) ||
-                   __put_user(get_start_sect(ino->i_bdev), &geo->start))
-                       return -EFAULT;
-               return 0;
-       }
+       geo->sectors = d->sectors ? d->sectors : 0;
+       geo->heads = d->tracks ? d->tracks  : 64;
+       geo->cylinders = d->cylinders ? d->cylinders :
+               get_capacity(disk) / (geo->cylinders * geo->heads);
 
-       return -EINVAL;
+       return 0;
 }
 
 /*
@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = {
        .owner = THIS_MODULE,
        .open = viodasd_open,
        .release = viodasd_release,
-       .ioctl = viodasd_ioctl,
+       .getgeo = viodasd_getgeo,
 };
 
 /*
index 68b6d7b154cf88057b138d72a58b74d93409c23f..97f5dab24b5adf46b939b11d3b3b357b2e0d72db 100644 (file)
@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock);
 
 static struct gendisk *xd_gendisk[2];
 
+static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
+
 static struct block_device_operations xd_fops = {
        .owner  = THIS_MODULE,
        .ioctl  = xd_ioctl,
+       .getgeo = xd_getgeo,
 };
 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
 static 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)
        }
 }
 
+static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       XD_INFO *p = bdev->bd_disk->private_data;
+
+       geo->heads = p->heads;
+       geo->sectors = p->sectors;
+       geo->cylinders = p->cylinders;
+       return 0;
+}
+
 /* xd_ioctl: handle device ioctl's */
 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
 {
-       XD_INFO *p = inode->i_bdev->bd_disk->private_data;
-
        switch (cmd) {
-               case HDIO_GETGEO:
-               {
-                       struct hd_geometry g;
-                       struct hd_geometry __user *geom= (void __user *)arg;
-                       g.heads = p->heads;
-                       g.sectors = p->sectors;
-                       g.cylinders = p->cylinders;
-                       g.start = get_start_sect(inode->i_bdev);
-                       return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0;
-               }
                case HDIO_SET_DMA:
                        if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if (xdc_busy) return -EBUSY;
index 4b441720b6ba94cf07599511c73ba0bbc4ff82ad..cab362ea03360a1bc4586ebec338cf2cadf74418 100644 (file)
@@ -1130,6 +1130,17 @@ static int idedisk_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
+static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+       ide_drive_t *drive = idkp->drive;
+
+       geo->heads = drive->bios_head;
+       geo->sectors = drive->bios_sect;
+       geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+       return 0;
+}
+
 static int idedisk_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
@@ -1164,6 +1175,7 @@ static struct block_device_operations idedisk_ops = {
        .open           = idedisk_open,
        .release        = idedisk_release,
        .ioctl          = idedisk_ioctl,
+       .getgeo         = idedisk_getgeo,
        .media_changed  = idedisk_media_changed,
        .revalidate_disk= idedisk_revalidate_disk
 };
index fba3fffc2d6635561e4157e311145d916053247c..5945f551aaaad493d22c05e358f2df30b06f110c 100644 (file)
@@ -2031,6 +2031,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
+static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+       ide_drive_t *drive = floppy->drive;
+
+       geo->heads = drive->bios_head;
+       geo->sectors = drive->bios_sect;
+       geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+       return 0;
+}
+
 static int idefloppy_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
@@ -2120,6 +2131,7 @@ static struct block_device_operations idefloppy_ops = {
        .open           = idefloppy_open,
        .release        = idefloppy_release,
        .ioctl          = idefloppy_ioctl,
+       .getgeo         = idefloppy_getgeo,
        .media_changed  = idefloppy_media_changed,
        .revalidate_disk= idefloppy_revalidate_disk
 };
index 4b524f6b3ecd3e57e15bc161b013bf6b40aa33e9..b069b13b75a760ec58dc8e6c6fe7dbcbdc844452 100644 (file)
@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
        up(&ide_setting_sem);
 
        switch (cmd) {
-               case HDIO_GETGEO:
-               {
-                       struct hd_geometry geom;
-                       if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
-                       geom.heads = drive->bios_head;
-                       geom.sectors = drive->bios_sect;
-                       geom.cylinders = (u16)drive->bios_cyl; /* truncate */
-                       geom.start = get_start_sect(bdev);
-                       if (copy_to_user(p, &geom, sizeof(struct hd_geometry)))
-                               return -EFAULT;
-                       return 0;
-               }
-
                case HDIO_OBSOLETE_IDENTITY:
                case HDIO_GET_IDENTITY:
                        if (bdev != bdev->bd_contains)
index 242029c9c0ca9a5e9e61b64011a3cd9dce7c31fd..6439dec66881619fc26d678a5bab544e18e06182 100644 (file)
@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q)
        enable_irq(HD_IRQ);
 }
 
-static int hd_ioctl(struct inode * inode, struct file * file,
-       unsigned int cmd, unsigned long arg)
+static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
-       struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
-       struct hd_geometry g; 
-
-       if (cmd != HDIO_GETGEO)
-               return -EINVAL;
-       if (!loc)
-               return -EINVAL;
-       g.heads = disk->head;
-       g.sectors = disk->sect;
-       g.cylinders = disk->cyl;
-       g.start = get_start_sect(inode->i_bdev);
-       return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+       struct hd_i_struct *disk = bdev->bd_disk->private_data;
+
+       geo->heads = disk->head;
+       geo->sectors = disk->sect;
+       geo->cylinders = disk->cyl;
+       return 0;
 }
 
 /*
@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 static struct block_device_operations hd_fops = {
-       .ioctl =        hd_ioctl,
+       .getgeo =       hd_getgeo,
 };
 
 /*
index 1b76fb29fb7065b1ac52aaa1db009515e16e46ca..e423a16ba3c95c6778c0051bd5bc0a4f6b056c2e 100644 (file)
@@ -3598,12 +3598,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
        return 0;
 }
 
+static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       mddev_t *mddev = bdev->bd_disk->private_data;
+
+       geo->heads = 2;
+       geo->sectors = 4;
+       geo->cylinders = get_capacity(mddev->gendisk) / 8;
+       return 0;
+}
+
 static int md_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
        int err = 0;
        void __user *argp = (void __user *)arg;
-       struct hd_geometry __user *loc = argp;
        mddev_t *mddev = NULL;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -3765,24 +3774,6 @@ static int md_ioctl(struct inode *inode, struct file *file,
         * 4 sectors (with a BIG number of cylinders...). This drives
         * dosfs just mad... ;-)
         */
-               case HDIO_GETGEO:
-                       if (!loc) {
-                               err = -EINVAL;
-                               goto abort_unlock;
-                       }
-                       err = put_user (2, (char __user *) &loc->heads);
-                       if (err)
-                               goto abort_unlock;
-                       err = put_user (4, (char __user *) &loc->sectors);
-                       if (err)
-                               goto abort_unlock;
-                       err = put_user(get_capacity(mddev->gendisk)/8,
-                                       (short __user *) &loc->cylinders);
-                       if (err)
-                               goto abort_unlock;
-                       err = put_user (get_start_sect(inode->i_bdev),
-                                               (long __user *) &loc->start);
-                       goto done_unlock;
        }
 
        /*
@@ -3911,6 +3902,7 @@ static struct block_device_operations md_fops =
        .open           = md_open,
        .release        = md_release,
        .ioctl          = md_ioctl,
+       .getgeo         = md_getgeo,
        .media_changed  = md_media_changed,
        .revalidate_disk= md_revalidate,
 };
index 5b1febed313344e13370583ad799986f95fad700..b09fb6307153740efc92e674ae65dade0046c8aa 100644 (file)
@@ -662,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       i2o_block_biosparam(get_capacity(bdev->bd_disk),
+                           &geo->cylinders, &geo->heads, &geo->sectors);
+       return 0;
+}
+
 /**
  *     i2o_block_ioctl - Issue device specific ioctl calls.
  *     @cmd: ioctl command
@@ -676,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
        struct i2o_block_device *dev = disk->private_data;
-       void __user *argp = (void __user *)arg;
 
        /* Anyone capable of this syscall can do *real bad* things */
 
@@ -684,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
                return -EPERM;
 
        switch (cmd) {
-       case HDIO_GETGEO:
-               {
-                       struct hd_geometry g;
-                       i2o_block_biosparam(get_capacity(disk),
-                                           &g.cylinders, &g.heads, &g.sectors);
-                       g.start = get_start_sect(inode->i_bdev);
-                       return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
-               }
-
        case BLKI2OGRSTRAT:
                return put_user(dev->rcache, (int __user *)arg);
        case BLKI2OGWSTRAT:
@@ -962,6 +959,7 @@ static struct block_device_operations i2o_block_fops = {
        .open = i2o_block_open,
        .release = i2o_block_release,
        .ioctl = i2o_block_ioctl,
+       .getgeo = i2o_block_getgeo,
        .media_changed = i2o_block_media_changed
 };
 
index 198561d21710c0c9139746926ce107d99c93a782..d5f28981596b3e6ab5df1d63795e53cc3fb62d98 100644 (file)
@@ -113,31 +113,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp)
 }
 
 static int
-mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct block_device *bdev = inode->i_bdev;
-
-       if (cmd == HDIO_GETGEO) {
-               struct hd_geometry geo;
-
-               memset(&geo, 0, sizeof(struct hd_geometry));
-
-               geo.cylinders   = get_capacity(bdev->bd_disk) / (4 * 16);
-               geo.heads       = 4;
-               geo.sectors     = 16;
-               geo.start       = get_start_sect(bdev);
-
-               return copy_to_user((void __user *)arg, &geo, sizeof(geo))
-                       ? -EFAULT : 0;
-       }
-
-       return -ENOTTY;
+       geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
+       geo->heads = 4;
+       geo->sectors = 16;
+       return 0;
 }
 
 static struct block_device_operations mmc_bdops = {
        .open                   = mmc_blk_open,
        .release                = mmc_blk_release,
-       .ioctl                  = mmc_blk_ioctl,
+       .getgeo                 = mmc_blk_getgeo,
        .owner                  = THIS_MODULE,
 };
 
index 339cb1218eaa0b9d7e7431f069ec89a354051873..7f3ff500b68e37e3d5028bac85e4c22b9312db40 100644 (file)
@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f)
        return ret;
 }
 
+static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+
+       if (dev->tr->getgeo)
+               return dev->tr->getgeo(dev, geo);
+       return -ENOTTY;
+}
 
 static int blktrans_ioctl(struct inode *inode, struct file *file,
                              unsigned int cmd, unsigned long arg)
@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
                        return tr->flush(dev);
                /* The core code did the work, we had nothing to do. */
                return 0;
-
-       case HDIO_GETGEO:
-               if (tr->getgeo) {
-                       struct hd_geometry g;
-                       int ret;
-
-                       memset(&g, 0, sizeof(g));
-                       ret = tr->getgeo(dev, &g);
-                       if (ret)
-                               return ret;
-
-                       g.start = get_start_sect(inode->i_bdev);
-                       if (copy_to_user((void __user *)arg, &g, sizeof(g)))
-                               return -EFAULT;
-                       return 0;
-               } /* else */
        default:
                return -ENOTTY;
        }
@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = {
        .open           = blktrans_open,
        .release        = blktrans_release,
        .ioctl          = blktrans_ioctl,
+       .getgeo         = blktrans_getgeo,
 };
 
 int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
index f779f674dfa0414b498f1cf0be497e4a87a89291..2472fa1a1be14c72a6e324ec28e42070ea4fb253 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
+#include <linux/hdreg.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -1723,12 +1724,34 @@ dasd_release(struct inode *inp, struct file *filp)
        return 0;
 }
 
+/*
+ * Return disk geometry.
+ */
+static int
+dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       struct dasd_device *device;
+
+       device = bdev->bd_disk->private_data;
+       if (!device)
+               return -ENODEV;
+
+       if (!device->discipline ||
+           !device->discipline->fill_geometry)
+               return -EINVAL;
+
+       device->discipline->fill_geometry(device, geo);
+       geo->start = get_start_sect(bdev) >> device->s2b_shift;
+       return 0;
+}
+
 struct block_device_operations
 dasd_device_operations = {
        .owner          = THIS_MODULE,
        .open           = dasd_open,
        .release        = dasd_release,
        .ioctl          = dasd_ioctl,
+       .getgeo         = dasd_getgeo,
 };
 
 
index 044b7537199075b132c73047c7a29078b7659ae7..8e4dcd58599eb7ba4db58377865fa0eef8684296 100644 (file)
@@ -485,33 +485,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
        return rc;
 }
 
-/*
- * Return disk geometry.
- */
-static int
-dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
-{
-       struct hd_geometry geo = { 0, };
-       struct dasd_device *device;
-
-       device =  bdev->bd_disk->private_data;
-       if (device == NULL)
-               return -ENODEV;
-
-       if (device == NULL || device->discipline == NULL ||
-           device->discipline->fill_geometry == NULL)
-               return -EINVAL;
-
-       geo = (struct hd_geometry) {};
-       device->discipline->fill_geometry(device, &geo);
-       geo.start = get_start_sect(bdev) >> device->s2b_shift;
-       if (copy_to_user((struct hd_geometry __user *) args, &geo,
-                        sizeof (struct hd_geometry)))
-               return -EFAULT;
-
-       return 0;
-}
-
 /*
  * List of static ioctls.
  */
@@ -528,7 +501,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
        { BIODASDPRRST, dasd_ioctl_reset_profile },
        { BLKROSET, dasd_ioctl_set_ro },
        { DASDAPIVER, dasd_ioctl_api_version },
-       { HDIO_GETGEO, dasd_ioctl_getgeo },
        { -1, NULL }
 };
 
index bf3a67c3cc5e6b0cb44599602fd23aa64bf22d2f..54ecd548c3185b1aac9a78e7343b079bce771ea9 100644 (file)
@@ -328,31 +328,27 @@ fail:
        return 0;
 }
 
-static int xpram_ioctl (struct inode *inode, struct file *filp,
-                unsigned int cmd, unsigned long arg)
+static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct hd_geometry __user *geo;
        unsigned long size;
-       if (cmd != HDIO_GETGEO)
-               return -EINVAL;
+
        /*
         * get geometry: we have to fake one...  trim the size to a
         * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
         * whatever cylinders. Tell also that data starts at sector. 4.
         */
-       geo = (struct hd_geometry __user *) arg;
        size = (xpram_pages * 8) & ~0x3f;
-       put_user(size >> 6, &geo->cylinders);
-       put_user(4, &geo->heads);
-       put_user(16, &geo->sectors);
-       put_user(4, &geo->start);
+       geo->cylinders = size >> 6;
+       geo->heads = 4;
+       geo->sectors = 16;
+       geo->start = 4;
        return 0;
 }
 
 static struct block_device_operations xpram_devops =
 {
        .owner  = THIS_MODULE,
-       .ioctl  = xpram_ioctl,
+       .getgeo = xpram_getgeo,
 };
 
 /*
index 32d4d8d7b9f393e6524153ac7a71c9c00784116c..4c5127ed379c6560dd22e17e0aa408b7b51979f8 100644 (file)
@@ -527,7 +527,7 @@ static int sd_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc)
+static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
        struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
        struct scsi_device *sdp = sdkp->device;
@@ -545,15 +545,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *
        else
                scsicam_bios_param(bdev, sdkp->capacity, diskinfo);
 
-       if (put_user(diskinfo[0], &loc->heads))
-               return -EFAULT;
-       if (put_user(diskinfo[1], &loc->sectors))
-               return -EFAULT;
-       if (put_user(diskinfo[2], &loc->cylinders))
-               return -EFAULT;
-       if (put_user((unsigned)get_start_sect(bdev),
-                    (unsigned long __user *)&loc->start))
-               return -EFAULT;
+       geo->heads = diskinfo[0];
+       geo->sectors = diskinfo[1];
+       geo->cylinders = diskinfo[2];
        return 0;
 }
 
@@ -593,12 +587,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
        if (!scsi_block_when_processing_errors(sdp) || !error)
                return error;
 
-       if (cmd == HDIO_GETGEO) {
-               if (!arg)
-                       return -EINVAL;
-               return sd_hdio_getgeo(bdev, p);
-       }
-
        /*
         * Send SCSI addressing ioctls directly to mid level, send other
         * 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 = {
        .open                   = sd_open,
        .release                = sd_release,
        .ioctl                  = sd_ioctl,
+       .getgeo                 = sd_getgeo,
 #ifdef CONFIG_COMPAT
        .compat_ioctl           = sd_compat_ioctl,
 #endif
index 74c01aabd4ab63214d50fe33f5f83bc1a8a33719..7f140480c6a83f1cd6ec47d866239b6182d19afa 100644 (file)
@@ -224,6 +224,7 @@ extern int dir_notify_enable;
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
 
+struct hd_geometry;
 struct iovec;
 struct nameidata;
 struct kiocb;
@@ -962,6 +963,7 @@ struct block_device_operations {
        int (*direct_access) (struct block_device *, sector_t, unsigned long *);
        int (*media_changed) (struct gendisk *);
        int (*revalidate_disk) (struct gendisk *);
+       int (*getgeo)(struct block_device *, struct hd_geometry *);
        struct module *owner;
 };