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
   *  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>
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
  #include <linux/config.h>
  #include <linux/module.h>
1cc9be68e   Al Viro   [PATCH] noise rem...
11
12
  #include <linux/blkdev.h>
  #include <linux/elevator.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
  #include <linux/hash.h>
  #include <linux/rbtree.h>
22e2c507c   Jens Axboe   [PATCH] Update cf...
15
  #include <linux/ioprio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
  
  /*
   * tunables
   */
64100099e   Arjan van de Ven   [BLOCK] mark some...
20
21
22
23
24
  static const int cfq_quantum = 4;		/* max queue in one round of service */
  static const int cfq_queued = 8;		/* minimum rq allocate limit per-queue*/
  static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
  static const int cfq_back_max = 16 * 1024;	/* maximum backwards seek, in KiB */
  static const int cfq_back_penalty = 2;		/* penalty of a backwards seek */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

64100099e   Arjan van de Ven   [BLOCK] mark some...
26
  static const int cfq_slice_sync = HZ / 10;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
27
  static int cfq_slice_async = HZ / 25;
64100099e   Arjan van de Ven   [BLOCK] mark some...
28
  static const int cfq_slice_async_rq = 2;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
29
  static int cfq_slice_idle = HZ / 125;
22e2c507c   Jens Axboe   [PATCH] Update cf...
30
31
32
33
34
  
  #define CFQ_IDLE_GRACE		(HZ / 10)
  #define CFQ_SLICE_SCALE		(5)
  
  #define CFQ_KEY_ASYNC		(0)
22e2c507c   Jens Axboe   [PATCH] Update cf...
35

3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
36
  static DEFINE_SPINLOCK(cfq_exit_lock);
a6a0763a6   Al Viro   [PATCH] fix the e...
37

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  /*
   * 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...
56
  #define list_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
  
  #define RQ_DATA(rq)		(rq)->elevator_private
  
  /*
   * rb-tree defines
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  #define RB_EMPTY(node)		((node)->rb_node == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  #define RB_CLEAR(node)		do {	\
3db3a4453   David Woodhouse   [RBTREE] Change r...
65
  		memset(node, 0, sizeof(*node)); \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
  } while (0)
  #define RB_CLEAR_ROOT(root)	((root)->rb_node = NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
  #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
70
71
72
  static kmem_cache_t *crq_pool;
  static kmem_cache_t *cfq_pool;
  static kmem_cache_t *cfq_ioc_pool;
334e94de9   Al Viro   [PATCH] deal with...
73
74
  static atomic_t ioc_count = ATOMIC_INIT(0);
  static struct completion *ioc_gone;
22e2c507c   Jens Axboe   [PATCH] Update cf...
75
76
77
78
  #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...
79
80
81
82
83
84
85
86
87
88
  #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...
89

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
90
  #define sample_valid(samples)	((samples) > 80)
22e2c507c   Jens Axboe   [PATCH] Update cf...
91
92
93
  /*
   * Per block device queue structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  struct cfq_data {
22e2c507c   Jens Axboe   [PATCH] Update cf...
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  	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
109
  	struct list_head empty_list;
22e2c507c   Jens Axboe   [PATCH] Update cf...
110
111
112
  	/*
  	 * cfqq lookup hash
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  	struct hlist_head *cfq_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114

22e2c507c   Jens Axboe   [PATCH] Update cf...
115
116
117
118
  	/*
  	 * global crq hash for all queues
  	 */
  	struct hlist_head *crq_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119

22e2c507c   Jens Axboe   [PATCH] Update cf...
120
  	mempool_t *crq_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121

22e2c507c   Jens Axboe   [PATCH] Update cf...
122
  	int rq_in_driver;
25776e359   Jens Axboe   [PATCH] cfq-iosch...
123
  	int hw_tag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124

22e2c507c   Jens Axboe   [PATCH] Update cf...
125
126
127
128
129
130
131
132
  	/*
  	 * 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
133

22e2c507c   Jens Axboe   [PATCH] Update cf...
134
135
136
137
138
139
  	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
140
141
  
  	sector_t last_sector;
22e2c507c   Jens Axboe   [PATCH] Update cf...
142
  	unsigned long last_end_request;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

22e2c507c   Jens Axboe   [PATCH] Update cf...
144
  	unsigned int rq_starved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
  
  	/*
  	 * tunables, see top of file
  	 */
  	unsigned int cfq_quantum;
  	unsigned int cfq_queued;
22e2c507c   Jens Axboe   [PATCH] Update cf...
151
  	unsigned int cfq_fifo_expire[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
  	unsigned int cfq_back_penalty;
  	unsigned int cfq_back_max;
22e2c507c   Jens Axboe   [PATCH] Update cf...
154
155
156
  	unsigned int cfq_slice[2];
  	unsigned int cfq_slice_async_rq;
  	unsigned int cfq_slice_idle;
d9ff41879   Al Viro   [PATCH] make cfq_...
157
158
  
  	struct list_head cic_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
160
161
162
  /*
   * Per process-grouping structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
  struct cfq_queue {
  	/* reference count */
  	atomic_t ref;
  	/* parent cfq_data */
  	struct cfq_data *cfqd;
22e2c507c   Jens Axboe   [PATCH] Update cf...
168
  	/* cfqq lookup hash */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
  	struct hlist_node cfq_hash;
  	/* hash key */
22e2c507c   Jens Axboe   [PATCH] Update cf...
171
  	unsigned int key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
176
177
178
179
180
181
182
  	/* 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...
183
  	struct list_head fifo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

22e2c507c   Jens Axboe   [PATCH] Update cf...
185
186
187
188
  	unsigned long slice_start;
  	unsigned long slice_end;
  	unsigned long slice_left;
  	unsigned long service_last;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
190
191
  	/* number of requests that are on the dispatch list */
  	int on_dispatch[2];
22e2c507c   Jens Axboe   [PATCH] Update cf...
192
193
194
195
  
  	/* io prio of this group */
  	unsigned short ioprio, org_ioprio;
  	unsigned short ioprio_class, org_ioprio_class;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
196
197
  	/* various state flags, see below */
  	unsigned int flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
201
202
203
204
205
206
207
  };
  
  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...
208
  	unsigned int crq_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  };
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
210
211
212
213
214
215
216
217
218
  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,
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  };
  
  #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);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
243
244
245
  #undef CFQ_CFQQ_FNS
  
  enum cfq_rq_state_flags {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
246
  	CFQ_CRQ_FLAG_is_sync = 0,
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  };
  
  #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...
262
  CFQ_CRQ_FNS(is_sync);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
263
264
265
  #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...
266
  static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
6f325a134   Al Viro   [PATCH] fix cfq_g...
267
  static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
