summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/bsg.c9
-rw-r--r--block/cmd-filter.c2
-rw-r--r--block/compat_ioctl.c177
-rw-r--r--block/genhd.c37
-rw-r--r--block/ioctl.c173
-rw-r--r--block/scsi_ioctl.c33
6 files changed, 214 insertions, 217 deletions
diff --git a/block/bsg.c b/block/bsg.c
index 034112bfe1f3..e8bd2475682a 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -173,7 +173,7 @@ unlock:
static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
struct sg_io_v4 *hdr, struct bsg_device *bd,
- int has_write_perm)
+ fmode_t has_write_perm)
{
if (hdr->request_len > BLK_MAX_CDB) {
rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
@@ -242,7 +242,7 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
* map sg_io_v4 to a request.
*/
static struct request *
-bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm)
+bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
{
struct request_queue *q = bd->queue;
struct request *rq, *next_rq = NULL;
@@ -601,7 +601,8 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
}
static int __bsg_write(struct bsg_device *bd, const char __user *buf,
- size_t count, ssize_t *bytes_written, int has_write_perm)
+ size_t count, ssize_t *bytes_written,
+ fmode_t has_write_perm)
{
struct bsg_command *bc;
struct request *rq;
@@ -913,7 +914,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case SG_EMULATED_HOST:
case SCSI_IOCTL_SEND_COMMAND: {
void __user *uarg = (void __user *) arg;
- return scsi_cmd_ioctl(file, bd->queue, NULL, cmd, uarg);
+ return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
}
case SG_IO: {
struct request *rq;
diff --git a/block/cmd-filter.c b/block/cmd-filter.c
index e669aed4c6bc..504b275e1b90 100644
--- a/block/cmd-filter.c
+++ b/block/cmd-filter.c
@@ -27,7 +27,7 @@
#include <linux/cdrom.h>
int blk_verify_command(struct blk_cmd_filter *filter,
- unsigned char *cmd, int has_write_perm)
+ unsigned char *cmd, fmode_t has_write_perm)
{
/* root can do any command. */
if (capable(CAP_SYS_RAWIO))
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 1e559fba7bdf..3d3e7a46f38c 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -71,8 +71,8 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
return ret;
}
-static int compat_hdio_ioctl(struct inode *inode, struct file *file,
- struct gendisk *disk, unsigned int cmd, unsigned long arg)
+static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
unsigned long kval;
@@ -80,7 +80,7 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file,
int error;
set_fs(KERNEL_DS);
- error = blkdev_driver_ioctl(inode, file, disk,
+ error = __blkdev_driver_ioctl(bdev, mode,
cmd, (unsigned long)(&kval));
set_fs(old_fs);
@@ -111,8 +111,8 @@ struct compat_cdrom_generic_command {
compat_caddr_t reserved[1];
};
-static int compat_cdrom_read_audio(struct inode *inode, struct file *file,
- struct gendisk *disk, unsigned int cmd, unsigned long arg)
+static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
struct cdrom_read_audio __user *cdread_audio;
struct compat_cdrom_read_audio __user *cdread_audio32;
@@ -134,12 +134,12 @@ static int compat_cdrom_read_audio(struct inode *inode, struct file *file,
if (put_user(datap, &cdread_audio->buf))
return -EFAULT;
- return blkdev_driver_ioctl(inode, file, disk, cmd,
+ return __blkdev_driver_ioctl(bdev, mode, cmd,
(unsigned long)cdread_audio);
}
-static int compat_cdrom_generic_command(struct inode *inode, struct file *file,
- struct gendisk *disk, unsigned int cmd, unsigned long arg)
+static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
struct cdrom_generic_command __user *cgc;
struct compat_cdrom_generic_command __user *cgc32;
@@ -167,7 +167,7 @@ static int compat_cdrom_generic_command(struct inode *inode, struct file *file,
put_user(compat_ptr(data), &cgc->reserved[0]))
return -EFAULT;
- return blkdev_driver_ioctl(inode, file, disk, cmd, (unsigned long)cgc);
+ return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
}
struct compat_blkpg_ioctl_arg {
@@ -177,7 +177,7 @@ struct compat_blkpg_ioctl_arg {
compat_caddr_t data;
};
-static int compat_blkpg_ioctl(struct inode *inode, struct file *file,
+static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
{
struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
@@ -196,7 +196,7 @@ static int compat_blkpg_ioctl(struct inode *inode, struct file *file,
if (err)
return err;
- return blkdev_ioctl(inode, file, cmd, (unsigned long)a);
+ return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
}
#define BLKBSZGET_32 _IOR(0x12, 112, int)
@@ -308,8 +308,8 @@ static struct {
#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
-static int compat_fd_ioctl(struct inode *inode, struct file *file,
- struct gendisk *disk, unsigned int cmd, unsigned long arg)
+static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
void *karg = NULL;
@@ -413,7 +413,7 @@ static int compat_fd_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
set_fs(KERNEL_DS);
- err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)karg);
+ err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
set_fs(old_fs);
if (err)
goto out;
@@ -579,11 +579,9 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
return 0;
}
-static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
- struct gendisk *disk, unsigned cmd, unsigned long arg)
+static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
- int ret;
-
switch (cmd) {
case HDIO_GET_UNMASKINTR:
case HDIO_GET_MULTCOUNT:
@@ -596,7 +594,7 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
case HDIO_GET_ACOUSTIC:
case HDIO_GET_ADDRESS:
case HDIO_GET_BUSSTATE:
- return compat_hdio_ioctl(inode, file, disk, cmd, arg);
+ return compat_hdio_ioctl(bdev, mode, cmd, arg);
case FDSETPRM32:
case FDDEFPRM32:
case FDGETPRM32:
@@ -606,11 +604,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
case FDPOLLDRVSTAT32:
case FDGETFDCSTAT32:
case FDWERRORGET32:
- return compat_fd_ioctl(inode, file, disk, cmd, arg);
+ return compat_fd_ioctl(bdev, mode, cmd, arg);
case CDROMREADAUDIO:
- return compat_cdrom_read_audio(inode, file, disk, cmd, arg);
+ return compat_cdrom_read_audio(bdev, mode, cmd, arg);
case CDROM_SEND_PACKET:
- return compat_cdrom_generic_command(inode, file, disk, cmd, arg);
+ return compat_cdrom_generic_command(bdev, mode, cmd, arg);
/*
* No handler required for the ones below, we just need to
@@ -679,55 +677,49 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
case DVD_WRITE_STRUCT:
case DVD_AUTH:
arg = (unsigned long)compat_ptr(arg);
- /* These intepret arg as an unsigned long, not as a pointer,
- * so we must not do compat_ptr() conversion. */
- case HDIO_SET_MULTCOUNT:
- case HDIO_SET_UNMASKINTR:
- case HDIO_SET_KEEPSETTINGS:
- case HDIO_SET_32BIT:
- case HDIO_SET_NOWERR:
- case HDIO_SET_DMA:
- case HDIO_SET_PIO_MODE:
- case HDIO_SET_NICE:
- case HDIO_SET_WCACHE:
- case HDIO_SET_ACOUSTIC:
- case HDIO_SET_BUSSTATE:
- case HDIO_SET_ADDRESS:
- case CDROMEJECT_SW:
- case CDROM_SET_OPTIONS:
- case CDROM_CLEAR_OPTIONS:
- case CDROM_SELECT_SPEED:
- case CDROM_SELECT_DISC:
- case CDROM_MEDIA_CHANGED:
- case CDROM_DRIVE_STATUS:
- case CDROM_LOCKDOOR:
- case CDROM_DEBUG:
break;
default:
/* unknown ioctl number */
return -ENOIOCTLCMD;
}
- if (disk->fops->unlocked_ioctl)
- return disk->fops->unlocked_ioctl(file, cmd, arg);
-
- if (disk->fops->ioctl) {
- lock_kernel();
- ret = disk->fops->ioctl(inode, file, cmd, arg);
- unlock_kernel();
- return ret;
- }
-
- return -ENOTTY;
+ return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
-static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
- struct block_device *bdev,
- unsigned cmd, unsigned long arg)
+/* Most of the generic ioctls are handled in the normal fallback path.
+ This assumes the blkdev's low level compat_ioctl always returns
+ ENOIOCTLCMD for unknown ioctls. */
+long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
+ int ret = -ENOIOCTLCMD;
+ struct inode *inode = file->f_mapping->host;
+ struct block_device *bdev = inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ fmode_t mode = file->f_mode;
struct backing_dev_info *bdi;
+ loff_t size;
+
+ if (file->f_flags & O_NDELAY)
+ mode |= FMODE_NDELAY_NOW;
switch (cmd) {
+ case HDIO_GETGEO:
+ return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
+ case BLKFLSBUF:
+ case BLKROSET:
+ case BLKDISCARD:
+ /*
+ * the ones below are implemented in blkdev_locked_ioctl,
+ * but we call blkdev_ioctl, which gets the lock for us
+ */
+ case BLKRRPART:
+ return blkdev_ioctl(bdev, mode, cmd,
+ (unsigned long)compat_ptr(arg));
+ case BLKBSZSET_32:
+ return blkdev_ioctl(bdev, mode, BLKBSZSET,
+ (unsigned long)compat_ptr(arg));
+ case BLKPG:
+ return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
case BLKRAGET:
case BLKFRAGET:
if (!arg)
@@ -753,65 +745,36 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
return -ENOTTY;
+ lock_kernel();
bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
+ unlock_kernel();
return 0;
case BLKGETSIZE:
- if ((bdev->bd_inode->i_size >> 9) > ~0UL)
+ size = bdev->bd_inode->i_size;
+ if ((size >> 9) > ~0UL)
return -EFBIG;
- return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9);
+ return compat_put_ulong(arg, size >> 9);
case BLKGETSIZE64_32:
return compat_put_u64(arg, bdev->bd_inode->i_size);
case BLKTRACESETUP32:
- return compat_blk_trace_setup(bdev, compat_ptr(arg));
+ lock_kernel();
+ ret = compat_blk_trace_setup(bdev, compat_ptr(arg));
+ unlock_kernel();
+ return ret;
case BLKTRACESTART: /* compatible */
case BLKTRACESTOP: /* compatible */
case BLKTRACETEARDOWN: /* compatible */
- return blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
- }
- return -ENOIOCTLCMD;
-}
-
-/* Most of the generic ioctls are handled in the normal fallback path.
- This assumes the blkdev's low level compat_ioctl always returns
- ENOIOCTLCMD for unknown ioctls. */
-long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
-{
- int ret = -ENOIOCTLCMD;
- struct inode *inode = file->f_mapping->host;
- struct block_device *bdev = inode->i_bdev;
- struct gendisk *disk = bdev->bd_disk;
-
- switch (cmd) {
- case HDIO_GETGEO:
- return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
- case BLKFLSBUF:
- case BLKROSET:
- case BLKDISCARD:
- /*
- * the ones below are implemented in blkdev_locked_ioctl,
- * but we call blkdev_ioctl, which gets the lock for us
- */
- case BLKRRPART:
- return blkdev_ioctl(inode, file, cmd,
- (unsigned long)compat_ptr(arg));
- case BLKBSZSET_32:
- return blkdev_ioctl(inode, file, BLKBSZSET,
- (unsigned long)compat_ptr(arg));
- case BLKPG:
- return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg));
- }
-
- lock_kernel();
- ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg);
- /* FIXME: why do we assume -> compat_ioctl needs the BKL? */
- if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
- ret = disk->fops->compat_ioctl(file, cmd, arg);
- unlock_kernel();
-
- if (ret != -ENOIOCTLCMD)
+ lock_kernel();
+ ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
+ unlock_kernel();
return ret;
-
- return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ default:
+ if (disk->fops->compat_ioctl)
+ ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
+ if (ret == -ENOIOCTLCMD)
+ ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
+ return ret;
+ }
}
diff --git a/block/genhd.c b/block/genhd.c
index 646e1d2507c7..4e5e7493f676 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -10,6 +10,7 @@
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -727,12 +728,24 @@ static int show_partition(struct seq_file *seqf, void *v)
return 0;
}
-const struct seq_operations partitions_op = {
+static const struct seq_operations partitions_op = {
.start = show_partition_start,
.next = disk_seqf_next,
.stop = disk_seqf_stop,
.show = show_partition
};
+
+static int partitions_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &partitions_op);
+}
+
+static const struct file_operations proc_partitions_operations = {
+ .open = partitions_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
#endif
@@ -992,12 +1005,32 @@ static int diskstats_show(struct seq_file *seqf, void *v)
return 0;
}
-const struct seq_operations diskstats_op = {
+static const struct seq_operations diskstats_op = {
.start = disk_seqf_start,
.next = disk_seqf_next,
.stop = disk_seqf_stop,
.show = diskstats_show
};
+
+static int diskstats_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &diskstats_op);
+}
+
+static const struct file_operations proc_diskstats_operations = {
+ .open = diskstats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init proc_genhd_init(void)
+{
+ proc_create("diskstats", 0, NULL, &proc_diskstats_operations);
+ proc_create("partitions", 0, NULL, &proc_partitions_operations);
+ return 0;
+}
+module_init(proc_genhd_init);
#endif /* CONFIG_PROC_FS */
static void media_change_notify_thread(struct work_struct *work)
diff --git a/block/ioctl.c b/block/ioctl.c
index 38bee321e1fa..c832d639b6e2 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -201,97 +201,41 @@ static int put_u64(unsigned long arg, u64 val)
return put_user(val, (u64 __user *)arg);
}
-static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
- unsigned cmd, unsigned long arg)
-{
- struct backing_dev_info *bdi;
- int ret, n;
-
- switch (cmd) {
- 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_get_queue(bdev)->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 __user *) arg))
- return -EFAULT;
- if (bd_claim(bdev, file) < 0)
- return -EBUSY;
- ret = set_blocksize(bdev, n);
- bd_release(bdev);
- return ret;
- case BLKPG:
- return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) 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 BLKTRACESTART:
- case BLKTRACESTOP:
- case BLKTRACESETUP:
- case BLKTRACETEARDOWN:
- return blk_trace_ioctl(bdev, cmd, (char __user *) arg);
- }
- return -ENOIOCTLCMD;
-}
-
-int blkdev_driver_ioctl(struct inode *inode, struct file *file,
- struct gendisk *disk, unsigned cmd, unsigned long arg)
+int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned cmd, unsigned long arg)
{
+ struct gendisk *disk = bdev->bd_disk;
int ret;
- if (disk->fops->unlocked_ioctl)
- return disk->fops->unlocked_ioctl(file, cmd, arg);
- if (disk->fops->ioctl) {
+ if (disk->fops->ioctl)
+ return disk->fops->ioctl(bdev, mode, cmd, arg);
+
+ if (disk->fops->locked_ioctl) {
lock_kernel();
- ret = disk->fops->ioctl(inode, file, cmd, arg);
+ ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg);
unlock_kernel();
return ret;
}
return -ENOTTY;
}
-EXPORT_SYMBOL_GPL(blkdev_driver_ioctl);
+/*
+ * For the record: _GPL here is only because somebody decided to slap it
+ * on the previous export. Sheer idiocy, since it wasn't copyrightable
+ * at all and could be open-coded without any exports by anybody who cares.
+ */
+EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl);
/*
* always keep this in sync with compat_blkdev_ioctl() and
* compat_blkdev_locked_ioctl()
*/
-int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
+ struct backing_dev_info *bdi;
+ loff_t size;
int ret, n;
switch(cmd) {
@@ -299,7 +243,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
/* -EINVAL to handle old uncorrected drivers */
if (ret != -EINVAL && ret != -ENOTTY)
return ret;
@@ -311,7 +255,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
return 0;
case BLKROSET:
- ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
/* -EINVAL to handle old uncorrected drivers */
if (ret != -EINVAL && ret != -ENOTTY)
return ret;
@@ -327,7 +271,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
case BLKDISCARD: {
uint64_t range[2];
- if (!(file->f_mode & FMODE_WRITE))
+ if (!(mode & FMODE_WRITE))
return -EBADF;
if (copy_from_user(range, (void __user *)arg, sizeof(range)))
@@ -357,14 +301,75 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
return -EFAULT;
return 0;
}
- }
-
- lock_kernel();
- ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
- unlock_kernel();
- if (ret != -ENOIOCTLCMD)
+ 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_get_queue(bdev)->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;
+ lock_kernel();
+ bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
+ unlock_kernel();
+ 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 __user *) arg))
+ return -EFAULT;
+ if (!(mode & FMODE_EXCL) && bd_claim(bdev, &bdev) < 0)
+ return -EBUSY;
+ ret = set_blocksize(bdev, n);
+ if (!(mode & FMODE_EXCL))
+ bd_release(bdev);
return ret;
-
- return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ case BLKPG:
+ lock_kernel();
+ ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
+ unlock_kernel();
+ break;
+ case BLKRRPART:
+ lock_kernel();
+ ret = blkdev_reread_part(bdev);
+ unlock_kernel();
+ break;
+ case BLKGETSIZE:
+ size = bdev->bd_inode->i_size;
+ if ((size >> 9) > ~0UL)
+ return -EFBIG;
+ return put_ulong(arg, size >> 9);
+ case BLKGETSIZE64:
+ return put_u64(arg, bdev->bd_inode->i_size);
+ case BLKTRACESTART:
+ case BLKTRACESTOP:
+ case BLKTRACESETUP:
+ case BLKTRACETEARDOWN:
+ lock_kernel();
+ ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg);
+ unlock_kernel();
+ break;
+ default:
+ ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+ }
+ return ret;
}
EXPORT_SYMBOL_GPL(blkdev_ioctl);
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index c34272a348fe..5963cf91a3a0 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -190,12 +190,11 @@ void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults);
static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
- struct sg_io_hdr *hdr, struct file *file)
+ struct sg_io_hdr *hdr, fmode_t mode)
{
if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
return -EFAULT;
- if (blk_verify_command(&q->cmd_filter, rq->cmd,
- file->f_mode & FMODE_WRITE))
+ if (blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE))
return -EPERM;
/*
@@ -260,8 +259,8 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
return r;
}
-static int sg_io(struct file *file, struct request_queue *q,
- struct gendisk *bd_disk, struct sg_io_hdr *hdr)
+static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
+ struct sg_io_hdr *hdr, fmode_t mode)
{
unsigned long start_time;
int writing = 0, ret = 0;
@@ -293,7 +292,7 @@ static int sg_io(struct file *file, struct request_queue *q,
if (!rq)
return -ENOMEM;
- if (blk_fill_sghdr_rq(q, rq, hdr, file)) {
+ if (blk_fill_sghdr_rq(q, rq, hdr, mode)) {
blk_put_request(rq);
return -EFAULT;
}
@@ -380,11 +379,11 @@ out:
* bytes in one int) where the lowest byte is the SCSI status.
*/
#define OMAX_SB_LEN 16 /* For backward compatibility */
-int sg_scsi_ioctl(struct file *file, struct request_queue *q,
- struct gendisk *disk, struct scsi_ioctl_command __user *sic)
+int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
+ struct scsi_ioctl_command __user *sic)
{
struct request *rq;
- int err, write_perm = 0;
+ int err;
unsigned int in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
@@ -426,11 +425,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
goto error;
- /* scsi_ioctl passes NULL */
- if (file && (file->f_mode & FMODE_WRITE))
- write_perm = 1;
-
- err = blk_verify_command(&q->cmd_filter, rq->cmd, write_perm);
+ err = blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE);
if (err)
goto error;
@@ -522,8 +517,8 @@ static inline int blk_send_start_stop(struct request_queue *q,
return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data);
}
-int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
- struct gendisk *bd_disk, unsigned int cmd, void __user *arg)
+int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode,
+ unsigned int cmd, void __user *arg)
{
int err;
@@ -564,7 +559,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
err = -EFAULT;
if (copy_from_user(&hdr, arg, sizeof(hdr)))
break;
- err = sg_io(file, q, bd_disk, &hdr);
+ err = sg_io(q, bd_disk, &hdr, mode);
if (err == -EFAULT)
break;
@@ -612,7 +607,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
hdr.cmd_len = sizeof(cgc.cmd);
- err = sg_io(file, q, bd_disk, &hdr);
+ err = sg_io(q, bd_disk, &hdr, mode);
if (err == -EFAULT)
break;
@@ -636,7 +631,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q,
if (!arg)
break;
- err = sg_scsi_ioctl(file, q, bd_disk, arg);
+ err = sg_scsi_ioctl(q, bd_disk, mode, arg);
break;
case CDROMCLOSETRAY:
err = blk_send_start_stop(q, bd_disk, 0x03);