Blame view

block/cfq-iosched.c 58.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   *  CFQ, or complete fairness queueing, disk scheduler.
   *
   *  Based on ideas from a previously unfinished io
   *  scheduler (round robin per-process disk scheduling) and Andrea Arcangeli.
   *
   *  Copyright (C) 2003 Jens Axboe <axboe@suse.de>
   */
  #include <linux/kernel.h>
  #include <linux/fs.h>
  #include <linux/blkdev.h>
  #include <linux/elevator.h>
  #include <linux/bio.h>
  #include <linux/config.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/compiler.h>
  #include <linux/hash.h>
  #include <linux/rbtree.h>
  #include <linux/mempool.h>
22e2c507c   Jens Axboe   [PATCH] Update cf...
22
23
  #include <linux/ioprio.h>
  #include <linux/writeback.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
  
  /*
   * tunables
   */
64100099e   Arjan van de Ven   [BLOCK] mark some...
28
29
30
31
32
  static const int cfq_quantum = 4;		/* max queue in one round of service */
  static const int cfq_queued = 8;		/* minimum rq allocate limit per-queue*/
  static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
  static const int cfq_back_max = 16 * 1024;	/* maximum backwards seek, in KiB */
  static const int cfq_back_penalty = 2;		/* penalty of a backwards seek */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

64100099e   Arjan van de Ven   [BLOCK] mark some...
34
  static const int cfq_slice_sync = HZ / 10;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
35
  static int cfq_slice_async = HZ / 25;
64100099e   Arjan van de Ven   [BLOCK] mark some...
36
  static const int cfq_slice_async_rq = 2;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
37
  static int cfq_slice_idle = HZ / 100;
22e2c507c   Jens Axboe   [PATCH] Update cf...
38
39
40
41
42
  
  #define CFQ_IDLE_GRACE		(HZ / 10)
  #define CFQ_SLICE_SCALE		(5)
  
  #define CFQ_KEY_ASYNC		(0)
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
43
  #define CFQ_KEY_ANY		(0xffff)
22e2c507c   Jens Axboe   [PATCH] Update cf...
44
45
46
47
  
  /*
   * disable queueing at the driver/hardware level
   */
64100099e   Arjan van de Ven   [BLOCK] mark some...
48
  static const int cfq_max_depth = 2;
22e2c507c   Jens Axboe   [PATCH] Update cf...
49

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  /*
   * for the hash of cfqq inside the cfqd
   */
  #define CFQ_QHASH_SHIFT		6
  #define CFQ_QHASH_ENTRIES	(1 << CFQ_QHASH_SHIFT)
  #define list_entry_qhash(entry)	hlist_entry((entry), struct cfq_queue, cfq_hash)
  
  /*
   * for the hash of crq inside the cfqq
   */
  #define CFQ_MHASH_SHIFT		6
  #define CFQ_MHASH_BLOCK(sec)	((sec) >> 3)
  #define CFQ_MHASH_ENTRIES	(1 << CFQ_MHASH_SHIFT)
  #define CFQ_MHASH_FN(sec)	hash_long(CFQ_MHASH_BLOCK(sec), CFQ_MHASH_SHIFT)
  #define rq_hash_key(rq)		((rq)->sector + (rq)->nr_sectors)
  #define list_entry_hash(ptr)	hlist_entry((ptr), struct cfq_rq, hash)
  
  #define list_entry_cfqq(ptr)	list_entry((ptr), struct cfq_queue, cfq_list)
22e2c507c   Jens Axboe   [PATCH] Update cf...
68
  #define list_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  
  #define RQ_DATA(rq)		(rq)->elevator_private
  
  /*
   * rb-tree defines
   */
  #define RB_NONE			(2)
  #define RB_EMPTY(node)		((node)->rb_node == NULL)
  #define RB_CLEAR_COLOR(node)	(node)->rb_color = RB_NONE
  #define RB_CLEAR(node)		do {	\
  	(node)->rb_parent = NULL;	\
  	RB_CLEAR_COLOR((node));		\
  	(node)->rb_right = NULL;	\
  	(node)->rb_left = NULL;		\
  } while (0)
  #define RB_CLEAR_ROOT(root)	((root)->rb_node = NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  #define rb_entry_crq(node)	rb_entry((node), struct cfq_rq, rb_node)
  #define rq_rb_key(rq)		(rq)->sector
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
  static kmem_cache_t *crq_pool;
  static kmem_cache_t *cfq_pool;
  static kmem_cache_t *cfq_ioc_pool;
22e2c507c   Jens Axboe   [PATCH] Update cf...
90
91
92
93
  #define CFQ_PRIO_LISTS		IOPRIO_BE_NR
  #define cfq_class_idle(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
  #define cfq_class_be(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_BE)
  #define cfq_class_rt(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
94
95
96
97
98
99
100
101
102
103
  #define ASYNC			(0)
  #define SYNC			(1)
  
  #define cfq_cfqq_dispatched(cfqq)	\
  	((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC])
  
  #define cfq_cfqq_class_sync(cfqq)	((cfqq)->key != CFQ_KEY_ASYNC)
  
  #define cfq_cfqq_sync(cfqq)		\
  	(cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC])
22e2c507c   Jens Axboe   [PATCH] Update cf...
104
105
106
107
  
  /*
   * Per block device queue structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  struct cfq_data {
22e2c507c   Jens Axboe   [PATCH] Update cf...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  	atomic_t ref;
  	request_queue_t *queue;
  
  	/*
  	 * rr list of queues with requests and the count of them
  	 */
  	struct list_head rr_list[CFQ_PRIO_LISTS];
  	struct list_head busy_rr;
  	struct list_head cur_rr;
  	struct list_head idle_rr;
  	unsigned int busy_queues;
  
  	/*
  	 * non-ordered list of empty cfqq's
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  	struct list_head empty_list;
22e2c507c   Jens Axboe   [PATCH] Update cf...
125
126
127
  	/*
  	 * cfqq lookup hash
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  	struct hlist_head *cfq_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129

22e2c507c   Jens Axboe   [PATCH] Update cf...
130
131
132
133
  	/*
  	 * global crq hash for all queues
  	 */
  	struct hlist_head *crq_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  
  	unsigned int max_queued;
22e2c507c   Jens Axboe   [PATCH] Update cf...
136
  	mempool_t *crq_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

22e2c507c   Jens Axboe   [PATCH] Update cf...
138
  	int rq_in_driver;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

22e2c507c   Jens Axboe   [PATCH] Update cf...
140
141
142
143
144
145
146
147
  	/*
  	 * schedule slice state info
  	 */
  	/*
  	 * idle window management
  	 */
  	struct timer_list idle_slice_timer;
  	struct work_struct unplug_work;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148

22e2c507c   Jens Axboe   [PATCH] Update cf...
149
150
151
152
153
154
  	struct cfq_queue *active_queue;
  	struct cfq_io_context *active_cic;
  	int cur_prio, cur_end_prio;
  	unsigned int dispatch_slice;
  
  	struct timer_list idle_class_timer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
  
  	sector_t last_sector;
22e2c507c   Jens Axboe   [PATCH] Update cf...
157
  	unsigned long last_end_request;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158

22e2c507c   Jens Axboe   [PATCH] Update cf...
159
  	unsigned int rq_starved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
164
165
  
  	/*
  	 * tunables, see top of file
  	 */
  	unsigned int cfq_quantum;
  	unsigned int cfq_queued;
22e2c507c   Jens Axboe   [PATCH] Update cf...
166
  	unsigned int cfq_fifo_expire[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  	unsigned int cfq_back_penalty;
  	unsigned int cfq_back_max;
22e2c507c   Jens Axboe   [PATCH] Update cf...
169
170
171
172
  	unsigned int cfq_slice[2];
  	unsigned int cfq_slice_async_rq;
  	unsigned int cfq_slice_idle;
  	unsigned int cfq_max_depth;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
174
175
176
  /*
   * Per process-grouping structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
180
181
  struct cfq_queue {
  	/* reference count */
  	atomic_t ref;
  	/* parent cfq_data */
  	struct cfq_data *cfqd;
22e2c507c   Jens Axboe   [PATCH] Update cf...
182
  	/* cfqq lookup hash */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  	struct hlist_node cfq_hash;
  	/* hash key */
22e2c507c   Jens Axboe   [PATCH] Update cf...
185
  	unsigned int key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
195
196
  	/* on either rr or empty list of cfqd */
  	struct list_head cfq_list;
  	/* sorted list of pending requests */
  	struct rb_root sort_list;
  	/* if fifo isn't expired, next request to serve */
  	struct cfq_rq *next_crq;
  	/* requests queued in sort_list */
  	int queued[2];
  	/* currently allocated requests */
  	int allocated[2];
  	/* fifo list of requests in sort_list */
22e2c507c   Jens Axboe   [PATCH] Update cf...
197
  	struct list_head fifo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

22e2c507c   Jens Axboe   [PATCH] Update cf...
199
200
201
202
  	unsigned long slice_start;
  	unsigned long slice_end;
  	unsigned long slice_left;
  	unsigned long service_last;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
204
205
  	/* number of requests that are on the dispatch list */
  	int on_dispatch[2];
22e2c507c   Jens Axboe   [PATCH] Update cf...
206
207
208
209
  
  	/* io prio of this group */
  	unsigned short ioprio, org_ioprio;
  	unsigned short ioprio_class, org_ioprio_class;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
210
211
  	/* various state flags, see below */
  	unsigned int flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
215
216
217
218
219
220
221
  };
  
  struct cfq_rq {
  	struct rb_node rb_node;
  	sector_t rb_key;
  	struct request *request;
  	struct hlist_node hash;
  
  	struct cfq_queue *cfq_queue;
  	struct cfq_io_context *io_context;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
222
  	unsigned int crq_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  };
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  enum cfqq_state_flags {
  	CFQ_CFQQ_FLAG_on_rr = 0,
  	CFQ_CFQQ_FLAG_wait_request,
  	CFQ_CFQQ_FLAG_must_alloc,
  	CFQ_CFQQ_FLAG_must_alloc_slice,
  	CFQ_CFQQ_FLAG_must_dispatch,
  	CFQ_CFQQ_FLAG_fifo_expire,
  	CFQ_CFQQ_FLAG_idle_window,
  	CFQ_CFQQ_FLAG_prio_changed,
  	CFQ_CFQQ_FLAG_expired,
  };
  
  #define CFQ_CFQQ_FNS(name)						\
  static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq)		\
  {									\
  	cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name);			\
  }									\
  static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq)	\
  {									\
  	cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name);			\
  }									\
  static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq)		\
  {									\
  	return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0;	\
  }
  
  CFQ_CFQQ_FNS(on_rr);
  CFQ_CFQQ_FNS(wait_request);
  CFQ_CFQQ_FNS(must_alloc);
  CFQ_CFQQ_FNS(must_alloc_slice);
  CFQ_CFQQ_FNS(must_dispatch);
  CFQ_CFQQ_FNS(fifo_expire);
  CFQ_CFQQ_FNS(idle_window);
  CFQ_CFQQ_FNS(prio_changed);
  CFQ_CFQQ_FNS(expired);
  #undef CFQ_CFQQ_FNS
  
  enum cfq_rq_state_flags {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
262
  	CFQ_CRQ_FLAG_is_sync = 0,
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  };
  
  #define CFQ_CRQ_FNS(name)						\
  static inline void cfq_mark_crq_##name(struct cfq_rq *crq)		\
  {									\
  	crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name);			\
  }									\
  static inline void cfq_clear_crq_##name(struct cfq_rq *crq)		\
  {									\
  	crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name);			\
  }									\
  static inline int cfq_crq_##name(const struct cfq_rq *crq)		\
  {									\
  	return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0;	\
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
278
  CFQ_CRQ_FNS(is_sync);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
279
280
281
  #undef CFQ_CRQ_FNS
  
  static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
282
  static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  static void cfq_put_cfqd(struct cfq_data *cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
284
  #define process_sync(tsk)	((tsk)->flags & PF_SYNCWRITE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
291
292
  
  /*
   * lots of deadline iosched dupes, can be abstracted later...
   */
  static inline void cfq_del_crq_hash(struct cfq_rq *crq)
  {
  	hlist_del_init(&crq->hash);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
  static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
  {
  	const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
302
303
304
305
306
  	hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]);
  }
  
  static struct request *cfq_find_rq_hash(struct cfq_data *cfqd, sector_t offset)
  {
  	struct hlist_head *hash_list = &cfqd->crq_hash[CFQ_MHASH_FN(offset)];
  	struct hlist_node *entry, *next;
  
  	hlist_for_each_safe(entry, next, hash_list) {
  		struct cfq_rq *crq = list_entry_hash(entry);
  		struct request *__rq = crq->request;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
311
312
313
314
315
316
317
  		if (!rq_mergeable(__rq)) {
  			cfq_del_crq_hash(crq);
  			continue;
  		}
  
  		if (rq_hash_key(__rq) == offset)
  			return __rq;
  	}
  
  	return NULL;
  }
99f95e528   Andrew Morton   [PATCH] cfq build...
318
319
320
321
322
323
  /*
   * scheduler run of queue, if there are requests pending and no one in the
   * driver that will restart queueing
   */
  static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
324
  	if (!cfqd->rq_in_driver && cfqd->busy_queues)
99f95e528   Andrew Morton   [PATCH] cfq build...
325
326
327
328
329
330
  		kblockd_schedule_work(&cfqd->unplug_work);
  }
  
  static int cfq_queue_empty(request_queue_t *q)
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
331
  	return !cfqd->busy_queues;
