Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22484856 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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
Loading
Loading
Loading
Loading
+9 −10
Original line number Original line Diff line number Diff line
@@ -98,9 +98,9 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data)


static DEFINE_MUTEX(ubd_lock);
static DEFINE_MUTEX(ubd_lock);


static int ubd_open(struct inode * inode, struct file * filp);
static int ubd_open(struct block_device *bdev, fmode_t mode);
static int ubd_release(struct inode * inode, struct file * file);
static int ubd_release(struct gendisk *disk, fmode_t mode);
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);
		     unsigned int cmd, unsigned long arg);
static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
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);
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;
	struct ubd *ubd_dev = disk->private_data;
	int err = 0;
	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
	/* This should no more be needed. And it didn't work anyway to exclude
	 * read-write remounting of filesystems.*/
	 * 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);
	        if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev);
	        err = -EROFS;
	        err = -EROFS;
	}*/
	}*/
@@ -1139,9 +1139,8 @@ static int ubd_open(struct inode *inode, struct file *filp)
	return err;
	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;
	struct ubd *ubd_dev = disk->private_data;


	if(--ubd_dev->count == 0)
	if(--ubd_dev->count == 0)
@@ -1306,10 +1305,10 @@ static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
	return 0;
	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)
		     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 = {
	struct hd_driveid ubd_id = {
		.cyls		= 0,
		.cyls		= 0,
		.heads		= 128,
		.heads		= 128,
+5 −4
Original line number Original line Diff line number Diff line
@@ -173,7 +173,7 @@ unlock:


static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
				struct sg_io_v4 *hdr, struct bsg_device *bd,
				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) {
	if (hdr->request_len > BLK_MAX_CDB) {
		rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
		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.
 * map sg_io_v4 to a request.
 */
 */
static struct 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_queue *q = bd->queue;
	struct request *rq, *next_rq = NULL;
	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,
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 bsg_command *bc;
	struct request *rq;
	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 SG_EMULATED_HOST:
	case SCSI_IOCTL_SEND_COMMAND: {
	case SCSI_IOCTL_SEND_COMMAND: {
		void __user *uarg = (void __user *) arg;
		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: {
	case SG_IO: {
		struct request *rq;
		struct request *rq;
+1 −1
Original line number Original line Diff line number Diff line
@@ -27,7 +27,7 @@
#include <linux/cdrom.h>
#include <linux/cdrom.h>


int blk_verify_command(struct blk_cmd_filter *filter,
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. */
	/* root can do any command. */
	if (capable(CAP_SYS_RAWIO))
	if (capable(CAP_SYS_RAWIO))
+70 −105
Original line number Original line Diff line number Diff line
@@ -71,8 +71,8 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
	return ret;
	return ret;
}
}


static int compat_hdio_ioctl(struct inode *inode, struct file *file,
static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
		struct gendisk *disk, unsigned int cmd, unsigned long arg)
		unsigned int cmd, unsigned long arg)
{
{
	mm_segment_t old_fs = get_fs();
	mm_segment_t old_fs = get_fs();
	unsigned long kval;
	unsigned long kval;
@@ -80,7 +80,7 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file,
	int error;
	int error;


	set_fs(KERNEL_DS);
	set_fs(KERNEL_DS);
	error = blkdev_driver_ioctl(inode, file, disk,
	error = __blkdev_driver_ioctl(bdev, mode,
				cmd, (unsigned long)(&kval));
				cmd, (unsigned long)(&kval));
	set_fs(old_fs);
	set_fs(old_fs);


@@ -111,8 +111,8 @@ struct compat_cdrom_generic_command {
	compat_caddr_t	reserved[1];
	compat_caddr_t	reserved[1];
};
};


static int compat_cdrom_read_audio(struct inode *inode, struct file *file,
static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
		struct gendisk *disk, unsigned int cmd, unsigned long arg)
		unsigned int cmd, unsigned long arg)
{
{
	struct cdrom_read_audio __user *cdread_audio;
	struct cdrom_read_audio __user *cdread_audio;
	struct compat_cdrom_read_audio __user *cdread_audio32;
	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))
	if (put_user(datap, &cdread_audio->buf))
		return -EFAULT;
		return -EFAULT;


	return blkdev_driver_ioctl(inode, file, disk, cmd,
	return __blkdev_driver_ioctl(bdev, mode, cmd,
			(unsigned long)cdread_audio);
			(unsigned long)cdread_audio);
}
}


static int compat_cdrom_generic_command(struct inode *inode, struct file *file,
static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
		struct gendisk *disk, unsigned int cmd, unsigned long arg)
		unsigned int cmd, unsigned long arg)
{
{
	struct cdrom_generic_command __user *cgc;
	struct cdrom_generic_command __user *cgc;
	struct compat_cdrom_generic_command __user *cgc32;
	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]))
	    put_user(compat_ptr(data), &cgc->reserved[0]))
		return -EFAULT;
		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 {
struct compat_blkpg_ioctl_arg {
@@ -177,7 +177,7 @@ struct compat_blkpg_ioctl_arg {
	compat_caddr_t data;
	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)
		unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
{
{
	struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
	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)
	if (err)
		return 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)
#define BLKBSZGET_32		_IOR(0x12, 112, int)
@@ -308,8 +308,8 @@ static struct {


#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)


static int compat_fd_ioctl(struct inode *inode, struct file *file,
static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
		struct gendisk *disk, unsigned int cmd, unsigned long arg)
		unsigned int cmd, unsigned long arg)
{
{
	mm_segment_t old_fs = get_fs();
	mm_segment_t old_fs = get_fs();
	void *karg = NULL;
	void *karg = NULL;
@@ -413,7 +413,7 @@ static int compat_fd_ioctl(struct inode *inode, struct file *file,
		return -EINVAL;
		return -EINVAL;
	}
	}
	set_fs(KERNEL_DS);
	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);
	set_fs(old_fs);
	if (err)
	if (err)
		goto out;
		goto out;
@@ -579,8 +579,8 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg)
	return 0;
	return 0;
}
}


