Commit 22484856 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/viro/bdev

* git://git.kernel.org/pub/scm/linux/kernel/git/viro/bdev: (66 commits)
  [PATCH] kill the rest of struct file propagation in block ioctls
  [PATCH] get rid of struct file use in blkdev_ioctl() BLKBSZSET
  [PATCH] get rid of blkdev_locked_ioctl()
  [PATCH] get rid of blkdev_driver_ioctl()
  [PATCH] sanitize blkdev_get() and friends
  [PATCH] remember mode of reiserfs journal
  [PATCH] propagate mode through swsusp_close()
  [PATCH] propagate mode through open_bdev_excl/close_bdev_excl
  [PATCH] pass fmode_t to blkdev_put()
  [PATCH] kill the unused bsize on the send side of /dev/loop
  [PATCH] trim file propagation in block/compat_ioctl.c
  [PATCH] end of methods switch: remove the old ones
  [PATCH] switch sr
  [PATCH] switch sd
  [PATCH] switch ide-scsi
  [PATCH] switch tape_block
  [PATCH] switch dcssblk
  [PATCH] switch dasd
  [PATCH] switch mtd_blkdevs
  [PATCH] switch mmc
  ...
parents 5ed487bc 56b26add
......@@ -98,9 +98,9 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)
static DEFINE_MUTEX(ubd_lock);
static int ubd_open(struct inode * inode, struct file * filp);
static int ubd_release(struct inode * inode, struct file * file);
static int ubd_ioctl(struct inode * inode, struct file * file,
static int ubd_open(struct block_device *bdev, fmode_t mode);
static int ubd_release(struct gendisk *disk, fmode_t mode);
static int ubd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg);
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
......@@ -1112,9 +1112,9 @@ static int __init ubd_driver_init(void){
device_initcall(ubd_driver_init);
static int ubd_open(struct inode *inode, struct file *filp)
static int ubd_open(struct block_device *bdev, fmode_t mode)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct gendisk *disk = bdev->bd_disk;
struct ubd *ubd_dev = disk->private_data;
int err = 0;
......@@ -1131,7 +1131,7 @@ static int ubd_open(struct inode *inode, struct file *filp)
/* This should no more be needed. And it didn't work anyway to exclude
* read-write remounting of filesystems.*/
/*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){
/*if((mode & FMODE_WRITE) && !ubd_dev->openflags.w){
if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev);
err = -EROFS;
}*/
......@@ -1139,9 +1139,8 @@ static int ubd_open(struct inode *inode, struct file *filp)
return err;
}
static int ubd_release(struct inode * inode, struct file * file)
static int ubd_release(struct gendisk *disk, fmode_t mode)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ubd *ubd_dev = disk->private_data;
if(--ubd_dev->count == 0)
......@@ -1306,10 +1305,10 @@ static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
return 0;
}
static int ubd_ioctl(struct inode * inode, struct file * file,
static int ubd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data;
struct ubd *ubd_dev = bdev->bd_disk->private_data;
struct hd_driveid ubd_id = {
.cyls = 0,
.heads = 128,
......
......@@ -173,7 +173,7 @@ static int bsg_io_schedule(struct bsg_device *bd)
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;
......
......@@ -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))
......
......@@ -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,8 +579,8 @@ 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;
......@@ -596,7 +596,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 +606,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 +679,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 +747,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;
}
}
......@@ -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);
......@@ -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 @@ static int sg_io(struct file *file, struct request_queue *q,
* 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))