pblk-rl.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2016 CNEX Labs
  4. * Initial release: Javier Gonzalez <javier@cnexlabs.com>
  5. * Matias Bjorling <matias@cnexlabs.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License version
  9. * 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * pblk-rl.c - pblk's rate limiter for user I/O
  17. *
  18. */
  19. #include "pblk.h"
  20. static void pblk_rl_kick_u_timer(struct pblk_rl *rl)
  21. {
  22. mod_timer(&rl->u_timer, jiffies + msecs_to_jiffies(5000));
  23. }
  24. int pblk_rl_is_limit(struct pblk_rl *rl)
  25. {
  26. int rb_space;
  27. rb_space = atomic_read(&rl->rb_space);
  28. return (rb_space == 0);
  29. }
  30. int pblk_rl_user_may_insert(struct pblk_rl *rl, int nr_entries)
  31. {
  32. int rb_user_cnt = atomic_read(&rl->rb_user_cnt);
  33. int rb_space = atomic_read(&rl->rb_space);
  34. if (unlikely(rb_space >= 0) && (rb_space - nr_entries < 0))
  35. return NVM_IO_ERR;
  36. if (rb_user_cnt >= rl->rb_user_max)
  37. return NVM_IO_REQUEUE;
  38. return NVM_IO_OK;
  39. }
  40. void pblk_rl_inserted(struct pblk_rl *rl, int nr_entries)
  41. {
  42. int rb_space = atomic_read(&rl->rb_space);
  43. if (unlikely(rb_space >= 0))
  44. atomic_sub(nr_entries, &rl->rb_space);
  45. }
  46. int pblk_rl_gc_may_insert(struct pblk_rl *rl, int nr_entries)
  47. {
  48. int rb_gc_cnt = atomic_read(&rl->rb_gc_cnt);
  49. int rb_user_active;
  50. /* If there is no user I/O let GC take over space on the write buffer */
  51. rb_user_active = READ_ONCE(rl->rb_user_active);
  52. return (!(rb_gc_cnt >= rl->rb_gc_max && rb_user_active));
  53. }
  54. void pblk_rl_user_in(struct pblk_rl *rl, int nr_entries)
  55. {
  56. atomic_add(nr_entries, &rl->rb_user_cnt);
  57. /* Release user I/O state. Protect from GC */
  58. smp_store_release(&rl->rb_user_active, 1);
  59. pblk_rl_kick_u_timer(rl);
  60. }
  61. void pblk_rl_werr_line_in(struct pblk_rl *rl)
  62. {
  63. atomic_inc(&rl->werr_lines);
  64. }
  65. void pblk_rl_werr_line_out(struct pblk_rl *rl)
  66. {
  67. atomic_dec(&rl->werr_lines);
  68. }
  69. void pblk_rl_gc_in(struct pblk_rl *rl, int nr_entries)
  70. {
  71. atomic_add(nr_entries, &rl->rb_gc_cnt);
  72. }
  73. void pblk_rl_out(struct pblk_rl *rl, int nr_user, int nr_gc)
  74. {
  75. atomic_sub(nr_user, &rl->rb_user_cnt);
  76. atomic_sub(nr_gc, &rl->rb_gc_cnt);
  77. }
  78. unsigned long pblk_rl_nr_free_blks(struct pblk_rl *rl)
  79. {
  80. return atomic_read(&rl->free_blocks);
  81. }
  82. unsigned long pblk_rl_nr_user_free_blks(struct pblk_rl *rl)
  83. {
  84. return atomic_read(&rl->free_user_blocks);
  85. }
  86. static void __pblk_rl_update_rates(struct pblk_rl *rl,
  87. unsigned long free_blocks)
  88. {
  89. struct pblk *pblk = container_of(rl, struct pblk, rl);
  90. int max = rl->rb_budget;
  91. int werr_gc_needed = atomic_read(&rl->werr_lines);
  92. if (free_blocks >= rl->high) {
  93. if (werr_gc_needed) {
  94. /* Allocate a small budget for recovering
  95. * lines with write errors
  96. */
  97. rl->rb_gc_max = 1 << rl->rb_windows_pw;
  98. rl->rb_user_max = max - rl->rb_gc_max;
  99. rl->rb_state = PBLK_RL_WERR;
  100. } else {
  101. rl->rb_user_max = max;
  102. rl->rb_gc_max = 0;
  103. rl->rb_state = PBLK_RL_OFF;
  104. }
  105. } else if (free_blocks < rl->high) {
  106. int shift = rl->high_pw - rl->rb_windows_pw;
  107. int user_windows = free_blocks >> shift;
  108. int user_max = user_windows << ilog2(NVM_MAX_VLBA);
  109. rl->rb_user_max = user_max;
  110. rl->rb_gc_max = max - user_max;
  111. if (free_blocks <= rl->rsv_blocks) {
  112. rl->rb_user_max = 0;
  113. rl->rb_gc_max = max;
  114. }
  115. /* In the worst case, we will need to GC lines in the low list
  116. * (high valid sector count). If there are lines to GC on high
  117. * or mid lists, these will be prioritized
  118. */
  119. rl->rb_state = PBLK_RL_LOW;
  120. }
  121. if (rl->rb_state != PBLK_RL_OFF)
  122. pblk_gc_should_start(pblk);
  123. else
  124. pblk_gc_should_stop(pblk);
  125. }
  126. void pblk_rl_update_rates(struct pblk_rl *rl)
  127. {
  128. __pblk_rl_update_rates(rl, pblk_rl_nr_user_free_blks(rl));
  129. }
  130. void pblk_rl_free_lines_inc(struct pblk_rl *rl, struct pblk_line *line)
  131. {
  132. int blk_in_line = atomic_read(&line->blk_in_line);
  133. int free_blocks;
  134. atomic_add(blk_in_line, &rl->free_blocks);
  135. free_blocks = atomic_add_return(blk_in_line, &rl->free_user_blocks);
  136. __pblk_rl_update_rates(rl, free_blocks);
  137. }
  138. void pblk_rl_free_lines_dec(struct pblk_rl *rl, struct pblk_line *line,
  139. bool used)
  140. {
  141. int blk_in_line = atomic_read(&line->blk_in_line);
  142. int free_blocks;
  143. atomic_sub(blk_in_line, &rl->free_blocks);
  144. if (used)
  145. free_blocks = atomic_sub_return(blk_in_line,
  146. &rl->free_user_blocks);
  147. else
  148. free_blocks = atomic_read(&rl->free_user_blocks);
  149. __pblk_rl_update_rates(rl, free_blocks);
  150. }
  151. int pblk_rl_high_thrs(struct pblk_rl *rl)
  152. {
  153. return rl->high;
  154. }
  155. int pblk_rl_max_io(struct pblk_rl *rl)
  156. {
  157. return rl->rb_max_io;
  158. }
  159. static void pblk_rl_u_timer(struct timer_list *t)
  160. {
  161. struct pblk_rl *rl = from_timer(rl, t, u_timer);
  162. /* Release user I/O state. Protect from GC */
  163. smp_store_release(&rl->rb_user_active, 0);
  164. }
  165. void pblk_rl_free(struct pblk_rl *rl)
  166. {
  167. del_timer(&rl->u_timer);
  168. }
  169. void pblk_rl_init(struct pblk_rl *rl, int budget, int threshold)
  170. {
  171. struct pblk *pblk = container_of(rl, struct pblk, rl);
  172. struct nvm_tgt_dev *dev = pblk->dev;
  173. struct nvm_geo *geo = &dev->geo;
  174. struct pblk_line_mgmt *l_mg = &pblk->l_mg;
  175. struct pblk_line_meta *lm = &pblk->lm;
  176. int sec_meta, blk_meta;
  177. unsigned int rb_windows;
  178. /* Consider sectors used for metadata */
  179. sec_meta = (lm->smeta_sec + lm->emeta_sec[0]) * l_mg->nr_free_lines;
  180. blk_meta = DIV_ROUND_UP(sec_meta, geo->clba);
  181. rl->high = pblk->op_blks - blk_meta - lm->blk_per_line;
  182. rl->high_pw = get_count_order(rl->high);
  183. rl->rsv_blocks = pblk_get_min_chks(pblk);
  184. /* This will always be a power-of-2 */
  185. rb_windows = budget / NVM_MAX_VLBA;
  186. rl->rb_windows_pw = get_count_order(rb_windows);
  187. /* To start with, all buffer is available to user I/O writers */
  188. rl->rb_budget = budget;
  189. rl->rb_user_max = budget;
  190. rl->rb_gc_max = 0;
  191. rl->rb_state = PBLK_RL_HIGH;
  192. /* Maximize I/O size and ansure that back threshold is respected */
  193. if (threshold)
  194. rl->rb_max_io = budget - pblk->min_write_pgs_data - threshold;
  195. else
  196. rl->rb_max_io = budget - pblk->min_write_pgs_data - 1;
  197. atomic_set(&rl->rb_user_cnt, 0);
  198. atomic_set(&rl->rb_gc_cnt, 0);
  199. atomic_set(&rl->rb_space, -1);
  200. atomic_set(&rl->werr_lines, 0);
  201. timer_setup(&rl->u_timer, pblk_rl_u_timer, 0);
  202. rl->rb_user_active = 0;
  203. rl->rb_gc_active = 0;
  204. }