aboutsummaryrefslogtreecommitdiffstats
path: root/block/deadline-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/deadline-iosched.c')
-rw-r--r--block/deadline-iosched.c128
1 files changed, 2 insertions, 126 deletions
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index c7ca9f0b6498..b66e820f544d 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -12,7 +12,6 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/compiler.h> 14#include <linux/compiler.h>
15#include <linux/hash.h>
16#include <linux/rbtree.h> 15#include <linux/rbtree.h>
17 16
18/* 17/*
@@ -24,13 +23,6 @@ static const int writes_starved = 2; /* max times reads can starve a write */
24static const int fifo_batch = 16; /* # of sequential requests treated as one 23static const int fifo_batch = 16; /* # of sequential requests treated as one
25 by the above parameters. For throughput. */ 24 by the above parameters. For throughput. */
26 25
27static const int deadline_hash_shift = 5;
28#define DL_HASH_BLOCK(sec) ((sec) >> 3)
29#define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift))
30#define DL_HASH_ENTRIES (1 << deadline_hash_shift)
31#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors)
32#define ON_HASH(drq) (!hlist_unhashed(&(drq)->hash))
33
34struct deadline_data { 26struct deadline_data {
35 /* 27 /*
36 * run time data 28 * run time data
@@ -46,7 +38,6 @@ struct deadline_data {
46 * next in sort order. read, write or both are NULL 38 * next in sort order. read, write or both are NULL
47 */ 39 */
48 struct deadline_rq *next_drq[2]; 40 struct deadline_rq *next_drq[2];
49 struct hlist_head *hash; /* request hash */
50 unsigned int batching; /* number of sequential requests made */ 41 unsigned int batching; /* number of sequential requests made */
51 sector_t last_sector; /* head position */ 42 sector_t last_sector; /* head position */
52 unsigned int starved; /* times reads have starved writes */ 43 unsigned int starved; /* times reads have starved writes */
@@ -75,11 +66,6 @@ struct deadline_rq {
75 struct request *request; 66 struct request *request;
76 67
77 /* 68 /*
78 * request hash, key is the ending offset (for back merge lookup)
79 */
80 struct hlist_node hash;
81
82 /*
83 * expire fifo 69 * expire fifo
84 */ 70 */
85 struct list_head fifo; 71 struct list_head fifo;
@@ -93,69 +79,6 @@ static kmem_cache_t *drq_pool;
93#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) 79#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private)
94 80
95/* 81/*
96 * the back merge hash support functions
97 */
98static inline void __deadline_del_drq_hash(struct deadline_rq *drq)
99{
100 hlist_del_init(&drq->hash);
101}
102
103static inline void deadline_del_drq_hash(struct deadline_rq *drq)
104{
105 if (ON_HASH(drq))
106 __deadline_del_drq_hash(drq);
107}
108
109static inline void
110deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
111{
112 struct request *rq = drq->request;
113
114 BUG_ON(ON_HASH(drq));
115
116 hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]);
117}
118
119/*
120 * move hot entry to front of chain
121 */
122static inline void
123deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
124{
125 struct request *rq = drq->request;
126 struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))];
127
128 if (ON_HASH(drq) && &drq->hash != head->first) {
129 hlist_del(&drq->hash);
130 hlist_add_head(&drq->hash, head);
131 }
132}
133
134static struct request *
135deadline_find_drq_hash(struct deadline_data *dd, sector_t offset)
136{
137 struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)];
138 struct hlist_node *entry, *next;
139 struct deadline_rq *drq;
140
141 hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) {
142 struct request *__rq = drq->request;
143
144 BUG_ON(!ON_HASH(drq));
145
146 if (!rq_mergeable(__rq)) {
147 __deadline_del_drq_hash(drq);
148 continue;
149 }
150
151 if (rq_hash_key(__rq) == offset)
152 return __rq;
153 }
154
155 return NULL;
156}
157
158/*
159 * rb tree support functions 82 * rb tree support functions
160 */ 83 */
161#define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) 84#define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node)
@@ -267,22 +190,19 @@ deadline_add_request(struct request_queue *q, struct request *rq)
267{ 190{
268 struct deadline_data *dd = q->elevator->elevator_data; 191 struct deadline_data *dd = q->elevator->elevator_data;
269 struct deadline_rq *drq = RQ_DATA(rq); 192 struct deadline_rq *drq = RQ_DATA(rq);
270
271 const int data_dir = rq_data_dir(drq->request); 193 const int data_dir = rq_data_dir(drq->request);
272 194
273 deadline_add_drq_rb(dd, drq); 195 deadline_add_drq_rb(dd, drq);
196
274 /* 197 /*
275 * set expire time (only used for reads) and add to fifo list 198 * set expire time (only used for reads) and add to fifo list
276 */ 199 */
277 drq->expires = jiffies + dd->fifo_expire[data_dir]; 200 drq->expires = jiffies + dd->fifo_expire[data_dir];
278 list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); 201 list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
279
280 if (rq_mergeable(rq))
281 deadline_add_drq_hash(dd, drq);
282} 202}
283 203
284/* 204/*
285 * remove rq from rbtree, fifo, and hash 205 * remove rq from rbtree and fifo.
286 */ 206 */
287static void deadline_remove_request(request_queue_t *q, struct request *rq) 207static void deadline_remove_request(request_queue_t *q, struct request *rq)
288{ 208{
@@ -291,7 +211,6 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq)
291 211
292 list_del_init(&drq->fifo); 212 list_del_init(&drq->fifo);
293 deadline_del_drq_rb(dd, drq); 213 deadline_del_drq_rb(dd, drq);
294 deadline_del_drq_hash(drq);
295} 214}
296 215
297static int 216static int
@@ -302,19 +221,6 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
302 int ret; 221 int ret;
303 222
304 /* 223 /*
305 * see if the merge hash can satisfy a back merge
306 */
307 __rq = deadline_find_drq_hash(dd, bio->bi_sector);
308 if (__rq) {
309 BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
310
311 if (elv_rq_merge_ok(__rq, bio)) {
312 ret = ELEVATOR_BACK_MERGE;
313 goto out;
314 }
315 }
316
317 /*
318 * check for front merge 224 * check for front merge
319 */ 225 */
320 if (dd->front_merges) { 226 if (dd->front_merges) {
@@ -333,8 +239,6 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
333 239
334 return ELEVATOR_NO_MERGE; 240 return ELEVATOR_NO_MERGE;
335out: 241out:
336 if (ret)
337 deadline_hot_drq_hash(dd, RQ_DATA(__rq));
338 *req = __rq; 242 *req = __rq;
339 return ret; 243 return ret;
340} 244}
@@ -345,12 +249,6 @@ static void deadline_merged_request(request_queue_t *q, struct request *req)
345 struct deadline_rq *drq = RQ_DATA(req); 249 struct deadline_rq *drq = RQ_DATA(req);
346 250
347 /* 251 /*
348 * hash always needs to be repositioned, key is end sector
349 */
350 deadline_del_drq_hash(drq);
351 deadline_add_drq_hash(dd, drq);
352
353 /*
354 * if the merge was a front merge, we need to reposition request 252 * if the merge was a front merge, we need to reposition request
355 */ 253 */
356 if (rq_rb_key(req) != drq->rb_key) { 254 if (rq_rb_key(req) != drq->rb_key) {
@@ -370,13 +268,6 @@ deadline_merged_requests(request_queue_t *q, struct request *req,
370 BUG_ON(!drq); 268 BUG_ON(!drq);
371 BUG_ON(!dnext); 269 BUG_ON(!dnext);
372 270
373 /*
374 * reposition drq (this is the merged request) in hash, and in rbtree
375 * in case of a front merge
376 */
377 deadline_del_drq_hash(drq);
378 deadline_add_drq_hash(dd, drq);
379
380 if (rq_rb_key(req) != drq->rb_key) { 271 if (rq_rb_key(req) != drq->rb_key) {
381 deadline_del_drq_rb(dd, drq); 272 deadline_del_drq_rb(dd, drq);
382 deadline_add_drq_rb(dd, drq); 273 deadline_add_drq_rb(dd, drq);
@@ -594,7 +485,6 @@ static void deadline_exit_queue(elevator_t *e)
594 BUG_ON(!list_empty(&dd->fifo_list[WRITE])); 485 BUG_ON(!list_empty(&dd->fifo_list[WRITE]));
595 486
596 mempool_destroy(dd->drq_pool); 487 mempool_destroy(dd->drq_pool);
597 kfree(dd->hash);
598 kfree(dd); 488 kfree(dd);
599} 489}
600 490
@@ -605,7 +495,6 @@ static void deadline_exit_queue(elevator_t *e)
605static void *deadline_init_queue(request_queue_t *q, elevator_t *e) 495static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
606{ 496{
607 struct deadline_data *dd; 497 struct deadline_data *dd;
608 int i;
609 498
610 if (!drq_pool) 499 if (!drq_pool)
611 return NULL; 500 return NULL;
@@ -615,24 +504,13 @@ static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
615 return NULL; 504 return NULL;
616 memset(dd, 0, sizeof(*dd)); 505 memset(dd, 0, sizeof(*dd));
617 506
618 dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES,
619 GFP_KERNEL, q->node);
620 if (!dd->hash) {
621 kfree(dd);
622 return NULL;
623 }
624
625 dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab, 507 dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
626 mempool_free_slab, drq_pool, q->node); 508 mempool_free_slab, drq_pool, q->node);
627 if (!dd->drq_pool) { 509 if (!dd->drq_pool) {
628 kfree(dd->hash);
629 kfree(dd); 510 kfree(dd);
630 return NULL; 511 return NULL;
631 } 512 }
632 513
633 for (i = 0; i < DL_HASH_ENTRIES; i++)
634 INIT_HLIST_HEAD(&dd->hash[i]);
635
636 INIT_LIST_HEAD(&dd->fifo_list[READ]); 514 INIT_LIST_HEAD(&dd->fifo_list[READ]);
637 INIT_LIST_HEAD(&dd->fifo_list[WRITE]); 515 INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
638 dd->sort_list[READ] = RB_ROOT; 516 dd->sort_list[READ] = RB_ROOT;
@@ -667,8 +545,6 @@ deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
667 RB_CLEAR_NODE(&drq->rb_node); 545 RB_CLEAR_NODE(&drq->rb_node);
668 drq->request = rq; 546 drq->request = rq;
669 547
670 INIT_HLIST_NODE(&drq->hash);
671
672 INIT_LIST_HEAD(&drq->fifo); 548 INIT_LIST_HEAD(&drq->fifo);
673 549
674 rq->elevator_private = drq; 550 rq->elevator_private = drq;