275
  /*
   * 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
276
277
278
  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
279
280
281
282
283
284
285
286
287
288
289
  	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
290
291
292
293
294
295
296
297
298
299
300
  		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...
301
302
303
304
305
306
  /*
   * 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)
  {
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
307
  	if (cfqd->busy_queues)
99f95e528   Andrew Morton   [PATCH] cfq build...
308
309
310
311
312
313
  		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...
314
  	return !cfqd->busy_queues;
99f95e528   Andrew Morton   [PATCH] cfq build...
315
  }
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
316
317
  static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
  {
b31dc66a5   Jens Axboe   [PATCH] Kill PF_S...
318
  	if (rw == READ || rw == WRITE_SYNC)
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
319
320
321
322
  		return task->pid;
  
  	return CFQ_KEY_ASYNC;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
  /*
   * 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
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
326
   * behind the head is penalized and only allowed to a certain extent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
   */
  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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  	unsigned long back_max;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
333
334
335
  #define CFQ_RQ1_WRAP	0x01 /* request 1 wraps */
  #define CFQ_RQ2_WRAP	0x02 /* request 2 wraps */
  	unsigned wrap = 0; /* bit mask: requests behind the disk head? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
340
  
  	if (crq1 == NULL || crq1 == crq2)
  		return crq2;
  	if (crq2 == NULL)
  		return crq1;
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
341

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
342
343
344
  	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...
345
  		return crq2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
  
  	s1 = crq1->request->sector;
  	s2 = crq2->request->sector;
  
  	last = cfqd->last_sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  	/*
  	 * 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
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
366
  		wrap |= CFQ_RQ1_WRAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
370
371
372
  
  	if (s2 >= last)
  		d2 = s2 - last;
  	else if (s2 + back_max >= last)
  		d2 = (last - s2) * cfqd->cfq_back_penalty;
  	else
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
373
  		wrap |= CFQ_RQ2_WRAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
  
  	/* Found required data */
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
376
377
378
379
380
381
382
383
  
  	/*
  	 * By doing switch() on the bit mask "wrap" we avoid having to
  	 * check two variables for all permutations: --> faster!
  	 */
  	switch (wrap) {
  	case 0: /* common case for CFQ: crq1 and crq2 not wrapped */
  		if (d1 < d2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  			return crq1;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
385
  		else if (d2 < d1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
  			return crq2;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
387
388
389
390
391
392
  		else {
  			if (s1 >= s2)
  				return crq1;
  			else
  				return crq2;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393

e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
394
  	case CFQ_RQ2_WRAP:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  		return crq1;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
396
  	case CFQ_RQ1_WRAP:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  		return crq2;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
398
399
400
401
402
403
404
405
406
  	case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */
  	default:
  		/*
  		 * Since both rqs are wrapped,
  		 * start with the one that's further behind head
  		 * (--> only *one* back seek required),
  		 * since back seek takes more time than forward.
  		 */
  		if (s1 <= s2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  			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...
422
  	if (!(rbnext = rb_next(&last->rb_node))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  		rbnext = rb_first(&cfqq->sort_list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
424
425
426
  		if (rbnext == &last->rb_node)
  			rbnext = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  
  	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...
445
  static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
447
448
  	struct cfq_data *cfqd = cfqq->cfqd;
  	struct list_head *list, *entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449

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

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

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

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

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

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
538
539
  	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
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
  }
  
  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...
573
  	cfqq->queued[cfq_crq_is_sync(crq)]++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
576
577
578
579
  
  	/*
  	 * 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...
580
  		cfq_dispatch_insert(cfqd->queue, __alias);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
  
  	rb_insert_color(&crq->rb_node, &cfqq->sort_list);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
583
  	if (!cfq_cfqq_on_rr(cfqq))
b4878f245   Jens Axboe   [PATCH] 02/05: up...
584
  		cfq_add_cfqq_rr(cfqd, cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
589
590
591
592
593
594
  
  	/*
  	 * 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...
595
596
  	rb_erase(&crq->rb_node, &cfqq->sort_list);
  	cfqq->queued[cfq_crq_is_sync(crq)]--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
  
  	cfq_add_crq_rb(crq);
  }
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
600
601
  static struct request *
  cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  {
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
603
604
605
  	struct task_struct *tsk = current;
  	pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio));
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
  	struct rb_node *n;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
607
  	sector_t sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
609
  	cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
  	if (!cfqq)
  		goto out;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
612
  	sector = bio->bi_sector + bio_sectors(bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  	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...
628
  static void cfq_activate_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
630
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
631

b4878f245   Jens Axboe   [PATCH] 02/05: up...
632
  	cfqd->rq_in_driver++;
25776e359   Jens Axboe   [PATCH] cfq-iosch...
633
634
635
636
637
638
639
640
641
  
  	/*
  	 * If the depth is larger 1, it really could be queueing. But lets
  	 * make the mark a little higher - idling could still be good for
  	 * low queueing, and a low queueing number could also just indicate
  	 * a SCSI mid layer like behaviour where limit+1 is often seen.
  	 */
  	if (!cfqd->hw_tag && cfqd->rq_in_driver > 4)
  		cfqd->hw_tag = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
643
  static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
645
646
647
648
  	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
649
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
650
  static void cfq_remove_request(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  {
  	struct cfq_rq *crq = RQ_DATA(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
653
654
  	list_del_init(&rq->queuelist);
  	cfq_del_crq_rb(crq);
98b11471d   Tejun Heo   [PATCH] 04/05 rem...
655
  	cfq_del_crq_hash(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
661
662
663
  }
  
  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
664
  	__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
22e2c507c   Jens Axboe   [PATCH] Update cf...
665
666
667
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
  		ret = ELEVATOR_BACK_MERGE;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
  	}
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
669
  	__rq = cfq_find_rq_fmerge(cfqd, bio);
22e2c507c   Jens Axboe   [PATCH] Update cf...
670
671
672
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
  		ret = ELEVATOR_FRONT_MERGE;
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
  	}
  
  	return ELEVATOR_NO_MERGE;
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
682
683
684
685
686
687
  	*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...
688
  	if (rq_rb_key(req) != crq->rb_key) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
690
691
692
693
  		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
694
695
696
697
698
699
  }
  
  static void
  cfq_merged_requests(request_queue_t *q, struct request *rq,
  		    struct request *next)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  	cfq_merged_request(q, rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
701
702
703
704
705
706
  	/*
  	 * 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...
707
  	cfq_remove_request(next);
22e2c507c   Jens Axboe   [PATCH] Update cf...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  }
  
  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...
722
723
  		cfq_clear_cfqq_must_alloc_slice(cfqq);
  		cfq_clear_cfqq_fifo_expire(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
724
725
726
727
728
729
  	}
  
  	cfqd->active_queue = cfqq;
  }
  
  /*
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
   * current cfqq expired its slice (or was too idle), select new one
   */
  static void
  __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		    int preempted)
  {
  	unsigned long now = jiffies;
  
  	if (cfq_cfqq_wait_request(cfqq))
  		del_timer(&cfqd->idle_slice_timer);
  
  	if (!preempted && !cfq_cfqq_dispatched(cfqq)) {
  		cfqq->service_last = now;
  		cfq_schedule_dispatch(cfqd);
  	}
  
  	cfq_clear_cfqq_must_dispatch(cfqq);
  	cfq_clear_cfqq_wait_request(cfqq);
  
  	/*
  	 * store what was left of this slice, if the queue idled out
  	 * or was preempted
  	 */
  	if (time_after(cfqq->slice_end, now))
  		cfqq->slice_left = cfqq->slice_end - now;
  	else
  		cfqq->slice_left = 0;
  
  	if (cfq_cfqq_on_rr(cfqq))
  		cfq_resort_rr_list(cfqq, preempted);
  
  	if (cfqq == cfqd->active_queue)
  		cfqd->active_queue = NULL;
  
  	if (cfqd->active_cic) {
  		put_io_context(cfqd->active_cic->ioc);
  		cfqd->active_cic = NULL;
  	}
  
  	cfqd->dispatch_slice = 0;
  }
  
  static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted)
  {
  	struct cfq_queue *cfqq = cfqd->active_queue;
  
  	if (cfqq)
  		__cfq_slice_expired(cfqd, cfqq, preempted);
  }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
   * 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
814
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
  	} 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
832
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
833
834
  	return prio;
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
835
  static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
22e2c507c   Jens Axboe   [PATCH] Update cf...
836
  {
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
837
  	struct cfq_queue *cfqq = NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
838
839
840
841
842
843
844
845
846
  
  	/*
  	 * 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);
  
  	/*
e0de0206a   Jens Axboe   [PATCH] cfq-iosch...
847
848
849
850
851
852
853
  	 * If no new queues are available, check if the busy list has some
  	 * before falling back to idle io.
  	 */
  	if (!cfqq && !list_empty(&cfqd->busy_rr))
  		cfqq = list_entry_cfqq(cfqd->busy_rr.next);
  
  	/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
  	 * 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...
868
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
869
  }
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
870
  #define CIC_SEEKY(cic) ((cic)->seek_mean > (128 * 1024))
22e2c507c   Jens Axboe   [PATCH] Update cf...
871
872
873
  static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  
  {
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
874
  	struct cfq_io_context *cic;
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
875
  	unsigned long sl;
22e2c507c   Jens Axboe   [PATCH] Update cf...
876
877
878
879
880
881
882
883
  	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...
884
  	if (!cfq_cfqq_idle_window(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
885
886
887
888
  		return 0;
  	/*
  	 * task has exited, don't wait
  	 */
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
889
890
  	cic = cfqd->active_cic;
  	if (!cic || !cic->ioc->task)
22e2c507c   Jens Axboe   [PATCH] Update cf...
891
  		return 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
892
893
  	cfq_mark_cfqq_must_dispatch(cfqq);
  	cfq_mark_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
894

7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
895
  	sl = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
896
897
898
899
900
901
  
  	/*
  	 * we don't want to idle for seeks, but we do want to allow
  	 * fair distribution of slice time for a process doing back-to-back
  	 * seeks. so allow a little bit of time for him to submit a new rq
  	 */
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
902
  	if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
903
  		sl = 2;
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
904
  	mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
22e2c507c   Jens Axboe   [PATCH] Update cf...
905
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
907
  static void cfq_dispatch_insert(request_queue_t *q, struct cfq_rq *crq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct cfq_queue *cfqq = crq->cfq_queue;
fd61af038   Jens Axboe   [PATCH] cfq-iosch...
911
  	struct request *rq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
912
913
  
  	cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
914
  	cfq_remove_request(crq->request);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
915
  	cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
916
  	elv_dispatch_sort(q, crq->request);
fd61af038   Jens Axboe   [PATCH] cfq-iosch...
917
918
919
  
  	rq = list_entry(q->queue_head.prev, struct request, queuelist);
  	cfqd->last_sector = rq->sector + rq->nr_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
921
922
923
924
925
926
927
  }
  
  /*
   * 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...
928
  	struct request *rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
  	struct cfq_rq *crq;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
930
  	if (cfq_cfqq_fifo_expire(cfqq))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
  		return NULL;
22e2c507c   Jens Axboe   [PATCH] Update cf...
932
  	if (!list_empty(&cfqq->fifo)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
933
  		int fifo = cfq_cfqq_class_sync(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934

22e2c507c   Jens Axboe   [PATCH] Update cf...
935
936
937
  		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...
938
  			cfq_mark_cfqq_fifo_expire(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
939
940
  			return crq;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
944
945
946
  	}
  
  	return NULL;
  }
  
  /*
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
947
948
949
   * 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
950
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
951
952
953
954
955
956
957
958
959
  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
960
  static inline void
22e2c507c   Jens Axboe   [PATCH] Update cf...
961
  cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
963
964
  	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965

22e2c507c   Jens Axboe   [PATCH] Update cf...
966
967
968
969
  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
970

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
973
  	return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
975
976
977
  /*
   * get next queue for service
   */
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
978
  static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
980
  	unsigned long now = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982

22e2c507c   Jens Axboe   [PATCH] Update cf...
983
984
985
  	cfqq = cfqd->active_queue;
  	if (!cfqq)
  		goto new_queue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986

22e2c507c   Jens Axboe   [PATCH] Update cf...
987
988
989
  	/*
  	 * slice has expired
  	 */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
990
991
  	if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end))
  		goto expire;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992

22e2c507c   Jens Axboe   [PATCH] Update cf...
993
994
995
996
997
998
  	/*
  	 * 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;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
999
1000
1001
1002
  	else if (cfq_cfqq_dispatched(cfqq)) {
  		cfqq = NULL;
  		goto keep_queue;
  	} else if (cfq_cfqq_class_sync(cfqq)) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1003
1004
1005
  		if (cfq_arm_slice_timer(cfqd, cfqq))
  			return NULL;
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1006
  expire:
22e2c507c   Jens Axboe   [PATCH] Update cf...
1007
  	cfq_slice_expired(cfqd, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1008
1009
  new_queue:
  	cfqq = cfq_set_active_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1010
  keep_queue:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1011
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  }
  
  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
1024
1025
  
  		/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1026
  		 * follow expired path, else get first next available
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
  		 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1028
1029
1030
1031
1032
1033
  		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...
1034
  		cfq_dispatch_insert(cfqd->queue, crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1035

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1039
1040
1041
1042
  		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
1043

22e2c507c   Jens Axboe   [PATCH] Update cf...
1044
1045
1046
1047
1048
1049
  		if (RB_EMPTY(&cfqq->sort_list))
  			break;
  
  	} while (dispatched < max_dispatch);
  
  	/*
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1050
  	 * if slice end isn't set yet, set it.
22e2c507c   Jens Axboe   [PATCH] Update cf...
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
  	 */
  	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)) ||
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1061
1062
  	    cfq_class_idle(cfqq) ||
  	    !cfq_cfqq_idle_window(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1063
1064
1065
1066
1067
1068
  		cfq_slice_expired(cfqd, 0);
  
  	return dispatched;
  }
  
  static int
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1069
1070
  cfq_forced_dispatch_cfqqs(struct list_head *list)
  {
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1071
1072
  	struct cfq_queue *cfqq, *next;
  	struct cfq_rq *crq;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1073
  	int dispatched;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1074

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1075
  	dispatched = 0;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1076
1077
1078
1079
1080
1081
1082
  	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));
  	}
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1083

1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  	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...
1107
  cfq_dispatch_requests(request_queue_t *q, int force)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1108
1109
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1110
1111
  	struct cfq_queue *cfqq, *prev_cfqq;
  	int dispatched;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1112
1113
1114
  
  	if (!cfqd->busy_queues)
  		return 0;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1115
1116
  	if (unlikely(force))
  		return cfq_forced_dispatch(cfqd);
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1117
1118
1119
  	dispatched = 0;
  	prev_cfqq = NULL;
  	while ((cfqq = cfq_select_queue(cfqd)) != NULL) {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1120
  		int max_dispatch;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1121
1122
1123
1124
1125
  		/*
  		 * Don't repeat dispatch from the previous queue.
  		 */
  		if (prev_cfqq == cfqq)
  			break;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1126
1127
  		cfq_clear_cfqq_must_dispatch(cfqq);
  		cfq_clear_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1128
  		del_timer(&cfqd->idle_slice_timer);
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1129
1130
1131
  		max_dispatch = cfqd->cfq_quantum;
  		if (cfq_class_idle(cfqq))
  			max_dispatch = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
  		dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
  
  		/*
  		 * If the dispatch cfqq has idling enabled and is still
  		 * the active queue, break out.
  		 */
  		if (cfq_cfqq_idle_window(cfqq) && cfqd->active_queue)
  			break;
  
  		prev_cfqq = cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
  	}
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1144
  	return dispatched;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
1147
1148
1149
1150
1151
1152
1153
  /*
   * 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...
1154
1155
1156
  	struct cfq_data *cfqd = cfqq->cfqd;
  
  	BUG_ON(atomic_read(&cfqq->ref) <= 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
1158
1159
1160
1161
  
  	if (!atomic_dec_and_test(&cfqq->ref))
  		return;
  
  	BUG_ON(rb_first(&cfqq->sort_list));
22e2c507c   Jens Axboe   [PATCH] Update cf...
1162
  	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1163
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164

7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
1165
  	if (unlikely(cfqd->active_queue == cfqq))
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1166
  		__cfq_slice_expired(cfqd, cfqq, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1167

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
1170
1171
1172
1173
1174
1175
1176
  	/*
  	 * 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...
1177
1178
  __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
1179
1180
  {
  	struct hlist_head *hash_list = &cfqd->cfq_hash[hashval];
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1181
1182
  	struct hlist_node *entry;
  	struct cfq_queue *__cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1184
  	hlist_for_each_entry(__cfqq, entry, hash_list, cfq_hash) {
b0a6916bc   Al Viro   [PATCH] fix cfq h...
1185
  		const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1187
  		if (__cfqq->key == key && (__p == prio || !prio))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
1191
1192
1193
1194
  			return __cfqq;
  	}
  
  	return NULL;
  }
  
  static struct cfq_queue *
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1195
  cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1196
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1197
  	return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
  }
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1199
  static void cfq_free_io_context(struct io_context *ioc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1201
  	struct cfq_io_context *__cic;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1202
1203
  	struct rb_node *n;
  	int freed = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1205
1206
1207
  	while ((n = rb_first(&ioc->cic_root)) != NULL) {
  		__cic = rb_entry(n, struct cfq_io_context, rb_node);
  		rb_erase(&__cic->rb_node, &ioc->cic_root);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1208
  		kmem_cache_free(cfq_ioc_pool, __cic);
334e94de9   Al Viro   [PATCH] deal with...
1209
  		freed++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
  	}
334e94de9   Al Viro   [PATCH] deal with...
1211
1212
  	if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone)
  		complete(ioc_gone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
  }
e17a9489b   Al Viro   [PATCH] stop elv_...
1214
1215
1216
  static void cfq_trim(struct io_context *ioc)
  {
  	ioc->set_ioprio = NULL;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1217
  	cfq_free_io_context(ioc);
e17a9489b   Al Viro   [PATCH] stop elv_...
1218
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1219
1220
1221
1222
  /*
   * Called with interrupts disabled
   */
  static void cfq_exit_single_io_context(struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
  {
478a82b0e   Al Viro   [PATCH] switch to...
1224
  	struct cfq_data *cfqd = cic->key;
d9ff41879   Al Viro   [PATCH] make cfq_...
1225
1226
1227
1228
1229
1230
  	request_queue_t *q;
  
  	if (!cfqd)
  		return;
  
  	q = cfqd->queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1231
1232
1233
1234
  
  	WARN_ON(!irqs_disabled());
  
  	spin_lock(q->queue_lock);
12a057321   Al Viro   [PATCH] keep sync...
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
  	if (cic->cfqq[ASYNC]) {
  		if (unlikely(cic->cfqq[ASYNC] == cfqd->active_queue))
  			__cfq_slice_expired(cfqd, cic->cfqq[ASYNC], 0);
  		cfq_put_queue(cic->cfqq[ASYNC]);
  		cic->cfqq[ASYNC] = NULL;
  	}
  
  	if (cic->cfqq[SYNC]) {
  		if (unlikely(cic->cfqq[SYNC] == cfqd->active_queue))
  			__cfq_slice_expired(cfqd, cic->cfqq[SYNC], 0);
  		cfq_put_queue(cic->cfqq[SYNC]);
  		cic->cfqq[SYNC] = NULL;
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1248

478a82b0e   Al Viro   [PATCH] switch to...
1249
  	cic->key = NULL;
d9ff41879   Al Viro   [PATCH] make cfq_...
1250
  	list_del_init(&cic->queue_list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1251
  	spin_unlock(q->queue_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
  }
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1253
  static void cfq_exit_io_context(struct io_context *ioc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1255
  	struct cfq_io_context *__cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
  	unsigned long flags;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1257
  	struct rb_node *n;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1258

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
1260
1261
  	/*
  	 * put the reference this task is holding to the various queues
  	 */
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1262
  	spin_lock_irqsave(&cfq_exit_lock, flags);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1263
1264
1265
1266
  
  	n = rb_first(&ioc->cic_root);
  	while (n != NULL) {
  		__cic = rb_entry(n, struct cfq_io_context, rb_node);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1267
  		cfq_exit_single_io_context(__cic);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1268
  		n = rb_next(n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
  	}
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1270
  	spin_unlock_irqrestore(&cfq_exit_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1272
  static struct cfq_io_context *
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1273
  cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1275
  	struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
1277
  
  	if (cic) {
553698f94   Jens Axboe   [PATCH] cfq-iosch...
1278
  		memset(cic, 0, sizeof(*cic));
22e2c507c   Jens Axboe   [PATCH] Update cf...
1279
  		cic->last_end_request = jiffies;
553698f94   Jens Axboe   [PATCH] cfq-iosch...
1280
  		INIT_LIST_HEAD(&cic->queue_list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1281
1282
  		cic->dtor = cfq_free_io_context;
  		cic->exit = cfq_exit_io_context;
334e94de9   Al Viro   [PATCH] deal with...
1283
  		atomic_inc(&ioc_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
1286
1287
  	}
  
  	return cic;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1288
1289
1290
1291
  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...
1292
  	if (!cfq_cfqq_prio_changed(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
  		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...
1318
  			cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1319
1320
1321
1322
1323
1324
1325
1326
1327
  			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...
1328
  	if (cfq_cfqq_on_rr(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1329
  		cfq_resort_rr_list(cfqq, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1330
  	cfq_clear_cfqq_prio_changed(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1331
  }
478a82b0e   Al Viro   [PATCH] switch to...
1332
  static inline void changed_ioprio(struct cfq_io_context *cic)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1333
  {
478a82b0e   Al Viro   [PATCH] switch to...
1334
1335
  	struct cfq_data *cfqd = cic->key;
  	struct cfq_queue *cfqq;
35e6077cb   Jens Axboe   [PATCH] cfq-iosch...
1336

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
  	if (unlikely(!cfqd))
  		return;
  
  	spin_lock(cfqd->queue->queue_lock);
  
  	cfqq = cic->cfqq[ASYNC];
  	if (cfqq) {
  		struct cfq_queue *new_cfqq;
  		new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC, cic->ioc->task,
  					 GFP_ATOMIC);
  		if (new_cfqq) {
  			cic->cfqq[ASYNC] = new_cfqq;
  			cfq_put_queue(cfqq);
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1351
  	}
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1352
1353
1354
1355
1356
1357
  
  	cfqq = cic->cfqq[SYNC];
  	if (cfqq)
  		cfq_mark_cfqq_prio_changed(cfqq);
  
  	spin_unlock(cfqd->queue->queue_lock);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1358
1359
1360
1361
1362
1363
1364
  }
  
  /*
   * callback from sys_ioprio_set, irqs are disabled
   */
  static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
  {
a6a0763a6   Al Viro   [PATCH] fix the e...
1365
  	struct cfq_io_context *cic;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1366
  	struct rb_node *n;
a6a0763a6   Al Viro   [PATCH] fix the e...
1367

3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1368
  	spin_lock(&cfq_exit_lock);
a6a0763a6   Al Viro   [PATCH] fix the e...
1369

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1370
1371
1372
  	n = rb_first(&ioc->cic_root);
  	while (n != NULL) {
  		cic = rb_entry(n, struct cfq_io_context, rb_node);
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1373

478a82b0e   Al Viro   [PATCH] switch to...
1374
  		changed_ioprio(cic);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1375
1376
  		n = rb_next(n);
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1377

3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1378
  	spin_unlock(&cfq_exit_lock);
a6a0763a6   Al Viro   [PATCH] fix the e...
1379

22e2c507c   Jens Axboe   [PATCH] Update cf...
1380
1381
1382
1383
  	return 0;
  }
  
  static struct cfq_queue *
6f325a134   Al Viro   [PATCH] fix cfq_g...
1384
  cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk,
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1385
  	      gfp_t gfp_mask)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1386
1387
1388
  {
  	const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
  	struct cfq_queue *cfqq, *new_cfqq = NULL;
6f325a134   Al Viro   [PATCH] fix cfq_g...
1389
  	unsigned short ioprio;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1390
1391
  
  retry:
6f325a134   Al Viro   [PATCH] fix cfq_g...
1392
  	ioprio = tsk->ioprio;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1393
  	cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
  
  	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;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1421
1422
1423
1424
1425
  		cfqq->service_last = 0;
  		/*
  		 * set ->slice_left to allow preemption for a new process
  		 */
  		cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1426
  		cfq_mark_cfqq_idle_window(cfqq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1427
1428
  		cfq_mark_cfqq_prio_changed(cfqq);
  		cfq_init_prio_data(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
  	}
  
  	if (new_cfqq)
  		kmem_cache_free(cfq_pool, new_cfqq);
  
  	atomic_inc(&cfqq->ref);
  out:
  	WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
  	return cfqq;
  }
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1439
1440
1441
  static void
  cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
  {
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1442
  	spin_lock(&cfq_exit_lock);
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1443
  	rb_erase(&cic->rb_node, &ioc->cic_root);
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1444
1445
  	list_del_init(&cic->queue_list);
  	spin_unlock(&cfq_exit_lock);
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1446
1447
1448
  	kmem_cache_free(cfq_ioc_pool, cic);
  	atomic_dec(&ioc_count);
  }
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1449
1450
1451
  static struct cfq_io_context *
  cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
  {
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1452
  	struct rb_node *n;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1453
  	struct cfq_io_context *cic;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1454
  	void *k, *key = cfqd;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1455

dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1456
1457
  restart:
  	n = ioc->cic_root.rb_node;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1458
1459
  	while (n) {
  		cic = rb_entry(n, struct cfq_io_context, rb_node);
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1460
1461
1462
  		/* ->key must be copied to avoid race with cfq_exit_queue() */
  		k = cic->key;
  		if (unlikely(!k)) {
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1463
1464
1465
  			cfq_drop_dead_cic(ioc, cic);
  			goto restart;
  		}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1466

be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1467
  		if (key < k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1468
  			n = n->rb_left;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1469
  		else if (key > k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
  			n = n->rb_right;
  		else
  			return cic;
  	}
  
  	return NULL;
  }
  
  static inline void
  cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
  	     struct cfq_io_context *cic)
  {
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1482
1483
  	struct rb_node **p;
  	struct rb_node *parent;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1484
  	struct cfq_io_context *__cic;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1485
  	void *k;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1486

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1487
1488
1489
1490
  	cic->ioc = ioc;
  	cic->key = cfqd;
  
  	ioc->set_ioprio = cfq_ioc_set_ioprio;
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1491
1492
1493
  restart:
  	parent = NULL;
  	p = &ioc->cic_root.rb_node;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1494
1495
1496
  	while (*p) {
  		parent = *p;
  		__cic = rb_entry(parent, struct cfq_io_context, rb_node);
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1497
1498
1499
  		/* ->key must be copied to avoid race with cfq_exit_queue() */
  		k = __cic->key;
  		if (unlikely(!k)) {
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1500
1501
1502
  			cfq_drop_dead_cic(ioc, cic);
  			goto restart;
  		}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1503

be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1504
  		if (cic->key < k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1505
  			p = &(*p)->rb_left;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1506
  		else if (cic->key > k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1507
1508
1509
1510
  			p = &(*p)->rb_right;
  		else
  			BUG();
  	}
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1511
  	spin_lock(&cfq_exit_lock);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1512
1513
1514
  	rb_link_node(&cic->rb_node, parent, p);
  	rb_insert_color(&cic->rb_node, &ioc->cic_root);
  	list_add(&cic->queue_list, &cfqd->cic_list);
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
1515
  	spin_unlock(&cfq_exit_lock);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1516
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
1518
1519
  /*
   * 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
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1520
   * than one device managed by cfq.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
   */
  static struct cfq_io_context *
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1523
  cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1525
  	struct io_context *ioc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
  	struct cfq_io_context *cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1527

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1530
  	ioc = get_io_context(gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1531
1532
  	if (!ioc)
  		return NULL;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1533
1534
1535
  	cic = cfq_cic_rb_lookup(cfqd, ioc);
  	if (cic)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1537
1538
1539
  	cic = cfq_alloc_io_context(cfqd, gfp_mask);
  	if (cic == NULL)
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1541
  	cfq_cic_link(cfqd, ioc, cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
1544
1545
1546
1547
  	return cic;
  err:
  	put_io_context(ioc);
  	return NULL;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1548
1549
  static void
  cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1551
  	unsigned long elapsed, ttime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552

22e2c507c   Jens Axboe   [PATCH] Update cf...
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
  	/*
  	 * 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
1565

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1568
1569
1570
1571
  	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
1572

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
  static void
  cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
  		       struct cfq_rq *crq)
  {
  	sector_t sdist;
  	u64 total;
  
  	if (cic->last_request_pos < crq->request->sector)
  		sdist = crq->request->sector - cic->last_request_pos;
  	else
  		sdist = cic->last_request_pos - crq->request->sector;
  
  	/*
  	 * Don't allow the seek distance to get too large from the
  	 * odd fragment, pagein, etc
  	 */
  	if (cic->seek_samples <= 60) /* second&third seek */
  		sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024);
  	else
  		sdist = min(sdist, (cic->seek_mean * 4)	+ 2*1024*64);
  
  	cic->seek_samples = (7*cic->seek_samples + 256) / 8;
  	cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8;
  	total = cic->seek_total + (cic->seek_samples/2);
  	do_div(total, cic->seek_samples);
  	cic->seek_mean = (sector_t)total;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600

22e2c507c   Jens Axboe   [PATCH] Update cf...
1601
1602
1603
1604
1605
1606
1607
1608
  /*
   * 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...
1609
  	int enable_idle = cfq_cfqq_idle_window(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1611
1612
  	if (!cic->ioc->task || !cfqd->cfq_slice_idle ||
  	    (cfqd->hw_tag && CIC_SEEKY(cic)))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1613
1614
1615
1616
1617
1618
  		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
1619
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1620
1621
1622
1623
  	if (enable_idle)
  		cfq_mark_cfqq_idle_window(cfqq);
  	else
  		cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1624
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1625

22e2c507c   Jens Axboe   [PATCH] Update cf...
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
  
  /*
   * 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)
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1641
  		return 0;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1642
1643
1644
  
  	if (cfq_class_idle(cfqq))
  		return 1;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1645
  	if (!cfq_cfqq_wait_request(new_cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1646
1647
1648
1649
1650
1651
  		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...
1652
  	if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
  		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;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1673
  	cfq_slice_expired(cfqd, 1);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  	__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)
  {
fd61af038   Jens Axboe   [PATCH] cfq-iosch...
1698
  	struct cfq_io_context *cic = crq->io_context;
12e9fddd6   Jens Axboe   [PATCH] cfq-iosch...
1699

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1700
1701
1702
1703
  	/*
  	 * we never wait for an async request and we don't allow preemption
  	 * of an async request. so just return early
  	 */
12e9fddd6   Jens Axboe   [PATCH] cfq-iosch...
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
  	if (!cfq_crq_is_sync(crq)) {
  		/*
  		 * sync process issued an async request, if it's waiting
  		 * then expire it and kick rq handling.
  		 */
  		if (cic == cfqd->active_cic &&
  		    del_timer(&cfqd->idle_slice_timer)) {
  			cfq_slice_expired(cfqd, 0);
  			cfq_start_queueing(cfqd, cfqq);
  		}
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1714
  		return;
12e9fddd6   Jens Axboe   [PATCH] cfq-iosch...
1715
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1716

9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1717
  	cfq_update_io_thinktime(cfqd, cic);
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1718
  	cfq_update_io_seektime(cfqd, cic, crq);
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1719
1720
1721
  	cfq_update_idle_window(cfqd, cfqq, cic);
  
  	cic->last_queue = jiffies;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1722
  	cic->last_request_pos = crq->request->sector + crq->request->nr_sectors;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1723
1724
1725
1726
1727
1728
1729
  
  	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...
1730
1731
  		if (cfq_cfqq_wait_request(cfqq)) {
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
  			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...
1742
  		cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1743
1744
  		cfq_start_queueing(cfqd, cfqq);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1746
  static void cfq_insert_request(request_queue_t *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1748
  	struct cfq_data *cfqd = q->elevator->elevator_data;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1749
1750
1751
1752
  	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
1753
1754
  
  	cfq_add_crq_rb(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755

22e2c507c   Jens Axboe   [PATCH] Update cf...
1756
  	list_add_tail(&rq->queuelist, &cfqq->fifo);
98b11471d   Tejun Heo   [PATCH] 04/05 rem...
1757
  	if (rq_mergeable(rq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1758
  		cfq_add_crq_hash(cfqd, crq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1759
  	cfq_crq_enqueued(cfqd, cfqq, crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
1762
1763
  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...
1764
1765
1766
1767
  	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
1768

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1771
1772
1773
1774
  	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
1775

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1779
1780
1781
1782
1783
  	if (!cfq_cfqq_dispatched(cfqq)) {
  		if (cfq_cfqq_on_rr(cfqq)) {
  			cfqq->service_last = now;
  			cfq_resort_rr_list(cfqq, 0);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1784
  	}
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1785
  	if (sync)
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1786
  		crq->io_context->last_end_request = now;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
  
  	/*
  	 * If this is the active queue, check if it needs to be expired,
  	 * or if we want to idle in case it has no pending requests.
  	 */
  	if (cfqd->active_queue == cfqq) {
  		if (time_after(now, cfqq->slice_end))
  			cfq_slice_expired(cfqd, 0);
  		else if (sync && RB_EMPTY(&cfqq->sort_list)) {
  			if (!cfq_arm_slice_timer(cfqd, cfqq))
  				cfq_schedule_dispatch(cfqd);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
  }
  
  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...
1825
1826
1827
1828
1829
  /*
   * 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
1830
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1831
1832
  	const int ioprio_class = cfqq->ioprio_class;
  	const int ioprio = cfqq->ioprio;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833

22e2c507c   Jens Axboe   [PATCH] Update cf...
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
  	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
1852

22e2c507c   Jens Axboe   [PATCH] Update cf...
1853
1854
1855
1856
  	/*
  	 * 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...
1857
  	    cfq_cfqq_on_rr(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1858
1859
  		cfq_resort_rr_list(cfqq, 0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860

22e2c507c   Jens Axboe   [PATCH] Update cf...
1861
1862
1863
1864
  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...
1865
  	if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
99f95e528   Andrew Morton   [PATCH] cfq build...
1866
  	    !cfq_cfqq_must_alloc_slice(cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1867
  		cfq_mark_cfqq_must_alloc_slice(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1868
  		return ELV_MQUEUE_MUST;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1869
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1870

22e2c507c   Jens Axboe   [PATCH] Update cf...
1871
  	return ELV_MQUEUE_MAY;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
  }
  
  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...
1886
  	cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1887
1888
1889
1890
1891
1892
1893
1894
  	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
1895
1896
1897
1898
  }
  
  static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1899
  	struct cfq_data *cfqd = q->elevator->elevator_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1900

271f18f10   Jens Axboe   [PATCH] cfq-iosch...
1901
1902
  	if (unlikely(cfqd->rq_starved)) {
  		struct request_list *rl = &q->rq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1903
1904
1905
  		smp_mb();
  		if (waitqueue_active(&rl->wait[READ]))
  			wake_up(&rl->wait[READ]);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1906
1907
1908
  		if (waitqueue_active(&rl->wait[WRITE]))
  			wake_up(&rl->wait[WRITE]);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
  }
  
  /*
   * 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...
1921
  		const int rw = rq_data_dir(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1922

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
1926
  		put_io_context(crq->io_context->ioc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
1928
1929
  
  		mempool_free(crq, cfqd->crq_pool);
  		rq->elevator_private = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
1932
1933
1934
1935
  		cfq_check_waiters(q, cfqq);
  		cfq_put_queue(cfqq);
  	}
  }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1936
   * Allocate cfq data structures associated with this request.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1937
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1938
1939
  static int
  cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1940
  		gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1941
1942
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1943
  	struct task_struct *tsk = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1944
1945
  	struct cfq_io_context *cic;
  	const int rw = rq_data_dir(rq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1946
  	pid_t key = cfq_queue_pid(tsk, rw);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1947
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
1949
  	struct cfq_rq *crq;
  	unsigned long flags;
12a057321   Al Viro   [PATCH] keep sync...
1950
  	int is_sync = key != CFQ_KEY_ASYNC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951
1952
  
  	might_sleep_if(gfp_mask & __GFP_WAIT);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1953
  	cic = cfq_get_io_context(cfqd, gfp_mask);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1954

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1955
  	spin_lock_irqsave(q->queue_lock, flags);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1956
1957
  	if (!cic)
  		goto queue_fail;
12a057321   Al Viro   [PATCH] keep sync...
1958
  	if (!cic->cfqq[is_sync]) {
6f325a134   Al Viro   [PATCH] fix cfq_g...
1959
  		cfqq = cfq_get_queue(cfqd, key, tsk, gfp_mask);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1960
1961
  		if (!cfqq)
  			goto queue_fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1962

12a057321   Al Viro   [PATCH] keep sync...
1963
  		cic->cfqq[is_sync] = cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1964
  	} else
12a057321   Al Viro   [PATCH] keep sync...
1965
  		cfqq = cic->cfqq[is_sync];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1966
1967
  
  	cfqq->allocated[rw]++;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1968
  	cfq_clear_cfqq_must_alloc(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1969
1970
  	cfqd->rq_starved = 0;
  	atomic_inc(&cfqq->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1971
  	spin_unlock_irqrestore(q->queue_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1972
1973
1974
1975
1976
1977
1978
1979
  	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...
1980

12a057321   Al Viro   [PATCH] keep sync...
1981
  		if (is_sync)
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1982
1983
1984
  			cfq_mark_crq_is_sync(crq);
  		else
  			cfq_clear_crq_is_sync(crq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1985
  		rq->elevator_private = crq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1986
1987
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1988
1989
  	spin_lock_irqsave(q->queue_lock, flags);
  	cfqq->allocated[rw]--;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1990
  	if (!(cfqq->allocated[0] + cfqq->allocated[1]))
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1991
  		cfq_mark_cfqq_must_alloc(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1992
  	cfq_put_queue(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1993
1994
1995
1996
1997
1998
1999
2000
2001
  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...
2002
  	cfq_schedule_dispatch(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003
2004
2005
  	spin_unlock_irqrestore(q->queue_lock, flags);
  	return 1;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
  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
  		 */
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
2057
  		if (!cfqd->busy_queues)
22e2c507c   Jens Axboe   [PATCH] Update cf...
2058
  			goto out_cont;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2059
2060
2061
2062
2063
  
  		/*
  		 * not expired and it has a request pending, let it dispatch
  		 */
  		if (!RB_EMPTY(&cfqq->sort_list)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2064
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2065
2066
2067
2068
2069
2070
  			goto out_kick;
  		}
  	}
  expire:
  	cfq_slice_expired(cfqd, 0);
  out_kick:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2071
  	cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
  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;
ae818a38d   Jens Axboe   [PATCH] cfq-iosch...
2090
2091
2092
  	if (!time_after_eq(jiffies, end))
  		mod_timer(&cfqd->idle_class_timer, end);
  	else
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2093
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2094
2095
2096
  
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2097
2098
2099
2100
2101
2102
  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...
2103

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2104
2105
  static void cfq_exit_queue(elevator_t *e)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
2106
  	struct cfq_data *cfqd = e->elevator_data;
d9ff41879   Al Viro   [PATCH] make cfq_...
2107
  	request_queue_t *q = cfqd->queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2108

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2109
  	cfq_shutdown_timer_wq(cfqd);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
2110

3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
2111
  	spin_lock(&cfq_exit_lock);
d9ff41879   Al Viro   [PATCH] make cfq_...
2112
  	spin_lock_irq(q->queue_lock);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
2113

d9ff41879   Al Viro   [PATCH] make cfq_...
2114
2115
  	if (cfqd->active_queue)
  		__cfq_slice_expired(cfqd, cfqd->active_queue, 0);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
2116
2117
  
  	while (!list_empty(&cfqd->cic_list)) {
d9ff41879   Al Viro   [PATCH] make cfq_...
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
  		struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
  							struct cfq_io_context,
  							queue_list);
  		if (cic->cfqq[ASYNC]) {
  			cfq_put_queue(cic->cfqq[ASYNC]);
  			cic->cfqq[ASYNC] = NULL;
  		}
  		if (cic->cfqq[SYNC]) {
  			cfq_put_queue(cic->cfqq[SYNC]);
  			cic->cfqq[SYNC] = NULL;
  		}
  		cic->key = NULL;
  		list_del_init(&cic->queue_list);
  	}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
2132

d9ff41879   Al Viro   [PATCH] make cfq_...
2133
  	spin_unlock_irq(q->queue_lock);
3793c65c1   Jens Axboe   [PATCH] cfq-iosch...
2134
  	spin_unlock(&cfq_exit_lock);
a90d742e4   Al Viro   [PATCH] don't bot...
2135
2136
2137
2138
2139
2140
2141
  
  	cfq_shutdown_timer_wq(cfqd);
  
  	mempool_destroy(cfqd->crq_pool);
  	kfree(cfqd->crq_hash);
  	kfree(cfqd->cfq_hash);
  	kfree(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2142
  }
bc1c11697   Jens Axboe   [PATCH] elevator ...
2143
  static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
2145
2146
2147
2148
2149
  {
  	struct cfq_data *cfqd;
  	int i;
  
  	cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
  	if (!cfqd)
bc1c11697   Jens Axboe   [PATCH] elevator ...
2150
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2151
2152
  
  	memset(cfqd, 0, sizeof(*cfqd));
22e2c507c   Jens Axboe   [PATCH] Update cf...
2153
2154
2155
2156
2157
2158
2159
  
  	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
2160
  	INIT_LIST_HEAD(&cfqd->empty_list);
d9ff41879   Al Viro   [PATCH] make cfq_...
2161
  	INIT_LIST_HEAD(&cfqd->cic_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2162
2163
2164
2165
2166
2167
2168
2169
  
  	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;
93d2341c7   Matthew Dobson   [PATCH] mempool: ...
2170
  	cfqd->crq_pool = mempool_create_slab_pool(BLKDEV_MIN_RQ, crq_pool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2171
2172
2173
2174
2175
2176
2177
  	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]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2178
  	cfqd->queue = q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2179

22e2c507c   Jens Axboe   [PATCH] Update cf...
2180
2181
2182
2183
2184
2185
2186
2187
2188
  	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
2189
2190
  	cfqd->cfq_queued = cfq_queued;
  	cfqd->cfq_quantum = cfq_quantum;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2191
2192
  	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
2193
2194
  	cfqd->cfq_back_max = cfq_back_max;
  	cfqd->cfq_back_penalty = cfq_back_penalty;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2195
2196
2197
2198
  	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;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
2199

bc1c11697   Jens Axboe   [PATCH] elevator ...
2200
  	return cfqd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2201
2202
2203
2204
2205
2206
  out_crqpool:
  	kfree(cfqd->cfq_hash);
  out_cfqhash:
  	kfree(cfqd->crq_hash);
  out_crqhash:
  	kfree(cfqd);
bc1c11697   Jens Axboe   [PATCH] elevator ...
2207
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
  }
  
  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
2242
2243
2244
  /*
   * sysfs parts below -->
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
  
  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
2261
  #define SHOW_FUNCTION(__FUNC, __VAR, __CONV)				\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2262
  static ssize_t __FUNC(elevator_t *e, char *page)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
  {									\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2264
  	struct cfq_data *cfqd = e->elevator_data;			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2265
2266
2267
2268
2269
2270
2271
  	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...
2272
2273
  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);
e572ec7e4   Al Viro   [PATCH] fix rmmod...
2274
2275
  SHOW_FUNCTION(cfq_back_seek_max_show, cfqd->cfq_back_max, 0);
  SHOW_FUNCTION(cfq_back_seek_penalty_show, cfqd->cfq_back_penalty, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2276
2277
2278
2279
  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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280
2281
2282
  #undef SHOW_FUNCTION
  
  #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2283
  static ssize_t __FUNC(elevator_t *e, const char *page, size_t count)	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2284
  {									\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2285
  	struct cfq_data *cfqd = e->elevator_data;			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
  	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...
2300
2301
  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);
e572ec7e4   Al Viro   [PATCH] fix rmmod...
2302
2303
  STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
  STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2304
2305
2306
2307
  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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2308
  #undef STORE_FUNCTION
e572ec7e4   Al Viro   [PATCH] fix rmmod...
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
  #define CFQ_ATTR(name) \
  	__ATTR(name, S_IRUGO|S_IWUSR, cfq_##name##_show, cfq_##name##_store)
  
  static struct elv_fs_entry cfq_attrs[] = {
  	CFQ_ATTR(quantum),
  	CFQ_ATTR(queued),
  	CFQ_ATTR(fifo_expire_sync),
  	CFQ_ATTR(fifo_expire_async),
  	CFQ_ATTR(back_seek_max),
  	CFQ_ATTR(back_seek_penalty),
  	CFQ_ATTR(slice_sync),
  	CFQ_ATTR(slice_async),
  	CFQ_ATTR(slice_async_rq),
  	CFQ_ATTR(slice_idle),
e572ec7e4   Al Viro   [PATCH] fix rmmod...
2323
  	__ATTR_NULL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2324
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
2326
2327
2328
2329
  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...
2330
  		.elevator_dispatch_fn =		cfq_dispatch_requests,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2331
  		.elevator_add_req_fn =		cfq_insert_request,
b4878f245   Jens Axboe   [PATCH] 02/05: up...
2332
  		.elevator_activate_req_fn =	cfq_activate_request,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
  		.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,
e17a9489b   Al Viro   [PATCH] stop elv_...
2343
  		.trim =				cfq_trim,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2344
  	},
3d1ab40f4   Al Viro   [PATCH] elevator_...
2345
  	.elevator_attrs =	cfq_attrs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2346
2347
2348
2349
2350
2351
2352
  	.elevator_name =	"cfq",
  	.elevator_owner =	THIS_MODULE,
  };
  
  static int __init cfq_init(void)
  {
  	int ret;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2353
2354
2355
2356
2357
2358
2359
  	/*
  	 * 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
2360
2361
2362
2363
  	if (cfq_slab_setup())
  		return -ENOMEM;
  
  	ret = elv_register(&iosched_cfq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2364
2365
  	if (ret)
  		cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2366

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2367
2368
2369
2370
2371
  	return ret;
  }
  
  static void __exit cfq_exit(void)
  {
334e94de9   Al Viro   [PATCH] deal with...
2372
  	DECLARE_COMPLETION(all_gone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2373
  	elv_unregister(&iosched_cfq);
334e94de9   Al Viro   [PATCH] deal with...
2374
  	ioc_gone = &all_gone;
fba822722   OGAWA Hirofumi   [PATCH 1/2] iosch...
2375
2376
  	/* ioc_gone's update must be visible before reading ioc_count */
  	smp_wmb();
334e94de9   Al Viro   [PATCH] deal with...
2377
  	if (atomic_read(&ioc_count))
fba822722   OGAWA Hirofumi   [PATCH 1/2] iosch...
2378
  		wait_for_completion(ioc_gone);
334e94de9   Al Viro   [PATCH] deal with...
2379
  	synchronize_rcu();
83521d3eb   Christoph Hellwig   [PATCH] cfq-iosch...
2380
  	cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2381
2382
2383
2384
2385
2386
2387
2388
  }
  
  module_init(cfq_init);
  module_exit(cfq_exit);
  
  MODULE_AUTHOR("Jens Axboe");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler");