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_LIGHT, 10 MIN_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT, 11 DEF_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT, 12 COMPACT_PRIO_ASYNC, 13 INIT_COMPACT_PRIORITY = COMPACT_PRIO_ASYNC 14 }; 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 29 /* compaction not active last round */ 30 COMPACT_INACTIVE = COMPACT_DEFERRED, 31 32 /* For more detailed tracepoint output - internal to compaction */ 33 COMPACT_NO_SUITABLE_PAGE, 34 /* compaction should continue to another pageblock */ 35 COMPACT_CONTINUE, 36 37 /* 38 * The full zone was compacted scanned but wasn't successfull to compact 39 * suitable pages. 40 */ 41 COMPACT_COMPLETE, 42 /* 43 * direct compaction has scanned part of the zone but wasn't successfull 44 * to compact suitable pages. 45 */ 46 COMPACT_PARTIAL_SKIPPED, 47 48 /* compaction terminated prematurely due to lock contentions */ 49 COMPACT_CONTENDED, 50 51 /* 52 * direct compaction partially compacted a zone and there might be 53 * suitable pages 54 */ 55 COMPACT_PARTIAL, 56 }; 57 58 struct alloc_context; /* in mm/internal.h */ 59 60 #ifdef CONFIG_COMPACTION 61 extern int sysctl_compact_memory; 62 extern int sysctl_compaction_handler(struct ctl_table *table, int write, 63 void __user *buffer, size_t *length, loff_t *ppos); 64 extern int sysctl_extfrag_threshold; 65 extern int sysctl_extfrag_handler(struct ctl_table *table, int write, 66 void __user *buffer, size_t *length, loff_t *ppos); 67 extern int sysctl_compact_unevictable_allowed; 68 69 extern int fragmentation_index(struct zone *zone, unsigned int order); 70 extern enum compact_result try_to_compact_pages(gfp_t gfp_mask, 71 unsigned int order, unsigned int alloc_flags, 72 const struct alloc_context *ac, enum compact_priority prio); 73 extern void compact_pgdat(pg_data_t *pgdat, int order); 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_PARTIAL) 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 compact_pgdat(pg_data_t *pgdat, int order) 158 { 159 } 160 161 static inline void reset_isolation_suitable(pg_data_t *pgdat) 162 { 163 } 164 165 static inline enum compact_result compaction_suitable(struct zone *zone, int order, 166 int alloc_flags, int classzone_idx) 167 { 168 return COMPACT_SKIPPED; 169 } 170 171 static inline void defer_compaction(struct zone *zone, int order) 172 { 173 } 174 175 static inline bool compaction_deferred(struct zone *zone, int order) 176 { 177 return true; 178 } 179 180 static inline bool compaction_made_progress(enum compact_result result) 181 { 182 return false; 183 } 184 185 static inline bool compaction_failed(enum compact_result result) 186 { 187 return false; 188 } 189 190 static inline bool compaction_withdrawn(enum compact_result result) 191 { 192 return true; 193 } 194 195 static inline int kcompactd_run(int nid) 196 { 197 return 0; 198 } 199 static inline void kcompactd_stop(int nid) 200 { 201 } 202 203 static inline void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx) 204 { 205 } 206 207 #endif /* CONFIG_COMPACTION */ 208 209 #if defined(CONFIG_COMPACTION) && defined(CONFIG_SYSFS) && defined(CONFIG_NUMA) 210 struct node; 211 extern int compaction_register_node(struct node *node); 212 extern void compaction_unregister_node(struct node *node); 213 214 #else 215 216 static inline int compaction_register_node(struct node *node) 217 { 218 return 0; 219 } 220 221 static inline void compaction_unregister_node(struct node *node) 222 { 223 } 224 #endif /* CONFIG_COMPACTION && CONFIG_SYSFS && CONFIG_NUMA */ 225 226 #endif /* _LINUX_COMPACTION_H */ 227