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