Blame view

block/elevator.c 24.1 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>
2056a782f   Jens Axboe   [PATCH] Block que...
34
  #include <linux/blktrace_api.h>
9817064b6   Jens Axboe   [PATCH] elevator:...
35
  #include <linux/hash.h>
0835da67c   Jens Axboe   block: use linux/...
36
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

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

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

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

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

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

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

165125e1e   Jens Axboe   [BLOCK] Get rid o...
169
  static void elevator_attach(struct request_queue *q, struct elevator_queue *eq,
bc1c11697   Jens Axboe   [PATCH] elevator ...
170
171
  			   void *data)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  	q->elevator = eq;
bc1c11697   Jens Axboe   [PATCH] elevator ...
173
  	eq->elevator_data = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  }
484fc254b   Wang Sheng-Hui   elevator: use ELV...
175
  static char chosen_elevator[ELV_NAME_MAX];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176

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

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

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

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

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

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

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

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

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

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

1b47f531e   Jens Axboe   [PATCH] generic d...
396
  	boundary = q->end_sector;
02e031cbc   Christoph Hellwig   block: remove REQ...
397
  	stop_flags = REQ_SOFTBARRIER | REQ_STARTED;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
398
399
  	list_for_each_prev(entry, &q->queue_head) {
  		struct request *pos = list_entry_rq(entry);
33659ebba   Christoph Hellwig   block: remove wra...
400
401
  		if ((rq->cmd_flags & REQ_DISCARD) !=
  		    (pos->cmd_flags & REQ_DISCARD))
e17fc0a1c   David Woodhouse   Allow elevators t...
402
  			break;
783660b2f   Jens Axboe   elevator: don't s...
403
404
  		if (rq_data_dir(rq) != rq_data_dir(pos))
  			break;
4eb166d98   Jens Axboe   block: make eleva...
405
  		if (pos->cmd_flags & stop_flags)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
406
  			break;
83096ebf1   Tejun Heo   block: convert to...
407
408
  		if (blk_rq_pos(rq) >= boundary) {
  			if (blk_rq_pos(pos) < boundary)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
409
410
  				continue;
  		} else {
83096ebf1   Tejun Heo   block: convert to...
411
  			if (blk_rq_pos(pos) >= boundary)
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
412
413
  				break;
  		}
83096ebf1   Tejun Heo   block: convert to...
414
  		if (blk_rq_pos(rq) >= blk_rq_pos(pos))
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
415
416
417
418
419
  			break;
  	}
  
  	list_add(&rq->queuelist, entry);
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
420
  EXPORT_SYMBOL(elv_dispatch_sort);
9817064b6   Jens Axboe   [PATCH] elevator:...
421
  /*
2e662b65f   Jens Axboe   [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   Jens Axboe   [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   Jens Axboe   [PATCH] elevator:...
439
  EXPORT_SYMBOL(elv_dispatch_add_tail);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
440
  int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  {
b374d18a4   Jens Axboe   block: get rid of...
442
  	struct elevator_queue *e = q->elevator;
9817064b6   Jens Axboe   [PATCH] elevator:...
443
  	struct request *__rq;
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
444
  	int ret;
9817064b6   Jens Axboe   [PATCH] elevator:...
445
  	/*
488991e28   Alan D. Brunelle   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   Jens Axboe   [PATCH] elevator:...
455
456
  	 * First try one-hit cache.
  	 */
