diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-11-10 09:10:44 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-10 09:10:44 +0100 |
commit | a5a64498c194c82ecad3a2d67cff6231cda8d3dd (patch) | |
tree | 723d5d81419f9960b8d30ed9a2ece8a58d6c4328 /block | |
parent | bb93d802ae5c1949977cc6da247b218240677f11 (diff) | |
parent | f7160c7573615ec82c691e294cf80d920b5d588d (diff) |
Merge commit 'v2.6.28-rc4' into timers/rtc
Conflicts:
drivers/rtc/rtc-cmos.c
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 4 | ||||
-rw-r--r-- | block/blk-merge.c | 21 | ||||
-rw-r--r-- | block/blk-timeout.c | 20 | ||||
-rw-r--r-- | block/bsg.c | 9 | ||||
-rw-r--r-- | block/cmd-filter.c | 2 | ||||
-rw-r--r-- | block/compat_ioctl.c | 177 | ||||
-rw-r--r-- | block/elevator.c | 12 | ||||
-rw-r--r-- | block/genhd.c | 37 | ||||
-rw-r--r-- | block/ioctl.c | 173 | ||||
-rw-r--r-- | block/scsi_ioctl.c | 33 |
10 files changed, 225 insertions, 263 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index c3df30cfb3f..10e8a64a5a5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1770,8 +1770,6 @@ static void end_that_request_last(struct request *req, int error) { struct gendisk *disk = req->rq_disk; - blk_delete_timer(req); - if (blk_rq_tagged(req)) blk_queue_end_tag(req->q, req); @@ -1781,6 +1779,8 @@ static void end_that_request_last(struct request *req, int error) if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); + blk_delete_timer(req); + /* * Account IO completion. bar_rq isn't accounted as a normal * IO on queueing nor completion. Accounting the containing diff --git a/block/blk-merge.c b/block/blk-merge.c index 8681cd6f991..b92f5b0866b 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -222,27 +222,6 @@ new_segment: } EXPORT_SYMBOL(blk_rq_map_sg); -static inline int ll_new_mergeable(struct request_queue *q, - struct request *req, - struct bio *bio) -{ - int nr_phys_segs = bio_phys_segments(q, bio); - - if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) { - req->cmd_flags |= REQ_NOMERGE; - if (req == q->last_merge) - q->last_merge = NULL; - return 0; - } - - /* - * A hw segment is just getting larger, bump just the phys - * counter. - */ - req->nr_phys_segments += nr_phys_segs; - return 1; -} - static inline int ll_new_hw_segment(struct request_queue *q, struct request *req, struct bio *bio) diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 972a63f848f..69185ea9fae 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -75,14 +75,7 @@ void blk_delete_timer(struct request *req) { struct request_queue *q = req->q; - /* - * Nothing to detach - */ - if (!q->rq_timed_out_fn || !req->deadline) - return; - list_del_init(&req->timeout_list); - if (list_empty(&q->timeout_list)) del_timer(&q->timeout); } @@ -142,7 +135,7 @@ void blk_rq_timed_out_timer(unsigned long data) } if (next_set && !list_empty(&q->timeout_list)) - mod_timer(&q->timeout, round_jiffies(next)); + mod_timer(&q->timeout, round_jiffies_up(next)); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -198,17 +191,10 @@ void blk_add_timer(struct request *req) /* * If the timer isn't already pending or this timeout is earlier - * than an existing one, modify the timer. Round to next nearest + * than an existing one, modify the timer. Round up to next nearest * second. */ - expiry = round_jiffies(req->deadline); - - /* - * We use ->deadline == 0 to detect whether a timer was added or - * not, so just increase to next jiffy for that specific case - */ - if (unlikely(!req->deadline)) - req->deadline = 1; + expiry = round_jiffies_up(req->deadline); if (!timer_pending(&q->timeout) || time_before(expiry, q->timeout.expires)) diff --git a/block/bsg.c b/block/bsg.c index 034112bfe1f..e8bd2475682 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 e669aed4c6b..504b275e1b9 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 1e559fba7bd..3d3e7a46f38 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/elevator.c b/block/elevator.c index 59173a69ebd..9ac82dde99d 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -773,12 +773,6 @@ struct request *elv_next_request(struct request_queue *q) */ rq->cmd_flags |= REQ_STARTED; blk_add_trace_rq(q, rq, BLK_TA_ISSUE); - - /* - * We are now handing the request to the hardware, - * add the timeout handler - */ - blk_add_timer(rq); } if (!q->boundary_rq || q->boundary_rq == rq) { @@ -850,6 +844,12 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq) */ if (blk_account_rq(rq)) q->in_flight++; + + /* + * We are now handing the request to the hardware, add the + * timeout handler. + */ + blk_add_timer(rq); } EXPORT_SYMBOL(elv_dequeue_request); diff --git a/block/genhd.c b/block/genhd.c index 646e1d2507c..4e5e7493f67 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 38bee321e1f..c832d639b6e 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 c34272a348f..5963cf91a3a 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); |