Skip to content

Commit

Permalink
[PATCH] Add block_device_operations.getgeo block device method
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and Linus Torvalds committed Jan 9, 2006
1 parent 5b0ed2c commit a885c8c
Show file tree
Hide file tree
Showing 30 changed files with 340 additions and 456 deletions.
21 changes: 12 additions & 9 deletions arch/um/drivers/ubd_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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 */
Expand Down Expand Up @@ -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)
{
Expand All @@ -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,
Expand Down
22 changes: 22 additions & 0 deletions block/ioctl.c
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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();
Expand Down
36 changes: 7 additions & 29 deletions drivers/acorn/block/mfmhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
};

/*
Expand Down
35 changes: 14 additions & 21 deletions drivers/block/DAC960.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,47 +92,40 @@ 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",
p, i->DriveGeometry);
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)
Expand All @@ -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,
};
Expand Down
26 changes: 14 additions & 12 deletions drivers/block/acsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1079,25 +1079,26 @@ 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 )
{
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),
Expand Down Expand Up @@ -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,
};
Expand Down
23 changes: 11 additions & 12 deletions drivers/block/amiflop.c
Original file line number Diff line number Diff line change
Expand Up @@ -1424,25 +1424,23 @@ 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)
{
int drive = iminor(inode) & 3;
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) {
Expand Down Expand Up @@ -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,
};

Expand Down
26 changes: 7 additions & 19 deletions drivers/block/aoe/aoeblk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down
Loading

0 comments on commit a885c8c

Please sign in to comment.