Blame view

block/cfq-iosched.c 58.1 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
28
29
  
  /*
   * tunables
   */
  static int cfq_quantum = 4;		/* max queue in one round of service */
  static int cfq_queued = 8;		/* minimum rq allocate limit per-queue*/
22e2c507c   Jens Axboe   [PATCH] Update cf...
30
  static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  static int cfq_back_max = 16 * 1024;	/* maximum backwards seek, in KiB */
  static int cfq_back_penalty = 2;	/* penalty of a backwards seek */
22e2c507c   Jens Axboe   [PATCH] Update cf...
33
  static int cfq_slice_sync = HZ / 10;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
34
  static int cfq_slice_async = HZ / 25;
22e2c507c   Jens Axboe   [PATCH] Update cf...
35
  static int cfq_slice_async_rq = 2;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
36
  static int cfq_slice_idle = HZ / 100;
22e2c507c   Jens Axboe   [PATCH] Update cf...
37
38
39
40
41
  
  #define CFQ_IDLE_GRACE		(HZ / 10)
  #define CFQ_SLICE_SCALE		(5)
  
  #define CFQ_KEY_ASYNC		(0)
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
42
  #define CFQ_KEY_ANY		(0xffff)
22e2c507c   Jens Axboe   [PATCH] Update cf...
43
44
45
46
  
  /*
   * disable queueing at the driver/hardware level
   */
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
47
  static int cfq_max_depth = 2;
22e2c507c   Jens Axboe   [PATCH] Update cf...
48

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  /*
   * 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...
67
  #define list_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  
  #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
84
85
  #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
86
87
88
  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...
89
90
91
92
  #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...
93
94
95
96
97
98
99
100
101
102
  #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...
103
104
105
106
  
  /*
   * Per block device queue structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  struct cfq_data {
22e2c507c   Jens Axboe   [PATCH] Update cf...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  	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
123
  	struct list_head empty_list;
22e2c507c   Jens Axboe   [PATCH] Update cf...
124
125
126
  	/*
  	 * cfqq lookup hash
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	struct hlist_head *cfq_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

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

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
139
140
141
142
143
144
145
146
  	/*
  	 * 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
147

22e2c507c   Jens Axboe   [PATCH] Update cf...
148
149
150
151
152
153
  	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
154
155
  
  	sector_t last_sector;
22e2c507c   Jens Axboe   [PATCH] Update cf...
156
  	unsigned long last_end_request;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

22e2c507c   Jens Axboe   [PATCH] Update cf...
158
  	unsigned int rq_starved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
163
164
  
  	/*
  	 * tunables, see top of file
  	 */
  	unsigned int cfq_quantum;
  	unsigned int cfq_queued;
22e2c507c   Jens Axboe   [PATCH] Update cf...
165
  	unsigned int cfq_fifo_expire[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
  	unsigned int cfq_back_penalty;
  	unsigned int cfq_back_max;
22e2c507c   Jens Axboe   [PATCH] Update cf...
168
169
170
171
  	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
172
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
173
174
175
  /*
   * Per process-grouping structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
180
  struct cfq_queue {
  	/* reference count */
  	atomic_t ref;
  	/* parent cfq_data */
  	struct cfq_data *cfqd;
22e2c507c   Jens Axboe   [PATCH] Update cf...
181
  	/* cfqq lookup hash */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  	struct hlist_node cfq_hash;
  	/* hash key */
22e2c507c   Jens Axboe   [PATCH] Update cf...
184
  	unsigned int key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
191
192
193
194
195
  	/* 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...
196
  	struct list_head fifo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

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

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
203
204
  	/* number of requests that are on the dispatch list */
  	int on_dispatch[2];
22e2c507c   Jens Axboe   [PATCH] Update cf...
205
206
207
208
  
  	/* io prio of this group */
  	unsigned short ioprio, org_ioprio;
  	unsigned short ioprio_class, org_ioprio_class;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
209
210
  	/* various state flags, see below */
  	unsigned int flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
217
218
219
220
  };
  
  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...
221
  	unsigned int crq_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  };
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
223
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
  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...
261
  	CFQ_CRQ_FLAG_is_sync = 0,
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  };
  
  #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...