99f95e528   Andrew Morton   [PATCH] cfq build...
332
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  /*
   * Lifted from AS - choose which of crq1 and crq2 that is best served now.
   * We choose the request that is closest to the head right now. Distance
   * behind the head are penalized and only allowed to a certain extent.
   */
  static struct cfq_rq *
  cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
  {
  	sector_t last, s1, s2, d1 = 0, d2 = 0;
  	int r1_wrap = 0, r2_wrap = 0;	/* requests are behind the disk head */
  	unsigned long back_max;
  
  	if (crq1 == NULL || crq1 == crq2)
  		return crq2;
  	if (crq2 == NULL)
  		return crq1;
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
349

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
350
351
352
  	if (cfq_crq_is_sync(crq1) && !cfq_crq_is_sync(crq2))
  		return crq1;
  	else if (cfq_crq_is_sync(crq2) && !cfq_crq_is_sync(crq1))
22e2c507c   Jens Axboe   [PATCH] Update cf...
353
  		return crq2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
358
  
  	s1 = crq1->request->sector;
  	s2 = crq2->request->sector;
  
  	last = cfqd->last_sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
  	/*
  	 * by definition, 1KiB is 2 sectors
  	 */
  	back_max = cfqd->cfq_back_max * 2;
  
  	/*
  	 * Strict one way elevator _except_ in the case where we allow
  	 * short backward seeks which are biased as twice the cost of a
  	 * similar forward seek.
  	 */
  	if (s1 >= last)
  		d1 = s1 - last;
  	else if (s1 + back_max >= last)
  		d1 = (last - s1) * cfqd->cfq_back_penalty;
  	else
  		r1_wrap = 1;
  
  	if (s2 >= last)
  		d2 = s2 - last;
  	else if (s2 + back_max >= last)
  		d2 = (last - s2) * cfqd->cfq_back_penalty;
  	else
  		r2_wrap = 1;
  
  	/* Found required data */
  	if (!r1_wrap && r2_wrap)
  		return crq1;
  	else if (!r2_wrap && r1_wrap)
  		return crq2;
  	else if (r1_wrap && r2_wrap) {
  		/* both behind the head */
  		if (s1 <= s2)
  			return crq1;
  		else
  			return crq2;
  	}
  
  	/* Both requests in front of the head */
  	if (d1 < d2)
  		return crq1;
  	else if (d2 < d1)
  		return crq2;
  	else {
  		if (s1 >= s2)
  			return crq1;
  		else
  			return crq2;
  	}
  }
  
  /*
   * would be nice to take fifo expire time into account as well
   */
  static struct cfq_rq *
  cfq_find_next_crq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		  struct cfq_rq *last)
  {
  	struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
  	struct rb_node *rbnext, *rbprev;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
418
  	if (!(rbnext = rb_next(&last->rb_node))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  		rbnext = rb_first(&cfqq->sort_list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
420
421
422
  		if (rbnext == &last->rb_node)
  			rbnext = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  
  	rbprev = rb_prev(&last->rb_node);
  
  	if (rbprev)
  		crq_prev = rb_entry_crq(rbprev);
  	if (rbnext)
  		crq_next = rb_entry_crq(rbnext);
  
  	return cfq_choose_req(cfqd, crq_next, crq_prev);
  }
  
  static void cfq_update_next_crq(struct cfq_rq *crq)
  {
  	struct cfq_queue *cfqq = crq->cfq_queue;
  
  	if (cfqq->next_crq == crq)
  		cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq);
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
441
  static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
443
444
  	struct cfq_data *cfqd = cfqq->cfqd;
  	struct list_head *list, *entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
446
  	BUG_ON(!cfq_cfqq_on_rr(cfqq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447

22e2c507c   Jens Axboe   [PATCH] Update cf...
448
  	list_del(&cfqq->cfq_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449

22e2c507c   Jens Axboe   [PATCH] Update cf...
450
451
452
453
454
455
456
457
458
459
460
461
  	if (cfq_class_rt(cfqq))
  		list = &cfqd->cur_rr;
  	else if (cfq_class_idle(cfqq))
  		list = &cfqd->idle_rr;
  	else {
  		/*
  		 * if cfqq has requests in flight, don't allow it to be
  		 * found in cfq_set_active_queue before it has finished them.
  		 * this is done to increase fairness between a process that
  		 * has lots of io pending vs one that only generates one
  		 * sporadically or synchronously
  		 */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
462
  		if (cfq_cfqq_dispatched(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
463
464
465
  			list = &cfqd->busy_rr;
  		else
  			list = &cfqd->rr_list[cfqq->ioprio];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
467
468
469
470
471
472
  	/*
  	 * if queue was preempted, just add to front to be fair. busy_rr
  	 * isn't sorted.
  	 */
  	if (preempted || list == &cfqd->busy_rr) {
  		list_add(&cfqq->cfq_list, list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  		return;
22e2c507c   Jens Axboe   [PATCH] Update cf...
474
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
  
  	/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
477
  	 * sort by when queue was last serviced
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  	 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
479
480
  	entry = list;
  	while ((entry = entry->prev) != list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  		struct cfq_queue *__cfqq = list_entry_cfqq(entry);
22e2c507c   Jens Axboe   [PATCH] Update cf...
482
483
484
  		if (!__cfqq->service_last)
  			break;
  		if (time_before(__cfqq->service_last, cfqq->service_last))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
490
491
492
  	}
  
  	list_add(&cfqq->cfq_list, entry);
  }
  
  /*
   * add to busy list of queues for service, trying to be fair in ordering
22e2c507c   Jens Axboe   [PATCH] Update cf...
493
   * the pending list according to last request service
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
   */
  static inline void
b4878f245   Jens Axboe   [PATCH] 02/05: up...
496
  cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
498
499
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
  	cfq_mark_cfqq_on_rr(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  	cfqd->busy_queues++;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
501
  	cfq_resort_rr_list(cfqq, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
  }
  
  static inline void
  cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
507
508
  	BUG_ON(!cfq_cfqq_on_rr(cfqq));
  	cfq_clear_cfqq_on_rr(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
509
  	list_move(&cfqq->cfq_list, &cfqd->empty_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
514
515
516
517
518
519
520
  
  	BUG_ON(!cfqd->busy_queues);
  	cfqd->busy_queues--;
  }
  
  /*
   * rb tree support functions
   */
  static inline void cfq_del_crq_rb(struct cfq_rq *crq)
  {
  	struct cfq_queue *cfqq = crq->cfq_queue;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
521
522
  	struct cfq_data *cfqd = cfqq->cfqd;
  	const int sync = cfq_crq_is_sync(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523

b4878f245   Jens Axboe   [PATCH] 02/05: up...
524
525
  	BUG_ON(!cfqq->queued[sync]);
  	cfqq->queued[sync]--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526

b4878f245   Jens Axboe   [PATCH] 02/05: up...
527
  	cfq_update_next_crq(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528

b4878f245   Jens Axboe   [PATCH] 02/05: up...
529
530
  	rb_erase(&crq->rb_node, &cfqq->sort_list);
  	RB_CLEAR_COLOR(&crq->rb_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531

b4878f245   Jens Axboe   [PATCH] 02/05: up...
532
533
  	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
  		cfq_del_cfqq_rr(cfqd, cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
  }
  
  static struct cfq_rq *
  __cfq_add_crq_rb(struct cfq_rq *crq)
  {
  	struct rb_node **p = &crq->cfq_queue->sort_list.rb_node;
  	struct rb_node *parent = NULL;
  	struct cfq_rq *__crq;
  
  	while (*p) {
  		parent = *p;
  		__crq = rb_entry_crq(parent);
  
  		if (crq->rb_key < __crq->rb_key)
  			p = &(*p)->rb_left;
  		else if (crq->rb_key > __crq->rb_key)
  			p = &(*p)->rb_right;
  		else
  			return __crq;
  	}
  
  	rb_link_node(&crq->rb_node, parent, p);
  	return NULL;
  }
  
  static void cfq_add_crq_rb(struct cfq_rq *crq)
  {
  	struct cfq_queue *cfqq = crq->cfq_queue;
  	struct cfq_data *cfqd = cfqq->cfqd;
  	struct request *rq = crq->request;
  	struct cfq_rq *__alias;
  
  	crq->rb_key = rq_rb_key(rq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
567
  	cfqq->queued[cfq_crq_is_sync(crq)]++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
572
573
  
  	/*
  	 * looks a little odd, but the first insert might return an alias.
  	 * if that happens, put the alias on the dispatch list
  	 */
  	while ((__alias = __cfq_add_crq_rb(crq)) != NULL)
b4878f245   Jens Axboe   [PATCH] 02/05: up...
574
  		cfq_dispatch_insert(cfqd->queue, __alias);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
  
  	rb_insert_color(&crq->rb_node, &cfqq->sort_list);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
577
  	if (!cfq_cfqq_on_rr(cfqq))
b4878f245   Jens Axboe   [PATCH] 02/05: up...
578
  		cfq_add_cfqq_rr(cfqd, cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
582
583
584
585
586
587
588
  
  	/*
  	 * check if this request is a better next-serve candidate
  	 */
  	cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
  }
  
  static inline void
  cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq)
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
589
590
  	rb_erase(&crq->rb_node, &cfqq->sort_list);
  	cfqq->queued[cfq_crq_is_sync(crq)]--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
  
  	cfq_add_crq_rb(crq);
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
594
  static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
596
  	struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
  	struct rb_node *n;
  
  	if (!cfqq)
  		goto out;
  
  	n = cfqq->sort_list.rb_node;
  	while (n) {
  		struct cfq_rq *crq = rb_entry_crq(n);
  
  		if (sector < crq->rb_key)
  			n = n->rb_left;
  		else if (sector > crq->rb_key)
  			n = n->rb_right;
  		else
  			return crq->request;
  	}
  
  out:
  	return NULL;
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
617
  static void cfq_activate_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
619
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
620

b4878f245   Jens Axboe   [PATCH] 02/05: up...
621
  	cfqd->rq_in_driver++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
623
  static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
625
626
627
628
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  
  	WARN_ON(!cfqd->rq_in_driver);
  	cfqd->rq_in_driver--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
630
  static void cfq_remove_request(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
  {
  	struct cfq_rq *crq = RQ_DATA(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
633
634
  	list_del_init(&rq->queuelist);
  	cfq_del_crq_rb(crq);
98b11471d   Tejun Heo   [PATCH] 04/05 rem...
635
  	cfq_del_crq_hash(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
639
640
641
642
643
  }
  
  static int
  cfq_merge(request_queue_t *q, struct request **req, struct bio *bio)
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct request *__rq;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  	__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
22e2c507c   Jens Axboe   [PATCH] Update cf...
645
646
647
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
  		ret = ELEVATOR_BACK_MERGE;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
650
  	}
  
  	__rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
22e2c507c   Jens Axboe   [PATCH] Update cf...
651
652
653
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
  		ret = ELEVATOR_FRONT_MERGE;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
  	}
  
  	return ELEVATOR_NO_MERGE;
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
664
665
666
667
668
  	*req = __rq;
  	return ret;
  }
  
  static void cfq_merged_request(request_queue_t *q, struct request *req)
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct cfq_rq *crq = RQ_DATA(req);
  
  	cfq_del_crq_hash(crq);
  	cfq_add_crq_hash(cfqd, crq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
669
  	if (rq_rb_key(req) != crq->rb_key) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
671
672
673
674
  		struct cfq_queue *cfqq = crq->cfq_queue;
  
  		cfq_update_next_crq(crq);
  		cfq_reposition_crq_rb(cfqq, crq);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
678
679
680
  }
  
  static void
  cfq_merged_requests(request_queue_t *q, struct request *rq,
  		    struct request *next)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  	cfq_merged_request(q, rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
682
683
684
685
686
687
  	/*
  	 * reposition in fifo if next is older than rq
  	 */
  	if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
  	    time_before(next->start_time, rq->start_time))
  		list_move(&rq->queuelist, &next->queuelist);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
688
  	cfq_remove_request(next);
22e2c507c   Jens Axboe   [PATCH] Update cf...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
  }
  
  static inline void
  __cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	if (cfqq) {
  		/*
  		 * stop potential idle class queues waiting service
  		 */
  		del_timer(&cfqd->idle_class_timer);
  
  		cfqq->slice_start = jiffies;
  		cfqq->slice_end = 0;
  		cfqq->slice_left = 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
703
704
705
  		cfq_clear_cfqq_must_alloc_slice(cfqq);
  		cfq_clear_cfqq_fifo_expire(cfqq);
  		cfq_clear_cfqq_expired(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
  	}
  
  	cfqd->active_queue = cfqq;
  }
  
  /*
   * 0
   * 0,1
   * 0,1,2
   * 0,1,2,3
   * 0,1,2,3,4
   * 0,1,2,3,4,5
   * 0,1,2,3,4,5,6
   * 0,1,2,3,4,5,6,7
   */
  static int cfq_get_next_prio_level(struct cfq_data *cfqd)
  {
  	int prio, wrap;
  
  	prio = -1;
  	wrap = 0;
  	do {
  		int p;
  
  		for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) {
  			if (!list_empty(&cfqd->rr_list[p])) {
  				prio = p;
  				break;
  			}
  		}
  
  		if (prio != -1)
  			break;
  		cfqd->cur_prio = 0;
  		if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) {
  			cfqd->cur_end_prio = 0;
  			if (wrap)
  				break;
  			wrap = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
  	} while (1);
  
  	if (unlikely(prio == -1))
  		return -1;
  
  	BUG_ON(prio >= CFQ_PRIO_LISTS);
  
  	list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr);
  
  	cfqd->cur_prio = prio + 1;
  	if (cfqd->cur_prio > cfqd->cur_end_prio) {
  		cfqd->cur_end_prio = cfqd->cur_prio;
  		cfqd->cur_prio = 0;
  	}
  	if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) {
  		cfqd->cur_prio = 0;
  		cfqd->cur_end_prio = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
764
765
  	return prio;
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
766
  static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
22e2c507c   Jens Axboe   [PATCH] Update cf...
767
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
768
769
770
771
772
773
774
775
776
777
  	struct cfq_queue *cfqq;
  
  	/*
  	 * if current queue is expired but not done with its requests yet,
  	 * wait for that to happen
  	 */
  	if ((cfqq = cfqd->active_queue) != NULL) {
  		if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq))
  			return NULL;
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  
  	/*
  	 * if current list is non-empty, grab first entry. if it is empty,
  	 * get next prio level and grab first entry then if any are spliced
  	 */
  	if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1)
  		cfqq = list_entry_cfqq(cfqd->cur_rr.next);
  
  	/*
  	 * if we have idle queues and no rt or be queues had pending
  	 * requests, either allow immediate service if the grace period
  	 * has passed or arm the idle grace timer
  	 */
  	if (!cfqq && !list_empty(&cfqd->idle_rr)) {
  		unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
  
  		if (time_after_eq(jiffies, end))
  			cfqq = list_entry_cfqq(cfqd->idle_rr.next);
  		else
  			mod_timer(&cfqd->idle_class_timer, end);
  	}
  
  	__cfq_set_active_queue(cfqd, cfqq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
801
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
802
803
804
805
806
  }
  
  /*
   * current cfqq expired its slice (or was too idle), select new one
   */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
807
808
809
  static void
  __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		    int preempted)
22e2c507c   Jens Axboe   [PATCH] Update cf...
810
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
811
  	unsigned long now = jiffies;
22e2c507c   Jens Axboe   [PATCH] Update cf...
812

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
813
814
  	if (cfq_cfqq_wait_request(cfqq))
  		del_timer(&cfqd->idle_slice_timer);
22e2c507c   Jens Axboe   [PATCH] Update cf...
815

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
816
817
  	if (!preempted && !cfq_cfqq_dispatched(cfqq))
  		cfqq->service_last = now;
22e2c507c   Jens Axboe   [PATCH] Update cf...
818

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
819
820
  	cfq_clear_cfqq_must_dispatch(cfqq);
  	cfq_clear_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
821

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
822
823
824
825
  	/*
  	 * store what was left of this slice, if the queue idled out
  	 * or was preempted
  	 */
b740d98f5   Tejun Heo   [BLOCK] cfq-iosch...
826
827
  	if (time_after(cfqq->slice_end, now))
  		cfqq->slice_left = cfqq->slice_end - now;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
828
829
  	else
  		cfqq->slice_left = 0;
22e2c507c   Jens Axboe   [PATCH] Update cf...
830

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
831
832
  	if (cfq_cfqq_on_rr(cfqq))
  		cfq_resort_rr_list(cfqq, preempted);
22e2c507c   Jens Axboe   [PATCH] Update cf...
833

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
834
  	if (cfqq == cfqd->active_queue)
22e2c507c   Jens Axboe   [PATCH] Update cf...
835
  		cfqd->active_queue = NULL;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
836
837
838
  	if (cfqd->active_cic) {
  		put_io_context(cfqd->active_cic->ioc);
  		cfqd->active_cic = NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
839
840
841
842
  	}
  
  	cfqd->dispatch_slice = 0;
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
  static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted)
  {
  	struct cfq_queue *cfqq = cfqd->active_queue;
  
  	if (cfqq) {
  		/*
  		 * use deferred expiry, if there are requests in progress as
  		 * not to disturb the slice of the next queue
  		 */
  		if (cfq_cfqq_dispatched(cfqq))
  			cfq_mark_cfqq_expired(cfqq);
  		else
  			__cfq_slice_expired(cfqd, cfqq, preempted);
  	}
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
858
859
860
861
862
863
864
865
866
867
868
  static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  
  {
  	WARN_ON(!RB_EMPTY(&cfqq->sort_list));
  	WARN_ON(cfqq != cfqd->active_queue);
  
  	/*
  	 * idle is disabled, either manually or by past process history
  	 */
  	if (!cfqd->cfq_slice_idle)
  		return 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
869
  	if (!cfq_cfqq_idle_window(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
870
871
872
873
874
875
  		return 0;
  	/*
  	 * task has exited, don't wait
  	 */
  	if (cfqd->active_cic && !cfqd->active_cic->ioc->task)
  		return 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
876
877
  	cfq_mark_cfqq_must_dispatch(cfqq);
  	cfq_mark_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
878
879
  
  	if (!timer_pending(&cfqd->idle_slice_timer)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
880
  		unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
22e2c507c   Jens Axboe   [PATCH] Update cf...
881

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
882
  		cfqd->idle_slice_timer.expires = jiffies + slice_left;
22e2c507c   Jens Axboe   [PATCH] Update cf...
883
884
885
886
  		add_timer(&cfqd->idle_slice_timer);
  	}
  
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
888
  static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
890
891
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct cfq_queue *cfqq = crq->cfq_queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
892
893
  
  	cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
894
  	cfq_remove_request(crq->request);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
895
  	cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
896
  	elv_dispatch_sort(q, crq->request);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
903
904
  }
  
  /*
   * return expired entry, or NULL to just start from scratch in rbtree
   */
  static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq)
  {
  	struct cfq_data *cfqd = cfqq->cfqd;
22e2c507c   Jens Axboe   [PATCH] Update cf...
905
  	struct request *rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
  	struct cfq_rq *crq;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
907
  	if (cfq_cfqq_fifo_expire(cfqq))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
  		return NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
909
  	if (!list_empty(&cfqq->fifo)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
910
  		int fifo = cfq_cfqq_class_sync(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911

22e2c507c   Jens Axboe   [PATCH] Update cf...
912
913
914
  		crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next));
  		rq = crq->request;
  		if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
915
  			cfq_mark_cfqq_fifo_expire(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
916
917
  			return crq;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
920
921
922
923
  	}
  
  	return NULL;
  }
  
  /*
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
924
925
926
   * Scale schedule slice based on io priority. Use the sync time slice only
   * if a queue is marked sync and has sync io queued. A sync queue with async
   * io only, should not get full sync slice length.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
928
929
930
931
932
933
934
935
936
  static inline int
  cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)];
  
  	WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
  
  	return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio));
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
  static inline void
22e2c507c   Jens Axboe   [PATCH] Update cf...
938
  cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
940
941
  	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942

22e2c507c   Jens Axboe   [PATCH] Update cf...
943
944
945
946
  static inline int
  cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	const int base_rq = cfqd->cfq_slice_async_rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947

22e2c507c   Jens Axboe   [PATCH] Update cf...
948
  	WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949

22e2c507c   Jens Axboe   [PATCH] Update cf...
950
  	return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
952
953
954
  /*
   * get next queue for service
   */
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
955
  static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
957
  	unsigned long now = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959

22e2c507c   Jens Axboe   [PATCH] Update cf...
960
961
962
  	cfqq = cfqd->active_queue;
  	if (!cfqq)
  		goto new_queue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
964
965
  	if (cfq_cfqq_expired(cfqq))
  		goto new_queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
966
967
968
  	/*
  	 * slice has expired
  	 */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
969
970
  	if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end))
  		goto expire;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971

22e2c507c   Jens Axboe   [PATCH] Update cf...
972
973
974
975
976
977
  	/*
  	 * if queue has requests, dispatch one. if not, check if
  	 * enough slice is left to wait for one
  	 */
  	if (!RB_EMPTY(&cfqq->sort_list))
  		goto keep_queue;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
978
  	else if (cfq_cfqq_class_sync(cfqq) &&
22e2c507c   Jens Axboe   [PATCH] Update cf...
979
980
981
982
  		 time_before(now, cfqq->slice_end)) {
  		if (cfq_arm_slice_timer(cfqd, cfqq))
  			return NULL;
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
983
  expire:
22e2c507c   Jens Axboe   [PATCH] Update cf...
984
  	cfq_slice_expired(cfqd, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
985
986
  new_queue:
  	cfqq = cfq_set_active_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
987
  keep_queue:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
988
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
989
990
991
992
993
994
995
996
997
998
999
1000
  }
  
  static int
  __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  			int max_dispatch)
  {
  	int dispatched = 0;
  
  	BUG_ON(RB_EMPTY(&cfqq->sort_list));
  
  	do {
  		struct cfq_rq *crq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001
1002
  
  		/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1003
  		 * follow expired path, else get first next available
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
  		 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1005
1006
1007
1008
1009
1010
  		if ((crq = cfq_check_fifo(cfqq)) == NULL)
  			crq = cfqq->next_crq;
  
  		/*
  		 * finally, insert request into driver dispatch list
  		 */
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1011
  		cfq_dispatch_insert(cfqd->queue, crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012

22e2c507c   Jens Axboe   [PATCH] Update cf...
1013
1014
  		cfqd->dispatch_slice++;
  		dispatched++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015

22e2c507c   Jens Axboe   [PATCH] Update cf...
1016
1017
1018
1019
  		if (!cfqd->active_cic) {
  			atomic_inc(&crq->io_context->ioc->refcount);
  			cfqd->active_cic = crq->io_context;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020

22e2c507c   Jens Axboe   [PATCH] Update cf...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  		if (RB_EMPTY(&cfqq->sort_list))
  			break;
  
  	} while (dispatched < max_dispatch);
  
  	/*
  	 * if slice end isn't set yet, set it. if at least one request was
  	 * sync, use the sync time slice value
  	 */
  	if (!cfqq->slice_end)
  		cfq_set_prio_slice(cfqd, cfqq);
  
  	/*
  	 * expire an async queue immediately if it has used up its slice. idle
  	 * queue always expire after 1 dispatch round.
  	 */
  	if ((!cfq_cfqq_sync(cfqq) &&
  	    cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
  	    cfq_class_idle(cfqq))
  		cfq_slice_expired(cfqd, 0);
  
  	return dispatched;
  }
  
  static int
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
  cfq_forced_dispatch_cfqqs(struct list_head *list)
  {
  	int dispatched = 0;
  	struct cfq_queue *cfqq, *next;
  	struct cfq_rq *crq;
  
  	list_for_each_entry_safe(cfqq, next, list, cfq_list) {
  		while ((crq = cfqq->next_crq)) {
  			cfq_dispatch_insert(cfqq->cfqd->queue, crq);
  			dispatched++;
  		}
  		BUG_ON(!list_empty(&cfqq->fifo));
  	}
  	return dispatched;
  }
  
  static int
  cfq_forced_dispatch(struct cfq_data *cfqd)
  {
  	int i, dispatched = 0;
  
  	for (i = 0; i < CFQ_PRIO_LISTS; i++)
  		dispatched += cfq_forced_dispatch_cfqqs(&cfqd->rr_list[i]);
  
  	dispatched += cfq_forced_dispatch_cfqqs(&cfqd->busy_rr);
  	dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr);
  	dispatched += cfq_forced_dispatch_cfqqs(&cfqd->idle_rr);
  
  	cfq_slice_expired(cfqd, 0);
  
  	BUG_ON(cfqd->busy_queues);
  
  	return dispatched;
  }
  
  static int
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1082
  cfq_dispatch_requests(request_queue_t *q, int force)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1083
1084
1085
1086
1087
1088
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct cfq_queue *cfqq;
  
  	if (!cfqd->busy_queues)
  		return 0;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1089
1090
1091
1092
  	if (unlikely(force))
  		return cfq_forced_dispatch(cfqd);
  
  	cfqq = cfq_select_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1093
  	if (cfqq) {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1094
1095
1096
1097
1098
1099
1100
1101
  		int max_dispatch;
  
  		/*
  		 * if idle window is disabled, allow queue buildup
  		 */
  		if (!cfq_cfqq_idle_window(cfqq) &&
  		    cfqd->rq_in_driver >= cfqd->cfq_max_depth)
  			return 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1102
1103
  		cfq_clear_cfqq_must_dispatch(cfqq);
  		cfq_clear_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1104
  		del_timer(&cfqd->idle_slice_timer);
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1105
1106
1107
  		max_dispatch = cfqd->cfq_quantum;
  		if (cfq_class_idle(cfqq))
  			max_dispatch = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108

22e2c507c   Jens Axboe   [PATCH] Update cf...
1109
  		return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1110
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1111
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113
1114
1115
1116
1117
1118
1119
1120
  /*
   * task holds one reference to the queue, dropped when task exits. each crq
   * in-flight on this queue also holds a reference, dropped when crq is freed.
   *
   * queue lock must be held here.
   */
  static void cfq_put_queue(struct cfq_queue *cfqq)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1121
1122
1123
  	struct cfq_data *cfqd = cfqq->cfqd;
  
  	BUG_ON(atomic_read(&cfqq->ref) <= 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124
1125
1126
1127
1128
  
  	if (!atomic_dec_and_test(&cfqq->ref))
  		return;
  
  	BUG_ON(rb_first(&cfqq->sort_list));
22e2c507c   Jens Axboe   [PATCH] Update cf...
1129
  	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1130
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131

22e2c507c   Jens Axboe   [PATCH] Update cf...
1132
  	if (unlikely(cfqd->active_queue == cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1133
1134
  		__cfq_slice_expired(cfqd, cfqq, 0);
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1135
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  	cfq_put_cfqd(cfqq->cfqd);
  
  	/*
  	 * it's on the empty list and still hashed
  	 */
  	list_del(&cfqq->cfq_list);
  	hlist_del(&cfqq->cfq_hash);
  	kmem_cache_free(cfq_pool, cfqq);
  }
  
  static inline struct cfq_queue *
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1147
1148
  __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
  		    const int hashval)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
1150
1151
1152
1153
1154
  {
  	struct hlist_head *hash_list = &cfqd->cfq_hash[hashval];
  	struct hlist_node *entry, *next;
  
  	hlist_for_each_safe(entry, next, hash_list) {
  		struct cfq_queue *__cfqq = list_entry_qhash(entry);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1155
  		const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1157
  		if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
1160
1161
1162
1163
1164
  			return __cfqq;
  	}
  
  	return NULL;
  }
  
  static struct cfq_queue *
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1165
  cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1167
  	return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1169
  static void cfq_free_io_context(struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1171
1172
  	struct cfq_io_context *__cic;
  	struct list_head *entry, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173

22e2c507c   Jens Axboe   [PATCH] Update cf...
1174
1175
1176
  	list_for_each_safe(entry, next, &cic->list) {
  		__cic = list_entry(entry, struct cfq_io_context, list);
  		kmem_cache_free(cfq_ioc_pool, __cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1178
  	kmem_cache_free(cfq_ioc_pool, cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1180
1181
1182
1183
  /*
   * Called with interrupts disabled
   */
  static void cfq_exit_single_io_context(struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1185
1186
1187
1188
1189
1190
1191
1192
  	struct cfq_data *cfqd = cic->cfqq->cfqd;
  	request_queue_t *q = cfqd->queue;
  
  	WARN_ON(!irqs_disabled());
  
  	spin_lock(q->queue_lock);
  
  	if (unlikely(cic->cfqq == cfqd->active_queue)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1193
1194
  		__cfq_slice_expired(cfqd, cic->cfqq, 0);
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1195
1196
1197
1198
1199
  	}
  
  	cfq_put_queue(cic->cfqq);
  	cic->cfqq = NULL;
  	spin_unlock(q->queue_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200
1201
1202
  }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1203
1204
   * Another task may update the task cic list, if it is doing a queue lookup
   * on its behalf. cfq_cic_lock excludes such concurrent updates
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
   */
  static void cfq_exit_io_context(struct cfq_io_context *cic)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1208
1209
  	struct cfq_io_context *__cic;
  	struct list_head *entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
  	unsigned long flags;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1211
  	local_irq_save(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212
1213
1214
  	/*
  	 * put the reference this task is holding to the various queues
  	 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1215
  	list_for_each(entry, &cic->list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
  		__cic = list_entry(entry, struct cfq_io_context, list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1217
  		cfq_exit_single_io_context(__cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1219
1220
  	cfq_exit_single_io_context(cic);
  	local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1222
  static struct cfq_io_context *
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1223
  cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1225
  	struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
  
  	if (cic) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
1229
  		INIT_LIST_HEAD(&cic->list);
  		cic->cfqq = NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1230
1231
1232
1233
1234
1235
1236
  		cic->key = NULL;
  		cic->last_end_request = jiffies;
  		cic->ttime_total = 0;
  		cic->ttime_samples = 0;
  		cic->ttime_mean = 0;
  		cic->dtor = cfq_free_io_context;
  		cic->exit = cfq_exit_io_context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
1240
  	}
  
  	return cic;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1241
1242
1243
1244
  static void cfq_init_prio_data(struct cfq_queue *cfqq)
  {
  	struct task_struct *tsk = current;
  	int ioprio_class;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1245
  	if (!cfq_cfqq_prio_changed(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  		return;
  
  	ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio);
  	switch (ioprio_class) {
  		default:
  			printk(KERN_ERR "cfq: bad prio %x
  ", ioprio_class);
  		case IOPRIO_CLASS_NONE:
  			/*
  			 * no prio set, place us in the middle of the BE classes
  			 */
  			cfqq->ioprio = task_nice_ioprio(tsk);
  			cfqq->ioprio_class = IOPRIO_CLASS_BE;
  			break;
  		case IOPRIO_CLASS_RT:
  			cfqq->ioprio = task_ioprio(tsk);
  			cfqq->ioprio_class = IOPRIO_CLASS_RT;
  			break;
  		case IOPRIO_CLASS_BE:
  			cfqq->ioprio = task_ioprio(tsk);
  			cfqq->ioprio_class = IOPRIO_CLASS_BE;
  			break;
  		case IOPRIO_CLASS_IDLE:
  			cfqq->ioprio_class = IOPRIO_CLASS_IDLE;
  			cfqq->ioprio = 7;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1271
  			cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1272
1273
1274
1275
1276
1277
1278
1279
1280
  			break;
  	}
  
  	/*
  	 * keep track of original prio settings in case we have to temporarily
  	 * elevate the priority of this queue
  	 */
  	cfqq->org_ioprio = cfqq->ioprio;
  	cfqq->org_ioprio_class = cfqq->ioprio_class;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1281
  	if (cfq_cfqq_on_rr(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1282
  		cfq_resort_rr_list(cfqq, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1283
  	cfq_clear_cfqq_prio_changed(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1284
1285
1286
1287
1288
1289
1290
1291
  }
  
  static inline void changed_ioprio(struct cfq_queue *cfqq)
  {
  	if (cfqq) {
  		struct cfq_data *cfqd = cfqq->cfqd;
  
  		spin_lock(cfqd->queue->queue_lock);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1292
  		cfq_mark_cfqq_prio_changed(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
  		cfq_init_prio_data(cfqq);
  		spin_unlock(cfqd->queue->queue_lock);
  	}
  }
  
  /*
   * callback from sys_ioprio_set, irqs are disabled
   */
  static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
  {
  	struct cfq_io_context *cic = ioc->cic;
  
  	changed_ioprio(cic->cfqq);
  
  	list_for_each_entry(cic, &cic->list, list)
  		changed_ioprio(cic->cfqq);
  
  	return 0;
  }
  
  static struct cfq_queue *
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1314
  cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1315
  	      gfp_t gfp_mask)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1316
1317
1318
1319
1320
  {
  	const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
  	struct cfq_queue *cfqq, *new_cfqq = NULL;
  
  retry:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1321
  	cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
  
  	if (!cfqq) {
  		if (new_cfqq) {
  			cfqq = new_cfqq;
  			new_cfqq = NULL;
  		} else if (gfp_mask & __GFP_WAIT) {
  			spin_unlock_irq(cfqd->queue->queue_lock);
  			new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
  			spin_lock_irq(cfqd->queue->queue_lock);
  			goto retry;
  		} else {
  			cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
  			if (!cfqq)
  				goto out;
  		}
  
  		memset(cfqq, 0, sizeof(*cfqq));
  
  		INIT_HLIST_NODE(&cfqq->cfq_hash);
  		INIT_LIST_HEAD(&cfqq->cfq_list);
  		RB_CLEAR_ROOT(&cfqq->sort_list);
  		INIT_LIST_HEAD(&cfqq->fifo);
  
  		cfqq->key = key;
  		hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
  		atomic_set(&cfqq->ref, 0);
  		cfqq->cfqd = cfqd;
  		atomic_inc(&cfqd->ref);
  		cfqq->service_last = 0;
  		/*
  		 * set ->slice_left to allow preemption for a new process
  		 */
  		cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1355
1356
1357
  		cfq_mark_cfqq_idle_window(cfqq);
  		cfq_mark_cfqq_prio_changed(cfqq);
  		cfq_init_prio_data(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
  	}
  
  	if (new_cfqq)
  		kmem_cache_free(cfq_pool, new_cfqq);
  
  	atomic_inc(&cfqq->ref);
  out:
  	WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
  	return cfqq;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
1370
1371
1372
1373
1374
  /*
   * Setup general io context and cfq io context. There can be several cfq
   * io contexts per general io context, if this process is doing io to more
   * than one device managed by cfq. Note that caller is holding a reference to
   * cfqq, so we don't need to worry about it disappearing
   */
  static struct cfq_io_context *
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1375
  cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1377
  	struct io_context *ioc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
  	struct cfq_io_context *cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379

22e2c507c   Jens Axboe   [PATCH] Update cf...
1380
  	might_sleep_if(gfp_mask & __GFP_WAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381

22e2c507c   Jens Axboe   [PATCH] Update cf...
1382
  	ioc = get_io_context(gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
1384
1385
1386
  	if (!ioc)
  		return NULL;
  
  	if ((cic = ioc->cic) == NULL) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1387
  		cic = cfq_alloc_io_context(cfqd, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
1389
1390
  
  		if (cic == NULL)
  			goto err;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1391
1392
1393
1394
  		/*
  		 * manually increment generic io_context usage count, it
  		 * cannot go away since we are already holding one ref to it
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
  		ioc->cic = cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1396
  		ioc->set_ioprio = cfq_ioc_set_ioprio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
  		cic->ioc = ioc;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1398
1399
  		cic->key = cfqd;
  		atomic_inc(&cfqd->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
1401
  	} else {
  		struct cfq_io_context *__cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
1403
  
  		/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1404
  		 * the first cic on the list is actually the head itself
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
  		 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1406
  		if (cic->key == cfqd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407
1408
1409
1410
1411
1412
1413
  			goto out;
  
  		/*
  		 * cic exists, check if we already are there. linear search
  		 * should be ok here, the list will usually not be more than
  		 * 1 or a few entries long
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414
1415
1416
1417
1418
  		list_for_each_entry(__cic, &cic->list, list) {
  			/*
  			 * this process is already holding a reference to
  			 * this queue, so no need to get one more
  			 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1419
  			if (__cic->key == cfqd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  				cic = __cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
1422
1423
  				goto out;
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
1426
1427
1428
  
  		/*
  		 * nope, process doesn't have a cic assoicated with this
  		 * cfqq yet. get a new one and add to list
  		 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1429
  		__cic = cfq_alloc_io_context(cfqd, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
1431
1432
1433
  		if (__cic == NULL)
  			goto err;
  
  		__cic->ioc = ioc;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1434
1435
  		__cic->key = cfqd;
  		atomic_inc(&cfqd->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1436
  		list_add(&__cic->list, &cic->list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
  		cic = __cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
1440
  	}
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441
1442
1443
1444
1445
  	return cic;
  err:
  	put_io_context(ioc);
  	return NULL;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1446
1447
  static void
  cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1449
  	unsigned long elapsed, ttime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450

22e2c507c   Jens Axboe   [PATCH] Update cf...
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
  	/*
  	 * if this context already has stuff queued, thinktime is from
  	 * last queue not last end
  	 */
  #if 0
  	if (time_after(cic->last_end_request, cic->last_queue))
  		elapsed = jiffies - cic->last_end_request;
  	else
  		elapsed = jiffies - cic->last_queue;
  #else
  		elapsed = jiffies - cic->last_end_request;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1463

22e2c507c   Jens Axboe   [PATCH] Update cf...
1464
  	ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
db3b5848e   Kiyoshi Ueda   When cfq I/O sche...
1465

22e2c507c   Jens Axboe   [PATCH] Update cf...
1466
1467
1468
1469
  	cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
  	cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
  	cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470

22e2c507c   Jens Axboe   [PATCH] Update cf...
1471
  #define sample_valid(samples)	((samples) > 80)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1472

22e2c507c   Jens Axboe   [PATCH] Update cf...
1473
1474
1475
1476
1477
1478
1479
1480
  /*
   * Disable idle window if the process thinks too long or seeks so much that
   * it doesn't matter
   */
  static void
  cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		       struct cfq_io_context *cic)
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1481
  	int enable_idle = cfq_cfqq_idle_window(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482

22e2c507c   Jens Axboe   [PATCH] Update cf...
1483
1484
1485
1486
1487
1488
1489
  	if (!cic->ioc->task || !cfqd->cfq_slice_idle)
  		enable_idle = 0;
  	else if (sample_valid(cic->ttime_samples)) {
  		if (cic->ttime_mean > cfqd->cfq_slice_idle)
  			enable_idle = 0;
  		else
  			enable_idle = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1490
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1491
1492
1493
1494
  	if (enable_idle)
  		cfq_mark_cfqq_idle_window(cfqq);
  	else
  		cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1495
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496

22e2c507c   Jens Axboe   [PATCH] Update cf...
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
  
  /*
   * Check if new_cfqq should preempt the currently active queue. Return 0 for
   * no or if we aren't sure, a 1 will cause a preempt.
   */
  static int
  cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
  		   struct cfq_rq *crq)
  {
  	struct cfq_queue *cfqq = cfqd->active_queue;
  
  	if (cfq_class_idle(new_cfqq))
  		return 0;
  
  	if (!cfqq)
  		return 1;
  
  	if (cfq_class_idle(cfqq))
  		return 1;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1516
  	if (!cfq_cfqq_wait_request(new_cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1517
1518
1519
1520
1521
1522
  		return 0;
  	/*
  	 * if it doesn't have slice left, forget it
  	 */
  	if (new_cfqq->slice_left < cfqd->cfq_slice_idle)
  		return 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1523
  	if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  		return 1;
  
  	return 0;
  }
  
  /*
   * cfqq preempts the active queue. if we allowed preempt with no slice left,
   * let it have half of its nominal slice.
   */
  static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	struct cfq_queue *__cfqq, *next;
  
  	list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list)
  		cfq_resort_rr_list(__cfqq, 1);
  
  	if (!cfqq->slice_left)
  		cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2;
  
  	cfqq->slice_end = cfqq->slice_left + jiffies;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1544
  	__cfq_slice_expired(cfqd, cfqq, 1);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
  	__cfq_set_active_queue(cfqd, cfqq);
  }
  
  /*
   * should really be a ll_rw_blk.c helper
   */
  static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	request_queue_t *q = cfqd->queue;
  
  	if (!blk_queue_plugged(q))
  		q->request_fn(q);
  	else
  		__generic_unplug_device(q);
  }
  
  /*
   * Called when a new fs request (crq) is added (to cfqq). Check if there's
   * something we should do about it
   */
  static void
  cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		 struct cfq_rq *crq)
  {
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1569
  	struct cfq_io_context *cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1570
1571
  
  	cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1572
1573
1574
1575
1576
1577
  	/*
  	 * we never wait for an async request and we don't allow preemption
  	 * of an async request. so just return early
  	 */
  	if (!cfq_crq_is_sync(crq))
  		return;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1578

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1579
  	cic = crq->io_context;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1580

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1581
1582
1583
1584
  	cfq_update_io_thinktime(cfqd, cic);
  	cfq_update_idle_window(cfqd, cfqq, cic);
  
  	cic->last_queue = jiffies;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1585
1586
1587
1588
1589
1590
1591
  
  	if (cfqq == cfqd->active_queue) {
  		/*
  		 * if we are waiting for a request for this queue, let it rip
  		 * immediately and flag that we must not expire this queue
  		 * just now
  		 */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1592
1593
  		if (cfq_cfqq_wait_request(cfqq)) {
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
  			del_timer(&cfqd->idle_slice_timer);
  			cfq_start_queueing(cfqd, cfqq);
  		}
  	} else if (cfq_should_preempt(cfqd, cfqq, crq)) {
  		/*
  		 * not the active queue - expire current slice if it is
  		 * idle and has expired it's mean thinktime or this new queue
  		 * has some old slice time left and is of higher priority
  		 */
  		cfq_preempt_queue(cfqd, cfqq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1604
  		cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1605
1606
  		cfq_start_queueing(cfqd, cfqq);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1608
  static void cfq_insert_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1610
  	struct cfq_data *cfqd = q->elevator->elevator_data;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1611
1612
1613
1614
  	struct cfq_rq *crq = RQ_DATA(rq);
  	struct cfq_queue *cfqq = crq->cfq_queue;
  
  	cfq_init_prio_data(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
1616
  
  	cfq_add_crq_rb(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617

22e2c507c   Jens Axboe   [PATCH] Update cf...
1618
  	list_add_tail(&rq->queuelist, &cfqq->fifo);
98b11471d   Tejun Heo   [PATCH] 04/05 rem...
1619
  	if (rq_mergeable(rq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1620
  		cfq_add_crq_hash(cfqd, crq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1621
  	cfq_crq_enqueued(cfqd, cfqq, crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1622
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
1624
1625
  static void cfq_completed_request(request_queue_t *q, struct request *rq)
  {
  	struct cfq_rq *crq = RQ_DATA(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1626
1627
1628
1629
  	struct cfq_queue *cfqq = crq->cfq_queue;
  	struct cfq_data *cfqd = cfqq->cfqd;
  	const int sync = cfq_crq_is_sync(crq);
  	unsigned long now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1630

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1631
  	now = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1633
1634
1635
1636
  	WARN_ON(!cfqd->rq_in_driver);
  	WARN_ON(!cfqq->on_dispatch[sync]);
  	cfqd->rq_in_driver--;
  	cfqq->on_dispatch[sync]--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1637

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1638
1639
  	if (!cfq_class_idle(cfqq))
  		cfqd->last_end_request = now;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1640

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1641
1642
1643
1644
1645
1646
1647
1648
1649
  	if (!cfq_cfqq_dispatched(cfqq)) {
  		if (cfq_cfqq_on_rr(cfqq)) {
  			cfqq->service_last = now;
  			cfq_resort_rr_list(cfqq, 0);
  		}
  		if (cfq_cfqq_expired(cfqq)) {
  			__cfq_slice_expired(cfqd, cfqq, 0);
  			cfq_schedule_dispatch(cfqd);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1650
  	}
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1651
1652
  	if (cfq_crq_is_sync(crq))
  		crq->io_context->last_end_request = now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
  }
  
  static struct request *
  cfq_former_request(request_queue_t *q, struct request *rq)
  {
  	struct cfq_rq *crq = RQ_DATA(rq);
  	struct rb_node *rbprev = rb_prev(&crq->rb_node);
  
  	if (rbprev)
  		return rb_entry_crq(rbprev)->request;
  
  	return NULL;
  }
  
  static struct request *
  cfq_latter_request(request_queue_t *q, struct request *rq)
  {
  	struct cfq_rq *crq = RQ_DATA(rq);
  	struct rb_node *rbnext = rb_next(&crq->rb_node);
  
  	if (rbnext)
  		return rb_entry_crq(rbnext)->request;
  
  	return NULL;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1678
1679
1680
1681
1682
  /*
   * we temporarily boost lower priority queues if they are holding fs exclusive
   * resources. they are boosted to normal prio (CLASS_BE/4)
   */
  static void cfq_prio_boost(struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1684
1685
  	const int ioprio_class = cfqq->ioprio_class;
  	const int ioprio = cfqq->ioprio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686

22e2c507c   Jens Axboe   [PATCH] Update cf...
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
  	if (has_fs_excl()) {
  		/*
  		 * boost idle prio on transactions that would lock out other
  		 * users of the filesystem
  		 */
  		if (cfq_class_idle(cfqq))
  			cfqq->ioprio_class = IOPRIO_CLASS_BE;
  		if (cfqq->ioprio > IOPRIO_NORM)
  			cfqq->ioprio = IOPRIO_NORM;
  	} else {
  		/*
  		 * check if we need to unboost the queue
  		 */
  		if (cfqq->ioprio_class != cfqq->org_ioprio_class)
  			cfqq->ioprio_class = cfqq->org_ioprio_class;
  		if (cfqq->ioprio != cfqq->org_ioprio)
  			cfqq->ioprio = cfqq->org_ioprio;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1705

22e2c507c   Jens Axboe   [PATCH] Update cf...
1706
1707
1708
1709
  	/*
  	 * refile between round-robin lists if we moved the priority class
  	 */
  	if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) &&
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1710
  	    cfq_cfqq_on_rr(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1711
1712
  		cfq_resort_rr_list(cfqq, 0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713

22e2c507c   Jens Axboe   [PATCH] Update cf...
1714
1715
1716
1717
  static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
  {
  	if (rw == READ || process_sync(task))
  		return task->pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1718

22e2c507c   Jens Axboe   [PATCH] Update cf...
1719
1720
  	return CFQ_KEY_ASYNC;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1721

22e2c507c   Jens Axboe   [PATCH] Update cf...
1722
1723
1724
1725
  static inline int
  __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		struct task_struct *task, int rw)
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1726
1727
  #if 1
  	if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
99f95e528   Andrew Morton   [PATCH] cfq build...
1728
  	    !cfq_cfqq_must_alloc_slice(cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1729
  		cfq_mark_cfqq_must_alloc_slice(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1730
  		return ELV_MQUEUE_MUST;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1731
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732

22e2c507c   Jens Axboe   [PATCH] Update cf...
1733
  	return ELV_MQUEUE_MAY;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1734
  #else
22e2c507c   Jens Axboe   [PATCH] Update cf...
1735
1736
  	if (!cfqq || task->flags & PF_MEMALLOC)
  		return ELV_MQUEUE_MAY;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1737
1738
  	if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) {
  		if (cfq_cfqq_wait_request(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1739
  			return ELV_MQUEUE_MUST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1740

22e2c507c   Jens Axboe   [PATCH] Update cf...
1741
1742
1743
1744
  		/*
  		 * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we
  		 * can quickly flood the queue with writes from a single task
  		 */
99f95e528   Andrew Morton   [PATCH] cfq build...
1745
  		if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1746
  			cfq_mark_cfqq_must_alloc_slice(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1747
  			return ELV_MQUEUE_MUST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1749
1750
  
  		return ELV_MQUEUE_MAY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1752
1753
1754
1755
1756
  	if (cfq_class_idle(cfqq))
  		return ELV_MQUEUE_NO;
  	if (cfqq->allocated[rw] >= cfqd->max_queued) {
  		struct io_context *ioc = get_io_context(GFP_ATOMIC);
  		int ret = ELV_MQUEUE_NO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1757

22e2c507c   Jens Axboe   [PATCH] Update cf...
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
  		if (ioc && ioc->nr_batch_requests)
  			ret = ELV_MQUEUE_MAY;
  
  		put_io_context(ioc);
  		return ret;
  	}
  
  	return ELV_MQUEUE_MAY;
  #endif
  }
  
  static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio)
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct task_struct *tsk = current;
  	struct cfq_queue *cfqq;
  
  	/*
  	 * don't force setup of a queue from here, as a call to may_queue
  	 * does not necessarily imply that a request actually will be queued.
  	 * so just lookup a possibly existing queue, or return 'may queue'
  	 * if that fails
  	 */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1781
  	cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1782
1783
1784
1785
1786
1787
1788
1789
  	if (cfqq) {
  		cfq_init_prio_data(cfqq);
  		cfq_prio_boost(cfqq);
  
  		return __cfq_may_queue(cfqd, cfqq, tsk, rw);
  	}
  
  	return ELV_MQUEUE_MAY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1790
1791
1792
1793
  }
  
  static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1794
  	struct cfq_data *cfqd = q->elevator->elevator_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1795
  	struct request_list *rl = &q->rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796

22e2c507c   Jens Axboe   [PATCH] Update cf...
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
  	if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) {
  		smp_mb();
  		if (waitqueue_active(&rl->wait[READ]))
  			wake_up(&rl->wait[READ]);
  	}
  
  	if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) {
  		smp_mb();
  		if (waitqueue_active(&rl->wait[WRITE]))
  			wake_up(&rl->wait[WRITE]);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
  }
  
  /*
   * queue lock held here
   */
  static void cfq_put_request(request_queue_t *q, struct request *rq)
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct cfq_rq *crq = RQ_DATA(rq);
  
  	if (crq) {
  		struct cfq_queue *cfqq = crq->cfq_queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1820
  		const int rw = rq_data_dir(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821

22e2c507c   Jens Axboe   [PATCH] Update cf...
1822
1823
  		BUG_ON(!cfqq->allocated[rw]);
  		cfqq->allocated[rw]--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824

22e2c507c   Jens Axboe   [PATCH] Update cf...
1825
  		put_io_context(crq->io_context->ioc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
1827
1828
  
  		mempool_free(crq, cfqd->crq_pool);
  		rq->elevator_private = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1829
1830
1831
1832
1833
1834
  		cfq_check_waiters(q, cfqq);
  		cfq_put_queue(cfqq);
  	}
  }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1835
   * Allocate cfq data structures associated with this request.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1837
1838
  static int
  cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1839
  		gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840
1841
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1842
  	struct task_struct *tsk = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1843
1844
  	struct cfq_io_context *cic;
  	const int rw = rq_data_dir(rq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1845
  	pid_t key = cfq_queue_pid(tsk, rw);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1846
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
1848
1849
1850
  	struct cfq_rq *crq;
  	unsigned long flags;
  
  	might_sleep_if(gfp_mask & __GFP_WAIT);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1851
  	cic = cfq_get_io_context(cfqd, key, gfp_mask);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1852

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
  	spin_lock_irqsave(q->queue_lock, flags);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1854
1855
1856
1857
  	if (!cic)
  		goto queue_fail;
  
  	if (!cic->cfqq) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1858
  		cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1859
1860
  		if (!cfqq)
  			goto queue_fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861

22e2c507c   Jens Axboe   [PATCH] Update cf...
1862
1863
1864
  		cic->cfqq = cfqq;
  	} else
  		cfqq = cic->cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1865
1866
  
  	cfqq->allocated[rw]++;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1867
  	cfq_clear_cfqq_must_alloc(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1868
1869
  	cfqd->rq_starved = 0;
  	atomic_inc(&cfqq->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
  	spin_unlock_irqrestore(q->queue_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
1872
1873
1874
1875
1876
1877
1878
  	crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
  	if (crq) {
  		RB_CLEAR(&crq->rb_node);
  		crq->rb_key = 0;
  		crq->request = rq;
  		INIT_HLIST_NODE(&crq->hash);
  		crq->cfq_queue = cfqq;
  		crq->io_context = cic;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1879
1880
1881
1882
1883
  
  		if (rw == READ || process_sync(tsk))
  			cfq_mark_crq_is_sync(crq);
  		else
  			cfq_clear_crq_is_sync(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1884
  		rq->elevator_private = crq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1885
1886
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1887
1888
  	spin_lock_irqsave(q->queue_lock, flags);
  	cfqq->allocated[rw]--;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1889
  	if (!(cfqq->allocated[0] + cfqq->allocated[1]))
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1890
  		cfq_mark_cfqq_must_alloc(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1891
  	cfq_put_queue(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1892
1893
1894
1895
1896
1897
1898
1899
1900
  queue_fail:
  	if (cic)
  		put_io_context(cic->ioc);
  	/*
  	 * mark us rq allocation starved. we need to kickstart the process
  	 * ourselves if there are no pending requests that can do it for us.
  	 * that would be an extremely rare OOM situation
  	 */
  	cfqd->rq_starved = 1;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1901
  	cfq_schedule_dispatch(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902
1903
1904
  	spin_unlock_irqrestore(q->queue_lock, flags);
  	return 1;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
  static void cfq_kick_queue(void *data)
  {
  	request_queue_t *q = data;
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	unsigned long flags;
  
  	spin_lock_irqsave(q->queue_lock, flags);
  
  	if (cfqd->rq_starved) {
  		struct request_list *rl = &q->rq;
  
  		/*
  		 * we aren't guaranteed to get a request after this, but we
  		 * have to be opportunistic
  		 */
  		smp_mb();
  		if (waitqueue_active(&rl->wait[READ]))
  			wake_up(&rl->wait[READ]);
  		if (waitqueue_active(&rl->wait[WRITE]))
  			wake_up(&rl->wait[WRITE]);
  	}
  
  	blk_remove_plug(q);
  	q->request_fn(q);
  	spin_unlock_irqrestore(q->queue_lock, flags);
  }
  
  /*
   * Timer running if the active_queue is currently idling inside its time slice
   */
  static void cfq_idle_slice_timer(unsigned long data)
  {
  	struct cfq_data *cfqd = (struct cfq_data *) data;
  	struct cfq_queue *cfqq;
  	unsigned long flags;
  
  	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
  
  	if ((cfqq = cfqd->active_queue) != NULL) {
  		unsigned long now = jiffies;
  
  		/*
  		 * expired
  		 */
  		if (time_after(now, cfqq->slice_end))
  			goto expire;
  
  		/*
  		 * only expire and reinvoke request handler, if there are
  		 * other queues with pending requests
  		 */
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1956
  		if (!cfqd->busy_queues) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1957
1958
1959
1960
1961
1962
1963
1964
1965
  			cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
  			add_timer(&cfqd->idle_slice_timer);
  			goto out_cont;
  		}
  
  		/*
  		 * not expired and it has a request pending, let it dispatch
  		 */
  		if (!RB_EMPTY(&cfqq->sort_list)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1966
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1967
1968
1969
1970
1971
1972
  			goto out_kick;
  		}
  	}
  expire:
  	cfq_slice_expired(cfqd, 0);
  out_kick:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1973
  	cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
  out_cont:
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
  }
  
  /*
   * Timer running if an idle class queue is waiting for service
   */
  static void cfq_idle_class_timer(unsigned long data)
  {
  	struct cfq_data *cfqd = (struct cfq_data *) data;
  	unsigned long flags, end;
  
  	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
  
  	/*
  	 * race with a non-idle queue, reset timer
  	 */
  	end = cfqd->last_end_request + CFQ_IDLE_GRACE;
  	if (!time_after_eq(jiffies, end)) {
  		cfqd->idle_class_timer.expires = end;
  		add_timer(&cfqd->idle_class_timer);
  	} else
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1996
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1997
1998
1999
  
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2000
2001
2002
2003
2004
2005
  static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
  {
  	del_timer_sync(&cfqd->idle_slice_timer);
  	del_timer_sync(&cfqd->idle_class_timer);
  	blk_sync_queue(cfqd->queue);
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
2006

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
2008
2009
2010
2011
2012
  static void cfq_put_cfqd(struct cfq_data *cfqd)
  {
  	request_queue_t *q = cfqd->queue;
  
  	if (!atomic_dec_and_test(&cfqd->ref))
  		return;
96c51ce94   Jens Axboe   [PATCH] CFQ io sc...
2013
  	cfq_shutdown_timer_wq(cfqd);
4fc207419   Jens Axboe   [PATCH] Fix on-th...
2014
  	blk_put_queue(q);
96c51ce94   Jens Axboe   [PATCH] CFQ io sc...
2015

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2016
2017
2018
2019
2020
2021
2022
2023
  	mempool_destroy(cfqd->crq_pool);
  	kfree(cfqd->crq_hash);
  	kfree(cfqd->cfq_hash);
  	kfree(cfqd);
  }
  
  static void cfq_exit_queue(elevator_t *e)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
2024
  	struct cfq_data *cfqd = e->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2025
  	cfq_shutdown_timer_wq(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2026
  	cfq_put_cfqd(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
  }
  
  static int cfq_init_queue(request_queue_t *q, elevator_t *e)
  {
  	struct cfq_data *cfqd;
  	int i;
  
  	cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
  	if (!cfqd)
  		return -ENOMEM;
  
  	memset(cfqd, 0, sizeof(*cfqd));
22e2c507c   Jens Axboe   [PATCH] Update cf...
2039
2040
2041
2042
2043
2044
2045
  
  	for (i = 0; i < CFQ_PRIO_LISTS; i++)
  		INIT_LIST_HEAD(&cfqd->rr_list[i]);
  
  	INIT_LIST_HEAD(&cfqd->busy_rr);
  	INIT_LIST_HEAD(&cfqd->cur_rr);
  	INIT_LIST_HEAD(&cfqd->idle_rr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
  	INIT_LIST_HEAD(&cfqd->empty_list);
  
  	cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
  	if (!cfqd->crq_hash)
  		goto out_crqhash;
  
  	cfqd->cfq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_QHASH_ENTRIES, GFP_KERNEL);
  	if (!cfqd->cfq_hash)
  		goto out_cfqhash;
  
  	cfqd->crq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, crq_pool);
  	if (!cfqd->crq_pool)
  		goto out_crqpool;
  
  	for (i = 0; i < CFQ_MHASH_ENTRIES; i++)
  		INIT_HLIST_HEAD(&cfqd->crq_hash[i]);
  	for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
  		INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
  
  	e->elevator_data = cfqd;
  
  	cfqd->queue = q;
35797132b   Jens Axboe   [PATCH] cfq-iosch...
2068
  	atomic_inc(&q->refcnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2069

22e2c507c   Jens Axboe   [PATCH] Update cf...
2070
  	cfqd->max_queued = q->nr_requests / 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2071
  	q->nr_batching = cfq_queued;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
  
  	init_timer(&cfqd->idle_slice_timer);
  	cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
  	cfqd->idle_slice_timer.data = (unsigned long) cfqd;
  
  	init_timer(&cfqd->idle_class_timer);
  	cfqd->idle_class_timer.function = cfq_idle_class_timer;
  	cfqd->idle_class_timer.data = (unsigned long) cfqd;
  
  	INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2082
2083
2084
2085
  	atomic_set(&cfqd->ref, 1);
  
  	cfqd->cfq_queued = cfq_queued;
  	cfqd->cfq_quantum = cfq_quantum;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2086
2087
  	cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
  	cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
2089
  	cfqd->cfq_back_max = cfq_back_max;
  	cfqd->cfq_back_penalty = cfq_back_penalty;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2090
2091
2092
2093
2094
  	cfqd->cfq_slice[0] = cfq_slice_async;
  	cfqd->cfq_slice[1] = cfq_slice_sync;
  	cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
  	cfqd->cfq_slice_idle = cfq_slice_idle;
  	cfqd->cfq_max_depth = cfq_max_depth;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2095

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
  	return 0;
  out_crqpool:
  	kfree(cfqd->cfq_hash);
  out_cfqhash:
  	kfree(cfqd->crq_hash);
  out_crqhash:
  	kfree(cfqd);
  	return -ENOMEM;
  }
  
  static void cfq_slab_kill(void)
  {
  	if (crq_pool)
  		kmem_cache_destroy(crq_pool);
  	if (cfq_pool)
  		kmem_cache_destroy(cfq_pool);
  	if (cfq_ioc_pool)
  		kmem_cache_destroy(cfq_ioc_pool);
  }
  
  static int __init cfq_slab_setup(void)
  {
  	crq_pool = kmem_cache_create("crq_pool", sizeof(struct cfq_rq), 0, 0,
  					NULL, NULL);
  	if (!crq_pool)
  		goto fail;
  
  	cfq_pool = kmem_cache_create("cfq_pool", sizeof(struct cfq_queue), 0, 0,
  					NULL, NULL);
  	if (!cfq_pool)
  		goto fail;
  
  	cfq_ioc_pool = kmem_cache_create("cfq_ioc_pool",
  			sizeof(struct cfq_io_context), 0, 0, NULL, NULL);
  	if (!cfq_ioc_pool)
  		goto fail;
  
  	return 0;
  fail:
  	cfq_slab_kill();
  	return -ENOMEM;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
  /*
   * sysfs parts below -->
   */
  struct cfq_fs_entry {
  	struct attribute attr;
  	ssize_t (*show)(struct cfq_data *, char *);
  	ssize_t (*store)(struct cfq_data *, const char *, size_t);
  };
  
  static ssize_t
  cfq_var_show(unsigned int var, char *page)
  {
  	return sprintf(page, "%d
  ", var);
  }
  
  static ssize_t
  cfq_var_store(unsigned int *var, const char *page, size_t count)
  {
  	char *p = (char *) page;
  
  	*var = simple_strtoul(p, &p, 10);
  	return count;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
  #define SHOW_FUNCTION(__FUNC, __VAR, __CONV)				\
  static ssize_t __FUNC(struct cfq_data *cfqd, char *page)		\
  {									\
  	unsigned int __data = __VAR;					\
  	if (__CONV)							\
  		__data = jiffies_to_msecs(__data);			\
  	return cfq_var_show(__data, (page));				\
  }
  SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0);
  SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2172
2173
  SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1);
  SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2174
2175
  SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0);
  SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2176
2177
2178
2179
2180
  SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
  SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
  SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
  SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
  SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
  #undef SHOW_FUNCTION
  
  #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
  static ssize_t __FUNC(struct cfq_data *cfqd, const char *page, size_t count)	\
  {									\
  	unsigned int __data;						\
  	int ret = cfq_var_store(&__data, (page), count);		\
  	if (__data < (MIN))						\
  		__data = (MIN);						\
  	else if (__data > (MAX))					\
  		__data = (MAX);						\
  	if (__CONV)							\
  		*(__PTR) = msecs_to_jiffies(__data);			\
  	else								\
  		*(__PTR) = __data;					\
  	return ret;							\
  }
  STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
  STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2200
2201
  STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1);
  STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2202
2203
  STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
  STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2204
2205
2206
2207
2208
  STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
  STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
  STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
  STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0);
  STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
  #undef STORE_FUNCTION
  
  static struct cfq_fs_entry cfq_quantum_entry = {
  	.attr = {.name = "quantum", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_quantum_show,
  	.store = cfq_quantum_store,
  };
  static struct cfq_fs_entry cfq_queued_entry = {
  	.attr = {.name = "queued", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_queued_show,
  	.store = cfq_queued_store,
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
2221
  static struct cfq_fs_entry cfq_fifo_expire_sync_entry = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2222
  	.attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR },
22e2c507c   Jens Axboe   [PATCH] Update cf...
2223
2224
  	.show = cfq_fifo_expire_sync_show,
  	.store = cfq_fifo_expire_sync_store,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2225
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
2226
  static struct cfq_fs_entry cfq_fifo_expire_async_entry = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2227
  	.attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR },
22e2c507c   Jens Axboe   [PATCH] Update cf...
2228
2229
  	.show = cfq_fifo_expire_async_show,
  	.store = cfq_fifo_expire_async_store,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
  };
  static struct cfq_fs_entry cfq_back_max_entry = {
  	.attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_back_max_show,
  	.store = cfq_back_max_store,
  };
  static struct cfq_fs_entry cfq_back_penalty_entry = {
  	.attr = {.name = "back_seek_penalty", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_back_penalty_show,
  	.store = cfq_back_penalty_store,
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
2241
2242
2243
2244
  static struct cfq_fs_entry cfq_slice_sync_entry = {
  	.attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_slice_sync_show,
  	.store = cfq_slice_sync_store,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2245
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
  static struct cfq_fs_entry cfq_slice_async_entry = {
  	.attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_slice_async_show,
  	.store = cfq_slice_async_store,
  };
  static struct cfq_fs_entry cfq_slice_async_rq_entry = {
  	.attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_slice_async_rq_show,
  	.store = cfq_slice_async_rq_store,
  };
  static struct cfq_fs_entry cfq_slice_idle_entry = {
  	.attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_slice_idle_show,
  	.store = cfq_slice_idle_store,
  };
  static struct cfq_fs_entry cfq_max_depth_entry = {
  	.attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR },
  	.show = cfq_max_depth_show,
  	.store = cfq_max_depth_store,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2265
  };
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2266

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2267
2268
2269
  static struct attribute *default_attrs[] = {
  	&cfq_quantum_entry.attr,
  	&cfq_queued_entry.attr,
22e2c507c   Jens Axboe   [PATCH] Update cf...
2270
2271
  	&cfq_fifo_expire_sync_entry.attr,
  	&cfq_fifo_expire_async_entry.attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2272
2273
  	&cfq_back_max_entry.attr,
  	&cfq_back_penalty_entry.attr,
22e2c507c   Jens Axboe   [PATCH] Update cf...
2274
2275
2276
2277
2278
  	&cfq_slice_sync_entry.attr,
  	&cfq_slice_async_entry.attr,
  	&cfq_slice_async_rq_entry.attr,
  	&cfq_slice_idle_entry.attr,
  	&cfq_max_depth_entry.attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
  	NULL,
  };
  
  #define to_cfq(atr) container_of((atr), struct cfq_fs_entry, attr)
  
  static ssize_t
  cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
  {
  	elevator_t *e = container_of(kobj, elevator_t, kobj);
  	struct cfq_fs_entry *entry = to_cfq(attr);
  
  	if (!entry->show)
6c1852a08   Dmitry Torokhov   [PATCH] sysfs: (d...
2291
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
  
  	return entry->show(e->elevator_data, page);
  }
  
  static ssize_t
  cfq_attr_store(struct kobject *kobj, struct attribute *attr,
  	       const char *page, size_t length)
  {
  	elevator_t *e = container_of(kobj, elevator_t, kobj);
  	struct cfq_fs_entry *entry = to_cfq(attr);
  
  	if (!entry->store)
6c1852a08   Dmitry Torokhov   [PATCH] sysfs: (d...
2304
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
  
  	return entry->store(e->elevator_data, page, length);
  }
  
  static struct sysfs_ops cfq_sysfs_ops = {
  	.show	= cfq_attr_show,
  	.store	= cfq_attr_store,
  };
  
  static struct kobj_type cfq_ktype = {
  	.sysfs_ops	= &cfq_sysfs_ops,
  	.default_attrs	= default_attrs,
  };
  
  static struct elevator_type iosched_cfq = {
  	.ops = {
  		.elevator_merge_fn = 		cfq_merge,
  		.elevator_merged_fn =		cfq_merged_request,
  		.elevator_merge_req_fn =	cfq_merged_requests,
b4878f245   Jens Axboe   [PATCH] 02/05: up...
2324
  		.elevator_dispatch_fn =		cfq_dispatch_requests,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
  		.elevator_add_req_fn =		cfq_insert_request,
b4878f245   Jens Axboe   [PATCH] 02/05: up...
2326
  		.elevator_activate_req_fn =	cfq_activate_request,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
  		.elevator_deactivate_req_fn =	cfq_deactivate_request,
  		.elevator_queue_empty_fn =	cfq_queue_empty,
  		.elevator_completed_req_fn =	cfq_completed_request,
  		.elevator_former_req_fn =	cfq_former_request,
  		.elevator_latter_req_fn =	cfq_latter_request,
  		.elevator_set_req_fn =		cfq_set_request,
  		.elevator_put_req_fn =		cfq_put_request,
  		.elevator_may_queue_fn =	cfq_may_queue,
  		.elevator_init_fn =		cfq_init_queue,
  		.elevator_exit_fn =		cfq_exit_queue,
  	},
  	.elevator_ktype =	&cfq_ktype,
  	.elevator_name =	"cfq",
  	.elevator_owner =	THIS_MODULE,
  };
  
  static int __init cfq_init(void)
  {
  	int ret;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2346
2347
2348
2349
2350
2351
2352
  	/*
  	 * could be 0 on HZ < 1000 setups
  	 */
  	if (!cfq_slice_async)
  		cfq_slice_async = 1;
  	if (!cfq_slice_idle)
  		cfq_slice_idle = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2353
2354
2355
2356
  	if (cfq_slab_setup())
  		return -ENOMEM;
  
  	ret = elv_register(&iosched_cfq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2357
2358
  	if (ret)
  		cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2359

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2360
2361
2362
2363
2364
  	return ret;
  }
  
  static void __exit cfq_exit(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2365
  	elv_unregister(&iosched_cfq);
83521d3eb   Christoph Hellwig   [PATCH] cfq-iosch...
2366
  	cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2367
2368
2369
2370
2371
2372
2373
2374
  }
  
  module_init(cfq_init);
  module_exit(cfq_exit);
  
  MODULE_AUTHOR("Jens Axboe");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler");