diff options
author | James Morris <jmorris@namei.org> | 2008-11-05 18:12:34 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-05 18:12:34 -0500 |
commit | e21e696edb498c7f7eed42ba3096f6bbe13927b6 (patch) | |
tree | 73b0bc28e45b0268f05c4b384a17bfb2140a73bc /block | |
parent | 2f99db28af90957271a6448479c3e492ccf7c697 (diff) | |
parent | 75fa67706cce5272bcfc51ed646f2da21f3bdb6e (diff) |
Merge branch 'master' into next
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 37 | ||||
-rw-r--r-- | block/blk-merge.c | 20 | ||||
-rw-r--r-- | block/blk-settings.c | 2 | ||||
-rw-r--r-- | block/blk.h | 1 | ||||
-rw-r--r-- | block/bsg.c | 12 | ||||
-rw-r--r-- | block/cmd-filter.c | 2 | ||||
-rw-r--r-- | block/compat_ioctl.c | 177 | ||||
-rw-r--r-- | block/elevator.c | 16 | ||||
-rw-r--r-- | block/genhd.c | 40 | ||||
-rw-r--r-- | block/ioctl.c | 173 | ||||
-rw-r--r-- | block/scsi_ioctl.c | 33 |
11 files changed, 270 insertions, 243 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 2d053b584410..c3df30cfb3fc 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -257,7 +257,6 @@ void __generic_unplug_device(struct request_queue *q) | |||
257 | 257 | ||
258 | q->request_fn(q); | 258 | q->request_fn(q); |
259 | } | 259 | } |
260 | EXPORT_SYMBOL(__generic_unplug_device); | ||
261 | 260 | ||
262 | /** | 261 | /** |
263 | * generic_unplug_device - fire a request queue | 262 | * generic_unplug_device - fire a request queue |
@@ -325,6 +324,9 @@ EXPORT_SYMBOL(blk_unplug); | |||
325 | 324 | ||
326 | static void blk_invoke_request_fn(struct request_queue *q) | 325 | static void blk_invoke_request_fn(struct request_queue *q) |
327 | { | 326 | { |
327 | if (unlikely(blk_queue_stopped(q))) | ||
328 | return; | ||
329 | |||
328 | /* | 330 | /* |
329 | * one level of recursion is ok and is much faster than kicking | 331 | * one level of recursion is ok and is much faster than kicking |
330 | * the unplug handling | 332 | * the unplug handling |
@@ -399,8 +401,13 @@ void blk_sync_queue(struct request_queue *q) | |||
399 | EXPORT_SYMBOL(blk_sync_queue); | 401 | EXPORT_SYMBOL(blk_sync_queue); |
400 | 402 | ||
401 | /** | 403 | /** |
402 | * blk_run_queue - run a single device queue | 404 | * __blk_run_queue - run a single device queue |
403 | * @q: The queue to run | 405 | * @q: The queue to run |
406 | * | ||
407 | * Description: | ||
408 | * See @blk_run_queue. This variant must be called with the queue lock | ||
409 | * held and interrupts disabled. | ||
410 | * | ||
404 | */ | 411 | */ |
405 | void __blk_run_queue(struct request_queue *q) | 412 | void __blk_run_queue(struct request_queue *q) |
406 | { | 413 | { |
@@ -418,6 +425,12 @@ EXPORT_SYMBOL(__blk_run_queue); | |||
418 | /** | 425 | /** |
419 | * blk_run_queue - run a single device queue | 426 | * blk_run_queue - run a single device queue |
420 | * @q: The queue to run | 427 | * @q: The queue to run |
428 | * | ||
429 | * Description: | ||
430 | * Invoke request handling on this queue, if it has pending work to do. | ||
431 | * May be used to restart queueing when a request has completed. Also | ||
432 | * See @blk_start_queueing. | ||
433 | * | ||
421 | */ | 434 | */ |
422 | void blk_run_queue(struct request_queue *q) | 435 | void blk_run_queue(struct request_queue *q) |
423 | { | 436 | { |
@@ -501,6 +514,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) | |||
501 | init_timer(&q->unplug_timer); | 514 | init_timer(&q->unplug_timer); |
502 | setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); | 515 | setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); |
503 | INIT_LIST_HEAD(&q->timeout_list); | 516 | INIT_LIST_HEAD(&q->timeout_list); |
517 | INIT_WORK(&q->unplug_work, blk_unplug_work); | ||
504 | 518 | ||
505 | kobject_init(&q->kobj, &blk_queue_ktype); | 519 | kobject_init(&q->kobj, &blk_queue_ktype); |
506 | 520 | ||
@@ -884,7 +898,8 @@ EXPORT_SYMBOL(blk_get_request); | |||
884 | * | 898 | * |
885 | * This is basically a helper to remove the need to know whether a queue | 899 | * This is basically a helper to remove the need to know whether a queue |
886 | * is plugged or not if someone just wants to initiate dispatch of requests | 900 | * is plugged or not if someone just wants to initiate dispatch of requests |
887 | * for this queue. | 901 | * for this queue. Should be used to start queueing on a device outside |
902 | * of ->request_fn() context. Also see @blk_run_queue. | ||
888 | * | 903 | * |
889 | * The queue lock must be held with interrupts disabled. | 904 | * The queue lock must be held with interrupts disabled. |
890 | */ | 905 | */ |
@@ -1003,8 +1018,9 @@ static void part_round_stats_single(int cpu, struct hd_struct *part, | |||
1003 | } | 1018 | } |
1004 | 1019 | ||
1005 | /** | 1020 | /** |
1006 | * part_round_stats() - Round off the performance stats on a struct | 1021 | * part_round_stats() - Round off the performance stats on a struct disk_stats. |
1007 | * disk_stats. | 1022 | * @cpu: cpu number for stats access |
1023 | * @part: target partition | ||
1008 | * | 1024 | * |
1009 | * The average IO queue length and utilisation statistics are maintained | 1025 | * The average IO queue length and utilisation statistics are maintained |
1010 | * by observing the current state of the queue length and the amount of | 1026 | * by observing the current state of the queue length and the amount of |
@@ -1075,8 +1091,15 @@ void init_request_from_bio(struct request *req, struct bio *bio) | |||
1075 | /* | 1091 | /* |
1076 | * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) | 1092 | * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) |
1077 | */ | 1093 | */ |
1078 | if (bio_rw_ahead(bio) || bio_failfast(bio)) | 1094 | if (bio_rw_ahead(bio)) |
1079 | req->cmd_flags |= REQ_FAILFAST; | 1095 | req->cmd_flags |= (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | |
1096 | REQ_FAILFAST_DRIVER); | ||
1097 | if (bio_failfast_dev(bio)) | ||
1098 | req->cmd_flags |= REQ_FAILFAST_DEV; | ||
1099 | if (bio_failfast_transport(bio)) | ||
1100 | req->cmd_flags |= REQ_FAILFAST_TRANSPORT; | ||
1101 | if (bio_failfast_driver(bio)) | ||
1102 | req->cmd_flags |= REQ_FAILFAST_DRIVER; | ||
1080 | 1103 | ||
1081 | /* | 1104 | /* |
1082 | * REQ_BARRIER implies no merging, but lets make it explicit | 1105 | * REQ_BARRIER implies no merging, but lets make it explicit |
diff --git a/block/blk-merge.c b/block/blk-merge.c index 908d3e11ac52..8681cd6f9911 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -77,12 +77,20 @@ void blk_recalc_rq_segments(struct request *rq) | |||
77 | continue; | 77 | continue; |
78 | } | 78 | } |
79 | new_segment: | 79 | new_segment: |
80 | if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size) | ||
81 | rq->bio->bi_seg_front_size = seg_size; | ||
82 | |||
80 | nr_phys_segs++; | 83 | nr_phys_segs++; |
81 | bvprv = bv; | 84 | bvprv = bv; |
82 | seg_size = bv->bv_len; | 85 | seg_size = bv->bv_len; |
83 | highprv = high; | 86 | highprv = high; |
84 | } | 87 | } |
85 | 88 | ||
89 | if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size) | ||
90 | rq->bio->bi_seg_front_size = seg_size; | ||
91 | if (seg_size > rq->biotail->bi_seg_back_size) | ||
92 | rq->biotail->bi_seg_back_size = seg_size; | ||
93 | |||
86 | rq->nr_phys_segments = nr_phys_segs; | 94 | rq->nr_phys_segments = nr_phys_segs; |
87 | } | 95 | } |
88 | 96 | ||
@@ -106,7 +114,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio, | |||
106 | if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) | 114 | if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags)) |
107 | return 0; | 115 | return 0; |
108 | 116 | ||
109 | if (bio->bi_size + nxt->bi_size > q->max_segment_size) | 117 | if (bio->bi_seg_back_size + nxt->bi_seg_front_size > |
118 | q->max_segment_size) | ||
110 | return 0; | 119 | return 0; |
111 | 120 | ||
112 | if (!bio_has_data(bio)) | 121 | if (!bio_has_data(bio)) |
@@ -309,6 +318,8 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, | |||
309 | struct request *next) | 318 | struct request *next) |
310 | { | 319 | { |
311 | int total_phys_segments; | 320 | int total_phys_segments; |
321 | unsigned int seg_size = | ||
322 | req->biotail->bi_seg_back_size + next->bio->bi_seg_front_size; | ||
312 | 323 | ||
313 | /* | 324 | /* |
314 | * First check if the either of the requests are re-queued | 325 | * First check if the either of the requests are re-queued |
@@ -324,8 +335,13 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, | |||
324 | return 0; | 335 | return 0; |
325 | 336 | ||
326 | total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; | 337 | total_phys_segments = req->nr_phys_segments + next->nr_phys_segments; |
327 | if (blk_phys_contig_segment(q, req->biotail, next->bio)) | 338 | if (blk_phys_contig_segment(q, req->biotail, next->bio)) { |
339 | if (req->nr_phys_segments == 1) | ||
340 | req->bio->bi_seg_front_size = seg_size; | ||
341 | if (next->nr_phys_segments == 1) | ||
342 | next->biotail->bi_seg_back_size = seg_size; | ||
328 | total_phys_segments--; | 343 | total_phys_segments--; |
344 | } | ||
329 | 345 | ||
330 | if (total_phys_segments > q->max_phys_segments) | 346 | if (total_phys_segments > q->max_phys_segments) |
331 | return 0; | 347 | return 0; |
diff --git a/block/blk-settings.c b/block/blk-settings.c index b21dcdb64151..41392fbe19ff 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -141,8 +141,6 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) | |||
141 | if (q->unplug_delay == 0) | 141 | if (q->unplug_delay == 0) |
142 | q->unplug_delay = 1; | 142 | q->unplug_delay = 1; |
143 | 143 | ||
144 | INIT_WORK(&q->unplug_work, blk_unplug_work); | ||
145 | |||
146 | q->unplug_timer.function = blk_unplug_timeout; | 144 | q->unplug_timer.function = blk_unplug_timeout; |
147 | q->unplug_timer.data = (unsigned long)q; | 145 | q->unplug_timer.data = (unsigned long)q; |
148 | 146 | ||
diff --git a/block/blk.h b/block/blk.h index e5c579769963..d2e49af90db5 100644 --- a/block/blk.h +++ b/block/blk.h | |||
@@ -20,6 +20,7 @@ void blk_unplug_timeout(unsigned long data); | |||
20 | void blk_rq_timed_out_timer(unsigned long data); | 20 | void blk_rq_timed_out_timer(unsigned long data); |
21 | void blk_delete_timer(struct request *); | 21 | void blk_delete_timer(struct request *); |
22 | void blk_add_timer(struct request *); | 22 | void blk_add_timer(struct request *); |
23 | void __generic_unplug_device(struct request_queue *); | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * Internal atomic flags for request handling | 26 | * Internal atomic flags for request handling |
diff --git a/block/bsg.c b/block/bsg.c index 56cb343c76d8..e8bd2475682a 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -173,7 +173,7 @@ unlock: | |||
173 | 173 | ||
174 | static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, | 174 | static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, |
175 | struct sg_io_v4 *hdr, struct bsg_device *bd, | 175 | struct sg_io_v4 *hdr, struct bsg_device *bd, |
176 | int has_write_perm) | 176 | fmode_t has_write_perm) |
177 | { | 177 | { |
178 | if (hdr->request_len > BLK_MAX_CDB) { | 178 | if (hdr->request_len > BLK_MAX_CDB) { |
179 | rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL); | 179 | 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) | |||
242 | * map sg_io_v4 to a request. | 242 | * map sg_io_v4 to a request. |
243 | */ | 243 | */ |
244 | static struct request * | 244 | static struct request * |
245 | bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, int has_write_perm) | 245 | bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm) |
246 | { | 246 | { |
247 | struct request_queue *q = bd->queue; | 247 | struct request_queue *q = bd->queue; |
248 | struct request *rq, *next_rq = NULL; | 248 | struct request *rq, *next_rq = NULL; |
@@ -601,7 +601,8 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
601 | } | 601 | } |
602 | 602 | ||
603 | static int __bsg_write(struct bsg_device *bd, const char __user *buf, | 603 | static int __bsg_write(struct bsg_device *bd, const char __user *buf, |
604 | size_t count, ssize_t *bytes_written, int has_write_perm) | 604 | size_t count, ssize_t *bytes_written, |
605 | fmode_t has_write_perm) | ||
605 | { | 606 | { |
606 | struct bsg_command *bc; | 607 | struct bsg_command *bc; |
607 | struct request *rq; | 608 | struct request *rq; |
@@ -913,7 +914,7 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
913 | case SG_EMULATED_HOST: | 914 | case SG_EMULATED_HOST: |
914 | case SCSI_IOCTL_SEND_COMMAND: { | 915 | case SCSI_IOCTL_SEND_COMMAND: { |
915 | void __user *uarg = (void __user *) arg; | 916 | void __user *uarg = (void __user *) arg; |
916 | return scsi_cmd_ioctl(file, bd->queue, NULL, cmd, uarg); | 917 | return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg); |
917 | } | 918 | } |
918 | case SG_IO: { | 919 | case SG_IO: { |
919 | struct request *rq; | 920 | struct request *rq; |
@@ -1024,8 +1025,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent, | |||
1024 | bcd->release = release; | 1025 | bcd->release = release; |
1025 | kref_init(&bcd->ref); | 1026 | kref_init(&bcd->ref); |
1026 | dev = MKDEV(bsg_major, bcd->minor); | 1027 | dev = MKDEV(bsg_major, bcd->minor); |
1027 | class_dev = device_create_drvdata(bsg_class, parent, dev, NULL, | 1028 | class_dev = device_create(bsg_class, parent, dev, NULL, "%s", devname); |
1028 | "%s", devname); | ||
1029 | if (IS_ERR(class_dev)) { | 1029 | if (IS_ERR(class_dev)) { |
1030 | ret = PTR_ERR(class_dev); | 1030 | ret = PTR_ERR(class_dev); |
1031 | goto put_dev; | 1031 | goto put_dev; |
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 @@ | |||
27 | #include <linux/cdrom.h> | 27 | #include <linux/cdrom.h> |
28 | 28 | ||
29 | int blk_verify_command(struct blk_cmd_filter *filter, | 29 | int blk_verify_command(struct blk_cmd_filter *filter, |
30 | unsigned char *cmd, int has_write_perm) | 30 | unsigned char *cmd, fmode_t has_write_perm) |
31 | { | 31 | { |
32 | /* root can do any command. */ | 32 | /* root can do any command. */ |
33 | if (capable(CAP_SYS_RAWIO)) | 33 | 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, | |||
71 | return ret; | 71 | return ret; |
72 | } | 72 | } |
73 | 73 | ||
74 | static int compat_hdio_ioctl(struct inode *inode, struct file *file, | 74 | static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode, |
75 | struct gendisk *disk, unsigned int cmd, unsigned long arg) | 75 | unsigned int cmd, unsigned long arg) |
76 | { | 76 | { |
77 | mm_segment_t old_fs = get_fs(); | 77 | mm_segment_t old_fs = get_fs(); |
78 | unsigned long kval; | 78 | unsigned long kval; |
@@ -80,7 +80,7 @@ static int compat_hdio_ioctl(struct inode *inode, struct file *file, | |||
80 | int error; | 80 | int error; |
81 | 81 | ||
82 | set_fs(KERNEL_DS); | 82 | set_fs(KERNEL_DS); |
83 | error = blkdev_driver_ioctl(inode, file, disk, | 83 | error = __blkdev_driver_ioctl(bdev, mode, |
84 | cmd, (unsigned long)(&kval)); | 84 | cmd, (unsigned long)(&kval)); |
85 | set_fs(old_fs); | 85 | set_fs(old_fs); |
86 | 86 | ||
@@ -111,8 +111,8 @@ struct compat_cdrom_generic_command { | |||
111 | compat_caddr_t reserved[1]; | 111 | compat_caddr_t reserved[1]; |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static int compat_cdrom_read_audio(struct inode *inode, struct file *file, | 114 | static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode, |
115 | struct gendisk *disk, unsigned int cmd, unsigned long arg) | 115 | unsigned int cmd, unsigned long arg) |
116 | { | 116 | { |
117 | struct cdrom_read_audio __user *cdread_audio; | 117 | struct cdrom_read_audio __user *cdread_audio; |
118 | struct compat_cdrom_read_audio __user *cdread_audio32; | 118 | struct compat_cdrom_read_audio __user *cdread_audio32; |
@@ -134,12 +134,12 @@ static int compat_cdrom_read_audio(struct inode *inode, struct file *file, | |||
134 | if (put_user(datap, &cdread_audio->buf)) | 134 | if (put_user(datap, &cdread_audio->buf)) |
135 | return -EFAULT; | 135 | return -EFAULT; |
136 | 136 | ||
137 | return blkdev_driver_ioctl(inode, file, disk, cmd, | 137 | return __blkdev_driver_ioctl(bdev, mode, cmd, |
138 | (unsigned long)cdread_audio); | 138 | (unsigned long)cdread_audio); |
139 | } | 139 | } |
140 | 140 | ||
141 | static int compat_cdrom_generic_command(struct inode *inode, struct file *file, | 141 | static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode, |
142 | struct gendisk *disk, unsigned int cmd, unsigned long arg) | 142 | unsigned int cmd, unsigned long arg) |
143 | { | 143 | { |
144 | struct cdrom_generic_command __user *cgc; | 144 | struct cdrom_generic_command __user *cgc; |
145 | struct compat_cdrom_generic_command __user *cgc32; | 145 | struct compat_cdrom_generic_command __user *cgc32; |
@@ -167,7 +167,7 @@ static int compat_cdrom_generic_command(struct inode *inode, struct file *file, | |||
167 | put_user(compat_ptr(data), &cgc->reserved[0])) | 167 | put_user(compat_ptr(data), &cgc->reserved[0])) |
168 | return -EFAULT; | 168 | return -EFAULT; |
169 | 169 | ||
170 | return blkdev_driver_ioctl(inode, file, disk, cmd, (unsigned long)cgc); | 170 | return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc); |
171 | } | 171 | } |
172 | 172 | ||
173 | struct compat_blkpg_ioctl_arg { | 173 | struct compat_blkpg_ioctl_arg { |
@@ -177,7 +177,7 @@ struct compat_blkpg_ioctl_arg { | |||
177 | compat_caddr_t data; | 177 | compat_caddr_t data; |
178 | }; | 178 | }; |
179 | 179 | ||
180 | static int compat_blkpg_ioctl(struct inode *inode, struct file *file, | 180 | static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, |
181 | unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) | 181 | unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) |
182 | { | 182 | { |
183 | struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); | 183 | 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, | |||
196 | if (err) | 196 | if (err) |
197 | return err; | 197 | return err; |
198 | 198 | ||
199 | return blkdev_ioctl(inode, file, cmd, (unsigned long)a); | 199 | return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a); |
200 | } | 200 | } |
201 | 201 | ||
202 | #define BLKBSZGET_32 _IOR(0x12, 112, int) | 202 | #define BLKBSZGET_32 _IOR(0x12, 112, int) |
@@ -308,8 +308,8 @@ static struct { | |||
308 | 308 | ||
309 | #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) | 309 | #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) |
310 | 310 | ||
311 | static int compat_fd_ioctl(struct inode *inode, struct file *file, | 311 | static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, |
312 | struct gendisk *disk, unsigned int cmd, unsigned long arg) | 312 | unsigned int cmd, unsigned long arg) |
313 | { | 313 | { |
314 | mm_segment_t old_fs = get_fs(); | 314 | mm_segment_t old_fs = get_fs(); |
315 | void *karg = NULL; | 315 | void *karg = NULL; |
@@ -413,7 +413,7 @@ static int compat_fd_ioctl(struct inode *inode, struct file *file, | |||
413 | return -EINVAL; | 413 | return -EINVAL; |
414 | } | 414 | } |
415 | set_fs(KERNEL_DS); | 415 | set_fs(KERNEL_DS); |
416 | err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)karg); | 416 | err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg); |
417 | set_fs(old_fs); | 417 | set_fs(old_fs); |
418 | if (err) | 418 | if (err) |
419 | goto out; | 419 | goto out; |
@@ -579,11 +579,9 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg) | |||
579 | return 0; | 579 | return 0; |
580 | } | 580 | } |
581 | 581 | ||
582 | static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, | 582 | static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, |
583 | struct gendisk *disk, unsigned cmd, unsigned long arg) | 583 | unsigned cmd, unsigned long arg) |
584 | { | 584 | { |
585 | int ret; | ||
586 | |||
587 | switch (cmd) { | 585 | switch (cmd) { |
588 | case HDIO_GET_UNMASKINTR: | 586 | case HDIO_GET_UNMASKINTR: |
589 | case HDIO_GET_MULTCOUNT: | 587 | case HDIO_GET_MULTCOUNT: |
@@ -596,7 +594,7 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, | |||
596 | case HDIO_GET_ACOUSTIC: | 594 | case HDIO_GET_ACOUSTIC: |
597 | case HDIO_GET_ADDRESS: | 595 | case HDIO_GET_ADDRESS: |
598 | case HDIO_GET_BUSSTATE: | 596 | case HDIO_GET_BUSSTATE: |
599 | return compat_hdio_ioctl(inode, file, disk, cmd, arg); | 597 | return compat_hdio_ioctl(bdev, mode, cmd, arg); |
600 | case FDSETPRM32: | 598 | case FDSETPRM32: |
601 | case FDDEFPRM32: | 599 | case FDDEFPRM32: |
602 | case FDGETPRM32: | 600 | case FDGETPRM32: |
@@ -606,11 +604,11 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, | |||
606 | case FDPOLLDRVSTAT32: | 604 | case FDPOLLDRVSTAT32: |
607 | case FDGETFDCSTAT32: | 605 | case FDGETFDCSTAT32: |
608 | case FDWERRORGET32: | 606 | case FDWERRORGET32: |
609 | return compat_fd_ioctl(inode, file, disk, cmd, arg); | 607 | return compat_fd_ioctl(bdev, mode, cmd, arg); |
610 | case CDROMREADAUDIO: | 608 | case CDROMREADAUDIO: |
611 | return compat_cdrom_read_audio(inode, file, disk, cmd, arg); | 609 | return compat_cdrom_read_audio(bdev, mode, cmd, arg); |
612 | case CDROM_SEND_PACKET: | 610 | case CDROM_SEND_PACKET: |
613 | return compat_cdrom_generic_command(inode, file, disk, cmd, arg); | 611 | return compat_cdrom_generic_command(bdev, mode, cmd, arg); |
614 | 612 | ||
615 | /* | 613 | /* |
616 | * No handler required for the ones below, we just need to | 614 | * 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, | |||
679 | case DVD_WRITE_STRUCT: | 677 | case DVD_WRITE_STRUCT: |
680 | case DVD_AUTH: | 678 | case DVD_AUTH: |
681 | arg = (unsigned long)compat_ptr(arg); | 679 | arg = (unsigned long)compat_ptr(arg); |
682 | /* These intepret arg as an unsigned long, not as a pointer, | ||
683 | * so we must not do compat_ptr() conversion. */ | ||
684 | case HDIO_SET_MULTCOUNT: | ||
685 | case HDIO_SET_UNMASKINTR: | ||
686 | case HDIO_SET_KEEPSETTINGS: | ||
687 | case HDIO_SET_32BIT: | ||
688 | case HDIO_SET_NOWERR: | ||
689 | case HDIO_SET_DMA: | ||
690 | case HDIO_SET_PIO_MODE: | ||
691 | case HDIO_SET_NICE: | ||
692 | case HDIO_SET_WCACHE: | ||
693 | case HDIO_SET_ACOUSTIC: | ||
694 | case HDIO_SET_BUSSTATE: | ||
695 | case HDIO_SET_ADDRESS: | ||
696 | case CDROMEJECT_SW: | ||
697 | case CDROM_SET_OPTIONS: | ||
698 | case CDROM_CLEAR_OPTIONS: | ||
699 | case CDROM_SELECT_SPEED: | ||
700 | case CDROM_SELECT_DISC: | ||
701 | case CDROM_MEDIA_CHANGED: | ||
702 | case CDROM_DRIVE_STATUS: | ||
703 | case CDROM_LOCKDOOR: | ||
704 | case CDROM_DEBUG: | ||
705 | break; | 680 | break; |
706 | default: | 681 | default: |
707 | /* unknown ioctl number */ | 682 | /* unknown ioctl number */ |
708 | return -ENOIOCTLCMD; | 683 | return -ENOIOCTLCMD; |
709 | } | 684 | } |
710 | 685 | ||
711 | if (disk->fops->unlocked_ioctl) | 686 | return __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
712 | return disk->fops->unlocked_ioctl(file, cmd, arg); | ||
713 | |||
714 | if (disk->fops->ioctl) { | ||
715 | lock_kernel(); | ||
716 | ret = disk->fops->ioctl(inode, file, cmd, arg); | ||
717 | unlock_kernel(); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | return -ENOTTY; | ||
722 | } | 687 | } |
723 | 688 | ||
724 | static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, | 689 | /* Most of the generic ioctls are handled in the normal fallback path. |
725 | struct block_device *bdev, | 690 | This assumes the blkdev's low level compat_ioctl always returns |
726 | unsigned cmd, unsigned long arg) | 691 | ENOIOCTLCMD for unknown ioctls. */ |
692 | long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||
727 | { | 693 | { |
694 | int ret = -ENOIOCTLCMD; | ||
695 | struct inode *inode = file->f_mapping->host; | ||
696 | struct block_device *bdev = inode->i_bdev; | ||
697 | struct gendisk *disk = bdev->bd_disk; | ||
698 | fmode_t mode = file->f_mode; | ||
728 | struct backing_dev_info *bdi; | 699 | struct backing_dev_info *bdi; |
700 | loff_t size; | ||
701 | |||
702 | if (file->f_flags & O_NDELAY) | ||
703 | mode |= FMODE_NDELAY_NOW; | ||
729 | 704 | ||
730 | switch (cmd) { | 705 | switch (cmd) { |
706 | case HDIO_GETGEO: | ||
707 | return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); | ||
708 | case BLKFLSBUF: | ||
709 | case BLKROSET: | ||
710 | case BLKDISCARD: | ||
711 | /* | ||
712 | * the ones below are implemented in blkdev_locked_ioctl, | ||
713 | * but we call blkdev_ioctl, which gets the lock for us | ||
714 | */ | ||
715 | case BLKRRPART: | ||
716 | return blkdev_ioctl(bdev, mode, cmd, | ||
717 | (unsigned long)compat_ptr(arg)); | ||
718 | case BLKBSZSET_32: | ||
719 | return blkdev_ioctl(bdev, mode, BLKBSZSET, | ||
720 | (unsigned long)compat_ptr(arg)); | ||
721 | case BLKPG: | ||
722 | return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); | ||
731 | case BLKRAGET: | 723 | case BLKRAGET: |
732 | case BLKFRAGET: | 724 | case BLKFRAGET: |
733 | if (!arg) | 725 | if (!arg) |
@@ -753,65 +745,36 @@ static int compat_blkdev_locked_ioctl(struct inode *inode, struct file *file, | |||
753 | bdi = blk_get_backing_dev_info(bdev); | 745 | bdi = blk_get_backing_dev_info(bdev); |
754 | if (bdi == NULL) | 746 | if (bdi == NULL) |
755 | return -ENOTTY; | 747 | return -ENOTTY; |
748 | lock_kernel(); | ||
756 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | 749 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; |
750 | unlock_kernel(); | ||
757 | return 0; | 751 | return 0; |
758 | case BLKGETSIZE: | 752 | case BLKGETSIZE: |
759 | if ((bdev->bd_inode->i_size >> 9) > ~0UL) | 753 | size = bdev->bd_inode->i_size; |
754 | if ((size >> 9) > ~0UL) | ||
760 | return -EFBIG; | 755 | return -EFBIG; |
761 | return compat_put_ulong(arg, bdev->bd_inode->i_size >> 9); | 756 | return compat_put_ulong(arg, size >> 9); |
762 | 757 | ||
763 | case BLKGETSIZE64_32: | 758 | case BLKGETSIZE64_32: |
764 | return compat_put_u64(arg, bdev->bd_inode->i_size); | 759 | return compat_put_u64(arg, bdev->bd_inode->i_size); |
765 | 760 | ||
766 | case BLKTRACESETUP32: | 761 | case BLKTRACESETUP32: |
767 | return compat_blk_trace_setup(bdev, compat_ptr(arg)); | 762 | lock_kernel(); |
763 | ret = compat_blk_trace_setup(bdev, compat_ptr(arg)); | ||
764 | unlock_kernel(); | ||
765 | return ret; | ||
768 | case BLKTRACESTART: /* compatible */ | 766 | case BLKTRACESTART: /* compatible */ |
769 | case BLKTRACESTOP: /* compatible */ | 767 | case BLKTRACESTOP: /* compatible */ |
770 | case BLKTRACETEARDOWN: /* compatible */ | 768 | case BLKTRACETEARDOWN: /* compatible */ |
771 | return blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); | 769 | lock_kernel(); |
772 | } | 770 | ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); |
773 | return -ENOIOCTLCMD; | 771 | unlock_kernel(); |
774 | } | ||
775 | |||
776 | /* Most of the generic ioctls are handled in the normal fallback path. | ||
777 | This assumes the blkdev's low level compat_ioctl always returns | ||
778 | ENOIOCTLCMD for unknown ioctls. */ | ||
779 | long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||
780 | { | ||
781 | int ret = -ENOIOCTLCMD; | ||
782 | struct inode *inode = file->f_mapping->host; | ||
783 | struct block_device *bdev = inode->i_bdev; | ||
784 | struct gendisk *disk = bdev->bd_disk; | ||
785 | |||
786 | switch (cmd) { | ||
787 | case HDIO_GETGEO: | ||
788 | return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); | ||
789 | case BLKFLSBUF: | ||
790 | case BLKROSET: | ||
791 | case BLKDISCARD: | ||
792 | /* | ||
793 | * the ones below are implemented in blkdev_locked_ioctl, | ||
794 | * but we call blkdev_ioctl, which gets the lock for us | ||
795 | */ | ||
796 | case BLKRRPART: | ||
797 | return blkdev_ioctl(inode, file, cmd, | ||
798 | (unsigned long)compat_ptr(arg)); | ||
799 | case BLKBSZSET_32: | ||
800 | return blkdev_ioctl(inode, file, BLKBSZSET, | ||
801 | (unsigned long)compat_ptr(arg)); | ||
802 | case BLKPG: | ||
803 | return compat_blkpg_ioctl(inode, file, cmd, compat_ptr(arg)); | ||
804 | } | ||
805 | |||
806 | lock_kernel(); | ||
807 | ret = compat_blkdev_locked_ioctl(inode, file, bdev, cmd, arg); | ||
808 | /* FIXME: why do we assume -> compat_ioctl needs the BKL? */ | ||
809 | if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl) | ||
810 | ret = disk->fops->compat_ioctl(file, cmd, arg); | ||
811 | unlock_kernel(); | ||
812 | |||
813 | if (ret != -ENOIOCTLCMD) | ||
814 | return ret; | 772 | return ret; |
815 | 773 | default: | |
816 | return compat_blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 774 | if (disk->fops->compat_ioctl) |
775 | ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); | ||
776 | if (ret == -ENOIOCTLCMD) | ||
777 | ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); | ||
778 | return ret; | ||
779 | } | ||
817 | } | 780 | } |
diff --git a/block/elevator.c b/block/elevator.c index 04518921db31..59173a69ebdf 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -612,7 +612,7 @@ void elv_insert(struct request_queue *q, struct request *rq, int where) | |||
612 | * processing. | 612 | * processing. |
613 | */ | 613 | */ |
614 | blk_remove_plug(q); | 614 | blk_remove_plug(q); |
615 | q->request_fn(q); | 615 | blk_start_queueing(q); |
616 | break; | 616 | break; |
617 | 617 | ||
618 | case ELEVATOR_INSERT_SORT: | 618 | case ELEVATOR_INSERT_SORT: |
@@ -950,7 +950,7 @@ void elv_completed_request(struct request_queue *q, struct request *rq) | |||
950 | blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && | 950 | blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && |
951 | blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { | 951 | blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { |
952 | blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); | 952 | blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); |
953 | q->request_fn(q); | 953 | blk_start_queueing(q); |
954 | } | 954 | } |
955 | } | 955 | } |
956 | } | 956 | } |
@@ -1109,8 +1109,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) | |||
1109 | elv_drain_elevator(q); | 1109 | elv_drain_elevator(q); |
1110 | 1110 | ||
1111 | while (q->rq.elvpriv) { | 1111 | while (q->rq.elvpriv) { |
1112 | blk_remove_plug(q); | 1112 | blk_start_queueing(q); |
1113 | q->request_fn(q); | ||
1114 | spin_unlock_irq(q->queue_lock); | 1113 | spin_unlock_irq(q->queue_lock); |
1115 | msleep(10); | 1114 | msleep(10); |
1116 | spin_lock_irq(q->queue_lock); | 1115 | spin_lock_irq(q->queue_lock); |
@@ -1166,15 +1165,10 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, | |||
1166 | size_t count) | 1165 | size_t count) |
1167 | { | 1166 | { |
1168 | char elevator_name[ELV_NAME_MAX]; | 1167 | char elevator_name[ELV_NAME_MAX]; |
1169 | size_t len; | ||
1170 | struct elevator_type *e; | 1168 | struct elevator_type *e; |
1171 | 1169 | ||
1172 | elevator_name[sizeof(elevator_name) - 1] = '\0'; | 1170 | strlcpy(elevator_name, name, sizeof(elevator_name)); |
1173 | strncpy(elevator_name, name, sizeof(elevator_name) - 1); | 1171 | strstrip(elevator_name); |
1174 | len = strlen(elevator_name); | ||
1175 | |||
1176 | if (len && elevator_name[len - 1] == '\n') | ||
1177 | elevator_name[len - 1] = '\0'; | ||
1178 | 1172 | ||
1179 | e = elevator_get(elevator_name); | 1173 | e = elevator_get(elevator_name); |
1180 | if (!e) { | 1174 | if (!e) { |
diff --git a/block/genhd.c b/block/genhd.c index 4cd3433c99ac..4e5e7493f676 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/blkdev.h> | 10 | #include <linux/blkdev.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/proc_fs.h> | ||
13 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/kmod.h> | 16 | #include <linux/kmod.h> |
@@ -358,7 +359,6 @@ static int blk_mangle_minor(int minor) | |||
358 | /** | 359 | /** |
359 | * blk_alloc_devt - allocate a dev_t for a partition | 360 | * blk_alloc_devt - allocate a dev_t for a partition |
360 | * @part: partition to allocate dev_t for | 361 | * @part: partition to allocate dev_t for |
361 | * @gfp_mask: memory allocation flag | ||
362 | * @devt: out parameter for resulting dev_t | 362 | * @devt: out parameter for resulting dev_t |
363 | * | 363 | * |
364 | * Allocate a dev_t for block device. | 364 | * Allocate a dev_t for block device. |
@@ -535,7 +535,7 @@ void unlink_gendisk(struct gendisk *disk) | |||
535 | /** | 535 | /** |
536 | * get_gendisk - get partitioning information for a given device | 536 | * get_gendisk - get partitioning information for a given device |
537 | * @devt: device to get partitioning information for | 537 | * @devt: device to get partitioning information for |
538 | * @part: returned partition index | 538 | * @partno: returned partition index |
539 | * | 539 | * |
540 | * This function gets the structure containing partitioning | 540 | * This function gets the structure containing partitioning |
541 | * information for the given device @devt. | 541 | * information for the given device @devt. |
@@ -728,12 +728,24 @@ static int show_partition(struct seq_file *seqf, void *v) | |||
728 | return 0; | 728 | return 0; |
729 | } | 729 | } |
730 | 730 | ||
731 | const struct seq_operations partitions_op = { | 731 | static const struct seq_operations partitions_op = { |
732 | .start = show_partition_start, | 732 | .start = show_partition_start, |
733 | .next = disk_seqf_next, | 733 | .next = disk_seqf_next, |
734 | .stop = disk_seqf_stop, | 734 | .stop = disk_seqf_stop, |
735 | .show = show_partition | 735 | .show = show_partition |
736 | }; | 736 | }; |
737 | |||
738 | static int partitions_open(struct inode *inode, struct file *file) | ||
739 | { | ||
740 | return seq_open(file, &partitions_op); | ||
741 | } | ||
742 | |||
743 | static const struct file_operations proc_partitions_operations = { | ||
744 | .open = partitions_open, | ||
745 | .read = seq_read, | ||
746 | .llseek = seq_lseek, | ||
747 | .release = seq_release, | ||
748 | }; | ||
737 | #endif | 749 | #endif |
738 | 750 | ||
739 | 751 | ||
@@ -993,12 +1005,32 @@ static int diskstats_show(struct seq_file *seqf, void *v) | |||
993 | return 0; | 1005 | return 0; |
994 | } | 1006 | } |
995 | 1007 | ||
996 | const struct seq_operations diskstats_op = { | 1008 | static const struct seq_operations diskstats_op = { |
997 | .start = disk_seqf_start, | 1009 | .start = disk_seqf_start, |
998 | .next = disk_seqf_next, | 1010 | .next = disk_seqf_next, |
999 | .stop = disk_seqf_stop, | 1011 | .stop = disk_seqf_stop, |
1000 | .show = diskstats_show | 1012 | .show = diskstats_show |
1001 | }; | 1013 | }; |
1014 | |||
1015 | static int diskstats_open(struct inode *inode, struct file *file) | ||
1016 | { | ||
1017 | return seq_open(file, &diskstats_op); | ||
1018 | } | ||
1019 | |||
1020 | static const struct file_operations proc_diskstats_operations = { | ||
1021 | .open = diskstats_open, | ||
1022 | .read = seq_read, | ||
1023 | .llseek = seq_lseek, | ||
1024 | .release = seq_release, | ||
1025 | }; | ||
1026 | |||
1027 | static int __init proc_genhd_init(void) | ||
1028 | { | ||
1029 | proc_create("diskstats", 0, NULL, &proc_diskstats_operations); | ||
1030 | proc_create("partitions", 0, NULL, &proc_partitions_operations); | ||
1031 | return 0; | ||
1032 | } | ||
1033 | module_init(proc_genhd_init); | ||
1002 | #endif /* CONFIG_PROC_FS */ | 1034 | #endif /* CONFIG_PROC_FS */ |
1003 | 1035 | ||
1004 | static void media_change_notify_thread(struct work_struct *work) | 1036 | 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) | |||
201 | return put_user(val, (u64 __user *)arg); | 201 | return put_user(val, (u64 __user *)arg); |
202 | } | 202 | } |
203 | 203 | ||
204 | static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev, | 204 | int __blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, |
205 | unsigned cmd, unsigned long arg) | 205 | unsigned cmd, unsigned long arg) |
206 | { | ||
207 | struct backing_dev_info *bdi; | ||
208 | int ret, n; | ||
209 | |||
210 | switch (cmd) { | ||
211 | case BLKRAGET: | ||
212 | case BLKFRAGET: | ||
213 | if (!arg) | ||
214 | return -EINVAL; | ||
215 | bdi = blk_get_backing_dev_info(bdev); | ||
216 | if (bdi == NULL) | ||
217 | return -ENOTTY; | ||
218 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | ||
219 | case BLKROGET: | ||
220 | return put_int(arg, bdev_read_only(bdev) != 0); | ||
221 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | ||
222 | return put_int(arg, block_size(bdev)); | ||
223 | case BLKSSZGET: /* get block device hardware sector size */ | ||
224 | return put_int(arg, bdev_hardsect_size(bdev)); | ||
225 | case BLKSECTGET: | ||
226 | return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); | ||
227 | case BLKRASET: | ||
228 | case BLKFRASET: | ||
229 | if(!capable(CAP_SYS_ADMIN)) | ||
230 | return -EACCES; | ||
231 | bdi = blk_get_backing_dev_info(bdev); | ||
232 | if (bdi == NULL) | ||
233 | return -ENOTTY; | ||
234 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | ||
235 | return 0; | ||
236 | case BLKBSZSET: | ||
237 | /* set the logical block size */ | ||
238 | if (!capable(CAP_SYS_ADMIN)) | ||
239 | return -EACCES; | ||
240 | if (!arg) | ||
241 | return -EINVAL; | ||
242 | if (get_user(n, (int __user *) arg)) | ||
243 | return -EFAULT; | ||
244 | if (bd_claim(bdev, file) < 0) | ||
245 | return -EBUSY; | ||
246 | ret = set_blocksize(bdev, n); | ||
247 | bd_release(bdev); | ||
248 | return ret; | ||
249 | case BLKPG: | ||
250 | return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); | ||
251 | case BLKRRPART: | ||
252 | return blkdev_reread_part(bdev); | ||
253 | case BLKGETSIZE: | ||
254 | if ((bdev->bd_inode->i_size >> 9) > ~0UL) | ||
255 | return -EFBIG; | ||
256 | return put_ulong(arg, bdev->bd_inode->i_size >> 9); | ||
257 | case BLKGETSIZE64: | ||
258 | return put_u64(arg, bdev->bd_inode->i_size); | ||
259 | case BLKTRACESTART: | ||
260 | case BLKTRACESTOP: | ||
261 | case BLKTRACESETUP: | ||
262 | case BLKTRACETEARDOWN: | ||
263 | return blk_trace_ioctl(bdev, cmd, (char __user *) arg); | ||
264 | } | ||
265 | return -ENOIOCTLCMD; | ||
266 | } | ||
267 | |||
268 | int blkdev_driver_ioctl(struct inode *inode, struct file *file, | ||
269 | struct gendisk *disk, unsigned cmd, unsigned long arg) | ||
270 | { | 206 | { |
207 | struct gendisk *disk = bdev->bd_disk; | ||
271 | int ret; | 208 | int ret; |
272 | if (disk->fops->unlocked_ioctl) | ||
273 | return disk->fops->unlocked_ioctl(file, cmd, arg); | ||
274 | 209 | ||
275 | if (disk->fops->ioctl) { | 210 | if (disk->fops->ioctl) |
211 | return disk->fops->ioctl(bdev, mode, cmd, arg); | ||
212 | |||
213 | if (disk->fops->locked_ioctl) { | ||
276 | lock_kernel(); | 214 | lock_kernel(); |
277 | ret = disk->fops->ioctl(inode, file, cmd, arg); | 215 | ret = disk->fops->locked_ioctl(bdev, mode, cmd, arg); |
278 | unlock_kernel(); | 216 | unlock_kernel(); |
279 | return ret; | 217 | return ret; |
280 | } | 218 | } |
281 | 219 | ||
282 | return -ENOTTY; | 220 | return -ENOTTY; |
283 | } | 221 | } |
284 | EXPORT_SYMBOL_GPL(blkdev_driver_ioctl); | 222 | /* |
223 | * For the record: _GPL here is only because somebody decided to slap it | ||
224 | * on the previous export. Sheer idiocy, since it wasn't copyrightable | ||
225 | * at all and could be open-coded without any exports by anybody who cares. | ||
226 | */ | ||
227 | EXPORT_SYMBOL_GPL(__blkdev_driver_ioctl); | ||
285 | 228 | ||
286 | /* | 229 | /* |
287 | * always keep this in sync with compat_blkdev_ioctl() and | 230 | * always keep this in sync with compat_blkdev_ioctl() and |
288 | * compat_blkdev_locked_ioctl() | 231 | * compat_blkdev_locked_ioctl() |
289 | */ | 232 | */ |
290 | int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | 233 | int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, |
291 | unsigned long arg) | 234 | unsigned long arg) |
292 | { | 235 | { |
293 | struct block_device *bdev = inode->i_bdev; | ||
294 | struct gendisk *disk = bdev->bd_disk; | 236 | struct gendisk *disk = bdev->bd_disk; |
237 | struct backing_dev_info *bdi; | ||
238 | loff_t size; | ||
295 | int ret, n; | 239 | int ret, n; |
296 | 240 | ||
297 | switch(cmd) { | 241 | switch(cmd) { |
@@ -299,7 +243,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
299 | if (!capable(CAP_SYS_ADMIN)) | 243 | if (!capable(CAP_SYS_ADMIN)) |
300 | return -EACCES; | 244 | return -EACCES; |
301 | 245 | ||
302 | ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 246 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
303 | /* -EINVAL to handle old uncorrected drivers */ | 247 | /* -EINVAL to handle old uncorrected drivers */ |
304 | if (ret != -EINVAL && ret != -ENOTTY) | 248 | if (ret != -EINVAL && ret != -ENOTTY) |
305 | return ret; | 249 | return ret; |
@@ -311,7 +255,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
311 | return 0; | 255 | return 0; |
312 | 256 | ||
313 | case BLKROSET: | 257 | case BLKROSET: |
314 | ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 258 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); |
315 | /* -EINVAL to handle old uncorrected drivers */ | 259 | /* -EINVAL to handle old uncorrected drivers */ |
316 | if (ret != -EINVAL && ret != -ENOTTY) | 260 | if (ret != -EINVAL && ret != -ENOTTY) |
317 | return ret; | 261 | return ret; |
@@ -327,7 +271,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, | |||
327 | case BLKDISCARD: { | 271 | case BLKDISCARD: { |
328 | uint64_t range[2]; | 272 | uint64_t range[2]; |
329 | 273 | ||
330 | if (!(file->f_mode & FMODE_WRITE)) | 274 | if (!(mode & FMODE_WRITE)) |
331 | return -EBADF; | 275 | return -EBADF; |
332 | 276 | ||
333 | if (copy_from_user(range, (void __user *)arg, sizeof(range))) | 277 | 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, | |||
357 | return -EFAULT; | 301 | return -EFAULT; |
358 | return 0; | 302 | return 0; |
359 | } | 303 | } |
360 | } | 304 | case BLKRAGET: |
361 | 305 | case BLKFRAGET: | |
362 | lock_kernel(); | 306 | if (!arg) |
363 | ret = blkdev_locked_ioctl(file, bdev, cmd, arg); | 307 | return -EINVAL; |
364 | unlock_kernel(); | 308 | bdi = blk_get_backing_dev_info(bdev); |
365 | if (ret != -ENOIOCTLCMD) | 309 | if (bdi == NULL) |
310 | return -ENOTTY; | ||
311 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | ||
312 | case BLKROGET: | ||
313 | return put_int(arg, bdev_read_only(bdev) != 0); | ||
314 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | ||
315 | return put_int(arg, block_size(bdev)); | ||
316 | case BLKSSZGET: /* get block device hardware sector size */ | ||
317 | return put_int(arg, bdev_hardsect_size(bdev)); | ||
318 | case BLKSECTGET: | ||
319 | return put_ushort(arg, bdev_get_queue(bdev)->max_sectors); | ||
320 | case BLKRASET: | ||
321 | case BLKFRASET: | ||
322 | if(!capable(CAP_SYS_ADMIN)) | ||
323 | return -EACCES; | ||
324 | bdi = blk_get_backing_dev_info(bdev); | ||
325 | if (bdi == NULL) | ||
326 | return -ENOTTY; | ||
327 | lock_kernel(); | ||
328 | bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; | ||
329 | unlock_kernel(); | ||
330 | return 0; | ||
331 | case BLKBSZSET: | ||
332 | /* set the logical block size */ | ||
333 | if (!capable(CAP_SYS_ADMIN)) | ||
334 | return -EACCES; | ||
335 | if (!arg) | ||
336 | return -EINVAL; | ||
337 | if (get_user(n, (int __user *) arg)) | ||
338 | return -EFAULT; | ||
339 | if (!(mode & FMODE_EXCL) && bd_claim(bdev, &bdev) < 0) | ||
340 | return -EBUSY; | ||
341 | ret = set_blocksize(bdev, n); | ||
342 | if (!(mode & FMODE_EXCL)) | ||
343 | bd_release(bdev); | ||
366 | return ret; | 344 | return ret; |
367 | 345 | case BLKPG: | |
368 | return blkdev_driver_ioctl(inode, file, disk, cmd, arg); | 346 | lock_kernel(); |
347 | ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg); | ||
348 | unlock_kernel(); | ||
349 | break; | ||
350 | case BLKRRPART: | ||
351 | lock_kernel(); | ||
352 | ret = blkdev_reread_part(bdev); | ||
353 | unlock_kernel(); | ||
354 | break; | ||
355 | case BLKGETSIZE: | ||
356 | size = bdev->bd_inode->i_size; | ||
357 | if ((size >> 9) > ~0UL) | ||
358 | return -EFBIG; | ||
359 | return put_ulong(arg, size >> 9); | ||
360 | case BLKGETSIZE64: | ||
361 | return put_u64(arg, bdev->bd_inode->i_size); | ||
362 | case BLKTRACESTART: | ||
363 | case BLKTRACESTOP: | ||
364 | case BLKTRACESETUP: | ||
365 | case BLKTRACETEARDOWN: | ||
366 | lock_kernel(); | ||
367 | ret = blk_trace_ioctl(bdev, cmd, (char __user *) arg); | ||
368 | unlock_kernel(); | ||
369 | break; | ||
370 | default: | ||
371 | ret = __blkdev_driver_ioctl(bdev, mode, cmd, arg); | ||
372 | } | ||
373 | return ret; | ||
369 | } | 374 | } |
370 | EXPORT_SYMBOL_GPL(blkdev_ioctl); | 375 | 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) | |||
190 | EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); | 190 | EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); |
191 | 191 | ||
192 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, | 192 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, |
193 | struct sg_io_hdr *hdr, struct file *file) | 193 | struct sg_io_hdr *hdr, fmode_t mode) |
194 | { | 194 | { |
195 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) | 195 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) |
196 | return -EFAULT; | 196 | return -EFAULT; |
197 | if (blk_verify_command(&q->cmd_filter, rq->cmd, | 197 | if (blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE)) |
198 | file->f_mode & FMODE_WRITE)) | ||
199 | return -EPERM; | 198 | return -EPERM; |
200 | 199 | ||
201 | /* | 200 | /* |
@@ -260,8 +259,8 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, | |||
260 | return r; | 259 | return r; |
261 | } | 260 | } |
262 | 261 | ||
263 | static int sg_io(struct file *file, struct request_queue *q, | 262 | static int sg_io(struct request_queue *q, struct gendisk *bd_disk, |
264 | struct gendisk *bd_disk, struct sg_io_hdr *hdr) | 263 | struct sg_io_hdr *hdr, fmode_t mode) |
265 | { | 264 | { |
266 | unsigned long start_time; | 265 | unsigned long start_time; |
267 | int writing = 0, ret = 0; | 266 | int writing = 0, ret = 0; |
@@ -293,7 +292,7 @@ static int sg_io(struct file *file, struct request_queue *q, | |||
293 | if (!rq) | 292 | if (!rq) |
294 | return -ENOMEM; | 293 | return -ENOMEM; |
295 | 294 | ||
296 | if (blk_fill_sghdr_rq(q, rq, hdr, file)) { | 295 | if (blk_fill_sghdr_rq(q, rq, hdr, mode)) { |
297 | blk_put_request(rq); | 296 | blk_put_request(rq); |
298 | return -EFAULT; | 297 | return -EFAULT; |
299 | } | 298 | } |
@@ -380,11 +379,11 @@ out: | |||
380 | * bytes in one int) where the lowest byte is the SCSI status. | 379 | * bytes in one int) where the lowest byte is the SCSI status. |
381 | */ | 380 | */ |
382 | #define OMAX_SB_LEN 16 /* For backward compatibility */ | 381 | #define OMAX_SB_LEN 16 /* For backward compatibility */ |
383 | int sg_scsi_ioctl(struct file *file, struct request_queue *q, | 382 | int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, |
384 | struct gendisk *disk, struct scsi_ioctl_command __user *sic) | 383 | struct scsi_ioctl_command __user *sic) |
385 | { | 384 | { |
386 | struct request *rq; | 385 | struct request *rq; |
387 | int err, write_perm = 0; | 386 | int err; |
388 | unsigned int in_len, out_len, bytes, opcode, cmdlen; | 387 | unsigned int in_len, out_len, bytes, opcode, cmdlen; |
389 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; | 388 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; |
390 | 389 | ||
@@ -426,11 +425,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |||
426 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) | 425 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) |
427 | goto error; | 426 | goto error; |
428 | 427 | ||
429 | /* scsi_ioctl passes NULL */ | 428 | err = blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE); |
430 | if (file && (file->f_mode & FMODE_WRITE)) | ||
431 | write_perm = 1; | ||
432 | |||
433 | err = blk_verify_command(&q->cmd_filter, rq->cmd, write_perm); | ||
434 | if (err) | 429 | if (err) |
435 | goto error; | 430 | goto error; |
436 | 431 | ||
@@ -522,8 +517,8 @@ static inline int blk_send_start_stop(struct request_queue *q, | |||
522 | return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); | 517 | return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); |
523 | } | 518 | } |
524 | 519 | ||
525 | int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | 520 | int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode, |
526 | struct gendisk *bd_disk, unsigned int cmd, void __user *arg) | 521 | unsigned int cmd, void __user *arg) |
527 | { | 522 | { |
528 | int err; | 523 | int err; |
529 | 524 | ||
@@ -564,7 +559,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | |||
564 | err = -EFAULT; | 559 | err = -EFAULT; |
565 | if (copy_from_user(&hdr, arg, sizeof(hdr))) | 560 | if (copy_from_user(&hdr, arg, sizeof(hdr))) |
566 | break; | 561 | break; |
567 | err = sg_io(file, q, bd_disk, &hdr); | 562 | err = sg_io(q, bd_disk, &hdr, mode); |
568 | if (err == -EFAULT) | 563 | if (err == -EFAULT) |
569 | break; | 564 | break; |
570 | 565 | ||
@@ -612,7 +607,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | |||
612 | hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; | 607 | hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; |
613 | hdr.cmd_len = sizeof(cgc.cmd); | 608 | hdr.cmd_len = sizeof(cgc.cmd); |
614 | 609 | ||
615 | err = sg_io(file, q, bd_disk, &hdr); | 610 | err = sg_io(q, bd_disk, &hdr, mode); |
616 | if (err == -EFAULT) | 611 | if (err == -EFAULT) |
617 | break; | 612 | break; |
618 | 613 | ||
@@ -636,7 +631,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | |||
636 | if (!arg) | 631 | if (!arg) |
637 | break; | 632 | break; |
638 | 633 | ||
639 | err = sg_scsi_ioctl(file, q, bd_disk, arg); | 634 | err = sg_scsi_ioctl(q, bd_disk, mode, arg); |
640 | break; | 635 | break; |
641 | case CDROMCLOSETRAY: | 636 | case CDROMCLOSETRAY: |
642 | err = blk_send_start_stop(q, bd_disk, 0x03); | 637 | err = blk_send_start_stop(q, bd_disk, 0x03); |