Blame view

block/elevator.c 24.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
   *  Block device elevator/IO-scheduler.
   *
   *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
   *
0fe234795   Jens Axboe   [PATCH] Update ax...
6
   * 30042000 Jens Axboe <axboe@kernel.dk> :
1da177e4c   Linus Torvalds   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   Linus Torvalds   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   Tejun Heo   [BLOCK] Reimpleme...
34
  #include <linux/delay.h>
2056a782f   Jens Axboe   [PATCH] Block que...
35
  #include <linux/blktrace_api.h>
9817064b6   Jens Axboe   [PATCH] elevator:...
36
  #include <linux/hash.h>
0835da67c   Jens Axboe   block: use linux/...
37
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

55782138e   Li Zefan   tracing/events: c...
39
  #include <trace/events/block.h>
242f9dcb8   Jens Axboe   block: unify requ...
40
  #include "blk.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
  static DEFINE_SPINLOCK(elv_list_lock);
  static LIST_HEAD(elv_list);
  
  /*
9817064b6   Jens Axboe   [PATCH] elevator:...
45
46
47
48
   * Merge hash stuff.
   */
  static const int elv_hash_shift = 6;
  #define ELV_HASH_BLOCK(sec)	((sec) >> 3)
4eb166d98   Jens Axboe   block: make eleva...
49
50
  #define ELV_HASH_FN(sec)	\
  		(hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift))
9817064b6   Jens Axboe   [PATCH] elevator:...
51
  #define ELV_HASH_ENTRIES	(1 << elv_hash_shift)
83096ebf1   Tejun Heo   block: convert to...
52
  #define rq_hash_key(rq)		(blk_rq_pos(rq) + blk_rq_sectors(rq))
9817064b6   Jens Axboe   [PATCH] elevator:...
53
54
  
  /*
da7752650   Jens Axboe   [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   Jens Axboe   [BLOCK] Get rid o...
60
  	struct request_queue *q = rq->q;
b374d18a4   Jens Axboe   block: get rid of...
61
  	struct elevator_queue *e = q->elevator;
da7752650   Jens Axboe   [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   Linus Torvalds   Linux-2.6.12-rc2
70
71
   * can we safely merge with this request?
   */
