linux/include/linux/compaction.h
<<
>>
Prefs
   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 */
   9enum 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 */
  21enum 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
  61struct 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 */
  68static 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        return 2UL << order;
  84}
  85
  86#ifdef CONFIG_COMPACTION
  87extern int sysctl_compact_memory;
  88extern int sysctl_compaction_handler(struct ctl_table *table, int write,
  89                        void __user *buffer, size_t *length, loff_t *ppos);
  90extern int sysctl_extfrag_threshold;
  91extern int sysctl_compact_unevictable_allowed;
  92
  93extern int fragmentation_index(struct zone *zone, unsigned int order);
  94extern 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);
  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
 229struct node;
 230#if defined(CONFIG_COMPACTION) && defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
 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