aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/elevator.c123
-rw-r--r--block/ll_rw_blk.c7
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/elevator.h18
4 files changed, 130 insertions, 19 deletions
diff --git a/block/elevator.c b/block/elevator.c
index cff1102dac9d..cbbc36ba016a 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -239,6 +239,8 @@ int elevator_init(request_queue_t *q, char *name)
239 return ret; 239 return ret;
240} 240}
241 241
242EXPORT_SYMBOL(elevator_init);
243
242void elevator_exit(elevator_t *e) 244void elevator_exit(elevator_t *e)
243{ 245{
244 mutex_lock(&e->sysfs_lock); 246 mutex_lock(&e->sysfs_lock);
@@ -250,6 +252,8 @@ void elevator_exit(elevator_t *e)
250 kobject_put(&e->kobj); 252 kobject_put(&e->kobj);
251} 253}
252 254
255EXPORT_SYMBOL(elevator_exit);
256
253static inline void __elv_rqhash_del(struct request *rq) 257static inline void __elv_rqhash_del(struct request *rq)
254{ 258{
255 hlist_del_init(&rq->hash); 259 hlist_del_init(&rq->hash);
@@ -298,9 +302,68 @@ static struct request *elv_rqhash_find(request_queue_t *q, sector_t offset)
298} 302}
299 303
300/* 304/*
305 * RB-tree support functions for inserting/lookup/removal of requests
306 * in a sorted RB tree.
307 */
308struct request *elv_rb_add(struct rb_root *root, struct request *rq)
309{
310 struct rb_node **p = &root->rb_node;
311 struct rb_node *parent = NULL;
312 struct request *__rq;
313
314 while (*p) {
315 parent = *p;
316 __rq = rb_entry(parent, struct request, rb_node);
317
318 if (rq->sector < __rq->sector)
319 p = &(*p)->rb_left;
320 else if (rq->sector > __rq->sector)
321 p = &(*p)->rb_right;
322 else
323 return __rq;
324 }
325
326 rb_link_node(&rq->rb_node, parent, p);
327 rb_insert_color(&rq->rb_node, root);
328 return NULL;
329}
330
331EXPORT_SYMBOL(elv_rb_add);
332
333void elv_rb_del(struct rb_root *root, struct request *rq)
334{
335 BUG_ON(RB_EMPTY_NODE(&rq->rb_node));
336 rb_erase(&rq->rb_node, root);
337 RB_CLEAR_NODE(&rq->rb_node);
338}
339
340EXPORT_SYMBOL(elv_rb_del);
341
342struct request *elv_rb_find(struct rb_root *root, sector_t sector)
343{
344 struct rb_node *n = root->rb_node;
345 struct request *rq;
346
347 while (n) {
348 rq = rb_entry(n, struct request, rb_node);
349
350 if (sector < rq->sector)
351 n = n->rb_left;
352 else if (sector > rq->sector)
353 n = n->rb_right;
354 else
355 return rq;
356 }
357
358 return NULL;
359}
360
361EXPORT_SYMBOL(elv_rb_find);
362
363/*
301 * Insert rq into dispatch queue of q. Queue lock must be held on 364 * Insert rq into dispatch queue of q. Queue lock must be held on
302 * entry. If sort != 0, rq is sort-inserted; otherwise, rq will be 365 * entry. rq is sort insted into the dispatch queue. To be used by
303 * appended to the dispatch queue. To be used by specific elevators. 366 * specific elevators.
304 */ 367 */
305void elv_dispatch_sort(request_queue_t *q, struct request *rq) 368void elv_dispatch_sort(request_queue_t *q, struct request *rq)
306{ 369{
@@ -335,8 +398,12 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
335 list_add(&rq->queuelist, entry); 398 list_add(&rq->queuelist, entry);
336} 399}
337 400
401EXPORT_SYMBOL(elv_dispatch_sort);
402
338/* 403/*
339 * This should be in elevator.h, but that requires pulling in rq and q 404 * Insert rq into dispatch queue of q. Queue lock must be held on
405 * entry. rq is added to the back of the dispatch queue. To be used by
406 * specific elevators.
340 */ 407 */
341void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) 408void elv_dispatch_add_tail(struct request_queue *q, struct request *rq)
342{ 409{
@@ -352,6 +419,8 @@ void elv_dispatch_add_tail(struct request_queue *q, struct request *rq)
352 list_add_tail(&rq->queuelist, &q->queue_head); 419 list_add_tail(&rq->queuelist, &q->queue_head);
353} 420}
354 421
422EXPORT_SYMBOL(elv_dispatch_add_tail);
423
355int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) 424int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
356{ 425{
357 elevator_t *e = q->elevator; 426 elevator_t *e = q->elevator;
@@ -384,14 +453,15 @@ int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
384 return ELEVATOR_NO_MERGE; 453 return ELEVATOR_NO_MERGE;
385} 454}
386 455
387void elv_merged_request(request_queue_t *q, struct request *rq) 456void elv_merged_request(request_queue_t *q, struct request *rq, int type)
388{ 457{
389 elevator_t *e = q->elevator; 458 elevator_t *e = q->elevator;
390 459
391 if (e->ops->elevator_merged_fn) 460 if (e->ops->elevator_merged_fn)
392 e->ops->elevator_merged_fn(q, rq); 461 e->ops->elevator_merged_fn(q, rq, type);
393 462
394 elv_rqhash_reposition(q, rq); 463 if (type == ELEVATOR_BACK_MERGE)
464 elv_rqhash_reposition(q, rq);
395 465
396 q->last_merge = rq; 466 q->last_merge = rq;
397} 467}
@@ -577,6 +647,8 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
577 elv_insert(q, rq, where); 647 elv_insert(q, rq, where);
578} 648}
579 649
650EXPORT_SYMBOL(__elv_add_request);
651
580void elv_add_request(request_queue_t *q, struct request *rq, int where, 652void elv_add_request(request_queue_t *q, struct request *rq, int where,
581 int plug) 653 int plug)
582{ 654{
@@ -587,6 +659,8 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
587 spin_unlock_irqrestore(q->queue_lock, flags); 659 spin_unlock_irqrestore(q->queue_lock, flags);
588} 660}
589 661
662EXPORT_SYMBOL(elv_add_request);
663
590static inline struct request *__elv_next_request(request_queue_t *q) 664static inline struct request *__elv_next_request(request_queue_t *q)
591{ 665{
592 struct request *rq; 666 struct request *rq;
@@ -670,6 +744,8 @@ struct request *elv_next_request(request_queue_t *q)
670 return rq; 744 return rq;
671} 745}
672 746
747EXPORT_SYMBOL(elv_next_request);
748
673void elv_dequeue_request(request_queue_t *q, struct request *rq) 749void elv_dequeue_request(request_queue_t *q, struct request *rq)
674{ 750{
675 BUG_ON(list_empty(&rq->queuelist)); 751 BUG_ON(list_empty(&rq->queuelist));
@@ -686,6 +762,8 @@ void elv_dequeue_request(request_queue_t *q, struct request *rq)
686 q->in_flight++; 762 q->in_flight++;
687} 763}
688 764
765EXPORT_SYMBOL(elv_dequeue_request);
766
689int elv_queue_empty(request_queue_t *q) 767int elv_queue_empty(request_queue_t *q)
690{ 768{
691 elevator_t *e = q->elevator; 769 elevator_t *e = q->elevator;
@@ -699,6 +777,8 @@ int elv_queue_empty(request_queue_t *q)
699 return 1; 777 return 1;
700} 778}
701 779
780EXPORT_SYMBOL(elv_queue_empty);
781
702struct request *elv_latter_request(request_queue_t *q, struct request *rq) 782struct request *elv_latter_request(request_queue_t *q, struct request *rq)
703{ 783{
704 elevator_t *e = q->elevator; 784 elevator_t *e = q->elevator;
@@ -1025,11 +1105,26 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
1025 return len; 1105 return len;
1026} 1106}
1027 1107
1028EXPORT_SYMBOL(elv_dispatch_sort); 1108struct request *elv_rb_former_request(request_queue_t *q, struct request *rq)
1029EXPORT_SYMBOL(elv_add_request); 1109{
1030EXPORT_SYMBOL(__elv_add_request); 1110 struct rb_node *rbprev = rb_prev(&rq->rb_node);
1031EXPORT_SYMBOL(elv_next_request); 1111
1032EXPORT_SYMBOL(elv_dequeue_request); 1112 if (rbprev)
1033EXPORT_SYMBOL(elv_queue_empty); 1113 return rb_entry_rq(rbprev);
1034EXPORT_SYMBOL(elevator_exit); 1114
1035EXPORT_SYMBOL(elevator_init); 1115 return NULL;
1116}
1117
1118EXPORT_SYMBOL(elv_rb_former_request);
1119
1120struct request *elv_rb_latter_request(request_queue_t *q, struct request *rq)
1121{
1122 struct rb_node *rbnext = rb_next(&rq->rb_node);
1123
1124 if (rbnext)
1125 return rb_entry_rq(rbnext);
1126
1127 return NULL;
1128}
1129
1130EXPORT_SYMBOL(elv_rb_latter_request);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 9cbf7b550c78..d388486e98bb 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -281,11 +281,12 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
281{ 281{
282 INIT_LIST_HEAD(&rq->queuelist); 282 INIT_LIST_HEAD(&rq->queuelist);
283 INIT_LIST_HEAD(&rq->donelist); 283 INIT_LIST_HEAD(&rq->donelist);
284 INIT_HLIST_NODE(&rq->hash);
285 284
286 rq->errors = 0; 285 rq->errors = 0;
287 rq->rq_status = RQ_ACTIVE; 286 rq->rq_status = RQ_ACTIVE;
288 rq->bio = rq->biotail = NULL; 287 rq->bio = rq->biotail = NULL;
288 INIT_HLIST_NODE(&rq->hash);
289 RB_CLEAR_NODE(&rq->rb_node);
289 rq->ioprio = 0; 290 rq->ioprio = 0;
290 rq->buffer = NULL; 291 rq->buffer = NULL;
291 rq->ref_count = 1; 292 rq->ref_count = 1;
@@ -2943,7 +2944,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
2943 req->ioprio = ioprio_best(req->ioprio, prio); 2944 req->ioprio = ioprio_best(req->ioprio, prio);
2944 drive_stat_acct(req, nr_sectors, 0); 2945 drive_stat_acct(req, nr_sectors, 0);
2945 if (!attempt_back_merge(q, req)) 2946 if (!attempt_back_merge(q, req))
2946 elv_merged_request(q, req); 2947 elv_merged_request(q, req, el_ret);
2947 goto out; 2948 goto out;
2948 2949
2949 case ELEVATOR_FRONT_MERGE: 2950 case ELEVATOR_FRONT_MERGE:
@@ -2970,7 +2971,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
2970 req->ioprio = ioprio_best(req->ioprio, prio); 2971 req->ioprio = ioprio_best(req->ioprio, prio);
2971 drive_stat_acct(req, nr_sectors, 0); 2972 drive_stat_acct(req, nr_sectors, 0);
2972 if (!attempt_front_merge(q, req)) 2973 if (!attempt_front_merge(q, req))
2973 elv_merged_request(q, req); 2974 elv_merged_request(q, req, el_ret);
2974 goto out; 2975 goto out;
2975 2976
2976 /* ELV_NO_MERGE: elevator says don't/can't merge. */ 2977 /* ELV_NO_MERGE: elevator says don't/can't merge. */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 8f5486964671..a905c4934a55 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -230,6 +230,7 @@ struct request {
230 struct bio *biotail; 230 struct bio *biotail;
231 231
232 struct hlist_node hash; /* merge hash */ 232 struct hlist_node hash; /* merge hash */
233 struct rb_node rb_node; /* sort/lookup */
233 234
234 void *elevator_private; 235 void *elevator_private;
235 void *completion_data; 236 void *completion_data;
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 2c270e90b33e..95b2a04b969c 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -6,7 +6,7 @@ typedef int (elevator_merge_fn) (request_queue_t *, struct request **,
6 6
7typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *); 7typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *);
8 8
9typedef void (elevator_merged_fn) (request_queue_t *, struct request *); 9typedef void (elevator_merged_fn) (request_queue_t *, struct request *, int);
10 10
11typedef int (elevator_dispatch_fn) (request_queue_t *, int); 11typedef int (elevator_dispatch_fn) (request_queue_t *, int);
12 12
@@ -96,7 +96,7 @@ extern void elv_insert(request_queue_t *, struct request *, int);
96extern int elv_merge(request_queue_t *, struct request **, struct bio *); 96extern int elv_merge(request_queue_t *, struct request **, struct bio *);
97extern void elv_merge_requests(request_queue_t *, struct request *, 97extern void elv_merge_requests(request_queue_t *, struct request *,
98 struct request *); 98 struct request *);
99extern void elv_merged_request(request_queue_t *, struct request *); 99extern void elv_merged_request(request_queue_t *, struct request *, int);
100extern void elv_dequeue_request(request_queue_t *, struct request *); 100extern void elv_dequeue_request(request_queue_t *, struct request *);
101extern void elv_requeue_request(request_queue_t *, struct request *); 101extern void elv_requeue_request(request_queue_t *, struct request *);
102extern int elv_queue_empty(request_queue_t *); 102extern int elv_queue_empty(request_queue_t *);
@@ -127,6 +127,19 @@ extern void elevator_exit(elevator_t *);
127extern int elv_rq_merge_ok(struct request *, struct bio *); 127extern int elv_rq_merge_ok(struct request *, struct bio *);
128 128
129/* 129/*
130 * Helper functions.
131 */
132extern struct request *elv_rb_former_request(request_queue_t *, struct request *);
133extern struct request *elv_rb_latter_request(request_queue_t *, struct request *);
134
135/*
136 * rb support functions.
137 */
138extern struct request *elv_rb_add(struct rb_root *, struct request *);
139extern void elv_rb_del(struct rb_root *, struct request *);
140extern struct request *elv_rb_find(struct rb_root *, sector_t);
141
142/*
130 * Return values from elevator merger 143 * Return values from elevator merger
131 */ 144 */
132#define ELEVATOR_NO_MERGE 0 145#define ELEVATOR_NO_MERGE 0
@@ -151,5 +164,6 @@ enum {
151}; 164};
152 165
153#define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors) 166#define rq_end_sector(rq) ((rq)->sector + (rq)->nr_sectors)
167#define rb_entry_rq(node) rb_entry((node), struct request, rb_node)
154 168
155#endif 169#endif