Blame view

block/cfq-iosched.c 53.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
   *  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.
   *
0fe234795   Jens Axboe   [PATCH] Update ax...
7
   *  Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include <linux/module.h>
1cc9be68e   Al Viro   [PATCH] noise rem...
10
11
  #include <linux/blkdev.h>
  #include <linux/elevator.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <linux/rbtree.h>
22e2c507c   Jens Axboe   [PATCH] Update cf...
13
  #include <linux/ioprio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
  
  /*
   * tunables
   */
64100099e   Arjan van de Ven   [BLOCK] mark some...
18
  static const int cfq_quantum = 4;		/* max queue in one round of service */
64100099e   Arjan van de Ven   [BLOCK] mark some...
19
20
21
  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
22

64100099e   Arjan van de Ven   [BLOCK] mark some...
23
  static const int cfq_slice_sync = HZ / 10;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
24
  static int cfq_slice_async = HZ / 25;
64100099e   Arjan van de Ven   [BLOCK] mark some...
25
  static const int cfq_slice_async_rq = 2;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
26
  static int cfq_slice_idle = HZ / 125;
22e2c507c   Jens Axboe   [PATCH] Update cf...
27

d9e7620e6   Jens Axboe   cfq-iosched: rewo...
28
29
30
  /*
   * grace period before allowing idle class to get disk access
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
31
  #define CFQ_IDLE_GRACE		(HZ / 10)
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
32
33
34
35
36
  
  /*
   * below this threshold, we consider thinktime immediate
   */
  #define CFQ_MIN_TT		(2)
22e2c507c   Jens Axboe   [PATCH] Update cf...
37
  #define CFQ_SLICE_SCALE		(5)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
38
39
  #define RQ_CIC(rq)		((struct cfq_io_context*)(rq)->elevator_private)
  #define RQ_CFQQ(rq)		((rq)->elevator_private2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

e18b890bb   Christoph Lameter   [PATCH] slab: rem...
41
42
  static struct kmem_cache *cfq_pool;
  static struct kmem_cache *cfq_ioc_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

4050cf167   Jens Axboe   [PATCH] cfq-iosch...
44
  static DEFINE_PER_CPU(unsigned long, ioc_count);
334e94de9   Al Viro   [PATCH] deal with...
45
  static struct completion *ioc_gone;
22e2c507c   Jens Axboe   [PATCH] Update cf...
46
47
  #define CFQ_PRIO_LISTS		IOPRIO_BE_NR
  #define cfq_class_idle(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
22e2c507c   Jens Axboe   [PATCH] Update cf...
48
  #define cfq_class_rt(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
49
50
  #define ASYNC			(0)
  #define SYNC			(1)
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
51
  #define sample_valid(samples)	((samples) > 80)
22e2c507c   Jens Axboe   [PATCH] Update cf...
52
  /*
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
53
54
55
56
57
58
59
60
61
62
63
64
   * Most of our rbtree usage is for sorting with min extraction, so
   * if we cache the leftmost node we don't have to walk down the tree
   * to find it. Idea borrowed from Ingo Molnars CFS scheduler. We should
   * move this into the elevator for the rq sorting as well.
   */
  struct cfq_rb_root {
  	struct rb_root rb;
  	struct rb_node *left;
  };
  #define CFQ_RB_ROOT	(struct cfq_rb_root) { RB_ROOT, NULL, }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
65
66
   * Per block device queue structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  struct cfq_data {
165125e1e   Jens Axboe   [BLOCK] Get rid o...
68
  	struct request_queue *queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
69
70
71
72
  
  	/*
  	 * rr list of queues with requests and the count of them
  	 */
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
73
  	struct cfq_rb_root service_tree;
22e2c507c   Jens Axboe   [PATCH] Update cf...
74
  	unsigned int busy_queues;
22e2c507c   Jens Axboe   [PATCH] Update cf...
75
  	int rq_in_driver;
3ed9a2965   Jens Axboe   cfq-iosched: impr...
76
  	int sync_flight;
25776e359   Jens Axboe   [PATCH] cfq-iosch...
77
  	int hw_tag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

22e2c507c   Jens Axboe   [PATCH] Update cf...
79
  	/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
80
81
82
83
  	 * idle window management
  	 */
  	struct timer_list idle_slice_timer;
  	struct work_struct unplug_work;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84

22e2c507c   Jens Axboe   [PATCH] Update cf...
85
86
  	struct cfq_queue *active_queue;
  	struct cfq_io_context *active_cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
87

c2dea2d1f   Vasily Tarasov   cfq: async queue ...
88
89
90
91
92
  	/*
  	 * async queue for each priority case
  	 */
  	struct cfq_queue *async_cfqq[2][IOPRIO_BE_NR];
  	struct cfq_queue *async_idle_cfqq;
15c31be4d   Jens Axboe   cfq-iosched: fix ...
93

22e2c507c   Jens Axboe   [PATCH] Update cf...
94
  	struct timer_list idle_class_timer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95

6d048f531   Jens Axboe   cfq-iosched: deve...
96
  	sector_t last_position;
22e2c507c   Jens Axboe   [PATCH] Update cf...
97
  	unsigned long last_end_request;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
101
102
  	/*
  	 * tunables, see top of file
  	 */
  	unsigned int cfq_quantum;
22e2c507c   Jens Axboe   [PATCH] Update cf...
103
  	unsigned int cfq_fifo_expire[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
  	unsigned int cfq_back_penalty;
  	unsigned int cfq_back_max;
22e2c507c   Jens Axboe   [PATCH] Update cf...
106
107
108
  	unsigned int cfq_slice[2];
  	unsigned int cfq_slice_async_rq;
  	unsigned int cfq_slice_idle;
d9ff41879   Al Viro   [PATCH] make cfq_...
109
110
  
  	struct list_head cic_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  };
22e2c507c   Jens Axboe   [PATCH] Update cf...
112
113
114
  /*
   * Per process-grouping structure
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
  struct cfq_queue {
  	/* reference count */
  	atomic_t ref;
  	/* parent cfq_data */
  	struct cfq_data *cfqd;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
120
121
122
123
  	/* service_tree member */
  	struct rb_node rb_node;
  	/* service_tree key */
  	unsigned long rb_key;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
  	/* sorted list of pending requests */
  	struct rb_root sort_list;
  	/* if fifo isn't expired, next request to serve */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
127
  	struct request *next_rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
  	/* requests queued in sort_list */
  	int queued[2];
  	/* currently allocated requests */
  	int allocated[2];
374f84ac3   Jens Axboe   [PATCH] cfq-iosch...
132
133
  	/* pending metadata requests */
  	int meta_pending;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  	/* fifo list of requests in sort_list */
22e2c507c   Jens Axboe   [PATCH] Update cf...
135
  	struct list_head fifo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

22e2c507c   Jens Axboe   [PATCH] Update cf...
137
  	unsigned long slice_end;
c5b680f3b   Jens Axboe   cfq-iosched: acco...
138
  	long slice_resid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

6d048f531   Jens Axboe   cfq-iosched: deve...
140
141
  	/* number of requests that are on the dispatch list or inside driver */
  	int dispatched;
22e2c507c   Jens Axboe   [PATCH] Update cf...
142
143
144
145
  
  	/* io prio of this group */
  	unsigned short ioprio, org_ioprio;
  	unsigned short ioprio_class, org_ioprio_class;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
146
147
  	/* various state flags, see below */
  	unsigned int flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  };
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
149
  enum cfqq_state_flags {
b0b8d7494   Jens Axboe   cfq-iosched: docu...
150
151
152
153
154
155
156
157
158
  	CFQ_CFQQ_FLAG_on_rr = 0,	/* on round-robin busy list */
  	CFQ_CFQQ_FLAG_wait_request,	/* waiting for a request */
  	CFQ_CFQQ_FLAG_must_alloc,	/* must be allowed rq alloc */
  	CFQ_CFQQ_FLAG_must_alloc_slice,	/* per-slice must_alloc flag */
  	CFQ_CFQQ_FLAG_must_dispatch,	/* must dispatch, even if expired */
  	CFQ_CFQQ_FLAG_fifo_expire,	/* FIFO checked in this slice */
  	CFQ_CFQQ_FLAG_idle_window,	/* slice idling enabled */
  	CFQ_CFQQ_FLAG_prio_changed,	/* task priority has changed */
  	CFQ_CFQQ_FLAG_queue_new,	/* queue never been serviced */
44f7c1606   Jens Axboe   cfq-iosched: defe...
159
  	CFQ_CFQQ_FLAG_slice_new,	/* no requests dispatched in slice */
91fac317a   Vasily Tarasov   cfq-iosched: get ...
160
  	CFQ_CFQQ_FLAG_sync,		/* synchronous queue */
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  };
  
  #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);
53b03744e   Jens Axboe   [PATCH] cfq-iosch...
185
  CFQ_CFQQ_FNS(queue_new);
44f7c1606   Jens Axboe   cfq-iosched: defe...
186
  CFQ_CFQQ_FNS(slice_new);
91fac317a   Vasily Tarasov   cfq-iosched: get ...
187
  CFQ_CFQQ_FNS(sync);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
188
  #undef CFQ_CFQQ_FNS
165125e1e   Jens Axboe   [BLOCK] Get rid o...
189
  static void cfq_dispatch_insert(struct request_queue *, struct request *);
91fac317a   Vasily Tarasov   cfq-iosched: get ...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  static struct cfq_queue *cfq_get_queue(struct cfq_data *, int,
  				       struct task_struct *, gfp_t);
  static struct cfq_io_context *cfq_cic_rb_lookup(struct cfq_data *,
  						struct io_context *);
  
  static inline struct cfq_queue *cic_to_cfqq(struct cfq_io_context *cic,
  					    int is_sync)
  {
  	return cic->cfqq[!!is_sync];
  }
  
  static inline void cic_set_cfqq(struct cfq_io_context *cic,
  				struct cfq_queue *cfqq, int is_sync)
  {
  	cic->cfqq[!!is_sync] = cfqq;
  }
  
  /*
   * We regard a request as SYNC, if it's either a read or has the SYNC bit
   * set (in which case it could also be direct WRITE).
   */
  static inline int cfq_bio_sync(struct bio *bio)
  {
  	if (bio_data_dir(bio) == READ || bio_sync(bio))
  		return 1;
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  /*
99f95e528   Andrew Morton   [PATCH] cfq build...
220
221
222
223
224
   * 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...
225
  	if (cfqd->busy_queues)
99f95e528   Andrew Morton   [PATCH] cfq build...
226
227
  		kblockd_schedule_work(&cfqd->unplug_work);
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
228
  static int cfq_queue_empty(struct request_queue *q)
99f95e528   Andrew Morton   [PATCH] cfq build...
229
230
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
231
  	return !cfqd->busy_queues;
99f95e528   Andrew Morton   [PATCH] cfq build...
232
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  /*
44f7c1606   Jens Axboe   cfq-iosched: defe...
234
235
236
237
   * 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.
   */
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
238
239
  static inline int cfq_prio_slice(struct cfq_data *cfqd, int sync,
  				 unsigned short prio)
44f7c1606   Jens Axboe   cfq-iosched: defe...
240
  {
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
241
  	const int base_slice = cfqd->cfq_slice[sync];
44f7c1606   Jens Axboe   cfq-iosched: defe...
242

d9e7620e6   Jens Axboe   cfq-iosched: rewo...
243
244
245
246
  	WARN_ON(prio >= IOPRIO_BE_NR);
  
  	return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - prio));
  }
