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        /* 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 successful to compact
  39         * suitable pages.
  40         */
  41        COMPACT_COMPLETE,
  42        /*
  43         * direct compaction has scanned part of the zone but wasn't successful
  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 terminated after concluding that the allocation
  53         * should now succeed
  54         */
  55        COMPACT_SUCCESS,
  56};
  57
  58struct alloc_context; /* in mm/internal.h */
  59
  60/*
  61 * Number of free order-0 pages that should be available above given watermark
  62 * to make sure compaction has reasonable chance of not running out of free
  63 * pages that it needs to isolate as migration target during its work.
  64 */
  65static inline unsigned long compact_gap(unsigned int order)
  66{
  67        /*
  68         * Although all the isolations for migration are temporary, compaction
  69         * free scanner may have up to 1 << order pages on its list and then
  70         * try to split an (order - 1) free page. At that point, a gap of
  71         * 1 << order might not be enough, so it's safer to require twice that
  72         * amount. Note that the number of pages on the list is also
  73         * effectively limited by COMPACT_CLUSTER_MAX, as that's the maximum
  74         * that the migrate scanner can have isolated on migrate list, and free
  75         * scanner is only invoked when the number of isolated free pages is
  76         * lower than that. But it's not worth to complicate the formula here
  77         * as a bigger gap for higher orders than strictly necessary can also
  78         * improve chances of compaction success.
  79         */
  80        return 2UL << order;
  81}
  82
  83#ifdef CONFIG_COMPACTION
  84extern unsigned int sysctl_compaction_proactiveness;
  85extern int sysctl_compaction_handler(struct ctl_table *table, int write,
  86                        void *buffer, size_t *length, loff_t *ppos);
  87extern int compaction_proactiveness_sysctl_handler(struct ctl_table *table,
  88                int write, void *buffer, size_t *length, loff_t *ppos);
  89extern int sysctl_extfrag_threshold;
  90extern int sysctl_compact_unevictable_allowed;
  91
  92extern unsigned int extfrag_for_order(struct zone *zone, unsigned int order);
  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 highest_zoneidx);
 101
 102extern void compaction_defer_reset(struct zone *zone, int order,
 103                                bool alloc_success);
 104
 105/* Compaction has made some progress and retrying makes sense */
 106static inline bool compaction_made_progress(enum compact_result result)
 107{
 108        /*
 109         * Even though this might sound confusing this in fact tells us
 110         * that the compaction successfully isolated and migrated some
 111         * pageblocks.
 112         */
 113        if (result == COMPACT_SUCCESS)
 114                return true;
 115
 116        return false;
 117}
 118
 119/* Compaction has failed and it doesn't make much sense to keep retrying. */
 120static inline bool compaction_failed(enum compact_result result)
 121{
 122        /* All zones were scanned completely and still not result. */
 123        if (result == COMPACT_COMPLETE)
 124                return true;
 125
 126        return false;
 127}
 128
 129/* Compaction needs reclaim to be performed first, so it can continue. */
 130static inline bool compaction_needs_reclaim(enum compact_result result)
 131{
 132        /*
 133         * Compaction backed off due to watermark checks for order-0
 134         * so the regular reclaim has to try harder and reclaim something.
 135         */
 136        if (result == COMPACT_SKIPPED)
 137                return true;
 138
 139        return false;
 140}
 141
 142/*
 143 * Compaction has backed off for some reason after doing some work or none
 144 * at all. It might be throttling or lock contention. Retrying might be still
 145 * worthwhile, but with a higher priority if allowed.
 146 */
 147static inline bool compaction_withdrawn(enum compact_result result)
 148{
 149        /*
 150         * If compaction is deferred for high-order allocations, it is
 151         * because sync compaction recently failed. If this is the case
 152         * and the caller requested a THP allocation, we do not want
 153         * to heavily disrupt the system, so we fail the allocation
 154         * instead of entering direct reclaim.
 155         */
 156        if (result == COMPACT_DEFERRED)
 157                return true;
 158
 159        /*
 160         * If compaction in async mode encounters contention or blocks higher
 161         * priority task we back off early rather than cause stalls.
 162         */
 163        if (result == COMPACT_CONTENDED)
 164                return true;
 165
 166        /*
 167         * Page scanners have met but we haven't scanned full zones so this
 168         * is a back off in fact.
 169         */
 170        if (result == COMPACT_PARTIAL_SKIPPED)
 171                return true;
 172
 173        return false;
 174}
 175
 176
 177bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
 178                                        int alloc_flags);
 179
 180extern int kcompactd_run(int nid);
 181extern void kcompactd_stop(int nid);
 182extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx);
 183
 184#else
 185static inline void reset_isolation_suitable(pg_data_t *pgdat)
 186{
 187}
 188
 189static inline enum compact_result compaction_suitable(struct zone *zone, int order,
 190                                        int alloc_flags, int highest_zoneidx)
 191{
 192        return COMPACT_SKIPPED;
 193}
 194
 195static inline bool compaction_made_progress(enum compact_result result)
 196{
 197        return false;
 198}
 199
 200static inline bool compaction_failed(enum compact_result result)
 201{
 202        return false;
 203}
 204
 205static inline bool compaction_needs_reclaim(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,
 224                                int order, int highest_zoneidx)
 225{
 226}
 227
 228#endif /* CONFIG_COMPACTION */
 229
 230struct node;
 231#if defined(CONFIG_COMPACTION) && defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
 232extern int compaction_register_node(struct node *node);
 233extern void compaction_unregister_node(struct node *node);
 234
 235#else
 236
 237static inline int compaction_register_node(struct node *node)
 238{
 239        return 0;
 240}
 241
 242static inline void compaction_unregister_node(struct node *node)
 243{
 244}
 245#endif /* CONFIG_COMPACTION && CONFIG_SYSFS && CONFIG_NUMA */
 246
 247#endif /* _LINUX_COMPACTION_H */
 248