06b86245c   Tejun Heo   [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   Linus Torvalds   Linux-2.6.12-rc2
464

488991e28   Alan D. Brunelle   block: Added in s...
465
  	if (blk_queue_noxmerges(q))
ac9fafa12   Alan D. Brunelle   block: Skip I/O m...
466
  		return ELEVATOR_NO_MERGE;
9817064b6   Jens Axboe   [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   Linus Torvalds   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   Jens Axboe   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   Jens Axboe   [BLOCK] Get rid o...
513
  void elv_merged_request(struct request_queue *q, struct request *rq, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
  {
b374d18a4   Jens Axboe   block: get rid of...
515
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
  
  	if (e->ops->elevator_merged_fn)
2e662b65f   Jens Axboe   [PATCH] elevator:...
518
  		e->ops->elevator_merged_fn(q, rq, type);
06b86245c   Tejun Heo   [PATCH] 03/05 mov...
519

2e662b65f   Jens Axboe   [PATCH] elevator:...
520
521
  	if (type == ELEVATOR_BACK_MERGE)
  		elv_rqhash_reposition(q, rq);
9817064b6   Jens Axboe   [PATCH] elevator:...
522

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

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

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

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

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

b710a4805   Jens Axboe   block: get rid of...
564
  	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
  }
26308eab6   Jerome Marchand   block: fix incons...
566
  void elv_drain_elevator(struct request_queue *q)
15853af9f   Tejun Heo   [BLOCK] Implement...
567
568
  {
  	static int printed;
e3c78ca52   Tejun Heo   block: reorganize...
569
570
  
  	lockdep_assert_held(q->queue_lock);
15853af9f   Tejun Heo   [BLOCK] Implement...
571
572
  	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
  		;
e3c78ca52   Tejun Heo   block: reorganize...
573
  	if (q->nr_sorted && printed++ < 10) {
15853af9f   Tejun Heo   [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   Jens Axboe   block: fix bad sp...
580
  void elv_quiesce_start(struct request_queue *q)
6c7e8cee6   Jens Axboe   block: elevator q...
581
  {
cd43e26f0   Martin K. Petersen   block: Expose sta...
582
583
  	if (!q->elevator)
  		return;
e3c78ca52   Tejun Heo   block: reorganize...
584
  	spin_lock_irq(q->queue_lock);
6c7e8cee6   Jens Axboe   block: elevator q...
585
  	queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
e3c78ca52   Tejun Heo   block: reorganize...
586
  	spin_unlock_irq(q->queue_lock);
6c7e8cee6   Jens Axboe   block: elevator q...
587

c9a929dde   Tejun Heo   block: fix reques...
588
  	blk_drain_queue(q, false);
6c7e8cee6   Jens Axboe   block: elevator q...
589
  }
f600abe2d   Jens Axboe   block: fix bad sp...
590
  void elv_quiesce_end(struct request_queue *q)
6c7e8cee6   Jens Axboe   block: elevator q...
591
  {
e3c78ca52   Tejun Heo   block: reorganize...
592
  	spin_lock_irq(q->queue_lock);
6c7e8cee6   Jens Axboe   block: elevator q...
593
  	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
e3c78ca52   Tejun Heo   block: reorganize...
594
  	spin_unlock_irq(q->queue_lock);
6c7e8cee6   Jens Axboe   block: elevator q...
595
  }
b710a4805   Jens Axboe   block: get rid of...
596
  void __elv_add_request(struct request_queue *q, struct request *rq, int where)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
  {
5f3ea37c7   Arnaldo Carvalho de Melo   blktrace: port to...
598
  	trace_block_rq_insert(q, rq);
2056a782f   Jens Axboe   [PATCH] Block que...
599

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  	rq->q = q;
b710a4805   Jens Axboe   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   Jens Axboe   elevator: check f...
609
610
  		    (where == ELEVATOR_INSERT_SORT ||
  		     where == ELEVATOR_INSERT_SORT_MERGE))
b710a4805   Jens Axboe   block: get rid of...
611
  		where = ELEVATOR_INSERT_BACK;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
612
  	switch (where) {
28e7d1845   Tejun Heo   block: drop barri...
613
  	case ELEVATOR_INSERT_REQUEUE:
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
614
  	case ELEVATOR_INSERT_FRONT:
4aff5e233   Jens Axboe   [PATCH] Split str...
615
  		rq->cmd_flags |= REQ_SOFTBARRIER;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
616
617
618
619
  		list_add(&rq->queuelist, &q->queue_head);
  		break;
  
  	case ELEVATOR_INSERT_BACK:
4aff5e233   Jens Axboe   [PATCH] Split str...
620
  		rq->cmd_flags |= REQ_SOFTBARRIER;
15853af9f   Tejun Heo   [BLOCK] Implement...
621
  		elv_drain_elevator(q);
8922e16cf   Tejun Heo   [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   Christoph Hellwig   block: add blk_ru...
633
  		__blk_run_queue(q);
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
634
  		break;
5e84ea3a9   Jens Axboe   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   Tejun Heo   [PATCH] 01/05 Imp...
643
  	case ELEVATOR_INSERT_SORT:
33659ebba   Christoph Hellwig   block: remove wra...
644
645
  		BUG_ON(rq->cmd_type != REQ_TYPE_FS &&
  		       !(rq->cmd_flags & REQ_DISCARD));
4aff5e233   Jens Axboe   [PATCH] Split str...
646
  		rq->cmd_flags |= REQ_SORTED;
15853af9f   Tejun Heo   [BLOCK] Implement...
647
  		q->nr_sorted++;
9817064b6   Jens Axboe   [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   Tejun Heo   [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   Tejun Heo   [PATCH] 01/05 Imp...
659
  		break;
ae1b15396   Tejun Heo   block: reimplemen...
660
661
662
663
  	case ELEVATOR_INSERT_FLUSH:
  		rq->cmd_flags |= REQ_SOFTBARRIER;
  		blk_insert_flush(rq);
  		break;
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
664
665
666
  	default:
  		printk(KERN_ERR "%s: bad insertion point %d
  ",
24c03d47d   Harvey Harrison   block: remove rem...
667
  		       __func__, where);
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
668
669
  		BUG();
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
671
  EXPORT_SYMBOL(__elv_add_request);
7eaceacca   Jens Axboe   block: remove per...
672
  void elv_add_request(struct request_queue *q, struct request *rq, int where)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(q->queue_lock, flags);
7eaceacca   Jens Axboe   block: remove per...
677
  	__elv_add_request(q, rq, where);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
  	spin_unlock_irqrestore(q->queue_lock, flags);
  }
2e662b65f   Jens Axboe   [PATCH] elevator:...
680
  EXPORT_SYMBOL(elv_add_request);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
681
  struct request *elv_latter_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
  {
b374d18a4   Jens Axboe   block: get rid of...
683
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
687
688
  	return NULL;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
689
  struct request *elv_former_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
  {
b374d18a4   Jens Axboe   block: get rid of...
691
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
695
696
  	return NULL;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
697
  int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  {
b374d18a4   Jens Axboe   block: get rid of...
699
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
  
  	if (e->ops->elevator_set_req_fn)
cb78b285c   Jens Axboe   [PATCH] Drop usel...
702
  		return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703

c186794db   Mike Snitzer   block: share requ...
704
  	rq->elevator_private[0] = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
  	return 0;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
707
  void elv_put_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
  {
b374d18a4   Jens Axboe   block: get rid of...
709
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
  
  	if (e->ops->elevator_put_req_fn)
bb37b94c6   Jens Axboe   [BLOCK] Cleanup u...
712
  		e->ops->elevator_put_req_fn(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
714
  int elv_may_queue(struct request_queue *q, int rw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  {
b374d18a4   Jens Axboe   block: get rid of...
716
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
  
  	if (e->ops->elevator_may_queue_fn)
cb78b285c   Jens Axboe   [PATCH] Drop usel...
719
  		return e->ops->elevator_may_queue_fn(q, rw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
  
  	return ELV_MQUEUE_MAY;
  }
11914a53d   Mike Anderson   block: Add interf...
723
724
725
  void elv_abort_queue(struct request_queue *q)
  {
  	struct request *rq;
ae1b15396   Tejun Heo   block: reimplemen...
726
  	blk_abort_flushes(q);
11914a53d   Mike Anderson   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   Arnaldo Carvalho de Melo   blktrace: port to...
730
  		trace_block_rq_abort(q, rq);
53c663ce0   Kiyoshi Ueda   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   Tejun Heo   block: implement ...
736
  		__blk_end_request_all(rq, -EIO);
11914a53d   Mike Anderson   block: Add interf...
737
738
739
  	}
  }
  EXPORT_SYMBOL(elv_abort_queue);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
740
  void elv_completed_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  {
b374d18a4   Jens Axboe   block: get rid of...
742
  	struct elevator_queue *e = q->elevator;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
745
746
  
  	/*
  	 * request is released from the driver, io must be done
  	 */
8922e16cf   Tejun Heo   [PATCH] 01/05 Imp...
747
  	if (blk_account_rq(rq)) {
0a7ae2ff0   Jens Axboe   block: change the...
748
  		q->in_flight[rq_is_sync(rq)]--;
33659ebba   Christoph Hellwig   block: remove wra...
749
750
  		if ((rq->cmd_flags & REQ_SORTED) &&
  		    e->ops->elevator_completed_req_fn)
1bc691d35   Tejun Heo   [PATCH] fix queue...
751
752
  			e->ops->elevator_completed_req_fn(q, rq);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  }
3d1ab40f4   Al Viro   [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   Linus Torvalds   Linux-2.6.12-rc2
758
  {
3d1ab40f4   Al Viro   [PATCH] elevator_...
759
  	struct elv_fs_entry *entry = to_elv(attr);
b374d18a4   Jens Axboe   block: get rid of...
760
  	struct elevator_queue *e;
3d1ab40f4   Al Viro   [PATCH] elevator_...
761
762
763
764
  	ssize_t error;
  
  	if (!entry->show)
  		return -EIO;
b374d18a4   Jens Axboe   block: get rid of...
765
  	e = container_of(kobj, struct elevator_queue, kobj);
3d1ab40f4   Al Viro   [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   Linus Torvalds   Linux-2.6.12-rc2
771

3d1ab40f4   Al Viro   [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   Al Viro   [PATCH] elevator_...
776
  	struct elv_fs_entry *entry = to_elv(attr);
b374d18a4   Jens Axboe   block: get rid of...
777
  	struct elevator_queue *e;
3d1ab40f4   Al Viro   [PATCH] elevator_...
778
  	ssize_t error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779

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

b374d18a4   Jens Axboe   block: get rid of...
783
  	e = container_of(kobj, struct elevator_queue, kobj);
3d1ab40f4   Al Viro   [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   Emese Revfy   Driver core: Cons...
789
  static const struct sysfs_ops elv_sysfs_ops = {
3d1ab40f4   Al Viro   [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   Jens Axboe   block: get rid of...
801
  	struct elevator_queue *e = q->elevator;
3d1ab40f4   Al Viro   [PATCH] elevator_...
802
  	int error;
b2d6db587   Greg Kroah-Hartman   Kobject: rename k...
803
  	error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
3d1ab40f4   Al Viro   [PATCH] elevator_...
804
  	if (!error) {
e572ec7e4   Al Viro   [PATCH] fix rmmod...
805
  		struct elv_fs_entry *attr = e->elevator_type->elevator_attrs;
3d1ab40f4   Al Viro   [PATCH] elevator_...
806
  		if (attr) {
e572ec7e4   Al Viro   [PATCH] fix rmmod...
807
808
  			while (attr->attr.name) {
  				if (sysfs_create_file(&e->kobj, &attr->attr))
3d1ab40f4   Al Viro   [PATCH] elevator_...
809
  					break;
e572ec7e4   Al Viro   [PATCH] fix rmmod...
810
  				attr++;
3d1ab40f4   Al Viro   [PATCH] elevator_...
811
812
813
  			}
  		}
  		kobject_uevent(&e->kobj, KOBJ_ADD);
430c62fb2   Jens Axboe   elevator: fix oop...
814
  		e->registered = 1;
3d1ab40f4   Al Viro   [PATCH] elevator_...
815
816
  	}
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
  }
01effb0dc   Mike Snitzer   block: allow init...
818
  EXPORT_SYMBOL(elv_register_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819

b374d18a4   Jens Axboe   block: get rid of...
820
  static void __elv_unregister_queue(struct elevator_queue *e)
bc1c11697   Jens Axboe   [PATCH] elevator ...
821
822
823
  {
  	kobject_uevent(&e->kobj, KOBJ_REMOVE);
  	kobject_del(&e->kobj);
430c62fb2   Jens Axboe   elevator: fix oop...
824
  	e->registered = 0;
bc1c11697   Jens Axboe   [PATCH] elevator ...
825
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
827
  void elv_unregister_queue(struct request_queue *q)
  {
bc1c11697   Jens Axboe   [PATCH] elevator ...
828
829
  	if (q)
  		__elv_unregister_queue(q->elevator);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
  }
01effb0dc   Mike Snitzer   block: allow init...
831
  EXPORT_SYMBOL(elv_unregister_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832

2fdd82bd8   Adrian Bunk   block: let elv_re...
833
  void elv_register(struct elevator_type *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
  {
1ffb96c58   Thibaut VARENE   make elv_register...
835
  	char *def = "";
2a12dcd71   Jens Axboe   [PATCH] elevator:...
836
837
  
  	spin_lock(&elv_list_lock);
ce5244974   Eric Sesterhenn   BUG_ON() Conversi...
838
  	BUG_ON(elevator_find(e->elevator_name));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  	list_add_tail(&e->list, &elv_list);
2a12dcd71   Jens Axboe   [PATCH] elevator:...
840
  	spin_unlock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841

5f0039764   Nate Diller   [BLOCK] elevator:...
842
843
844
  	if (!strcmp(e->elevator_name, chosen_elevator) ||
  			(!*chosen_elevator &&
  			 !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED)))
1ffb96c58   Thibaut VARENE   make elv_register...
845
  				def = " (default)";
4eb166d98   Jens Axboe   block: make eleva...
846
847
848
  	printk(KERN_INFO "io scheduler %s registered%s
  ", e->elevator_name,
  								def);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
850
851
852
853
  }
  EXPORT_SYMBOL_GPL(elv_register);
  
  void elv_unregister(struct elevator_type *e)
  {
83521d3eb   Christoph Hellwig   [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   Al Viro   [PATCH] stop elv_...
859
860
861
862
  	if (e->ops.trim) {
  		read_lock(&tasklist_lock);
  		do_each_thread(g, p) {
  			task_lock(p);
2d8f61316   Oleg Nesterov   elv_unregister: f...
863
864
  			if (p->io_context)
  				e->ops.trim(p->io_context);
e17a9489b   Al Viro   [PATCH] stop elv_...
865
866
867
868
  			task_unlock(p);
  		} while_each_thread(g, p);
  		read_unlock(&tasklist_lock);
  	}
83521d3eb   Christoph Hellwig   [PATCH] cfq-iosch...
869

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

cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
888
889
890
  	/*
  	 * Allocate new elevator
  	 */
b5deef901   Jens Axboe   [PATCH] Make sure...
891
  	e = elevator_alloc(q, new_e);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
892
  	if (!e)
5dd531a03   Jens Axboe   block: add functi...
893
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894

bc1c11697   Jens Axboe   [PATCH] elevator ...
895
896
897
  	data = elevator_init_queue(q, e);
  	if (!data) {
  		kobject_put(&e->kobj);
5dd531a03   Jens Axboe   block: add functi...
898
  		return -ENOMEM;
bc1c11697   Jens Axboe   [PATCH] elevator ...
899
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
  	/*
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
901
  	 * Turn on BYPASS and drain all requests w/ elevator private data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
  	 */
f600abe2d   Jens Axboe   block: fix bad sp...
903
  	elv_quiesce_start(q);
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
904

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  	/*
bc1c11697   Jens Axboe   [PATCH] elevator ...
906
  	 * Remember old elevator.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
  	old_elevator = q->elevator;
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
  	 * attach and start new elevator
  	 */
e3c78ca52   Tejun Heo   block: reorganize...
913
  	spin_lock_irq(q->queue_lock);
bc1c11697   Jens Axboe   [PATCH] elevator ...
914
  	elevator_attach(q, e, data);
bc1c11697   Jens Axboe   [PATCH] elevator ...
915
  	spin_unlock_irq(q->queue_lock);
430c62fb2   Jens Axboe   elevator: fix oop...
916
917
  	if (old_elevator->registered) {
  		__elv_unregister_queue(old_elevator);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918

430c62fb2   Jens Axboe   elevator: fix oop...
919
920
921
922
  		err = elv_register_queue(q);
  		if (err)
  			goto fail_register;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
  
  	/*
cb98fc8bb   Tejun Heo   [BLOCK] Reimpleme...
925
  	 * finally exit old elevator and turn off BYPASS.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
  	 */
  	elevator_exit(old_elevator);
f600abe2d   Jens Axboe   block: fix bad sp...
928
  	elv_quiesce_end(q);
75ad23bc0   Nick Piggin   block: make queue...
929

4722dc52a   Alan D. Brunelle   Added in elevator...
930
  	blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
5dd531a03   Jens Axboe   block: add functi...
931
  	return 0;
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
939
940
  	q->elevator = old_elevator;
  	elv_register_queue(q);
e3c78ca52   Tejun Heo   block: reorganize...
941
  	elv_quiesce_end(q);
75ad23bc0   Nick Piggin   block: make queue...
942

5dd531a03   Jens Axboe   block: add functi...
943
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
  }
5dd531a03   Jens Axboe   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   Linus Torvalds   Linux-2.6.12-rc2
949
950
951
  {
  	char elevator_name[ELV_NAME_MAX];
  	struct elevator_type *e;
cd43e26f0   Martin K. Petersen   block: Expose sta...
952
  	if (!q->elevator)
5dd531a03   Jens Axboe   block: add functi...
953
  		return -ENXIO;
cd43e26f0   Martin K. Petersen   block: Expose sta...
954

ee2e992cc   Li Zefan   block: simplify s...
955
  	strlcpy(elevator_name, name, sizeof(elevator_name));
8c2795985   KOSAKI Motohiro   elv_iosched_store...
956
  	e = elevator_get(strstrip(elevator_name));
1da177e4c   Linus Torvalds   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   Nate Diller   [PATCH] block cle...
962
963
  	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) {
  		elevator_put(e);
5dd531a03   Jens Axboe   block: add functi...
964
  		return 0;
2ca7d93bb   Nate Diller   [PATCH] block cle...
965
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966

5dd531a03   Jens Axboe   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   Linus Torvalds   Linux-2.6.12-rc2
986
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
987
  ssize_t elv_iosched_show(struct request_queue *q, char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
  {
b374d18a4   Jens Axboe   block: get rid of...
989
  	struct elevator_queue *e = q->elevator;
cd43e26f0   Martin K. Petersen   block: Expose sta...
990
  	struct elevator_type *elv;
70cee26e0   Matthias Kaehlcke   Use list_for_each...
991
  	struct elevator_type *__e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
  	int len = 0;
e36f724b4   Mike Snitzer   block: Adjust elv...
993
  	if (!q->elevator || !blk_queue_stackable(q))
cd43e26f0   Martin K. Petersen   block: Expose sta...
994
995
996
997
  		return sprintf(name, "none
  ");
  
  	elv = e->elevator_type;
2a12dcd71   Jens Axboe   [PATCH] elevator:...
998
  	spin_lock(&elv_list_lock);
70cee26e0   Matthias Kaehlcke   Use list_for_each...
999
  	list_for_each_entry(__e, &elv_list, list) {
1da177e4c   Linus Torvalds   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   Jens Axboe   [PATCH] elevator:...
1005
  	spin_unlock(&elv_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
1007
1008
1009
1010
  
  	len += sprintf(len+name, "
  ");
  	return len;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1011
1012
  struct request *elv_rb_former_request(struct request_queue *q,
  				      struct request *rq)
2e662b65f   Jens Axboe   [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   Jens Axboe   [PATCH] elevator:...
1021
  EXPORT_SYMBOL(elv_rb_former_request);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1022
1023
  struct request *elv_rb_latter_request(struct request_queue *q,
  				      struct request *rq)
2e662b65f   Jens Axboe   [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   Jens Axboe   [PATCH] elevator:...
1032
  EXPORT_SYMBOL(elv_rb_latter_request);