44f7c1606   Jens Axboe   cfq-iosched: defe...
247

d9e7620e6   Jens Axboe   cfq-iosched: rewo...
248
249
250
251
  static inline int
  cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	return cfq_prio_slice(cfqd, cfq_cfqq_sync(cfqq), cfqq->ioprio);
44f7c1606   Jens Axboe   cfq-iosched: defe...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  }
  
  static inline void
  cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
  	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
  }
  
  /*
   * We need to wrap this check in cfq_cfqq_slice_new(), since ->slice_end
   * isn't valid until the first request from the dispatch is activated
   * and the slice time set.
   */
  static inline int cfq_slice_used(struct cfq_queue *cfqq)
  {
  	if (cfq_cfqq_slice_new(cfqq))
  		return 0;
  	if (time_before(jiffies, cfqq->slice_end))
  		return 0;
  
  	return 1;
  }
  
  /*
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
276
   * Lifted from AS - choose which of rq1 and rq2 that is best served now.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
   * We choose the request that is closest to the head right now. Distance
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
278
   * behind the head is penalized and only allowed to a certain extent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
   */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
280
281
  static struct request *
  cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
  {
  	sector_t last, s1, s2, d1 = 0, d2 = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  	unsigned long back_max;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
285
286
287
  #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
288

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
289
290
291
292
  	if (rq1 == NULL || rq1 == rq2)
  		return rq2;
  	if (rq2 == NULL)
  		return rq1;
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
293

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
294
295
296
297
  	if (rq_is_sync(rq1) && !rq_is_sync(rq2))
  		return rq1;
  	else if (rq_is_sync(rq2) && !rq_is_sync(rq1))
  		return rq2;
374f84ac3   Jens Axboe   [PATCH] cfq-iosch...
298
299
300
301
  	if (rq_is_meta(rq1) && !rq_is_meta(rq2))
  		return rq1;
  	else if (rq_is_meta(rq2) && !rq_is_meta(rq1))
  		return rq2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
303
304
  	s1 = rq1->sector;
  	s2 = rq2->sector;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305

6d048f531   Jens Axboe   cfq-iosched: deve...
306
  	last = cfqd->last_position;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	/*
  	 * 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...
323
  		wrap |= CFQ_RQ1_WRAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
  
  	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...
330
  		wrap |= CFQ_RQ2_WRAP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
  
  	/* Found required data */
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
333
334
335
336
337
338
  
  	/*
  	 * By doing switch() on the bit mask "wrap" we avoid having to
  	 * check two variables for all permutations: --> faster!
  	 */
  	switch (wrap) {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
339
  	case 0: /* common case for CFQ: rq1 and rq2 not wrapped */
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
340
  		if (d1 < d2)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
341
  			return rq1;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
342
  		else if (d2 < d1)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
343
  			return rq2;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
344
345
  		else {
  			if (s1 >= s2)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
346
  				return rq1;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
347
  			else
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
348
  				return rq2;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
349
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350

e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
351
  	case CFQ_RQ2_WRAP:
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
352
  		return rq1;
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
353
  	case CFQ_RQ1_WRAP:
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
354
355
  		return rq2;
  	case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both rqs wrapped */
e8a99053e   Andreas Mohr   [PATCH] cfq-iosch...
356
357
358
359
360
361
362
363
  	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)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
364
  			return rq1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  		else
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
366
  			return rq2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
  	}
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
369
370
371
  /*
   * The below is leftmost cache rbtree addon
   */
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  static struct rb_node *cfq_rb_first(struct cfq_rb_root *root)
  {
  	if (!root->left)
  		root->left = rb_first(&root->rb);
  
  	return root->left;
  }
  
  static void cfq_rb_erase(struct rb_node *n, struct cfq_rb_root *root)
  {
  	if (root->left == n)
  		root->left = NULL;
  
  	rb_erase(n, &root->rb);
  	RB_CLEAR_NODE(n);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
  /*
   * would be nice to take fifo expire time into account as well
   */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
391
392
393
  static struct request *
  cfq_find_next_rq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		  struct request *last)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  {
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
395
396
  	struct rb_node *rbnext = rb_next(&last->rb_node);
  	struct rb_node *rbprev = rb_prev(&last->rb_node);
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
397
  	struct request *next = NULL, *prev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398

21183b07e   Jens Axboe   [PATCH] cfq-iosch...
399
  	BUG_ON(RB_EMPTY_NODE(&last->rb_node));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
  
  	if (rbprev)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
402
  		prev = rb_entry_rq(rbprev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403

21183b07e   Jens Axboe   [PATCH] cfq-iosch...
404
  	if (rbnext)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
405
  		next = rb_entry_rq(rbnext);
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
406
407
408
  	else {
  		rbnext = rb_first(&cfqq->sort_list);
  		if (rbnext && rbnext != &last->rb_node)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
409
  			next = rb_entry_rq(rbnext);
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
410
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411

21183b07e   Jens Axboe   [PATCH] cfq-iosch...
412
  	return cfq_choose_req(cfqd, next, prev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  }
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
414
415
  static unsigned long cfq_slice_offset(struct cfq_data *cfqd,
  				      struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  {
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
417
418
419
  	/*
  	 * just an approximation, should be ok.
  	 */
67e6b49e3   Jens Axboe   cfq-iosched: slic...
420
421
  	return (cfqd->busy_queues - 1) * (cfq_prio_slice(cfqd, 1, 0) -
  		       cfq_prio_slice(cfqd, cfq_cfqq_sync(cfqq), cfqq->ioprio));
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
422
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
423
424
425
426
427
  /*
   * The cfqd->service_tree holds all pending cfq_queue's that have
   * requests waiting to be processed. It is sorted in the order that
   * we will service the queues.
   */
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
428
  static void cfq_service_tree_add(struct cfq_data *cfqd,
edd75ffd9   Jens Axboe   cfq-iosched: get ...
429
  				    struct cfq_queue *cfqq, int add_front)
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
430
  {
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
431
  	struct rb_node **p = &cfqd->service_tree.rb.rb_node;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
432
  	struct rb_node *parent = NULL;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
433
  	unsigned long rb_key;
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
434
  	int left;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
435

edd75ffd9   Jens Axboe   cfq-iosched: get ...
436
437
438
439
440
441
  	if (!add_front) {
  		rb_key = cfq_slice_offset(cfqd, cfqq) + jiffies;
  		rb_key += cfqq->slice_resid;
  		cfqq->slice_resid = 0;
  	} else
  		rb_key = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442

d9e7620e6   Jens Axboe   cfq-iosched: rewo...
443
  	if (!RB_EMPTY_NODE(&cfqq->rb_node)) {
99f9628ab   Jens Axboe   [PATCH] cfq-iosch...
444
  		/*
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
445
  		 * same position, nothing more to do
99f9628ab   Jens Axboe   [PATCH] cfq-iosch...
446
  		 */
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
447
448
  		if (rb_key == cfqq->rb_key)
  			return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449

cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
450
  		cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
  	}
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
452

498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
453
  	left = 1;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
454
  	while (*p) {
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
455
  		struct cfq_queue *__cfqq;
67060e379   Jens Axboe   cfq-iosched: sort...
456
  		struct rb_node **n;
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
457

d9e7620e6   Jens Axboe   cfq-iosched: rewo...
458
459
  		parent = *p;
  		__cfqq = rb_entry(parent, struct cfq_queue, rb_node);
0c534e0a4   Jens Axboe   cfq-iosched: sort...
460
461
  		/*
  		 * sort RT queues first, we always want to give
67060e379   Jens Axboe   cfq-iosched: sort...
462
463
  		 * preference to them. IDLE queues goes to the back.
  		 * after that, sort on the next service time.
0c534e0a4   Jens Axboe   cfq-iosched: sort...
464
465
  		 */
  		if (cfq_class_rt(cfqq) > cfq_class_rt(__cfqq))
67060e379   Jens Axboe   cfq-iosched: sort...
466
  			n = &(*p)->rb_left;
0c534e0a4   Jens Axboe   cfq-iosched: sort...
467
  		else if (cfq_class_rt(cfqq) < cfq_class_rt(__cfqq))
67060e379   Jens Axboe   cfq-iosched: sort...
468
469
470
471
472
  			n = &(*p)->rb_right;
  		else if (cfq_class_idle(cfqq) < cfq_class_idle(__cfqq))
  			n = &(*p)->rb_left;
  		else if (cfq_class_idle(cfqq) > cfq_class_idle(__cfqq))
  			n = &(*p)->rb_right;
0c534e0a4   Jens Axboe   cfq-iosched: sort...
473
  		else if (rb_key < __cfqq->rb_key)
67060e379   Jens Axboe   cfq-iosched: sort...
474
475
476
477
478
  			n = &(*p)->rb_left;
  		else
  			n = &(*p)->rb_right;
  
  		if (n == &(*p)->rb_right)
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
479
  			left = 0;
67060e379   Jens Axboe   cfq-iosched: sort...
480
481
  
  		p = n;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
482
  	}
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
483
484
  	if (left)
  		cfqd->service_tree.left = &cfqq->rb_node;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
485
486
  	cfqq->rb_key = rb_key;
  	rb_link_node(&cfqq->rb_node, parent, p);
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
487
  	rb_insert_color(&cfqq->rb_node, &cfqd->service_tree.rb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
489
490
491
  /*
   * Update cfqq's position in the service tree.
   */
edd75ffd9   Jens Axboe   cfq-iosched: get ...
492
  static void cfq_resort_rr_list(struct cfq_data *cfqd, struct cfq_queue *cfqq)
6d048f531   Jens Axboe   cfq-iosched: deve...
493
  {
6d048f531   Jens Axboe   cfq-iosched: deve...
494
495
496
  	/*
  	 * Resorting requires the cfqq to be on the RR list already.
  	 */
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
497
  	if (cfq_cfqq_on_rr(cfqq))
edd75ffd9   Jens Axboe   cfq-iosched: get ...
498
  		cfq_service_tree_add(cfqd, cfqq, 0);
6d048f531   Jens Axboe   cfq-iosched: deve...
499
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
  /*
   * add to busy list of queues for service, trying to be fair in ordering
22e2c507c   Jens Axboe   [PATCH] Update cf...
502
   * the pending list according to last request service
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
   */
  static inline void
b4878f245   Jens Axboe   [PATCH] 02/05: up...
505
  cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
507
508
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
  	cfq_mark_cfqq_on_rr(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  	cfqd->busy_queues++;
edd75ffd9   Jens Axboe   cfq-iosched: get ...
510
  	cfq_resort_rr_list(cfqd, cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
512
513
514
515
  /*
   * Called when the cfqq no longer has requests pending, remove it from
   * the service tree.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
  static inline void
  cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
519
520
  	BUG_ON(!cfq_cfqq_on_rr(cfqq));
  	cfq_clear_cfqq_on_rr(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521

cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
522
523
  	if (!RB_EMPTY_NODE(&cfqq->rb_node))
  		cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree);
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
524

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
530
531
  	BUG_ON(!cfqd->busy_queues);
  	cfqd->busy_queues--;
  }
  
  /*
   * rb tree support functions
   */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
532
  static inline void cfq_del_rq_rb(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
534
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
535
  	struct cfq_data *cfqd = cfqq->cfqd;
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
536
  	const int sync = rq_is_sync(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537

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

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
541
  	elv_rb_del(&cfqq->sort_list, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542

dd67d0515   Jens Axboe   [PATCH] rbtree: s...
543
  	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list))
b4878f245   Jens Axboe   [PATCH] 02/05: up...
544
  		cfq_del_cfqq_rr(cfqd, cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  }
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
546
  static void cfq_add_rq_rb(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
  {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
548
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
  	struct cfq_data *cfqd = cfqq->cfqd;
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
550
  	struct request *__alias;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551

5380a101d   Jens Axboe   [PATCH] cfq-iosch...
552
  	cfqq->queued[rq_is_sync(rq)]++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
  
  	/*
  	 * looks a little odd, but the first insert might return an alias.
  	 * if that happens, put the alias on the dispatch list
  	 */
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
558
  	while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
559
  		cfq_dispatch_insert(cfqd->queue, __alias);
5fccbf61b   Jens Axboe   [PATCH] CFQ: requ...
560
561
562
  
  	if (!cfq_cfqq_on_rr(cfqq))
  		cfq_add_cfqq_rr(cfqd, cfqq);
5044eed48   Jens Axboe   cfq-iosched: fix ...
563
564
565
566
567
568
  
  	/*
  	 * check if this request is a better next-serve candidate
  	 */
  	cfqq->next_rq = cfq_choose_req(cfqd, cfqq->next_rq, rq);
  	BUG_ON(!cfqq->next_rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
571
  }
  
  static inline void
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
572
  cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  {
5380a101d   Jens Axboe   [PATCH] cfq-iosch...
574
575
  	elv_rb_del(&cfqq->sort_list, rq);
  	cfqq->queued[rq_is_sync(rq)]--;
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
576
  	cfq_add_rq_rb(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  }
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
578
579
  static struct request *
  cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
581
  	struct task_struct *tsk = current;
91fac317a   Vasily Tarasov   cfq-iosched: get ...
582
  	struct cfq_io_context *cic;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
583
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584

91fac317a   Vasily Tarasov   cfq-iosched: get ...
585
586
587
588
589
  	cic = cfq_cic_rb_lookup(cfqd, tsk->io_context);
  	if (!cic)
  		return NULL;
  
  	cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
590
591
  	if (cfqq) {
  		sector_t sector = bio->bi_sector + bio_sectors(bio);
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
592
  		return elv_rb_find(&cfqq->sort_list, sector);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
593
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
  	return NULL;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
597
  static void cfq_activate_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
599
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
600

b4878f245   Jens Axboe   [PATCH] 02/05: up...
601
  	cfqd->rq_in_driver++;
25776e359   Jens Axboe   [PATCH] cfq-iosch...
602
603
604
605
606
607
608
609
610
  
  	/*
  	 * 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;
6d048f531   Jens Axboe   cfq-iosched: deve...
611
612
  
  	cfqd->last_position = rq->hard_sector + rq->hard_nr_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
614
  static void cfq_deactivate_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
616
617
618
619
  	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
620
  }
b4878f245   Jens Axboe   [PATCH] 02/05: up...
621
  static void cfq_remove_request(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
623
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
624

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
625
626
  	if (cfqq->next_rq == rq)
  		cfqq->next_rq = cfq_find_next_rq(cfqq->cfqd, cfqq, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

b4878f245   Jens Axboe   [PATCH] 02/05: up...
628
  	list_del_init(&rq->queuelist);
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
629
  	cfq_del_rq_rb(rq);
374f84ac3   Jens Axboe   [PATCH] cfq-iosch...
630
631
632
633
634
  
  	if (rq_is_meta(rq)) {
  		WARN_ON(!cfqq->meta_pending);
  		cfqq->meta_pending--;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
636
637
  static int cfq_merge(struct request_queue *q, struct request **req,
  		     struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct request *__rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
642
  	__rq = cfq_find_rq_fmerge(cfqd, bio);
22e2c507c   Jens Axboe   [PATCH] Update cf...
643
  	if (__rq && elv_rq_merge_ok(__rq, bio)) {
9817064b6   Jens Axboe   [PATCH] elevator:...
644
645
  		*req = __rq;
  		return ELEVATOR_FRONT_MERGE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
647
648
  	}
  
  	return ELEVATOR_NO_MERGE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
649
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
650
  static void cfq_merged_request(struct request_queue *q, struct request *req,
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
651
  			       int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  {
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
653
  	if (type == ELEVATOR_FRONT_MERGE) {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
654
  		struct cfq_queue *cfqq = RQ_CFQQ(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
656
  		cfq_reposition_rq_rb(cfqq, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
  }
  
  static void
165125e1e   Jens Axboe   [BLOCK] Get rid o...
661
  cfq_merged_requests(struct request_queue *q, struct request *rq,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
  		    struct request *next)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
664
665
666
667
668
669
  	/*
  	 * 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...
670
  	cfq_remove_request(next);
22e2c507c   Jens Axboe   [PATCH] Update cf...
671
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
672
  static int cfq_allow_merge(struct request_queue *q, struct request *rq,
da7752650   Jens Axboe   [PATCH] cfq-iosch...
673
674
675
  			   struct bio *bio)
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
91fac317a   Vasily Tarasov   cfq-iosched: get ...
676
  	struct cfq_io_context *cic;
da7752650   Jens Axboe   [PATCH] cfq-iosch...
677
  	struct cfq_queue *cfqq;
da7752650   Jens Axboe   [PATCH] cfq-iosch...
678
679
  
  	/*
ec8acb690   Jens Axboe   [PATCH] cfq-iosch...
680
  	 * Disallow merge of a sync bio into an async request.
da7752650   Jens Axboe   [PATCH] cfq-iosch...
681
  	 */
91fac317a   Vasily Tarasov   cfq-iosched: get ...
682
  	if (cfq_bio_sync(bio) && !rq_is_sync(rq))
da7752650   Jens Axboe   [PATCH] cfq-iosch...
683
684
685
  		return 0;
  
  	/*
719d34027   Jens Axboe   [PATCH] cfq-iosch...
686
687
  	 * Lookup the cfqq that this bio will be queued with. Allow
  	 * merge only if rq is queued there.
da7752650   Jens Axboe   [PATCH] cfq-iosch...
688
  	 */
91fac317a   Vasily Tarasov   cfq-iosched: get ...
689
690
691
  	cic = cfq_cic_rb_lookup(cfqd, current->io_context);
  	if (!cic)
  		return 0;
719d34027   Jens Axboe   [PATCH] cfq-iosch...
692

91fac317a   Vasily Tarasov   cfq-iosched: get ...
693
  	cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
719d34027   Jens Axboe   [PATCH] cfq-iosch...
694
695
  	if (cfqq == RQ_CFQQ(rq))
  		return 1;
da7752650   Jens Axboe   [PATCH] cfq-iosch...
696

ec8acb690   Jens Axboe   [PATCH] cfq-iosch...
697
  	return 0;
da7752650   Jens Axboe   [PATCH] cfq-iosch...
698
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
699
700
701
702
703
704
705
706
  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);
22e2c507c   Jens Axboe   [PATCH] Update cf...
707
  		cfqq->slice_end = 0;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
708
709
  		cfq_clear_cfqq_must_alloc_slice(cfqq);
  		cfq_clear_cfqq_fifo_expire(cfqq);
44f7c1606   Jens Axboe   cfq-iosched: defe...
710
  		cfq_mark_cfqq_slice_new(cfqq);
1afba0451   Jens Axboe   cfq-iosched: mino...
711
  		cfq_clear_cfqq_queue_new(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
712
713
714
715
716
717
  	}
  
  	cfqd->active_queue = cfqq;
  }
  
  /*
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
718
719
720
721
   * 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,
6084cdda0   Jens Axboe   cfq-iosched: don'...
722
  		    int timed_out)
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
723
  {
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
724
725
  	if (cfq_cfqq_wait_request(cfqq))
  		del_timer(&cfqd->idle_slice_timer);
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
726
727
728
729
  	cfq_clear_cfqq_must_dispatch(cfqq);
  	cfq_clear_cfqq_wait_request(cfqq);
  
  	/*
6084cdda0   Jens Axboe   cfq-iosched: don'...
730
  	 * store what was left of this slice, if the queue idled/timed out
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
731
  	 */
3c6bd2f87   Jens Axboe   cfq-iosched: chec...
732
  	if (timed_out && !cfq_cfqq_slice_new(cfqq))
c5b680f3b   Jens Axboe   cfq-iosched: acco...
733
  		cfqq->slice_resid = cfqq->slice_end - jiffies;
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
734

edd75ffd9   Jens Axboe   cfq-iosched: get ...
735
  	cfq_resort_rr_list(cfqd, cfqq);
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
736
737
738
739
740
741
742
743
  
  	if (cfqq == cfqd->active_queue)
  		cfqd->active_queue = NULL;
  
  	if (cfqd->active_cic) {
  		put_io_context(cfqd->active_cic->ioc);
  		cfqd->active_cic = NULL;
  	}
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
744
  }
6084cdda0   Jens Axboe   cfq-iosched: don'...
745
  static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out)
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
746
747
748
749
  {
  	struct cfq_queue *cfqq = cfqd->active_queue;
  
  	if (cfqq)
6084cdda0   Jens Axboe   cfq-iosched: don'...
750
  		__cfq_slice_expired(cfqd, cfqq, timed_out);
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
751
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
752
753
754
755
  /*
   * Get next queue for service. Unless we have a queue preemption,
   * we'll simply select the first cfqq in the service tree.
   */
6d048f531   Jens Axboe   cfq-iosched: deve...
756
  static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd)
22e2c507c   Jens Axboe   [PATCH] Update cf...
757
  {
edd75ffd9   Jens Axboe   cfq-iosched: get ...
758
759
  	struct cfq_queue *cfqq;
  	struct rb_node *n;
22e2c507c   Jens Axboe   [PATCH] Update cf...
760

edd75ffd9   Jens Axboe   cfq-iosched: get ...
761
762
  	if (RB_EMPTY_ROOT(&cfqd->service_tree.rb))
  		return NULL;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
763

edd75ffd9   Jens Axboe   cfq-iosched: get ...
764
765
  	n = cfq_rb_first(&cfqd->service_tree);
  	cfqq = rb_entry(n, struct cfq_queue, rb_node);
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
766

edd75ffd9   Jens Axboe   cfq-iosched: get ...
767
768
769
770
771
772
773
774
775
776
777
778
779
  	if (cfq_class_idle(cfqq)) {
  		unsigned long end;
  
  		/*
  		 * 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
  		 */
  		end = cfqd->last_end_request + CFQ_IDLE_GRACE;
  		if (time_before(jiffies, end)) {
  			mod_timer(&cfqd->idle_class_timer, end);
  			cfqq = NULL;
67060e379   Jens Axboe   cfq-iosched: sort...
780
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
781
  	}
6d048f531   Jens Axboe   cfq-iosched: deve...
782
783
  	return cfqq;
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
784
785
786
  /*
   * Get and set a new active queue for service.
   */
6d048f531   Jens Axboe   cfq-iosched: deve...
787
788
789
  static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
  {
  	struct cfq_queue *cfqq;
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
790
  	cfqq = cfq_get_next_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
791
  	__cfq_set_active_queue(cfqd, cfqq);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
792
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
793
  }
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
794
795
796
797
798
799
800
801
  static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,
  					  struct request *rq)
  {
  	if (rq->sector >= cfqd->last_position)
  		return rq->sector - cfqd->last_position;
  	else
  		return cfqd->last_position - rq->sector;
  }
6d048f531   Jens Axboe   cfq-iosched: deve...
802
803
804
805
806
807
808
809
810
  static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq)
  {
  	struct cfq_io_context *cic = cfqd->active_cic;
  
  	if (!sample_valid(cic->seek_samples))
  		return 0;
  
  	return cfq_dist_from_last(cfqd, rq) <= cic->seek_mean;
  }
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
811
812
  static int cfq_close_cooperator(struct cfq_data *cfq_data,
  				struct cfq_queue *cfqq)
6d048f531   Jens Axboe   cfq-iosched: deve...
813
  {
6d048f531   Jens Axboe   cfq-iosched: deve...
814
  	/*
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
815
816
817
  	 * We should notice if some of the queues are cooperating, eg
  	 * working closely on the same area of the disk. In that case,
  	 * we can group them together and don't waste time idling.
6d048f531   Jens Axboe   cfq-iosched: deve...
818
  	 */
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
819
  	return 0;
6d048f531   Jens Axboe   cfq-iosched: deve...
820
821
822
  }
  
  #define CIC_SEEKY(cic) ((cic)->seek_mean > (8 * 1024))
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
823

6d048f531   Jens Axboe   cfq-iosched: deve...
824
  static void cfq_arm_slice_timer(struct cfq_data *cfqd)
22e2c507c   Jens Axboe   [PATCH] Update cf...
825
  {
1792669cc   Jens Axboe   cfq-iosched: don'...
826
  	struct cfq_queue *cfqq = cfqd->active_queue;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
827
  	struct cfq_io_context *cic;
7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
828
  	unsigned long sl;
dd67d0515   Jens Axboe   [PATCH] rbtree: s...
829
  	WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list));
6d048f531   Jens Axboe   cfq-iosched: deve...
830
  	WARN_ON(cfq_cfqq_slice_new(cfqq));
22e2c507c   Jens Axboe   [PATCH] Update cf...
831
832
833
834
  
  	/*
  	 * idle is disabled, either manually or by past process history
  	 */
6d048f531   Jens Axboe   cfq-iosched: deve...
835
836
  	if (!cfqd->cfq_slice_idle || !cfq_cfqq_idle_window(cfqq))
  		return;
22e2c507c   Jens Axboe   [PATCH] Update cf...
837
838
839
  	/*
  	 * task has exited, don't wait
  	 */
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
840
841
  	cic = cfqd->active_cic;
  	if (!cic || !cic->ioc->task)
6d048f531   Jens Axboe   cfq-iosched: deve...
842
843
844
845
846
  		return;
  
  	/*
  	 * See if this prio level has a good candidate
  	 */
1afba0451   Jens Axboe   cfq-iosched: mino...
847
848
  	if (cfq_close_cooperator(cfqd, cfqq) &&
  	    (sample_valid(cic->ttime_samples) && cic->ttime_mean > 2))
6d048f531   Jens Axboe   cfq-iosched: deve...
849
  		return;
22e2c507c   Jens Axboe   [PATCH] Update cf...
850

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
851
852
  	cfq_mark_cfqq_must_dispatch(cfqq);
  	cfq_mark_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
853

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
854
855
856
857
858
  	/*
  	 * 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
  	 */
6d048f531   Jens Axboe   cfq-iosched: deve...
859
  	sl = cfqd->cfq_slice_idle;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
860
  	if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
861
  		sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
862

7b14e3b52   Jens Axboe   [PATCH] cfq-iosch...
863
  	mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
865
866
867
  /*
   * Move request from internal lists to the request queue dispatch list.
   */
165125e1e   Jens Axboe   [BLOCK] Get rid o...
868
  static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
  {
3ed9a2965   Jens Axboe   cfq-iosched: impr...
870
  	struct cfq_data *cfqd = q->elevator->elevator_data;
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
871
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
872

5380a101d   Jens Axboe   [PATCH] cfq-iosch...
873
  	cfq_remove_request(rq);
6d048f531   Jens Axboe   cfq-iosched: deve...
874
  	cfqq->dispatched++;
5380a101d   Jens Axboe   [PATCH] cfq-iosch...
875
  	elv_dispatch_sort(q, rq);
3ed9a2965   Jens Axboe   cfq-iosched: impr...
876
877
878
  
  	if (cfq_cfqq_sync(cfqq))
  		cfqd->sync_flight++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
881
882
883
  }
  
  /*
   * return expired entry, or NULL to just start from scratch in rbtree
   */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
884
  static inline struct request *cfq_check_fifo(struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
  {
  	struct cfq_data *cfqd = cfqq->cfqd;
22e2c507c   Jens Axboe   [PATCH] Update cf...
887
  	struct request *rq;
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
888
  	int fifo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
890
  	if (cfq_cfqq_fifo_expire(cfqq))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
  		return NULL;
cb8874119   Jens Axboe   cfq-iosched: twea...
892
893
  
  	cfq_mark_cfqq_fifo_expire(cfqq);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
894
895
  	if (list_empty(&cfqq->fifo))
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896

6d048f531   Jens Axboe   cfq-iosched: deve...
897
  	fifo = cfq_cfqq_sync(cfqq);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
898
  	rq = rq_entry_fifo(cfqq->fifo.next);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899

6d048f531   Jens Axboe   cfq-iosched: deve...
900
901
  	if (time_before(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo]))
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902

6d048f531   Jens Axboe   cfq-iosched: deve...
903
  	return rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
905
906
907
908
  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
909

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

22e2c507c   Jens Axboe   [PATCH] Update cf...
912
  	return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
914
  /*
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
915
916
   * Select a queue for service. If we have a current active queue,
   * check whether to continue servicing it, or retrieve and set a new one.
22e2c507c   Jens Axboe   [PATCH] Update cf...
917
   */
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
918
  static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921

22e2c507c   Jens Axboe   [PATCH] Update cf...
922
923
924
  	cfqq = cfqd->active_queue;
  	if (!cfqq)
  		goto new_queue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925

22e2c507c   Jens Axboe   [PATCH] Update cf...
926
  	/*
6d048f531   Jens Axboe   cfq-iosched: deve...
927
  	 * The active queue has run out of time, expire it and select new.
22e2c507c   Jens Axboe   [PATCH] Update cf...
928
  	 */
6d048f531   Jens Axboe   cfq-iosched: deve...
929
  	if (cfq_slice_used(cfqq))
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
930
  		goto expire;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931

22e2c507c   Jens Axboe   [PATCH] Update cf...
932
  	/*
6d048f531   Jens Axboe   cfq-iosched: deve...
933
934
  	 * The active queue has requests and isn't expired, allow it to
  	 * dispatch.
22e2c507c   Jens Axboe   [PATCH] Update cf...
935
  	 */
dd67d0515   Jens Axboe   [PATCH] rbtree: s...
936
  	if (!RB_EMPTY_ROOT(&cfqq->sort_list))
22e2c507c   Jens Axboe   [PATCH] Update cf...
937
  		goto keep_queue;
6d048f531   Jens Axboe   cfq-iosched: deve...
938
939
940
941
942
943
  
  	/*
  	 * No requests pending. If the active queue still has requests in
  	 * flight or is idling for a new request, allow either of these
  	 * conditions to happen (or time out) before selecting a new queue.
  	 */
cc1974797   Jens Axboe   cfq-iosched: tigh...
944
945
  	if (timer_pending(&cfqd->idle_slice_timer) ||
  	    (cfqq->dispatched && cfq_cfqq_idle_window(cfqq))) {
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
946
947
  		cfqq = NULL;
  		goto keep_queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
948
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
949
  expire:
6084cdda0   Jens Axboe   cfq-iosched: don'...
950
  	cfq_slice_expired(cfqd, 0);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
951
952
  new_queue:
  	cfqq = cfq_set_active_queue(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
953
  keep_queue:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
954
  	return cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
955
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
956
957
958
959
  /*
   * Dispatch some requests from cfqq, moving them to the request queue
   * dispatch list.
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
960
961
962
963
964
  static int
  __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  			int max_dispatch)
  {
  	int dispatched = 0;
dd67d0515   Jens Axboe   [PATCH] rbtree: s...
965
  	BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
22e2c507c   Jens Axboe   [PATCH] Update cf...
966
967
  
  	do {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
968
  		struct request *rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
  
  		/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
971
  		 * follow expired path, else get first next available
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
  		 */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
973
974
  		if ((rq = cfq_check_fifo(cfqq)) == NULL)
  			rq = cfqq->next_rq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
975
976
977
978
  
  		/*
  		 * finally, insert request into driver dispatch list
  		 */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
979
  		cfq_dispatch_insert(cfqd->queue, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980

22e2c507c   Jens Axboe   [PATCH] Update cf...
981
  		dispatched++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982

22e2c507c   Jens Axboe   [PATCH] Update cf...
983
  		if (!cfqd->active_cic) {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
984
985
  			atomic_inc(&RQ_CIC(rq)->ioc->refcount);
  			cfqd->active_cic = RQ_CIC(rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
986
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987

dd67d0515   Jens Axboe   [PATCH] rbtree: s...
988
  		if (RB_EMPTY_ROOT(&cfqq->sort_list))
22e2c507c   Jens Axboe   [PATCH] Update cf...
989
990
991
992
993
  			break;
  
  	} while (dispatched < max_dispatch);
  
  	/*
22e2c507c   Jens Axboe   [PATCH] Update cf...
994
995
996
  	 * expire an async queue immediately if it has used up its slice. idle
  	 * queue always expire after 1 dispatch round.
  	 */
a99380065   Jens Axboe   cfq-iosched: fix ...
997
  	if (cfqd->busy_queues > 1 && ((!cfq_cfqq_sync(cfqq) &&
20e493a8d   Jens Axboe   cfq-iosched: get ...
998
  	    dispatched >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
a99380065   Jens Axboe   cfq-iosched: fix ...
999
  	    cfq_class_idle(cfqq))) {
44f7c1606   Jens Axboe   cfq-iosched: defe...
1000
  		cfqq->slice_end = jiffies + 1;
6084cdda0   Jens Axboe   cfq-iosched: don'...
1001
  		cfq_slice_expired(cfqd, 0);
44f7c1606   Jens Axboe   cfq-iosched: defe...
1002
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1003
1004
1005
  
  	return dispatched;
  }
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  static inline int __cfq_forced_dispatch_cfqq(struct cfq_queue *cfqq)
  {
  	int dispatched = 0;
  
  	while (cfqq->next_rq) {
  		cfq_dispatch_insert(cfqq->cfqd->queue, cfqq->next_rq);
  		dispatched++;
  	}
  
  	BUG_ON(!list_empty(&cfqq->fifo));
  	return dispatched;
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
1018
1019
1020
1021
  /*
   * Drain our current requests. Used for barriers and when switching
   * io schedulers on-the-fly.
   */
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
1022
  static int cfq_forced_dispatch(struct cfq_data *cfqd)
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1023
  {
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
1024
1025
  	int dispatched = 0;
  	struct rb_node *n;
cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
1026
  	while ((n = cfq_rb_first(&cfqd->service_tree)) != NULL) {
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
1027
  		struct cfq_queue *cfqq = rb_entry(n, struct cfq_queue, rb_node);
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1028

d9e7620e6   Jens Axboe   cfq-iosched: rewo...
1029
1030
  		dispatched += __cfq_forced_dispatch_cfqq(cfqq);
  	}
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1031

6084cdda0   Jens Axboe   cfq-iosched: don'...
1032
  	cfq_slice_expired(cfqd, 0);
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1033
1034
1035
1036
1037
  
  	BUG_ON(cfqd->busy_queues);
  
  	return dispatched;
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1038
  static int cfq_dispatch_requests(struct request_queue *q, int force)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1039
1040
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
6d048f531   Jens Axboe   cfq-iosched: deve...
1041
  	struct cfq_queue *cfqq;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1042
  	int dispatched;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1043
1044
1045
  
  	if (!cfqd->busy_queues)
  		return 0;
1b5ed5e1f   Tejun Heo   [BLOCK] cfq-iosch...
1046
1047
  	if (unlikely(force))
  		return cfq_forced_dispatch(cfqd);
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1048
  	dispatched = 0;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1049
  	while ((cfqq = cfq_select_queue(cfqd)) != NULL) {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1050
  		int max_dispatch;
3ed9a2965   Jens Axboe   cfq-iosched: impr...
1051
1052
1053
1054
1055
1056
  		max_dispatch = cfqd->cfq_quantum;
  		if (cfq_class_idle(cfqq))
  			max_dispatch = 1;
  
  		if (cfqq->dispatched >= max_dispatch) {
  			if (cfqd->busy_queues > 1)
6d048f531   Jens Axboe   cfq-iosched: deve...
1057
  				break;
3ed9a2965   Jens Axboe   cfq-iosched: impr...
1058
  			if (cfqq->dispatched >= 4 * max_dispatch)
a99380065   Jens Axboe   cfq-iosched: fix ...
1059
1060
  				break;
  		}
9ede209e8   Jens Axboe   cfq-iosched: impr...
1061

3ed9a2965   Jens Axboe   cfq-iosched: impr...
1062
1063
  		if (cfqd->sync_flight && !cfq_cfqq_sync(cfqq))
  			break;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1064
1065
  		cfq_clear_cfqq_must_dispatch(cfqq);
  		cfq_clear_cfqq_wait_request(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1066
  		del_timer(&cfqd->idle_slice_timer);
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1067
  		dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068
  	}
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1069
  	return dispatched;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
  /*
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1072
1073
   * task holds one reference to the queue, dropped when task exits. each rq
   * in-flight on this queue also holds a reference, dropped when rq is freed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
1075
1076
1077
1078
   *
   * queue lock must be held here.
   */
  static void cfq_put_queue(struct cfq_queue *cfqq)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1079
1080
1081
  	struct cfq_data *cfqd = cfqq->cfqd;
  
  	BUG_ON(atomic_read(&cfqq->ref) <= 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1082
1083
1084
1085
1086
  
  	if (!atomic_dec_and_test(&cfqq->ref))
  		return;
  
  	BUG_ON(rb_first(&cfqq->sort_list));
22e2c507c   Jens Axboe   [PATCH] Update cf...
1087
  	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1088
  	BUG_ON(cfq_cfqq_on_rr(cfqq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089

28f95cbc3   Jens Axboe   cfq-iosched: remo...
1090
  	if (unlikely(cfqd->active_queue == cfqq)) {
6084cdda0   Jens Axboe   cfq-iosched: don'...
1091
  		__cfq_slice_expired(cfqd, cfqq, 0);
28f95cbc3   Jens Axboe   cfq-iosched: remo...
1092
1093
  		cfq_schedule_dispatch(cfqd);
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1094

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
1096
  	kmem_cache_free(cfq_pool, cfqq);
  }
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1097
  static void cfq_free_io_context(struct io_context *ioc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1099
  	struct cfq_io_context *__cic;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1100
1101
  	struct rb_node *n;
  	int freed = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1102

597bc485d   Jens Axboe   cfq-iosched: spee...
1103
  	ioc->ioc_data = NULL;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1104
1105
1106
  	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...
1107
  		kmem_cache_free(cfq_ioc_pool, __cic);
334e94de9   Al Viro   [PATCH] deal with...
1108
  		freed++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
  	}
4050cf167   Jens Axboe   [PATCH] cfq-iosch...
1110
1111
1112
  	elv_ioc_count_mod(ioc_count, -freed);
  
  	if (ioc_gone && !elv_ioc_count_read(ioc_count))
334e94de9   Al Viro   [PATCH] deal with...
1113
  		complete(ioc_gone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
  }
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1115
  static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
  {
28f95cbc3   Jens Axboe   cfq-iosched: remo...
1117
  	if (unlikely(cfqq == cfqd->active_queue)) {
6084cdda0   Jens Axboe   cfq-iosched: don'...
1118
  		__cfq_slice_expired(cfqd, cfqq, 0);
28f95cbc3   Jens Axboe   cfq-iosched: remo...
1119
1120
  		cfq_schedule_dispatch(cfqd);
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1121

89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1122
1123
  	cfq_put_queue(cfqq);
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1124

89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1125
1126
1127
  static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
  					 struct cfq_io_context *cic)
  {
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1128
1129
1130
  	list_del_init(&cic->queue_list);
  	smp_wmb();
  	cic->key = NULL;
12a057321   Al Viro   [PATCH] keep sync...
1131
  	if (cic->cfqq[ASYNC]) {
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1132
  		cfq_exit_cfqq(cfqd, cic->cfqq[ASYNC]);
12a057321   Al Viro   [PATCH] keep sync...
1133
1134
1135
1136
  		cic->cfqq[ASYNC] = NULL;
  	}
  
  	if (cic->cfqq[SYNC]) {
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1137
  		cfq_exit_cfqq(cfqd, cic->cfqq[SYNC]);
12a057321   Al Viro   [PATCH] keep sync...
1138
1139
  		cic->cfqq[SYNC] = NULL;
  	}
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1140
  }
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1141
1142
1143
  static void cfq_exit_single_io_context(struct cfq_io_context *cic)
  {
  	struct cfq_data *cfqd = cic->key;
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1144
  	if (cfqd) {
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1145
  		struct request_queue *q = cfqd->queue;
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1146

fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1147
  		spin_lock_irq(q->queue_lock);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1148
  		__cfq_exit_single_io_context(cfqd, cic);
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1149
  		spin_unlock_irq(q->queue_lock);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1150
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1151
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
1152
1153
1154
1155
  /*
   * The process that ioc belongs to has exited, we need to clean up
   * and put the internal structures we have that belongs to that process.
   */
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1156
  static void cfq_exit_io_context(struct io_context *ioc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1158
  	struct cfq_io_context *__cic;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1159
  	struct rb_node *n;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1160

597bc485d   Jens Axboe   cfq-iosched: spee...
1161
  	ioc->ioc_data = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
1164
  	/*
  	 * put the reference this task is holding to the various queues
  	 */
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1165
1166
1167
  	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...
1168
  		cfq_exit_single_io_context(__cic);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1169
  		n = rb_next(n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1172
  static struct cfq_io_context *
8267e268e   Al Viro   [PATCH] gfp_t: bl...
1173
  cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  {
b5deef901   Jens Axboe   [PATCH] Make sure...
1175
  	struct cfq_io_context *cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176

94f6030ca   Christoph Lameter   Slab allocators: ...
1177
1178
  	cic = kmem_cache_alloc_node(cfq_ioc_pool, gfp_mask | __GFP_ZERO,
  							cfqd->queue->node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
  	if (cic) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1180
  		cic->last_end_request = jiffies;
553698f94   Jens Axboe   [PATCH] cfq-iosch...
1181
  		INIT_LIST_HEAD(&cic->queue_list);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1182
1183
  		cic->dtor = cfq_free_io_context;
  		cic->exit = cfq_exit_io_context;
4050cf167   Jens Axboe   [PATCH] cfq-iosch...
1184
  		elv_ioc_count_inc(ioc_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1185
1186
1187
1188
  	}
  
  	return cic;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1189
1190
1191
1192
  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...
1193
  	if (!cfq_cfqq_prio_changed(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
  		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...
1219
  			cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1220
1221
1222
1223
1224
1225
1226
1227
1228
  			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...
1229
  	cfq_clear_cfqq_prio_changed(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1230
  }
478a82b0e   Al Viro   [PATCH] switch to...
1231
  static inline void changed_ioprio(struct cfq_io_context *cic)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1232
  {
478a82b0e   Al Viro   [PATCH] switch to...
1233
1234
  	struct cfq_data *cfqd = cic->key;
  	struct cfq_queue *cfqq;
c1b707d25   Jens Axboe   [PATCH] CFQ: bad ...
1235
  	unsigned long flags;
35e6077cb   Jens Axboe   [PATCH] cfq-iosch...
1236

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1237
1238
  	if (unlikely(!cfqd))
  		return;
c1b707d25   Jens Axboe   [PATCH] CFQ: bad ...
1239
  	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1240
1241
1242
1243
  
  	cfqq = cic->cfqq[ASYNC];
  	if (cfqq) {
  		struct cfq_queue *new_cfqq;
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1244
  		new_cfqq = cfq_get_queue(cfqd, ASYNC, cic->ioc->task,
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1245
1246
1247
1248
1249
  					 GFP_ATOMIC);
  		if (new_cfqq) {
  			cic->cfqq[ASYNC] = new_cfqq;
  			cfq_put_queue(cfqq);
  		}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1250
  	}
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1251
1252
1253
1254
  
  	cfqq = cic->cfqq[SYNC];
  	if (cfqq)
  		cfq_mark_cfqq_prio_changed(cfqq);
c1b707d25   Jens Axboe   [PATCH] CFQ: bad ...
1255
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1256
  }
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1257
  static void cfq_ioc_set_ioprio(struct io_context *ioc)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1258
  {
a6a0763a6   Al Viro   [PATCH] fix the e...
1259
  	struct cfq_io_context *cic;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1260
  	struct rb_node *n;
a6a0763a6   Al Viro   [PATCH] fix the e...
1261

fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1262
  	ioc->ioprio_changed = 0;
a6a0763a6   Al Viro   [PATCH] fix the e...
1263

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1264
1265
1266
  	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...
1267

478a82b0e   Al Viro   [PATCH] switch to...
1268
  		changed_ioprio(cic);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1269
1270
  		n = rb_next(n);
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1271
1272
1273
  }
  
  static struct cfq_queue *
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1274
1275
  cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
  		     struct task_struct *tsk, gfp_t gfp_mask)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1276
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1277
  	struct cfq_queue *cfqq, *new_cfqq = NULL;
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1278
  	struct cfq_io_context *cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1279
1280
  
  retry:
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1281
1282
1283
  	cic = cfq_cic_rb_lookup(cfqd, tsk->io_context);
  	/* cic always exists here */
  	cfqq = cic_to_cfqq(cic, is_sync);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1284
1285
1286
1287
1288
1289
  
  	if (!cfqq) {
  		if (new_cfqq) {
  			cfqq = new_cfqq;
  			new_cfqq = NULL;
  		} else if (gfp_mask & __GFP_WAIT) {
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1290
1291
1292
1293
1294
1295
  			/*
  			 * Inform the allocator of the fact that we will
  			 * just repeat this allocation if it fails, to allow
  			 * the allocator to do whatever it needs to attempt to
  			 * free memory.
  			 */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1296
  			spin_unlock_irq(cfqd->queue->queue_lock);
94f6030ca   Christoph Lameter   Slab allocators: ...
1297
1298
1299
  			new_cfqq = kmem_cache_alloc_node(cfq_pool,
  					gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
  					cfqd->queue->node);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1300
1301
1302
  			spin_lock_irq(cfqd->queue->queue_lock);
  			goto retry;
  		} else {
94f6030ca   Christoph Lameter   Slab allocators: ...
1303
1304
1305
  			cfqq = kmem_cache_alloc_node(cfq_pool,
  					gfp_mask | __GFP_ZERO,
  					cfqd->queue->node);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1306
1307
1308
  			if (!cfqq)
  				goto out;
  		}
d9e7620e6   Jens Axboe   cfq-iosched: rewo...
1309
  		RB_CLEAR_NODE(&cfqq->rb_node);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1310
  		INIT_LIST_HEAD(&cfqq->fifo);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1311
1312
  		atomic_set(&cfqq->ref, 0);
  		cfqq->cfqd = cfqd;
c5b680f3b   Jens Axboe   cfq-iosched: acco...
1313

91fac317a   Vasily Tarasov   cfq-iosched: get ...
1314
  		if (is_sync) {
a99380065   Jens Axboe   cfq-iosched: fix ...
1315
  			cfq_mark_cfqq_idle_window(cfqq);
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1316
1317
  			cfq_mark_cfqq_sync(cfqq);
  		}
a99380065   Jens Axboe   cfq-iosched: fix ...
1318

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1319
  		cfq_mark_cfqq_prio_changed(cfqq);
53b03744e   Jens Axboe   [PATCH] cfq-iosch...
1320
  		cfq_mark_cfqq_queue_new(cfqq);
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1321

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1322
  		cfq_init_prio_data(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1323
1324
1325
1326
  	}
  
  	if (new_cfqq)
  		kmem_cache_free(cfq_pool, new_cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1327
1328
1329
1330
  out:
  	WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
  	return cfqq;
  }
c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
  static struct cfq_queue **
  cfq_async_queue_prio(struct cfq_data *cfqd, int ioprio_class, int ioprio)
  {
  	switch(ioprio_class) {
  	case IOPRIO_CLASS_RT:
  		return &cfqd->async_cfqq[0][ioprio];
  	case IOPRIO_CLASS_BE:
  		return &cfqd->async_cfqq[1][ioprio];
  	case IOPRIO_CLASS_IDLE:
  		return &cfqd->async_idle_cfqq;
  	default:
  		BUG();
  	}
  }
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1345
1346
1347
1348
1349
  static struct cfq_queue *
  cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
  	      gfp_t gfp_mask)
  {
  	const int ioprio = task_ioprio(tsk);
c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1350
1351
  	const int ioprio_class = task_ioprio_class(tsk);
  	struct cfq_queue **async_cfqq = NULL;
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1352
  	struct cfq_queue *cfqq = NULL;
c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1353
1354
1355
1356
  	if (!is_sync) {
  		async_cfqq = cfq_async_queue_prio(cfqd, ioprio_class, ioprio);
  		cfqq = *async_cfqq;
  	}
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1357
1358
1359
1360
1361
1362
  	if (!cfqq)
  		cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);
  
  	/*
  	 * pin the queue now that it's allocated, scheduler exit will prune it
  	 */
c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1363
  	if (!is_sync && !(*async_cfqq)) {
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1364
  		atomic_inc(&cfqq->ref);
c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1365
  		*async_cfqq = cfqq;
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1366
1367
1368
1369
1370
  	}
  
  	atomic_inc(&cfqq->ref);
  	return cfqq;
  }
498d3aa2b   Jens Axboe   [PATCH] cfq-iosch...
1371
1372
1373
  /*
   * We drop cfq io contexts lazily, so we may find a dead one.
   */
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1374
1375
1376
  static void
  cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
  {
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1377
  	WARN_ON(!list_empty(&cic->queue_list));
597bc485d   Jens Axboe   cfq-iosched: spee...
1378
1379
1380
  
  	if (ioc->ioc_data == cic)
  		ioc->ioc_data = NULL;
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1381
  	rb_erase(&cic->rb_node, &ioc->cic_root);
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1382
  	kmem_cache_free(cfq_ioc_pool, cic);
4050cf167   Jens Axboe   [PATCH] cfq-iosch...
1383
  	elv_ioc_count_dec(ioc_count);
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1384
  }
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1385
1386
1387
  static struct cfq_io_context *
  cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
  {
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1388
  	struct rb_node *n;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1389
  	struct cfq_io_context *cic;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1390
  	void *k, *key = cfqd;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1391

91fac317a   Vasily Tarasov   cfq-iosched: get ...
1392
1393
  	if (unlikely(!ioc))
  		return NULL;
597bc485d   Jens Axboe   cfq-iosched: spee...
1394
1395
1396
1397
1398
1399
  	/*
  	 * we maintain a last-hit cache, to avoid browsing over the tree
  	 */
  	cic = ioc->ioc_data;
  	if (cic && cic->key == cfqd)
  		return cic;
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1400
1401
  restart:
  	n = ioc->cic_root.rb_node;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1402
1403
  	while (n) {
  		cic = rb_entry(n, struct cfq_io_context, rb_node);
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1404
1405
1406
  		/* ->key must be copied to avoid race with cfq_exit_queue() */
  		k = cic->key;
  		if (unlikely(!k)) {
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1407
1408
1409
  			cfq_drop_dead_cic(ioc, cic);
  			goto restart;
  		}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1410

be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1411
  		if (key < k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1412
  			n = n->rb_left;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1413
  		else if (key > k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1414
  			n = n->rb_right;
597bc485d   Jens Axboe   cfq-iosched: spee...
1415
1416
  		else {
  			ioc->ioc_data = cic;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1417
  			return cic;
597bc485d   Jens Axboe   cfq-iosched: spee...
1418
  		}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1419
1420
1421
1422
1423
1424
1425
1426
1427
  	}
  
  	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: ...
1428
1429
  	struct rb_node **p;
  	struct rb_node *parent;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1430
  	struct cfq_io_context *__cic;
0261d6886   Jens Axboe   [PATCH] CFQ: use ...
1431
  	unsigned long flags;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1432
  	void *k;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1433

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1434
1435
  	cic->ioc = ioc;
  	cic->key = cfqd;
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1436
1437
1438
  restart:
  	parent = NULL;
  	p = &ioc->cic_root.rb_node;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1439
1440
1441
  	while (*p) {
  		parent = *p;
  		__cic = rb_entry(parent, struct cfq_io_context, rb_node);
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1442
1443
1444
  		/* ->key must be copied to avoid race with cfq_exit_queue() */
  		k = __cic->key;
  		if (unlikely(!k)) {
be33c3a67   Oleg Nesterov   [PATCH] cfq_cic_l...
1445
  			cfq_drop_dead_cic(ioc, __cic);
dbecf3ab4   OGAWA Hirofumi   [PATCH 2/2] cfq: ...
1446
1447
  			goto restart;
  		}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1448

be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1449
  		if (cic->key < k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1450
  			p = &(*p)->rb_left;
be3b07535   OGAWA Hirofumi   [PATCH] cfq: Furt...
1451
  		else if (cic->key > k)
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1452
1453
1454
1455
1456
1457
1458
  			p = &(*p)->rb_right;
  		else
  			BUG();
  	}
  
  	rb_link_node(&cic->rb_node, parent, p);
  	rb_insert_color(&cic->rb_node, &ioc->cic_root);
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1459

0261d6886   Jens Axboe   [PATCH] CFQ: use ...
1460
  	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1461
  	list_add(&cic->queue_list, &cfqd->cic_list);
0261d6886   Jens Axboe   [PATCH] CFQ: use ...
1462
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1463
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
1466
  /*
   * 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...
1467
   * than one device managed by cfq.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468
1469
   */
  static struct cfq_io_context *
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1470
  cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1471
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1472
  	struct io_context *ioc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
  	struct cfq_io_context *cic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474

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

b5deef901   Jens Axboe   [PATCH] Make sure...
1477
  	ioc = get_io_context(gfp_mask, cfqd->queue->node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
  	if (!ioc)
  		return NULL;
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1480
1481
1482
  	cic = cfq_cic_rb_lookup(cfqd, ioc);
  	if (cic)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1484
1485
1486
  	cic = cfq_alloc_io_context(cfqd, gfp_mask);
  	if (cic == NULL)
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487

e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1488
  	cfq_cic_link(cfqd, ioc, cic);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
  out:
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
1490
1491
1492
  	smp_read_barrier_depends();
  	if (unlikely(ioc->ioprio_changed))
  		cfq_ioc_set_ioprio(ioc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1493
1494
1495
1496
1497
  	return cic;
  err:
  	put_io_context(ioc);
  	return NULL;
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1498
1499
  static void
  cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
  {
aaf1228dd   Jens Axboe   cfq-iosched: remo...
1501
1502
  	unsigned long elapsed = jiffies - cic->last_end_request;
  	unsigned long ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
db3b5848e   Kiyoshi Ueda   When cfq I/O sche...
1503

22e2c507c   Jens Axboe   [PATCH] Update cf...
1504
1505
1506
1507
  	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
1508

206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1509
  static void
6d048f531   Jens Axboe   cfq-iosched: deve...
1510
1511
  cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic,
  		       struct request *rq)
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1512
1513
1514
  {
  	sector_t sdist;
  	u64 total;
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1515
1516
  	if (cic->last_request_pos < rq->sector)
  		sdist = rq->sector - cic->last_request_pos;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1517
  	else
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1518
  		sdist = cic->last_request_pos - rq->sector;
206dc69b3   Jens Axboe   [BLOCK] cfq-iosch...
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
  
  	/*
  	 * 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
1535

22e2c507c   Jens Axboe   [PATCH] Update cf...
1536
1537
1538
1539
1540
1541
1542
1543
  /*
   * 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)
  {
1be92f2fc   Jens Axboe   cfq-iosched: neve...
1544
1545
1546
1547
1548
1549
  	int enable_idle;
  
  	if (!cfq_cfqq_sync(cfqq))
  		return;
  
  	enable_idle = cfq_cfqq_idle_window(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1551
1552
  	if (!cic->ioc->task || !cfqd->cfq_slice_idle ||
  	    (cfqd->hw_tag && CIC_SEEKY(cic)))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1553
1554
1555
1556
1557
1558
  		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
1559
  	}
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1560
1561
1562
1563
  	if (enable_idle)
  		cfq_mark_cfqq_idle_window(cfqq);
  	else
  		cfq_clear_cfqq_idle_window(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1564
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565

22e2c507c   Jens Axboe   [PATCH] Update cf...
1566
1567
1568
1569
1570
1571
  /*
   * 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,
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1572
  		   struct request *rq)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1573
  {
6d048f531   Jens Axboe   cfq-iosched: deve...
1574
  	struct cfq_queue *cfqq;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1575

6d048f531   Jens Axboe   cfq-iosched: deve...
1576
1577
  	cfqq = cfqd->active_queue;
  	if (!cfqq)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1578
  		return 0;
6d048f531   Jens Axboe   cfq-iosched: deve...
1579
1580
1581
1582
  	if (cfq_slice_used(cfqq))
  		return 1;
  
  	if (cfq_class_idle(new_cfqq))
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1583
  		return 0;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1584
1585
1586
  
  	if (cfq_class_idle(cfqq))
  		return 1;
1e3335de0   Jens Axboe   cfq-iosched: impr...
1587

22e2c507c   Jens Axboe   [PATCH] Update cf...
1588
  	/*
374f84ac3   Jens Axboe   [PATCH] cfq-iosch...
1589
1590
1591
  	 * if the new request is sync, but the currently running queue is
  	 * not, let the sync request have priority.
  	 */
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1592
  	if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1593
  		return 1;
1e3335de0   Jens Axboe   cfq-iosched: impr...
1594

374f84ac3   Jens Axboe   [PATCH] cfq-iosch...
1595
1596
1597
1598
1599
1600
  	/*
  	 * So both queues are sync. Let the new request get disk time if
  	 * it's a metadata request and the current queue is doing regular IO.
  	 */
  	if (rq_is_meta(rq) && !cfqq->meta_pending)
  		return 1;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1601

1e3335de0   Jens Axboe   cfq-iosched: impr...
1602
1603
1604
1605
1606
1607
1608
  	if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
  		return 0;
  
  	/*
  	 * if this request is as-good as one we would expect from the
  	 * current cfqq, let it preempt
  	 */
6d048f531   Jens Axboe   cfq-iosched: deve...
1609
  	if (cfq_rq_close(cfqd, rq))
1e3335de0   Jens Axboe   cfq-iosched: impr...
1610
  		return 1;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1611
1612
1613
1614
1615
1616
1617
1618
1619
  	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)
  {
6084cdda0   Jens Axboe   cfq-iosched: don'...
1620
  	cfq_slice_expired(cfqd, 1);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1621

bf5722567   Jens Axboe   [PATCH] cfq-iosch...
1622
1623
1624
1625
1626
  	/*
  	 * Put the new queue at the front of the of the current list,
  	 * so we know that it will be selected next.
  	 */
  	BUG_ON(!cfq_cfqq_on_rr(cfqq));
edd75ffd9   Jens Axboe   cfq-iosched: get ...
1627
1628
  
  	cfq_service_tree_add(cfqd, cfqq, 1);
bf5722567   Jens Axboe   [PATCH] cfq-iosch...
1629

44f7c1606   Jens Axboe   cfq-iosched: defe...
1630
1631
  	cfqq->slice_end = 0;
  	cfq_mark_cfqq_slice_new(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1632
1633
1634
  }
  
  /*
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1635
   * Called when a new fs request (rq) is added (to cfqq). Check if there's
22e2c507c   Jens Axboe   [PATCH] Update cf...
1636
1637
1638
   * something we should do about it
   */
  static void
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1639
1640
  cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
  		struct request *rq)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1641
  {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1642
  	struct cfq_io_context *cic = RQ_CIC(rq);
12e9fddd6   Jens Axboe   [PATCH] cfq-iosch...
1643

374f84ac3   Jens Axboe   [PATCH] cfq-iosch...
1644
1645
  	if (rq_is_meta(rq))
  		cfqq->meta_pending++;
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1646
  	cfq_update_io_thinktime(cfqd, cic);
6d048f531   Jens Axboe   cfq-iosched: deve...
1647
  	cfq_update_io_seektime(cfqd, cic, rq);
9c2c38a12   Jens Axboe   [PATCH] cfq-iosch...
1648
  	cfq_update_idle_window(cfqd, cfqq, cic);
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1649
  	cic->last_request_pos = rq->sector + rq->nr_sectors;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1650
1651
1652
1653
1654
1655
1656
  
  	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...
1657
1658
  		if (cfq_cfqq_wait_request(cfqq)) {
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1659
  			del_timer(&cfqd->idle_slice_timer);
dc72ef4ae   Jens Axboe   [PATCH] Add blk_s...
1660
  			blk_start_queueing(cfqd->queue);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1661
  		}
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1662
  	} else if (cfq_should_preempt(cfqd, cfqq, rq)) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1663
1664
1665
1666
1667
1668
  		/*
  		 * 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...
1669
  		cfq_mark_cfqq_must_dispatch(cfqq);
dc72ef4ae   Jens Axboe   [PATCH] Add blk_s...
1670
  		blk_start_queueing(cfqd->queue);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1671
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1673
  static void cfq_insert_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  {
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1675
  	struct cfq_data *cfqd = q->elevator->elevator_data;
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1676
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1677
1678
  
  	cfq_init_prio_data(cfqq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1680
  	cfq_add_rq_rb(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1681

22e2c507c   Jens Axboe   [PATCH] Update cf...
1682
  	list_add_tail(&rq->queuelist, &cfqq->fifo);
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1683
  	cfq_rq_enqueued(cfqd, cfqq, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1684
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1685
  static void cfq_completed_request(struct request_queue *q, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
  {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1687
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1688
  	struct cfq_data *cfqd = cfqq->cfqd;
5380a101d   Jens Axboe   [PATCH] cfq-iosch...
1689
  	const int sync = rq_is_sync(rq);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1690
  	unsigned long now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691

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

b4878f245   Jens Axboe   [PATCH] 02/05: up...
1694
  	WARN_ON(!cfqd->rq_in_driver);
6d048f531   Jens Axboe   cfq-iosched: deve...
1695
  	WARN_ON(!cfqq->dispatched);
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1696
  	cfqd->rq_in_driver--;
6d048f531   Jens Axboe   cfq-iosched: deve...
1697
  	cfqq->dispatched--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1698

3ed9a2965   Jens Axboe   cfq-iosched: impr...
1699
1700
  	if (cfq_cfqq_sync(cfqq))
  		cfqd->sync_flight--;
b4878f245   Jens Axboe   [PATCH] 02/05: up...
1701
1702
  	if (!cfq_class_idle(cfqq))
  		cfqd->last_end_request = now;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1703

caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1704
  	if (sync)
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1705
  		RQ_CIC(rq)->last_end_request = now;
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1706
1707
1708
1709
1710
1711
  
  	/*
  	 * 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) {
44f7c1606   Jens Axboe   cfq-iosched: defe...
1712
1713
1714
1715
1716
  		if (cfq_cfqq_slice_new(cfqq)) {
  			cfq_set_prio_slice(cfqd, cfqq);
  			cfq_clear_cfqq_slice_new(cfqq);
  		}
  		if (cfq_slice_used(cfqq))
6084cdda0   Jens Axboe   cfq-iosched: don'...
1717
  			cfq_slice_expired(cfqd, 1);
6d048f531   Jens Axboe   cfq-iosched: deve...
1718
1719
  		else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list))
  			cfq_arm_slice_timer(cfqd);
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1720
  	}
6d048f531   Jens Axboe   cfq-iosched: deve...
1721
1722
1723
  
  	if (!cfqd->rq_in_driver)
  		cfq_schedule_dispatch(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1724
  }
22e2c507c   Jens Axboe   [PATCH] Update cf...
1725
1726
1727
1728
1729
  /*
   * 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
1730
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
  	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;
  	}
22e2c507c   Jens Axboe   [PATCH] Update cf...
1749
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750

89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1751
  static inline int __cfq_may_queue(struct cfq_queue *cfqq)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1752
  {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1753
  	if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
99f95e528   Andrew Morton   [PATCH] cfq build...
1754
  	    !cfq_cfqq_must_alloc_slice(cfqq)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1755
  		cfq_mark_cfqq_must_alloc_slice(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1756
  		return ELV_MQUEUE_MUST;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1757
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758

22e2c507c   Jens Axboe   [PATCH] Update cf...
1759
  	return ELV_MQUEUE_MAY;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1760
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1761
  static int cfq_may_queue(struct request_queue *q, int rw)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1762
1763
1764
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
  	struct task_struct *tsk = current;
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1765
  	struct cfq_io_context *cic;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1766
1767
1768
1769
1770
1771
1772
1773
  	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
  	 */
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1774
1775
1776
1777
1778
  	cic = cfq_cic_rb_lookup(cfqd, tsk->io_context);
  	if (!cic)
  		return ELV_MQUEUE_MAY;
  
  	cfqq = cic_to_cfqq(cic, rw & REQ_RW_SYNC);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1779
1780
1781
  	if (cfqq) {
  		cfq_init_prio_data(cfqq);
  		cfq_prio_boost(cfqq);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1782
  		return __cfq_may_queue(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1783
1784
1785
  	}
  
  	return ELV_MQUEUE_MAY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787
1788
1789
  /*
   * queue lock held here
   */
bb37b94c6   Jens Axboe   [BLOCK] Cleanup u...
1790
  static void cfq_put_request(struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
  {
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1792
  	struct cfq_queue *cfqq = RQ_CFQQ(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1794
  	if (cfqq) {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1795
  		const int rw = rq_data_dir(rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1796

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

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1800
  		put_io_context(RQ_CIC(rq)->ioc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1802
  		rq->elevator_private = NULL;
5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1803
  		rq->elevator_private2 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1805
1806
1807
1808
1809
  		cfq_put_queue(cfqq);
  	}
  }
  
  /*
22e2c507c   Jens Axboe   [PATCH] Update cf...
1810
   * Allocate cfq data structures associated with this request.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1811
   */
22e2c507c   Jens Axboe   [PATCH] Update cf...
1812
  static int
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1813
  cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1814
1815
  {
  	struct cfq_data *cfqd = q->elevator->elevator_data;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1816
  	struct task_struct *tsk = current;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1817
1818
  	struct cfq_io_context *cic;
  	const int rw = rq_data_dir(rq);
7749a8d42   Jens Axboe   [PATCH] Propagate...
1819
  	const int is_sync = rq_is_sync(rq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1820
  	struct cfq_queue *cfqq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821
1822
1823
  	unsigned long flags;
  
  	might_sleep_if(gfp_mask & __GFP_WAIT);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1824
  	cic = cfq_get_io_context(cfqd, gfp_mask);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1825

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
  	spin_lock_irqsave(q->queue_lock, flags);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1827
1828
  	if (!cic)
  		goto queue_fail;
91fac317a   Vasily Tarasov   cfq-iosched: get ...
1829
1830
1831
  	cfqq = cic_to_cfqq(cic, is_sync);
  	if (!cfqq) {
  		cfqq = cfq_get_queue(cfqd, is_sync, tsk, gfp_mask);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1832
1833
  		if (!cfqq)
  			goto queue_fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834

91fac317a   Vasily Tarasov   cfq-iosched: get ...
1835
1836
  		cic_set_cfqq(cic, cfqq, is_sync);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837
1838
  
  	cfqq->allocated[rw]++;
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1839
  	cfq_clear_cfqq_must_alloc(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1840
  	atomic_inc(&cfqq->ref);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1842
  	spin_unlock_irqrestore(q->queue_lock, flags);
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1843

5e7053747   Jens Axboe   [PATCH] cfq-iosch...
1844
1845
1846
  	rq->elevator_private = cic;
  	rq->elevator_private2 = cfqq;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847

22e2c507c   Jens Axboe   [PATCH] Update cf...
1848
1849
1850
  queue_fail:
  	if (cic)
  		put_io_context(cic->ioc);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1851

3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1852
  	cfq_schedule_dispatch(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
1854
1855
  	spin_unlock_irqrestore(q->queue_lock, flags);
  	return 1;
  }
65f27f384   David Howells   WorkStruct: Pass ...
1856
  static void cfq_kick_queue(struct work_struct *work)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1857
  {
65f27f384   David Howells   WorkStruct: Pass ...
1858
1859
  	struct cfq_data *cfqd =
  		container_of(work, struct cfq_data, unplug_work);
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1860
  	struct request_queue *q = cfqd->queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1861
1862
1863
  	unsigned long flags;
  
  	spin_lock_irqsave(q->queue_lock, flags);
dc72ef4ae   Jens Axboe   [PATCH] Add blk_s...
1864
  	blk_start_queueing(q);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
  	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;
3c6bd2f87   Jens Axboe   cfq-iosched: chec...
1876
  	int timed_out = 1;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1877
1878
1879
1880
  
  	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
  
  	if ((cfqq = cfqd->active_queue) != NULL) {
3c6bd2f87   Jens Axboe   cfq-iosched: chec...
1881
  		timed_out = 0;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1882
1883
1884
  		/*
  		 * expired
  		 */
44f7c1606   Jens Axboe   cfq-iosched: defe...
1885
  		if (cfq_slice_used(cfqq))
22e2c507c   Jens Axboe   [PATCH] Update cf...
1886
1887
1888
1889
1890
1891
  			goto expire;
  
  		/*
  		 * only expire and reinvoke request handler, if there are
  		 * other queues with pending requests
  		 */
caaa5f9f0   Jens Axboe   [PATCH] cfq-iosch...
1892
  		if (!cfqd->busy_queues)
22e2c507c   Jens Axboe   [PATCH] Update cf...
1893
  			goto out_cont;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1894
1895
1896
1897
  
  		/*
  		 * not expired and it has a request pending, let it dispatch
  		 */
dd67d0515   Jens Axboe   [PATCH] rbtree: s...
1898
  		if (!RB_EMPTY_ROOT(&cfqq->sort_list)) {
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1899
  			cfq_mark_cfqq_must_dispatch(cfqq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1900
1901
1902
1903
  			goto out_kick;
  		}
  	}
  expire:
6084cdda0   Jens Axboe   cfq-iosched: don'...
1904
  	cfq_slice_expired(cfqd, timed_out);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1905
  out_kick:
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1906
  	cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
  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...
1925
1926
1927
  	if (!time_after_eq(jiffies, end))
  		mod_timer(&cfqd->idle_class_timer, end);
  	else
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1928
  		cfq_schedule_dispatch(cfqd);
22e2c507c   Jens Axboe   [PATCH] Update cf...
1929
1930
1931
  
  	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
  }
3b18152c3   Jens Axboe   [PATCH] CFQ io sc...
1932
1933
1934
1935
1936
1937
  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...
1938

c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
  static void cfq_put_async_queues(struct cfq_data *cfqd)
  {
  	int i;
  
  	for (i = 0; i < IOPRIO_BE_NR; i++) {
  		if (cfqd->async_cfqq[0][i])
  			cfq_put_queue(cfqd->async_cfqq[0][i]);
  		if (cfqd->async_cfqq[1][i])
  			cfq_put_queue(cfqd->async_cfqq[1][i]);
  		if (cfqd->async_idle_cfqq)
  			cfq_put_queue(cfqd->async_idle_cfqq);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1952
1953
  static void cfq_exit_queue(elevator_t *e)
  {
22e2c507c   Jens Axboe   [PATCH] Update cf...
1954
  	struct cfq_data *cfqd = e->elevator_data;
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1955
  	struct request_queue *q = cfqd->queue;
22e2c507c   Jens Axboe   [PATCH] Update cf...
1956

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

d9ff41879   Al Viro   [PATCH] make cfq_...
1959
  	spin_lock_irq(q->queue_lock);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1960

d9ff41879   Al Viro   [PATCH] make cfq_...
1961
  	if (cfqd->active_queue)
6084cdda0   Jens Axboe   cfq-iosched: don'...
1962
  		__cfq_slice_expired(cfqd, cfqd->active_queue, 0);
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1963
1964
  
  	while (!list_empty(&cfqd->cic_list)) {
d9ff41879   Al Viro   [PATCH] make cfq_...
1965
1966
1967
  		struct cfq_io_context *cic = list_entry(cfqd->cic_list.next,
  							struct cfq_io_context,
  							queue_list);
89850f7ee   Jens Axboe   [PATCH] cfq-iosch...
1968
1969
  
  		__cfq_exit_single_io_context(cfqd, cic);
d9ff41879   Al Viro   [PATCH] make cfq_...
1970
  	}
e2d74ac06   Jens Axboe   [PATCH] [BLOCK] c...
1971

c2dea2d1f   Vasily Tarasov   cfq: async queue ...
1972
  	cfq_put_async_queues(cfqd);
15c31be4d   Jens Axboe   cfq-iosched: fix ...
1973

d9ff41879   Al Viro   [PATCH] make cfq_...
1974
  	spin_unlock_irq(q->queue_lock);
a90d742e4   Al Viro   [PATCH] don't bot...
1975
1976
  
  	cfq_shutdown_timer_wq(cfqd);
a90d742e4   Al Viro   [PATCH] don't bot...
1977
  	kfree(cfqd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1978
  }
165125e1e   Jens Axboe   [BLOCK] Get rid o...
1979
  static void *cfq_init_queue(struct request_queue *q)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1980
1981
  {
  	struct cfq_data *cfqd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1982

94f6030ca   Christoph Lameter   Slab allocators: ...
1983
  	cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1984
  	if (!cfqd)
bc1c11697   Jens Axboe   [PATCH] elevator ...
1985
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1986

cc09e2990   Jens Axboe   [PATCH] cfq-iosch...
1987
  	cfqd->service_tree = CFQ_RB_ROOT;
d9ff41879   Al Viro   [PATCH] make cfq_...
1988
  	INIT_LIST_HEAD(&cfqd->cic_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1989

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990
  	cfqd->queue = q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1991

22e2c507c   Jens Axboe   [PATCH] Update cf...
1992
1993
1994
1995
1996
1997
1998
  	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;
65f27f384   David Howells   WorkStruct: Pass ...
1999
  	INIT_WORK(&cfqd->unplug_work, cfq_kick_queue);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2000

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2001
  	cfqd->cfq_quantum = cfq_quantum;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2002
2003
  	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
2004
2005
  	cfqd->cfq_back_max = cfq_back_max;
  	cfqd->cfq_back_penalty = cfq_back_penalty;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2006
2007
2008
2009
  	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...
2010

bc1c11697   Jens Axboe   [PATCH] elevator ...
2011
  	return cfqd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2012
2013
2014
2015
  }
  
  static void cfq_slab_kill(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2016
2017
2018
2019
2020
2021
2022
2023
  	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)
  {
0a31bd5f2   Christoph Lameter   KMEM_CACHE(): sim...
2024
  	cfq_pool = KMEM_CACHE(cfq_queue, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2025
2026
  	if (!cfq_pool)
  		goto fail;
0a31bd5f2   Christoph Lameter   KMEM_CACHE(): sim...
2027
  	cfq_ioc_pool = KMEM_CACHE(cfq_io_context, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2028
2029
2030
2031
2032
2033
2034
2035
  	if (!cfq_ioc_pool)
  		goto fail;
  
  	return 0;
  fail:
  	cfq_slab_kill();
  	return -ENOMEM;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2036
2037
2038
  /*
   * sysfs parts below -->
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
  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
2054
  #define SHOW_FUNCTION(__FUNC, __VAR, __CONV)				\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2055
  static ssize_t __FUNC(elevator_t *e, char *page)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2056
  {									\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2057
  	struct cfq_data *cfqd = e->elevator_data;			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
2059
2060
2061
2062
2063
  	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);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2064
2065
  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...
2066
2067
  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...
2068
2069
2070
2071
  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
2072
2073
2074
  #undef SHOW_FUNCTION
  
  #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2075
  static ssize_t __FUNC(elevator_t *e, const char *page, size_t count)	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
  {									\
3d1ab40f4   Al Viro   [PATCH] elevator_...
2077
  	struct cfq_data *cfqd = e->elevator_data;			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
  	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);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2091
2092
  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...
2093
2094
  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...
2095
2096
2097
2098
  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
2099
  #undef STORE_FUNCTION
e572ec7e4   Al Viro   [PATCH] fix rmmod...
2100
2101
2102
2103
2104
  #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),
e572ec7e4   Al Viro   [PATCH] fix rmmod...
2105
2106
2107
2108
2109
2110
2111
2112
  	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...
2113
  	__ATTR_NULL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2114
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2115
2116
2117
2118
2119
  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,
da7752650   Jens Axboe   [PATCH] cfq-iosch...
2120
  		.elevator_allow_merge_fn =	cfq_allow_merge,
b4878f245   Jens Axboe   [PATCH] 02/05: up...
2121
  		.elevator_dispatch_fn =		cfq_dispatch_requests,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
  		.elevator_add_req_fn =		cfq_insert_request,
b4878f245   Jens Axboe   [PATCH] 02/05: up...
2123
  		.elevator_activate_req_fn =	cfq_activate_request,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2124
2125
2126
  		.elevator_deactivate_req_fn =	cfq_deactivate_request,
  		.elevator_queue_empty_fn =	cfq_queue_empty,
  		.elevator_completed_req_fn =	cfq_completed_request,
21183b07e   Jens Axboe   [PATCH] cfq-iosch...
2127
2128
  		.elevator_former_req_fn =	elv_rb_former_request,
  		.elevator_latter_req_fn =	elv_rb_latter_request,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2129
2130
2131
2132
2133
  		.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,
fc46379da   Jens Axboe   [PATCH] cfq-iosch...
2134
  		.trim =				cfq_free_io_context,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
  	},
3d1ab40f4   Al Viro   [PATCH] elevator_...
2136
  	.elevator_attrs =	cfq_attrs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2137
2138
2139
2140
2141
2142
2143
  	.elevator_name =	"cfq",
  	.elevator_owner =	THIS_MODULE,
  };
  
  static int __init cfq_init(void)
  {
  	int ret;
22e2c507c   Jens Axboe   [PATCH] Update cf...
2144
2145
2146
2147
2148
2149
2150
  	/*
  	 * 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
2151
2152
2153
2154
  	if (cfq_slab_setup())
  		return -ENOMEM;
  
  	ret = elv_register(&iosched_cfq);
22e2c507c   Jens Axboe   [PATCH] Update cf...
2155
2156
  	if (ret)
  		cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2157

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2158
2159
2160
2161
2162
  	return ret;
  }
  
  static void __exit cfq_exit(void)
  {
6e9a4738c   Peter Zijlstra   [PATCH] completio...
2163
  	DECLARE_COMPLETION_ONSTACK(all_gone);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
  	elv_unregister(&iosched_cfq);
334e94de9   Al Viro   [PATCH] deal with...
2165
  	ioc_gone = &all_gone;
fba822722   OGAWA Hirofumi   [PATCH 1/2] iosch...
2166
2167
  	/* ioc_gone's update must be visible before reading ioc_count */
  	smp_wmb();
4050cf167   Jens Axboe   [PATCH] cfq-iosch...
2168
  	if (elv_ioc_count_read(ioc_count))
fba822722   OGAWA Hirofumi   [PATCH 1/2] iosch...
2169
  		wait_for_completion(ioc_gone);
334e94de9   Al Viro   [PATCH] deal with...
2170
  	synchronize_rcu();
83521d3eb   Christoph Hellwig   [PATCH] cfq-iosch...
2171
  	cfq_slab_kill();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2172
2173
2174
2175
2176
2177
2178
2179
  }
  
  module_init(cfq_init);
  module_exit(cfq_exit);
  
  MODULE_AUTHOR("Jens Axboe");
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler");