blob: b8c16e7055635e5d290c84f2afcae2eded652da9 [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
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020050/**
51 * struct row_queue_params - ROW queue parameters
52 * @idling_enabled: Flag indicating whether idling is enable on
53 * the queue
54 * @quantum: Number of requests to be dispatched from this queue
55 * in a dispatch cycle
56 * @is_urgent: Flags indicating whether the queue can notify on
57 * urgent requests
58 *
59 */
60struct row_queue_params {
61 bool idling_enabled;
62 int quantum;
63 bool is_urgent;
Tatyana Brokhman16349062012-09-20 10:46:10 +030064};
65
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020066/*
67 * This array holds the default values of the different configurables
68 * for each ROW queue. Each row of the array holds the following values:
69 * {idling_enabled, quantum, is_urgent}
70 * Each row corresponds to a queue with the same index (according to
71 * enum row_queue_prio)
72 */
73static const struct row_queue_params row_queues_def[] = {
74/* idling_enabled, quantum, is_urgent */
75 {true, 100, true}, /* ROWQ_PRIO_HIGH_READ */
76 {true, 100, true}, /* ROWQ_PRIO_REG_READ */
77 {false, 2, false}, /* ROWQ_PRIO_HIGH_SWRITE */
78 {false, 1, false}, /* ROWQ_PRIO_REG_SWRITE */
79 {false, 1, false}, /* ROWQ_PRIO_REG_WRITE */
80 {false, 1, false}, /* ROWQ_PRIO_LOW_READ */
81 {false, 1, false} /* ROWQ_PRIO_LOW_SWRITE */
Tatyana Brokhman16349062012-09-20 10:46:10 +030082};
83
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020084/* Default values for idling on read queues (in msec) */
85#define ROW_IDLE_TIME_MSEC 5
86#define ROW_READ_FREQ_MSEC 20
Tatyana Brokhman16349062012-09-20 10:46:10 +030087
88/**
89 * struct rowq_idling_data - parameters for idling on the queue
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020090 * @last_insert_time: time the last request was inserted
91 * to the queue
Tatyana Brokhman16349062012-09-20 10:46:10 +030092 * @begin_idling: flag indicating wether we should idle
93 *
94 */
95struct rowq_idling_data {
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020096 ktime_t last_insert_time;
Tatyana Brokhman16349062012-09-20 10:46:10 +030097 bool begin_idling;
98};
99
100/**
101 * struct row_queue - requests grouping structure
102 * @rdata: parent row_data structure
103 * @fifo: fifo of requests
104 * @prio: queue priority (enum row_queue_prio)
105 * @nr_dispatched: number of requests already dispatched in
106 * the current dispatch cycle
107 * @slice: number of requests to dispatch in a cycle
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200108 * @nr_req: number of requests in queue
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200109 * @dispatch quantum: number of requests this queue may
110 * dispatch in a dispatch cycle
Tatyana Brokhman16349062012-09-20 10:46:10 +0300111 * @idle_data: data for idling on queues
112 *
113 */
114struct row_queue {
115 struct row_data *rdata;
116 struct list_head fifo;
117 enum row_queue_prio prio;
118
119 unsigned int nr_dispatched;
120 unsigned int slice;
121
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200122 unsigned int nr_req;
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200123 int disp_quantum;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200124
Tatyana Brokhman16349062012-09-20 10:46:10 +0300125 /* used only for READ queues */
126 struct rowq_idling_data idle_data;
127};
128
129/**
130 * struct idling_data - data for idling on empty rqueue
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200131 * @idle_time: idling duration (jiffies)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300132 * @freq: min time between two requests that
133 * triger idling (msec)
134 * @idle_work: pointer to struct delayed_work
135 *
136 */
137struct idling_data {
138 unsigned long idle_time;
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200139 u32 freq;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300140
141 struct workqueue_struct *idle_workqueue;
142 struct delayed_work idle_work;
143};
144
145/**
146 * struct row_queue - Per block device rqueue structure
147 * @dispatch_queue: dispatch rqueue
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200148 * @row_queues: array of priority request queues
Tatyana Brokhman16349062012-09-20 10:46:10 +0300149 * @curr_queue: index in the row_queues array of the
150 * currently serviced rqueue
151 * @read_idle: data for idling after READ request
152 * @nr_reqs: nr_reqs[0] holds the number of all READ requests in
153 * scheduler, nr_reqs[1] holds the number of all WRITE
154 * requests in scheduler
155 * @cycle_flags: used for marking unserved queueus
156 *
157 */
158struct row_data {
159 struct request_queue *dispatch_queue;
160
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200161 struct row_queue row_queues[ROWQ_MAX_PRIO];
Tatyana Brokhman16349062012-09-20 10:46:10 +0300162
163 enum row_queue_prio curr_queue;
164
165 struct idling_data read_idle;
166 unsigned int nr_reqs[2];
167
168 unsigned int cycle_flags;
169};
170
171#define RQ_ROWQ(rq) ((struct row_queue *) ((rq)->elv.priv[0]))
172
173#define row_log(q, fmt, args...) \
174 blk_add_trace_msg(q, "%s():" fmt , __func__, ##args)
175#define row_log_rowq(rdata, rowq_id, fmt, args...) \
176 blk_add_trace_msg(rdata->dispatch_queue, "rowq%d " fmt, \
177 rowq_id, ##args)
178
179static inline void row_mark_rowq_unserved(struct row_data *rd,
180 enum row_queue_prio qnum)
181{
182 rd->cycle_flags |= (1 << qnum);
183}
184
185static inline void row_clear_rowq_unserved(struct row_data *rd,
186 enum row_queue_prio qnum)
187{
188 rd->cycle_flags &= ~(1 << qnum);
189}
190
191static inline int row_rowq_unserved(struct row_data *rd,
192 enum row_queue_prio qnum)
193{
194 return rd->cycle_flags & (1 << qnum);
195}
196
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200197static inline void __maybe_unused row_dump_queues_stat(struct row_data *rd)
198{
199 int i;
200
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200201 row_log(rd->dispatch_queue, " Queues status:");
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200202 for (i = 0; i < ROWQ_MAX_PRIO; i++)
203 row_log(rd->dispatch_queue,
204 "queue%d: dispatched= %d, nr_req=%d", i,
205 rd->row_queues[i].nr_dispatched,
206 rd->row_queues[i].nr_req);
207}
208
Tatyana Brokhman16349062012-09-20 10:46:10 +0300209/******************** Static helper functions ***********************/
210/*
211 * kick_queue() - Wake up device driver queue thread
212 * @work: pointer to struct work_struct
213 *
214 * This is a idling delayed work function. It's purpose is to wake up the
215 * device driver in order for it to start fetching requests.
216 *
217 */
218static void kick_queue(struct work_struct *work)
219{
220 struct delayed_work *idle_work = to_delayed_work(work);
221 struct idling_data *read_data =
222 container_of(idle_work, struct idling_data, idle_work);
223 struct row_data *rd =
224 container_of(read_data, struct row_data, read_idle);
225
226 row_log_rowq(rd, rd->curr_queue, "Performing delayed work");
227 /* Mark idling process as done */
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200228 rd->row_queues[rd->curr_queue].idle_data.begin_idling = false;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300229
230 if (!(rd->nr_reqs[0] + rd->nr_reqs[1]))
231 row_log(rd->dispatch_queue, "No requests in scheduler");
232 else {
233 spin_lock_irq(rd->dispatch_queue->queue_lock);
234 __blk_run_queue(rd->dispatch_queue);
235 spin_unlock_irq(rd->dispatch_queue->queue_lock);
236 }
237}
238
239/*
240 * row_restart_disp_cycle() - Restart the dispatch cycle
241 * @rd: pointer to struct row_data
242 *
243 * This function restarts the dispatch cycle by:
244 * - Setting current queue to ROWQ_PRIO_HIGH_READ
245 * - For each queue: reset the number of requests dispatched in
246 * the cycle
247 */
248static inline void row_restart_disp_cycle(struct row_data *rd)
249{
250 int i;
251
252 for (i = 0; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200253 rd->row_queues[i].nr_dispatched = 0;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300254
255 rd->curr_queue = ROWQ_PRIO_HIGH_READ;
256 row_log(rd->dispatch_queue, "Restarting cycle");
257}
258
259static inline void row_get_next_queue(struct row_data *rd)
260{
261 rd->curr_queue++;
262 if (rd->curr_queue == ROWQ_MAX_PRIO)
263 row_restart_disp_cycle(rd);
264}
265
266/******************* Elevator callback functions *********************/
267
268/*
269 * row_add_request() - Add request to the scheduler
270 * @q: requests queue
271 * @rq: request to add
272 *
273 */
274static void row_add_request(struct request_queue *q,
275 struct request *rq)
276{
277 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
278 struct row_queue *rqueue = RQ_ROWQ(rq);
279
280 list_add_tail(&rq->queuelist, &rqueue->fifo);
281 rd->nr_reqs[rq_data_dir(rq)]++;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200282 rqueue->nr_req++;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300283 rq_set_fifo_time(rq, jiffies); /* for statistics*/
284
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200285 if (row_queues_def[rqueue->prio].idling_enabled) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300286 if (delayed_work_pending(&rd->read_idle.idle_work))
287 (void)cancel_delayed_work(
288 &rd->read_idle.idle_work);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200289 if (ktime_to_ms(ktime_sub(ktime_get(),
290 rqueue->idle_data.last_insert_time)) <
291 rd->read_idle.freq) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300292 rqueue->idle_data.begin_idling = true;
293 row_log_rowq(rd, rqueue->prio, "Enable idling");
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200294 } else {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300295 rqueue->idle_data.begin_idling = false;
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200296 row_log_rowq(rd, rqueue->prio, "Disable idling");
297 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300298
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200299 rqueue->idle_data.last_insert_time = ktime_get();
Tatyana Brokhman16349062012-09-20 10:46:10 +0300300 }
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200301 if (row_queues_def[rqueue->prio].is_urgent &&
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200302 row_rowq_unserved(rd, rqueue->prio)) {
303 row_log_rowq(rd, rqueue->prio,
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200304 "added urgent request (total on queue=%d)",
305 rqueue->nr_req);
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200306 } else
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200307 row_log_rowq(rd, rqueue->prio,
308 "added request (total on queue=%d)", rqueue->nr_req);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300309}
310
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200311/**
312 * row_reinsert_req() - Reinsert request back to the scheduler
313 * @q: requests queue
314 * @rq: request to add
315 *
316 * Reinsert the given request back to the queue it was
317 * dispatched from as if it was never dispatched.
318 *
319 * Returns 0 on success, error code otherwise
320 */
321static int row_reinsert_req(struct request_queue *q,
322 struct request *rq)
323{
324 struct row_data *rd = q->elevator->elevator_data;
325 struct row_queue *rqueue = RQ_ROWQ(rq);
326
327 /* Verify rqueue is legitimate */
328 if (rqueue->prio >= ROWQ_MAX_PRIO) {
329 pr_err("\n\nROW BUG: row_reinsert_req() rqueue->prio = %d\n",
330 rqueue->prio);
331 blk_dump_rq_flags(rq, "");
332 return -EIO;
333 }
334
335 list_add(&rq->queuelist, &rqueue->fifo);
336 rd->nr_reqs[rq_data_dir(rq)]++;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200337 rqueue->nr_req++;
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200338
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200339 row_log_rowq(rd, rqueue->prio,
340 "request reinserted (total on queue=%d)", rqueue->nr_req);
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200341
342 return 0;
343}
344
345/**
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200346 * row_urgent_pending() - Return TRUE if there is an urgent
347 * request on scheduler
348 * @q: requests queue
349 */
350static bool row_urgent_pending(struct request_queue *q)
351{
352 struct row_data *rd = q->elevator->elevator_data;
353 int i;
354
355 for (i = 0; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200356 if (row_queues_def[i].is_urgent && row_rowq_unserved(rd, i) &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200357 !list_empty(&rd->row_queues[i].fifo)) {
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200358 row_log_rowq(rd, i,
359 "Urgent request pending (curr=%i)",
360 rd->curr_queue);
361 return true;
362 }
363
364 return false;
365}
366
367/**
Tatyana Brokhman16349062012-09-20 10:46:10 +0300368 * row_remove_request() - Remove given request from scheduler
369 * @q: requests queue
370 * @rq: request to remove
371 *
372 */
373static void row_remove_request(struct request_queue *q,
374 struct request *rq)
375{
376 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200377 struct row_queue *rqueue = RQ_ROWQ(rq);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300378
379 rq_fifo_clear(rq);
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200380 rqueue->nr_req--;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300381 rd->nr_reqs[rq_data_dir(rq)]--;
382}
383
384/*
385 * row_dispatch_insert() - move request to dispatch queue
386 * @rd: pointer to struct row_data
387 *
388 * This function moves the next request to dispatch from
389 * rd->curr_queue to the dispatch queue
390 *
391 */
392static void row_dispatch_insert(struct row_data *rd)
393{
394 struct request *rq;
395
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200396 rq = rq_entry_fifo(rd->row_queues[rd->curr_queue].fifo.next);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300397 row_remove_request(rd->dispatch_queue, rq);
398 elv_dispatch_add_tail(rd->dispatch_queue, rq);
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200399 rd->row_queues[rd->curr_queue].nr_dispatched++;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300400 row_clear_rowq_unserved(rd, rd->curr_queue);
401 row_log_rowq(rd, rd->curr_queue, " Dispatched request nr_disp = %d",
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200402 rd->row_queues[rd->curr_queue].nr_dispatched);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300403}
404
405/*
406 * row_choose_queue() - choose the next queue to dispatch from
407 * @rd: pointer to struct row_data
408 *
409 * Updates rd->curr_queue. Returns 1 if there are requests to
410 * dispatch, 0 if there are no requests in scheduler
411 *
412 */
413static int row_choose_queue(struct row_data *rd)
414{
415 int prev_curr_queue = rd->curr_queue;
416
417 if (!(rd->nr_reqs[0] + rd->nr_reqs[1])) {
418 row_log(rd->dispatch_queue, "No more requests in scheduler");
419 return 0;
420 }
421
422 row_get_next_queue(rd);
423
424 /*
425 * Loop over all queues to find the next queue that is not empty.
426 * Stop when you get back to curr_queue
427 */
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200428 while (list_empty(&rd->row_queues[rd->curr_queue].fifo)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300429 && rd->curr_queue != prev_curr_queue) {
430 /* Mark rqueue as unserved */
431 row_mark_rowq_unserved(rd, rd->curr_queue);
432 row_get_next_queue(rd);
433 }
434
435 return 1;
436}
437
438/*
439 * row_dispatch_requests() - selects the next request to dispatch
440 * @q: requests queue
441 * @force: ignored
442 *
443 * Return 0 if no requests were moved to the dispatch queue.
444 * 1 otherwise
445 *
446 */
447static int row_dispatch_requests(struct request_queue *q, int force)
448{
449 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
450 int ret = 0, currq, i;
451
452 currq = rd->curr_queue;
453
454 /*
455 * Find the first unserved queue (with higher priority then currq)
456 * that is not empty
457 */
458 for (i = 0; i < currq; i++) {
459 if (row_rowq_unserved(rd, i) &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200460 !list_empty(&rd->row_queues[i].fifo)) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300461 row_log_rowq(rd, currq,
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200462 " Preemting for unserved rowq%d. (nr_req=%u)",
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200463 i, rd->row_queues[currq].nr_req);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300464 rd->curr_queue = i;
465 row_dispatch_insert(rd);
466 ret = 1;
467 goto done;
468 }
469 }
470
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200471 if (rd->row_queues[currq].nr_dispatched >=
Tatyana Brokhman16349062012-09-20 10:46:10 +0300472 rd->row_queues[currq].disp_quantum) {
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200473 rd->row_queues[currq].nr_dispatched = 0;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300474 row_log_rowq(rd, currq, "Expiring rqueue");
475 ret = row_choose_queue(rd);
476 if (ret)
477 row_dispatch_insert(rd);
478 goto done;
479 }
480
481 /* Dispatch from curr_queue */
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200482 if (list_empty(&rd->row_queues[currq].fifo)) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300483 /* check idling */
484 if (delayed_work_pending(&rd->read_idle.idle_work)) {
Tatyana Brokhman25f39882012-10-15 20:56:02 +0200485 if (force) {
486 (void)cancel_delayed_work(
487 &rd->read_idle.idle_work);
488 row_log_rowq(rd, currq,
489 "Canceled delayed work - forced dispatch");
490 } else {
491 row_log_rowq(rd, currq,
492 "Delayed work pending. Exiting");
493 goto done;
494 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300495 }
496
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200497 if (!force && row_queues_def[currq].idling_enabled &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200498 rd->row_queues[currq].idle_data.begin_idling) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300499 if (!queue_delayed_work(rd->read_idle.idle_workqueue,
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200500 &rd->read_idle.idle_work,
501 rd->read_idle.idle_time)) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300502 row_log_rowq(rd, currq,
503 "Work already on queue!");
504 pr_err("ROW_BUG: Work already on queue!");
505 } else
506 row_log_rowq(rd, currq,
507 "Scheduled delayed work. exiting");
508 goto done;
509 } else {
510 row_log_rowq(rd, currq,
511 "Currq empty. Choose next queue");
512 ret = row_choose_queue(rd);
513 if (!ret)
514 goto done;
515 }
516 }
517
518 ret = 1;
519 row_dispatch_insert(rd);
520
521done:
522 return ret;
523}
524
525/*
526 * row_init_queue() - Init scheduler data structures
527 * @q: requests queue
528 *
529 * Return pointer to struct row_data to be saved in elevator for
530 * this dispatch queue
531 *
532 */
533static void *row_init_queue(struct request_queue *q)
534{
535
536 struct row_data *rdata;
537 int i;
538
539 rdata = kmalloc_node(sizeof(*rdata),
540 GFP_KERNEL | __GFP_ZERO, q->node);
541 if (!rdata)
542 return NULL;
543
544 for (i = 0; i < ROWQ_MAX_PRIO; i++) {
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200545 INIT_LIST_HEAD(&rdata->row_queues[i].fifo);
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200546 rdata->row_queues[i].disp_quantum = row_queues_def[i].quantum;
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200547 rdata->row_queues[i].rdata = rdata;
548 rdata->row_queues[i].prio = i;
549 rdata->row_queues[i].idle_data.begin_idling = false;
550 rdata->row_queues[i].idle_data.last_insert_time =
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200551 ktime_set(0, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300552 }
553
554 /*
555 * Currently idling is enabled only for READ queues. If we want to
556 * enable it for write queues also, note that idling frequency will
557 * be the same in both cases
558 */
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200559 rdata->read_idle.idle_time = msecs_to_jiffies(ROW_IDLE_TIME_MSEC);
560 /* Maybe 0 on some platforms */
561 if (!rdata->read_idle.idle_time)
562 rdata->read_idle.idle_time = 1;
563 rdata->read_idle.freq = ROW_READ_FREQ_MSEC;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300564 rdata->read_idle.idle_workqueue = alloc_workqueue("row_idle_work",
565 WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
566 if (!rdata->read_idle.idle_workqueue)
567 panic("Failed to create idle workqueue\n");
568 INIT_DELAYED_WORK(&rdata->read_idle.idle_work, kick_queue);
569
570 rdata->curr_queue = ROWQ_PRIO_HIGH_READ;
571 rdata->dispatch_queue = q;
572
573 rdata->nr_reqs[READ] = rdata->nr_reqs[WRITE] = 0;
574
575 return rdata;
576}
577
578/*
579 * row_exit_queue() - called on unloading the RAW scheduler
580 * @e: poiner to struct elevator_queue
581 *
582 */
583static void row_exit_queue(struct elevator_queue *e)
584{
585 struct row_data *rd = (struct row_data *)e->elevator_data;
586 int i;
587
588 for (i = 0; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200589 BUG_ON(!list_empty(&rd->row_queues[i].fifo));
Tatyana Brokhman16349062012-09-20 10:46:10 +0300590 (void)cancel_delayed_work_sync(&rd->read_idle.idle_work);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200591 BUG_ON(delayed_work_pending(&rd->read_idle.idle_work));
592 destroy_workqueue(rd->read_idle.idle_workqueue);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300593 kfree(rd);
594}
595
596/*
597 * row_merged_requests() - Called when 2 requests are merged
598 * @q: requests queue
599 * @rq: request the two requests were merged into
600 * @next: request that was merged
601 */
602static void row_merged_requests(struct request_queue *q, struct request *rq,
603 struct request *next)
604{
605 struct row_queue *rqueue = RQ_ROWQ(next);
606
607 list_del_init(&next->queuelist);
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200608 rqueue->nr_req--;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300609
610 rqueue->rdata->nr_reqs[rq_data_dir(rq)]--;
611}
612
613/*
614 * get_queue_type() - Get queue type for a given request
615 *
616 * This is a helping function which purpose is to determine what
617 * ROW queue the given request should be added to (and
618 * dispatched from leter on)
619 *
620 * TODO: Right now only 3 queues are used REG_READ, REG_WRITE
621 * and REG_SWRITE
622 */
623static enum row_queue_prio get_queue_type(struct request *rq)
624{
625 const int data_dir = rq_data_dir(rq);
626 const bool is_sync = rq_is_sync(rq);
627
628 if (data_dir == READ)
629 return ROWQ_PRIO_REG_READ;
630 else if (is_sync)
631 return ROWQ_PRIO_REG_SWRITE;
632 else
633 return ROWQ_PRIO_REG_WRITE;
634}
635
636/*
637 * row_set_request() - Set ROW data structures associated with this request.
638 * @q: requests queue
639 * @rq: pointer to the request
640 * @gfp_mask: ignored
641 *
642 */
643static int
644row_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
645{
646 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
647 unsigned long flags;
648
649 spin_lock_irqsave(q->queue_lock, flags);
650 rq->elv.priv[0] =
651 (void *)(&rd->row_queues[get_queue_type(rq)]);
652 spin_unlock_irqrestore(q->queue_lock, flags);
653
654 return 0;
655}
656
657/********** Helping sysfs functions/defenitions for ROW attributes ******/
658static ssize_t row_var_show(int var, char *page)
659{
660 return snprintf(page, 100, "%d\n", var);
661}
662
663static ssize_t row_var_store(int *var, const char *page, size_t count)
664{
665 int err;
666 err = kstrtoul(page, 10, (unsigned long *)var);
667
668 return count;
669}
670
671#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
672static ssize_t __FUNC(struct elevator_queue *e, char *page) \
673{ \
674 struct row_data *rowd = e->elevator_data; \
675 int __data = __VAR; \
676 if (__CONV) \
677 __data = jiffies_to_msecs(__data); \
678 return row_var_show(__data, (page)); \
679}
680SHOW_FUNCTION(row_hp_read_quantum_show,
681 rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 0);
682SHOW_FUNCTION(row_rp_read_quantum_show,
683 rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, 0);
684SHOW_FUNCTION(row_hp_swrite_quantum_show,
685 rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, 0);
686SHOW_FUNCTION(row_rp_swrite_quantum_show,
687 rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, 0);
688SHOW_FUNCTION(row_rp_write_quantum_show,
689 rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, 0);
690SHOW_FUNCTION(row_lp_read_quantum_show,
691 rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, 0);
692SHOW_FUNCTION(row_lp_swrite_quantum_show,
693 rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
Tatyana Brokhman9ca05c02013-01-12 16:21:47 +0200694SHOW_FUNCTION(row_read_idle_show, rowd->read_idle.idle_time, 0);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200695SHOW_FUNCTION(row_read_idle_freq_show, rowd->read_idle.freq, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300696#undef SHOW_FUNCTION
697
698#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
699static ssize_t __FUNC(struct elevator_queue *e, \
700 const char *page, size_t count) \
701{ \
702 struct row_data *rowd = e->elevator_data; \
703 int __data; \
704 int ret = row_var_store(&__data, (page), count); \
705 if (__CONV) \
706 __data = (int)msecs_to_jiffies(__data); \
707 if (__data < (MIN)) \
708 __data = (MIN); \
709 else if (__data > (MAX)) \
710 __data = (MAX); \
711 *(__PTR) = __data; \
712 return ret; \
713}
714STORE_FUNCTION(row_hp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200715&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300716STORE_FUNCTION(row_rp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200717 &rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum,
718 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300719STORE_FUNCTION(row_hp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200720 &rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum,
721 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300722STORE_FUNCTION(row_rp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200723 &rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum,
724 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300725STORE_FUNCTION(row_rp_write_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200726 &rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum,
727 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300728STORE_FUNCTION(row_lp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200729 &rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum,
730 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300731STORE_FUNCTION(row_lp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200732 &rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
733 1, INT_MAX, 1);
Tatyana Brokhman9ca05c02013-01-12 16:21:47 +0200734STORE_FUNCTION(row_read_idle_store, &rowd->read_idle.idle_time, 1, INT_MAX, 0);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200735STORE_FUNCTION(row_read_idle_freq_store, &rowd->read_idle.freq, 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300736
737#undef STORE_FUNCTION
738
739#define ROW_ATTR(name) \
740 __ATTR(name, S_IRUGO|S_IWUSR, row_##name##_show, \
741 row_##name##_store)
742
743static struct elv_fs_entry row_attrs[] = {
744 ROW_ATTR(hp_read_quantum),
745 ROW_ATTR(rp_read_quantum),
746 ROW_ATTR(hp_swrite_quantum),
747 ROW_ATTR(rp_swrite_quantum),
748 ROW_ATTR(rp_write_quantum),
749 ROW_ATTR(lp_read_quantum),
750 ROW_ATTR(lp_swrite_quantum),
751 ROW_ATTR(read_idle),
752 ROW_ATTR(read_idle_freq),
753 __ATTR_NULL
754};
755
756static struct elevator_type iosched_row = {
757 .ops = {
758 .elevator_merge_req_fn = row_merged_requests,
759 .elevator_dispatch_fn = row_dispatch_requests,
760 .elevator_add_req_fn = row_add_request,
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200761 .elevator_reinsert_req_fn = row_reinsert_req,
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200762 .elevator_is_urgent_fn = row_urgent_pending,
Tatyana Brokhman16349062012-09-20 10:46:10 +0300763 .elevator_former_req_fn = elv_rb_former_request,
764 .elevator_latter_req_fn = elv_rb_latter_request,
765 .elevator_set_req_fn = row_set_request,
766 .elevator_init_fn = row_init_queue,
767 .elevator_exit_fn = row_exit_queue,
768 },
769
770 .elevator_attrs = row_attrs,
771 .elevator_name = "row",
772 .elevator_owner = THIS_MODULE,
773};
774
775static int __init row_init(void)
776{
777 elv_register(&iosched_row);
778 return 0;
779}
780
781static void __exit row_exit(void)
782{
783 elv_unregister(&iosched_row);
784}
785
786module_init(row_init);
787module_exit(row_exit);
788
789MODULE_LICENSE("GPLv2");
790MODULE_DESCRIPTION("Read Over Write IO scheduler");