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