compaction.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #ifndef _LINUX_COMPACTION_H
  2. #define _LINUX_COMPACTION_H
  3. /*
  4. * Determines how hard direct compaction should try to succeed.
  5. * Lower value means higher priority, analogically to reclaim priority.
  6. */
  7. enum compact_priority {
  8. COMPACT_PRIO_SYNC_FULL,
  9. MIN_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_FULL,
  10. COMPACT_PRIO_SYNC_LIGHT,
  11. MIN_COMPACT_COSTLY_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
  12. DEF_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
  13. COMPACT_PRIO_ASYNC,
  14. INIT_COMPACT_PRIORITY = COMPACT_PRIO_ASYNC
  15. };
  16. /* Return values for compact_zone() and try_to_compact_pages() */
  17. /* When adding new states, please adjust include/trace/events/compaction.h */
  18. enum compact_result {
  19. /* For more detailed tracepoint output - internal to compaction */
  20. COMPACT_NOT_SUITABLE_ZONE,
  21. /*
  22. * compaction didn't start as it was not possible or direct reclaim
  23. * was more suitable
  24. */
  25. COMPACT_SKIPPED,
  26. /* compaction didn't start as it was deferred due to past failures */
  27. COMPACT_DEFERRED,
  28. /* compaction not active last round */
  29. COMPACT_INACTIVE = COMPACT_DEFERRED,
  30. /* For more detailed tracepoint output - internal to compaction */
  31. COMPACT_NO_SUITABLE_PAGE,
  32. /* compaction should continue to another pageblock */
  33. COMPACT_CONTINUE,
  34. /*
  35. * The full zone was compacted scanned but wasn't successfull to compact
  36. * suitable pages.
  37. */
  38. COMPACT_COMPLETE,
  39. /*
  40. * direct compaction has scanned part of the zone but wasn't successfull
  41. * to compact suitable pages.
  42. */
  43. COMPACT_PARTIAL_SKIPPED,
  44. /* compaction terminated prematurely due to lock contentions */
  45. COMPACT_CONTENDED,
  46. /*
  47. * direct compaction terminated after concluding that the allocation
  48. * should now succeed
  49. */
  50. COMPACT_SUCCESS,
  51. };
  52. struct alloc_context; /* in mm/internal.h */
  53. /*
  54. * Number of free order-0 pages that should be available above given watermark
  55. * to make sure compaction has reasonable chance of not running out of free
  56. * pages that it needs to isolate as migration target during its work.
  57. */
  58. static inline unsigned long compact_gap(unsigned int order)
  59. {
  60. /*
  61. * Although all the isolations for migration are temporary, compaction
  62. * free scanner may have up to 1 << order pages on its list and then
  63. * try to split an (order - 1) free page. At that point, a gap of
  64. * 1 << order might not be enough, so it's safer to require twice that
  65. * amount. Note that the number of pages on the list is also
  66. * effectively limited by COMPACT_CLUSTER_MAX, as that's the maximum
  67. * that the migrate scanner can have isolated on migrate list, and free
  68. * scanner is only invoked when the number of isolated free pages is
  69. * lower than that. But it's not worth to complicate the formula here
  70. * as a bigger gap for higher orders than strictly necessary can also
  71. * improve chances of compaction success.
  72. */
  73. return 2UL << order;
  74. }
  75. #ifdef CONFIG_COMPACTION
  76. extern int sysctl_compact_memory;
  77. extern int sysctl_compaction_handler(struct ctl_table *table, int write,
  78. void __user *buffer, size_t *length, loff_t *ppos);
  79. extern int sysctl_extfrag_threshold;
  80. extern int sysctl_extfrag_handler(struct ctl_table *table, int write,
  81. void __user *buffer, size_t *length, loff_t *ppos);
  82. extern int sysctl_compact_unevictable_allowed;
  83. extern int fragmentation_index(struct zone *zone, unsigned int order);
  84. extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
  85. unsigned int order, unsigned int alloc_flags,
  86. const struct alloc_context *ac, enum compact_priority prio);
  87. extern void reset_isolation_suitable(pg_data_t *pgdat);
  88. extern enum compact_result compaction_suitable(struct zone *zone, int order,
  89. unsigned int alloc_flags, int classzone_idx);
  90. extern void defer_compaction(struct zone *zone, int order);
  91. extern bool compaction_deferred(struct zone *zone, int order);
  92. extern void compaction_defer_reset(struct zone *zone, int order,
  93. bool alloc_success);
  94. extern bool compaction_restarting(struct zone *zone, int order);
  95. /* Compaction has made some progress and retrying makes sense */
  96. static inline bool compaction_made_progress(enum compact_result result)
  97. {
  98. /*
  99. * Even though this might sound confusing this in fact tells us
  100. * that the compaction successfully isolated and migrated some
  101. * pageblocks.
  102. */
  103. if (result == COMPACT_SUCCESS)
  104. return true;
  105. return false;
  106. }
  107. /* Compaction has failed and it doesn't make much sense to keep retrying. */
  108. static inline bool compaction_failed(enum compact_result result)
  109. {
  110. /* All zones were scanned completely and still not result. */
  111. if (result == COMPACT_COMPLETE)
  112. return true;
  113. return false;
  114. }
  115. /*
  116. * Compaction has backed off for some reason. It might be throttling or
  117. * lock contention. Retrying is still worthwhile.
  118. */
  119. static inline bool compaction_withdrawn(enum compact_result result)
  120. {
  121. /*
  122. * Compaction backed off due to watermark checks for order-0
  123. * so the regular reclaim has to try harder and reclaim something.
  124. */
  125. if (result == COMPACT_SKIPPED)
  126. return true;
  127. /*
  128. * If compaction is deferred for high-order allocations, it is
  129. * because sync compaction recently failed. If this is the case
  130. * and the caller requested a THP allocation, we do not want
  131. * to heavily disrupt the system, so we fail the allocation
  132. * instead of entering direct reclaim.
  133. */
  134. if (result == COMPACT_DEFERRED)
  135. return true;
  136. /*
  137. * If compaction in async mode encounters contention or blocks higher
  138. * priority task we back off early rather than cause stalls.
  139. */
  140. if (result == COMPACT_CONTENDED)
  141. return true;
  142. /*
  143. * Page scanners have met but we haven't scanned full zones so this
  144. * is a back off in fact.
  145. */
  146. if (result == COMPACT_PARTIAL_SKIPPED)
  147. return true;
  148. return false;
  149. }
  150. bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
  151. int alloc_flags);
  152. extern int kcompactd_run(int nid);
  153. extern void kcompactd_stop(int nid);
  154. extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);
  155. #else
  156. static inline void reset_isolation_suitable(pg_data_t *pgdat)
  157. {
  158. }
  159. static inline enum compact_result compaction_suitable(struct zone *zone, int order,
  160. int alloc_flags, int classzone_idx)
  161. {
  162. return COMPACT_SKIPPED;
  163. }
  164. static inline void defer_compaction(struct zone *zone, int order)
  165. {
  166. }
  167. static inline bool compaction_deferred(struct zone *zone, int order)
  168. {
  169. return true;
  170. }
  171. static inline bool compaction_made_progress(enum compact_result result)
  172. {
  173. return false;
  174. }
  175. static inline bool compaction_failed(enum compact_result result)
  176. {
  177. return false;
  178. }
  179. static inline bool compaction_withdrawn(enum compact_result result)
  180. {
  181. return true;
  182. }
  183. static inline int kcompactd_run(int nid)
  184. {
  185. return 0;
  186. }
  187. static inline void kcompactd_stop(int nid)
  188. {
  189. }
  190. static inline void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx)
  191. {
  192. }
  193. #endif /* CONFIG_COMPACTION */
  194. #if defined(CONFIG_COMPACTION) && defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
  195. struct node;
  196. extern int compaction_register_node(struct node *node);
  197. extern void compaction_unregister_node(struct node *node);
  198. #else
  199. static inline int compaction_register_node(struct node *node)
  200. {
  201. return 0;
  202. }
  203. static inline void compaction_unregister_node(struct node *node)
  204. {
  205. }
  206. #endif /* CONFIG_COMPACTION && CONFIG_SYSFS && CONFIG_NUMA */
  207. #endif /* _LINUX_COMPACTION_H */