277
  CFQ_CRQ_FNS(is_sync);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
278
279
280
  #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...
281
  static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  static void cfq_put_cfqd(struct cfq_data *cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
283
  #define process_sync(tsk)	((tsk)->flags & PF_SYNCWRITE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
287
288
289
290
291
  
  /*
   * 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
292
293
294
  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
295
296
297
298
299
300
301
302
303
304
305
  	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
306
307
308
309
310
311
312
313
314
315
316
  		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...
317
318
319
320
321
322
  /*
   * 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...
323
  	if (!cfqd->rq_in_driver && cfqd->busy_queues)
99f95e528   Andrew Morton   [PATCH] cfq build...
324
325
326
327
328
329
  		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...
330
  	return !cfqd->busy_queues;
99f95e528   Andrew Morton   [PATCH] cfq build...
331
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  /*
   * 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...
348

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
349
350
351
  	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...
352
  		return crq2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
356
357
  
  	s1 = crq1->request->sector;
  	s2 = crq2->request->sector;
  
  	last = cfqd->last_sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
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
  	/*
  	 * 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...
417
  	if (!(rbnext = rb_next(&last->rb_node))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  		rbnext = rb_first(&cfqq->sort_list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
419
420
421
  		if (rbnext == &last->rb_node)
  			rbnext = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  
  	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...
440
  static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
442
443
  	struct cfq_data *cfqd = cfqq->cfqd;
  	struct list_head *list, *entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444

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

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
449
450
451
452
453
454
455
456
457
458
459
460
  	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...
461
  		if (cfq_cfqq_dispatched(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
462
463
464
  			list = &cfqd->busy_rr;
  		else
  			list = &cfqd->rr_list[cfqq->ioprio];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
466
467
468
469
470
471
  	/*
  	 * 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
472
  		return;
22e2c507c   Jens Axboe   [PATCH] Update cf...
473
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  
  	/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
476
  	 * sort by when queue was last serviced
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  	 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
478
479
  	entry = list;
  	while ((entry = entry->prev) != list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  		struct cfq_queue *__cfqq = list_entry_cfqq(entry);
22e2c507c   Jens Axboe   [PATCH] Update cf...
481
482
483
  		if (!__cfqq->service_last)
  			break;
  		if (time_before(__cfqq->service_last, cfqq->service_last))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
489
490
491
  	}
  
  	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...
492
   * the pending list according to last request service
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
   */
  static inline void
b4878f245   Jens Axboe   [PATCH] 02/05: up...
495
  cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
497
498
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
  	cfq_mark_cfqq_on_rr(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  	cfqd->busy_queues++;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
500
  	cfq_resort_rr_list(cfqq, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
505
  }
  
  static inline void
  cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
506
507
  	BUG_ON(!cfq_cfqq_on_rr(cfqq));
  	cfq_clear_cfqq_on_rr(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
508
  	list_move(&cfqq->cfq_list, &cfqd->empty_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
513
514
515
516
517
518
519
  
  	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...
520
521
  	struct cfq_data *cfqd = cfqq->cfqd;
  	const int sync = cfq_crq_is_sync(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522

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

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

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
531
532
  	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
533
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
  }
  
  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...
566
  	cfqq->queued[cfq_crq_is_sync(crq)]++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
571
572
  
  	/*
  	 * 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...
573
  		cfq_dispatch_insert(cfqd->queue, __alias);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
  
  	rb_insert_color(&crq->rb_node, &cfqq->sort_list);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
576
  	if (!cfq_cfqq_on_rr(cfqq))
b4878f245   Jens Axboe   [PATCH] 02/05: up...
577
  		cfq_add_cfqq_rr(cfqd, cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
580
581
582
583
584
585
586
587
  
  	/*
  	 * 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...
588
589
  	rb_erase(&crq->rb_node, &cfqq->sort_list);
  	cfqq->queued[cfq_crq_is_sync(crq)]--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
592
  
  	cfq_add_crq_rb(crq);
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
593
  static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
595
  	struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
  	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...
616
  static void cfq_activate_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
618
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
619

b4878f245   Jens Axboe   [PATCH] 02/05: up...
620
  	cfqd->rq_in_driver++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
622
  static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
624
625
626
627
  	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
628
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
629
  static void cfq_remove_request(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
  {
  	struct cfq_rq *crq = RQ_DATA(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
632
633
  	list_del_init(&rq->queuelist);
  	cfq_del_crq_rb(crq);
98b11471d   Tejun Heo   [PATCH] 04/05 rem...
634
  	cfq_del_crq_hash(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
638
639
640
641
642
  }
  
  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
643
  	__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
22e2c507c   Jens Axboe   [PATCH] Update cf...
644
645
646
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
  		ret = ELEVATOR_BACK_MERGE;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
  	}
  
  	__rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
22e2c507c   Jens Axboe   [PATCH] Update cf...
650
651
652
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
  		ret = ELEVATOR_FRONT_MERGE;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
  	}
  
  	return ELEVATOR_NO_MERGE;
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
660
661
662
663
664
665
666
667
  	*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...
668
  	if (rq_rb_key(req) != crq->rb_key) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
673
  		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
674
675
676
677
678
679
  }
  
  static void
  cfq_merged_requests(request_queue_t *q, struct request *rq,
  		    struct request *next)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
  	cfq_merged_request(q, rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
681
682
683
684
685
686
  	/*
  	 * 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...
687
  	cfq_remove_request(next);
22e2c507c   Jens Axboe   [PATCH] Update cf...
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  }
  
  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...
702
703
704
  		cfq_clear_cfqq_must_alloc_slice(cfqq);
  		cfq_clear_cfqq_fifo_expire(cfqq);
  		cfq_clear_cfqq_expired(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
705
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
  	}
  
  	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
744
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
  	} 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
762
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
763
764
  	return prio;
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
765
  static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
22e2c507c   Jens Axboe   [PATCH] Update cf...
766
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
767
768
769
770
771
772
773
774
775
776
  	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...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
  
  	/*
  	 * 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...
800
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
801
802
803
804
805
  }
  
  /*
   * current cfqq expired its slice (or was too idle), select new one
   */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
806
807
808
  static void
  __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		    int preempted)
22e2c507c   Jens Axboe   [PATCH] Update cf...
809
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
810
  	unsigned long now = jiffies;
22e2c507c   Jens Axboe   [PATCH] Update cf...
811

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

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

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

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

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

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
833
  	if (cfqq == cfqd->active_queue)
22e2c507c   Jens Axboe   [PATCH] Update cf...
834
  		cfqd->active_queue = NULL;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
835
836
837
  	if (cfqd->active_cic) {
  		put_io_context(cfqd->active_cic->ioc);
  		cfqd->active_cic = NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
838
839
840
841
  	}
  
  	cfqd->dispatch_slice = 0;
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
  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...
857
858
859
860
861
862
863
864
865
866
867
  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...
868
  	if (!cfq_cfqq_idle_window(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
869
870
871
872
873
874
  		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...
875
876
  	cfq_mark_cfqq_must_dispatch(cfqq);
  	cfq_mark_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
877
878
  
  	if (!timer_pending(&cfqd->idle_slice_timer)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
879
  		unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
22e2c507c   Jens Axboe   [PATCH] Update cf...
880

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
911
912
913
  		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...
914
  			cfq_mark_cfqq_fifo_expire(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
915
916
  			return crq;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
918
919
920
921
922
  	}
  
  	return NULL;
  }
  
  /*
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
923
924
925
   * 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
926
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
927
928
929
930
931
932
933
934
935
  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
936
  static inline void
22e2c507c   Jens Axboe   [PATCH] Update cf...
937
  cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
939
940
  	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941

22e2c507c   Jens Axboe   [PATCH] Update cf...
942
943
944
945
  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
946

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

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

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

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
971
972
973
974
975
976
  	/*
  	 * 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...
977
  	else if (cfq_cfqq_class_sync(cfqq) &&
22e2c507c   Jens Axboe   [PATCH] Update cf...
978
979
980
981
  		 time_before(now, cfqq->slice_end)) {
  		if (cfq_arm_slice_timer(cfqd, cfqq))
  			return NULL;
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
982
  expire:
22e2c507c   Jens Axboe   [PATCH] Update cf...
983
  	cfq_slice_expired(cfqd, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
984
985
  new_queue:
  	cfqq = cfq_set_active_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
986
  keep_queue:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
987
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
988
989
990
991
992
993
994
995
996
997
998
999
  }
  
  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
1000
1001
  
  		/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1002
  		 * follow expired path, else get first next available
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
  		 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1004
1005
1006
1007
1008
1009
  		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...
1010
  		cfq_dispatch_insert(cfqd->queue, crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1015
1016
1017
1018
  		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
1019

22e2c507c   Jens Axboe   [PATCH] Update cf...
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  		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...
1045
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
  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...
1081
  cfq_dispatch_requests(request_queue_t *q, int force)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1082
1083
1084
1085
1086
1087
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct cfq_queue *cfqq;
  
  	if (!cfqd->busy_queues)
  		return 0;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1088
1089
1090
1091
  	if (unlikely(force))
  		return cfq_forced_dispatch(cfqd);
  
  	cfqq = cfq_select_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1092
  	if (cfqq) {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1093
1094
1095
1096
1097
1098
1099
1100
  		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...
1101
1102
  		cfq_clear_cfqq_must_dispatch(cfqq);
  		cfq_clear_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1103
  		del_timer(&cfqd->idle_slice_timer);
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1104
1105
1106
  		max_dispatch = cfqd->cfq_quantum;
  		if (cfq_class_idle(cfqq))
  			max_dispatch = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107

22e2c507c   Jens Axboe   [PATCH] Update cf...
1108
  		return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1110
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1112
1113
1114
1115
1116
1117
1118
1119
  /*
   * 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...
1120
1121
1122
  	struct cfq_data *cfqd = cfqq->cfqd;
  
  	BUG_ON(atomic_read(&cfqq->ref) <= 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1123
1124
1125
1126
1127
  
  	if (!atomic_dec_and_test(&cfqq->ref))
  		return;
  
  	BUG_ON(rb_first(&cfqq->sort_list));
22e2c507c   Jens Axboe   [PATCH] Update cf...
1128
  	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1129
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130

22e2c507c   Jens Axboe   [PATCH] Update cf...
1131
  	if (unlikely(cfqd->active_queue == cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1132
1133
  		__cfq_slice_expired(cfqd, cfqq, 0);
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1134
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
  	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...
1146
1147
  __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
1148
1149
1150
1151
1152
1153
  {
  	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...
1154
  		const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1155

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1173
1174
1175
  	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
1176
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1177
  	kmem_cache_free(cfq_ioc_pool, cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1179
1180
1181
1182
  /*
   * Called with interrupts disabled
   */
  static void cfq_exit_single_io_context(struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1184
1185
1186
1187
1188
1189
1190
1191
  	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...
1192
1193
  		__cfq_slice_expired(cfqd, cic->cfqq, 0);
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1194
1195
1196
1197
1198
  	}
  
  	cfq_put_queue(cic->cfqq);
  	cic->cfqq = NULL;
  	spin_unlock(q->queue_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
1200
1201
  }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1202
1203
   * 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
1204
1205
1206
   */
  static void cfq_exit_io_context(struct cfq_io_context *cic)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1207
1208
  	struct cfq_io_context *__cic;
  	struct list_head *entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
  	unsigned long flags;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1210
  	local_irq_save(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
1213
  	/*
  	 * put the reference this task is holding to the various queues
  	 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1214
  	list_for_each(entry, &cic->list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1215
  		__cic = list_entry(entry, struct cfq_io_context, list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1216
  		cfq_exit_single_io_context(__cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1218
1219
  	cfq_exit_single_io_context(cic);
  	local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1221
  static struct cfq_io_context *
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1222
  cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1224
  	struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
1226
  
  	if (cic) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
  		INIT_LIST_HEAD(&cic->list);
  		cic->cfqq = NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1229
1230
1231
1232
1233
1234
1235
  		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
1236
1237
1238
1239
  	}
  
  	return cic;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1240
1241
1242
1243
  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...
1244
  	if (!cfq_cfqq_prio_changed(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
  		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...
1270
  			cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1271
1272
1273
1274
1275
1276
1277
1278
1279
  			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...
1280
  	if (cfq_cfqq_on_rr(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1281
  		cfq_resort_rr_list(cfqq, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1282
  	cfq_clear_cfqq_prio_changed(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1283
1284
1285
1286
1287
1288
1289
1290
  }
  
  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...
1291
  		cfq_mark_cfqq_prio_changed(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
  		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...
1313
  cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1314
  	      gfp_t gfp_mask)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1315
1316
1317
1318
1319
  {
  	const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
  	struct cfq_queue *cfqq, *new_cfqq = NULL;
  
  retry:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1320
  	cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1321
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
  
  	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...
1354
1355
1356
  		cfq_mark_cfqq_idle_window(cfqq);
  		cfq_mark_cfqq_prio_changed(cfqq);
  		cfq_init_prio_data(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
  	}
  
  	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
1367
1368
1369
1370
1371
1372
1373
  /*
   * 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...
1374
  cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1376
  	struct io_context *ioc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
  	struct cfq_io_context *cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1381
  	ioc = get_io_context(gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
1384
1385
  	if (!ioc)
  		return NULL;
  
  	if ((cic = ioc->cic) == NULL) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1386
  		cic = cfq_alloc_io_context(cfqd, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
1389
  
  		if (cic == NULL)
  			goto err;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1390
1391
1392
1393
  		/*
  		 * 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
1394
  		ioc->cic = cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1395
  		ioc->set_ioprio = cfq_ioc_set_ioprio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  		cic->ioc = ioc;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1397
1398
  		cic->key = cfqd;
  		atomic_inc(&cfqd->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399
1400
  	} else {
  		struct cfq_io_context *__cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
1402
  
  		/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1403
  		 * the first cic on the list is actually the head itself
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1404
  		 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1405
  		if (cic->key == cfqd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
1408
1409
1410
1411
1412
  			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
1413
1414
1415
1416
1417
  		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...
1418
  			if (__cic->key == cfqd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
  				cic = __cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
1421
1422
  				goto out;
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423
1424
1425
1426
1427
  
  		/*
  		 * 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...
1428
  		__cic = cfq_alloc_io_context(cfqd, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
1430
1431
1432
  		if (__cic == NULL)
  			goto err;
  
  		__cic->ioc = ioc;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1433
1434
  		__cic->key = cfqd;
  		atomic_inc(&cfqd->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
  		list_add(&__cic->list, &cic->list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1436
  		cic = __cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
1438
1439
  	}
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1440
1441
1442
1443
1444
  	return cic;
  err:
  	put_io_context(ioc);
  	return NULL;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1445
1446
  static void
  cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1448
  	unsigned long elapsed, ttime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1449

22e2c507c   Jens Axboe   [PATCH] Update cf...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  	/*
  	 * 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
1462

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1465
1466
1467
1468
  	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
1469

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1472
1473
1474
1475
1476
1477
1478
1479
  /*
   * 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...
1480
  	int enable_idle = cfq_cfqq_idle_window(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481

22e2c507c   Jens Axboe   [PATCH] Update cf...
1482
1483
1484
1485
1486
1487
1488
  	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
1489
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1490
1491
1492
1493
  	if (enable_idle)
  		cfq_mark_cfqq_idle_window(cfqq);
  	else
  		cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1494
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495

22e2c507c   Jens Axboe   [PATCH] Update cf...
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
  
  /*
   * 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...
1515
  	if (!cfq_cfqq_wait_request(new_cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1516
1517
1518
1519
1520
1521
  		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...
1522
  	if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
  		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...
1543
  	__cfq_slice_expired(cfqd, cfqq, 1);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
  	__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...
1568
  	struct cfq_io_context *cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1569
1570
  
  	cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1571
1572
1573
1574
1575
1576
  	/*
  	 * 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...
1577

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

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1580
1581
1582
1583
  	cfq_update_io_thinktime(cfqd, cic);
  	cfq_update_idle_window(cfqd, cfqq, cic);
  
  	cic->last_queue = jiffies;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1584
1585
1586
1587
1588
1589
1590
  
  	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...
1591
1592
  		if (cfq_cfqq_wait_request(cfqq)) {
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
  			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...
1603
  		cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1604
1605
  		cfq_start_queueing(cfqd, cfqq);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1607
  static void cfq_insert_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1609
  	struct cfq_data *cfqd = q->elevator->elevator_data;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1610
1611
1612
1613
  	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
1614
1615
  
  	cfq_add_crq_rb(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616

22e2c507c   Jens Axboe   [PATCH] Update cf...
1617
  	list_add_tail(&rq->queuelist, &cfqq->fifo);
98b11471d   Tejun Heo   [PATCH] 04/05 rem...
1618
  	if (rq_mergeable(rq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1619
  		cfq_add_crq_hash(cfqd, crq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1620
  	cfq_crq_enqueued(cfqd, cfqq, crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1621
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1622
1623
1624
  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...
1625
1626
1627
1628
  	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
1629

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1632
1633
1634
1635
  	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
1636

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1640
1641
1642
1643
1644
1645
1646
1647
1648
  	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
1649
  	}
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1650
1651
  	if (cfq_crq_is_sync(crq))
  		crq->io_context->last_end_request = now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
  }
  
  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...
1677
1678
1679
1680
1681
  /*
   * 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
1682
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1683
1684
  	const int ioprio_class = cfqq->ioprio_class;
  	const int ioprio = cfqq->ioprio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685

22e2c507c   Jens Axboe   [PATCH] Update cf...
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
  	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
1704

22e2c507c   Jens Axboe   [PATCH] Update cf...
1705
1706
1707
1708
  	/*
  	 * 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...
1709
  	    cfq_cfqq_on_rr(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1710
1711
  		cfq_resort_rr_list(cfqq, 0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712

22e2c507c   Jens Axboe   [PATCH] Update cf...
1713
1714
1715
1716
  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
1717

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1721
1722
1723
1724
  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...
1725
1726
  #if 1
  	if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
99f95e528   Andrew Morton   [PATCH] cfq build...
1727
  	    !cfq_cfqq_must_alloc_slice(cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1728
  		cfq_mark_cfqq_must_alloc_slice(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1729
  		return ELV_MQUEUE_MUST;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1730
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1740
1741
1742
1743
  		/*
  		 * 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...
1744
  		if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1745
  			cfq_mark_cfqq_must_alloc_slice(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1746
  			return ELV_MQUEUE_MUST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1748
1749
  
  		return ELV_MQUEUE_MAY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1751
1752
1753
1754
1755
  	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
1756

22e2c507c   Jens Axboe   [PATCH] Update cf...
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
  		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...
1780
  	cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1781
1782
1783
1784
1785
1786
1787
1788
  	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
1789
1790
1791
1792
  }
  
  static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1793
  	struct cfq_data *cfqd = q->elevator->elevator_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
  	struct request_list *rl = &q->rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1795

22e2c507c   Jens Axboe   [PATCH] Update cf...
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
  	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
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
  }
  
  /*
   * 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...
1819
  		const int rw = rq_data_dir(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820

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

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

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1861
1862
1863
  		cic->cfqq = cfqq;
  	} else
  		cfqq = cic->cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1864
1865
  
  	cfqq->allocated[rw]++;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1866
  	cfq_clear_cfqq_must_alloc(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1867
1868
  	cfqd->rq_starved = 0;
  	atomic_inc(&cfqq->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1869
  	spin_unlock_irqrestore(q->queue_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870
1871
1872
1873
1874
1875
1876
1877
  	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...
1878
1879
1880
1881
1882
  
  		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
1883
  		rq->elevator_private = crq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1884
1885
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
1887
  	spin_lock_irqsave(q->queue_lock, flags);
  	cfqq->allocated[rw]--;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1888
  	if (!(cfqq->allocated[0] + cfqq->allocated[1]))
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1889
  		cfq_mark_cfqq_must_alloc(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
  	cfq_put_queue(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1891
1892
1893
1894
1895
1896
1897
1898
1899
  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...
1900
  	cfq_schedule_dispatch(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
1902
1903
  	spin_unlock_irqrestore(q->queue_lock, flags);
  	return 1;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1904
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
  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...
1955
  		if (!cfqd->busy_queues) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1956
1957
1958
1959
1960
1961
1962
1963
1964
  			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...
1965
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1966
1967
1968
1969
1970
1971
  			goto out_kick;
  		}
  	}
  expire:
  	cfq_slice_expired(cfqd, 0);
  out_kick:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1972
  	cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
  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...
1995
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1996
1997
1998
  
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1999
2000
2001
2002
2003
2004
  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...
2005

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2006
2007
2008
2009
2010
2011
  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...
2012
  	cfq_shutdown_timer_wq(cfqd);
4fc207419   Jens Axboe   [PATCH] Fix on-th...
2013
  	blk_put_queue(q);
96c51ce94   Jens Axboe   [PATCH] CFQ io sc...
2014

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015
2016
2017
2018
2019
2020
2021
2022
  	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...
2023
  	struct cfq_data *cfqd = e->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2024
  	cfq_shutdown_timer_wq(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2025
  	cfq_put_cfqd(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
  }
  
  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...
2038
2039
2040
2041
2042
2043
2044
  
  	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
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
  	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...
2067
  	atomic_inc(&q->refcnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068

22e2c507c   Jens Axboe   [PATCH] Update cf...
2069
  	cfqd->max_queued = q->nr_requests / 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
  	q->nr_batching = cfq_queued;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
  
  	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
2081
2082
2083
2084
  	atomic_set(&cfqd->ref, 1);
  
  	cfqd->cfq_queued = cfq_queued;
  	cfqd->cfq_quantum = cfq_quantum;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2085
2086
  	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
2087
2088
  	cfqd->cfq_back_max = cfq_back_max;
  	cfqd->cfq_back_penalty = cfq_back_penalty;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2089
2090
2091
2092
2093
  	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...
2094

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2095
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
  	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
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
  /*
   * 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
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
  #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...
2171
2172
  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
2173
2174
  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...
2175
2176
2177
2178
2179
  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
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
  #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...
2199
2200
  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
2201
2202
  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...
2203
2204
2205
2206
2207
  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
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
  #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...
2220
  static struct cfq_fs_entry cfq_fifo_expire_sync_entry = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2221
  	.attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR },
22e2c507c   Jens Axboe   [PATCH] Update cf...
2222
2223
  	.show = cfq_fifo_expire_sync_show,
  	.store = cfq_fifo_expire_sync_store,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2224
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
2225
  static struct cfq_fs_entry cfq_fifo_expire_async_entry = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2226
  	.attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR },
22e2c507c   Jens Axboe   [PATCH] Update cf...
2227
2228
  	.show = cfq_fifo_expire_async_show,
  	.store = cfq_fifo_expire_async_store,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
  };
  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...
2240
2241
2242
2243
  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
2244
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
  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
2264
  };
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2265

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2266
2267
2268
  static struct attribute *default_attrs[] = {
  	&cfq_quantum_entry.attr,
  	&cfq_queued_entry.attr,
22e2c507c   Jens Axboe   [PATCH] Update cf...
2269
2270
  	&cfq_fifo_expire_sync_entry.attr,
  	&cfq_fifo_expire_async_entry.attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2271
2272
  	&cfq_back_max_entry.attr,
  	&cfq_back_penalty_entry.attr,
22e2c507c   Jens Axboe   [PATCH] Update cf...
2273
2274
2275
2276
2277
  	&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
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
  	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...
2290
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
  
  	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...
2303
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
  
  	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...
2323
  		.elevator_dispatch_fn =		cfq_dispatch_requests,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2324
  		.elevator_add_req_fn =		cfq_insert_request,
b4878f245   Jens Axboe   [PATCH] 02/05: up...
2325
  		.elevator_activate_req_fn =	cfq_activate_request,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
  		.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...
2345
2346
2347
2348
2349
2350
2351
  	/*
  	 * 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
2352
2353
2354
2355
  	if (cfq_slab_setup())
  		return -ENOMEM;
  
  	ret = elv_register(&iosched_cfq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2356
2357
  	if (ret)
  		cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2358

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