diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/as-iosched.c | 10 | ||||
-rw-r--r-- | block/blk-barrier.c | 45 | ||||
-rw-r--r-- | block/blk-core.c | 9 | ||||
-rw-r--r-- | block/blk-settings.c | 34 | ||||
-rw-r--r-- | block/blk-sysfs.c | 11 | ||||
-rw-r--r-- | block/blk-tag.c | 2 | ||||
-rw-r--r-- | block/bsg.c | 4 | ||||
-rw-r--r-- | block/cfq-iosched.c | 252 | ||||
-rw-r--r-- | block/compat_ioctl.c | 13 | ||||
-rw-r--r-- | block/elevator.c | 4 | ||||
-rw-r--r-- | block/genhd.c | 10 | ||||
-rw-r--r-- | block/ioctl.c | 17 |
12 files changed, 258 insertions, 153 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c index 7a12cf6ee1d3..ce8ba57c6557 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c | |||
@@ -146,7 +146,7 @@ enum arq_state { | |||
146 | #define RQ_STATE(rq) ((enum arq_state)(rq)->elevator_private2) | 146 | #define RQ_STATE(rq) ((enum arq_state)(rq)->elevator_private2) |
147 | #define RQ_SET_STATE(rq, state) ((rq)->elevator_private2 = (void *) state) | 147 | #define RQ_SET_STATE(rq, state) ((rq)->elevator_private2 = (void *) state) |
148 | 148 | ||
149 | static DEFINE_PER_CPU(unsigned long, ioc_count); | 149 | static DEFINE_PER_CPU(unsigned long, as_ioc_count); |
150 | static struct completion *ioc_gone; | 150 | static struct completion *ioc_gone; |
151 | static DEFINE_SPINLOCK(ioc_gone_lock); | 151 | static DEFINE_SPINLOCK(ioc_gone_lock); |
152 | 152 | ||
@@ -161,7 +161,7 @@ static void as_antic_stop(struct as_data *ad); | |||
161 | static void free_as_io_context(struct as_io_context *aic) | 161 | static void free_as_io_context(struct as_io_context *aic) |
162 | { | 162 | { |
163 | kfree(aic); | 163 | kfree(aic); |
164 | elv_ioc_count_dec(ioc_count); | 164 | elv_ioc_count_dec(as_ioc_count); |
165 | if (ioc_gone) { | 165 | if (ioc_gone) { |
166 | /* | 166 | /* |
167 | * AS scheduler is exiting, grab exit lock and check | 167 | * AS scheduler is exiting, grab exit lock and check |
@@ -169,7 +169,7 @@ static void free_as_io_context(struct as_io_context *aic) | |||
169 | * complete ioc_gone and set it back to NULL. | 169 | * complete ioc_gone and set it back to NULL. |
170 | */ | 170 | */ |
171 | spin_lock(&ioc_gone_lock); | 171 | spin_lock(&ioc_gone_lock); |
172 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) { | 172 | if (ioc_gone && !elv_ioc_count_read(as_ioc_count)) { |
173 | complete(ioc_gone); | 173 | complete(ioc_gone); |
174 | ioc_gone = NULL; | 174 | ioc_gone = NULL; |
175 | } | 175 | } |
@@ -211,7 +211,7 @@ static struct as_io_context *alloc_as_io_context(void) | |||
211 | ret->seek_total = 0; | 211 | ret->seek_total = 0; |
212 | ret->seek_samples = 0; | 212 | ret->seek_samples = 0; |
213 | ret->seek_mean = 0; | 213 | ret->seek_mean = 0; |
214 | elv_ioc_count_inc(ioc_count); | 214 | elv_ioc_count_inc(as_ioc_count); |
215 | } | 215 | } |
216 | 216 | ||
217 | return ret; | 217 | return ret; |
@@ -1507,7 +1507,7 @@ static void __exit as_exit(void) | |||
1507 | ioc_gone = &all_gone; | 1507 | ioc_gone = &all_gone; |
1508 | /* ioc_gone's update must be visible before reading ioc_count */ | 1508 | /* ioc_gone's update must be visible before reading ioc_count */ |
1509 | smp_wmb(); | 1509 | smp_wmb(); |
1510 | if (elv_ioc_count_read(ioc_count)) | 1510 | if (elv_ioc_count_read(as_ioc_count)) |
1511 | wait_for_completion(&all_gone); | 1511 | wait_for_completion(&all_gone); |
1512 | synchronize_rcu(); | 1512 | synchronize_rcu(); |
1513 | } | 1513 | } |
diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 6593ab39cfe9..8873b9b439ff 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c | |||
@@ -350,6 +350,7 @@ static void blkdev_discard_end_io(struct bio *bio, int err) | |||
350 | 350 | ||
351 | if (bio->bi_private) | 351 | if (bio->bi_private) |
352 | complete(bio->bi_private); | 352 | complete(bio->bi_private); |
353 | __free_page(bio_page(bio)); | ||
353 | 354 | ||
354 | bio_put(bio); | 355 | bio_put(bio); |
355 | } | 356 | } |
@@ -372,30 +373,50 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
372 | struct request_queue *q = bdev_get_queue(bdev); | 373 | struct request_queue *q = bdev_get_queue(bdev); |
373 | int type = flags & DISCARD_FL_BARRIER ? | 374 | int type = flags & DISCARD_FL_BARRIER ? |
374 | DISCARD_BARRIER : DISCARD_NOBARRIER; | 375 | DISCARD_BARRIER : DISCARD_NOBARRIER; |
376 | struct bio *bio; | ||
377 | struct page *page; | ||
375 | int ret = 0; | 378 | int ret = 0; |
376 | 379 | ||
377 | if (!q) | 380 | if (!q) |
378 | return -ENXIO; | 381 | return -ENXIO; |
379 | 382 | ||
380 | if (!q->prepare_discard_fn) | 383 | if (!blk_queue_discard(q)) |
381 | return -EOPNOTSUPP; | 384 | return -EOPNOTSUPP; |
382 | 385 | ||
383 | while (nr_sects && !ret) { | 386 | while (nr_sects && !ret) { |
384 | struct bio *bio = bio_alloc(gfp_mask, 0); | 387 | unsigned int sector_size = q->limits.logical_block_size; |
385 | if (!bio) | 388 | unsigned int max_discard_sectors = |
386 | return -ENOMEM; | 389 | min(q->limits.max_discard_sectors, UINT_MAX >> 9); |
387 | 390 | ||
391 | bio = bio_alloc(gfp_mask, 1); | ||
392 | if (!bio) | ||
393 | goto out; | ||
394 | bio->bi_sector = sector; | ||
388 | bio->bi_end_io = blkdev_discard_end_io; | 395 | bio->bi_end_io = blkdev_discard_end_io; |
389 | bio->bi_bdev = bdev; | 396 | bio->bi_bdev = bdev; |
390 | if (flags & DISCARD_FL_WAIT) | 397 | if (flags & DISCARD_FL_WAIT) |
391 | bio->bi_private = &wait; | 398 | bio->bi_private = &wait; |
392 | 399 | ||
393 | bio->bi_sector = sector; | 400 | /* |
401 | * Add a zeroed one-sector payload as that's what | ||
402 | * our current implementations need. If we'll ever need | ||
403 | * more the interface will need revisiting. | ||
404 | */ | ||
405 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
406 | if (!page) | ||
407 | goto out_free_bio; | ||
408 | if (bio_add_pc_page(q, bio, page, sector_size, 0) < sector_size) | ||
409 | goto out_free_page; | ||
394 | 410 | ||
395 | if (nr_sects > queue_max_hw_sectors(q)) { | 411 | /* |
396 | bio->bi_size = queue_max_hw_sectors(q) << 9; | 412 | * And override the bio size - the way discard works we |
397 | nr_sects -= queue_max_hw_sectors(q); | 413 | * touch many more blocks on disk than the actual payload |
398 | sector += queue_max_hw_sectors(q); | 414 | * length. |
415 | */ | ||
416 | if (nr_sects > max_discard_sectors) { | ||
417 | bio->bi_size = max_discard_sectors << 9; | ||
418 | nr_sects -= max_discard_sectors; | ||
419 | sector += max_discard_sectors; | ||
399 | } else { | 420 | } else { |
400 | bio->bi_size = nr_sects << 9; | 421 | bio->bi_size = nr_sects << 9; |
401 | nr_sects = 0; | 422 | nr_sects = 0; |
@@ -414,5 +435,11 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
414 | bio_put(bio); | 435 | bio_put(bio); |
415 | } | 436 | } |
416 | return ret; | 437 | return ret; |
438 | out_free_page: | ||
439 | __free_page(page); | ||
440 | out_free_bio: | ||
441 | bio_put(bio); | ||
442 | out: | ||
443 | return -ENOMEM; | ||
417 | } | 444 | } |
418 | EXPORT_SYMBOL(blkdev_issue_discard); | 445 | EXPORT_SYMBOL(blkdev_issue_discard); |
diff --git a/block/blk-core.c b/block/blk-core.c index 8135228e4b29..ac0fa10f8fa5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "blk.h" | 34 | #include "blk.h" |
35 | 35 | ||
36 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_remap); | 36 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_remap); |
37 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap); | ||
37 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete); | 38 | EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete); |
38 | 39 | ||
39 | static int __make_request(struct request_queue *q, struct bio *bio); | 40 | static int __make_request(struct request_queue *q, struct bio *bio); |
@@ -1029,7 +1030,7 @@ static void part_round_stats_single(int cpu, struct hd_struct *part, | |||
1029 | if (now == part->stamp) | 1030 | if (now == part->stamp) |
1030 | return; | 1031 | return; |
1031 | 1032 | ||
1032 | if (part->in_flight) { | 1033 | if (part_in_flight(part)) { |
1033 | __part_stat_add(cpu, part, time_in_queue, | 1034 | __part_stat_add(cpu, part, time_in_queue, |
1034 | part_in_flight(part) * (now - part->stamp)); | 1035 | part_in_flight(part) * (now - part->stamp)); |
1035 | __part_stat_add(cpu, part, io_ticks, (now - part->stamp)); | 1036 | __part_stat_add(cpu, part, io_ticks, (now - part->stamp)); |
@@ -1124,7 +1125,6 @@ void init_request_from_bio(struct request *req, struct bio *bio) | |||
1124 | req->cmd_flags |= REQ_DISCARD; | 1125 | req->cmd_flags |= REQ_DISCARD; |
1125 | if (bio_rw_flagged(bio, BIO_RW_BARRIER)) | 1126 | if (bio_rw_flagged(bio, BIO_RW_BARRIER)) |
1126 | req->cmd_flags |= REQ_SOFTBARRIER; | 1127 | req->cmd_flags |= REQ_SOFTBARRIER; |
1127 | req->q->prepare_discard_fn(req->q, req); | ||
1128 | } else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) | 1128 | } else if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) |
1129 | req->cmd_flags |= REQ_HARDBARRIER; | 1129 | req->cmd_flags |= REQ_HARDBARRIER; |
1130 | 1130 | ||
@@ -1437,7 +1437,8 @@ static inline void __generic_make_request(struct bio *bio) | |||
1437 | goto end_io; | 1437 | goto end_io; |
1438 | } | 1438 | } |
1439 | 1439 | ||
1440 | if (unlikely(nr_sectors > queue_max_hw_sectors(q))) { | 1440 | if (unlikely(!bio_rw_flagged(bio, BIO_RW_DISCARD) && |
1441 | nr_sectors > queue_max_hw_sectors(q))) { | ||
1441 | printk(KERN_ERR "bio too big device %s (%u > %u)\n", | 1442 | printk(KERN_ERR "bio too big device %s (%u > %u)\n", |
1442 | bdevname(bio->bi_bdev, b), | 1443 | bdevname(bio->bi_bdev, b), |
1443 | bio_sectors(bio), | 1444 | bio_sectors(bio), |
@@ -1470,7 +1471,7 @@ static inline void __generic_make_request(struct bio *bio) | |||
1470 | goto end_io; | 1471 | goto end_io; |
1471 | 1472 | ||
1472 | if (bio_rw_flagged(bio, BIO_RW_DISCARD) && | 1473 | if (bio_rw_flagged(bio, BIO_RW_DISCARD) && |
1473 | !q->prepare_discard_fn) { | 1474 | !blk_queue_discard(q)) { |
1474 | err = -EOPNOTSUPP; | 1475 | err = -EOPNOTSUPP; |
1475 | goto end_io; | 1476 | goto end_io; |
1476 | } | 1477 | } |
diff --git a/block/blk-settings.c b/block/blk-settings.c index 83413ff83739..66d4aa8799b7 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -34,23 +34,6 @@ void blk_queue_prep_rq(struct request_queue *q, prep_rq_fn *pfn) | |||
34 | EXPORT_SYMBOL(blk_queue_prep_rq); | 34 | EXPORT_SYMBOL(blk_queue_prep_rq); |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * blk_queue_set_discard - set a discard_sectors function for queue | ||
38 | * @q: queue | ||
39 | * @dfn: prepare_discard function | ||
40 | * | ||
41 | * It's possible for a queue to register a discard callback which is used | ||
42 | * to transform a discard request into the appropriate type for the | ||
43 | * hardware. If none is registered, then discard requests are failed | ||
44 | * with %EOPNOTSUPP. | ||
45 | * | ||
46 | */ | ||
47 | void blk_queue_set_discard(struct request_queue *q, prepare_discard_fn *dfn) | ||
48 | { | ||
49 | q->prepare_discard_fn = dfn; | ||
50 | } | ||
51 | EXPORT_SYMBOL(blk_queue_set_discard); | ||
52 | |||
53 | /** | ||
54 | * blk_queue_merge_bvec - set a merge_bvec function for queue | 37 | * blk_queue_merge_bvec - set a merge_bvec function for queue |
55 | * @q: queue | 38 | * @q: queue |
56 | * @mbfn: merge_bvec_fn | 39 | * @mbfn: merge_bvec_fn |
@@ -111,7 +94,9 @@ void blk_set_default_limits(struct queue_limits *lim) | |||
111 | lim->max_hw_segments = MAX_HW_SEGMENTS; | 94 | lim->max_hw_segments = MAX_HW_SEGMENTS; |
112 | lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK; | 95 | lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK; |
113 | lim->max_segment_size = MAX_SEGMENT_SIZE; | 96 | lim->max_segment_size = MAX_SEGMENT_SIZE; |
114 | lim->max_sectors = lim->max_hw_sectors = SAFE_MAX_SECTORS; | 97 | lim->max_sectors = BLK_DEF_MAX_SECTORS; |
98 | lim->max_hw_sectors = INT_MAX; | ||
99 | lim->max_discard_sectors = SAFE_MAX_SECTORS; | ||
115 | lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; | 100 | lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; |
116 | lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); | 101 | lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); |
117 | lim->alignment_offset = 0; | 102 | lim->alignment_offset = 0; |
@@ -164,6 +149,7 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) | |||
164 | q->unplug_timer.data = (unsigned long)q; | 149 | q->unplug_timer.data = (unsigned long)q; |
165 | 150 | ||
166 | blk_set_default_limits(&q->limits); | 151 | blk_set_default_limits(&q->limits); |
152 | blk_queue_max_sectors(q, SAFE_MAX_SECTORS); | ||
167 | 153 | ||
168 | /* | 154 | /* |
169 | * If the caller didn't supply a lock, fall back to our embedded | 155 | * If the caller didn't supply a lock, fall back to our embedded |
@@ -254,6 +240,18 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_sectors) | |||
254 | EXPORT_SYMBOL(blk_queue_max_hw_sectors); | 240 | EXPORT_SYMBOL(blk_queue_max_hw_sectors); |
255 | 241 | ||
256 | /** | 242 | /** |
243 | * blk_queue_max_discard_sectors - set max sectors for a single discard | ||
244 | * @q: the request queue for the device | ||
245 | * @max_discard_sectors: maximum number of sectors to discard | ||
246 | **/ | ||
247 | void blk_queue_max_discard_sectors(struct request_queue *q, | ||
248 | unsigned int max_discard_sectors) | ||
249 | { | ||
250 | q->limits.max_discard_sectors = max_discard_sectors; | ||
251 | } | ||
252 | EXPORT_SYMBOL(blk_queue_max_discard_sectors); | ||
253 | |||
254 | /** | ||
257 | * blk_queue_max_phys_segments - set max phys segments for a request for this queue | 255 | * blk_queue_max_phys_segments - set max phys segments for a request for this queue |
258 | * @q: the request queue for the device | 256 | * @q: the request queue for the device |
259 | * @max_segments: max number of segments | 257 | * @max_segments: max number of segments |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index b78c9c3e2670..8a6d81afb284 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -452,6 +452,7 @@ int blk_register_queue(struct gendisk *disk) | |||
452 | if (ret) { | 452 | if (ret) { |
453 | kobject_uevent(&q->kobj, KOBJ_REMOVE); | 453 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
454 | kobject_del(&q->kobj); | 454 | kobject_del(&q->kobj); |
455 | blk_trace_remove_sysfs(disk_to_dev(disk)); | ||
455 | return ret; | 456 | return ret; |
456 | } | 457 | } |
457 | 458 | ||
@@ -465,11 +466,11 @@ void blk_unregister_queue(struct gendisk *disk) | |||
465 | if (WARN_ON(!q)) | 466 | if (WARN_ON(!q)) |
466 | return; | 467 | return; |
467 | 468 | ||
468 | if (q->request_fn) { | 469 | if (q->request_fn) |
469 | elv_unregister_queue(q); | 470 | elv_unregister_queue(q); |
470 | 471 | ||
471 | kobject_uevent(&q->kobj, KOBJ_REMOVE); | 472 | kobject_uevent(&q->kobj, KOBJ_REMOVE); |
472 | kobject_del(&q->kobj); | 473 | kobject_del(&q->kobj); |
473 | kobject_put(&disk_to_dev(disk)->kobj); | 474 | blk_trace_remove_sysfs(disk_to_dev(disk)); |
474 | } | 475 | kobject_put(&disk_to_dev(disk)->kobj); |
475 | } | 476 | } |
diff --git a/block/blk-tag.c b/block/blk-tag.c index 2e5cfeb59333..6b0f52c20964 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c | |||
@@ -359,7 +359,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) | |||
359 | max_depth -= 2; | 359 | max_depth -= 2; |
360 | if (!max_depth) | 360 | if (!max_depth) |
361 | max_depth = 1; | 361 | max_depth = 1; |
362 | if (q->in_flight[0] > max_depth) | 362 | if (q->in_flight[BLK_RW_ASYNC] > max_depth) |
363 | return 1; | 363 | return 1; |
364 | } | 364 | } |
365 | 365 | ||
diff --git a/block/bsg.c b/block/bsg.c index 5f184bb3ff9e..0676301f16d0 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -1062,7 +1062,7 @@ EXPORT_SYMBOL_GPL(bsg_register_queue); | |||
1062 | 1062 | ||
1063 | static struct cdev bsg_cdev; | 1063 | static struct cdev bsg_cdev; |
1064 | 1064 | ||
1065 | static char *bsg_nodename(struct device *dev) | 1065 | static char *bsg_devnode(struct device *dev, mode_t *mode) |
1066 | { | 1066 | { |
1067 | return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev)); | 1067 | return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev)); |
1068 | } | 1068 | } |
@@ -1087,7 +1087,7 @@ static int __init bsg_init(void) | |||
1087 | ret = PTR_ERR(bsg_class); | 1087 | ret = PTR_ERR(bsg_class); |
1088 | goto destroy_kmemcache; | 1088 | goto destroy_kmemcache; |
1089 | } | 1089 | } |
1090 | bsg_class->nodename = bsg_nodename; | 1090 | bsg_class->devnode = bsg_devnode; |
1091 | 1091 | ||
1092 | ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg"); | 1092 | ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg"); |
1093 | if (ret) | 1093 | if (ret) |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 0e3814b662af..069a61017c02 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -48,7 +48,7 @@ static int cfq_slice_idle = HZ / 125; | |||
48 | static struct kmem_cache *cfq_pool; | 48 | static struct kmem_cache *cfq_pool; |
49 | static struct kmem_cache *cfq_ioc_pool; | 49 | static struct kmem_cache *cfq_ioc_pool; |
50 | 50 | ||
51 | static DEFINE_PER_CPU(unsigned long, ioc_count); | 51 | static DEFINE_PER_CPU(unsigned long, cfq_ioc_count); |
52 | static struct completion *ioc_gone; | 52 | static struct completion *ioc_gone; |
53 | static DEFINE_SPINLOCK(ioc_gone_lock); | 53 | static DEFINE_SPINLOCK(ioc_gone_lock); |
54 | 54 | ||
@@ -173,6 +173,7 @@ struct cfq_data { | |||
173 | unsigned int cfq_slice[2]; | 173 | unsigned int cfq_slice[2]; |
174 | unsigned int cfq_slice_async_rq; | 174 | unsigned int cfq_slice_async_rq; |
175 | unsigned int cfq_slice_idle; | 175 | unsigned int cfq_slice_idle; |
176 | unsigned int cfq_latency; | ||
176 | 177 | ||
177 | struct list_head cic_list; | 178 | struct list_head cic_list; |
178 | 179 | ||
@@ -180,6 +181,8 @@ struct cfq_data { | |||
180 | * Fallback dummy cfqq for extreme OOM conditions | 181 | * Fallback dummy cfqq for extreme OOM conditions |
181 | */ | 182 | */ |
182 | struct cfq_queue oom_cfqq; | 183 | struct cfq_queue oom_cfqq; |
184 | |||
185 | unsigned long last_end_sync_rq; | ||
183 | }; | 186 | }; |
184 | 187 | ||
185 | enum cfqq_state_flags { | 188 | enum cfqq_state_flags { |
@@ -227,7 +230,7 @@ CFQ_CFQQ_FNS(coop); | |||
227 | blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args) | 230 | blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args) |
228 | 231 | ||
229 | static void cfq_dispatch_insert(struct request_queue *, struct request *); | 232 | static void cfq_dispatch_insert(struct request_queue *, struct request *); |
230 | static struct cfq_queue *cfq_get_queue(struct cfq_data *, int, | 233 | static struct cfq_queue *cfq_get_queue(struct cfq_data *, bool, |
231 | struct io_context *, gfp_t); | 234 | struct io_context *, gfp_t); |
232 | static struct cfq_io_context *cfq_cic_lookup(struct cfq_data *, | 235 | static struct cfq_io_context *cfq_cic_lookup(struct cfq_data *, |
233 | struct io_context *); | 236 | struct io_context *); |
@@ -238,27 +241,24 @@ static inline int rq_in_driver(struct cfq_data *cfqd) | |||
238 | } | 241 | } |
239 | 242 | ||
240 | static inline struct cfq_queue *cic_to_cfqq(struct cfq_io_context *cic, | 243 | static inline struct cfq_queue *cic_to_cfqq(struct cfq_io_context *cic, |
241 | int is_sync) | 244 | bool is_sync) |
242 | { | 245 | { |
243 | return cic->cfqq[!!is_sync]; | 246 | return cic->cfqq[is_sync]; |
244 | } | 247 | } |
245 | 248 | ||
246 | static inline void cic_set_cfqq(struct cfq_io_context *cic, | 249 | static inline void cic_set_cfqq(struct cfq_io_context *cic, |
247 | struct cfq_queue *cfqq, int is_sync) | 250 | struct cfq_queue *cfqq, bool is_sync) |
248 | { | 251 | { |
249 | cic->cfqq[!!is_sync] = cfqq; | 252 | cic->cfqq[is_sync] = cfqq; |
250 | } | 253 | } |
251 | 254 | ||
252 | /* | 255 | /* |
253 | * We regard a request as SYNC, if it's either a read or has the SYNC bit | 256 | * We regard a request as SYNC, if it's either a read or has the SYNC bit |
254 | * set (in which case it could also be direct WRITE). | 257 | * set (in which case it could also be direct WRITE). |
255 | */ | 258 | */ |
256 | static inline int cfq_bio_sync(struct bio *bio) | 259 | static inline bool cfq_bio_sync(struct bio *bio) |
257 | { | 260 | { |
258 | if (bio_data_dir(bio) == READ || bio_rw_flagged(bio, BIO_RW_SYNCIO)) | 261 | return bio_data_dir(bio) == READ || bio_rw_flagged(bio, BIO_RW_SYNCIO); |
259 | return 1; | ||
260 | |||
261 | return 0; | ||
262 | } | 262 | } |
263 | 263 | ||
264 | /* | 264 | /* |
@@ -285,7 +285,7 @@ static int cfq_queue_empty(struct request_queue *q) | |||
285 | * if a queue is marked sync and has sync io queued. A sync queue with async | 285 | * if a queue is marked sync and has sync io queued. A sync queue with async |
286 | * io only, should not get full sync slice length. | 286 | * io only, should not get full sync slice length. |
287 | */ | 287 | */ |
288 | static inline int cfq_prio_slice(struct cfq_data *cfqd, int sync, | 288 | static inline int cfq_prio_slice(struct cfq_data *cfqd, bool sync, |
289 | unsigned short prio) | 289 | unsigned short prio) |
290 | { | 290 | { |
291 | const int base_slice = cfqd->cfq_slice[sync]; | 291 | const int base_slice = cfqd->cfq_slice[sync]; |
@@ -313,7 +313,7 @@ cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
313 | * isn't valid until the first request from the dispatch is activated | 313 | * isn't valid until the first request from the dispatch is activated |
314 | * and the slice time set. | 314 | * and the slice time set. |
315 | */ | 315 | */ |
316 | static inline int cfq_slice_used(struct cfq_queue *cfqq) | 316 | static inline bool cfq_slice_used(struct cfq_queue *cfqq) |
317 | { | 317 | { |
318 | if (cfq_cfqq_slice_new(cfqq)) | 318 | if (cfq_cfqq_slice_new(cfqq)) |
319 | return 0; | 319 | return 0; |
@@ -488,7 +488,7 @@ static unsigned long cfq_slice_offset(struct cfq_data *cfqd, | |||
488 | * we will service the queues. | 488 | * we will service the queues. |
489 | */ | 489 | */ |
490 | static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 490 | static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
491 | int add_front) | 491 | bool add_front) |
492 | { | 492 | { |
493 | struct rb_node **p, *parent; | 493 | struct rb_node **p, *parent; |
494 | struct cfq_queue *__cfqq; | 494 | struct cfq_queue *__cfqq; |
@@ -504,11 +504,20 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
504 | } else | 504 | } else |
505 | rb_key += jiffies; | 505 | rb_key += jiffies; |
506 | } else if (!add_front) { | 506 | } else if (!add_front) { |
507 | /* | ||
508 | * Get our rb key offset. Subtract any residual slice | ||
509 | * value carried from last service. A negative resid | ||
510 | * count indicates slice overrun, and this should position | ||
511 | * the next service time further away in the tree. | ||
512 | */ | ||
507 | rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies; | 513 | rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies; |
508 | rb_key += cfqq->slice_resid; | 514 | rb_key -= cfqq->slice_resid; |
509 | cfqq->slice_resid = 0; | 515 | cfqq->slice_resid = 0; |
510 | } else | 516 | } else { |
511 | rb_key = 0; | 517 | rb_key = -HZ; |
518 | __cfqq = cfq_rb_first(&cfqd->service_tree); | ||
519 | rb_key += __cfqq ? __cfqq->rb_key : jiffies; | ||
520 | } | ||
512 | 521 | ||
513 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) { | 522 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) { |
514 | /* | 523 | /* |
@@ -542,7 +551,7 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
542 | n = &(*p)->rb_left; | 551 | n = &(*p)->rb_left; |
543 | else if (cfq_class_idle(cfqq) > cfq_class_idle(__cfqq)) | 552 | else if (cfq_class_idle(cfqq) > cfq_class_idle(__cfqq)) |
544 | n = &(*p)->rb_right; | 553 | n = &(*p)->rb_right; |
545 | else if (rb_key < __cfqq->rb_key) | 554 | else if (time_before(rb_key, __cfqq->rb_key)) |
546 | n = &(*p)->rb_left; | 555 | n = &(*p)->rb_left; |
547 | else | 556 | else |
548 | n = &(*p)->rb_right; | 557 | n = &(*p)->rb_right; |
@@ -822,8 +831,10 @@ cfq_merged_requests(struct request_queue *q, struct request *rq, | |||
822 | * reposition in fifo if next is older than rq | 831 | * reposition in fifo if next is older than rq |
823 | */ | 832 | */ |
824 | if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && | 833 | if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && |
825 | time_before(next->start_time, rq->start_time)) | 834 | time_before(rq_fifo_time(next), rq_fifo_time(rq))) { |
826 | list_move(&rq->queuelist, &next->queuelist); | 835 | list_move(&rq->queuelist, &next->queuelist); |
836 | rq_set_fifo_time(rq, rq_fifo_time(next)); | ||
837 | } | ||
827 | 838 | ||
828 | cfq_remove_request(next); | 839 | cfq_remove_request(next); |
829 | } | 840 | } |
@@ -839,7 +850,7 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq, | |||
839 | * Disallow merge of a sync bio into an async request. | 850 | * Disallow merge of a sync bio into an async request. |
840 | */ | 851 | */ |
841 | if (cfq_bio_sync(bio) && !rq_is_sync(rq)) | 852 | if (cfq_bio_sync(bio) && !rq_is_sync(rq)) |
842 | return 0; | 853 | return false; |
843 | 854 | ||
844 | /* | 855 | /* |
845 | * Lookup the cfqq that this bio will be queued with. Allow | 856 | * Lookup the cfqq that this bio will be queued with. Allow |
@@ -847,13 +858,10 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq, | |||
847 | */ | 858 | */ |
848 | cic = cfq_cic_lookup(cfqd, current->io_context); | 859 | cic = cfq_cic_lookup(cfqd, current->io_context); |
849 | if (!cic) | 860 | if (!cic) |
850 | return 0; | 861 | return false; |
851 | 862 | ||
852 | cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio)); | 863 | cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio)); |
853 | if (cfqq == RQ_CFQQ(rq)) | 864 | return cfqq == RQ_CFQQ(rq); |
854 | return 1; | ||
855 | |||
856 | return 0; | ||
857 | } | 865 | } |
858 | 866 | ||
859 | static void __cfq_set_active_queue(struct cfq_data *cfqd, | 867 | static void __cfq_set_active_queue(struct cfq_data *cfqd, |
@@ -881,7 +889,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd, | |||
881 | */ | 889 | */ |
882 | static void | 890 | static void |
883 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 891 | __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
884 | int timed_out) | 892 | bool timed_out) |
885 | { | 893 | { |
886 | cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out); | 894 | cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out); |
887 | 895 | ||
@@ -909,7 +917,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
909 | } | 917 | } |
910 | } | 918 | } |
911 | 919 | ||
912 | static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out) | 920 | static inline void cfq_slice_expired(struct cfq_data *cfqd, bool timed_out) |
913 | { | 921 | { |
914 | struct cfq_queue *cfqq = cfqd->active_queue; | 922 | struct cfq_queue *cfqq = cfqd->active_queue; |
915 | 923 | ||
@@ -1021,7 +1029,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | |||
1021 | */ | 1029 | */ |
1022 | static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd, | 1030 | static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd, |
1023 | struct cfq_queue *cur_cfqq, | 1031 | struct cfq_queue *cur_cfqq, |
1024 | int probe) | 1032 | bool probe) |
1025 | { | 1033 | { |
1026 | struct cfq_queue *cfqq; | 1034 | struct cfq_queue *cfqq; |
1027 | 1035 | ||
@@ -1085,6 +1093,15 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
1085 | if (!cic || !atomic_read(&cic->ioc->nr_tasks)) | 1093 | if (!cic || !atomic_read(&cic->ioc->nr_tasks)) |
1086 | return; | 1094 | return; |
1087 | 1095 | ||
1096 | /* | ||
1097 | * If our average think time is larger than the remaining time | ||
1098 | * slice, then don't idle. This avoids overrunning the allotted | ||
1099 | * time slice. | ||
1100 | */ | ||
1101 | if (sample_valid(cic->ttime_samples) && | ||
1102 | (cfqq->slice_end - jiffies < cic->ttime_mean)) | ||
1103 | return; | ||
1104 | |||
1088 | cfq_mark_cfqq_wait_request(cfqq); | 1105 | cfq_mark_cfqq_wait_request(cfqq); |
1089 | 1106 | ||
1090 | /* | 1107 | /* |
@@ -1124,9 +1141,7 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq) | |||
1124 | */ | 1141 | */ |
1125 | static struct request *cfq_check_fifo(struct cfq_queue *cfqq) | 1142 | static struct request *cfq_check_fifo(struct cfq_queue *cfqq) |
1126 | { | 1143 | { |
1127 | struct cfq_data *cfqd = cfqq->cfqd; | 1144 | struct request *rq = NULL; |
1128 | struct request *rq; | ||
1129 | int fifo; | ||
1130 | 1145 | ||
1131 | if (cfq_cfqq_fifo_expire(cfqq)) | 1146 | if (cfq_cfqq_fifo_expire(cfqq)) |
1132 | return NULL; | 1147 | return NULL; |
@@ -1136,13 +1151,11 @@ static struct request *cfq_check_fifo(struct cfq_queue *cfqq) | |||
1136 | if (list_empty(&cfqq->fifo)) | 1151 | if (list_empty(&cfqq->fifo)) |
1137 | return NULL; | 1152 | return NULL; |
1138 | 1153 | ||
1139 | fifo = cfq_cfqq_sync(cfqq); | ||
1140 | rq = rq_entry_fifo(cfqq->fifo.next); | 1154 | rq = rq_entry_fifo(cfqq->fifo.next); |
1141 | 1155 | if (time_before(jiffies, rq_fifo_time(rq))) | |
1142 | if (time_before(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) | ||
1143 | rq = NULL; | 1156 | rq = NULL; |
1144 | 1157 | ||
1145 | cfq_log_cfqq(cfqd, cfqq, "fifo=%p", rq); | 1158 | cfq_log_cfqq(cfqq->cfqd, cfqq, "fifo=%p", rq); |
1146 | return rq; | 1159 | return rq; |
1147 | } | 1160 | } |
1148 | 1161 | ||
@@ -1243,16 +1256,83 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd) | |||
1243 | return dispatched; | 1256 | return dispatched; |
1244 | } | 1257 | } |
1245 | 1258 | ||
1259 | static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq) | ||
1260 | { | ||
1261 | unsigned int max_dispatch; | ||
1262 | |||
1263 | /* | ||
1264 | * Drain async requests before we start sync IO | ||
1265 | */ | ||
1266 | if (cfq_cfqq_idle_window(cfqq) && cfqd->rq_in_driver[BLK_RW_ASYNC]) | ||
1267 | return false; | ||
1268 | |||
1269 | /* | ||
1270 | * If this is an async queue and we have sync IO in flight, let it wait | ||
1271 | */ | ||
1272 | if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq)) | ||
1273 | return false; | ||
1274 | |||
1275 | max_dispatch = cfqd->cfq_quantum; | ||
1276 | if (cfq_class_idle(cfqq)) | ||
1277 | max_dispatch = 1; | ||
1278 | |||
1279 | /* | ||
1280 | * Does this cfqq already have too much IO in flight? | ||
1281 | */ | ||
1282 | if (cfqq->dispatched >= max_dispatch) { | ||
1283 | /* | ||
1284 | * idle queue must always only have a single IO in flight | ||
1285 | */ | ||
1286 | if (cfq_class_idle(cfqq)) | ||
1287 | return false; | ||
1288 | |||
1289 | /* | ||
1290 | * We have other queues, don't allow more IO from this one | ||
1291 | */ | ||
1292 | if (cfqd->busy_queues > 1) | ||
1293 | return false; | ||
1294 | |||
1295 | /* | ||
1296 | * Sole queue user, allow bigger slice | ||
1297 | */ | ||
1298 | max_dispatch *= 4; | ||
1299 | } | ||
1300 | |||
1301 | /* | ||
1302 | * Async queues must wait a bit before being allowed dispatch. | ||
1303 | * We also ramp up the dispatch depth gradually for async IO, | ||
1304 | * based on the last sync IO we serviced | ||
1305 | */ | ||
1306 | if (!cfq_cfqq_sync(cfqq) && cfqd->cfq_latency) { | ||
1307 | unsigned long last_sync = jiffies - cfqd->last_end_sync_rq; | ||
1308 | unsigned int depth; | ||
1309 | |||
1310 | depth = last_sync / cfqd->cfq_slice[1]; | ||
1311 | if (!depth && !cfqq->dispatched) | ||
1312 | depth = 1; | ||
1313 | if (depth < max_dispatch) | ||
1314 | max_dispatch = depth; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1318 | * If we're below the current max, allow a dispatch | ||
1319 | */ | ||
1320 | return cfqq->dispatched < max_dispatch; | ||
1321 | } | ||
1322 | |||
1246 | /* | 1323 | /* |
1247 | * Dispatch a request from cfqq, moving them to the request queue | 1324 | * Dispatch a request from cfqq, moving them to the request queue |
1248 | * dispatch list. | 1325 | * dispatch list. |
1249 | */ | 1326 | */ |
1250 | static void cfq_dispatch_request(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 1327 | static bool cfq_dispatch_request(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
1251 | { | 1328 | { |
1252 | struct request *rq; | 1329 | struct request *rq; |
1253 | 1330 | ||
1254 | BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list)); | 1331 | BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list)); |
1255 | 1332 | ||
1333 | if (!cfq_may_dispatch(cfqd, cfqq)) | ||
1334 | return false; | ||
1335 | |||
1256 | /* | 1336 | /* |
1257 | * follow expired path, else get first next available | 1337 | * follow expired path, else get first next available |
1258 | */ | 1338 | */ |
@@ -1271,6 +1351,8 @@ static void cfq_dispatch_request(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1271 | atomic_long_inc(&cic->ioc->refcount); | 1351 | atomic_long_inc(&cic->ioc->refcount); |
1272 | cfqd->active_cic = cic; | 1352 | cfqd->active_cic = cic; |
1273 | } | 1353 | } |
1354 | |||
1355 | return true; | ||
1274 | } | 1356 | } |
1275 | 1357 | ||
1276 | /* | 1358 | /* |
@@ -1281,7 +1363,6 @@ static int cfq_dispatch_requests(struct request_queue *q, int force) | |||
1281 | { | 1363 | { |
1282 | struct cfq_data *cfqd = q->elevator->elevator_data; | 1364 | struct cfq_data *cfqd = q->elevator->elevator_data; |
1283 | struct cfq_queue *cfqq; | 1365 | struct cfq_queue *cfqq; |
1284 | unsigned int max_dispatch; | ||
1285 | 1366 | ||
1286 | if (!cfqd->busy_queues) | 1367 | if (!cfqd->busy_queues) |
1287 | return 0; | 1368 | return 0; |
@@ -1294,48 +1375,11 @@ static int cfq_dispatch_requests(struct request_queue *q, int force) | |||
1294 | return 0; | 1375 | return 0; |
1295 | 1376 | ||
1296 | /* | 1377 | /* |
1297 | * Drain async requests before we start sync IO | 1378 | * Dispatch a request from this cfqq, if it is allowed |
1298 | */ | 1379 | */ |
1299 | if (cfq_cfqq_idle_window(cfqq) && cfqd->rq_in_driver[BLK_RW_ASYNC]) | 1380 | if (!cfq_dispatch_request(cfqd, cfqq)) |
1300 | return 0; | 1381 | return 0; |
1301 | 1382 | ||
1302 | /* | ||
1303 | * If this is an async queue and we have sync IO in flight, let it wait | ||
1304 | */ | ||
1305 | if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq)) | ||
1306 | return 0; | ||
1307 | |||
1308 | max_dispatch = cfqd->cfq_quantum; | ||
1309 | if (cfq_class_idle(cfqq)) | ||
1310 | max_dispatch = 1; | ||
1311 | |||
1312 | /* | ||
1313 | * Does this cfqq already have too much IO in flight? | ||
1314 | */ | ||
1315 | if (cfqq->dispatched >= max_dispatch) { | ||
1316 | /* | ||
1317 | * idle queue must always only have a single IO in flight | ||
1318 | */ | ||
1319 | if (cfq_class_idle(cfqq)) | ||
1320 | return 0; | ||
1321 | |||
1322 | /* | ||
1323 | * We have other queues, don't allow more IO from this one | ||
1324 | */ | ||
1325 | if (cfqd->busy_queues > 1) | ||
1326 | return 0; | ||
1327 | |||
1328 | /* | ||
1329 | * we are the only queue, allow up to 4 times of 'quantum' | ||
1330 | */ | ||
1331 | if (cfqq->dispatched >= 4 * max_dispatch) | ||
1332 | return 0; | ||
1333 | } | ||
1334 | |||
1335 | /* | ||
1336 | * Dispatch a request from this cfqq | ||
1337 | */ | ||
1338 | cfq_dispatch_request(cfqd, cfqq); | ||
1339 | cfqq->slice_dispatch++; | 1383 | cfqq->slice_dispatch++; |
1340 | cfq_clear_cfqq_must_dispatch(cfqq); | 1384 | cfq_clear_cfqq_must_dispatch(cfqq); |
1341 | 1385 | ||
@@ -1415,7 +1459,7 @@ static void cfq_cic_free_rcu(struct rcu_head *head) | |||
1415 | cic = container_of(head, struct cfq_io_context, rcu_head); | 1459 | cic = container_of(head, struct cfq_io_context, rcu_head); |
1416 | 1460 | ||
1417 | kmem_cache_free(cfq_ioc_pool, cic); | 1461 | kmem_cache_free(cfq_ioc_pool, cic); |
1418 | elv_ioc_count_dec(ioc_count); | 1462 | elv_ioc_count_dec(cfq_ioc_count); |
1419 | 1463 | ||
1420 | if (ioc_gone) { | 1464 | if (ioc_gone) { |
1421 | /* | 1465 | /* |
@@ -1424,7 +1468,7 @@ static void cfq_cic_free_rcu(struct rcu_head *head) | |||
1424 | * complete ioc_gone and set it back to NULL | 1468 | * complete ioc_gone and set it back to NULL |
1425 | */ | 1469 | */ |
1426 | spin_lock(&ioc_gone_lock); | 1470 | spin_lock(&ioc_gone_lock); |
1427 | if (ioc_gone && !elv_ioc_count_read(ioc_count)) { | 1471 | if (ioc_gone && !elv_ioc_count_read(cfq_ioc_count)) { |
1428 | complete(ioc_gone); | 1472 | complete(ioc_gone); |
1429 | ioc_gone = NULL; | 1473 | ioc_gone = NULL; |
1430 | } | 1474 | } |
@@ -1550,7 +1594,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
1550 | INIT_HLIST_NODE(&cic->cic_list); | 1594 | INIT_HLIST_NODE(&cic->cic_list); |
1551 | cic->dtor = cfq_free_io_context; | 1595 | cic->dtor = cfq_free_io_context; |
1552 | cic->exit = cfq_exit_io_context; | 1596 | cic->exit = cfq_exit_io_context; |
1553 | elv_ioc_count_inc(ioc_count); | 1597 | elv_ioc_count_inc(cfq_ioc_count); |
1554 | } | 1598 | } |
1555 | 1599 | ||
1556 | return cic; | 1600 | return cic; |
@@ -1635,7 +1679,7 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc) | |||
1635 | } | 1679 | } |
1636 | 1680 | ||
1637 | static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 1681 | static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
1638 | pid_t pid, int is_sync) | 1682 | pid_t pid, bool is_sync) |
1639 | { | 1683 | { |
1640 | RB_CLEAR_NODE(&cfqq->rb_node); | 1684 | RB_CLEAR_NODE(&cfqq->rb_node); |
1641 | RB_CLEAR_NODE(&cfqq->p_node); | 1685 | RB_CLEAR_NODE(&cfqq->p_node); |
@@ -1655,7 +1699,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1655 | } | 1699 | } |
1656 | 1700 | ||
1657 | static struct cfq_queue * | 1701 | static struct cfq_queue * |
1658 | cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, | 1702 | cfq_find_alloc_queue(struct cfq_data *cfqd, bool is_sync, |
1659 | struct io_context *ioc, gfp_t gfp_mask) | 1703 | struct io_context *ioc, gfp_t gfp_mask) |
1660 | { | 1704 | { |
1661 | struct cfq_queue *cfqq, *new_cfqq = NULL; | 1705 | struct cfq_queue *cfqq, *new_cfqq = NULL; |
@@ -1719,7 +1763,7 @@ cfq_async_queue_prio(struct cfq_data *cfqd, int ioprio_class, int ioprio) | |||
1719 | } | 1763 | } |
1720 | 1764 | ||
1721 | static struct cfq_queue * | 1765 | static struct cfq_queue * |
1722 | cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc, | 1766 | cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc, |
1723 | gfp_t gfp_mask) | 1767 | gfp_t gfp_mask) |
1724 | { | 1768 | { |
1725 | const int ioprio = task_ioprio(ioc); | 1769 | const int ioprio = task_ioprio(ioc); |
@@ -1951,10 +1995,13 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1951 | enable_idle = old_idle = cfq_cfqq_idle_window(cfqq); | 1995 | enable_idle = old_idle = cfq_cfqq_idle_window(cfqq); |
1952 | 1996 | ||
1953 | if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle || | 1997 | if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle || |
1954 | (cfqd->hw_tag && CIC_SEEKY(cic))) | 1998 | (!cfqd->cfq_latency && cfqd->hw_tag && CIC_SEEKY(cic))) |
1955 | enable_idle = 0; | 1999 | enable_idle = 0; |
1956 | else if (sample_valid(cic->ttime_samples)) { | 2000 | else if (sample_valid(cic->ttime_samples)) { |
1957 | if (cic->ttime_mean > cfqd->cfq_slice_idle) | 2001 | unsigned int slice_idle = cfqd->cfq_slice_idle; |
2002 | if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic)) | ||
2003 | slice_idle = msecs_to_jiffies(CFQ_MIN_TT); | ||
2004 | if (cic->ttime_mean > slice_idle) | ||
1958 | enable_idle = 0; | 2005 | enable_idle = 0; |
1959 | else | 2006 | else |
1960 | enable_idle = 1; | 2007 | enable_idle = 1; |
@@ -1973,7 +2020,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
1973 | * Check if new_cfqq should preempt the currently active queue. Return 0 for | 2020 | * Check if new_cfqq should preempt the currently active queue. Return 0 for |
1974 | * no or if we aren't sure, a 1 will cause a preempt. | 2021 | * no or if we aren't sure, a 1 will cause a preempt. |
1975 | */ | 2022 | */ |
1976 | static int | 2023 | static bool |
1977 | cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | 2024 | cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, |
1978 | struct request *rq) | 2025 | struct request *rq) |
1979 | { | 2026 | { |
@@ -1981,48 +2028,48 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
1981 | 2028 | ||
1982 | cfqq = cfqd->active_queue; | 2029 | cfqq = cfqd->active_queue; |
1983 | if (!cfqq) | 2030 | if (!cfqq) |
1984 | return 0; | 2031 | return false; |
1985 | 2032 | ||
1986 | if (cfq_slice_used(cfqq)) | 2033 | if (cfq_slice_used(cfqq)) |
1987 | return 1; | 2034 | return true; |
1988 | 2035 | ||
1989 | if (cfq_class_idle(new_cfqq)) | 2036 | if (cfq_class_idle(new_cfqq)) |
1990 | return 0; | 2037 | return false; |
1991 | 2038 | ||
1992 | if (cfq_class_idle(cfqq)) | 2039 | if (cfq_class_idle(cfqq)) |
1993 | return 1; | 2040 | return true; |
1994 | 2041 | ||
1995 | /* | 2042 | /* |
1996 | * if the new request is sync, but the currently running queue is | 2043 | * if the new request is sync, but the currently running queue is |
1997 | * not, let the sync request have priority. | 2044 | * not, let the sync request have priority. |
1998 | */ | 2045 | */ |
1999 | if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) | 2046 | if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) |
2000 | return 1; | 2047 | return true; |
2001 | 2048 | ||
2002 | /* | 2049 | /* |
2003 | * So both queues are sync. Let the new request get disk time if | 2050 | * So both queues are sync. Let the new request get disk time if |
2004 | * it's a metadata request and the current queue is doing regular IO. | 2051 | * it's a metadata request and the current queue is doing regular IO. |
2005 | */ | 2052 | */ |
2006 | if (rq_is_meta(rq) && !cfqq->meta_pending) | 2053 | if (rq_is_meta(rq) && !cfqq->meta_pending) |
2007 | return 1; | 2054 | return false; |
2008 | 2055 | ||
2009 | /* | 2056 | /* |
2010 | * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice. | 2057 | * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice. |
2011 | */ | 2058 | */ |
2012 | if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq)) | 2059 | if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq)) |
2013 | return 1; | 2060 | return true; |
2014 | 2061 | ||
2015 | if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq)) | 2062 | if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq)) |
2016 | return 0; | 2063 | return false; |
2017 | 2064 | ||
2018 | /* | 2065 | /* |
2019 | * if this request is as-good as one we would expect from the | 2066 | * if this request is as-good as one we would expect from the |
2020 | * current cfqq, let it preempt | 2067 | * current cfqq, let it preempt |
2021 | */ | 2068 | */ |
2022 | if (cfq_rq_close(cfqd, rq)) | 2069 | if (cfq_rq_close(cfqd, rq)) |
2023 | return 1; | 2070 | return true; |
2024 | 2071 | ||
2025 | return 0; | 2072 | return false; |
2026 | } | 2073 | } |
2027 | 2074 | ||
2028 | /* | 2075 | /* |
@@ -2107,6 +2154,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) | |||
2107 | 2154 | ||
2108 | cfq_add_rq_rb(rq); | 2155 | cfq_add_rq_rb(rq); |
2109 | 2156 | ||
2157 | rq_set_fifo_time(rq, jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]); | ||
2110 | list_add_tail(&rq->queuelist, &cfqq->fifo); | 2158 | list_add_tail(&rq->queuelist, &cfqq->fifo); |
2111 | 2159 | ||
2112 | cfq_rq_enqueued(cfqd, cfqq, rq); | 2160 | cfq_rq_enqueued(cfqd, cfqq, rq); |
@@ -2157,8 +2205,10 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
2157 | if (cfq_cfqq_sync(cfqq)) | 2205 | if (cfq_cfqq_sync(cfqq)) |
2158 | cfqd->sync_flight--; | 2206 | cfqd->sync_flight--; |
2159 | 2207 | ||
2160 | if (sync) | 2208 | if (sync) { |
2161 | RQ_CIC(rq)->last_end_request = now; | 2209 | RQ_CIC(rq)->last_end_request = now; |
2210 | cfqd->last_end_sync_rq = now; | ||
2211 | } | ||
2162 | 2212 | ||
2163 | /* | 2213 | /* |
2164 | * If this is the active queue, check if it needs to be expired, | 2214 | * If this is the active queue, check if it needs to be expired, |
@@ -2284,7 +2334,7 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) | |||
2284 | struct cfq_data *cfqd = q->elevator->elevator_data; | 2334 | struct cfq_data *cfqd = q->elevator->elevator_data; |
2285 | struct cfq_io_context *cic; | 2335 | struct cfq_io_context *cic; |
2286 | const int rw = rq_data_dir(rq); | 2336 | const int rw = rq_data_dir(rq); |
2287 | const int is_sync = rq_is_sync(rq); | 2337 | const bool is_sync = rq_is_sync(rq); |
2288 | struct cfq_queue *cfqq; | 2338 | struct cfq_queue *cfqq; |
2289 | unsigned long flags; | 2339 | unsigned long flags; |
2290 | 2340 | ||
@@ -2480,8 +2530,9 @@ static void *cfq_init_queue(struct request_queue *q) | |||
2480 | cfqd->cfq_slice[1] = cfq_slice_sync; | 2530 | cfqd->cfq_slice[1] = cfq_slice_sync; |
2481 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; | 2531 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; |
2482 | cfqd->cfq_slice_idle = cfq_slice_idle; | 2532 | cfqd->cfq_slice_idle = cfq_slice_idle; |
2533 | cfqd->cfq_latency = 1; | ||
2483 | cfqd->hw_tag = 1; | 2534 | cfqd->hw_tag = 1; |
2484 | 2535 | cfqd->last_end_sync_rq = jiffies; | |
2485 | return cfqd; | 2536 | return cfqd; |
2486 | } | 2537 | } |
2487 | 2538 | ||
@@ -2549,6 +2600,7 @@ SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); | |||
2549 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); | 2600 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); |
2550 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); | 2601 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); |
2551 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); | 2602 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); |
2603 | SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0); | ||
2552 | #undef SHOW_FUNCTION | 2604 | #undef SHOW_FUNCTION |
2553 | 2605 | ||
2554 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ | 2606 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ |
@@ -2580,6 +2632,7 @@ STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); | |||
2580 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); | 2632 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); |
2581 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, | 2633 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, |
2582 | UINT_MAX, 0); | 2634 | UINT_MAX, 0); |
2635 | STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0); | ||
2583 | #undef STORE_FUNCTION | 2636 | #undef STORE_FUNCTION |
2584 | 2637 | ||
2585 | #define CFQ_ATTR(name) \ | 2638 | #define CFQ_ATTR(name) \ |
@@ -2595,6 +2648,7 @@ static struct elv_fs_entry cfq_attrs[] = { | |||
2595 | CFQ_ATTR(slice_async), | 2648 | CFQ_ATTR(slice_async), |
2596 | CFQ_ATTR(slice_async_rq), | 2649 | CFQ_ATTR(slice_async_rq), |
2597 | CFQ_ATTR(slice_idle), | 2650 | CFQ_ATTR(slice_idle), |
2651 | CFQ_ATTR(low_latency), | ||
2598 | __ATTR_NULL | 2652 | __ATTR_NULL |
2599 | }; | 2653 | }; |
2600 | 2654 | ||
@@ -2654,7 +2708,7 @@ static void __exit cfq_exit(void) | |||
2654 | * this also protects us from entering cfq_slab_kill() with | 2708 | * this also protects us from entering cfq_slab_kill() with |
2655 | * pending RCU callbacks | 2709 | * pending RCU callbacks |
2656 | */ | 2710 | */ |
2657 | if (elv_ioc_count_read(ioc_count)) | 2711 | if (elv_ioc_count_read(cfq_ioc_count)) |
2658 | wait_for_completion(&all_gone); | 2712 | wait_for_completion(&all_gone); |
2659 | cfq_slab_kill(); | 2713 | cfq_slab_kill(); |
2660 | } | 2714 | } |
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 7865a34e0faa..9bd086c1a4d5 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -21,6 +21,11 @@ static int compat_put_int(unsigned long arg, int val) | |||
21 | return put_user(val, (compat_int_t __user *)compat_ptr(arg)); | 21 | return put_user(val, (compat_int_t __user *)compat_ptr(arg)); |
22 | } | 22 | } |
23 | 23 | ||
24 | static int compat_put_uint(unsigned long arg, unsigned int val) | ||
25 | { | ||
26 | return put_user(val, (compat_uint_t __user *)compat_ptr(arg)); | ||
27 | } | ||
28 | |||
24 | static int compat_put_long(unsigned long arg, long val) | 29 | static int compat_put_long(unsigned long arg, long val) |
25 | { | 30 | { |
26 | return put_user(val, (compat_long_t __user *)compat_ptr(arg)); | 31 | return put_user(val, (compat_long_t __user *)compat_ptr(arg)); |
@@ -734,6 +739,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
734 | switch (cmd) { | 739 | switch (cmd) { |
735 | case HDIO_GETGEO: | 740 | case HDIO_GETGEO: |
736 | return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); | 741 | return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); |
742 | case BLKPBSZGET: | ||
743 | return compat_put_uint(arg, bdev_physical_block_size(bdev)); | ||
744 | case BLKIOMIN: | ||
745 | return compat_put_uint(arg, bdev_io_min(bdev)); | ||
746 | case BLKIOOPT: | ||
747 | return compat_put_uint(arg, bdev_io_opt(bdev)); | ||
748 | case BLKALIGNOFF: | ||
749 | return compat_put_int(arg, bdev_alignment_offset(bdev)); | ||
737 | case BLKFLSBUF: | 750 | case BLKFLSBUF: |
738 | case BLKROSET: | 751 | case BLKROSET: |
739 | case BLKDISCARD: | 752 | case BLKDISCARD: |
diff --git a/block/elevator.c b/block/elevator.c index 1975b619c86d..a847046c6e53 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -1059,9 +1059,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, | |||
1059 | return count; | 1059 | return count; |
1060 | 1060 | ||
1061 | strlcpy(elevator_name, name, sizeof(elevator_name)); | 1061 | strlcpy(elevator_name, name, sizeof(elevator_name)); |
1062 | strstrip(elevator_name); | 1062 | e = elevator_get(strstrip(elevator_name)); |
1063 | |||
1064 | e = elevator_get(elevator_name); | ||
1065 | if (!e) { | 1063 | if (!e) { |
1066 | printk(KERN_ERR "elevator: type %s not found\n", elevator_name); | 1064 | printk(KERN_ERR "elevator: type %s not found\n", elevator_name); |
1067 | return -EINVAL; | 1065 | return -EINVAL; |
diff --git a/block/genhd.c b/block/genhd.c index 5b76bf55d05c..517e4332cb37 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -903,7 +903,7 @@ static struct attribute_group disk_attr_group = { | |||
903 | .attrs = disk_attrs, | 903 | .attrs = disk_attrs, |
904 | }; | 904 | }; |
905 | 905 | ||
906 | static struct attribute_group *disk_attr_groups[] = { | 906 | static const struct attribute_group *disk_attr_groups[] = { |
907 | &disk_attr_group, | 907 | &disk_attr_group, |
908 | NULL | 908 | NULL |
909 | }; | 909 | }; |
@@ -998,12 +998,12 @@ struct class block_class = { | |||
998 | .name = "block", | 998 | .name = "block", |
999 | }; | 999 | }; |
1000 | 1000 | ||
1001 | static char *block_nodename(struct device *dev) | 1001 | static char *block_devnode(struct device *dev, mode_t *mode) |
1002 | { | 1002 | { |
1003 | struct gendisk *disk = dev_to_disk(dev); | 1003 | struct gendisk *disk = dev_to_disk(dev); |
1004 | 1004 | ||
1005 | if (disk->nodename) | 1005 | if (disk->devnode) |
1006 | return disk->nodename(disk); | 1006 | return disk->devnode(disk, mode); |
1007 | return NULL; | 1007 | return NULL; |
1008 | } | 1008 | } |
1009 | 1009 | ||
@@ -1011,7 +1011,7 @@ static struct device_type disk_type = { | |||
1011 | .name = "disk", | 1011 | .name = "disk", |
1012 | .groups = disk_attr_groups, | 1012 | .groups = disk_attr_groups, |
1013 | .release = disk_release, | 1013 | .release = disk_release, |
1014 | .nodename = block_nodename, | 1014 | .devnode = block_devnode, |
1015 | }; | 1015 | }; |
1016 | 1016 | ||
1017 | #ifdef CONFIG_PROC_FS | 1017 | #ifdef CONFIG_PROC_FS |
diff --git a/block/ioctl.c b/block/ioctl.c index d3e6b5827a34..1f4d1de12b09 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -138,6 +138,11 @@ static int put_int(unsigned long arg, int val) | |||
138 | return put_user(val, (int __user *)arg); | 138 | return put_user(val, (int __user *)arg); |
139 | } | 139 | } |
140 | 140 | ||
141 | static int put_uint(unsigned long arg, unsigned int val) | ||
142 | { | ||
143 | return put_user(val, (unsigned int __user *)arg); | ||
144 | } | ||
145 | |||
141 | static int put_long(unsigned long arg, long val) | 146 | static int put_long(unsigned long arg, long val) |
142 | { | 147 | { |
143 | return put_user(val, (long __user *)arg); | 148 | return put_user(val, (long __user *)arg); |
@@ -263,10 +268,18 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
263 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); | 268 | return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); |
264 | case BLKROGET: | 269 | case BLKROGET: |
265 | return put_int(arg, bdev_read_only(bdev) != 0); | 270 | return put_int(arg, bdev_read_only(bdev) != 0); |
266 | case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */ | 271 | case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */ |
267 | return put_int(arg, block_size(bdev)); | 272 | return put_int(arg, block_size(bdev)); |
268 | case BLKSSZGET: /* get block device hardware sector size */ | 273 | case BLKSSZGET: /* get block device logical block size */ |
269 | return put_int(arg, bdev_logical_block_size(bdev)); | 274 | return put_int(arg, bdev_logical_block_size(bdev)); |
275 | case BLKPBSZGET: /* get block device physical block size */ | ||
276 | return put_uint(arg, bdev_physical_block_size(bdev)); | ||
277 | case BLKIOMIN: | ||
278 | return put_uint(arg, bdev_io_min(bdev)); | ||
279 | case BLKIOOPT: | ||
280 | return put_uint(arg, bdev_io_opt(bdev)); | ||
281 | case BLKALIGNOFF: | ||
282 | return put_int(arg, bdev_alignment_offset(bdev)); | ||
270 | case BLKSECTGET: | 283 | case BLKSECTGET: |
271 | return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev))); | 284 | return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev))); |
272 | case BLKRASET: | 285 | case BLKRASET: |