diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2002-10-15 07:41:35 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2002-10-15 07:41:35 -0700 |
| commit | 8fbfe7cd5594010a23cb4e81786d1fb8015ffdee (patch) | |
| tree | b5be190f22984395209823ec3cac1c76fc93f67f /drivers/block | |
| parent | e22f7f5fd43205bfd20ea3a7bb4e689cb3f3d278 (diff) | |
| parent | 5a7728c6d3eb83df9d120944cca4cf476dd326a1 (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.c | 3 | ||||
| -rw-r--r-- | drivers/block/Makefile | 4 | ||||
| -rw-r--r-- | drivers/block/acsi.c | 18 | ||||
| -rw-r--r-- | drivers/block/amiflop.c | 11 | ||||
| -rw-r--r-- | drivers/block/ataflop.c | 20 | ||||
| -rw-r--r-- | drivers/block/blkpg.c | 310 | ||||
| -rw-r--r-- | drivers/block/block_ioctl.c | 83 | ||||
| -rw-r--r-- | drivers/block/cciss.c | 9 | ||||
| -rw-r--r-- | drivers/block/cpqarray.c | 7 | ||||
| -rw-r--r-- | drivers/block/floppy.c | 12 | ||||
| -rw-r--r-- | drivers/block/genhd.c | 85 | ||||
| -rw-r--r-- | drivers/block/ioctl.c | 215 | ||||
| -rw-r--r-- | drivers/block/ll_rw_blk.c | 15 | ||||
| -rw-r--r-- | drivers/block/loop.c | 2 | ||||
| -rw-r--r-- | drivers/block/nbd.c | 3 | ||||
| -rw-r--r-- | drivers/block/paride/pcd.c | 3 | ||||
| -rw-r--r-- | drivers/block/paride/pd.c | 6 | ||||
| -rw-r--r-- | drivers/block/paride/pf.c | 6 | ||||
| -rw-r--r-- | drivers/block/ps2esdi.c | 16 | ||||
| -rw-r--r-- | drivers/block/rd.c | 9 | ||||
| -rw-r--r-- | drivers/block/scsi_ioctl.c | 215 | ||||
| -rw-r--r-- | drivers/block/swim3.c | 2 | ||||
| -rw-r--r-- | drivers/block/swim_iop.c | 2 | ||||
| -rw-r--r-- | drivers/block/umem.c | 16 | ||||
| -rw-r--r-- | drivers/block/xd.c | 15 | ||||
| -rw-r--r-- | drivers/block/z2ram.c | 3 |
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"); |
