summaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2002-10-15 07:41:35 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2002-10-15 07:41:35 -0700
commit8fbfe7cd5594010a23cb4e81786d1fb8015ffdee (patch)
treeb5be190f22984395209823ec3cac1c76fc93f67f /drivers/block
parente22f7f5fd43205bfd20ea3a7bb4e689cb3f3d278 (diff)
parent5a7728c6d3eb83df9d120944cca4cf476dd326a1 (diff)
Merge nuts.ninka.net:/home/davem/src/BK/network-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/DAC960.c3
-rw-r--r--drivers/block/Makefile4
-rw-r--r--drivers/block/acsi.c18
-rw-r--r--drivers/block/amiflop.c11
-rw-r--r--drivers/block/ataflop.c20
-rw-r--r--drivers/block/blkpg.c310
-rw-r--r--drivers/block/block_ioctl.c83
-rw-r--r--drivers/block/cciss.c9
-rw-r--r--drivers/block/cpqarray.c7
-rw-r--r--drivers/block/floppy.c12
-rw-r--r--drivers/block/genhd.c85
-rw-r--r--drivers/block/ioctl.c215
-rw-r--r--drivers/block/ll_rw_blk.c15
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/nbd.c3
-rw-r--r--drivers/block/paride/pcd.c3
-rw-r--r--drivers/block/paride/pd.c6
-rw-r--r--drivers/block/paride/pf.c6
-rw-r--r--drivers/block/ps2esdi.c16
-rw-r--r--drivers/block/rd.c9
-rw-r--r--drivers/block/scsi_ioctl.c215
-rw-r--r--drivers/block/swim3.c2
-rw-r--r--drivers/block/swim_iop.c2
-rw-r--r--drivers/block/umem.c16
-rw-r--r--drivers/block/xd.c15
-rw-r--r--drivers/block/z2ram.c3
26 files changed, 533 insertions, 557 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 24a1ee66d93b..1c1a72e440e6 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -1962,7 +1962,6 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n);
disk->major = MajorNumber;
disk->first_minor = n << DAC960_MaxPartitionsBits;
- disk->minor_shift = DAC960_MaxPartitionsBits;
disk->fops = &DAC960_BlockDeviceOperations;
}
/*
@@ -2200,7 +2199,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
}
memset(Controller, 0, sizeof(DAC960_Controller_T));
for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
- Controller->disks[i] = alloc_disk();
+ Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
if (!Controller->disks[i])
goto Enomem;
}
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index eff7ee947ea7..6c22bb8963d6 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,9 +9,9 @@
#
export-objs := elevator.o ll_rw_blk.o loop.o genhd.o acsi.o \
- block_ioctl.o deadline-iosched.o
+ scsi_ioctl.o deadline-iosched.o
-obj-y := elevator.o ll_rw_blk.o blkpg.o genhd.o block_ioctl.o deadline-iosched.o
+obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o deadline-iosched.o
obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 5d36adb832e2..520eeabab869 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1086,8 +1086,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
{
int dev = DEVICE_NR(inode->i_rdev);
- if (dev >= NDevices)
- return -EINVAL;
switch (cmd) {
case HDIO_GETGEO:
/* HDIO_GETGEO is supported more for getting the partition's
@@ -1130,13 +1128,8 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
static int acsi_open( struct inode * inode, struct file * filp )
{
- int device;
- struct acsi_info_struct *aip;
-
- device = DEVICE_NR(inode->i_rdev);
- if (device >= NDevices)
- return -ENXIO;
- aip = &acsi_info[device];
+ int device = DEVICE_NR(inode->i_rdev);
+ struct acsi_info_struct *aip = &acsi_info[device];
if (access_count[device] == 0 && aip->removable) {
#if 0
@@ -1729,7 +1722,7 @@ int acsi_init( void )
#endif
err = -ENOMEM;
for( i = 0; i < NDevices; ++i ) {
- acsi_gendisk[i] = alloc_disk();
+ acsi_gendisk[i] = alloc_disk(16);
if (!acsi_gendisk[i])
goto out4;
}
@@ -1739,7 +1732,10 @@ int acsi_init( void )
sprintf(disk->disk_name, "ad%c", 'a'+i);
disk->major = MAJOR_NR;
disk->first_minor = i << 4;
- disk->minor_shift = (acsi_info[i].type==HARDDISK)?4:0;
+ if (acsi_info[i].type != HARDDISK) {
+ disk->minor_shift = 0;
+ disk->minors = 1;
+ }
disk->fops = &acsi_fops;
set_capacity(disk, acsi_info[i].size);
add_disk(disk);
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 22790c4145fe..9e6ae34ae194 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1607,9 +1607,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
if (!kdev_same(old_dev, inode->i_rdev))
return -EBUSY;
- if (unit[drive].type->code == FD_NODRIVE)
- return -ENODEV;
-
if (filp && filp->f_mode & 3) {
check_disk_change(inode->i_bdev);
if (filp->f_mode & 2 ) {
@@ -1683,11 +1680,6 @@ static int amiga_floppy_change(kdev_t dev)
int changed;
static int first_time = 1;
- if (major(dev) != MAJOR_NR) {
- printk(KERN_CRIT "floppy_change: not a floppy\n");
- return 0;
- }
-
if (first_time)
changed = first_time--;
else {
@@ -1735,7 +1727,7 @@ static int __init fd_probe_drives(void)
fd_probe(drive);
if (unit[drive].type->code == FD_NODRIVE)
continue;
- disk = alloc_disk();
+ disk = alloc_disk(1);
if (!disk) {
unit[drive].type->code = FD_NODRIVE;
continue;
@@ -1751,7 +1743,6 @@ static int __init fd_probe_drives(void)
printk("fd%d ",drive);
disk->major = MAJOR_NR;
disk->first_minor = drive;
- disk->minor_shift = 0;
disk->fops = &floppy_fops;
sprintf(disk->disk_name, "fd%d", drive);
set_capacity(disk, 880*2);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 12f3ae02b317..c2ae35bb875b 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1358,12 +1358,6 @@ static int fd_device[4] = { 0,0,0,0 };
static int check_floppy_change (kdev_t dev)
{
unsigned int drive = minor(dev) & 0x03;
-
- if (major(dev) != MAJOR_NR) {
- printk(KERN_ERR "floppy_changed: not a floppy\n");
- return 0;
- }
-
if (test_bit (drive, &fake_change)) {
/* simulated change (e.g. after formatting) */
return 1;
@@ -1855,17 +1849,11 @@ static void __init config_types( void )
static int floppy_open( struct inode *inode, struct file *filp )
{
- int drive, type;
- int old_dev;
+ int drive = minor(inode->i_rdev) & 3;
+ int type = minor(inode->i_rdev) >> 2;
+ int old_dev = fd_device[drive];
- drive = minor(inode->i_rdev) & 3;
- type = minor(inode->i_rdev) >> 2;
DPRINT(("fd_open: type=%d\n",type));
- if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
- return -ENXIO;
-
- old_dev = fd_device[drive];
-
if (fd_ref[drive] && old_dev != minor(inode->i_rdev))
return -EBUSY;
@@ -1949,7 +1937,7 @@ int __init atari_floppy_init (void)
}
for (i = 0; i < FD_MAX_UNITS; i++) {
- unit[i].disk = alloc_disk();
+ unit[i].disk = alloc_disk(1);
if (!unit[i].disk)
goto Enomem;
}
diff --git a/drivers/block/blkpg.c b/drivers/block/blkpg.c
deleted file mode 100644
index d5ba72a8ac86..000000000000
--- a/drivers/block/blkpg.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Partition table and disk geometry handling
- *
- * This obsoletes the partition-handling code in genhd.c:
- * Userspace can look at a disk in arbitrary format and tell
- * the kernel what partitions there are on the disk, and how
- * these should be numbered.
- * It also allows one to repartition a disk that is being used.
- *
- * A single ioctl with lots of subfunctions:
- *
- * Device number stuff:
- * get_whole_disk() (given the device number of a partition, find
- * the device number of the encompassing disk)
- * get_all_partitions() (given the device number of a disk, return the
- * device numbers of all its known partitions)
- *
- * Partition stuff:
- * add_partition()
- * delete_partition()
- * test_partition_in_use() (also for test_disk_in_use)
- *
- * Geometry stuff:
- * get_geometry()
- * set_geometry()
- * get_bios_drivedata()
- *
- * For today, only the partition stuff - aeb, 990515
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h> /* for BLKROSET, ... */
-#include <linux/sched.h> /* for capable() */
-#include <linux/blk.h> /* for set_device_ro() */
-#include <linux/blkpg.h>
-#include <linux/genhd.h>
-#include <linux/module.h> /* for EXPORT_SYMBOL */
-#include <linux/backing-dev.h>
-#include <linux/buffer_head.h>
-
-#include <asm/uaccess.h>
-
-/*
- * What is the data describing a partition?
- *
- * 1. a device number (kdev_t)
- * 2. a starting sector and number of sectors (hd_struct)
- * given in the part[] array of the gendisk structure for the drive.
- *
- * The number of sectors is replicated in the sizes[] array of
- * the gendisk structure for the major, which again is copied to
- * the blk_size[][] array.
- * (However, hd_struct has the number of 512-byte sectors,
- * g->sizes[] and blk_size[][] have the number of 1024-byte blocks.)
- * Note that several drives may have the same major.
- */
-
-/*
- * Add a partition.
- *
- * returns: EINVAL: bad parameters
- * ENXIO: cannot find drive
- * EBUSY: proposed partition overlaps an existing one
- * or has the same number as an existing one
- * 0: all OK.
- */
-int add_partition(struct block_device *bdev, struct blkpg_partition *p)
-{
- struct gendisk *g;
- long long ppstart, pplength;
- int part, i;
-
- /* convert bytes to sectors */
- ppstart = (p->start >> 9);
- pplength = (p->length >> 9);
-
- /* check for fit in a hd_struct */
- if (sizeof(sector_t) == sizeof(long) &&
- sizeof(long long) > sizeof(long)) {
- long pstart, plength;
- pstart = ppstart;
- plength = pplength;
- if (pstart != ppstart || plength != pplength
- || pstart < 0 || plength < 0)
- return -EINVAL;
- }
-
- /* find the drive major */
- g = get_gendisk(bdev->bd_dev, &part);
- if (!g)
- return -ENXIO;
-
- /* existing drive? */
-
- /* drive and partition number OK? */
- if (bdev != bdev->bd_contains)
- return -EINVAL;
- if (part)
- BUG();
- if (p->pno <= 0 || p->pno >= (1 << g->minor_shift))
- return -EINVAL;
-
- /* partition number in use? */
- if (g->part[p->pno - 1].nr_sects != 0)
- return -EBUSY;
-
- /* overlap? */
- for (i = 0; i < (1<<g->minor_shift) - 1; i++)
- if (!(ppstart+pplength <= g->part[i].start_sect ||
- ppstart >= g->part[i].start_sect + g->part[i].nr_sects))
- return -EBUSY;
-
- /* all seems OK */
- g->part[p->pno - 1].start_sect = ppstart;
- g->part[p->pno - 1].nr_sects = pplength;
- update_partition(g, p->pno);
- return 0;
-}
-
-/*
- * Delete a partition given by partition number
- *
- * returns: EINVAL: bad parameters
- * ENXIO: cannot find partition
- * EBUSY: partition is busy
- * 0: all OK.
- *
- * Note that the dev argument refers to the entire disk, not the partition.
- */
-int del_partition(struct block_device *bdev, struct blkpg_partition *p)
-{
- struct gendisk *g;
- struct block_device *bdevp;
- int part;
- int holder;
-
- /* find the drive major */
- g = get_gendisk(bdev->bd_dev, &part);
- if (!g)
- return -ENXIO;
- if (bdev != bdev->bd_contains)
- return -EINVAL;
- if (part)
- BUG();
- if (p->pno <= 0 || p->pno >= (1 << g->minor_shift))
- return -EINVAL;
-
- /* existing drive and partition? */
- if (g->part[p->pno - 1].nr_sects == 0)
- return -ENXIO;
-
- /* partition in use? Incomplete check for now. */
- bdevp = bdget(MKDEV(g->major, g->first_minor + p->pno));
- if (!bdevp)
- return -ENOMEM;
- if (bd_claim(bdevp, &holder) < 0) {
- bdput(bdevp);
- return -EBUSY;
- }
-
- /* all seems OK */
- fsync_bdev(bdevp);
- invalidate_bdev(bdevp, 0);
-
- g->part[p->pno - 1].start_sect = 0;
- g->part[p->pno - 1].nr_sects = 0;
- update_partition(g, p->pno);
- bd_release(bdevp);
- bdput(bdevp);
-
- return 0;
-}
-
-int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
-{
- struct blkpg_ioctl_arg a;
- struct blkpg_partition p;
- int len;
-
- if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
- return -EFAULT;
-
- switch (a.op) {
- case BLKPG_ADD_PARTITION:
- case BLKPG_DEL_PARTITION:
- len = a.datalen;
- if (len < sizeof(struct blkpg_partition))
- return -EINVAL;
- if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
- return -EFAULT;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (a.op == BLKPG_ADD_PARTITION)
- return add_partition(bdev, &p);
- else
- return del_partition(bdev, &p);
- default:
- return -EINVAL;
- }
-}
-
-/*
- * Common ioctl's for block devices
- */
-int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
-{
- request_queue_t *q;
- u64 ullval = 0;
- int intval;
- unsigned short usval;
- kdev_t dev = to_kdev_t(bdev->bd_dev);
- int holder;
- struct backing_dev_info *bdi;
-
- switch (cmd) {
- case BLKROSET:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (get_user(intval, (int *)(arg)))
- return -EFAULT;
- set_device_ro(dev, intval);
- return 0;
- case BLKROGET:
- intval = (bdev_read_only(bdev) != 0);
- return put_user(intval, (int *)(arg));
-
- case BLKRASET:
- case BLKFRASET:
- if(!capable(CAP_SYS_ADMIN))
- return -EACCES;
- bdi = blk_get_backing_dev_info(bdev);
- if (bdi == NULL)
- return -ENOTTY;
- bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
- return 0;
-
- case BLKRAGET:
- case BLKFRAGET:
- if (!arg)
- return -EINVAL;
- bdi = blk_get_backing_dev_info(bdev);
- if (bdi == NULL)
- return -ENOTTY;
- return put_user((bdi->ra_pages * PAGE_CACHE_SIZE) / 512,
- (long *)arg);
-
- case BLKSECTGET:
- if ((q = bdev_get_queue(bdev)) == NULL)
- return -EINVAL;
-
- usval = q->max_sectors;
- blk_put_queue(q);
- return put_user(usval, (unsigned short *)arg);
-
- case BLKFLSBUF:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- fsync_bdev(bdev);
- invalidate_bdev(bdev, 0);
- return 0;
-
- case BLKSSZGET:
- /* get block device hardware sector size */
- intval = bdev_hardsect_size(bdev);
- return put_user(intval, (int *) arg);
-
- case BLKGETSIZE:
- {
- unsigned long ret;
- /* size in sectors, works up to 2 TB */
- ullval = bdev->bd_inode->i_size;
- ret = ullval >> 9;
- if ((u64)ret != (ullval >> 9))
- return -EFBIG;
- return put_user(ret, (unsigned long *) arg);
- }
-
- case BLKGETSIZE64:
- /* size in bytes */
- ullval = bdev->bd_inode->i_size;
- return put_user(ullval, (u64 *) arg);
-
- case BLKPG:
- return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg);
- case BLKBSZGET:
- /* get the logical block size (cf. BLKSSZGET) */
- intval = block_size(bdev);
- return put_user(intval, (int *) arg);
-
- case BLKBSZSET:
- /* set the logical block size */
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (!arg)
- return -EINVAL;
- if (get_user(intval, (int *) arg))
- return -EFAULT;
- if (intval > PAGE_SIZE || intval < 512 ||
- (intval & (intval - 1)))
- return -EINVAL;
- if (bd_claim(bdev, &holder) < 0)
- return -EBUSY;
- set_blocksize(bdev, intval);
- bd_release(bdev);
- return 0;
-
- default:
- return -EINVAL;
- }
-}
diff --git a/drivers/block/block_ioctl.c b/drivers/block/block_ioctl.c
deleted file mode 100644
index edde76503d60..000000000000
--- a/drivers/block/block_ioctl.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public Licens
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
- *
- */
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/config.h>
-#include <linux/swap.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/module.h>
-#include <linux/blk.h>
-#include <linux/completion.h>
-
-#include <linux/cdrom.h>
-
-int blk_do_rq(request_queue_t *q, struct request *rq)
-{
- DECLARE_COMPLETION(wait);
- int err = 0;
-
- rq->flags |= REQ_NOMERGE;
- rq->waiting = &wait;
- elv_add_request(q, rq, 1);
- generic_unplug_device(q);
- wait_for_completion(&wait);
-
- /*
- * for now, never retry anything
- */
- if (rq->errors)
- err = -EIO;
-
- return err;
-}
-
-int block_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
-{
- request_queue_t *q;
- struct request *rq;
- int close = 0, err;
-
- q = bdev_get_queue(bdev);
- if (!q)
- return -ENXIO;
-
- switch (cmd) {
- case CDROMCLOSETRAY:
- close = 1;
- case CDROMEJECT:
- rq = blk_get_request(q, WRITE, __GFP_WAIT);
- rq->flags = REQ_BLOCK_PC;
- memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->cmd[0] = GPCMD_START_STOP_UNIT;
- rq->cmd[4] = 0x02 + (close != 0);
- err = blk_do_rq(q, rq);
- blk_put_request(rq);
- break;
- default:
- err = -ENOTTY;
- }
-
- blk_put_queue(q);
- return err;
-}
-
-EXPORT_SYMBOL(block_ioctl);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index ebd7a216810f..caa30e1c6e84 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -740,7 +740,7 @@ static int revalidate_allvol(kdev_t dev)
for(i=0; i< NWD; i++) {
struct gendisk *disk = hba[ctlr]->gendisk[i];
- if (disk->part)
+ if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
}
@@ -792,7 +792,7 @@ static int deregister_disk(int ctlr, int logvol)
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
/* invalidate the devices and deregister the disk */
- if (disk->part)
+ if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
/* check to see if it was the last disk */
if (logvol == h->highest_lun) {
@@ -2274,7 +2274,7 @@ static int alloc_cciss_hba(void)
struct gendisk *disk[NWD];
int i, n;
for (n = 0; n < NWD; n++) {
- disk[n] = alloc_disk();
+ disk[n] = alloc_disk(1 << NWD_SHIFT);
if (!disk[n])
goto out;
}
@@ -2447,7 +2447,6 @@ static int __init cciss_init_one(struct pci_dev *pdev,
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
disk->major = MAJOR_NR + i;
disk->first_minor = j << NWD_SHIFT;
- disk->minor_shift = NWD_SHIFT;
if( !(drv->nr_blocks))
continue;
(BLK_DEFAULT_QUEUE(MAJOR_NR + i))->hardsect_size = drv->block_size;
@@ -2500,7 +2499,7 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
- if (disk->part)
+ if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
}
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 7bfa29a5bc89..c3b1c4b17ea7 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -304,7 +304,7 @@ static void __exit cpqarray_exit(void)
kfree(hba[i]->cmd_pool_bits);
for (j = 0; j < NWD; j++) {
- if (ida_gendisk[i][j]->part)
+ if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
del_gendisk(ida_gendisk[i][j]);
put_disk(ida_gendisk[i][j]);
}
@@ -358,7 +358,7 @@ static int __init cpqarray_init(void)
}
num_cntlrs_reg++;
for (j=0; j<NWD; j++) {
- ida_gendisk[i][j] = alloc_disk();
+ ida_gendisk[i][j] = alloc_disk(1 << NWD_SHIFT);
if (!ida_gendisk[i][j])
goto Enomem2;
}
@@ -405,7 +405,6 @@ static int __init cpqarray_init(void)
sprintf(disk->disk_name, "ida/c%dd%d", i, j);
disk->major = MAJOR_NR + i;
disk->first_minor = j<<NWD_SHIFT;
- disk->minor_shift = NWD_SHIFT;
disk->flags = GENHD_FL_DEVFS;
disk->fops = &ida_fops;
if (!drv->nr_blks)
@@ -1428,7 +1427,7 @@ static int revalidate_allvol(kdev_t dev)
*/
for (i = 0; i < NWD; i++) {
struct gendisk *disk = ida_gendisk[ctlr][i];
- if (disk->part)
+ if (disk->flags & GENDH_FL_UP)
del_gendisk(disk);
}
memset(hba[ctlr]->drv, 0, sizeof(drv_info_t)*NWD);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 924e1e011f76..3fde460ce7ea 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3488,16 +3488,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
loc.start = 0;
return _COPYOUT(loc);
}
-
- case BLKGETSIZE:
- ECALL(get_floppy_geometry(drive, type, &g));
- return put_user(g->size, (unsigned long *) param);
-
- case BLKGETSIZE64:
- ECALL(get_floppy_geometry(drive, type, &g));
- return put_user((u64)g->size << 9, (u64 *) param);
- /* BLKRRPART is not defined as floppies don't have
- * partition tables */
}
/* convert the old style command into a new style command */
@@ -4240,7 +4230,7 @@ int __init floppy_init(void)
raw_cmd = NULL;
for (i=0; i<N_DRIVE; i++) {
- disks[i] = alloc_disk();
+ disks[i] = alloc_disk(1);
if (!disks[i])
goto Enomem;
}
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 3f6d259165f3..449e69061bbc 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -57,34 +57,13 @@ EXPORT_SYMBOL(blk_set_probe); /* Will go away */
* This function registers the partitioning information in @gp
* with the kernel.
*/
-static void add_gendisk(struct gendisk *gp)
+void add_disk(struct gendisk *disk)
{
- struct hd_struct *p = NULL;
-
- if (gp->minor_shift) {
- size_t size = sizeof(struct hd_struct)*((1<<gp->minor_shift)-1);
- p = kmalloc(size, GFP_KERNEL);
- if (!p) {
- printk(KERN_ERR "out of memory; no partitions for %s\n",
- gp->disk_name);
- gp->minor_shift = 0;
- } else
- memset(p, 0, size);
- }
- gp->part = p;
-
write_lock(&gendisk_lock);
- list_add(&gp->list, &gendisks[gp->major].list);
- if (gp->minor_shift)
- list_add_tail(&gp->full_list, &gendisk_list);
- else
- INIT_LIST_HEAD(&gp->full_list);
+ list_add(&disk->list, &gendisks[disk->major].list);
+ list_add_tail(&disk->full_list, &gendisk_list);
write_unlock(&gendisk_lock);
-}
-
-void add_disk(struct gendisk *disk)
-{
- add_gendisk(disk);
+ disk->flags |= GENHD_FL_UP;
register_disk(disk);
}
@@ -118,6 +97,8 @@ get_gendisk(dev_t dev, int *part)
read_lock(&gendisk_lock);
if (gendisks[major].get) {
disk = gendisks[major].get(minor);
+ if (disk)
+ get_disk(disk);
read_unlock(&gendisk_lock);
return disk;
}
@@ -125,8 +106,9 @@ get_gendisk(dev_t dev, int *part)
disk = list_entry(p, struct gendisk, list);
if (disk->first_minor > minor)
continue;
- if (disk->first_minor + (1<<disk->minor_shift) <= minor)
+ if (disk->first_minor + disk->minors <= minor)
continue;
+ get_disk(disk);
read_unlock(&gendisk_lock);
*part = minor - disk->first_minor;
return disk;
@@ -135,8 +117,6 @@ get_gendisk(dev_t dev, int *part)
return NULL;
}
-EXPORT_SYMBOL(get_gendisk);
-
#ifdef CONFIG_PROC_FS
/* iterator */
static void *part_start(struct seq_file *part, loff_t *pos)
@@ -173,7 +153,7 @@ static int show_partition(struct seq_file *part, void *v)
seq_puts(part, "major minor #blocks name\n\n");
/* Don't show non-partitionable devices or empty devices */
- if (!get_capacity(sgp))
+ if (!get_capacity(sgp) || sgp->minors == 1)
return 0;
/* show the full disk and all non-0 size partitions of it */
@@ -181,7 +161,7 @@ static int show_partition(struct seq_file *part, void *v)
sgp->major, sgp->first_minor,
(unsigned long long)get_capacity(sgp) >> 1,
disk_name(sgp, 0, buf));
- for (n = 0; n < (1<<sgp->minor_shift) - 1; n++) {
+ for (n = 0; n < sgp->minors - 1; n++) {
if (sgp->part[n].nr_sects == 0)
continue;
seq_printf(part, "%4d %4d %10llu %s\n",
@@ -210,6 +190,10 @@ struct device_class disk_devclass = {
.name = "disk",
};
+static struct bus_type disk_bus = {
+ name: "block",
+};
+
int __init device_init(void)
{
int i;
@@ -218,6 +202,7 @@ int __init device_init(void)
INIT_LIST_HEAD(&gendisks[i].list);
blk_dev_init();
devclass_register(&disk_devclass);
+ bus_register(&disk_bus);
return 0;
}
@@ -225,17 +210,51 @@ __initcall(device_init);
EXPORT_SYMBOL(disk_devclass);
-struct gendisk *alloc_disk(void)
+static void disk_release(struct device *dev)
+{
+ struct gendisk *disk = dev->driver_data;
+ kfree(disk->part);
+ kfree(disk);
+}
+
+struct gendisk *alloc_disk(int minors)
{
struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
- if (disk)
+ if (disk) {
memset(disk, 0, sizeof(struct gendisk));
+ if (minors > 1) {
+ int size = (minors - 1) * sizeof(struct hd_struct);
+ disk->part = kmalloc(size, GFP_KERNEL);
+ if (!disk->part) {
+ kfree(disk);
+ return NULL;
+ }
+ memset(disk->part, 0, size);
+ }
+ disk->minors = minors;
+ while (minors >>= 1)
+ disk->minor_shift++;
+ INIT_LIST_HEAD(&disk->full_list);
+ disk->disk_dev.bus = &disk_bus;
+ disk->disk_dev.release = disk_release;
+ disk->disk_dev.driver_data = disk;
+ device_initialize(&disk->disk_dev);
+ }
+ return disk;
+}
+
+struct gendisk *get_disk(struct gendisk *disk)
+{
+ atomic_inc(&disk->disk_dev.refcount);
return disk;
}
void put_disk(struct gendisk *disk)
{
- kfree(disk);
+ if (disk)
+ put_device(&disk->disk_dev);
}
+
EXPORT_SYMBOL(alloc_disk);
+EXPORT_SYMBOL(get_disk);
EXPORT_SYMBOL(put_disk);
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
new file mode 100644
index 000000000000..e420c691763d
--- /dev/null
+++ b/drivers/block/ioctl.c
@@ -0,0 +1,215 @@
+#include <linux/sched.h> /* for capable() */
+#include <linux/blk.h> /* for set_device_ro() */
+#include <linux/blkpg.h>
+#include <linux/backing-dev.h>
+#include <linux/buffer_head.h>
+#include <asm/uaccess.h>
+
+static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
+{
+ struct block_device *bdevp;
+ int holder;
+ struct gendisk *disk;
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+ long long start, length;
+ int part;
+ int i;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
+ return -EFAULT;
+ if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+ return -EFAULT;
+ disk = bdev->bd_disk;
+ if (bdev != bdev->bd_contains)
+ return -EINVAL;
+ part = p.pno;
+ if (part <= 0 || part >= disk->minors)
+ return -EINVAL;
+ switch (a.op) {
+ case BLKPG_ADD_PARTITION:
+ start = p.start >> 9;
+ length = p.length >> 9;
+ /* check for fit in a hd_struct */
+ if (sizeof(sector_t) == sizeof(long) &&
+ sizeof(long long) > sizeof(long)) {
+ long pstart = start, plength = length;
+ if (pstart != start || plength != length
+ || pstart < 0 || plength < 0)
+ return -EINVAL;
+ }
+ /* partition number in use? */
+ if (disk->part[part - 1].nr_sects != 0)
+ return -EBUSY;
+ /* overlap? */
+ for (i = 0; i < disk->minors - 1; i++) {
+ struct hd_struct *s = &disk->part[i];
+ if (!(start+length <= s->start_sect ||
+ start >= s->start_sect + s->nr_sects))
+ return -EBUSY;
+ }
+ /* all seems OK */
+ add_partition(disk, part, start, length);
+ return 0;
+ case BLKPG_DEL_PARTITION:
+ if (disk->part[part - 1].nr_sects == 0)
+ return -ENXIO;
+ /* partition in use? Incomplete check for now. */
+ bdevp = bdget(MKDEV(disk->major, disk->first_minor) + part);
+ if (!bdevp)
+ return -ENOMEM;
+ if (bd_claim(bdevp, &holder) < 0) {
+ bdput(bdevp);
+ return -EBUSY;
+ }
+ /* all seems OK */
+ fsync_bdev(bdevp);
+ invalidate_bdev(bdevp, 0);
+
+ delete_partition(disk, part);
+ bd_release(bdevp);
+ bdput(bdevp);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int blkdev_reread_part(struct block_device *bdev)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ int res;
+
+ if (disk->minors == 1 || bdev != bdev->bd_contains)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (down_trylock(&bdev->bd_sem))
+ return -EBUSY;
+ res = rescan_partitions(disk, bdev);
+ up(&bdev->bd_sem);
+ return res;
+}
+
+static int put_ushort(unsigned long arg, unsigned short val)
+{
+ return put_user(val, (unsigned short *)arg);
+}
+
+static int put_int(unsigned long arg, int val)
+{
+ return put_user(val, (int *)arg);
+}
+
+static int put_long(unsigned long arg, long val)
+{
+ return put_user(val, (long *)arg);
+}
+
+static int put_ulong(unsigned long arg, unsigned long val)
+{
+ return put_user(val, (unsigned long *)arg);
+}
+
+static int put_u64(unsigned long arg, u64 val)
+{
+ return put_user(val, (u64 *)arg);
+}
+
+int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ struct backing_dev_info *bdi;
+ int holder;
+ int ret, n;
+
+ switch (cmd) {
+ case BLKELVGET:
+ case BLKELVSET:
+ /* deprecated, use the /proc/iosched interface instead */
+ return -ENOTTY;
+ case BLKRAGET:
+ case BLKFRAGET:
+ if (!arg)
+ return -EINVAL;
+ bdi = blk_get_backing_dev_info(bdev);
+ if (bdi == NULL)
+ return -ENOTTY;
+ return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
+ case BLKROGET:
+ return put_int(arg, bdev_read_only(bdev) != 0);
+ case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */
+ return put_int(arg, block_size(bdev));
+ case BLKSSZGET: /* get block device hardware sector size */
+ return put_int(arg, bdev_hardsect_size(bdev));
+ case BLKSECTGET:
+ return put_ushort(arg, bdev->bd_queue->max_sectors);
+ case BLKRASET:
+ case BLKFRASET:
+ if(!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ bdi = blk_get_backing_dev_info(bdev);
+ if (bdi == NULL)
+ return -ENOTTY;
+ bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
+ return 0;
+ case BLKBSZSET:
+ /* set the logical block size */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (!arg)
+ return -EINVAL;
+ if (get_user(n, (int *) arg))
+ return -EFAULT;
+ if (n > PAGE_SIZE || n < 512 || (n & (n - 1)))
+ return -EINVAL;
+ if (bd_claim(bdev, &holder) < 0)
+ return -EBUSY;
+ set_blocksize(bdev, n);
+ bd_release(bdev);
+ return 0;
+ case BLKPG:
+ return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg);
+ case BLKRRPART:
+ return blkdev_reread_part(bdev);
+ case BLKGETSIZE:
+ if ((bdev->bd_inode->i_size >> 9) > ~0UL)
+ return -EFBIG;
+ return put_ulong(arg, bdev->bd_inode->i_size >> 9);
+ case BLKGETSIZE64:
+ return put_u64(arg, bdev->bd_inode->i_size);
+ case BLKFLSBUF:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (bdev->bd_op->ioctl) {
+ ret = bdev->bd_op->ioctl(inode, file, cmd, arg);
+ if (ret != -EINVAL)
+ return ret;
+ }
+ fsync_bdev(bdev);
+ invalidate_bdev(bdev, 0);
+ return 0;
+ case BLKROSET:
+ if (bdev->bd_op->ioctl) {
+ ret = bdev->bd_op->ioctl(inode, file, cmd, arg);
+ if (ret != -EINVAL)
+ return ret;
+ }
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (get_user(n, (int *)(arg)))
+ return -EFAULT;
+ set_device_ro(to_kdev_t(bdev->bd_dev), n);
+ return 0;
+ default:
+ if (bdev->bd_op->ioctl) {
+ ret = bdev->bd_op->ioctl(inode, file, cmd, arg);
+ if (ret != -EINVAL)
+ return ret;
+ }
+ }
+ return -ENOTTY;
+}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index ea56c1d8456c..eb877e50a8d1 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1427,7 +1427,19 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
int rw = rq_data_dir(rq);
unsigned int index;
- index = disk_index(rq->rq_dev);
+ if (!rq->rq_disk)
+ return;
+
+ if (rw == READ) {
+ rq->rq_disk->rio += new_io;
+ rq->rq_disk->reads += nr_sectors;
+ } else if (rw == WRITE) {
+ rq->rq_disk->wio += new_io;
+ rq->rq_disk->writes += nr_sectors;
+ }
+
+ index = rq->rq_disk->first_minor >> rq->rq_disk->minor_shift;
+
if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
return;
@@ -1747,6 +1759,7 @@ get_rq:
req->waiting = NULL;
req->bio = req->biotail = bio;
req->rq_dev = to_kdev_t(bio->bi_bdev->bd_dev);
+ req->rq_disk = bio->bi_bdev->bd_disk;
add_request(q, req, insert_here);
out:
if (freereq)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index e39755017faf..14fa8720f8db 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1075,7 +1075,7 @@ int __init loop_init(void)
goto out_mem;
for (i = 0; i < max_loop; i++) {
- disks[i] = alloc_disk();
+ disks[i] = alloc_disk(1);
if (!disks[i])
goto out_mem2;
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index be27027d32b8..27726bd0246a 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -507,7 +507,7 @@ static int __init nbd_init(void)
}
for (i = 0; i < MAX_NBD; i++) {
- struct gendisk *disk = alloc_disk();
+ struct gendisk *disk = alloc_disk(1);
if (!disk)
goto out;
nbd_dev[i].disk = disk;
@@ -537,7 +537,6 @@ static int __init nbd_init(void)
nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
disk->major = MAJOR_NR;
disk->first_minor = i;
- disk->minor_shift = 0;
disk->fops = &nbd_fops;
sprintf(disk->disk_name, "nbd%d", i);
set_capacity(disk, 0x3ffffe);
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index 0e4bac2bd1ef..95bedb2a580c 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -281,7 +281,7 @@ static void pcd_init_units(void)
pcd_drive_count = 0;
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
- struct gendisk *disk = alloc_disk();
+ struct gendisk *disk = alloc_disk(1);
if (!disk)
continue;
cd->disk = disk;
@@ -303,7 +303,6 @@ static void pcd_init_units(void)
cd->info.mask = 0;
disk->major = major;
disk->first_minor = unit;
- disk->minor_shift = 0;
strcpy(disk->disk_name, cd->name); /* umm... */
disk->fops = &pcd_bdops;
}
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 7fdf4a3e4b2a..2278ee4928ab 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -350,9 +350,6 @@ static int pd_open(struct inode *inode, struct file *file)
int unit = DEVICE_NR(inode->i_rdev);
struct pd_unit *disk = pd + unit;
- if (unit >= PD_UNITS || !disk->present)
- return -ENODEV;
-
disk->access++;
if (disk->removable) {
@@ -703,14 +700,13 @@ static int pd_detect(void)
}
for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) {
if (disk->present) {
- struct gendisk *p = alloc_disk();
+ struct gendisk *p = alloc_disk(1 << PD_BITS);
if (!p) {
disk->present = 0;
k--;
continue;
}
strcpy(p->disk_name, disk->name);
- p->minor_shift = PD_BITS;
p->fops = &pd_fops;
p->major = major;
p->first_minor = unit << PD_BITS;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index becf37efd5ec..9598323b5694 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -308,7 +308,7 @@ void pf_init_units(void)
pf_drive_count = 0;
for (unit = 0, pf = units; unit < PF_UNITS; unit++, pf++) {
- struct gendisk *disk = alloc_disk();
+ struct gendisk *disk = alloc_disk(1);
if (!disk)
continue;
pf->disk = disk;
@@ -320,7 +320,6 @@ void pf_init_units(void)
disk->major = MAJOR_NR;
disk->first_minor = unit;
strcpy(disk->disk_name, pf->name);
- disk->minor_shift = 0;
disk->fops = &pf_fops;
if (!(*drives[unit])[D_PRT])
pf_drive_count++;
@@ -332,9 +331,6 @@ static int pf_open(struct inode *inode, struct file *file)
int unit = DEVICE_NR(inode->i_rdev);
struct pf_unit *pf = units + unit;
- if ((unit >= PF_UNITS) || (!pf->present))
- return -ENODEV;
-
pf_identify(pf);
if (pf->media_status == PF_NM)
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 770fbfd4613f..0015ef9a1cd2 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -89,9 +89,6 @@ 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_open(struct inode *inode, struct file *file);
-
static int ps2esdi_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg);
@@ -141,7 +138,6 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
static struct block_device_operations ps2esdi_fops =
{
.owner = THIS_MODULE,
- .open = ps2esdi_open,
.ioctl = ps2esdi_ioctl,
};
@@ -421,13 +417,12 @@ static int __init ps2esdi_geninit(void)
error = -ENOMEM;
for (i = 0; i < ps2esdi_drives; i++) {
- struct gendisk *disk = alloc_disk();
+ struct gendisk *disk = alloc_disk(64);
if (!disk)
goto err_out4;
disk->major = MAJOR_NR;
disk->first_minor = i<<6;
sprintf(disk->disk_name, "ed%c", 'a'+i);
- disk->minor_shift = 6;
disk->fops = &ps2esdi_fops;
ps2esdi_gendisk[i] = disk;
}
@@ -1076,15 +1071,6 @@ static void dump_cmd_complete_status(u_int int_ret_code)
}
-
-static int ps2esdi_open(struct inode *inode, struct file *file)
-{
- int dev = DEVICE_NR(inode->i_rdev);
- if (dev >= ps2esdi_drives)
- return -ENODEV;
- return 0;
-}
-
static int ps2esdi_ioctl(struct inode *inode,
struct file *file, u_int cmd, u_long arg)
{
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index a0e60c5972a6..bbd247fa29dc 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -291,8 +291,6 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
if (cmd != BLKFLSBUF)
return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
/* special: we want to release the ramdisk memory,
it's not like with the other blockdevices where
this ioctl only flushes away the buffer cache. */
@@ -383,6 +381,7 @@ static int rd_open(struct inode * inode, struct file * filp)
rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
rd_bdev[unit]->bd_inode->i_size = rd_length[unit];
rd_bdev[unit]->bd_queue = &blk_dev[MAJOR_NR].request_queue;
+ rd_bdev[unit]->bd_disk = get_disk(rd_disks[unit]);
}
return 0;
@@ -431,17 +430,16 @@ static int __init rd_init (void)
}
#ifdef CONFIG_BLK_DEV_INITRD
- initrd_disk = alloc_disk();
+ initrd_disk = alloc_disk(1);
if (!initrd_disk)
return -ENOMEM;
initrd_disk->major = MAJOR_NR;
initrd_disk->first_minor = INITRD_MINOR;
- initrd_disk->minor_shift = 0;
initrd_disk->fops = &rd_bd_op;
sprintf(initrd_disk->disk_name, "initrd");
#endif
for (i = 0; i < NUM_RAMDISKS; i++) {
- rd_disks[i] = alloc_disk();
+ rd_disks[i] = alloc_disk(1);
if (!rd_disks[i])
goto out;
}
@@ -460,7 +458,6 @@ static int __init rd_init (void)
rd_length[i] = rd_size << 10;
disk->major = MAJOR_NR;
disk->first_minor = i;
- disk->minor_shift = 0;
disk->fops = &rd_bd_op;
sprintf(disk->disk_name, "rd%d", i);
set_capacity(disk, rd_size * 2);
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
new file mode 100644
index 000000000000..1f7ef11b1c62
--- /dev/null
+++ b/drivers/block/scsi_ioctl.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
+ *
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/module.h>
+#include <linux/blk.h>
+#include <linux/completion.h>
+#include <linux/cdrom.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+
+#include <asm/uaccess.h>
+
+int blk_do_rq(request_queue_t *q, struct request *rq)
+{
+ DECLARE_COMPLETION(wait);
+ int err = 0;
+
+ rq->flags |= REQ_NOMERGE;
+ rq->waiting = &wait;
+ elv_add_request(q, rq, 1);
+ generic_unplug_device(q);
+ wait_for_completion(&wait);
+
+ /*
+ * for now, never retry anything
+ */
+ if (rq->errors)
+ err = -EIO;
+
+ return err;
+}
+
+#include <scsi/sg.h>
+
+static int sg_get_version(int *p)
+{
+ static int sg_version_num = 30527;
+ return put_user(sg_version_num, p);
+}
+
+static int scsi_get_idlun(request_queue_t *q, int *p)
+{
+ return put_user(0, p);
+}
+
+static int scsi_get_bus(request_queue_t *q, int *p)
+{
+ return put_user(0, p);
+}
+
+static int sg_get_timeout(request_queue_t *q)
+{
+ return HZ;
+}
+
+static int sg_set_timeout(request_queue_t *q, int *p)
+{
+ int timeout;
+ int error = get_user(timeout, p);
+ return error;
+}
+
+static int reserved_size = 0;
+
+static int sg_get_reserved_size(request_queue_t *q, int *p)
+{
+ return put_user(reserved_size, p);
+}
+
+static int sg_set_reserved_size(request_queue_t *q, int *p)
+{
+ int size;
+ int error = get_user(size, p);
+ if (!error)
+ reserved_size = size;
+ return error;
+}
+
+static int sg_emulated_host(request_queue_t *q, int *p)
+{
+ return put_user(1, p);
+}
+
+static int sg_io(request_queue_t *q, struct sg_io_hdr *uptr)
+{
+ int err;
+ struct sg_io_hdr hdr;
+ struct request *rq;
+ void *buffer;
+
+ if (!access_ok(VERIFY_WRITE, uptr, sizeof(*uptr)))
+ return -EFAULT;
+ if (copy_from_user(&hdr, uptr, sizeof(*uptr)))
+ return -EFAULT;
+
+ if ( hdr.cmd_len > sizeof(rq->cmd) )
+ return -EINVAL;
+
+ buffer = NULL;
+ if (hdr.dxfer_len) {
+ unsigned int bytes = (hdr.dxfer_len + 511) & ~511;
+
+ switch (hdr.dxfer_direction) {
+ default:
+ return -EINVAL;
+ case SG_DXFER_TO_DEV:
+ case SG_DXFER_FROM_DEV:
+ case SG_DXFER_TO_FROM_DEV:
+ break;
+ }
+ buffer = kmalloc(bytes, GFP_USER);
+ if (!buffer)
+ return -ENOMEM;
+ if (hdr.dxfer_direction == SG_DXFER_TO_DEV ||
+ hdr.dxfer_direction == SG_DXFER_TO_FROM_DEV)
+ copy_from_user(buffer, hdr.dxferp, hdr.dxfer_len);
+ }
+
+ rq = blk_get_request(q, WRITE, __GFP_WAIT);
+ rq->timeout = 60*HZ;
+ rq->data = buffer;
+ rq->data_len = hdr.dxfer_len;
+ rq->flags = REQ_BLOCK_PC;
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ copy_from_user(rq->cmd, hdr.cmdp, hdr.cmd_len);
+ err = blk_do_rq(q, rq);
+
+ blk_put_request(rq);
+
+ copy_to_user(uptr, &hdr, sizeof(*uptr));
+ if (buffer) {
+ if (hdr.dxfer_direction == SG_DXFER_FROM_DEV ||
+ hdr.dxfer_direction == SG_DXFER_TO_FROM_DEV)
+ copy_to_user(hdr.dxferp, buffer, hdr.dxfer_len);
+ kfree(buffer);
+ }
+ return err;
+}
+
+int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
+{
+ request_queue_t *q;
+ struct request *rq;
+ int close = 0, err;
+
+ q = bdev_get_queue(bdev);
+ if (!q)
+ return -ENXIO;
+
+ switch (cmd) {
+ case SG_GET_VERSION_NUM:
+ return sg_get_version((int *) arg);
+ case SCSI_IOCTL_GET_IDLUN:
+ return scsi_get_idlun(q, (int *) arg);
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ return scsi_get_bus(q, (int *) arg);
+ case SG_SET_TIMEOUT:
+ return sg_set_timeout(q, (int *) arg);
+ case SG_GET_TIMEOUT:
+ return sg_get_timeout(q);
+ case SG_GET_RESERVED_SIZE:
+ return sg_get_reserved_size(q, (int *) arg);
+ case SG_SET_RESERVED_SIZE:
+ return sg_set_reserved_size(q, (int *) arg);
+ case SG_EMULATED_HOST:
+ return sg_emulated_host(q, (int *) arg);
+ case SG_IO:
+ return sg_io(q, (struct sg_io_hdr *) arg);
+ case CDROMCLOSETRAY:
+ close = 1;
+ case CDROMEJECT:
+ rq = blk_get_request(q, WRITE, __GFP_WAIT);
+ rq->flags = REQ_BLOCK_PC;
+ rq->data = NULL;
+ rq->data_len = 0;
+ rq->timeout = 60*HZ;
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->cmd[0] = GPCMD_START_STOP_UNIT;
+ rq->cmd[4] = 0x02 + (close != 0);
+ err = blk_do_rq(q, rq);
+ blk_put_request(rq);
+ break;
+ default:
+ err = -ENOTTY;
+ }
+
+ blk_put_queue(q);
+ return err;
+}
+
+EXPORT_SYMBOL(scsi_cmd_ioctl);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index b1cb36f3ca5c..2a5f3afefbfa 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1037,7 +1037,7 @@ int swim3_init(void)
return -ENODEV;
for (i = 0; i < floppy_count; i++) {
- disks[i] = alloc_disk();
+ disks[i] = alloc_disk(1);
if (!disks[i])
goto out;
}
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 29c2f1696063..3ec747c3f80f 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -188,7 +188,7 @@ int swimiop_init(void)
printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
for (i = 0; i < floppy_count; i++) {
- struct gendisk *disk = alloc_disk();
+ struct gendisk *disk = alloc_disk(1);
if (!disk)
continue;
disk->major = MAJOR_NR;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 53dfd2a7c624..4a2b212f1261 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -864,18 +864,6 @@ static int mm_check_change(kdev_t i_rdev)
return 0;
}
-
-/*
------------------------------------------------------------------------------------
--- mm_open
------------------------------------------------------------------------------------
-*/
-static int mm_open(struct inode *i, struct file *filp)
-{
- if (DEVICE_NR(i->i_rdev) >= num_cards)
- return -ENXIO;
- return 0;
-}
/*
-----------------------------------------------------------------------------------
-- mm_fops
@@ -883,7 +871,6 @@ static int mm_open(struct inode *i, struct file *filp)
*/
static struct block_device_operations mm_fops = {
owner: THIS_MODULE,
- open: mm_open,
ioctl: mm_ioctl,
revalidate: mm_revalidate,
check_media_change: mm_check_change,
@@ -1190,7 +1177,7 @@ int __init mm_init(void)
}
for (i = 0; i < num_cards; i++) {
- mm_gendisk[i] = alloc_disk();
+ mm_gendisk[i] = alloc_disk(1 << MM_SHIFT);
if (!mm_gendisk[i])
goto out;
}
@@ -1203,7 +1190,6 @@ int __init mm_init(void)
spin_lock_init(&cards[i].lock);
disk->major = major_nr;
disk->first_minor = i << MM_SHIFT;
- disk->minor_shift = MM_SHIFT;
disk->fops = &mm_fops;
set_capacity(disk, cards[i].mm_size << 1);
add_disk(disk);
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 3e3315e81bde..939901490525 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -130,7 +130,6 @@ static struct gendisk *xd_gendisk[2];
static struct block_device_operations xd_fops = {
owner: THIS_MODULE,
- open: xd_open,
ioctl: xd_ioctl,
};
static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
@@ -205,12 +204,11 @@ static int __init xd_init(void)
goto out3;
for (i = 0; i < xd_drives; i++) {
- struct gendisk *disk = alloc_disk();
+ struct gendisk *disk = alloc_disk(64);
if (!disk)
goto Enomem;
disk->major = MAJOR_NR;
disk->first_minor = i<<6;
- disk->minor_shift = 6;
sprintf(disk->disk_name, "xd%c", i+'a');
disk->fops = &xd_fops;
xd_gendisk[i] = disk;
@@ -284,15 +282,6 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address)
return (found);
}
-/* xd_open: open a device */
-static int xd_open (struct inode *inode,struct file *file)
-{
- int dev = DEVICE_NR(inode->i_rdev);
- if (dev >= xd_drives)
- return -ENXIO;
- return 0;
-}
-
/* do_xd_request: handle an incoming request */
static void do_xd_request (request_queue_t * q)
{
@@ -337,8 +326,6 @@ static void do_xd_request (request_queue_t * q)
static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
{
int dev = DEVICE_NR(inode->i_rdev);
-
- if (dev >= xd_drives) return -EINVAL;
switch (cmd) {
case HDIO_GETGEO:
{
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 30625811de3e..edb2676680e3 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -365,14 +365,13 @@ z2_init( void )
MAJOR_NR );
return -EBUSY;
}
- z2ram_gendisk = alloc_disk();
+ z2ram_gendisk = alloc_disk(1);
if (!z2ram_gendisk) {
unregister_blkdev( MAJOR_NR, DEVICE_NAME );
return -ENOMEM;
}
z2ram_gendisk->major = MAJOR_NR;
z2ram_gendisk->first_minor = 0;
- z2ram_gendisk->minor_shift = 0;
z2ram_gendisk->fops = &z2_fops;
sprintf(z2ram_gendisk->disk_name, "z2ram");