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