blob: bf9ad05e90c62fd32aef15d4112dc23f6a1e233f [file] [log] [blame]
Tatyana Brokhman16349062012-09-20 10:46:10 +03001/*
2 * ROW (Read Over Write) I/O scheduler.
3 *
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +02004 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Tatyana Brokhman16349062012-09-20 10:46:10 +03005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and
8 * only version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16/* See Documentation/block/row-iosched.txt */
17
18#include <linux/kernel.h>
19#include <linux/fs.h>
20#include <linux/blkdev.h>
21#include <linux/elevator.h>
22#include <linux/bio.h>
23#include <linux/module.h>
24#include <linux/slab.h>
25#include <linux/init.h>
26#include <linux/compiler.h>
27#include <linux/blktrace_api.h>
28#include <linux/jiffies.h>
29
30/*
31 * enum row_queue_prio - Priorities of the ROW queues
32 *
33 * This enum defines the priorities (and the number of queues)
34 * the requests will be disptributed to. The higher priority -
35 * the bigger is the dispatch quantum given to that queue.
36 * ROWQ_PRIO_HIGH_READ - is the higher priority queue.
37 *
38 */
39enum row_queue_prio {
40 ROWQ_PRIO_HIGH_READ = 0,
41 ROWQ_PRIO_REG_READ,
42 ROWQ_PRIO_HIGH_SWRITE,
43 ROWQ_PRIO_REG_SWRITE,
44 ROWQ_PRIO_REG_WRITE,
45 ROWQ_PRIO_LOW_READ,
46 ROWQ_PRIO_LOW_SWRITE,
47 ROWQ_MAX_PRIO,
48};
49
50/* Flags indicating whether idling is enabled on the queue */
51static const bool queue_idling_enabled[] = {
52 true, /* ROWQ_PRIO_HIGH_READ */
53 true, /* ROWQ_PRIO_REG_READ */
54 false, /* ROWQ_PRIO_HIGH_SWRITE */
55 false, /* ROWQ_PRIO_REG_SWRITE */
56 false, /* ROWQ_PRIO_REG_WRITE */
57 false, /* ROWQ_PRIO_LOW_READ */
58 false, /* ROWQ_PRIO_LOW_SWRITE */
59};
60
Tatyana Brokhman0ef81432012-12-20 19:23:58 +020061/* Flags indicating whether the queue can notify on urgent requests */
62static const bool urgent_queues[] = {
63 true, /* ROWQ_PRIO_HIGH_READ */
64 true, /* ROWQ_PRIO_REG_READ */
65 false, /* ROWQ_PRIO_HIGH_SWRITE */
66 false, /* ROWQ_PRIO_REG_SWRITE */
67 false, /* ROWQ_PRIO_REG_WRITE */
68 false, /* ROWQ_PRIO_LOW_READ */
69 false, /* ROWQ_PRIO_LOW_SWRITE */
70};
71
Tatyana Brokhman16349062012-09-20 10:46:10 +030072/* Default values for row queues quantums in each dispatch cycle */
73static const int queue_quantum[] = {
74 100, /* ROWQ_PRIO_HIGH_READ */
75 100, /* ROWQ_PRIO_REG_READ */
76 2, /* ROWQ_PRIO_HIGH_SWRITE */
77 1, /* ROWQ_PRIO_REG_SWRITE */
78 1, /* ROWQ_PRIO_REG_WRITE */
79 1, /* ROWQ_PRIO_LOW_READ */
80 1 /* ROWQ_PRIO_LOW_SWRITE */
81};
82
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020083/* Default values for idling on read queues (in msec) */
84#define ROW_IDLE_TIME_MSEC 5
85#define ROW_READ_FREQ_MSEC 20
Tatyana Brokhman16349062012-09-20 10:46:10 +030086
87/**
88 * struct rowq_idling_data - parameters for idling on the queue
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020089 * @last_insert_time: time the last request was inserted
90 * to the queue
Tatyana Brokhman16349062012-09-20 10:46:10 +030091 * @begin_idling: flag indicating wether we should idle
92 *
93 */
94struct rowq_idling_data {
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020095 ktime_t last_insert_time;
Tatyana Brokhman16349062012-09-20 10:46:10 +030096 bool begin_idling;
97};
98
99/**
100 * struct row_queue - requests grouping structure
101 * @rdata: parent row_data structure
102 * @fifo: fifo of requests
103 * @prio: queue priority (enum row_queue_prio)
104 * @nr_dispatched: number of requests already dispatched in
105 * the current dispatch cycle
106 * @slice: number of requests to dispatch in a cycle
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200107 * @nr_req: number of requests in queue
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200108 * @dispatch quantum: number of requests this queue may
109 * dispatch in a dispatch cycle
Tatyana Brokhman16349062012-09-20 10:46:10 +0300110 * @idle_data: data for idling on queues
111 *
112 */
113struct row_queue {
114 struct row_data *rdata;
115 struct list_head fifo;
116 enum row_queue_prio prio;
117
118 unsigned int nr_dispatched;
119 unsigned int slice;
120
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200121 unsigned int nr_req;
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200122 int disp_quantum;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200123
Tatyana Brokhman16349062012-09-20 10:46:10 +0300124 /* used only for READ queues */
125 struct rowq_idling_data idle_data;
126};
127
128/**
129 * struct idling_data - data for idling on empty rqueue
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200130 * @idle_time: idling duration (jiffies)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300131 * @freq: min time between two requests that
132 * triger idling (msec)
133 * @idle_work: pointer to struct delayed_work
134 *
135 */
136struct idling_data {
137 unsigned long idle_time;
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200138 u32 freq;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300139
140 struct workqueue_struct *idle_workqueue;
141 struct delayed_work idle_work;
142};
143
144/**
145 * struct row_queue - Per block device rqueue structure
146 * @dispatch_queue: dispatch rqueue
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200147 * @row_queues: array of priority request queues
Tatyana Brokhman16349062012-09-20 10:46:10 +0300148 * @curr_queue: index in the row_queues array of the
149 * currently serviced rqueue
150 * @read_idle: data for idling after READ request
151 * @nr_reqs: nr_reqs[0] holds the number of all READ requests in
152 * scheduler, nr_reqs[1] holds the number of all WRITE
153 * requests in scheduler
154 * @cycle_flags: used for marking unserved queueus
155 *
156 */
157struct row_data {
158 struct request_queue *dispatch_queue;
159
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200160 struct row_queue row_queues[ROWQ_MAX_PRIO];
Tatyana Brokhman16349062012-09-20 10:46:10 +0300161
162 enum row_queue_prio curr_queue;
163
164 struct idling_data read_idle;
165 unsigned int nr_reqs[2];
166
167 unsigned int cycle_flags;
168};
169
170#define RQ_ROWQ(rq) ((struct row_queue *) ((rq)->elv.priv[0]))
171
172#define row_log(q, fmt, args...) \
173 blk_add_trace_msg(q, "%s():" fmt , __func__, ##args)
174#define row_log_rowq(rdata, rowq_id, fmt, args...) \
175 blk_add_trace_msg(rdata->dispatch_queue, "rowq%d " fmt, \
176 rowq_id, ##args)
177
178static inline void row_mark_rowq_unserved(struct row_data *rd,
179 enum row_queue_prio qnum)
180{
181 rd->cycle_flags |= (1 << qnum);
182}
183
184static inline void row_clear_rowq_unserved(struct row_data *rd,
185 enum row_queue_prio qnum)
186{
187 rd->cycle_flags &= ~(1 << qnum);
188}
189
190static inline int row_rowq_unserved(struct row_data *rd,
191 enum row_queue_prio qnum)
192{
193 return rd->cycle_flags & (1 << qnum);
194}
195
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200196static inline void __maybe_unused row_dump_queues_stat(struct row_data *rd)
197{
198 int i;
199
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200200 row_log(rd->dispatch_queue, " Queues status:");
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200201 for (i = 0; i < ROWQ_MAX_PRIO; i++)
202 row_log(rd->dispatch_queue,
203 "queue%d: dispatched= %d, nr_req=%d", i,
204 rd->row_queues[i].nr_dispatched,
205 rd->row_queues[i].nr_req);
206}
207
Tatyana Brokhman16349062012-09-20 10:46:10 +0300208/******************** Static helper functions ***********************/
209/*
210 * kick_queue() - Wake up device driver queue thread
211 * @work: pointer to struct work_struct
212 *
213 * This is a idling delayed work function. It's purpose is to wake up the
214 * device driver in order for it to start fetching requests.
215 *
216 */
217static void kick_queue(struct work_struct *work)
218{
219 struct delayed_work *idle_work = to_delayed_work(work);
220 struct idling_data *read_data =
221 container_of(idle_work, struct idling_data, idle_work);
222 struct row_data *rd =
223 container_of(read_data, struct row_data, read_idle);
224
225 row_log_rowq(rd, rd->curr_queue, "Performing delayed work");
226 /* Mark idling process as done */
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200227 rd->row_queues[rd->curr_queue].idle_data.begin_idling = false;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300228
229 if (!(rd->nr_reqs[0] + rd->nr_reqs[1]))
230 row_log(rd->dispatch_queue, "No requests in scheduler");
231 else {
232 spin_lock_irq(rd->dispatch_queue->queue_lock);
233 __blk_run_queue(rd->dispatch_queue);
234 spin_unlock_irq(rd->dispatch_queue->queue_lock);
235 }
236}
237
238/*
239 * row_restart_disp_cycle() - Restart the dispatch cycle
240 * @rd: pointer to struct row_data
241 *
242 * This function restarts the dispatch cycle by:
243 * - Setting current queue to ROWQ_PRIO_HIGH_READ
244 * - For each queue: reset the number of requests dispatched in
245 * the cycle
246 */
247static inline void row_restart_disp_cycle(struct row_data *rd)
248{
249 int i;
250
251 for (i = 0; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200252 rd->row_queues[i].nr_dispatched = 0;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300253
254 rd->curr_queue = ROWQ_PRIO_HIGH_READ;
255 row_log(rd->dispatch_queue, "Restarting cycle");
256}
257
258static inline void row_get_next_queue(struct row_data *rd)
259{
260 rd->curr_queue++;
261 if (rd->curr_queue == ROWQ_MAX_PRIO)
262 row_restart_disp_cycle(rd);
263}
264
265/******************* Elevator callback functions *********************/
266
267/*
268 * row_add_request() - Add request to the scheduler
269 * @q: requests queue
270 * @rq: request to add
271 *
272 */
273static void row_add_request(struct request_queue *q,
274 struct request *rq)
275{
276 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
277 struct row_queue *rqueue = RQ_ROWQ(rq);
278
279 list_add_tail(&rq->queuelist, &rqueue->fifo);
280 rd->nr_reqs[rq_data_dir(rq)]++;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200281 rqueue->nr_req++;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300282 rq_set_fifo_time(rq, jiffies); /* for statistics*/
283
284 if (queue_idling_enabled[rqueue->prio]) {
285 if (delayed_work_pending(&rd->read_idle.idle_work))
286 (void)cancel_delayed_work(
287 &rd->read_idle.idle_work);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200288 if (ktime_to_ms(ktime_sub(ktime_get(),
289 rqueue->idle_data.last_insert_time)) <
290 rd->read_idle.freq) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300291 rqueue->idle_data.begin_idling = true;
292 row_log_rowq(rd, rqueue->prio, "Enable idling");
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200293 } else {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300294 rqueue->idle_data.begin_idling = false;
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200295 row_log_rowq(rd, rqueue->prio, "Disable idling");
296 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300297
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200298 rqueue->idle_data.last_insert_time = ktime_get();
Tatyana Brokhman16349062012-09-20 10:46:10 +0300299 }
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200300 if (urgent_queues[rqueue->prio] &&
301 row_rowq_unserved(rd, rqueue->prio)) {
302 row_log_rowq(rd, rqueue->prio,
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200303 "added urgent request (total on queue=%d)",
304 rqueue->nr_req);
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200305 } else
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200306 row_log_rowq(rd, rqueue->prio,
307 "added request (total on queue=%d)", rqueue->nr_req);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300308}
309
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200310/**
311 * row_reinsert_req() - Reinsert request back to the scheduler
312 * @q: requests queue
313 * @rq: request to add
314 *
315 * Reinsert the given request back to the queue it was
316 * dispatched from as if it was never dispatched.
317 *
318 * Returns 0 on success, error code otherwise
319 */
320static int row_reinsert_req(struct request_queue *q,
321 struct request *rq)
322{
323 struct row_data *rd = q->elevator->elevator_data;
324 struct row_queue *rqueue = RQ_ROWQ(rq);
325
326 /* Verify rqueue is legitimate */
327 if (rqueue->prio >= ROWQ_MAX_PRIO) {
328 pr_err("\n\nROW BUG: row_reinsert_req() rqueue->prio = %d\n",
329 rqueue->prio);
330 blk_dump_rq_flags(rq, "");
331 return -EIO;
332 }
333
334 list_add(&rq->queuelist, &rqueue->fifo);
335 rd->nr_reqs[rq_data_dir(rq)]++;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200336 rqueue->nr_req++;
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200337
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200338 row_log_rowq(rd, rqueue->prio,
339 "request reinserted (total on queue=%d)", rqueue->nr_req);
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200340
341 return 0;
342}
343
344/**
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200345 * row_urgent_pending() - Return TRUE if there is an urgent
346 * request on scheduler
347 * @q: requests queue
348 */
349static bool row_urgent_pending(struct request_queue *q)
350{
351 struct row_data *rd = q->elevator->elevator_data;
352 int i;
353
354 for (i = 0; i < ROWQ_MAX_PRIO; i++)
355 if (urgent_queues[i] && row_rowq_unserved(rd, i) &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200356 !list_empty(&rd->row_queues[i].fifo)) {
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200357 row_log_rowq(rd, i,
358 "Urgent request pending (curr=%i)",
359 rd->curr_queue);
360 return true;
361 }
362
363 return false;
364}
365
366/**
Tatyana Brokhman16349062012-09-20 10:46:10 +0300367 * row_remove_request() - Remove given request from scheduler
368 * @q: requests queue
369 * @rq: request to remove
370 *
371 */
372static void row_remove_request(struct request_queue *q,
373 struct request *rq)
374{
375 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200376 struct row_queue *rqueue = RQ_ROWQ(rq);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300377
378 rq_fifo_clear(rq);
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200379 rqueue->nr_req--;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300380 rd->nr_reqs[rq_data_dir(rq)]--;
381}
382
383/*
384 * row_dispatch_insert() - move request to dispatch queue
385 * @rd: pointer to struct row_data
386 *
387 * This function moves the next request to dispatch from
388 * rd->curr_queue to the dispatch queue
389 *
390 */
391static void row_dispatch_insert(struct row_data *rd)
392{
393 struct request *rq;
394
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200395 rq = rq_entry_fifo(rd->row_queues[rd->curr_queue].fifo.next);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300396 row_remove_request(rd->dispatch_queue, rq);
397 elv_dispatch_add_tail(rd->dispatch_queue, rq);
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200398 rd->row_queues[rd->curr_queue].nr_dispatched++;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300399 row_clear_rowq_unserved(rd, rd->curr_queue);
400 row_log_rowq(rd, rd->curr_queue, " Dispatched request nr_disp = %d",
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200401 rd->row_queues[rd->curr_queue].nr_dispatched);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300402}
403
404/*
405 * row_choose_queue() - choose the next queue to dispatch from
406 * @rd: pointer to struct row_data
407 *
408 * Updates rd->curr_queue. Returns 1 if there are requests to
409 * dispatch, 0 if there are no requests in scheduler
410 *
411 */
412static int row_choose_queue(struct row_data *rd)
413{
414 int prev_curr_queue = rd->curr_queue;
415
416 if (!(rd->nr_reqs[0] + rd->nr_reqs[1])) {
417 row_log(rd->dispatch_queue, "No more requests in scheduler");
418 return 0;
419 }
420
421 row_get_next_queue(rd);
422
423 /*
424 * Loop over all queues to find the next queue that is not empty.
425 * Stop when you get back to curr_queue
426 */
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200427 while (list_empty(&rd->row_queues[rd->curr_queue].fifo)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300428 && rd->curr_queue != prev_curr_queue) {
429 /* Mark rqueue as unserved */
430 row_mark_rowq_unserved(rd, rd->curr_queue);
431 row_get_next_queue(rd);
432 }
433
434 return 1;
435}
436
437/*
438 * row_dispatch_requests() - selects the next request to dispatch
439 * @q: requests queue
440 * @force: ignored
441 *
442 * Return 0 if no requests were moved to the dispatch queue.
443 * 1 otherwise
444 *
445 */
446static int row_dispatch_requests(struct request_queue *q, int force)
447{
448 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
449 int ret = 0, currq, i;
450
451 currq = rd->curr_queue;
452
453 /*
454 * Find the first unserved queue (with higher priority then currq)
455 * that is not empty
456 */
457 for (i = 0; i < currq; i++) {
458 if (row_rowq_unserved(rd, i) &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200459 !list_empty(&rd->row_queues[i].fifo)) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300460 row_log_rowq(rd, currq,
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200461 " Preemting for unserved rowq%d. (nr_req=%u)",
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200462 i, rd->row_queues[currq].nr_req);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300463 rd->curr_queue = i;
464 row_dispatch_insert(rd);
465 ret = 1;
466 goto done;
467 }
468 }
469
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200470 if (rd->row_queues[currq].nr_dispatched >=
Tatyana Brokhman16349062012-09-20 10:46:10 +0300471 rd->row_queues[currq].disp_quantum) {
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200472 rd->row_queues[currq].nr_dispatched = 0;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300473 row_log_rowq(rd, currq, "Expiring rqueue");
474 ret = row_choose_queue(rd);
475 if (ret)
476 row_dispatch_insert(rd);
477 goto done;
478 }
479
480 /* Dispatch from curr_queue */
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200481 if (list_empty(&rd->row_queues[currq].fifo)) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300482 /* check idling */
483 if (delayed_work_pending(&rd->read_idle.idle_work)) {
Tatyana Brokhman25f39882012-10-15 20:56:02 +0200484 if (force) {
485 (void)cancel_delayed_work(
486 &rd->read_idle.idle_work);
487 row_log_rowq(rd, currq,
488 "Canceled delayed work - forced dispatch");
489 } else {
490 row_log_rowq(rd, currq,
491 "Delayed work pending. Exiting");
492 goto done;
493 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300494 }
495
Tatyana Brokhman25f39882012-10-15 20:56:02 +0200496 if (!force && queue_idling_enabled[currq] &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200497 rd->row_queues[currq].idle_data.begin_idling) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300498 if (!queue_delayed_work(rd->read_idle.idle_workqueue,
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200499 &rd->read_idle.idle_work,
500 rd->read_idle.idle_time)) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300501 row_log_rowq(rd, currq,
502 "Work already on queue!");
503 pr_err("ROW_BUG: Work already on queue!");
504 } else
505 row_log_rowq(rd, currq,
506 "Scheduled delayed work. exiting");
507 goto done;
508 } else {
509 row_log_rowq(rd, currq,
510 "Currq empty. Choose next queue");
511 ret = row_choose_queue(rd);
512 if (!ret)
513 goto done;
514 }
515 }
516
517 ret = 1;
518 row_dispatch_insert(rd);
519
520done:
521 return ret;
522}
523
524/*
525 * row_init_queue() - Init scheduler data structures
526 * @q: requests queue
527 *
528 * Return pointer to struct row_data to be saved in elevator for
529 * this dispatch queue
530 *
531 */
532static void *row_init_queue(struct request_queue *q)
533{
534
535 struct row_data *rdata;
536 int i;
537
538 rdata = kmalloc_node(sizeof(*rdata),
539 GFP_KERNEL | __GFP_ZERO, q->node);
540 if (!rdata)
541 return NULL;
542
543 for (i = 0; i < ROWQ_MAX_PRIO; i++) {
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200544 INIT_LIST_HEAD(&rdata->row_queues[i].fifo);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300545 rdata->row_queues[i].disp_quantum = queue_quantum[i];
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200546 rdata->row_queues[i].rdata = rdata;
547 rdata->row_queues[i].prio = i;
548 rdata->row_queues[i].idle_data.begin_idling = false;
549 rdata->row_queues[i].idle_data.last_insert_time =
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200550 ktime_set(0, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300551 }
552
553 /*
554 * Currently idling is enabled only for READ queues. If we want to
555 * enable it for write queues also, note that idling frequency will
556 * be the same in both cases
557 */
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200558 rdata->read_idle.idle_time = msecs_to_jiffies(ROW_IDLE_TIME_MSEC);
559 /* Maybe 0 on some platforms */
560 if (!rdata->read_idle.idle_time)
561 rdata->read_idle.idle_time = 1;
562 rdata->read_idle.freq = ROW_READ_FREQ_MSEC;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300563 rdata->read_idle.idle_workqueue = alloc_workqueue("row_idle_work",
564 WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
565 if (!rdata->read_idle.idle_workqueue)
566 panic("Failed to create idle workqueue\n");
567 INIT_DELAYED_WORK(&rdata->read_idle.idle_work, kick_queue);
568
569 rdata->curr_queue = ROWQ_PRIO_HIGH_READ;
570 rdata->dispatch_queue = q;
571
572 rdata->nr_reqs[READ] = rdata->nr_reqs[WRITE] = 0;
573
574 return rdata;
575}
576
577/*
578 * row_exit_queue() - called on unloading the RAW scheduler
579 * @e: poiner to struct elevator_queue
580 *
581 */
582static void row_exit_queue(struct elevator_queue *e)
583{
584 struct row_data *rd = (struct row_data *)e->elevator_data;
585 int i;
586
587 for (i = 0; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200588 BUG_ON(!list_empty(&rd->row_queues[i].fifo));
Tatyana Brokhman16349062012-09-20 10:46:10 +0300589 (void)cancel_delayed_work_sync(&rd->read_idle.idle_work);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200590 BUG_ON(delayed_work_pending(&rd->read_idle.idle_work));
591 destroy_workqueue(rd->read_idle.idle_workqueue);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300592 kfree(rd);
593}
594
595/*
596 * row_merged_requests() - Called when 2 requests are merged
597 * @q: requests queue
598 * @rq: request the two requests were merged into
599 * @next: request that was merged
600 */
601static void row_merged_requests(struct request_queue *q, struct request *rq,
602 struct request *next)
603{
604 struct row_queue *rqueue = RQ_ROWQ(next);
605
606 list_del_init(&next->queuelist);
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200607 rqueue->nr_req--;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300608
609 rqueue->rdata->nr_reqs[rq_data_dir(rq)]--;
610}
611
612/*
613 * get_queue_type() - Get queue type for a given request
614 *
615 * This is a helping function which purpose is to determine what
616 * ROW queue the given request should be added to (and
617 * dispatched from leter on)
618 *
619 * TODO: Right now only 3 queues are used REG_READ, REG_WRITE
620 * and REG_SWRITE
621 */
622static enum row_queue_prio get_queue_type(struct request *rq)
623{
624 const int data_dir = rq_data_dir(rq);
625 const bool is_sync = rq_is_sync(rq);
626
627 if (data_dir == READ)
628 return ROWQ_PRIO_REG_READ;
629 else if (is_sync)
630 return ROWQ_PRIO_REG_SWRITE;
631 else
632 return ROWQ_PRIO_REG_WRITE;
633}
634
635/*
636 * row_set_request() - Set ROW data structures associated with this request.
637 * @q: requests queue
638 * @rq: pointer to the request
639 * @gfp_mask: ignored
640 *
641 */
642static int
643row_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
644{
645 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
646 unsigned long flags;
647
648 spin_lock_irqsave(q->queue_lock, flags);
649 rq->elv.priv[0] =
650 (void *)(&rd->row_queues[get_queue_type(rq)]);
651 spin_unlock_irqrestore(q->queue_lock, flags);
652
653 return 0;
654}
655
656/********** Helping sysfs functions/defenitions for ROW attributes ******/
657static ssize_t row_var_show(int var, char *page)
658{
659 return snprintf(page, 100, "%d\n", var);
660}
661
662static ssize_t row_var_store(int *var, const char *page, size_t count)
663{
664 int err;
665 err = kstrtoul(page, 10, (unsigned long *)var);
666
667 return count;
668}
669
670#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
671static ssize_t __FUNC(struct elevator_queue *e, char *page) \
672{ \
673 struct row_data *rowd = e->elevator_data; \
674 int __data = __VAR; \
675 if (__CONV) \
676 __data = jiffies_to_msecs(__data); \
677 return row_var_show(__data, (page)); \
678}
679SHOW_FUNCTION(row_hp_read_quantum_show,
680 rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 0);
681SHOW_FUNCTION(row_rp_read_quantum_show,
682 rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, 0);
683SHOW_FUNCTION(row_hp_swrite_quantum_show,
684 rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, 0);
685SHOW_FUNCTION(row_rp_swrite_quantum_show,
686 rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, 0);
687SHOW_FUNCTION(row_rp_write_quantum_show,
688 rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, 0);
689SHOW_FUNCTION(row_lp_read_quantum_show,
690 rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, 0);
691SHOW_FUNCTION(row_lp_swrite_quantum_show,
692 rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
693SHOW_FUNCTION(row_read_idle_show, rowd->read_idle.idle_time, 1);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200694SHOW_FUNCTION(row_read_idle_freq_show, rowd->read_idle.freq, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300695#undef SHOW_FUNCTION
696
697#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
698static ssize_t __FUNC(struct elevator_queue *e, \
699 const char *page, size_t count) \
700{ \
701 struct row_data *rowd = e->elevator_data; \
702 int __data; \
703 int ret = row_var_store(&__data, (page), count); \
704 if (__CONV) \
705 __data = (int)msecs_to_jiffies(__data); \
706 if (__data < (MIN)) \
707 __data = (MIN); \
708 else if (__data > (MAX)) \
709 __data = (MAX); \
710 *(__PTR) = __data; \
711 return ret; \
712}
713STORE_FUNCTION(row_hp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200714&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300715STORE_FUNCTION(row_rp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200716 &rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum,
717 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300718STORE_FUNCTION(row_hp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200719 &rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum,
720 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300721STORE_FUNCTION(row_rp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200722 &rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum,
723 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300724STORE_FUNCTION(row_rp_write_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200725 &rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum,
726 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300727STORE_FUNCTION(row_lp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200728 &rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum,
729 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300730STORE_FUNCTION(row_lp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200731 &rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
732 1, INT_MAX, 1);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300733STORE_FUNCTION(row_read_idle_store, &rowd->read_idle.idle_time, 1, INT_MAX, 1);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200734STORE_FUNCTION(row_read_idle_freq_store, &rowd->read_idle.freq, 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300735
736#undef STORE_FUNCTION
737
738#define ROW_ATTR(name) \
739 __ATTR(name, S_IRUGO|S_IWUSR, row_##name##_show, \
740 row_##name##_store)
741
742static struct elv_fs_entry row_attrs[] = {
743 ROW_ATTR(hp_read_quantum),
744 ROW_ATTR(rp_read_quantum),
745 ROW_ATTR(hp_swrite_quantum),
746 ROW_ATTR(rp_swrite_quantum),
747 ROW_ATTR(rp_write_quantum),
748 ROW_ATTR(lp_read_quantum),
749 ROW_ATTR(lp_swrite_quantum),
750 ROW_ATTR(read_idle),
751 ROW_ATTR(read_idle_freq),
752 __ATTR_NULL
753};
754
755static struct elevator_type iosched_row = {
756 .ops = {
757 .elevator_merge_req_fn = row_merged_requests,
758 .elevator_dispatch_fn = row_dispatch_requests,
759 .elevator_add_req_fn = row_add_request,
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200760 .elevator_reinsert_req_fn = row_reinsert_req,
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200761 .elevator_is_urgent_fn = row_urgent_pending,
Tatyana Brokhman16349062012-09-20 10:46:10 +0300762 .elevator_former_req_fn = elv_rb_former_request,
763 .elevator_latter_req_fn = elv_rb_latter_request,
764 .elevator_set_req_fn = row_set_request,
765 .elevator_init_fn = row_init_queue,
766 .elevator_exit_fn = row_exit_queue,
767 },
768
769 .elevator_attrs = row_attrs,
770 .elevator_name = "row",
771 .elevator_owner = THIS_MODULE,
772};
773
774static int __init row_init(void)
775{
776 elv_register(&iosched_row);
777 return 0;
778}
779
780static void __exit row_exit(void)
781{
782 elv_unregister(&iosched_row);
783}
784
785module_init(row_init);
786module_exit(row_exit);
787
788MODULE_LICENSE("GPLv2");
789MODULE_DESCRIPTION("Read Over Write IO scheduler");