static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
			struct gendisk *disk, unsigned cmd, unsigned long arg)
			unsigned cmd, unsigned long arg)
{
{
	int ret;
	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_ACOUSTIC:
	case HDIO_GET_ADDRESS:
	case HDIO_GET_ADDRESS:
	case HDIO_GET_BUSSTATE:
	case HDIO_GET_BUSSTATE:
		return compat_hdio_ioctl(inode, file, disk, cmd, arg);
		return compat_hdio_ioctl(bdev, mode, cmd, arg);
	case FDSETPRM32:
	case FDSETPRM32:
	case FDDEFPRM32:
	case FDDEFPRM32:
	case FDGETPRM32:
	case FDGETPRM32:
@@ -606,11 +606,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file,
	case FDPOLLDRVSTAT32:
	case FDPOLLDRVSTAT32:
	case FDGETFDCSTAT32:
	case FDGETFDCSTAT32:
	case FDWERRORGET32:
	case FDWERRORGET32:
		return compat_fd_ioctl(inode, file, disk, cmd, arg);
		return compat_fd_ioctl(bdev, mode, cmd, arg);
	case CDROMREADAUDIO:
	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:
	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
	 * 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_WRITE_STRUCT:
	case DVD_AUTH:
	case DVD_AUTH:
		arg = (unsigned long)compat_ptr(arg);
		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;
		break;
	default:
	default:
		/* unknown ioctl number */
		/* unknown ioctl number */
		return -ENOIOCTLCMD;
		return -ENOIOCTLCMD;
	}
	}


	if (disk->fops->unlocked_ioctl)
	return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
		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;
}
}


