PageRenderTime 30ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/block/row-iosched.c

https://gitlab.com/LiquidSmooth-Devices/android_kernel_htc_msm8974
C | 860 lines | 725 code | 121 blank | 14 comment | 103 complexity | 7cf944b910f7d7085f7f9c33a9671069 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * ROW (Read Over Write) I/O scheduler.
  3. *
  4. * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  5. *
  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. #include <linux/kernel.h>
  16. #include <linux/fs.h>
  17. #include <linux/blkdev.h>
  18. #include <linux/elevator.h>
  19. #include <linux/bio.h>
  20. #include <linux/module.h>
  21. #include <linux/slab.h>
  22. #include <linux/init.h>
  23. #include <linux/compiler.h>
  24. #include <linux/blktrace_api.h>
  25. #include <linux/hrtimer.h>
  26. enum row_queue_prio {
  27. ROWQ_PRIO_HIGH_READ = 0,
  28. ROWQ_PRIO_HIGH_SWRITE,
  29. ROWQ_PRIO_REG_READ,
  30. ROWQ_PRIO_REG_SWRITE,
  31. ROWQ_PRIO_REG_WRITE,
  32. ROWQ_PRIO_LOW_READ,
  33. ROWQ_PRIO_LOW_SWRITE,
  34. ROWQ_MAX_PRIO,
  35. };
  36. #define ROWQ_HIGH_PRIO_IDX ROWQ_PRIO_HIGH_READ
  37. #define ROWQ_REG_PRIO_IDX ROWQ_PRIO_REG_READ
  38. #define ROWQ_LOW_PRIO_IDX ROWQ_PRIO_LOW_READ
  39. struct row_queue_params {
  40. bool idling_enabled;
  41. int quantum;
  42. bool is_urgent;
  43. };
  44. static const struct row_queue_params row_queues_def[] = {
  45. {true, 10, true},
  46. {false, 1, false},
  47. {true, 100, true},
  48. {false, 1, false},
  49. {false, 1, false},
  50. {false, 1, false},
  51. {false, 1, false}
  52. };
  53. #define ROW_IDLE_TIME_MSEC 5
  54. #define ROW_READ_FREQ_MSEC 5
  55. struct rowq_idling_data {
  56. ktime_t last_insert_time;
  57. bool begin_idling;
  58. };
  59. struct row_queue {
  60. struct row_data *rdata;
  61. struct list_head fifo;
  62. enum row_queue_prio prio;
  63. unsigned int nr_dispatched;
  64. unsigned int nr_req;
  65. int disp_quantum;
  66. struct rowq_idling_data idle_data;
  67. };
  68. struct idling_data {
  69. s64 idle_time_ms;
  70. s64 freq_ms;
  71. struct hrtimer hr_timer;
  72. struct work_struct idle_work;
  73. enum row_queue_prio idling_queue_idx;
  74. };
  75. struct starvation_data {
  76. int starvation_limit;
  77. int starvation_counter;
  78. };
  79. struct row_data {
  80. struct request_queue *dispatch_queue;
  81. struct row_queue row_queues[ROWQ_MAX_PRIO];
  82. struct idling_data rd_idle_data;
  83. unsigned int nr_reqs[2];
  84. bool urgent_in_flight;
  85. struct request *pending_urgent_rq;
  86. int last_served_ioprio_class;
  87. #define ROW_REG_STARVATION_TOLLERANCE 5000
  88. struct starvation_data reg_prio_starvation;
  89. #define ROW_LOW_STARVATION_TOLLERANCE 10000
  90. struct starvation_data low_prio_starvation;
  91. unsigned int cycle_flags;
  92. };
  93. #define RQ_ROWQ(rq) ((struct row_queue *) ((rq)->elv.priv[0]))
  94. #define row_log(q, fmt, args...) \
  95. blk_add_trace_msg(q, "%s():" fmt , __func__, ##args)
  96. #define row_log_rowq(rdata, rowq_id, fmt, args...) \
  97. blk_add_trace_msg(rdata->dispatch_queue, "rowq%d " fmt, \
  98. rowq_id, ##args)
  99. static inline void row_mark_rowq_unserved(struct row_data *rd,
  100. enum row_queue_prio qnum)
  101. {
  102. rd->cycle_flags |= (1 << qnum);
  103. }
  104. static inline void row_clear_rowq_unserved(struct row_data *rd,
  105. enum row_queue_prio qnum)
  106. {
  107. rd->cycle_flags &= ~(1 << qnum);
  108. }
  109. static inline int row_rowq_unserved(struct row_data *rd,
  110. enum row_queue_prio qnum)
  111. {
  112. return rd->cycle_flags & (1 << qnum);
  113. }
  114. static inline void __maybe_unused row_dump_queues_stat(struct row_data *rd)
  115. {
  116. int i;
  117. row_log(rd->dispatch_queue, " Queues status:");
  118. for (i = 0; i < ROWQ_MAX_PRIO; i++)
  119. row_log(rd->dispatch_queue,
  120. "queue%d: dispatched= %d, nr_req=%d", i,
  121. rd->row_queues[i].nr_dispatched,
  122. rd->row_queues[i].nr_req);
  123. }
  124. static void kick_queue(struct work_struct *work)
  125. {
  126. struct idling_data *read_data =
  127. container_of(work, struct idling_data, idle_work);
  128. struct row_data *rd =
  129. container_of(read_data, struct row_data, rd_idle_data);
  130. blk_run_queue(rd->dispatch_queue);
  131. }
  132. static enum hrtimer_restart row_idle_hrtimer_fn(struct hrtimer *hr_timer)
  133. {
  134. struct idling_data *read_data =
  135. container_of(hr_timer, struct idling_data, hr_timer);
  136. struct row_data *rd =
  137. container_of(read_data, struct row_data, rd_idle_data);
  138. row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx,
  139. "Performing delayed work");
  140. rd->row_queues[rd->rd_idle_data.idling_queue_idx].
  141. idle_data.begin_idling = false;
  142. rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
  143. if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE])
  144. row_log(rd->dispatch_queue, "No requests in scheduler");
  145. else
  146. kblockd_schedule_work(rd->dispatch_queue,
  147. &read_data->idle_work);
  148. return HRTIMER_NORESTART;
  149. }
  150. static inline bool row_regular_req_pending(struct row_data *rd)
  151. {
  152. int i;
  153. for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++)
  154. if (!list_empty(&rd->row_queues[i].fifo))
  155. return true;
  156. return false;
  157. }
  158. static inline bool row_low_req_pending(struct row_data *rd)
  159. {
  160. int i;
  161. for (i = ROWQ_LOW_PRIO_IDX; i < ROWQ_MAX_PRIO; i++)
  162. if (!list_empty(&rd->row_queues[i].fifo))
  163. return true;
  164. return false;
  165. }
  166. static void row_add_request(struct request_queue *q,
  167. struct request *rq)
  168. {
  169. struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
  170. struct row_queue *rqueue = RQ_ROWQ(rq);
  171. s64 diff_ms;
  172. bool queue_was_empty = list_empty(&rqueue->fifo);
  173. list_add_tail(&rq->queuelist, &rqueue->fifo);
  174. rd->nr_reqs[rq_data_dir(rq)]++;
  175. rqueue->nr_req++;
  176. rq_set_fifo_time(rq, jiffies);
  177. if (rq->cmd_flags & REQ_URGENT) {
  178. WARN_ON(1);
  179. blk_dump_rq_flags(rq, "");
  180. rq->cmd_flags &= ~REQ_URGENT;
  181. }
  182. if (row_queues_def[rqueue->prio].idling_enabled) {
  183. if (rd->rd_idle_data.idling_queue_idx == rqueue->prio &&
  184. hrtimer_active(&rd->rd_idle_data.hr_timer)) {
  185. if (hrtimer_try_to_cancel(
  186. &rd->rd_idle_data.hr_timer) >= 0) {
  187. row_log_rowq(rd, rqueue->prio,
  188. "Canceled delayed work on %d",
  189. rd->rd_idle_data.idling_queue_idx);
  190. rd->rd_idle_data.idling_queue_idx =
  191. ROWQ_MAX_PRIO;
  192. }
  193. }
  194. diff_ms = ktime_to_ms(ktime_sub(ktime_get(),
  195. rqueue->idle_data.last_insert_time));
  196. if (unlikely(diff_ms < 0)) {
  197. pr_err("%s(): time delta error: diff_ms < 0",
  198. __func__);
  199. rqueue->idle_data.begin_idling = false;
  200. return;
  201. }
  202. if (diff_ms < rd->rd_idle_data.freq_ms) {
  203. rqueue->idle_data.begin_idling = true;
  204. row_log_rowq(rd, rqueue->prio, "Enable idling");
  205. } else {
  206. rqueue->idle_data.begin_idling = false;
  207. row_log_rowq(rd, rqueue->prio, "Disable idling (%ldms)",
  208. (long)diff_ms);
  209. }
  210. rqueue->idle_data.last_insert_time = ktime_get();
  211. }
  212. if (row_queues_def[rqueue->prio].is_urgent &&
  213. !rd->pending_urgent_rq && !rd->urgent_in_flight) {
  214. if (rqueue->prio < ROWQ_REG_PRIO_IDX &&
  215. rd->last_served_ioprio_class != IOPRIO_CLASS_RT &&
  216. queue_was_empty) {
  217. row_log_rowq(rd, rqueue->prio,
  218. "added (high prio) urgent request");
  219. rq->cmd_flags |= REQ_URGENT;
  220. rd->pending_urgent_rq = rq;
  221. } else if (row_rowq_unserved(rd, rqueue->prio)) {
  222. row_log_rowq(rd, rqueue->prio,
  223. "added urgent request (total on queue=%d)",
  224. rqueue->nr_req);
  225. rq->cmd_flags |= REQ_URGENT;
  226. rd->pending_urgent_rq = rq;
  227. }
  228. } else
  229. row_log_rowq(rd, rqueue->prio,
  230. "added request (total on queue=%d)", rqueue->nr_req);
  231. }
  232. static int row_reinsert_req(struct request_queue *q,
  233. struct request *rq)
  234. {
  235. struct row_data *rd = q->elevator->elevator_data;
  236. struct row_queue *rqueue = RQ_ROWQ(rq);
  237. if (!rqueue || rqueue->prio >= ROWQ_MAX_PRIO)
  238. return -EIO;
  239. list_add(&rq->queuelist, &rqueue->fifo);
  240. rd->nr_reqs[rq_data_dir(rq)]++;
  241. rqueue->nr_req++;
  242. row_log_rowq(rd, rqueue->prio,
  243. "%s request reinserted (total on queue=%d)",
  244. (rq_data_dir(rq) == READ ? "READ" : "write"), rqueue->nr_req);
  245. if (rq->cmd_flags & REQ_URGENT) {
  246. WARN_ON(1);
  247. if (!rd->urgent_in_flight) {
  248. pr_err("%s(): no urgent in flight", __func__);
  249. } else {
  250. rd->urgent_in_flight = false;
  251. pr_err("%s(): reinserting URGENT %s req",
  252. __func__,
  253. (rq_data_dir(rq) == READ ? "READ" : "WRITE"));
  254. if (rd->pending_urgent_rq) {
  255. pr_err("%s(): urgent rq is pending",
  256. __func__);
  257. rd->pending_urgent_rq->cmd_flags &= ~REQ_URGENT;
  258. }
  259. rd->pending_urgent_rq = rq;
  260. }
  261. }
  262. return 0;
  263. }
  264. static void row_completed_req(struct request_queue *q, struct request *rq)
  265. {
  266. struct row_data *rd = q->elevator->elevator_data;
  267. if (rq->cmd_flags & REQ_URGENT) {
  268. if (!rd->urgent_in_flight) {
  269. WARN_ON(1);
  270. pr_err("%s(): URGENT req but urgent_in_flight = F",
  271. __func__);
  272. }
  273. rd->urgent_in_flight = false;
  274. rq->cmd_flags &= ~REQ_URGENT;
  275. }
  276. row_log(q, "completed %s %s req.",
  277. (rq->cmd_flags & REQ_URGENT ? "URGENT" : "regular"),
  278. (rq_data_dir(rq) == READ ? "READ" : "WRITE"));
  279. }
  280. static bool row_urgent_pending(struct request_queue *q)
  281. {
  282. struct row_data *rd = q->elevator->elevator_data;
  283. if (rd->urgent_in_flight) {
  284. row_log(rd->dispatch_queue, "%d urgent requests in flight",
  285. rd->urgent_in_flight);
  286. return false;
  287. }
  288. if (rd->pending_urgent_rq) {
  289. row_log(rd->dispatch_queue, "Urgent request pending");
  290. return true;
  291. }
  292. row_log(rd->dispatch_queue, "no urgent request pending/in flight");
  293. return false;
  294. }
  295. static void row_remove_request(struct row_data *rd,
  296. struct request *rq)
  297. {
  298. struct row_queue *rqueue = RQ_ROWQ(rq);
  299. list_del_init(&(rq)->queuelist);
  300. if (rd->pending_urgent_rq == rq)
  301. rd->pending_urgent_rq = NULL;
  302. else
  303. BUG_ON(rq->cmd_flags & REQ_URGENT);
  304. rqueue->nr_req--;
  305. rd->nr_reqs[rq_data_dir(rq)]--;
  306. }
  307. static void row_dispatch_insert(struct row_data *rd, struct request *rq)
  308. {
  309. struct row_queue *rqueue = RQ_ROWQ(rq);
  310. row_remove_request(rd, rq);
  311. elv_dispatch_sort(rd->dispatch_queue, rq);
  312. if (rq->cmd_flags & REQ_URGENT) {
  313. WARN_ON(rd->urgent_in_flight);
  314. rd->urgent_in_flight = true;
  315. }
  316. rqueue->nr_dispatched++;
  317. row_clear_rowq_unserved(rd, rqueue->prio);
  318. row_log_rowq(rd, rqueue->prio,
  319. " Dispatched request %p nr_disp = %d", rq,
  320. rqueue->nr_dispatched);
  321. if (rqueue->prio < ROWQ_REG_PRIO_IDX) {
  322. rd->last_served_ioprio_class = IOPRIO_CLASS_RT;
  323. if (row_regular_req_pending(rd))
  324. rd->reg_prio_starvation.starvation_counter++;
  325. if (row_low_req_pending(rd))
  326. rd->low_prio_starvation.starvation_counter++;
  327. } else if (rqueue->prio < ROWQ_LOW_PRIO_IDX) {
  328. rd->last_served_ioprio_class = IOPRIO_CLASS_BE;
  329. rd->reg_prio_starvation.starvation_counter = 0;
  330. if (row_low_req_pending(rd))
  331. rd->low_prio_starvation.starvation_counter++;
  332. } else {
  333. rd->last_served_ioprio_class = IOPRIO_CLASS_IDLE;
  334. rd->low_prio_starvation.starvation_counter = 0;
  335. }
  336. }
  337. static int row_get_ioprio_class_to_serve(struct row_data *rd, int force)
  338. {
  339. int i;
  340. int ret = IOPRIO_CLASS_NONE;
  341. if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) {
  342. row_log(rd->dispatch_queue, "No more requests in scheduler");
  343. goto check_idling;
  344. }
  345. for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) {
  346. if (!list_empty(&rd->row_queues[i].fifo)) {
  347. if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
  348. if (hrtimer_try_to_cancel(
  349. &rd->rd_idle_data.hr_timer) >= 0) {
  350. row_log(rd->dispatch_queue,
  351. "Canceling delayed work on %d. RT pending",
  352. rd->rd_idle_data.idling_queue_idx);
  353. rd->rd_idle_data.idling_queue_idx =
  354. ROWQ_MAX_PRIO;
  355. }
  356. }
  357. if (row_regular_req_pending(rd) &&
  358. (rd->reg_prio_starvation.starvation_counter >=
  359. rd->reg_prio_starvation.starvation_limit))
  360. ret = IOPRIO_CLASS_BE;
  361. else if (row_low_req_pending(rd) &&
  362. (rd->low_prio_starvation.starvation_counter >=
  363. rd->low_prio_starvation.starvation_limit))
  364. ret = IOPRIO_CLASS_IDLE;
  365. else
  366. ret = IOPRIO_CLASS_RT;
  367. goto done;
  368. }
  369. }
  370. if (hrtimer_active(&rd->rd_idle_data.hr_timer)) {
  371. row_log(rd->dispatch_queue, "Delayed work pending. Exiting");
  372. goto done;
  373. }
  374. check_idling:
  375. for (i = 0; i < ROWQ_REG_PRIO_IDX && !force; i++) {
  376. if (rd->row_queues[i].idle_data.begin_idling &&
  377. row_queues_def[i].idling_enabled)
  378. goto initiate_idling;
  379. }
  380. for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) {
  381. if (list_empty(&rd->row_queues[i].fifo)) {
  382. if (rd->row_queues[i].idle_data.begin_idling &&
  383. !force && row_queues_def[i].idling_enabled)
  384. goto initiate_idling;
  385. } else {
  386. if (row_low_req_pending(rd) &&
  387. (rd->low_prio_starvation.starvation_counter >=
  388. rd->low_prio_starvation.starvation_limit))
  389. ret = IOPRIO_CLASS_IDLE;
  390. else
  391. ret = IOPRIO_CLASS_BE;
  392. goto done;
  393. }
  394. }
  395. if (rd->nr_reqs[READ] || rd->nr_reqs[WRITE])
  396. ret = IOPRIO_CLASS_IDLE;
  397. goto done;
  398. initiate_idling:
  399. hrtimer_start(&rd->rd_idle_data.hr_timer,
  400. ktime_set(0, rd->rd_idle_data.idle_time_ms * NSEC_PER_MSEC),
  401. HRTIMER_MODE_REL);
  402. rd->rd_idle_data.idling_queue_idx = i;
  403. row_log_rowq(rd, i, "Scheduled delayed work on %d. exiting", i);
  404. done:
  405. return ret;
  406. }
  407. static void row_restart_cycle(struct row_data *rd,
  408. int start_idx, int end_idx)
  409. {
  410. int i;
  411. row_dump_queues_stat(rd);
  412. for (i = start_idx; i < end_idx; i++) {
  413. if (rd->row_queues[i].nr_dispatched <
  414. rd->row_queues[i].disp_quantum)
  415. row_mark_rowq_unserved(rd, i);
  416. rd->row_queues[i].nr_dispatched = 0;
  417. }
  418. row_log(rd->dispatch_queue, "Restarting cycle for class @ %d-%d",
  419. start_idx, end_idx);
  420. }
  421. static int row_get_next_queue(struct request_queue *q, struct row_data *rd,
  422. int start_idx, int end_idx)
  423. {
  424. int i = start_idx;
  425. bool restart = true;
  426. int ret = -EIO;
  427. do {
  428. if (list_empty(&rd->row_queues[i].fifo) ||
  429. rd->row_queues[i].nr_dispatched >=
  430. rd->row_queues[i].disp_quantum) {
  431. i++;
  432. if (i == end_idx && restart) {
  433. row_restart_cycle(rd, start_idx, end_idx);
  434. i = start_idx;
  435. restart = false;
  436. }
  437. } else {
  438. ret = i;
  439. break;
  440. }
  441. } while (i < end_idx);
  442. return ret;
  443. }
  444. static int row_dispatch_requests(struct request_queue *q, int force)
  445. {
  446. struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
  447. int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx;
  448. if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) {
  449. if (hrtimer_try_to_cancel(&rd->rd_idle_data.hr_timer) >= 0) {
  450. row_log(rd->dispatch_queue,
  451. "Canceled delayed work on %d - forced dispatch",
  452. rd->rd_idle_data.idling_queue_idx);
  453. rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
  454. }
  455. }
  456. if (rd->pending_urgent_rq) {
  457. row_log(rd->dispatch_queue, "dispatching urgent request");
  458. row_dispatch_insert(rd, rd->pending_urgent_rq);
  459. ret = 1;
  460. goto done;
  461. }
  462. ioprio_class_to_serve = row_get_ioprio_class_to_serve(rd, force);
  463. row_log(rd->dispatch_queue, "Dispatching from %d priority class",
  464. ioprio_class_to_serve);
  465. switch (ioprio_class_to_serve) {
  466. case IOPRIO_CLASS_NONE:
  467. rd->last_served_ioprio_class = IOPRIO_CLASS_NONE;
  468. goto done;
  469. case IOPRIO_CLASS_RT:
  470. start_idx = ROWQ_HIGH_PRIO_IDX;
  471. end_idx = ROWQ_REG_PRIO_IDX;
  472. break;
  473. case IOPRIO_CLASS_BE:
  474. start_idx = ROWQ_REG_PRIO_IDX;
  475. end_idx = ROWQ_LOW_PRIO_IDX;
  476. break;
  477. case IOPRIO_CLASS_IDLE:
  478. start_idx = ROWQ_LOW_PRIO_IDX;
  479. end_idx = ROWQ_MAX_PRIO;
  480. break;
  481. default:
  482. pr_err("%s(): Invalid I/O priority class", __func__);
  483. goto done;
  484. }
  485. currq = row_get_next_queue(q, rd, start_idx, end_idx);
  486. if (currq >= 0) {
  487. row_dispatch_insert(rd,
  488. rq_entry_fifo(rd->row_queues[currq].fifo.next));
  489. ret = 1;
  490. }
  491. done:
  492. return ret;
  493. }
  494. static void *row_init_queue(struct request_queue *q)
  495. {
  496. struct row_data *rdata;
  497. int i;
  498. rdata = kmalloc_node(sizeof(*rdata),
  499. GFP_KERNEL | __GFP_ZERO, q->node);
  500. if (!rdata)
  501. return NULL;
  502. memset(rdata, 0, sizeof(*rdata));
  503. for (i = 0; i < ROWQ_MAX_PRIO; i++) {
  504. INIT_LIST_HEAD(&rdata->row_queues[i].fifo);
  505. rdata->row_queues[i].disp_quantum = row_queues_def[i].quantum;
  506. rdata->row_queues[i].rdata = rdata;
  507. rdata->row_queues[i].prio = i;
  508. rdata->row_queues[i].idle_data.begin_idling = false;
  509. rdata->row_queues[i].idle_data.last_insert_time =
  510. ktime_set(0, 0);
  511. }
  512. rdata->reg_prio_starvation.starvation_limit =
  513. ROW_REG_STARVATION_TOLLERANCE;
  514. rdata->low_prio_starvation.starvation_limit =
  515. ROW_LOW_STARVATION_TOLLERANCE;
  516. rdata->rd_idle_data.idle_time_ms = ROW_IDLE_TIME_MSEC;
  517. rdata->rd_idle_data.freq_ms = ROW_READ_FREQ_MSEC;
  518. hrtimer_init(&rdata->rd_idle_data.hr_timer,
  519. CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  520. rdata->rd_idle_data.hr_timer.function = &row_idle_hrtimer_fn;
  521. INIT_WORK(&rdata->rd_idle_data.idle_work, kick_queue);
  522. rdata->last_served_ioprio_class = IOPRIO_CLASS_NONE;
  523. rdata->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
  524. rdata->dispatch_queue = q;
  525. return rdata;
  526. }
  527. static void row_exit_queue(struct elevator_queue *e)
  528. {
  529. struct row_data *rd = (struct row_data *)e->elevator_data;
  530. int i;
  531. for (i = 0; i < ROWQ_MAX_PRIO; i++)
  532. BUG_ON(!list_empty(&rd->row_queues[i].fifo));
  533. if (hrtimer_cancel(&rd->rd_idle_data.hr_timer))
  534. pr_err("%s(): idle timer was active!", __func__);
  535. rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
  536. kfree(rd);
  537. }
  538. static void row_merged_requests(struct request_queue *q, struct request *rq,
  539. struct request *next)
  540. {
  541. struct row_queue *rqueue = RQ_ROWQ(next);
  542. list_del_init(&next->queuelist);
  543. rqueue->nr_req--;
  544. if (rqueue->rdata->pending_urgent_rq == next) {
  545. pr_err("\n\nROW_WARNING: merging pending urgent!");
  546. rqueue->rdata->pending_urgent_rq = rq;
  547. rq->cmd_flags |= REQ_URGENT;
  548. WARN_ON(!(next->cmd_flags & REQ_URGENT));
  549. next->cmd_flags &= ~REQ_URGENT;
  550. }
  551. rqueue->rdata->nr_reqs[rq_data_dir(rq)]--;
  552. }
  553. static enum row_queue_prio row_get_queue_prio(struct request *rq,
  554. struct row_data *rd)
  555. {
  556. const int data_dir = rq_data_dir(rq);
  557. const bool is_sync = rq_is_sync(rq);
  558. enum row_queue_prio q_type = ROWQ_MAX_PRIO;
  559. int ioprio_class = IOPRIO_PRIO_CLASS(rq->elv.icq->ioc->ioprio);
  560. switch (ioprio_class) {
  561. case IOPRIO_CLASS_RT:
  562. if (data_dir == READ)
  563. q_type = ROWQ_PRIO_HIGH_READ;
  564. else if (is_sync)
  565. q_type = ROWQ_PRIO_HIGH_SWRITE;
  566. else {
  567. pr_err("%s:%s(): got a simple write from RT_CLASS. How???",
  568. rq->rq_disk->disk_name, __func__);
  569. q_type = ROWQ_PRIO_REG_WRITE;
  570. }
  571. break;
  572. case IOPRIO_CLASS_IDLE:
  573. if (data_dir == READ)
  574. q_type = ROWQ_PRIO_LOW_READ;
  575. else if (is_sync)
  576. q_type = ROWQ_PRIO_LOW_SWRITE;
  577. else {
  578. pr_err("%s:%s(): got a simple write from IDLE_CLASS. How???",
  579. rq->rq_disk->disk_name, __func__);
  580. q_type = ROWQ_PRIO_REG_WRITE;
  581. }
  582. break;
  583. case IOPRIO_CLASS_NONE:
  584. case IOPRIO_CLASS_BE:
  585. default:
  586. if (data_dir == READ)
  587. q_type = ROWQ_PRIO_REG_READ;
  588. else if (is_sync)
  589. q_type = ROWQ_PRIO_REG_SWRITE;
  590. else
  591. q_type = ROWQ_PRIO_REG_WRITE;
  592. break;
  593. }
  594. return q_type;
  595. }
  596. static int
  597. row_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
  598. {
  599. struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
  600. unsigned long flags;
  601. spin_lock_irqsave(q->queue_lock, flags);
  602. rq->elv.priv[0] =
  603. (void *)(&rd->row_queues[row_get_queue_prio(rq, rd)]);
  604. spin_unlock_irqrestore(q->queue_lock, flags);
  605. return 0;
  606. }
  607. static ssize_t row_var_show(int var, char *page)
  608. {
  609. return snprintf(page, 100, "%d\n", var);
  610. }
  611. static ssize_t row_var_store(int *var, const char *page, size_t count)
  612. {
  613. int err;
  614. err = kstrtoul(page, 10, (unsigned long *)var);
  615. return count;
  616. }
  617. #define SHOW_FUNCTION(__FUNC, __VAR) \
  618. static ssize_t __FUNC(struct elevator_queue *e, char *page) \
  619. { \
  620. struct row_data *rowd = e->elevator_data; \
  621. int __data = __VAR; \
  622. return row_var_show(__data, (page)); \
  623. }
  624. SHOW_FUNCTION(row_hp_read_quantum_show,
  625. rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum);
  626. SHOW_FUNCTION(row_rp_read_quantum_show,
  627. rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum);
  628. SHOW_FUNCTION(row_hp_swrite_quantum_show,
  629. rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum);
  630. SHOW_FUNCTION(row_rp_swrite_quantum_show,
  631. rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum);
  632. SHOW_FUNCTION(row_rp_write_quantum_show,
  633. rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum);
  634. SHOW_FUNCTION(row_lp_read_quantum_show,
  635. rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum);
  636. SHOW_FUNCTION(row_lp_swrite_quantum_show,
  637. rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum);
  638. SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms);
  639. SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms);
  640. SHOW_FUNCTION(row_reg_starv_limit_show,
  641. rowd->reg_prio_starvation.starvation_limit);
  642. SHOW_FUNCTION(row_low_starv_limit_show,
  643. rowd->low_prio_starvation.starvation_limit);
  644. #undef SHOW_FUNCTION
  645. #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \
  646. static ssize_t __FUNC(struct elevator_queue *e, \
  647. const char *page, size_t count) \
  648. { \
  649. struct row_data *rowd = e->elevator_data; \
  650. int __data; \
  651. int ret = row_var_store(&__data, (page), count); \
  652. if (__data < (MIN)) \
  653. __data = (MIN); \
  654. else if (__data > (MAX)) \
  655. __data = (MAX); \
  656. *(__PTR) = __data; \
  657. return ret; \
  658. }
  659. STORE_FUNCTION(row_hp_read_quantum_store,
  660. &rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX);
  661. STORE_FUNCTION(row_rp_read_quantum_store,
  662. &rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum,
  663. 1, INT_MAX);
  664. STORE_FUNCTION(row_hp_swrite_quantum_store,
  665. &rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum,
  666. 1, INT_MAX);
  667. STORE_FUNCTION(row_rp_swrite_quantum_store,
  668. &rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum,
  669. 1, INT_MAX);
  670. STORE_FUNCTION(row_rp_write_quantum_store,
  671. &rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum,
  672. 1, INT_MAX);
  673. STORE_FUNCTION(row_lp_read_quantum_store,
  674. &rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum,
  675. 1, INT_MAX);
  676. STORE_FUNCTION(row_lp_swrite_quantum_store,
  677. &rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
  678. 1, INT_MAX);
  679. STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms,
  680. 1, INT_MAX);
  681. STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms,
  682. 1, INT_MAX);
  683. STORE_FUNCTION(row_reg_starv_limit_store,
  684. &rowd->reg_prio_starvation.starvation_limit,
  685. 1, INT_MAX);
  686. STORE_FUNCTION(row_low_starv_limit_store,
  687. &rowd->low_prio_starvation.starvation_limit,
  688. 1, INT_MAX);
  689. #undef STORE_FUNCTION
  690. #define ROW_ATTR(name) \
  691. __ATTR(name, S_IRUGO|S_IWUSR, row_##name##_show, \
  692. row_##name##_store)
  693. static struct elv_fs_entry row_attrs[] = {
  694. ROW_ATTR(hp_read_quantum),
  695. ROW_ATTR(rp_read_quantum),
  696. ROW_ATTR(hp_swrite_quantum),
  697. ROW_ATTR(rp_swrite_quantum),
  698. ROW_ATTR(rp_write_quantum),
  699. ROW_ATTR(lp_read_quantum),
  700. ROW_ATTR(lp_swrite_quantum),
  701. ROW_ATTR(rd_idle_data),
  702. ROW_ATTR(rd_idle_data_freq),
  703. ROW_ATTR(reg_starv_limit),
  704. ROW_ATTR(low_starv_limit),
  705. __ATTR_NULL
  706. };
  707. static struct elevator_type iosched_row = {
  708. .ops = {
  709. .elevator_merge_req_fn = row_merged_requests,
  710. .elevator_dispatch_fn = row_dispatch_requests,
  711. .elevator_add_req_fn = row_add_request,
  712. .elevator_reinsert_req_fn = row_reinsert_req,
  713. .elevator_is_urgent_fn = row_urgent_pending,
  714. .elevator_completed_req_fn = row_completed_req,
  715. .elevator_former_req_fn = elv_rb_former_request,
  716. .elevator_latter_req_fn = elv_rb_latter_request,
  717. .elevator_set_req_fn = row_set_request,
  718. .elevator_init_fn = row_init_queue,
  719. .elevator_exit_fn = row_exit_queue,
  720. },
  721. .icq_size = sizeof(struct io_cq),
  722. .icq_align = __alignof__(struct io_cq),
  723. .elevator_attrs = row_attrs,
  724. .elevator_name = "row",
  725. .elevator_owner = THIS_MODULE,
  726. };
  727. static int __init row_init(void)
  728. {
  729. elv_register(&iosched_row);
  730. return 0;
  731. }
  732. static void __exit row_exit(void)
  733. {
  734. elv_unregister(&iosched_row);
  735. }
  736. module_init(row_init);
  737. module_exit(row_exit);
  738. MODULE_LICENSE("GPLv2");
  739. MODULE_DESCRIPTION("Read Over Write IO scheduler");