Blame view
block/elevator.c
24.4 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 |
* Block device elevator/IO-scheduler. * * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE * |
0fe234795 [PATCH] Update ax... |
6 |
* 30042000 Jens Axboe <axboe@kernel.dk> : |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
* * Split the elevator a bit so that it is possible to choose a different * one or even write a new "plug in". There are three pieces: * - elevator_fn, inserts a new request in the queue list * - elevator_merge_fn, decides whether a new buffer can be merged with * an existing request * - elevator_dequeue_fn, called when a request is taken off the active list * * 20082000 Dave Jones <davej@suse.de> : * Removed tests for max-bomb-segments, which was breaking elvtune * when run without -bN * * Jens: * - Rework again to work with bio instead of buffer_heads * - loose bi_dev comparisons, partition handling is right now * - completely modularize elevator setup and teardown * */ #include <linux/kernel.h> #include <linux/fs.h> #include <linux/blkdev.h> #include <linux/elevator.h> #include <linux/bio.h> |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 |
#include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/compiler.h> |
cb98fc8bb [BLOCK] Reimpleme... |
34 |
#include <linux/delay.h> |
2056a782f [PATCH] Block que... |
35 |
#include <linux/blktrace_api.h> |
9817064b6 [PATCH] elevator:... |
36 |
#include <linux/hash.h> |
0835da67c block: use linux/... |
37 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
55782138e tracing/events: c... |
39 |
#include <trace/events/block.h> |
242f9dcb8 block: unify requ... |
40 |
#include "blk.h" |
1da177e4c Linux-2.6.12-rc2 |
41 42 43 44 |
static DEFINE_SPINLOCK(elv_list_lock); static LIST_HEAD(elv_list); /* |
9817064b6 [PATCH] elevator:... |
45 46 47 48 |
* Merge hash stuff. */ static const int elv_hash_shift = 6; #define ELV_HASH_BLOCK(sec) ((sec) >> 3) |
4eb166d98 block: make eleva... |
49 50 |
#define ELV_HASH_FN(sec) \ (hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift)) |
9817064b6 [PATCH] elevator:... |
51 |
#define ELV_HASH_ENTRIES (1 << elv_hash_shift) |
83096ebf1 block: convert to... |
52 |
#define rq_hash_key(rq) (blk_rq_pos(rq) + blk_rq_sectors(rq)) |
9817064b6 [PATCH] elevator:... |
53 54 |
/* |
da7752650 [PATCH] cfq-iosch... |
55 56 57 58 59 |
* Query io scheduler to see if the current process issuing bio may be * merged with rq. */ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) { |
165125e1e [BLOCK] Get rid o... |
60 |
struct request_queue *q = rq->q; |
b374d18a4 block: get rid of... |
61 |
struct elevator_queue *e = q->elevator; |
da7752650 [PATCH] cfq-iosch... |
62 63 64 65 66 67 68 69 |
if (e->ops->elevator_allow_merge_fn) return e->ops->elevator_allow_merge_fn(q, rq, bio); return 1; } /* |
1da177e4c Linux-2.6.12-rc2 |
70 71 |
* can we safely merge with this request? */ |
72ed0bf60 block/elevator.c:... |
72 |
int elv_rq_merge_ok(struct request *rq, struct bio *bio) |
1da177e4c Linux-2.6.12-rc2 |
73 74 75 76 77 |
{ if (!rq_mergeable(rq)) return 0; /* |
e17fc0a1c Allow elevators t... |
78 79 |
* Don't merge file system requests and discard requests */ |
7b6d91dae block: unify flag... |
80 |
if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) |
e17fc0a1c Allow elevators t... |
81 82 83 |
return 0; /* |
8d57a98cc block: add secure... |
84 85 86 87 88 89 |
* Don't merge discard requests and secure discard requests */ if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) return 0; /* |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 95 |
* different data direction or already started, don't merge */ if (bio_data_dir(bio) != rq_data_dir(rq)) return 0; /* |
da7752650 [PATCH] cfq-iosch... |
96 |
* must be same device and not a special request |
1da177e4c Linux-2.6.12-rc2 |
97 |
*/ |
bb4067e34 [PATCH] elevator:... |
98 |
if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) |
da7752650 [PATCH] cfq-iosch... |
99 |
return 0; |
7ba1ba12e block: Block laye... |
100 101 102 103 104 |
/* * only merge integrity protected bio into ditto rq */ if (bio_integrity(bio) != blk_integrity_rq(rq)) return 0; |
da7752650 [PATCH] cfq-iosch... |
105 106 |
if (!elv_iosched_allow_merge(rq, bio)) return 0; |
1da177e4c Linux-2.6.12-rc2 |
107 |
|
da7752650 [PATCH] cfq-iosch... |
108 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
109 110 |
} EXPORT_SYMBOL(elv_rq_merge_ok); |
73c101011 block: initial pa... |
111 |
int elv_try_merge(struct request *__rq, struct bio *bio) |
1da177e4c Linux-2.6.12-rc2 |
112 113 114 115 116 117 118 |
{ int ret = ELEVATOR_NO_MERGE; /* * we can merge and sequence is ok, check if it's possible */ if (elv_rq_merge_ok(__rq, bio)) { |
83096ebf1 block: convert to... |
119 |
if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector) |
1da177e4c Linux-2.6.12-rc2 |
120 |
ret = ELEVATOR_BACK_MERGE; |
83096ebf1 block: convert to... |
121 |
else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector) |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 |
ret = ELEVATOR_FRONT_MERGE; } return ret; } |
1da177e4c Linux-2.6.12-rc2 |
127 |
|
1da177e4c Linux-2.6.12-rc2 |
128 129 |
static struct elevator_type *elevator_find(const char *name) { |
a22b169df [PATCH] block lay... |
130 |
struct elevator_type *e; |
1da177e4c Linux-2.6.12-rc2 |
131 |
|
70cee26e0 Use list_for_each... |
132 |
list_for_each_entry(e, &elv_list, list) { |
a22b169df [PATCH] block lay... |
133 134 |
if (!strcmp(e->elevator_name, name)) return e; |
1da177e4c Linux-2.6.12-rc2 |
135 |
} |
1da177e4c Linux-2.6.12-rc2 |
136 |
|
a22b169df [PATCH] block lay... |
137 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
138 139 140 141 142 143 144 145 146 |
} static void elevator_put(struct elevator_type *e) { module_put(e->elevator_owner); } static struct elevator_type *elevator_get(const char *name) { |
2824bc932 [PATCH] fix try_m... |
147 |
struct elevator_type *e; |
1da177e4c Linux-2.6.12-rc2 |
148 |
|
2a12dcd71 [PATCH] elevator:... |
149 |
spin_lock(&elv_list_lock); |
2824bc932 [PATCH] fix try_m... |
150 151 |
e = elevator_find(name); |
e16409496 elevator: make el... |
152 |
if (!e) { |
e16409496 elevator: make el... |
153 |
spin_unlock(&elv_list_lock); |
490b94be0 iosched: remove r... |
154 |
request_module("%s-iosched", name); |
e16409496 elevator: make el... |
155 156 157 |
spin_lock(&elv_list_lock); e = elevator_find(name); } |
2824bc932 [PATCH] fix try_m... |
158 159 |
if (e && !try_module_get(e->elevator_owner)) e = NULL; |
2a12dcd71 [PATCH] elevator:... |
160 |
spin_unlock(&elv_list_lock); |
1da177e4c Linux-2.6.12-rc2 |
161 162 163 |
return e; } |
165125e1e [BLOCK] Get rid o... |
164 165 |
static void *elevator_init_queue(struct request_queue *q, struct elevator_queue *eq) |
1da177e4c Linux-2.6.12-rc2 |
166 |
{ |
bb37b94c6 [BLOCK] Cleanup u... |
167 |
return eq->ops->elevator_init_fn(q); |
bc1c11697 [PATCH] elevator ... |
168 |
} |
1da177e4c Linux-2.6.12-rc2 |
169 |
|
165125e1e [BLOCK] Get rid o... |
170 |
static void elevator_attach(struct request_queue *q, struct elevator_queue *eq, |
bc1c11697 [PATCH] elevator ... |
171 172 |
void *data) { |
1da177e4c Linux-2.6.12-rc2 |
173 |
q->elevator = eq; |
bc1c11697 [PATCH] elevator ... |
174 |
eq->elevator_data = data; |
1da177e4c Linux-2.6.12-rc2 |
175 176 177 |
} static char chosen_elevator[16]; |
5f0039764 [BLOCK] elevator:... |
178 |
static int __init elevator_setup(char *str) |
1da177e4c Linux-2.6.12-rc2 |
179 |
{ |
752a3b796 [BLOCK] elevator:... |
180 181 182 183 |
/* * Be backwards-compatible with previous kernels, so users * won't get the wrong elevator. */ |
492af6350 block: remove the... |
184 |
strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); |
9b41046cd [PATCH] Don't pas... |
185 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
186 187 188 |
} __setup("elevator=", elevator_setup); |
3d1ab40f4 [PATCH] elevator_... |
189 |
static struct kobj_type elv_ktype; |
b374d18a4 block: get rid of... |
190 |
static struct elevator_queue *elevator_alloc(struct request_queue *q, |
165125e1e [BLOCK] Get rid o... |
191 |
struct elevator_type *e) |
3d1ab40f4 [PATCH] elevator_... |
192 |
{ |
b374d18a4 block: get rid of... |
193 |
struct elevator_queue *eq; |
9817064b6 [PATCH] elevator:... |
194 |
int i; |
b374d18a4 block: get rid of... |
195 |
eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node); |
9817064b6 [PATCH] elevator:... |
196 197 |
if (unlikely(!eq)) goto err; |
9817064b6 [PATCH] elevator:... |
198 199 |
eq->ops = &e->ops; eq->elevator_type = e; |
f9cb074bf Kobject: rename k... |
200 |
kobject_init(&eq->kobj, &elv_ktype); |
9817064b6 [PATCH] elevator:... |
201 |
mutex_init(&eq->sysfs_lock); |
b5deef901 [PATCH] Make sure... |
202 203 |
eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES, GFP_KERNEL, q->node); |
9817064b6 [PATCH] elevator:... |
204 205 206 207 208 |
if (!eq->hash) goto err; for (i = 0; i < ELV_HASH_ENTRIES; i++) INIT_HLIST_HEAD(&eq->hash[i]); |
3d1ab40f4 [PATCH] elevator_... |
209 |
return eq; |
9817064b6 [PATCH] elevator:... |
210 211 212 213 |
err: kfree(eq); elevator_put(e); return NULL; |
3d1ab40f4 [PATCH] elevator_... |
214 215 216 217 |
} static void elevator_release(struct kobject *kobj) { |
b374d18a4 block: get rid of... |
218 |
struct elevator_queue *e; |
9817064b6 [PATCH] elevator:... |
219 |
|
b374d18a4 block: get rid of... |
220 |
e = container_of(kobj, struct elevator_queue, kobj); |
3d1ab40f4 [PATCH] elevator_... |
221 |
elevator_put(e->elevator_type); |
9817064b6 [PATCH] elevator:... |
222 |
kfree(e->hash); |
3d1ab40f4 [PATCH] elevator_... |
223 224 |
kfree(e); } |
165125e1e [BLOCK] Get rid o... |
225 |
int elevator_init(struct request_queue *q, char *name) |
1da177e4c Linux-2.6.12-rc2 |
226 227 228 |
{ struct elevator_type *e = NULL; struct elevator_queue *eq; |
bc1c11697 [PATCH] elevator ... |
229 |
void *data; |
1da177e4c Linux-2.6.12-rc2 |
230 |
|
1abec4fdb block: make blk_i... |
231 232 |
if (unlikely(q->elevator)) return 0; |
cb98fc8bb [BLOCK] Reimpleme... |
233 234 235 236 |
INIT_LIST_HEAD(&q->queue_head); q->last_merge = NULL; q->end_sector = 0; q->boundary_rq = NULL; |
cb98fc8bb [BLOCK] Reimpleme... |
237 |
|
4eb166d98 block: make eleva... |
238 239 240 241 242 |
if (name) { e = elevator_get(name); if (!e) return -EINVAL; } |
1da177e4c Linux-2.6.12-rc2 |
243 |
|
4eb166d98 block: make eleva... |
244 245 246 247 248 249 250 |
if (!e && *chosen_elevator) { e = elevator_get(chosen_elevator); if (!e) printk(KERN_ERR "I/O scheduler %s not found ", chosen_elevator); } |
248d5ca5e [BLOCK] elevator:... |
251 |
|
4eb166d98 block: make eleva... |
252 253 254 255 256 257 258 259 260 |
if (!e) { e = elevator_get(CONFIG_DEFAULT_IOSCHED); if (!e) { printk(KERN_ERR "Default I/O scheduler not found. " \ "Using noop. "); e = elevator_get("noop"); } |
5f0039764 [BLOCK] elevator:... |
261 |
} |
b5deef901 [PATCH] Make sure... |
262 |
eq = elevator_alloc(q, e); |
3d1ab40f4 [PATCH] elevator_... |
263 |
if (!eq) |
1da177e4c Linux-2.6.12-rc2 |
264 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
265 |
|
bc1c11697 [PATCH] elevator ... |
266 267 |
data = elevator_init_queue(q, eq); if (!data) { |
3d1ab40f4 [PATCH] elevator_... |
268 |
kobject_put(&eq->kobj); |
bc1c11697 [PATCH] elevator ... |
269 270 |
return -ENOMEM; } |
1da177e4c Linux-2.6.12-rc2 |
271 |
|
bc1c11697 [PATCH] elevator ... |
272 |
elevator_attach(q, eq, data); |
1abec4fdb block: make blk_i... |
273 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
274 |
} |
2e662b65f [PATCH] elevator:... |
275 |
EXPORT_SYMBOL(elevator_init); |
b374d18a4 block: get rid of... |
276 |
void elevator_exit(struct elevator_queue *e) |
1da177e4c Linux-2.6.12-rc2 |
277 |
{ |
3d1ab40f4 [PATCH] elevator_... |
278 |
mutex_lock(&e->sysfs_lock); |
1da177e4c Linux-2.6.12-rc2 |
279 280 |
if (e->ops->elevator_exit_fn) e->ops->elevator_exit_fn(e); |
3d1ab40f4 [PATCH] elevator_... |
281 282 |
e->ops = NULL; mutex_unlock(&e->sysfs_lock); |
1da177e4c Linux-2.6.12-rc2 |
283 |
|
3d1ab40f4 [PATCH] elevator_... |
284 |
kobject_put(&e->kobj); |
1da177e4c Linux-2.6.12-rc2 |
285 |
} |
2e662b65f [PATCH] elevator:... |
286 |
EXPORT_SYMBOL(elevator_exit); |
9817064b6 [PATCH] elevator:... |
287 288 289 290 |
static inline void __elv_rqhash_del(struct request *rq) { hlist_del_init(&rq->hash); } |
165125e1e [BLOCK] Get rid o... |
291 |
static void elv_rqhash_del(struct request_queue *q, struct request *rq) |
9817064b6 [PATCH] elevator:... |
292 293 294 295 |
{ if (ELV_ON_HASH(rq)) __elv_rqhash_del(rq); } |
165125e1e [BLOCK] Get rid o... |
296 |
static void elv_rqhash_add(struct request_queue *q, struct request *rq) |
9817064b6 [PATCH] elevator:... |
297 |
{ |
b374d18a4 block: get rid of... |
298 |
struct elevator_queue *e = q->elevator; |
9817064b6 [PATCH] elevator:... |
299 300 301 302 |
BUG_ON(ELV_ON_HASH(rq)); hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]); } |
165125e1e [BLOCK] Get rid o... |
303 |
static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) |
9817064b6 [PATCH] elevator:... |
304 305 306 307 |
{ __elv_rqhash_del(rq); elv_rqhash_add(q, rq); } |
165125e1e [BLOCK] Get rid o... |
308 |
static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset) |
9817064b6 [PATCH] elevator:... |
309 |
{ |
b374d18a4 block: get rid of... |
310 |
struct elevator_queue *e = q->elevator; |
9817064b6 [PATCH] elevator:... |
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)]; struct hlist_node *entry, *next; struct request *rq; hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) { BUG_ON(!ELV_ON_HASH(rq)); if (unlikely(!rq_mergeable(rq))) { __elv_rqhash_del(rq); continue; } if (rq_hash_key(rq) == offset) return rq; } return NULL; } |
8922e16cf [PATCH] 01/05 Imp... |
329 |
/* |
2e662b65f [PATCH] elevator:... |
330 331 332 |
* RB-tree support functions for inserting/lookup/removal of requests * in a sorted RB tree. */ |
796d5116c iosched: prevent ... |
333 |
void elv_rb_add(struct rb_root *root, struct request *rq) |
2e662b65f [PATCH] elevator:... |
334 335 336 337 338 339 340 341 |
{ struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct request *__rq; while (*p) { parent = *p; __rq = rb_entry(parent, struct request, rb_node); |
83096ebf1 block: convert to... |
342 |
if (blk_rq_pos(rq) < blk_rq_pos(__rq)) |
2e662b65f [PATCH] elevator:... |
343 |
p = &(*p)->rb_left; |
796d5116c iosched: prevent ... |
344 |
else if (blk_rq_pos(rq) >= blk_rq_pos(__rq)) |
2e662b65f [PATCH] elevator:... |
345 |
p = &(*p)->rb_right; |
2e662b65f [PATCH] elevator:... |
346 347 348 349 |
} rb_link_node(&rq->rb_node, parent, p); rb_insert_color(&rq->rb_node, root); |
2e662b65f [PATCH] elevator:... |
350 |
} |
2e662b65f [PATCH] elevator:... |
351 352 353 354 355 356 357 358 |
EXPORT_SYMBOL(elv_rb_add); void elv_rb_del(struct rb_root *root, struct request *rq) { BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); rb_erase(&rq->rb_node, root); RB_CLEAR_NODE(&rq->rb_node); } |
2e662b65f [PATCH] elevator:... |
359 360 361 362 363 364 365 366 367 |
EXPORT_SYMBOL(elv_rb_del); struct request *elv_rb_find(struct rb_root *root, sector_t sector) { struct rb_node *n = root->rb_node; struct request *rq; while (n) { rq = rb_entry(n, struct request, rb_node); |
83096ebf1 block: convert to... |
368 |
if (sector < blk_rq_pos(rq)) |
2e662b65f [PATCH] elevator:... |
369 |
n = n->rb_left; |
83096ebf1 block: convert to... |
370 |
else if (sector > blk_rq_pos(rq)) |
2e662b65f [PATCH] elevator:... |
371 372 373 374 375 376 377 |
n = n->rb_right; else return rq; } return NULL; } |
2e662b65f [PATCH] elevator:... |
378 379 380 |
EXPORT_SYMBOL(elv_rb_find); /* |
8922e16cf [PATCH] 01/05 Imp... |
381 |
* Insert rq into dispatch queue of q. Queue lock must be held on |
dbe7f76dd fix typo "insted"... |
382 |
* entry. rq is sort instead into the dispatch queue. To be used by |
2e662b65f [PATCH] elevator:... |
383 |
* specific elevators. |
8922e16cf [PATCH] 01/05 Imp... |
384 |
*/ |
165125e1e [BLOCK] Get rid o... |
385 |
void elv_dispatch_sort(struct request_queue *q, struct request *rq) |
8922e16cf [PATCH] 01/05 Imp... |
386 387 |
{ sector_t boundary; |
8922e16cf [PATCH] 01/05 Imp... |
388 |
struct list_head *entry; |
4eb166d98 block: make eleva... |
389 |
int stop_flags; |
8922e16cf [PATCH] 01/05 Imp... |
390 |
|
06b86245c [PATCH] 03/05 mov... |
391 392 |
if (q->last_merge == rq) q->last_merge = NULL; |
9817064b6 [PATCH] elevator:... |
393 394 |
elv_rqhash_del(q, rq); |
15853af9f [BLOCK] Implement... |
395 |
q->nr_sorted--; |
06b86245c [PATCH] 03/05 mov... |
396 |
|
1b47f531e [PATCH] generic d... |
397 |
boundary = q->end_sector; |
02e031cbc block: remove REQ... |
398 |
stop_flags = REQ_SOFTBARRIER | REQ_STARTED; |
8922e16cf [PATCH] 01/05 Imp... |
399 400 |
list_for_each_prev(entry, &q->queue_head) { struct request *pos = list_entry_rq(entry); |
33659ebba block: remove wra... |
401 402 |
if ((rq->cmd_flags & REQ_DISCARD) != (pos->cmd_flags & REQ_DISCARD)) |
e17fc0a1c Allow elevators t... |
403 |
break; |
783660b2f elevator: don't s... |
404 405 |
if (rq_data_dir(rq) != rq_data_dir(pos)) break; |
4eb166d98 block: make eleva... |
406 |
if (pos->cmd_flags & stop_flags) |
8922e16cf [PATCH] 01/05 Imp... |
407 |
break; |
83096ebf1 block: convert to... |
408 409 |
if (blk_rq_pos(rq) >= boundary) { if (blk_rq_pos(pos) < boundary) |
8922e16cf [PATCH] 01/05 Imp... |
410 411 |
continue; } else { |
83096ebf1 block: convert to... |
412 |
if (blk_rq_pos(pos) >= boundary) |
8922e16cf [PATCH] 01/05 Imp... |
413 414 |
break; } |
83096ebf1 block: convert to... |
415 |
if (blk_rq_pos(rq) >= blk_rq_pos(pos)) |
8922e16cf [PATCH] 01/05 Imp... |
416 417 418 419 420 |
break; } list_add(&rq->queuelist, entry); } |
2e662b65f [PATCH] elevator:... |
421 |
EXPORT_SYMBOL(elv_dispatch_sort); |
9817064b6 [PATCH] elevator:... |
422 |
/* |
2e662b65f [PATCH] elevator:... |
423 424 425 |
* Insert rq into dispatch queue of q. Queue lock must be held on * entry. rq is added to the back of the dispatch queue. To be used by * specific elevators. |
9817064b6 [PATCH] elevator:... |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
*/ void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) { if (q->last_merge == rq) q->last_merge = NULL; elv_rqhash_del(q, rq); q->nr_sorted--; q->end_sector = rq_end_sector(rq); q->boundary_rq = rq; list_add_tail(&rq->queuelist, &q->queue_head); } |
2e662b65f [PATCH] elevator:... |
440 |
EXPORT_SYMBOL(elv_dispatch_add_tail); |
165125e1e [BLOCK] Get rid o... |
441 |
int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) |
1da177e4c Linux-2.6.12-rc2 |
442 |
{ |
b374d18a4 block: get rid of... |
443 |
struct elevator_queue *e = q->elevator; |
9817064b6 [PATCH] elevator:... |
444 |
struct request *__rq; |
06b86245c [PATCH] 03/05 mov... |
445 |
int ret; |
9817064b6 [PATCH] elevator:... |
446 |
/* |
488991e28 block: Added in s... |
447 448 449 450 451 452 453 454 455 |
* Levels of merges: * nomerges: No merges at all attempted * noxmerges: Only simple one-hit cache try * merges: All merge tries attempted */ if (blk_queue_nomerges(q)) return ELEVATOR_NO_MERGE; /* |
9817064b6 [PATCH] elevator:... |
456 457 |
* First try one-hit cache. */ |
06b86245c [PATCH] 03/05 mov... |
458 459 460 461 462 463 464 |
if (q->last_merge) { ret = elv_try_merge(q->last_merge, bio); if (ret != ELEVATOR_NO_MERGE) { *req = q->last_merge; return ret; } } |
1da177e4c Linux-2.6.12-rc2 |
465 |
|
488991e28 block: Added in s... |
466 |
if (blk_queue_noxmerges(q)) |
ac9fafa12 block: Skip I/O m... |
467 |
return ELEVATOR_NO_MERGE; |
9817064b6 [PATCH] elevator:... |
468 469 470 471 472 473 474 475 |
/* * See if our hash lookup can find a potential backmerge. */ __rq = elv_rqhash_find(q, bio->bi_sector); if (__rq && elv_rq_merge_ok(__rq, bio)) { *req = __rq; return ELEVATOR_BACK_MERGE; } |
1da177e4c Linux-2.6.12-rc2 |
476 477 478 479 480 |
if (e->ops->elevator_merge_fn) return e->ops->elevator_merge_fn(q, req, bio); return ELEVATOR_NO_MERGE; } |
5e84ea3a9 block: attempt to... |
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
/* * Attempt to do an insertion back merge. Only check for the case where * we can append 'rq' to an existing request, so we can throw 'rq' away * afterwards. * * Returns true if we merged, false otherwise */ static bool elv_attempt_insert_merge(struct request_queue *q, struct request *rq) { struct request *__rq; if (blk_queue_nomerges(q)) return false; /* * First try one-hit cache. */ if (q->last_merge && blk_attempt_req_merge(q, q->last_merge, rq)) return true; if (blk_queue_noxmerges(q)) return false; /* * See if our hash lookup can find a potential backmerge. */ __rq = elv_rqhash_find(q, blk_rq_pos(rq)); if (__rq && blk_attempt_req_merge(q, __rq, rq)) return true; return false; } |
165125e1e [BLOCK] Get rid o... |
514 |
void elv_merged_request(struct request_queue *q, struct request *rq, int type) |
1da177e4c Linux-2.6.12-rc2 |
515 |
{ |
b374d18a4 block: get rid of... |
516 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
517 518 |
if (e->ops->elevator_merged_fn) |
2e662b65f [PATCH] elevator:... |
519 |
e->ops->elevator_merged_fn(q, rq, type); |
06b86245c [PATCH] 03/05 mov... |
520 |
|
2e662b65f [PATCH] elevator:... |
521 522 |
if (type == ELEVATOR_BACK_MERGE) elv_rqhash_reposition(q, rq); |
9817064b6 [PATCH] elevator:... |
523 |
|
06b86245c [PATCH] 03/05 mov... |
524 |
q->last_merge = rq; |
1da177e4c Linux-2.6.12-rc2 |
525 |
} |
165125e1e [BLOCK] Get rid o... |
526 |
void elv_merge_requests(struct request_queue *q, struct request *rq, |
1da177e4c Linux-2.6.12-rc2 |
527 528 |
struct request *next) { |
b374d18a4 block: get rid of... |
529 |
struct elevator_queue *e = q->elevator; |
5e84ea3a9 block: attempt to... |
530 |
const int next_sorted = next->cmd_flags & REQ_SORTED; |
1da177e4c Linux-2.6.12-rc2 |
531 |
|
5e84ea3a9 block: attempt to... |
532 |
if (next_sorted && e->ops->elevator_merge_req_fn) |
1da177e4c Linux-2.6.12-rc2 |
533 |
e->ops->elevator_merge_req_fn(q, rq, next); |
06b86245c [PATCH] 03/05 mov... |
534 |
|
9817064b6 [PATCH] elevator:... |
535 |
elv_rqhash_reposition(q, rq); |
9817064b6 [PATCH] elevator:... |
536 |
|
5e84ea3a9 block: attempt to... |
537 538 539 540 |
if (next_sorted) { elv_rqhash_del(q, next); q->nr_sorted--; } |
06b86245c [PATCH] 03/05 mov... |
541 |
q->last_merge = rq; |
1da177e4c Linux-2.6.12-rc2 |
542 |
} |
812d40264 blkio: Add io_mer... |
543 544 545 546 547 548 549 550 |
void elv_bio_merged(struct request_queue *q, struct request *rq, struct bio *bio) { struct elevator_queue *e = q->elevator; if (e->ops->elevator_bio_merged_fn) e->ops->elevator_bio_merged_fn(q, rq, bio); } |
165125e1e [BLOCK] Get rid o... |
551 |
void elv_requeue_request(struct request_queue *q, struct request *rq) |
1da177e4c Linux-2.6.12-rc2 |
552 |
{ |
1da177e4c Linux-2.6.12-rc2 |
553 554 555 556 |
/* * it already went through dequeue, we need to decrement the * in_flight count again */ |
8922e16cf [PATCH] 01/05 Imp... |
557 |
if (blk_account_rq(rq)) { |
0a7ae2ff0 block: change the... |
558 |
q->in_flight[rq_is_sync(rq)]--; |
33659ebba block: remove wra... |
559 |
if (rq->cmd_flags & REQ_SORTED) |
cad975164 elevator: abstrac... |
560 |
elv_deactivate_rq(q, rq); |
8922e16cf [PATCH] 01/05 Imp... |
561 |
} |
1da177e4c Linux-2.6.12-rc2 |
562 |
|
4aff5e233 [PATCH] Split str... |
563 |
rq->cmd_flags &= ~REQ_STARTED; |
1da177e4c Linux-2.6.12-rc2 |
564 |
|
b710a4805 block: get rid of... |
565 |
__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); |
1da177e4c Linux-2.6.12-rc2 |
566 |
} |
26308eab6 block: fix incons... |
567 |
void elv_drain_elevator(struct request_queue *q) |
15853af9f [BLOCK] Implement... |
568 569 570 571 572 573 574 575 576 577 578 579 580 |
{ static int printed; while (q->elevator->ops->elevator_dispatch_fn(q, 1)) ; if (q->nr_sorted == 0) return; if (printed++ < 10) { printk(KERN_ERR "%s: forced dispatching is broken " "(nr_sorted=%u), please report this ", q->elevator->elevator_type->elevator_name, q->nr_sorted); } } |
6c7e8cee6 block: elevator q... |
581 582 583 |
/* * Call with queue lock held, interrupts disabled */ |
f600abe2d block: fix bad sp... |
584 |
void elv_quiesce_start(struct request_queue *q) |
6c7e8cee6 block: elevator q... |
585 |
{ |
cd43e26f0 block: Expose sta... |
586 587 |
if (!q->elevator) return; |
6c7e8cee6 block: elevator q... |
588 589 590 591 592 593 594 |
queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); /* * make sure we don't have any requests in flight */ elv_drain_elevator(q); while (q->rq.elvpriv) { |
24ecfbe27 block: add blk_ru... |
595 |
__blk_run_queue(q); |
6c7e8cee6 block: elevator q... |
596 597 598 599 600 601 |
spin_unlock_irq(q->queue_lock); msleep(10); spin_lock_irq(q->queue_lock); elv_drain_elevator(q); } } |
f600abe2d block: fix bad sp... |
602 |
void elv_quiesce_end(struct request_queue *q) |
6c7e8cee6 block: elevator q... |
603 604 605 |
{ queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); } |
b710a4805 block: get rid of... |
606 |
void __elv_add_request(struct request_queue *q, struct request *rq, int where) |
1da177e4c Linux-2.6.12-rc2 |
607 |
{ |
5f3ea37c7 blktrace: port to... |
608 |
trace_block_rq_insert(q, rq); |
2056a782f [PATCH] Block que... |
609 |
|
1da177e4c Linux-2.6.12-rc2 |
610 |
rq->q = q; |
b710a4805 block: get rid of... |
611 612 613 614 615 616 617 618 |
if (rq->cmd_flags & REQ_SOFTBARRIER) { /* barriers are scheduling boundary, update end_sector */ if (rq->cmd_type == REQ_TYPE_FS || (rq->cmd_flags & REQ_DISCARD)) { q->end_sector = rq_end_sector(rq); q->boundary_rq = rq; } } else if (!(rq->cmd_flags & REQ_ELVPRIV) && |
3aa72873f elevator: check f... |
619 620 |
(where == ELEVATOR_INSERT_SORT || where == ELEVATOR_INSERT_SORT_MERGE)) |
b710a4805 block: get rid of... |
621 |
where = ELEVATOR_INSERT_BACK; |
8922e16cf [PATCH] 01/05 Imp... |
622 |
switch (where) { |
28e7d1845 block: drop barri... |
623 |
case ELEVATOR_INSERT_REQUEUE: |
8922e16cf [PATCH] 01/05 Imp... |
624 |
case ELEVATOR_INSERT_FRONT: |
4aff5e233 [PATCH] Split str... |
625 |
rq->cmd_flags |= REQ_SOFTBARRIER; |
8922e16cf [PATCH] 01/05 Imp... |
626 627 628 629 |
list_add(&rq->queuelist, &q->queue_head); break; case ELEVATOR_INSERT_BACK: |
4aff5e233 [PATCH] Split str... |
630 |
rq->cmd_flags |= REQ_SOFTBARRIER; |
15853af9f [BLOCK] Implement... |
631 |
elv_drain_elevator(q); |
8922e16cf [PATCH] 01/05 Imp... |
632 633 634 635 636 637 638 639 640 641 642 |
list_add_tail(&rq->queuelist, &q->queue_head); /* * We kick the queue here for the following reasons. * - The elevator might have returned NULL previously * to delay requests and returned them now. As the * queue wasn't empty before this request, ll_rw_blk * won't run the queue on return, resulting in hang. * - Usually, back inserted requests won't be merged * with anything. There's no point in delaying queue * processing. */ |
24ecfbe27 block: add blk_ru... |
643 |
__blk_run_queue(q); |
8922e16cf [PATCH] 01/05 Imp... |
644 |
break; |
5e84ea3a9 block: attempt to... |
645 646 647 648 649 650 651 652 |
case ELEVATOR_INSERT_SORT_MERGE: /* * If we succeed in merging this request with one in the * queue already, we are done - rq has now been freed, * so no need to do anything further. */ if (elv_attempt_insert_merge(q, rq)) break; |
8922e16cf [PATCH] 01/05 Imp... |
653 |
case ELEVATOR_INSERT_SORT: |
33659ebba block: remove wra... |
654 655 |
BUG_ON(rq->cmd_type != REQ_TYPE_FS && !(rq->cmd_flags & REQ_DISCARD)); |
4aff5e233 [PATCH] Split str... |
656 |
rq->cmd_flags |= REQ_SORTED; |
15853af9f [BLOCK] Implement... |
657 |
q->nr_sorted++; |
9817064b6 [PATCH] elevator:... |
658 659 660 661 662 |
if (rq_mergeable(rq)) { elv_rqhash_add(q, rq); if (!q->last_merge) q->last_merge = rq; } |
ca23509fb [PATCH] blk: fix ... |
663 664 665 666 667 668 |
/* * Some ioscheds (cfq) run q->request_fn directly, so * rq cannot be accessed after calling * elevator_add_req_fn. */ q->elevator->ops->elevator_add_req_fn(q, rq); |
8922e16cf [PATCH] 01/05 Imp... |
669 |
break; |
ae1b15396 block: reimplemen... |
670 671 672 673 |
case ELEVATOR_INSERT_FLUSH: rq->cmd_flags |= REQ_SOFTBARRIER; blk_insert_flush(rq); break; |
8922e16cf [PATCH] 01/05 Imp... |
674 675 676 |
default: printk(KERN_ERR "%s: bad insertion point %d ", |
24c03d47d block: remove rem... |
677 |
__func__, where); |
8922e16cf [PATCH] 01/05 Imp... |
678 679 |
BUG(); } |
1da177e4c Linux-2.6.12-rc2 |
680 |
} |
2e662b65f [PATCH] elevator:... |
681 |
EXPORT_SYMBOL(__elv_add_request); |
7eaceacca block: remove per... |
682 |
void elv_add_request(struct request_queue *q, struct request *rq, int where) |
1da177e4c Linux-2.6.12-rc2 |
683 684 685 686 |
{ unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); |
7eaceacca block: remove per... |
687 |
__elv_add_request(q, rq, where); |
1da177e4c Linux-2.6.12-rc2 |
688 689 |
spin_unlock_irqrestore(q->queue_lock, flags); } |
2e662b65f [PATCH] elevator:... |
690 |
EXPORT_SYMBOL(elv_add_request); |
165125e1e [BLOCK] Get rid o... |
691 |
struct request *elv_latter_request(struct request_queue *q, struct request *rq) |
1da177e4c Linux-2.6.12-rc2 |
692 |
{ |
b374d18a4 block: get rid of... |
693 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
694 695 696 |
if (e->ops->elevator_latter_req_fn) return e->ops->elevator_latter_req_fn(q, rq); |
1da177e4c Linux-2.6.12-rc2 |
697 698 |
return NULL; } |
165125e1e [BLOCK] Get rid o... |
699 |
struct request *elv_former_request(struct request_queue *q, struct request *rq) |
1da177e4c Linux-2.6.12-rc2 |
700 |
{ |
b374d18a4 block: get rid of... |
701 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
702 703 704 |
if (e->ops->elevator_former_req_fn) return e->ops->elevator_former_req_fn(q, rq); |
1da177e4c Linux-2.6.12-rc2 |
705 706 |
return NULL; } |
165125e1e [BLOCK] Get rid o... |
707 |
int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) |
1da177e4c Linux-2.6.12-rc2 |
708 |
{ |
b374d18a4 block: get rid of... |
709 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
710 711 |
if (e->ops->elevator_set_req_fn) |
cb78b285c [PATCH] Drop usel... |
712 |
return e->ops->elevator_set_req_fn(q, rq, gfp_mask); |
1da177e4c Linux-2.6.12-rc2 |
713 |
|
c186794db block: share requ... |
714 |
rq->elevator_private[0] = NULL; |
1da177e4c Linux-2.6.12-rc2 |
715 716 |
return 0; } |
165125e1e [BLOCK] Get rid o... |
717 |
void elv_put_request(struct request_queue *q, struct request *rq) |
1da177e4c Linux-2.6.12-rc2 |
718 |
{ |
b374d18a4 block: get rid of... |
719 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
720 721 |
if (e->ops->elevator_put_req_fn) |
bb37b94c6 [BLOCK] Cleanup u... |
722 |
e->ops->elevator_put_req_fn(rq); |
1da177e4c Linux-2.6.12-rc2 |
723 |
} |
165125e1e [BLOCK] Get rid o... |
724 |
int elv_may_queue(struct request_queue *q, int rw) |
1da177e4c Linux-2.6.12-rc2 |
725 |
{ |
b374d18a4 block: get rid of... |
726 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
727 728 |
if (e->ops->elevator_may_queue_fn) |
cb78b285c [PATCH] Drop usel... |
729 |
return e->ops->elevator_may_queue_fn(q, rw); |
1da177e4c Linux-2.6.12-rc2 |
730 731 732 |
return ELV_MQUEUE_MAY; } |
11914a53d block: Add interf... |
733 734 735 |
void elv_abort_queue(struct request_queue *q) { struct request *rq; |
ae1b15396 block: reimplemen... |
736 |
blk_abort_flushes(q); |
11914a53d block: Add interf... |
737 738 739 |
while (!list_empty(&q->queue_head)) { rq = list_entry_rq(q->queue_head.next); rq->cmd_flags |= REQ_QUIET; |
5f3ea37c7 blktrace: port to... |
740 |
trace_block_rq_abort(q, rq); |
53c663ce0 block: fix a poss... |
741 742 743 744 745 |
/* * Mark this request as started so we don't trigger * any debug logic in the end I/O path. */ blk_start_request(rq); |
40cbbb781 block: implement ... |
746 |
__blk_end_request_all(rq, -EIO); |
11914a53d block: Add interf... |
747 748 749 |
} } EXPORT_SYMBOL(elv_abort_queue); |
165125e1e [BLOCK] Get rid o... |
750 |
void elv_completed_request(struct request_queue *q, struct request *rq) |
1da177e4c Linux-2.6.12-rc2 |
751 |
{ |
b374d18a4 block: get rid of... |
752 |
struct elevator_queue *e = q->elevator; |
1da177e4c Linux-2.6.12-rc2 |
753 754 755 756 |
/* * request is released from the driver, io must be done */ |
8922e16cf [PATCH] 01/05 Imp... |
757 |
if (blk_account_rq(rq)) { |
0a7ae2ff0 block: change the... |
758 |
q->in_flight[rq_is_sync(rq)]--; |
33659ebba block: remove wra... |
759 760 |
if ((rq->cmd_flags & REQ_SORTED) && e->ops->elevator_completed_req_fn) |
1bc691d35 [PATCH] fix queue... |
761 762 |
e->ops->elevator_completed_req_fn(q, rq); } |
1da177e4c Linux-2.6.12-rc2 |
763 |
} |
3d1ab40f4 [PATCH] elevator_... |
764 765 766 767 |
#define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) static ssize_t elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) |
1da177e4c Linux-2.6.12-rc2 |
768 |
{ |
3d1ab40f4 [PATCH] elevator_... |
769 |
struct elv_fs_entry *entry = to_elv(attr); |
b374d18a4 block: get rid of... |
770 |
struct elevator_queue *e; |
3d1ab40f4 [PATCH] elevator_... |
771 772 773 774 |
ssize_t error; if (!entry->show) return -EIO; |
b374d18a4 block: get rid of... |
775 |
e = container_of(kobj, struct elevator_queue, kobj); |
3d1ab40f4 [PATCH] elevator_... |
776 777 778 779 780 |
mutex_lock(&e->sysfs_lock); error = e->ops ? entry->show(e, page) : -ENOENT; mutex_unlock(&e->sysfs_lock); return error; } |
1da177e4c Linux-2.6.12-rc2 |
781 |
|
3d1ab40f4 [PATCH] elevator_... |
782 783 784 785 |
static ssize_t elv_attr_store(struct kobject *kobj, struct attribute *attr, const char *page, size_t length) { |
3d1ab40f4 [PATCH] elevator_... |
786 |
struct elv_fs_entry *entry = to_elv(attr); |
b374d18a4 block: get rid of... |
787 |
struct elevator_queue *e; |
3d1ab40f4 [PATCH] elevator_... |
788 |
ssize_t error; |
1da177e4c Linux-2.6.12-rc2 |
789 |
|
3d1ab40f4 [PATCH] elevator_... |
790 791 |
if (!entry->store) return -EIO; |
1da177e4c Linux-2.6.12-rc2 |
792 |
|
b374d18a4 block: get rid of... |
793 |
e = container_of(kobj, struct elevator_queue, kobj); |
3d1ab40f4 [PATCH] elevator_... |
794 795 796 797 798 |
mutex_lock(&e->sysfs_lock); error = e->ops ? entry->store(e, page, length) : -ENOENT; mutex_unlock(&e->sysfs_lock); return error; } |
52cf25d0a Driver core: Cons... |
799 |
static const struct sysfs_ops elv_sysfs_ops = { |
3d1ab40f4 [PATCH] elevator_... |
800 801 802 803 804 805 806 807 808 809 810 |
.show = elv_attr_show, .store = elv_attr_store, }; static struct kobj_type elv_ktype = { .sysfs_ops = &elv_sysfs_ops, .release = elevator_release, }; int elv_register_queue(struct request_queue *q) { |
b374d18a4 block: get rid of... |
811 |
struct elevator_queue *e = q->elevator; |
3d1ab40f4 [PATCH] elevator_... |
812 |
int error; |
b2d6db587 Kobject: rename k... |
813 |
error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); |
3d1ab40f4 [PATCH] elevator_... |
814 |
if (!error) { |
e572ec7e4 [PATCH] fix rmmod... |
815 |
struct elv_fs_entry *attr = e->elevator_type->elevator_attrs; |
3d1ab40f4 [PATCH] elevator_... |
816 |
if (attr) { |
e572ec7e4 [PATCH] fix rmmod... |
817 818 |
while (attr->attr.name) { if (sysfs_create_file(&e->kobj, &attr->attr)) |
3d1ab40f4 [PATCH] elevator_... |
819 |
break; |
e572ec7e4 [PATCH] fix rmmod... |
820 |
attr++; |
3d1ab40f4 [PATCH] elevator_... |
821 822 823 |
} } kobject_uevent(&e->kobj, KOBJ_ADD); |
430c62fb2 elevator: fix oop... |
824 |
e->registered = 1; |
3d1ab40f4 [PATCH] elevator_... |
825 826 |
} return error; |
1da177e4c Linux-2.6.12-rc2 |
827 |
} |
01effb0dc block: allow init... |
828 |
EXPORT_SYMBOL(elv_register_queue); |
1da177e4c Linux-2.6.12-rc2 |
829 |
|
b374d18a4 block: get rid of... |
830 |
static void __elv_unregister_queue(struct elevator_queue *e) |
bc1c11697 [PATCH] elevator ... |
831 832 833 |
{ kobject_uevent(&e->kobj, KOBJ_REMOVE); kobject_del(&e->kobj); |
430c62fb2 elevator: fix oop... |
834 |
e->registered = 0; |
bc1c11697 [PATCH] elevator ... |
835 |
} |
1da177e4c Linux-2.6.12-rc2 |
836 837 |
void elv_unregister_queue(struct request_queue *q) { |
bc1c11697 [PATCH] elevator ... |
838 839 |
if (q) __elv_unregister_queue(q->elevator); |
1da177e4c Linux-2.6.12-rc2 |
840 |
} |
01effb0dc block: allow init... |
841 |
EXPORT_SYMBOL(elv_unregister_queue); |
1da177e4c Linux-2.6.12-rc2 |
842 |
|
2fdd82bd8 block: let elv_re... |
843 |
void elv_register(struct elevator_type *e) |
1da177e4c Linux-2.6.12-rc2 |
844 |
{ |
1ffb96c58 make elv_register... |
845 |
char *def = ""; |
2a12dcd71 [PATCH] elevator:... |
846 847 |
spin_lock(&elv_list_lock); |
ce5244974 BUG_ON() Conversi... |
848 |
BUG_ON(elevator_find(e->elevator_name)); |
1da177e4c Linux-2.6.12-rc2 |
849 |
list_add_tail(&e->list, &elv_list); |
2a12dcd71 [PATCH] elevator:... |
850 |
spin_unlock(&elv_list_lock); |
1da177e4c Linux-2.6.12-rc2 |
851 |
|
5f0039764 [BLOCK] elevator:... |
852 853 854 |
if (!strcmp(e->elevator_name, chosen_elevator) || (!*chosen_elevator && !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) |
1ffb96c58 make elv_register... |
855 |
def = " (default)"; |
4eb166d98 block: make eleva... |
856 857 858 |
printk(KERN_INFO "io scheduler %s registered%s ", e->elevator_name, def); |
1da177e4c Linux-2.6.12-rc2 |
859 860 861 862 863 |
} EXPORT_SYMBOL_GPL(elv_register); void elv_unregister(struct elevator_type *e) { |
83521d3eb [PATCH] cfq-iosch... |
864 865 866 867 868 |
struct task_struct *g, *p; /* * Iterate every thread in the process to remove the io contexts. */ |
e17a9489b [PATCH] stop elv_... |
869 870 871 872 |
if (e->ops.trim) { read_lock(&tasklist_lock); do_each_thread(g, p) { task_lock(p); |
2d8f61316 elv_unregister: f... |
873 874 |
if (p->io_context) e->ops.trim(p->io_context); |
e17a9489b [PATCH] stop elv_... |
875 876 877 878 |
task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); } |
83521d3eb [PATCH] cfq-iosch... |
879 |
|
2a12dcd71 [PATCH] elevator:... |
880 |
spin_lock(&elv_list_lock); |
1da177e4c Linux-2.6.12-rc2 |
881 |
list_del_init(&e->list); |
2a12dcd71 [PATCH] elevator:... |
882 |
spin_unlock(&elv_list_lock); |
1da177e4c Linux-2.6.12-rc2 |
883 884 885 886 887 888 889 |
} EXPORT_SYMBOL_GPL(elv_unregister); /* * switch to new_e io scheduler. be careful not to introduce deadlocks - * we don't free the old io scheduler, before we have allocated what we * need for the new one. this way we have a chance of going back to the old |
cb98fc8bb [BLOCK] Reimpleme... |
890 |
* one, if the new one fails init for some reason. |
1da177e4c Linux-2.6.12-rc2 |
891 |
*/ |
165125e1e [BLOCK] Get rid o... |
892 |
static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) |
1da177e4c Linux-2.6.12-rc2 |
893 |
{ |
b374d18a4 block: get rid of... |
894 |
struct elevator_queue *old_elevator, *e; |
bc1c11697 [PATCH] elevator ... |
895 |
void *data; |
5dd531a03 block: add functi... |
896 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
897 |
|
cb98fc8bb [BLOCK] Reimpleme... |
898 899 900 |
/* * Allocate new elevator */ |
b5deef901 [PATCH] Make sure... |
901 |
e = elevator_alloc(q, new_e); |
1da177e4c Linux-2.6.12-rc2 |
902 |
if (!e) |
5dd531a03 block: add functi... |
903 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
904 |
|
bc1c11697 [PATCH] elevator ... |
905 906 907 |
data = elevator_init_queue(q, e); if (!data) { kobject_put(&e->kobj); |
5dd531a03 block: add functi... |
908 |
return -ENOMEM; |
bc1c11697 [PATCH] elevator ... |
909 |
} |
1da177e4c Linux-2.6.12-rc2 |
910 |
/* |
cb98fc8bb [BLOCK] Reimpleme... |
911 |
* Turn on BYPASS and drain all requests w/ elevator private data |
1da177e4c Linux-2.6.12-rc2 |
912 |
*/ |
cb98fc8bb [BLOCK] Reimpleme... |
913 |
spin_lock_irq(q->queue_lock); |
f600abe2d block: fix bad sp... |
914 |
elv_quiesce_start(q); |
cb98fc8bb [BLOCK] Reimpleme... |
915 |
|
1da177e4c Linux-2.6.12-rc2 |
916 |
/* |
bc1c11697 [PATCH] elevator ... |
917 |
* Remember old elevator. |
1da177e4c Linux-2.6.12-rc2 |
918 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
919 920 921 |
old_elevator = q->elevator; /* |
1da177e4c Linux-2.6.12-rc2 |
922 923 |
* attach and start new elevator */ |
bc1c11697 [PATCH] elevator ... |
924 925 926 |
elevator_attach(q, e, data); spin_unlock_irq(q->queue_lock); |
430c62fb2 elevator: fix oop... |
927 928 |
if (old_elevator->registered) { __elv_unregister_queue(old_elevator); |
1da177e4c Linux-2.6.12-rc2 |
929 |
|
430c62fb2 elevator: fix oop... |
930 931 932 933 |
err = elv_register_queue(q); if (err) goto fail_register; } |
1da177e4c Linux-2.6.12-rc2 |
934 935 |
/* |
cb98fc8bb [BLOCK] Reimpleme... |
936 |
* finally exit old elevator and turn off BYPASS. |
1da177e4c Linux-2.6.12-rc2 |
937 938 |
*/ elevator_exit(old_elevator); |
75ad23bc0 block: make queue... |
939 |
spin_lock_irq(q->queue_lock); |
f600abe2d block: fix bad sp... |
940 |
elv_quiesce_end(q); |
75ad23bc0 block: make queue... |
941 |
spin_unlock_irq(q->queue_lock); |
4722dc52a Added in elevator... |
942 |
blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); |
5dd531a03 block: add functi... |
943 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
944 945 946 947 948 949 950 |
fail_register: /* * switch failed, exit the new io scheduler and reattach the old * one again (along with re-adding the sysfs dir) */ elevator_exit(e); |
1da177e4c Linux-2.6.12-rc2 |
951 952 |
q->elevator = old_elevator; elv_register_queue(q); |
75ad23bc0 block: make queue... |
953 954 955 956 |
spin_lock_irq(q->queue_lock); queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); spin_unlock_irq(q->queue_lock); |
5dd531a03 block: add functi... |
957 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
958 |
} |
5dd531a03 block: add functi... |
959 960 961 962 |
/* * Switch this queue to the given IO scheduler. */ int elevator_change(struct request_queue *q, const char *name) |
1da177e4c Linux-2.6.12-rc2 |
963 964 965 |
{ char elevator_name[ELV_NAME_MAX]; struct elevator_type *e; |
cd43e26f0 block: Expose sta... |
966 |
if (!q->elevator) |
5dd531a03 block: add functi... |
967 |
return -ENXIO; |
cd43e26f0 block: Expose sta... |
968 |
|
ee2e992cc block: simplify s... |
969 |
strlcpy(elevator_name, name, sizeof(elevator_name)); |
8c2795985 elv_iosched_store... |
970 |
e = elevator_get(strstrip(elevator_name)); |
1da177e4c Linux-2.6.12-rc2 |
971 972 973 974 975 |
if (!e) { printk(KERN_ERR "elevator: type %s not found ", elevator_name); return -EINVAL; } |
2ca7d93bb [PATCH] block cle... |
976 977 |
if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { elevator_put(e); |
5dd531a03 block: add functi... |
978 |
return 0; |
2ca7d93bb [PATCH] block cle... |
979 |
} |
1da177e4c Linux-2.6.12-rc2 |
980 |
|
5dd531a03 block: add functi... |
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 |
return elevator_switch(q, e); } EXPORT_SYMBOL(elevator_change); ssize_t elv_iosched_store(struct request_queue *q, const char *name, size_t count) { int ret; if (!q->elevator) return count; ret = elevator_change(q, name); if (!ret) return count; printk(KERN_ERR "elevator: switch to %s failed ", name); return ret; |
1da177e4c Linux-2.6.12-rc2 |
1000 |
} |
165125e1e [BLOCK] Get rid o... |
1001 |
ssize_t elv_iosched_show(struct request_queue *q, char *name) |
1da177e4c Linux-2.6.12-rc2 |
1002 |
{ |
b374d18a4 block: get rid of... |
1003 |
struct elevator_queue *e = q->elevator; |
cd43e26f0 block: Expose sta... |
1004 |
struct elevator_type *elv; |
70cee26e0 Use list_for_each... |
1005 |
struct elevator_type *__e; |
1da177e4c Linux-2.6.12-rc2 |
1006 |
int len = 0; |
e36f724b4 block: Adjust elv... |
1007 |
if (!q->elevator || !blk_queue_stackable(q)) |
cd43e26f0 block: Expose sta... |
1008 1009 1010 1011 |
return sprintf(name, "none "); elv = e->elevator_type; |
2a12dcd71 [PATCH] elevator:... |
1012 |
spin_lock(&elv_list_lock); |
70cee26e0 Use list_for_each... |
1013 |
list_for_each_entry(__e, &elv_list, list) { |
1da177e4c Linux-2.6.12-rc2 |
1014 1015 1016 1017 1018 |
if (!strcmp(elv->elevator_name, __e->elevator_name)) len += sprintf(name+len, "[%s] ", elv->elevator_name); else len += sprintf(name+len, "%s ", __e->elevator_name); } |
2a12dcd71 [PATCH] elevator:... |
1019 |
spin_unlock(&elv_list_lock); |
1da177e4c Linux-2.6.12-rc2 |
1020 1021 1022 1023 1024 |
len += sprintf(len+name, " "); return len; } |
165125e1e [BLOCK] Get rid o... |
1025 1026 |
struct request *elv_rb_former_request(struct request_queue *q, struct request *rq) |
2e662b65f [PATCH] elevator:... |
1027 1028 1029 1030 1031 1032 1033 1034 |
{ struct rb_node *rbprev = rb_prev(&rq->rb_node); if (rbprev) return rb_entry_rq(rbprev); return NULL; } |
2e662b65f [PATCH] elevator:... |
1035 |
EXPORT_SYMBOL(elv_rb_former_request); |
165125e1e [BLOCK] Get rid o... |
1036 1037 |
struct request *elv_rb_latter_request(struct request_queue *q, struct request *rq) |
2e662b65f [PATCH] elevator:... |
1038 1039 1040 1041 1042 1043 1044 1045 |
{ struct rb_node *rbnext = rb_next(&rq->rb_node); if (rbnext) return rb_entry_rq(rbnext); return NULL; } |
2e662b65f [PATCH] elevator:... |
1046 |
EXPORT_SYMBOL(elv_rb_latter_request); |