static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file,
/* Most of the generic ioctls are handled in the normal fallback path.
				struct block_device *bdev,
   This assumes the blkdev's low level compat_ioctl always returns
				unsigned cmd, unsigned long arg)
   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;
	struct backing_dev_info *bdi;
	loff_t size;

	if (file->f_flags & O_NDELAY)
		mode |= FMODE_NDELAY_NOW;


	switch (cmd) {
	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 BLKRAGET:
	case BLKFRAGET:
	case BLKFRAGET:
		if (!arg)
		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);
		bdi = blk_get_backing_dev_info(bdev);
		if (bdi == NULL)
		if (bdi == NULL)
			return -ENOTTY;
			return -ENOTTY;
		lock_kernel();
		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
		unlock_kernel();
		return 0;
		return 0;
	case BLKGETSIZE:
	case BLKGETSIZE:
		if ((bdev->bd_inode->i_size >> 9) > ~0UL)
		size = bdev->bd_inode->i_size;
		if ((size >> 9) > ~0UL)
			return -EFBIG;
			return -EFBIG;
		return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9);
		return compat_put_ulong(arg, size >> 9);


	case BLKGETSIZE64_32:
	case BLKGETSIZE64_32:
		return compat_put_u64(arg, bdev->bd_inode->i_size);
		return compat_put_u64(arg, bdev->bd_inode->i_size);


	case BLKTRACESETUP32:
	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 BLKTRACESTART: /* compatible */
	case BLKTRACESTOP:  /* compatible */
	case BLKTRACESTOP:  /* compatible */
	case BLKTRACETEARDOWN: /* 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();
		lock_kernel();
	ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg);
		ret = blk_trace_ioctl(bdev, cmd, compat_ptr(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();
		unlock_kernel();

	if (ret != -ENOIOCTLCMD)
		return ret;
		return ret;

	default:
	return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg);
		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;
	}
}
}
+89 −84
Original line number Original line Diff line number Diff line
@@ -201,97 +201,41 @@ static int put_u64(unsigned long arg, u64 val)
	return put_user(val, (u64 __user *)arg);
	return put_user(val, (u64 __user *)arg);
}
}


static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
			unsigned cmd, unsigned long arg)
			unsigned cmd, unsigned long arg)
{
{
	struct backing_dev_info *bdi;
	struct gendisk *disk = bdev->bd_disk;
	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 ret;
	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();
		lock_kernel();
		ret = disk->fops->ioctl(inode, file, cmd, arg);
		ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg);
		unlock_kernel();
		unlock_kernel();
		return ret;
		return ret;
	}
	}


	return -ENOTTY;
	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
 * always keep this in sync with compat_blkdev_ioctl() and
 * compat_blkdev_locked_ioctl()
 * 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)
			unsigned long arg)
{
{
	struct block_device *bdev = inode->i_bdev;
	struct gendisk *disk = bdev->bd_disk;
	struct gendisk *disk = bdev->bd_disk;
	struct backing_dev_info *bdi;
	loff_t size;
	int ret, n;
	int ret, n;


	switch(cmd) {
	switch(cmd) {
@@ -299,7 +243,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
		if (!capable(CAP_SYS_ADMIN))
		if (!capable(CAP_SYS_ADMIN))
			return -EACCES;
			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 */
		/* -EINVAL to handle old uncorrected drivers */
		if (ret != -EINVAL && ret != -ENOTTY)
		if (ret != -EINVAL && ret != -ENOTTY)
			return ret;
			return ret;
@@ -311,7 +255,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
		return 0;
		return 0;


	case BLKROSET:
	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 */
		/* -EINVAL to handle old uncorrected drivers */
		if (ret != -EINVAL && ret != -ENOTTY)
		if (ret != -EINVAL && ret != -ENOTTY)
			return ret;
			return ret;
@@ -327,7 +271,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
	case BLKDISCARD: {
	case BLKDISCARD: {
		uint64_t range[2];
		uint64_t range[2];


		if (!(file->f_mode & FMODE_WRITE))
		if (!(mode & FMODE_WRITE))
			return -EBADF;
			return -EBADF;


		if (copy_from_user(range, (void __user *)arg, sizeof(range)))
		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 -EFAULT;
		return 0;
		return 0;
	}
	}
	}
	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();
		lock_kernel();
	ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
		unlock_kernel();
		unlock_kernel();
	if (ret != -ENOIOCTLCMD)
		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;
	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;
	return ret;

	return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
}
}
EXPORT_SYMBOL_GPL(blkdev_ioctl);
EXPORT_SYMBOL_GPL(blkdev_ioctl);
Loading