aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c33
-rw-r--r--block/elevator.c26
2 files changed, 55 insertions, 4 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 533a2938ffd6..9fc5eafa6c0e 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -568,6 +568,38 @@ cfq_merged_requests(request_queue_t *q, struct request *rq,
568 cfq_remove_request(next); 568 cfq_remove_request(next);
569} 569}
570 570
571static int cfq_allow_merge(request_queue_t *q, struct request *rq,
572 struct bio *bio)
573{
574 struct cfq_data *cfqd = q->elevator->elevator_data;
575 const int rw = bio_data_dir(bio);
576 struct cfq_queue *cfqq;
577 pid_t key;
578
579 /*
580 * If bio is async or a write, always allow merge
581 */
582 if (!bio_sync(bio) || rw == WRITE)
583 return 1;
584
585 /*
586 * bio is sync. if request is not, disallow.
587 */
588 if (!rq_is_sync(rq))
589 return 0;
590
591 /*
592 * Ok, both bio and request are sync. Allow merge if they are
593 * from the same queue.
594 */
595 key = cfq_queue_pid(current, rw, 1);
596 cfqq = cfq_find_cfq_hash(cfqd, key, current->ioprio);
597 if (cfqq != RQ_CFQQ(rq))
598 return 0;
599
600 return 1;
601}
602
571static inline void 603static inline void
572__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) 604__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
573{ 605{
@@ -2125,6 +2157,7 @@ static struct elevator_type iosched_cfq = {
2125 .elevator_merge_fn = cfq_merge, 2157 .elevator_merge_fn = cfq_merge,
2126 .elevator_merged_fn = cfq_merged_request, 2158 .elevator_merged_fn = cfq_merged_request,
2127 .elevator_merge_req_fn = cfq_merged_requests, 2159 .elevator_merge_req_fn = cfq_merged_requests,
2160 .elevator_allow_merge_fn = cfq_allow_merge,
2128 .elevator_dispatch_fn = cfq_dispatch_requests, 2161 .elevator_dispatch_fn = cfq_dispatch_requests,
2129 .elevator_add_req_fn = cfq_insert_request, 2162 .elevator_add_req_fn = cfq_insert_request,
2130 .elevator_activate_req_fn = cfq_activate_request, 2163 .elevator_activate_req_fn = cfq_activate_request,
diff --git a/block/elevator.c b/block/elevator.c
index c0063f345c5d..62c7a3069d3a 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -51,6 +51,21 @@ static const int elv_hash_shift = 6;
51#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash)) 51#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
52 52
53/* 53/*
54 * Query io scheduler to see if the current process issuing bio may be
55 * merged with rq.
56 */
57static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
58{
59 request_queue_t *q = rq->q;
60 elevator_t *e = q->elevator;
61
62 if (e->ops->elevator_allow_merge_fn)
63 return e->ops->elevator_allow_merge_fn(q, rq, bio);
64
65 return 1;
66}
67
68/*
54 * can we safely merge with this request? 69 * can we safely merge with this request?
55 */ 70 */
56inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) 71inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
@@ -65,12 +80,15 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
65 return 0; 80 return 0;
66 81
67 /* 82 /*
68 * same device and no special stuff set, merge is ok 83 * must be same device and not a special request
69 */ 84 */
70 if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special) 85 if (rq->rq_disk != bio->bi_bdev->bd_disk || !rq->special)
71 return 1; 86 return 0;
72 87
73 return 0; 88 if (!elv_iosched_allow_merge(rq, bio))
89 return 0;
90
91 return 1;
74} 92}
75EXPORT_SYMBOL(elv_rq_merge_ok); 93EXPORT_SYMBOL(elv_rq_merge_ok);
76 94