swap_ratio.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/mm_types.h>
  14. #include <linux/swapfile.h>
  15. #include <linux/swap.h>
  16. #define SWAP_RATIO_GROUP_START (SWAP_FLAG_PRIO_MASK - 9) /* 32758 */
  17. #define SWAP_RATIO_GROUP_END (SWAP_FLAG_PRIO_MASK) /* 32767 */
  18. #define SWAP_FAST_WRITES (SWAPFILE_CLUSTER * (SWAP_CLUSTER_MAX / 8))
  19. #define SWAP_SLOW_WRITES SWAPFILE_CLUSTER
  20. /*
  21. * The fast/slow swap write ratio.
  22. * 100 indicates that all writes should
  23. * go to fast swap device.
  24. */
  25. int sysctl_swap_ratio = 100;
  26. /* Enable the swap ratio feature */
  27. int sysctl_swap_ratio_enable;
  28. static bool is_same_group(struct swap_info_struct *a,
  29. struct swap_info_struct *b)
  30. {
  31. if (!sysctl_swap_ratio_enable)
  32. return false;
  33. if (!is_swap_ratio_group(a->prio))
  34. return false;
  35. if (a->prio == b->prio)
  36. return true;
  37. return false;
  38. }
  39. /* Caller must hold swap_avail_lock */
  40. static int calculate_write_pending(struct swap_info_struct *si,
  41. struct swap_info_struct *n)
  42. {
  43. int ratio = sysctl_swap_ratio;
  44. if ((ratio < 0) || (ratio > 100))
  45. return -EINVAL;
  46. if (WARN_ON(!(si->flags & SWP_FAST)))
  47. return -ENODEV;
  48. if ((n->flags & SWP_FAST) || !is_same_group(si, n))
  49. return -ENODEV;
  50. si->max_writes = ratio ? SWAP_FAST_WRITES : 0;
  51. n->max_writes = ratio ? (SWAP_FAST_WRITES * 100) /
  52. ratio - SWAP_FAST_WRITES : SWAP_SLOW_WRITES;
  53. si->write_pending = si->max_writes;
  54. n->write_pending = n->max_writes;
  55. return 0;
  56. }
  57. static int swap_ratio_slow(struct swap_info_struct **si)
  58. {
  59. struct swap_info_struct *n = NULL;
  60. int ret = 0;
  61. spin_lock(&(*si)->lock);
  62. spin_lock(&swap_avail_lock);
  63. if (&(*si)->avail_list == plist_last(&swap_avail_head)) {
  64. /* just to make skip work */
  65. n = *si;
  66. ret = -ENODEV;
  67. goto skip;
  68. }
  69. n = plist_next_entry(&(*si)->avail_list,
  70. struct swap_info_struct,
  71. avail_list);
  72. if (n == *si) {
  73. /* No other swap device */
  74. ret = -ENODEV;
  75. goto skip;
  76. }
  77. spin_unlock(&swap_avail_lock);
  78. spin_lock(&n->lock);
  79. spin_lock(&swap_avail_lock);
  80. if ((*si)->flags & SWP_FAST) {
  81. if ((*si)->write_pending) {
  82. (*si)->write_pending--;
  83. goto exit;
  84. } else {
  85. if ((n->flags & SWP_FAST) || !is_same_group(*si, n)) {
  86. /* Should never happen */
  87. ret = -ENODEV;
  88. } else if (n->write_pending) {
  89. /*
  90. * Requeue fast device, since there are pending
  91. * writes for slow device.
  92. */
  93. plist_requeue(&(*si)->avail_list,
  94. &swap_avail_head);
  95. n->write_pending--;
  96. spin_unlock(&(*si)->lock);
  97. *si = n;
  98. goto skip;
  99. } else {
  100. if (calculate_write_pending(*si, n) < 0) {
  101. ret = -ENODEV;
  102. goto exit;
  103. }
  104. /* Restart from fast device */
  105. (*si)->write_pending--;
  106. }
  107. }
  108. } else {
  109. if (!(n->flags & SWP_FAST) || !is_same_group(*si, n)) {
  110. /* Should never happen */
  111. ret = -ENODEV;
  112. } else if (n->write_pending) {
  113. /*
  114. * Pending writes for fast device.
  115. * We reach here when slow device is swapped on first,
  116. * before fast device.
  117. */
  118. /* requeue slow device to the end */
  119. plist_requeue(&(*si)->avail_list, &swap_avail_head);
  120. n->write_pending--;
  121. spin_unlock(&(*si)->lock);
  122. *si = n;
  123. goto skip;
  124. } else {
  125. if ((*si)->write_pending) {
  126. (*si)->write_pending--;
  127. } else {
  128. if (calculate_write_pending(n, *si) < 0) {
  129. ret = -ENODEV;
  130. goto exit;
  131. }
  132. n->write_pending--;
  133. plist_requeue(&(*si)->avail_list,
  134. &swap_avail_head);
  135. spin_unlock(&(*si)->lock);
  136. *si = n;
  137. goto skip;
  138. }
  139. }
  140. }
  141. exit:
  142. spin_unlock(&(*si)->lock);
  143. skip:
  144. spin_unlock(&swap_avail_lock);
  145. /* n and si would have got interchanged */
  146. spin_unlock(&n->lock);
  147. return ret;
  148. }
  149. bool is_swap_ratio_group(int prio)
  150. {
  151. return ((prio >= SWAP_RATIO_GROUP_START) &&
  152. (prio <= SWAP_RATIO_GROUP_END)) ? true : false;
  153. }
  154. void setup_swap_ratio(struct swap_info_struct *p, int prio)
  155. {
  156. /* Used only if sysctl_swap_ratio_enable is set */
  157. if (is_swap_ratio_group(prio)) {
  158. if (p->flags & SWP_FAST)
  159. p->write_pending = SWAP_FAST_WRITES;
  160. else
  161. p->write_pending = SWAP_SLOW_WRITES;
  162. p->max_writes = p->write_pending;
  163. }
  164. }
  165. int swap_ratio(struct swap_info_struct **si)
  166. {
  167. if (!sysctl_swap_ratio_enable)
  168. return -ENODEV;
  169. if (is_swap_ratio_group((*si)->prio))
  170. return swap_ratio_slow(si);
  171. else
  172. return -ENODEV;
  173. }