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