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