blob: 5c44b11856c434e034e118a06f471bbaf03387f8 [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>
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +020028#include <linux/hrtimer.h>
Tatyana Brokhman16349062012-09-20 10:46:10 +030029
30/*
31 * enum row_queue_prio - Priorities of the ROW queues
32 *
33 * This enum defines the priorities (and the number of queues)
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +020034 * the requests will be distributed to. The higher priority -
35 * the bigger is the "bus time" (or the dispatch quantum) given
36 * to that queue.
Tatyana Brokhman16349062012-09-20 10:46:10 +030037 * ROWQ_PRIO_HIGH_READ - is the higher priority queue.
38 *
39 */
40enum row_queue_prio {
41 ROWQ_PRIO_HIGH_READ = 0,
Tatyana Brokhman16349062012-09-20 10:46:10 +030042 ROWQ_PRIO_HIGH_SWRITE,
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +020043 ROWQ_PRIO_REG_READ,
Tatyana Brokhman16349062012-09-20 10:46:10 +030044 ROWQ_PRIO_REG_SWRITE,
45 ROWQ_PRIO_REG_WRITE,
46 ROWQ_PRIO_LOW_READ,
47 ROWQ_PRIO_LOW_SWRITE,
48 ROWQ_MAX_PRIO,
49};
50
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +020051/*
52 * The following indexes define the distribution of ROW queues according to
53 * priorities. Each index defines the first queue in that priority group.
54 */
55#define ROWQ_HIGH_PRIO_IDX ROWQ_PRIO_HIGH_READ
56#define ROWQ_REG_PRIO_IDX ROWQ_PRIO_REG_READ
57#define ROWQ_LOW_PRIO_IDX ROWQ_PRIO_LOW_READ
58
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020059/**
60 * struct row_queue_params - ROW queue parameters
61 * @idling_enabled: Flag indicating whether idling is enable on
62 * the queue
63 * @quantum: Number of requests to be dispatched from this queue
64 * in a dispatch cycle
65 * @is_urgent: Flags indicating whether the queue can notify on
66 * urgent requests
67 *
68 */
69struct row_queue_params {
70 bool idling_enabled;
71 int quantum;
72 bool is_urgent;
Tatyana Brokhman16349062012-09-20 10:46:10 +030073};
74
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020075/*
76 * This array holds the default values of the different configurables
77 * for each ROW queue. Each row of the array holds the following values:
78 * {idling_enabled, quantum, is_urgent}
79 * Each row corresponds to a queue with the same index (according to
80 * enum row_queue_prio)
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +020081 * Note: The quantums are valid inside their priority type. For example:
82 * For every 10 high priority read requests, 1 high priority sync
83 * write will be dispatched.
84 * For every 100 regular read requests 1 regular write request will
85 * be dispatched.
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020086 */
87static const struct row_queue_params row_queues_def[] = {
88/* idling_enabled, quantum, is_urgent */
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +020089 {true, 10, true}, /* ROWQ_PRIO_HIGH_READ */
90 {false, 1, true}, /* ROWQ_PRIO_HIGH_SWRITE */
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020091 {true, 100, true}, /* ROWQ_PRIO_REG_READ */
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +020092 {false, 1, false}, /* ROWQ_PRIO_REG_SWRITE */
93 {false, 1, false}, /* ROWQ_PRIO_REG_WRITE */
94 {false, 1, false}, /* ROWQ_PRIO_LOW_READ */
95 {false, 1, false} /* ROWQ_PRIO_LOW_SWRITE */
Tatyana Brokhman16349062012-09-20 10:46:10 +030096};
97
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +020098/* Default values for idling on read queues (in msec) */
99#define ROW_IDLE_TIME_MSEC 5
100#define ROW_READ_FREQ_MSEC 20
Tatyana Brokhman16349062012-09-20 10:46:10 +0300101
102/**
103 * struct rowq_idling_data - parameters for idling on the queue
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200104 * @last_insert_time: time the last request was inserted
105 * to the queue
Tatyana Brokhman16349062012-09-20 10:46:10 +0300106 * @begin_idling: flag indicating wether we should idle
107 *
108 */
109struct rowq_idling_data {
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200110 ktime_t last_insert_time;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300111 bool begin_idling;
112};
113
114/**
115 * struct row_queue - requests grouping structure
116 * @rdata: parent row_data structure
117 * @fifo: fifo of requests
118 * @prio: queue priority (enum row_queue_prio)
119 * @nr_dispatched: number of requests already dispatched in
120 * the current dispatch cycle
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200121 * @nr_req: number of requests in queue
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200122 * @dispatch quantum: number of requests this queue may
123 * dispatch in a dispatch cycle
Tatyana Brokhman16349062012-09-20 10:46:10 +0300124 * @idle_data: data for idling on queues
125 *
126 */
127struct row_queue {
128 struct row_data *rdata;
129 struct list_head fifo;
130 enum row_queue_prio prio;
131
132 unsigned int nr_dispatched;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300133
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200134 unsigned int nr_req;
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200135 int disp_quantum;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200136
Tatyana Brokhman16349062012-09-20 10:46:10 +0300137 /* used only for READ queues */
138 struct rowq_idling_data idle_data;
139};
140
141/**
142 * struct idling_data - data for idling on empty rqueue
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200143 * @idle_time_ms: idling duration (msec)
144 * @freq_ms: min time between two requests that
Tatyana Brokhman16349062012-09-20 10:46:10 +0300145 * triger idling (msec)
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200146 * @hr_timer: idling timer
147 * @idle_work: the work to be scheduled when idling timer expires
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200148 * @idling_queue_idx: index of the queues we're idling on
Tatyana Brokhman16349062012-09-20 10:46:10 +0300149 *
150 */
151struct idling_data {
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200152 s64 idle_time_ms;
153 s64 freq_ms;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300154
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200155 struct hrtimer hr_timer;
156 struct work_struct idle_work;
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200157 enum row_queue_prio idling_queue_idx;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300158};
159
160/**
161 * struct row_queue - Per block device rqueue structure
162 * @dispatch_queue: dispatch rqueue
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200163 * @row_queues: array of priority request queues
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200164 * @rd_idle_data: data for idling after READ request
Tatyana Brokhman16349062012-09-20 10:46:10 +0300165 * @nr_reqs: nr_reqs[0] holds the number of all READ requests in
166 * scheduler, nr_reqs[1] holds the number of all WRITE
167 * requests in scheduler
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200168 * @nr_urgent_in_flight: number of uncompleted urgent requests
169 * (both reads and writes)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300170 * @cycle_flags: used for marking unserved queueus
171 *
172 */
173struct row_data {
174 struct request_queue *dispatch_queue;
175
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200176 struct row_queue row_queues[ROWQ_MAX_PRIO];
Tatyana Brokhman16349062012-09-20 10:46:10 +0300177
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200178 struct idling_data rd_idle_data;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300179 unsigned int nr_reqs[2];
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200180 unsigned int nr_urgent_in_flight;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300181
182 unsigned int cycle_flags;
183};
184
185#define RQ_ROWQ(rq) ((struct row_queue *) ((rq)->elv.priv[0]))
186
187#define row_log(q, fmt, args...) \
188 blk_add_trace_msg(q, "%s():" fmt , __func__, ##args)
189#define row_log_rowq(rdata, rowq_id, fmt, args...) \
190 blk_add_trace_msg(rdata->dispatch_queue, "rowq%d " fmt, \
191 rowq_id, ##args)
192
193static inline void row_mark_rowq_unserved(struct row_data *rd,
194 enum row_queue_prio qnum)
195{
196 rd->cycle_flags |= (1 << qnum);
197}
198
199static inline void row_clear_rowq_unserved(struct row_data *rd,
200 enum row_queue_prio qnum)
201{
202 rd->cycle_flags &= ~(1 << qnum);
203}
204
205static inline int row_rowq_unserved(struct row_data *rd,
206 enum row_queue_prio qnum)
207{
208 return rd->cycle_flags & (1 << qnum);
209}
210
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200211static inline void __maybe_unused row_dump_queues_stat(struct row_data *rd)
212{
213 int i;
214
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200215 row_log(rd->dispatch_queue, " Queues status:");
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200216 for (i = 0; i < ROWQ_MAX_PRIO; i++)
217 row_log(rd->dispatch_queue,
218 "queue%d: dispatched= %d, nr_req=%d", i,
219 rd->row_queues[i].nr_dispatched,
220 rd->row_queues[i].nr_req);
221}
222
Tatyana Brokhman16349062012-09-20 10:46:10 +0300223/******************** Static helper functions ***********************/
Tatyana Brokhman16349062012-09-20 10:46:10 +0300224static void kick_queue(struct work_struct *work)
225{
Tatyana Brokhman16349062012-09-20 10:46:10 +0300226 struct idling_data *read_data =
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200227 container_of(work, struct idling_data, idle_work);
228 struct row_data *rd =
229 container_of(read_data, struct row_data, rd_idle_data);
230
231 blk_run_queue(rd->dispatch_queue);
232}
233
234
235static enum hrtimer_restart row_idle_hrtimer_fn(struct hrtimer *hr_timer)
236{
237 struct idling_data *read_data =
238 container_of(hr_timer, struct idling_data, hr_timer);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300239 struct row_data *rd =
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200240 container_of(read_data, struct row_data, rd_idle_data);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300241
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200242 row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx,
243 "Performing delayed work");
Tatyana Brokhman16349062012-09-20 10:46:10 +0300244 /* Mark idling process as done */
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200245 rd->row_queues[rd->rd_idle_data.idling_queue_idx].
246 idle_data.begin_idling = false;
247 rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300248
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200249 if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE])
Tatyana Brokhman16349062012-09-20 10:46:10 +0300250 row_log(rd->dispatch_queue, "No requests in scheduler");
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200251 else
252 kblockd_schedule_work(rd->dispatch_queue,
253 &read_data->idle_work);
254 return HRTIMER_NORESTART;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300255}
256
Tatyana Brokhman16349062012-09-20 10:46:10 +0300257/******************* Elevator callback functions *********************/
258
259/*
260 * row_add_request() - Add request to the scheduler
261 * @q: requests queue
262 * @rq: request to add
263 *
264 */
265static void row_add_request(struct request_queue *q,
266 struct request *rq)
267{
268 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
269 struct row_queue *rqueue = RQ_ROWQ(rq);
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200270 s64 diff_ms;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300271
272 list_add_tail(&rq->queuelist, &rqueue->fifo);
273 rd->nr_reqs[rq_data_dir(rq)]++;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200274 rqueue->nr_req++;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300275 rq_set_fifo_time(rq, jiffies); /* for statistics*/
276
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200277 if (row_queues_def[rqueue->prio].idling_enabled) {
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200278 if (rd->rd_idle_data.idling_queue_idx == rqueue->prio &&
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200279 hrtimer_active(&rd->rd_idle_data.hr_timer)) {
280 (void)hrtimer_cancel(&rd->rd_idle_data.hr_timer);
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200281 row_log_rowq(rd, rqueue->prio,
282 "Canceled delayed work on %d",
283 rd->rd_idle_data.idling_queue_idx);
284 rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
285 }
286 diff_ms = ktime_to_ms(ktime_sub(ktime_get(),
287 rqueue->idle_data.last_insert_time));
288 if (unlikely(diff_ms < 0)) {
289 pr_err("ROW BUG: %s diff_ms < 0", __func__);
290 rqueue->idle_data.begin_idling = false;
291 return;
292 }
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200293 if (diff_ms < rd->rd_idle_data.freq_ms) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300294 rqueue->idle_data.begin_idling = true;
295 row_log_rowq(rd, rqueue->prio, "Enable idling");
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200296 } else {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300297 rqueue->idle_data.begin_idling = false;
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200298 row_log_rowq(rd, rqueue->prio, "Disable idling (%ldms)",
299 (long)diff_ms);
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200300 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300301
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200302 rqueue->idle_data.last_insert_time = ktime_get();
Tatyana Brokhman16349062012-09-20 10:46:10 +0300303 }
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200304 if (row_queues_def[rqueue->prio].is_urgent &&
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200305 row_rowq_unserved(rd, rqueue->prio)) {
306 row_log_rowq(rd, rqueue->prio,
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200307 "added urgent request (total on queue=%d)",
308 rqueue->nr_req);
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200309 rq->cmd_flags |= REQ_URGENT;
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200310 } else
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200311 row_log_rowq(rd, rqueue->prio,
312 "added request (total on queue=%d)", rqueue->nr_req);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300313}
314
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200315/**
316 * row_reinsert_req() - Reinsert request back to the scheduler
317 * @q: requests queue
318 * @rq: request to add
319 *
320 * Reinsert the given request back to the queue it was
321 * dispatched from as if it was never dispatched.
322 *
323 * Returns 0 on success, error code otherwise
324 */
325static int row_reinsert_req(struct request_queue *q,
326 struct request *rq)
327{
328 struct row_data *rd = q->elevator->elevator_data;
329 struct row_queue *rqueue = RQ_ROWQ(rq);
330
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200331 if (rqueue->prio >= ROWQ_MAX_PRIO) {
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200332 pr_err("\n\n%s:ROW BUG: row_reinsert_req() rqueue->prio = %d\n",
333 rq->rq_disk->disk_name, rqueue->prio);
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200334 blk_dump_rq_flags(rq, "");
335 return -EIO;
336 }
337
338 list_add(&rq->queuelist, &rqueue->fifo);
339 rd->nr_reqs[rq_data_dir(rq)]++;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200340 rqueue->nr_req++;
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200341
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200342 row_log_rowq(rd, rqueue->prio,
343 "request reinserted (total on queue=%d)", rqueue->nr_req);
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200344
345 return 0;
346}
347
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200348static void row_completed_req(struct request_queue *q, struct request *rq)
349{
350 struct row_data *rd = q->elevator->elevator_data;
351
352 if (rq->cmd_flags & REQ_URGENT) {
353 if (!rd->nr_urgent_in_flight) {
354 pr_err("ROW BUG: %s() nr_urgent_in_flight = 0",
355 __func__);
356 return;
357 }
358 rd->nr_urgent_in_flight--;
359 }
360}
361
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200362/**
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200363 * row_urgent_pending() - Return TRUE if there is an urgent
364 * request on scheduler
365 * @q: requests queue
366 */
367static bool row_urgent_pending(struct request_queue *q)
368{
369 struct row_data *rd = q->elevator->elevator_data;
370 int i;
371
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200372 if (rd->nr_urgent_in_flight) {
373 row_log(rd->dispatch_queue, "%d urgent requests in flight",
374 rd->nr_urgent_in_flight);
375 return false;
376 }
377
378 for (i = ROWQ_HIGH_PRIO_IDX; i < ROWQ_REG_PRIO_IDX; i++)
379 if (!list_empty(&rd->row_queues[i].fifo)) {
380 row_log_rowq(rd, i,
381 "Urgent (high prio) request pending");
382 return true;
383 }
384
385 for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200386 if (row_queues_def[i].is_urgent && row_rowq_unserved(rd, i) &&
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200387 !list_empty(&rd->row_queues[i].fifo)) {
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200388 row_log_rowq(rd, i, "Urgent request pending");
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200389 return true;
390 }
391
392 return false;
393}
394
395/**
Tatyana Brokhman16349062012-09-20 10:46:10 +0300396 * row_remove_request() - Remove given request from scheduler
397 * @q: requests queue
398 * @rq: request to remove
399 *
400 */
401static void row_remove_request(struct request_queue *q,
402 struct request *rq)
403{
404 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200405 struct row_queue *rqueue = RQ_ROWQ(rq);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300406
407 rq_fifo_clear(rq);
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200408 rqueue->nr_req--;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300409 rd->nr_reqs[rq_data_dir(rq)]--;
410}
411
412/*
413 * row_dispatch_insert() - move request to dispatch queue
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200414 * @rd: pointer to struct row_data
415 * @queue_idx: index of the row_queue to dispatch from
Tatyana Brokhman16349062012-09-20 10:46:10 +0300416 *
417 * This function moves the next request to dispatch from
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200418 * the given queue (row_queues[queue_idx]) to the dispatch queue
Tatyana Brokhman16349062012-09-20 10:46:10 +0300419 *
420 */
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200421static void row_dispatch_insert(struct row_data *rd, int queue_idx)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300422{
423 struct request *rq;
424
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200425 rq = rq_entry_fifo(rd->row_queues[queue_idx].fifo.next);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300426 row_remove_request(rd->dispatch_queue, rq);
427 elv_dispatch_add_tail(rd->dispatch_queue, rq);
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200428 rd->row_queues[queue_idx].nr_dispatched++;
429 row_clear_rowq_unserved(rd, queue_idx);
430 row_log_rowq(rd, queue_idx, " Dispatched request nr_disp = %d",
431 rd->row_queues[queue_idx].nr_dispatched);
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200432 if (rq->cmd_flags & REQ_URGENT)
433 rd->nr_urgent_in_flight++;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300434}
435
436/*
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200437 * row_get_ioprio_class_to_serve() - Return the next I/O priority
438 * class to dispatch requests from
Tatyana Brokhman16349062012-09-20 10:46:10 +0300439 * @rd: pointer to struct row_data
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200440 * @force: flag indicating if forced dispatch
Tatyana Brokhman16349062012-09-20 10:46:10 +0300441 *
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200442 * This function returns the next I/O priority class to serve
443 * {IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE}.
444 * If there are no more requests in scheduler or if we're idling on some queue
445 * IOPRIO_CLASS_NONE will be returned.
446 * If idling is scheduled on a lower priority queue than the one that needs
447 * to be served, it will be canceled.
Tatyana Brokhman16349062012-09-20 10:46:10 +0300448 *
449 */
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200450static int row_get_ioprio_class_to_serve(struct row_data *rd, int force)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300451{
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200452 int i;
453 int ret = IOPRIO_CLASS_NONE;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300454
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200455 if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) {
Tatyana Brokhman16349062012-09-20 10:46:10 +0300456 row_log(rd->dispatch_queue, "No more requests in scheduler");
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200457 goto check_idling;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300458 }
459
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200460 /* First, go over the high priority queues */
461 for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) {
462 if (!list_empty(&rd->row_queues[i].fifo)) {
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200463 if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
464 (void)hrtimer_cancel(
465 &rd->rd_idle_data.hr_timer);
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200466 row_log_rowq(rd,
467 rd->rd_idle_data.idling_queue_idx,
468 "Canceling delayed work on %d. RT pending",
469 rd->rd_idle_data.idling_queue_idx);
470 rd->rd_idle_data.idling_queue_idx =
471 ROWQ_MAX_PRIO;
472 }
473 ret = IOPRIO_CLASS_RT;
474 goto done;
475 }
476 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300477
478 /*
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200479 * At the moment idling is implemented only for READ queues.
480 * If enabled on WRITE, this needs updating
Tatyana Brokhman16349062012-09-20 10:46:10 +0300481 */
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200482 if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200483 row_log(rd->dispatch_queue, "Delayed work pending. Exiting");
484 goto done;
485 }
486check_idling:
487 /* Check for (high priority) idling and enable if needed */
488 for (i = 0; i < ROWQ_REG_PRIO_IDX && !force; i++) {
489 if (rd->row_queues[i].idle_data.begin_idling &&
490 row_queues_def[i].idling_enabled)
491 goto initiate_idling;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300492 }
493
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200494 /* Regular priority queues */
495 for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) {
496 if (list_empty(&rd->row_queues[i].fifo)) {
497 /* We can idle only if this is not a forced dispatch */
498 if (rd->row_queues[i].idle_data.begin_idling &&
499 !force && row_queues_def[i].idling_enabled)
500 goto initiate_idling;
501 } else {
502 ret = IOPRIO_CLASS_BE;
503 goto done;
504 }
505 }
506
507 if (rd->nr_reqs[READ] || rd->nr_reqs[WRITE])
508 ret = IOPRIO_CLASS_IDLE;
509 goto done;
510
511initiate_idling:
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200512 hrtimer_start(&rd->rd_idle_data.hr_timer,
513 ktime_set(0, rd->rd_idle_data.idle_time_ms * NSEC_PER_MSEC),
514 HRTIMER_MODE_REL);
515
516 rd->rd_idle_data.idling_queue_idx = i;
517 row_log_rowq(rd, i, "Scheduled delayed work on %d. exiting", i);
518
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200519done:
520 return ret;
521}
522
523static void row_restart_cycle(struct row_data *rd,
524 int start_idx, int end_idx)
525{
526 int i;
527
528 row_dump_queues_stat(rd);
529 for (i = start_idx; i < end_idx; i++) {
530 if (rd->row_queues[i].nr_dispatched <
531 rd->row_queues[i].disp_quantum)
532 row_mark_rowq_unserved(rd, i);
533 rd->row_queues[i].nr_dispatched = 0;
534 }
535 row_log(rd->dispatch_queue, "Restarting cycle for class @ %d-%d",
536 start_idx, end_idx);
537}
538
539/*
540 * row_get_next_queue() - selects the next queue to dispatch from
541 * @q: requests queue
542 * @rd: pointer to struct row_data
543 * @start_idx/end_idx: indexes in the row_queues array to select a queue
544 * from.
545 *
546 * Return index of the queues to dispatch from. Error code if fails.
547 *
548 */
549static int row_get_next_queue(struct request_queue *q, struct row_data *rd,
550 int start_idx, int end_idx)
551{
552 int i = start_idx;
553 bool restart = true;
554 int ret = -EIO;
555
556 do {
557 if (list_empty(&rd->row_queues[i].fifo) ||
558 rd->row_queues[i].nr_dispatched >=
559 rd->row_queues[i].disp_quantum) {
560 i++;
561 if (i == end_idx && restart) {
562 /* Restart cycle for this priority class */
563 row_restart_cycle(rd, start_idx, end_idx);
564 i = start_idx;
565 restart = false;
566 }
567 } else {
568 ret = i;
569 break;
570 }
571 } while (i < end_idx);
572
573 return ret;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300574}
575
576/*
577 * row_dispatch_requests() - selects the next request to dispatch
578 * @q: requests queue
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200579 * @force: flag indicating if forced dispatch
Tatyana Brokhman16349062012-09-20 10:46:10 +0300580 *
581 * Return 0 if no requests were moved to the dispatch queue.
582 * 1 otherwise
583 *
584 */
585static int row_dispatch_requests(struct request_queue *q, int force)
586{
587 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200588 int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300589
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200590 if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) {
591 (void)hrtimer_cancel(&rd->rd_idle_data.hr_timer);
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200592 row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx,
593 "Canceled delayed work on %d - forced dispatch",
594 rd->rd_idle_data.idling_queue_idx);
595 rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300596 }
597
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200598 ioprio_class_to_serve = row_get_ioprio_class_to_serve(rd, force);
599 row_log(rd->dispatch_queue, "Dispatching from %d priority class",
600 ioprio_class_to_serve);
601
602 switch (ioprio_class_to_serve) {
603 case IOPRIO_CLASS_NONE:
604 goto done;
605 case IOPRIO_CLASS_RT:
606 start_idx = ROWQ_HIGH_PRIO_IDX;
607 end_idx = ROWQ_REG_PRIO_IDX;
608 break;
609 case IOPRIO_CLASS_BE:
610 start_idx = ROWQ_REG_PRIO_IDX;
611 end_idx = ROWQ_LOW_PRIO_IDX;
612 break;
613 case IOPRIO_CLASS_IDLE:
614 start_idx = ROWQ_LOW_PRIO_IDX;
615 end_idx = ROWQ_MAX_PRIO;
616 break;
617 default:
618 pr_err("%s(): Invalid I/O priority class", __func__);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300619 goto done;
620 }
621
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200622 currq = row_get_next_queue(q, rd, start_idx, end_idx);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300623
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200624 /* Dispatch */
625 if (currq >= 0) {
626 row_dispatch_insert(rd, currq);
627 ret = 1;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300628 }
Tatyana Brokhman16349062012-09-20 10:46:10 +0300629done:
630 return ret;
631}
632
633/*
634 * row_init_queue() - Init scheduler data structures
635 * @q: requests queue
636 *
637 * Return pointer to struct row_data to be saved in elevator for
638 * this dispatch queue
639 *
640 */
641static void *row_init_queue(struct request_queue *q)
642{
643
644 struct row_data *rdata;
645 int i;
646
647 rdata = kmalloc_node(sizeof(*rdata),
648 GFP_KERNEL | __GFP_ZERO, q->node);
649 if (!rdata)
650 return NULL;
651
652 for (i = 0; i < ROWQ_MAX_PRIO; i++) {
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200653 INIT_LIST_HEAD(&rdata->row_queues[i].fifo);
Tatyana Brokhman9375bcc2013-01-12 16:23:18 +0200654 rdata->row_queues[i].disp_quantum = row_queues_def[i].quantum;
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200655 rdata->row_queues[i].rdata = rdata;
656 rdata->row_queues[i].prio = i;
657 rdata->row_queues[i].idle_data.begin_idling = false;
658 rdata->row_queues[i].idle_data.last_insert_time =
Tatyana Brokhmanbfb04f62012-12-06 13:17:19 +0200659 ktime_set(0, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300660 }
661
662 /*
663 * Currently idling is enabled only for READ queues. If we want to
664 * enable it for write queues also, note that idling frequency will
665 * be the same in both cases
666 */
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200667 rdata->rd_idle_data.idle_time_ms = ROW_IDLE_TIME_MSEC;
668 rdata->rd_idle_data.freq_ms = ROW_READ_FREQ_MSEC;
669 hrtimer_init(&rdata->rd_idle_data.hr_timer,
670 CLOCK_MONOTONIC, HRTIMER_MODE_REL);
671 rdata->rd_idle_data.hr_timer.function = &row_idle_hrtimer_fn;
672
673 INIT_WORK(&rdata->rd_idle_data.idle_work, kick_queue);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300674
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200675 rdata->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300676 rdata->dispatch_queue = q;
677
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200678 rdata->nr_urgent_in_flight = 0;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300679 rdata->nr_reqs[READ] = rdata->nr_reqs[WRITE] = 0;
680
681 return rdata;
682}
683
684/*
685 * row_exit_queue() - called on unloading the RAW scheduler
686 * @e: poiner to struct elevator_queue
687 *
688 */
689static void row_exit_queue(struct elevator_queue *e)
690{
691 struct row_data *rd = (struct row_data *)e->elevator_data;
692 int i;
693
694 for (i = 0; i < ROWQ_MAX_PRIO; i++)
Tatyana Brokhman8a970bc2013-01-12 16:21:12 +0200695 BUG_ON(!list_empty(&rd->row_queues[i].fifo));
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200696 if (hrtimer_cancel(&rd->rd_idle_data.hr_timer))
697 pr_err("ROW BUG: idle timer was active!");
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200698 rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300699 kfree(rd);
700}
701
702/*
703 * row_merged_requests() - Called when 2 requests are merged
704 * @q: requests queue
705 * @rq: request the two requests were merged into
706 * @next: request that was merged
707 */
708static void row_merged_requests(struct request_queue *q, struct request *rq,
709 struct request *next)
710{
711 struct row_queue *rqueue = RQ_ROWQ(next);
712
713 list_del_init(&next->queuelist);
Tatyana Brokhmanbd56be32013-01-13 22:04:59 +0200714 rqueue->nr_req--;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300715
716 rqueue->rdata->nr_reqs[rq_data_dir(rq)]--;
717}
718
719/*
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200720 * row_get_queue_prio() - Get queue priority for a given request
Tatyana Brokhman16349062012-09-20 10:46:10 +0300721 *
722 * This is a helping function which purpose is to determine what
723 * ROW queue the given request should be added to (and
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200724 * dispatched from later on)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300725 *
Tatyana Brokhman16349062012-09-20 10:46:10 +0300726 */
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200727static enum row_queue_prio row_get_queue_prio(struct request *rq)
Tatyana Brokhman16349062012-09-20 10:46:10 +0300728{
729 const int data_dir = rq_data_dir(rq);
730 const bool is_sync = rq_is_sync(rq);
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200731 enum row_queue_prio q_type = ROWQ_MAX_PRIO;
732 int ioprio_class = IOPRIO_PRIO_CLASS(rq->elv.icq->ioc->ioprio);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300733
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200734 switch (ioprio_class) {
735 case IOPRIO_CLASS_RT:
736 if (data_dir == READ)
737 q_type = ROWQ_PRIO_HIGH_READ;
738 else if (is_sync)
739 q_type = ROWQ_PRIO_HIGH_SWRITE;
740 else {
741 pr_err("%s:%s(): got a simple write from RT_CLASS. How???",
742 rq->rq_disk->disk_name, __func__);
743 q_type = ROWQ_PRIO_REG_WRITE;
744 }
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200745 rq->cmd_flags |= REQ_URGENT;
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200746 break;
747 case IOPRIO_CLASS_IDLE:
748 if (data_dir == READ)
749 q_type = ROWQ_PRIO_LOW_READ;
750 else if (is_sync)
751 q_type = ROWQ_PRIO_LOW_SWRITE;
752 else {
753 pr_err("%s:%s(): got a simple write from IDLE_CLASS. How???",
754 rq->rq_disk->disk_name, __func__);
755 q_type = ROWQ_PRIO_REG_WRITE;
756 }
757 break;
758 case IOPRIO_CLASS_NONE:
759 case IOPRIO_CLASS_BE:
760 default:
761 if (data_dir == READ)
762 q_type = ROWQ_PRIO_REG_READ;
763 else if (is_sync)
764 q_type = ROWQ_PRIO_REG_SWRITE;
765 else
766 q_type = ROWQ_PRIO_REG_WRITE;
767 break;
768 }
769
770 return q_type;
Tatyana Brokhman16349062012-09-20 10:46:10 +0300771}
772
773/*
774 * row_set_request() - Set ROW data structures associated with this request.
775 * @q: requests queue
776 * @rq: pointer to the request
777 * @gfp_mask: ignored
778 *
779 */
780static int
781row_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
782{
783 struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
784 unsigned long flags;
785
786 spin_lock_irqsave(q->queue_lock, flags);
787 rq->elv.priv[0] =
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200788 (void *)(&rd->row_queues[row_get_queue_prio(rq)]);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300789 spin_unlock_irqrestore(q->queue_lock, flags);
790
791 return 0;
792}
793
794/********** Helping sysfs functions/defenitions for ROW attributes ******/
795static ssize_t row_var_show(int var, char *page)
796{
797 return snprintf(page, 100, "%d\n", var);
798}
799
800static ssize_t row_var_store(int *var, const char *page, size_t count)
801{
802 int err;
803 err = kstrtoul(page, 10, (unsigned long *)var);
804
805 return count;
806}
807
808#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
809static ssize_t __FUNC(struct elevator_queue *e, char *page) \
810{ \
811 struct row_data *rowd = e->elevator_data; \
812 int __data = __VAR; \
813 if (__CONV) \
814 __data = jiffies_to_msecs(__data); \
815 return row_var_show(__data, (page)); \
816}
817SHOW_FUNCTION(row_hp_read_quantum_show,
818 rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 0);
819SHOW_FUNCTION(row_rp_read_quantum_show,
820 rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, 0);
821SHOW_FUNCTION(row_hp_swrite_quantum_show,
822 rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, 0);
823SHOW_FUNCTION(row_rp_swrite_quantum_show,
824 rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, 0);
825SHOW_FUNCTION(row_rp_write_quantum_show,
826 rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, 0);
827SHOW_FUNCTION(row_lp_read_quantum_show,
828 rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, 0);
829SHOW_FUNCTION(row_lp_swrite_quantum_show,
830 rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200831SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms, 0);
832SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300833#undef SHOW_FUNCTION
834
835#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
836static ssize_t __FUNC(struct elevator_queue *e, \
837 const char *page, size_t count) \
838{ \
839 struct row_data *rowd = e->elevator_data; \
840 int __data; \
841 int ret = row_var_store(&__data, (page), count); \
842 if (__CONV) \
843 __data = (int)msecs_to_jiffies(__data); \
844 if (__data < (MIN)) \
845 __data = (MIN); \
846 else if (__data > (MAX)) \
847 __data = (MAX); \
848 *(__PTR) = __data; \
849 return ret; \
850}
851STORE_FUNCTION(row_hp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200852&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300853STORE_FUNCTION(row_rp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200854 &rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum,
855 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300856STORE_FUNCTION(row_hp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200857 &rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum,
858 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300859STORE_FUNCTION(row_rp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200860 &rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum,
861 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300862STORE_FUNCTION(row_rp_write_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200863 &rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum,
864 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300865STORE_FUNCTION(row_lp_read_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200866 &rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum,
867 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300868STORE_FUNCTION(row_lp_swrite_quantum_store,
Tatyana Brokhman0a0345a2012-10-15 20:50:54 +0200869 &rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200870 1, INT_MAX, 0);
Tatyana Brokhmance1a8ed2013-01-17 20:56:07 +0200871STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms,
872 1, INT_MAX, 0);
873STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms,
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200874 1, INT_MAX, 0);
Tatyana Brokhman16349062012-09-20 10:46:10 +0300875
876#undef STORE_FUNCTION
877
878#define ROW_ATTR(name) \
879 __ATTR(name, S_IRUGO|S_IWUSR, row_##name##_show, \
880 row_##name##_store)
881
882static struct elv_fs_entry row_attrs[] = {
883 ROW_ATTR(hp_read_quantum),
884 ROW_ATTR(rp_read_quantum),
885 ROW_ATTR(hp_swrite_quantum),
886 ROW_ATTR(rp_swrite_quantum),
887 ROW_ATTR(rp_write_quantum),
888 ROW_ATTR(lp_read_quantum),
889 ROW_ATTR(lp_swrite_quantum),
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200890 ROW_ATTR(rd_idle_data),
891 ROW_ATTR(rd_idle_data_freq),
Tatyana Brokhman16349062012-09-20 10:46:10 +0300892 __ATTR_NULL
893};
894
895static struct elevator_type iosched_row = {
896 .ops = {
897 .elevator_merge_req_fn = row_merged_requests,
898 .elevator_dispatch_fn = row_dispatch_requests,
899 .elevator_add_req_fn = row_add_request,
Tatyana Brokhmanb7bf9ac2012-10-30 08:33:06 +0200900 .elevator_reinsert_req_fn = row_reinsert_req,
Tatyana Brokhman0ef81432012-12-20 19:23:58 +0200901 .elevator_is_urgent_fn = row_urgent_pending,
Tatyana Brokhman4c3c3cc2013-01-24 15:08:40 +0200902 .elevator_completed_req_fn = row_completed_req,
Tatyana Brokhman16349062012-09-20 10:46:10 +0300903 .elevator_former_req_fn = elv_rb_former_request,
904 .elevator_latter_req_fn = elv_rb_latter_request,
905 .elevator_set_req_fn = row_set_request,
906 .elevator_init_fn = row_init_queue,
907 .elevator_exit_fn = row_exit_queue,
908 },
Tatyana Brokhmandb7c1532013-01-23 17:15:49 +0200909 .icq_size = sizeof(struct io_cq),
910 .icq_align = __alignof__(struct io_cq),
Tatyana Brokhman16349062012-09-20 10:46:10 +0300911 .elevator_attrs = row_attrs,
912 .elevator_name = "row",
913 .elevator_owner = THIS_MODULE,
914};
915
916static int __init row_init(void)
917{
918 elv_register(&iosched_row);
919 return 0;
920}
921
922static void __exit row_exit(void)
923{
924 elv_unregister(&iosched_row);
925}
926
927module_init(row_init);
928module_exit(row_exit);
929
930MODULE_LICENSE("GPLv2");
931MODULE_DESCRIPTION("Read Over Write IO scheduler");