72ed0bf60   Adrian Bunk   block/elevator.c:...
72
  int elv_rq_merge_ok(struct request *rq, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
  {
  	if (!rq_mergeable(rq))
  		return 0;
  
  	/*
e17fc0a1c   David Woodhouse   Allow elevators t...
78
79
  	 * Don't merge file system requests and discard requests
  	 */
7b6d91dae   Christoph Hellwig   block: unify flag...
80
  	if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
e17fc0a1c   David Woodhouse   Allow elevators t...
81
82
83
  		return 0;
  
  	/*
8d57a98cc   Adrian Hunter   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   Linus Torvalds   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   Jens Axboe   [PATCH] cfq-iosch...
96
  	 * must be same device and not a special request
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  	 */
bb4067e34   Jens Axboe   [PATCH] elevator:...
98
  	if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
da7752650   Jens Axboe   [PATCH] cfq-iosch...
99
  		return 0;
7ba1ba12e   Martin K. Petersen   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   Jens Axboe   [PATCH] cfq-iosch...
105
106
  	if (!elv_iosched_allow_merge(rq, bio))
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107

da7752650   Jens Axboe   [PATCH] cfq-iosch...
108
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
  }
  EXPORT_SYMBOL(elv_rq_merge_ok);
73c101011   Jens Axboe   block: initial pa...
111
  int elv_try_merge(struct request *__rq, struct bio *bio)
1da177e4c   Linus Torvalds   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   Tejun Heo   block: convert to...
119
  		if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  			ret = ELEVATOR_BACK_MERGE;
83096ebf1   Tejun Heo   block: convert to...
121
  		else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
  			ret = ELEVATOR_FRONT_MERGE;
  	}
  
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
  static struct elevator_type *elevator_find(const char *name)
  {
a22b169df   Vasily Tarasov   [PATCH] block lay...
130
  	struct elevator_type *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131

70cee26e0   Matthias Kaehlcke   Use list_for_each...
132
  	list_for_each_entry(e, &elv_list, list) {
a22b169df   Vasily Tarasov   [PATCH] block lay...
133
134
  		if (!strcmp(e->elevator_name, name))
  			return e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

a22b169df   Vasily Tarasov   [PATCH] block lay...
137
  	return NULL;
1da177e4c   Linus Torvalds   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   Tejun Heo   [PATCH] fix try_m...
147
  	struct elevator_type *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

2a12dcd71   Jens Axboe   [PATCH] elevator:...
149
  	spin_lock(&elv_list_lock);
2824bc932   Tejun Heo   [PATCH] fix try_m...
150
151
  
  	e = elevator_find(name);
e16409496   Jens Axboe   elevator: make el...
152
  	if (!e) {
e16409496   Jens Axboe   elevator: make el...
153
  		spin_unlock(&elv_list_lock);
490b94be0   Kees Cook   iosched: remove r...
154
  		request_module("%s-iosched", name);
e16409496   Jens Axboe   elevator: make el...
155
156
157
  		spin_lock(&elv_list_lock);
  		e = elevator_find(name);
  	}
2824bc932   Tejun Heo   [PATCH] fix try_m...
158
159
  	if (e && !try_module_get(e->elevator_owner))
  		e = NULL;
2a12dcd71   Jens Axboe   [PATCH] elevator:...
160
  	spin_unlock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
  
  	return e;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
164
165
  static void *elevator_init_queue(struct request_queue *q,
  				 struct elevator_queue *eq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  {
bb37b94c6   Jens Axboe   [BLOCK] Cleanup u...
167
  	return eq->ops->elevator_init_fn(q);
bc1c11697   Jens Axboe   [PATCH] elevator ...
168
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169

165125e1e   Jens Axboe   [BLOCK] Get rid o...
170
  static void elevator_attach(struct request_queue *q, struct elevator_queue *eq,
bc1c11697   Jens Axboe   [PATCH] elevator ...
171
172
  			   void *data)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  	q->elevator = eq;
bc1c11697   Jens Axboe   [PATCH] elevator ...
174
  	eq->elevator_data = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
  }
  
  static char chosen_elevator[16];
5f0039764   Nate Diller   [BLOCK] elevator:...
178
  static int __init elevator_setup(char *str)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  {
752a3b796   Chuck Ebbert   [BLOCK] elevator:...
180
181
182
183
  	/*
  	 * Be backwards-compatible with previous kernels, so users
  	 * won't get the wrong elevator.
  	 */
492af6350   Jens Axboe   block: remove the...
184
  	strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
9b41046cd   OGAWA Hirofumi   [PATCH] Don't pas...
185
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
  }
  
  __setup("elevator=", elevator_setup);
3d1ab40f4   Al Viro   [PATCH] elevator_...
189
  static struct kobj_type elv_ktype;
b374d18a4   Jens Axboe   block: get rid of...
190
  static struct elevator_queue *elevator_alloc(struct request_queue *q,
165125e1e   Jens Axboe   [BLOCK] Get rid o...
191
  				  struct elevator_type *e)
3d1ab40f4   Al Viro   [PATCH] elevator_...
192
  {
b374d18a4   Jens Axboe   block: get rid of...
193
  	struct elevator_queue *eq;
9817064b6   Jens Axboe   [PATCH] elevator:...
194
  	int i;
b374d18a4   Jens Axboe   block: get rid of...
195
  	eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node);
9817064b6   Jens Axboe   [PATCH] elevator:...
196
197
  	if (unlikely(!eq))
  		goto err;
9817064b6   Jens Axboe   [PATCH] elevator:...
198
199
  	eq->ops = &e->ops;
  	eq->elevator_type = e;
f9cb074bf   Greg Kroah-Hartman   Kobject: rename k...
200
  	kobject_init(&eq->kobj, &elv_ktype);
9817064b6   Jens Axboe   [PATCH] elevator:...
201
  	mutex_init(&eq->sysfs_lock);
b5deef901   Jens Axboe   [PATCH] Make sure...
202
203
  	eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES,
  					GFP_KERNEL, q->node);
9817064b6   Jens Axboe   [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   Al Viro   [PATCH] elevator_...
209
  	return eq;
9817064b6   Jens Axboe   [PATCH] elevator:...
210
211
212
213
  err:
  	kfree(eq);
  	elevator_put(e);
  	return NULL;
3d1ab40f4   Al Viro   [PATCH] elevator_...
214
215
216
217
  }
  
  static void elevator_release(struct kobject *kobj)
  {
b374d18a4   Jens Axboe   block: get rid of...
218
  	struct elevator_queue *e;
9817064b6   Jens Axboe   [PATCH] elevator:...
219

b374d18a4   Jens Axboe   block: get rid of...
220
  	e = container_of(kobj, struct elevator_queue, kobj);
3d1ab40f4   Al Viro   [PATCH] elevator_...
221
  	elevator_put(e->elevator_type);
9817064b6   Jens Axboe   [PATCH] elevator:...
222
  	kfree(e->hash);
3d1ab40f4   Al Viro   [PATCH] elevator_...
223
224
  	kfree(e);
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
225
  int elevator_init(struct request_queue *q, char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
  {
  	struct elevator_type *e = NULL;
  	struct elevator_queue *eq;
bc1c11697   Jens Axboe   [PATCH] elevator ...
229
  	void *data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230

1abec4fdb   Mike Snitzer   block: make blk_i...
231
232
  	if (unlikely(q->elevator))
  		return 0;
cb98fc8bb   Tejun Heo   [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   Tejun Heo   [BLOCK] Reimpleme...
237

4eb166d98   Jens Axboe   block: make eleva...
238
239
240
241
242
  	if (name) {
  		e = elevator_get(name);
  		if (!e)
  			return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

4eb166d98   Jens Axboe   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   Nate Diller   [BLOCK] elevator:...
251

4eb166d98   Jens Axboe   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   Nate Diller   [BLOCK] elevator:...
261
  	}
b5deef901   Jens Axboe   [PATCH] Make sure...
262
  	eq = elevator_alloc(q, e);
3d1ab40f4   Al Viro   [PATCH] elevator_...
263
  	if (!eq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

bc1c11697   Jens Axboe   [PATCH] elevator ...
266
267
  	data = elevator_init_queue(q, eq);
  	if (!data) {
3d1ab40f4   Al Viro   [PATCH] elevator_...
268
  		kobject_put(&eq->kobj);
bc1c11697   Jens Axboe   [PATCH] elevator ...
269
270
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271

bc1c11697   Jens Axboe   [PATCH] elevator ...
272
  	elevator_attach(q, eq, data);
1abec4fdb   Mike Snitzer   block: make blk_i...
273
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
275
  EXPORT_SYMBOL(elevator_init);
b374d18a4   Jens Axboe   block: get rid of...
276
  void elevator_exit(struct elevator_queue *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  {
3d1ab40f4   Al Viro   [PATCH] elevator_...
278
  	mutex_lock(&e->sysfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  	if (e->ops->elevator_exit_fn)
  		e->ops->elevator_exit_fn(e);
3d1ab40f4   Al Viro   [PATCH] elevator_...
281
282
  	e->ops = NULL;
  	mutex_unlock(&e->sysfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

3d1ab40f4   Al Viro   [PATCH] elevator_...
284
  	kobject_put(&e->kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
286
  EXPORT_SYMBOL(elevator_exit);
9817064b6   Jens Axboe   [PATCH] elevator:...
287
288
289
290
  static inline void __elv_rqhash_del(struct request *rq)
  {
  	hlist_del_init(&rq->hash);
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
291
  static void elv_rqhash_del(struct request_queue *q, struct request *rq)
9817064b6   Jens Axboe   [PATCH] elevator:...
292
293
294
295
  {
  	if (ELV_ON_HASH(rq))
  		__elv_rqhash_del(rq);
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
296
  static void elv_rqhash_add(struct request_queue *q, struct request *rq)
9817064b6   Jens Axboe   [PATCH] elevator:...
297
  {
b374d18a4   Jens Axboe   block: get rid of...
298
  	struct elevator_queue *e = q->elevator;
9817064b6   Jens Axboe   [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   Jens Axboe   [BLOCK] Get rid o...
303
  static void elv_rqhash_reposition(struct request_queue *q, struct request *rq)
9817064b6   Jens Axboe   [PATCH] elevator:...
304
305
306
307
  {
  	__elv_rqhash_del(rq);
  	elv_rqhash_add(q, rq);
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
308
  static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
9817064b6   Jens Axboe   [PATCH] elevator:...
309
  {
b374d18a4   Jens Axboe   block: get rid of...
310
  	struct elevator_queue *e = q->elevator;
9817064b6   Jens Axboe   [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   Tejun Heo   [PATCH] 01/05 Imp...
329
  /*
2e662b65f   Jens Axboe   [PATCH] elevator:...
330
331
332
333
334
335
336
337
338
339
340
341
   * RB-tree support functions for inserting/lookup/removal of requests
   * in a sorted RB tree.
   */
  struct request *elv_rb_add(struct rb_root *root, struct request *rq)
  {
  	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   Tejun Heo   block: convert to...
342
  		if (blk_rq_pos(rq) < blk_rq_pos(__rq))
2e662b65f   Jens Axboe   [PATCH] elevator:...
343
  			p = &(*p)->rb_left;
83096ebf1   Tejun Heo   block: convert to...
344
  		else if (blk_rq_pos(rq) > blk_rq_pos(__rq))
2e662b65f   Jens Axboe   [PATCH] elevator:...
345
346
347
348
349
350
351
352
353
  			p = &(*p)->rb_right;
  		else
  			return __rq;
  	}
  
  	rb_link_node(&rq->rb_node, parent, p);
  	rb_insert_color(&rq->rb_node, root);
  	return NULL;
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
354
355
356
357
358
359
360
361
  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   Jens Axboe   [PATCH] elevator:...
362
363
364
365
366
367
368
369
370
  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   Tejun Heo   block: convert to...
371
  		if (sector < blk_rq_pos(rq))
2e662b65f   Jens Axboe   [PATCH] elevator:...
372
  			n = n->rb_left;
83096ebf1   Tejun Heo   block: convert to...
373
  		else if (sector > blk_rq_pos(rq))
2e662b65f   Jens Axboe   [PATCH] elevator:...
374
375
376
377
378
379
380
  			n = n->rb_right;
  		else
  			return rq;
  	}
  
  	return NULL;
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
381
382
383
  EXPORT_SYMBOL(elv_rb_find);
  
  /*
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
384
   * Insert rq into dispatch queue of q.  Queue lock must be held on
dbe7f76dd   Uwe Kleine-König   fix typo "insted"...
385
   * entry.  rq is sort instead into the dispatch queue. To be used by
2e662b65f   Jens Axboe   [PATCH] elevator:...
386
   * specific elevators.
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
387
   */
165125e1e   Jens Axboe   [BLOCK] Get rid o...
388
  void elv_dispatch_sort(struct request_queue *q, struct request *rq)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
389
390
  {
  	sector_t boundary;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
391
  	struct list_head *entry;
4eb166d98   Jens Axboe   block: make eleva...
392
  	int stop_flags;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
393

06b86245c   Tejun Heo   [PATCH] 03/05 mov...
394
395
  	if (q->last_merge == rq)
  		q->last_merge = NULL;
9817064b6   Jens Axboe   [PATCH] elevator:...
396
397
  
  	elv_rqhash_del(q, rq);
15853af9f   Tejun Heo   [BLOCK] Implement...
398
  	q->nr_sorted--;
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
399

1b47f531e   Jens Axboe   [PATCH] generic d...
400
  	boundary = q->end_sector;
02e031cbc   Christoph Hellwig   block: remove REQ...
401
  	stop_flags = REQ_SOFTBARRIER | REQ_STARTED;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
402
403
  	list_for_each_prev(entry, &q->queue_head) {
  		struct request *pos = list_entry_rq(entry);
33659ebba   Christoph Hellwig   block: remove wra...
404
405
  		if ((rq->cmd_flags & REQ_DISCARD) !=
  		    (pos->cmd_flags & REQ_DISCARD))
e17fc0a1c   David Woodhouse   Allow elevators t...
406
  			break;
783660b2f   Jens Axboe   elevator: don't s...
407
408
  		if (rq_data_dir(rq) != rq_data_dir(pos))
  			break;
4eb166d98   Jens Axboe   block: make eleva...
409
  		if (pos->cmd_flags & stop_flags)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
410
  			break;
83096ebf1   Tejun Heo   block: convert to...
411
412
  		if (blk_rq_pos(rq) >= boundary) {
  			if (blk_rq_pos(pos) < boundary)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
413
414
  				continue;
  		} else {
83096ebf1   Tejun Heo   block: convert to...
415
  			if (blk_rq_pos(pos) >= boundary)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
416
417
  				break;
  		}
83096ebf1   Tejun Heo   block: convert to...
418
  		if (blk_rq_pos(rq) >= blk_rq_pos(pos))
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
419
420
421
422
423
  			break;
  	}
  
  	list_add(&rq->queuelist, entry);
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
424
  EXPORT_SYMBOL(elv_dispatch_sort);
9817064b6   Jens Axboe   [PATCH] elevator:...
425
  /*
2e662b65f   Jens Axboe   [PATCH] elevator:...
426
427
428
   * 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   Jens Axboe   [PATCH] elevator:...
429
430
431
432
433
434
435
436
437
438
439
440
441
442
   */
  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   Jens Axboe   [PATCH] elevator:...
443
  EXPORT_SYMBOL(elv_dispatch_add_tail);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
444
  int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  {
b374d18a4   Jens Axboe   block: get rid of...
446
  	struct elevator_queue *e = q->elevator;
9817064b6   Jens Axboe   [PATCH] elevator:...
447
  	struct request *__rq;
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
448
  	int ret;
9817064b6   Jens Axboe   [PATCH] elevator:...
449
  	/*
488991e28   Alan D. Brunelle   block: Added in s...
450
451
452
453
454
455
456
457
458
  	 * 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   Jens Axboe   [PATCH] elevator:...
459
460
  	 * First try one-hit cache.
  	 */
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
461
462
463
464
465
466
467
  	if (q->last_merge) {
  		ret = elv_try_merge(q->last_merge, bio);
  		if (ret != ELEVATOR_NO_MERGE) {
  			*req = q->last_merge;
  			return ret;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468

488991e28   Alan D. Brunelle   block: Added in s...
469
  	if (blk_queue_noxmerges(q))
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
470
  		return ELEVATOR_NO_MERGE;
9817064b6   Jens Axboe   [PATCH] elevator:...
471
472
473
474
475
476
477
478
  	/*
  	 * 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   Linus Torvalds   Linux-2.6.12-rc2
479
480
481
482
483
  	if (e->ops->elevator_merge_fn)
  		return e->ops->elevator_merge_fn(q, req, bio);
  
  	return ELEVATOR_NO_MERGE;
  }
5e84ea3a9   Jens Axboe   block: attempt to...
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
514
515
516
  /*
   * 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   Jens Axboe   [BLOCK] Get rid o...
517
  void elv_merged_request(struct request_queue *q, struct request *rq, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  {
b374d18a4   Jens Axboe   block: get rid of...
519
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
  
  	if (e->ops->elevator_merged_fn)
2e662b65f   Jens Axboe   [PATCH] elevator:...
522
  		e->ops->elevator_merged_fn(q, rq, type);
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
523

2e662b65f   Jens Axboe   [PATCH] elevator:...
524
525
  	if (type == ELEVATOR_BACK_MERGE)
  		elv_rqhash_reposition(q, rq);
9817064b6   Jens Axboe   [PATCH] elevator:...
526

06b86245c   Tejun Heo   [PATCH] 03/05 mov...
527
  	q->last_merge = rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
529
  void elv_merge_requests(struct request_queue *q, struct request *rq,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
  			     struct request *next)
  {
b374d18a4   Jens Axboe   block: get rid of...
532
  	struct elevator_queue *e = q->elevator;
5e84ea3a9   Jens Axboe   block: attempt to...
533
  	const int next_sorted = next->cmd_flags & REQ_SORTED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534

5e84ea3a9   Jens Axboe   block: attempt to...
535
  	if (next_sorted && e->ops->elevator_merge_req_fn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  		e->ops->elevator_merge_req_fn(q, rq, next);
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
537

9817064b6   Jens Axboe   [PATCH] elevator:...
538
  	elv_rqhash_reposition(q, rq);
9817064b6   Jens Axboe   [PATCH] elevator:...
539

5e84ea3a9   Jens Axboe   block: attempt to...
540
541
542
543
  	if (next_sorted) {
  		elv_rqhash_del(q, next);
  		q->nr_sorted--;
  	}
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
544
  	q->last_merge = rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  }
812d40264   Divyesh Shah   blkio: Add io_mer...
546
547
548
549
550
551
552
553
  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   Jens Axboe   [BLOCK] Get rid o...
554
  void elv_requeue_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
  	/*
  	 * it already went through dequeue, we need to decrement the
  	 * in_flight count again
  	 */
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
560
  	if (blk_account_rq(rq)) {
0a7ae2ff0   Jens Axboe   block: change the...
561
  		q->in_flight[rq_is_sync(rq)]--;
33659ebba   Christoph Hellwig   block: remove wra...
562
  		if (rq->cmd_flags & REQ_SORTED)
cad975164   Jens Axboe   elevator: abstrac...
563
  			elv_deactivate_rq(q, rq);
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
564
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565

4aff5e233   Jens Axboe   [PATCH] Split str...
566
  	rq->cmd_flags &= ~REQ_STARTED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567

b710a4805   Jens Axboe   block: get rid of...
568
  	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  }
26308eab6   Jerome Marchand   block: fix incons...
570
  void elv_drain_elevator(struct request_queue *q)
15853af9f   Tejun Heo   [BLOCK] Implement...
571
572
573
574
575
576
577
578
579
580
581
582
583
  {
  	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   Jens Axboe   block: elevator q...
584
585
586
  /*
   * Call with queue lock held, interrupts disabled
   */
f600abe2d   Jens Axboe   block: fix bad sp...
587
  void elv_quiesce_start(struct request_queue *q)
6c7e8cee6   Jens Axboe   block: elevator q...
588
  {
cd43e26f0   Martin K. Petersen   block: Expose sta...
589
590
  	if (!q->elevator)
  		return;
6c7e8cee6   Jens Axboe   block: elevator q...
591
592
593
594
595
596
597
  	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   Christoph Hellwig   block: add blk_ru...
598
  		__blk_run_queue(q);
6c7e8cee6   Jens Axboe   block: elevator q...
599
600
601
602
603
604
  		spin_unlock_irq(q->queue_lock);
  		msleep(10);
  		spin_lock_irq(q->queue_lock);
  		elv_drain_elevator(q);
  	}
  }
f600abe2d   Jens Axboe   block: fix bad sp...
605
  void elv_quiesce_end(struct request_queue *q)
6c7e8cee6   Jens Axboe   block: elevator q...
606
607
608
  {
  	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
  }
b710a4805   Jens Axboe   block: get rid of...
609
  void __elv_add_request(struct request_queue *q, struct request *rq, int where)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
  {
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
611
  	trace_block_rq_insert(q, rq);
2056a782f   Jens Axboe   [PATCH] Block que...
612

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  	rq->q = q;
b710a4805   Jens Axboe   block: get rid of...
614
615
616
617
618
619
620
621
  	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   Jens Axboe   elevator: check f...
622
623
  		    (where == ELEVATOR_INSERT_SORT ||
  		     where == ELEVATOR_INSERT_SORT_MERGE))
b710a4805   Jens Axboe   block: get rid of...
624
  		where = ELEVATOR_INSERT_BACK;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
625
  	switch (where) {
28e7d1845   Tejun Heo   block: drop barri...
626
  	case ELEVATOR_INSERT_REQUEUE:
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
627
  	case ELEVATOR_INSERT_FRONT:
4aff5e233   Jens Axboe   [PATCH] Split str...
628
  		rq->cmd_flags |= REQ_SOFTBARRIER;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
629
630
631
632
  		list_add(&rq->queuelist, &q->queue_head);
  		break;
  
  	case ELEVATOR_INSERT_BACK:
4aff5e233   Jens Axboe   [PATCH] Split str...
633
  		rq->cmd_flags |= REQ_SOFTBARRIER;
15853af9f   Tejun Heo   [BLOCK] Implement...
634
  		elv_drain_elevator(q);
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
635
636
637
638
639
640
641
642
643
644
645
  		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   Christoph Hellwig   block: add blk_ru...
646
  		__blk_run_queue(q);
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
647
  		break;
5e84ea3a9   Jens Axboe   block: attempt to...
648
649
650
651
652
653
654
655
  	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   Tejun Heo   [PATCH] 01/05 Imp...
656
  	case ELEVATOR_INSERT_SORT:
33659ebba   Christoph Hellwig   block: remove wra...
657
658
  		BUG_ON(rq->cmd_type != REQ_TYPE_FS &&
  		       !(rq->cmd_flags & REQ_DISCARD));
4aff5e233   Jens Axboe   [PATCH] Split str...
659
  		rq->cmd_flags |= REQ_SORTED;
15853af9f   Tejun Heo   [BLOCK] Implement...
660
  		q->nr_sorted++;
9817064b6   Jens Axboe   [PATCH] elevator:...
661
662
663
664
665
  		if (rq_mergeable(rq)) {
  			elv_rqhash_add(q, rq);
  			if (!q->last_merge)
  				q->last_merge = rq;
  		}
ca23509fb   Tejun Heo   [PATCH] blk: fix ...
666
667
668
669
670
671
  		/*
  		 * 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   Tejun Heo   [PATCH] 01/05 Imp...
672
  		break;
ae1b15396   Tejun Heo   block: reimplemen...
673
674
675
676
  	case ELEVATOR_INSERT_FLUSH:
  		rq->cmd_flags |= REQ_SOFTBARRIER;
  		blk_insert_flush(rq);
  		break;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
677
678
679
  	default:
  		printk(KERN_ERR "%s: bad insertion point %d
  ",
24c03d47d   Harvey Harrison   block: remove rem...
680
  		       __func__, where);
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
681
682
  		BUG();
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
684
  EXPORT_SYMBOL(__elv_add_request);
7eaceacca   Jens Axboe   block: remove per...
685
  void elv_add_request(struct request_queue *q, struct request *rq, int where)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(q->queue_lock, flags);
7eaceacca   Jens Axboe   block: remove per...
690
  	__elv_add_request(q, rq, where);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
  	spin_unlock_irqrestore(q->queue_lock, flags);
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
693
  EXPORT_SYMBOL(elv_add_request);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
694
  struct request *elv_latter_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
  {
b374d18a4   Jens Axboe   block: get rid of...
696
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
699
  
  	if (e->ops->elevator_latter_req_fn)
  		return e->ops->elevator_latter_req_fn(q, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
  	return NULL;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
702
  struct request *elv_former_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  {
b374d18a4   Jens Axboe   block: get rid of...
704
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
  
  	if (e->ops->elevator_former_req_fn)
  		return e->ops->elevator_former_req_fn(q, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
  	return NULL;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
710
  int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  {
b374d18a4   Jens Axboe   block: get rid of...
712
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
  
  	if (e->ops->elevator_set_req_fn)
cb78b285c   Jens Axboe   [PATCH] Drop usel...
715
  		return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716

c186794db   Mike Snitzer   block: share requ...
717
  	rq->elevator_private[0] = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
  	return 0;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
720
  void elv_put_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  {
b374d18a4   Jens Axboe   block: get rid of...
722
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
  
  	if (e->ops->elevator_put_req_fn)
bb37b94c6   Jens Axboe   [BLOCK] Cleanup u...
725
  		e->ops->elevator_put_req_fn(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
727
  int elv_may_queue(struct request_queue *q, int rw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  {
b374d18a4   Jens Axboe   block: get rid of...
729
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
731
  
  	if (e->ops->elevator_may_queue_fn)
cb78b285c   Jens Axboe   [PATCH] Drop usel...
732
  		return e->ops->elevator_may_queue_fn(q, rw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
  
  	return ELV_MQUEUE_MAY;
  }
11914a53d   Mike Anderson   block: Add interf...
736
737
738
  void elv_abort_queue(struct request_queue *q)
  {
  	struct request *rq;
ae1b15396   Tejun Heo   block: reimplemen...
739
  	blk_abort_flushes(q);
11914a53d   Mike Anderson   block: Add interf...
740
741
742
  	while (!list_empty(&q->queue_head)) {
  		rq = list_entry_rq(q->queue_head.next);
  		rq->cmd_flags |= REQ_QUIET;
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
743
  		trace_block_rq_abort(q, rq);
53c663ce0   Kiyoshi Ueda   block: fix a poss...
744
745
746
747
748
  		/*
  		 * Mark this request as started so we don't trigger
  		 * any debug logic in the end I/O path.
  		 */
  		blk_start_request(rq);
40cbbb781   Tejun Heo   block: implement ...
749
  		__blk_end_request_all(rq, -EIO);
11914a53d   Mike Anderson   block: Add interf...
750
751
752
  	}
  }
  EXPORT_SYMBOL(elv_abort_queue);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
753
  void elv_completed_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
  {
b374d18a4   Jens Axboe   block: get rid of...
755
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
759
  
  	/*
  	 * request is released from the driver, io must be done
  	 */
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
760
  	if (blk_account_rq(rq)) {
0a7ae2ff0   Jens Axboe   block: change the...
761
  		q->in_flight[rq_is_sync(rq)]--;
33659ebba   Christoph Hellwig   block: remove wra...
762
763
  		if ((rq->cmd_flags & REQ_SORTED) &&
  		    e->ops->elevator_completed_req_fn)
1bc691d35   Tejun Heo   [PATCH] fix queue...
764
765
  			e->ops->elevator_completed_req_fn(q, rq);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  }
3d1ab40f4   Al Viro   [PATCH] elevator_...
767
768
769
770
  #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   Linus Torvalds   Linux-2.6.12-rc2
771
  {
3d1ab40f4   Al Viro   [PATCH] elevator_...
772
  	struct elv_fs_entry *entry = to_elv(attr);
b374d18a4   Jens Axboe   block: get rid of...
773
  	struct elevator_queue *e;
3d1ab40f4   Al Viro   [PATCH] elevator_...
774
775
776
777
  	ssize_t error;
  
  	if (!entry->show)
  		return -EIO;
b374d18a4   Jens Axboe   block: get rid of...
778
  	e = container_of(kobj, struct elevator_queue, kobj);
3d1ab40f4   Al Viro   [PATCH] elevator_...
779
780
781
782
783
  	mutex_lock(&e->sysfs_lock);
  	error = e->ops ? entry->show(e, page) : -ENOENT;
  	mutex_unlock(&e->sysfs_lock);
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784

3d1ab40f4   Al Viro   [PATCH] elevator_...
785
786
787
788
  static ssize_t
  elv_attr_store(struct kobject *kobj, struct attribute *attr,
  	       const char *page, size_t length)
  {
3d1ab40f4   Al Viro   [PATCH] elevator_...
789
  	struct elv_fs_entry *entry = to_elv(attr);
b374d18a4   Jens Axboe   block: get rid of...
790
  	struct elevator_queue *e;
3d1ab40f4   Al Viro   [PATCH] elevator_...
791
  	ssize_t error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792

3d1ab40f4   Al Viro   [PATCH] elevator_...
793
794
  	if (!entry->store)
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795

b374d18a4   Jens Axboe   block: get rid of...
796
  	e = container_of(kobj, struct elevator_queue, kobj);
3d1ab40f4   Al Viro   [PATCH] elevator_...
797
798
799
800
801
  	mutex_lock(&e->sysfs_lock);
  	error = e->ops ? entry->store(e, page, length) : -ENOENT;
  	mutex_unlock(&e->sysfs_lock);
  	return error;
  }
52cf25d0a   Emese Revfy   Driver core: Cons...
802
  static const struct sysfs_ops elv_sysfs_ops = {
3d1ab40f4   Al Viro   [PATCH] elevator_...
803
804
805
806
807
808
809
810
811
812
813
  	.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   Jens Axboe   block: get rid of...
814
  	struct elevator_queue *e = q->elevator;
3d1ab40f4   Al Viro   [PATCH] elevator_...
815
  	int error;
b2d6db587   Greg Kroah-Hartman   Kobject: rename k...
816
  	error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
3d1ab40f4   Al Viro   [PATCH] elevator_...
817
  	if (!error) {
e572ec7e4   Al Viro   [PATCH] fix rmmod...
818
  		struct elv_fs_entry *attr = e->elevator_type->elevator_attrs;
3d1ab40f4   Al Viro   [PATCH] elevator_...
819
  		if (attr) {
e572ec7e4   Al Viro   [PATCH] fix rmmod...
820
821
  			while (attr->attr.name) {
  				if (sysfs_create_file(&e->kobj, &attr->attr))
3d1ab40f4   Al Viro   [PATCH] elevator_...
822
  					break;
e572ec7e4   Al Viro   [PATCH] fix rmmod...
823
  				attr++;
3d1ab40f4   Al Viro   [PATCH] elevator_...
824
825
826
  			}
  		}
  		kobject_uevent(&e->kobj, KOBJ_ADD);
430c62fb2   Jens Axboe   elevator: fix oop...
827
  		e->registered = 1;
3d1ab40f4   Al Viro   [PATCH] elevator_...
828
829
  	}
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
  }
01effb0dc   Mike Snitzer   block: allow init...
831
  EXPORT_SYMBOL(elv_register_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832

b374d18a4   Jens Axboe   block: get rid of...
833
  static void __elv_unregister_queue(struct elevator_queue *e)
bc1c11697   Jens Axboe   [PATCH] elevator ...
834
835
836
  {
  	kobject_uevent(&e->kobj, KOBJ_REMOVE);
  	kobject_del(&e->kobj);
430c62fb2   Jens Axboe   elevator: fix oop...
837
  	e->registered = 0;
bc1c11697   Jens Axboe   [PATCH] elevator ...
838
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
840
  void elv_unregister_queue(struct request_queue *q)
  {
bc1c11697   Jens Axboe   [PATCH] elevator ...
841
842
  	if (q)
  		__elv_unregister_queue(q->elevator);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  }
01effb0dc   Mike Snitzer   block: allow init...
844
  EXPORT_SYMBOL(elv_unregister_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845

2fdd82bd8   Adrian Bunk   block: let elv_re...
846
  void elv_register(struct elevator_type *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847
  {
1ffb96c58   Thibaut VARENE   make elv_register...
848
  	char *def = "";
2a12dcd71   Jens Axboe   [PATCH] elevator:...
849
850
  
  	spin_lock(&elv_list_lock);
ce5244974   Eric Sesterhenn   BUG_ON() Conversi...
851
  	BUG_ON(elevator_find(e->elevator_name));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  	list_add_tail(&e->list, &elv_list);
2a12dcd71   Jens Axboe   [PATCH] elevator:...
853
  	spin_unlock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854

5f0039764   Nate Diller   [BLOCK] elevator:...
855
856
857
  	if (!strcmp(e->elevator_name, chosen_elevator) ||
  			(!*chosen_elevator &&
  			 !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED)))
1ffb96c58   Thibaut VARENE   make elv_register...
858
  				def = " (default)";
4eb166d98   Jens Axboe   block: make eleva...
859
860
861
  	printk(KERN_INFO "io scheduler %s registered%s
  ", e->elevator_name,
  								def);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
862
863
864
865
866
  }
  EXPORT_SYMBOL_GPL(elv_register);
  
  void elv_unregister(struct elevator_type *e)
  {
83521d3eb   Christoph Hellwig   [PATCH] cfq-iosch...
867
868
869
870
871
  	struct task_struct *g, *p;
  
  	/*
  	 * Iterate every thread in the process to remove the io contexts.
  	 */
e17a9489b   Al Viro   [PATCH] stop elv_...
872
873
874
875
  	if (e->ops.trim) {
  		read_lock(&tasklist_lock);
  		do_each_thread(g, p) {
  			task_lock(p);
2d8f61316   Oleg Nesterov   elv_unregister: f...
876
877
  			if (p->io_context)
  				e->ops.trim(p->io_context);
e17a9489b   Al Viro   [PATCH] stop elv_...
878
879
880
881
  			task_unlock(p);
  		} while_each_thread(g, p);
  		read_unlock(&tasklist_lock);
  	}
83521d3eb   Christoph Hellwig   [PATCH] cfq-iosch...
882

2a12dcd71   Jens Axboe   [PATCH] elevator:...
883
  	spin_lock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
884
  	list_del_init(&e->list);
2a12dcd71   Jens Axboe   [PATCH] elevator:...
885
  	spin_unlock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
888
889
890
891
892
  }
  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   Tejun Heo   [BLOCK] Reimpleme...
893
   * one, if the new one fails init for some reason.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
   */
165125e1e   Jens Axboe   [BLOCK] Get rid o...
895
  static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
  {
b374d18a4   Jens Axboe   block: get rid of...
897
  	struct elevator_queue *old_elevator, *e;
bc1c11697   Jens Axboe   [PATCH] elevator ...
898
  	void *data;
5dd531a03   Jens Axboe   block: add functi...
899
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900

cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
901
902
903
  	/*
  	 * Allocate new elevator
  	 */
b5deef901   Jens Axboe   [PATCH] Make sure...
904
  	e = elevator_alloc(q, new_e);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  	if (!e)
5dd531a03   Jens Axboe   block: add functi...
906
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907

bc1c11697   Jens Axboe   [PATCH] elevator ...
908
909
910
  	data = elevator_init_queue(q, e);
  	if (!data) {
  		kobject_put(&e->kobj);
5dd531a03   Jens Axboe   block: add functi...
911
  		return -ENOMEM;
bc1c11697   Jens Axboe   [PATCH] elevator ...
912
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
  	/*
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
914
  	 * Turn on BYPASS and drain all requests w/ elevator private data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
  	 */
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
916
  	spin_lock_irq(q->queue_lock);
f600abe2d   Jens Axboe   block: fix bad sp...
917
  	elv_quiesce_start(q);
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
918

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  	/*
bc1c11697   Jens Axboe   [PATCH] elevator ...
920
  	 * Remember old elevator.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
923
924
  	old_elevator = q->elevator;
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
  	 * attach and start new elevator
  	 */
bc1c11697   Jens Axboe   [PATCH] elevator ...
927
928
929
  	elevator_attach(q, e, data);
  
  	spin_unlock_irq(q->queue_lock);
430c62fb2   Jens Axboe   elevator: fix oop...
930
931
  	if (old_elevator->registered) {
  		__elv_unregister_queue(old_elevator);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932

430c62fb2   Jens Axboe   elevator: fix oop...
933
934
935
936
  		err = elv_register_queue(q);
  		if (err)
  			goto fail_register;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
938
  
  	/*
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
939
  	 * finally exit old elevator and turn off BYPASS.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
941
  	 */
  	elevator_exit(old_elevator);
75ad23bc0   Nick Piggin   block: make queue...
942
  	spin_lock_irq(q->queue_lock);
f600abe2d   Jens Axboe   block: fix bad sp...
943
  	elv_quiesce_end(q);
75ad23bc0   Nick Piggin   block: make queue...
944
  	spin_unlock_irq(q->queue_lock);
4722dc52a   Alan D. Brunelle   Added in elevator...
945
  	blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
5dd531a03   Jens Axboe   block: add functi...
946
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
948
949
950
951
952
953
  
  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   Linus Torvalds   Linux-2.6.12-rc2
954
955
  	q->elevator = old_elevator;
  	elv_register_queue(q);
75ad23bc0   Nick Piggin   block: make queue...
956
957
958
959
  
  	spin_lock_irq(q->queue_lock);
  	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
  	spin_unlock_irq(q->queue_lock);
5dd531a03   Jens Axboe   block: add functi...
960
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  }
5dd531a03   Jens Axboe   block: add functi...
962
963
964
965
  /*
   * Switch this queue to the given IO scheduler.
   */
  int elevator_change(struct request_queue *q, const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
968
  {
  	char elevator_name[ELV_NAME_MAX];
  	struct elevator_type *e;
cd43e26f0   Martin K. Petersen   block: Expose sta...
969
  	if (!q->elevator)
5dd531a03   Jens Axboe   block: add functi...
970
  		return -ENXIO;
cd43e26f0   Martin K. Petersen   block: Expose sta...
971

ee2e992cc   Li Zefan   block: simplify s...
972
  	strlcpy(elevator_name, name, sizeof(elevator_name));
8c2795985   KOSAKI Motohiro   elv_iosched_store...
973
  	e = elevator_get(strstrip(elevator_name));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974
975
976
977
978
  	if (!e) {
  		printk(KERN_ERR "elevator: type %s not found
  ", elevator_name);
  		return -EINVAL;
  	}
2ca7d93bb   Nate Diller   [PATCH] block cle...
979
980
  	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) {
  		elevator_put(e);
5dd531a03   Jens Axboe   block: add functi...
981
  		return 0;
2ca7d93bb   Nate Diller   [PATCH] block cle...
982
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983

5dd531a03   Jens Axboe   block: add functi...
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
  	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   Linus Torvalds   Linux-2.6.12-rc2
1003
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1004
  ssize_t elv_iosched_show(struct request_queue *q, char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
  {
b374d18a4   Jens Axboe   block: get rid of...
1006
  	struct elevator_queue *e = q->elevator;
cd43e26f0   Martin K. Petersen   block: Expose sta...
1007
  	struct elevator_type *elv;
70cee26e0   Matthias Kaehlcke   Use list_for_each...
1008
  	struct elevator_type *__e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
  	int len = 0;
e36f724b4   Mike Snitzer   block: Adjust elv...
1010
  	if (!q->elevator || !blk_queue_stackable(q))
cd43e26f0   Martin K. Petersen   block: Expose sta...
1011
1012
1013
1014
  		return sprintf(name, "none
  ");
  
  	elv = e->elevator_type;
2a12dcd71   Jens Axboe   [PATCH] elevator:...
1015
  	spin_lock(&elv_list_lock);
70cee26e0   Matthias Kaehlcke   Use list_for_each...
1016
  	list_for_each_entry(__e, &elv_list, list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
1018
1019
1020
1021
  		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   Jens Axboe   [PATCH] elevator:...
1022
  	spin_unlock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
1026
1027
  
  	len += sprintf(len+name, "
  ");
  	return len;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1028
1029
  struct request *elv_rb_former_request(struct request_queue *q,
  				      struct request *rq)
2e662b65f   Jens Axboe   [PATCH] elevator:...
1030
1031
1032
1033
1034
1035
1036
1037
  {
  	struct rb_node *rbprev = rb_prev(&rq->rb_node);
  
  	if (rbprev)
  		return rb_entry_rq(rbprev);
  
  	return NULL;
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
1038
  EXPORT_SYMBOL(elv_rb_former_request);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1039
1040
  struct request *elv_rb_latter_request(struct request_queue *q,
  				      struct request *rq)
2e662b65f   Jens Axboe   [PATCH] elevator:...
1041
1042
1043
1044
1045
1046
1047
1048
  {
  	struct rb_node *rbnext = rb_next(&rq->rb_node);
  
  	if (rbnext)
  		return rb_entry_rq(rbnext);
  
  	return NULL;
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
1049
  EXPORT_SYMBOL(elv_rb_latter_request);