xref: /linux-6.15/include/linux/compaction.h (revision 67914ac0)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2748446bbSMel Gorman #ifndef _LINUX_COMPACTION_H
3748446bbSMel Gorman #define _LINUX_COMPACTION_H
4748446bbSMel Gorman 
5a5508cd8SVlastimil Babka /*
6a5508cd8SVlastimil Babka  * Determines how hard direct compaction should try to succeed.
7a5508cd8SVlastimil Babka  * Lower value means higher priority, analogically to reclaim priority.
8a5508cd8SVlastimil Babka  */
9a5508cd8SVlastimil Babka enum compact_priority {
10a8e025e5SVlastimil Babka 	COMPACT_PRIO_SYNC_FULL,
11a8e025e5SVlastimil Babka 	MIN_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_FULL,
12a5508cd8SVlastimil Babka 	COMPACT_PRIO_SYNC_LIGHT,
13c2033b00SVlastimil Babka 	MIN_COMPACT_COSTLY_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
14a5508cd8SVlastimil Babka 	DEF_COMPACT_PRIORITY = COMPACT_PRIO_SYNC_LIGHT,
15a5508cd8SVlastimil Babka 	COMPACT_PRIO_ASYNC,
16a5508cd8SVlastimil Babka 	INIT_COMPACT_PRIORITY = COMPACT_PRIO_ASYNC
17a5508cd8SVlastimil Babka };
18a5508cd8SVlastimil Babka 
1956de7263SMel Gorman /* Return values for compact_zone() and try_to_compact_pages() */
20fa6c7b46SVlastimil Babka /* When adding new states, please adjust include/trace/events/compaction.h */
21ea7ab982SMichal Hocko enum compact_result {
224f9a358cSMichal Hocko 	/* For more detailed tracepoint output - internal to compaction */
234f9a358cSMichal Hocko 	COMPACT_NOT_SUITABLE_ZONE,
24ea7ab982SMichal Hocko 	/*
25ea7ab982SMichal Hocko 	 * compaction didn't start as it was not possible or direct reclaim
26ea7ab982SMichal Hocko 	 * was more suitable
27ea7ab982SMichal Hocko 	 */
28ea7ab982SMichal Hocko 	COMPACT_SKIPPED,
291d4746d3SMichal Hocko 	/* compaction didn't start as it was deferred due to past failures */
301d4746d3SMichal Hocko 	COMPACT_DEFERRED,
314f9a358cSMichal Hocko 
324f9a358cSMichal Hocko 	/* For more detailed tracepoint output - internal to compaction */
334f9a358cSMichal Hocko 	COMPACT_NO_SUITABLE_PAGE,
34ea7ab982SMichal Hocko 	/* compaction should continue to another pageblock */
35ea7ab982SMichal Hocko 	COMPACT_CONTINUE,
364f9a358cSMichal Hocko 
37c8f7de0bSMichal Hocko 	/*
3806c88398SZhen Lei 	 * The full zone was compacted scanned but wasn't successful to compact
39c8f7de0bSMichal Hocko 	 * suitable pages.
40c8f7de0bSMichal Hocko 	 */
41ea7ab982SMichal Hocko 	COMPACT_COMPLETE,
424f9a358cSMichal Hocko 	/*
4306c88398SZhen Lei 	 * direct compaction has scanned part of the zone but wasn't successful
444f9a358cSMichal Hocko 	 * to compact suitable pages.
454f9a358cSMichal Hocko 	 */
464f9a358cSMichal Hocko 	COMPACT_PARTIAL_SKIPPED,
474f9a358cSMichal Hocko 
484f9a358cSMichal Hocko 	/* compaction terminated prematurely due to lock contentions */
49ea7ab982SMichal Hocko 	COMPACT_CONTENDED,
504f9a358cSMichal Hocko 
514f9a358cSMichal Hocko 	/*
52cf378319SVlastimil Babka 	 * direct compaction terminated after concluding that the allocation
53cf378319SVlastimil Babka 	 * should now succeed
544f9a358cSMichal Hocko 	 */
55cf378319SVlastimil Babka 	COMPACT_SUCCESS,
56ea7ab982SMichal Hocko };
57748446bbSMel Gorman 
581a6d53a1SVlastimil Babka struct alloc_context; /* in mm/internal.h */
591a6d53a1SVlastimil Babka 
609861a62cSVlastimil Babka /*
619861a62cSVlastimil Babka  * Number of free order-0 pages that should be available above given watermark
629861a62cSVlastimil Babka  * to make sure compaction has reasonable chance of not running out of free
639861a62cSVlastimil Babka  * pages that it needs to isolate as migration target during its work.
649861a62cSVlastimil Babka  */
compact_gap(unsigned int order)659861a62cSVlastimil Babka static inline unsigned long compact_gap(unsigned int order)
669861a62cSVlastimil Babka {
679861a62cSVlastimil Babka 	/*
689861a62cSVlastimil Babka 	 * Although all the isolations for migration are temporary, compaction
699861a62cSVlastimil Babka 	 * free scanner may have up to 1 << order pages on its list and then
709861a62cSVlastimil Babka 	 * try to split an (order - 1) free page. At that point, a gap of
719861a62cSVlastimil Babka 	 * 1 << order might not be enough, so it's safer to require twice that
729861a62cSVlastimil Babka 	 * amount. Note that the number of pages on the list is also
739861a62cSVlastimil Babka 	 * effectively limited by COMPACT_CLUSTER_MAX, as that's the maximum
749861a62cSVlastimil Babka 	 * that the migrate scanner can have isolated on migrate list, and free
759861a62cSVlastimil Babka 	 * scanner is only invoked when the number of isolated free pages is
769861a62cSVlastimil Babka 	 * lower than that. But it's not worth to complicate the formula here
779861a62cSVlastimil Babka 	 * as a bigger gap for higher orders than strictly necessary can also
789861a62cSVlastimil Babka 	 * improve chances of compaction success.
799861a62cSVlastimil Babka 	 */
809861a62cSVlastimil Babka 	return 2UL << order;
819861a62cSVlastimil Babka }
829861a62cSVlastimil Babka 
current_is_kcompactd(void)83ce6d9c1cSMike Snitzer static inline int current_is_kcompactd(void)
84ce6d9c1cSMike Snitzer {
85ce6d9c1cSMike Snitzer 	return current->flags & PF_KCOMPACTD;
86ce6d9c1cSMike Snitzer }
87ce6d9c1cSMike Snitzer 
8876ab0f53SMel Gorman #ifdef CONFIG_COMPACTION
8956de7263SMel Gorman 
90d34c0a75SNitin Gupta extern unsigned int extfrag_for_order(struct zone *zone, unsigned int order);
9156de7263SMel Gorman extern int fragmentation_index(struct zone *zone, unsigned int order);
92ea7ab982SMichal Hocko extern enum compact_result try_to_compact_pages(gfp_t gfp_mask,
93c3486f53SVlastimil Babka 		unsigned int order, unsigned int alloc_flags,
945e1f0f09SMel Gorman 		const struct alloc_context *ac, enum compact_priority prio,
955e1f0f09SMel Gorman 		struct page **page);
9662997027SMel Gorman extern void reset_isolation_suitable(pg_data_t *pgdat);
973cf04937SJohannes Weiner extern bool compaction_suitable(struct zone *zone, int order,
98*67914ac0SJohannes Weiner 				unsigned long watermark, int highest_zoneidx);
994f92e258SMel Gorman 
10024e2716fSJoonsoo Kim extern void compaction_defer_reset(struct zone *zone, int order,
10124e2716fSJoonsoo Kim 				bool alloc_success);
10262997027SMel Gorman 
10386a294a8SMichal Hocko bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
10486a294a8SMichal Hocko 					int alloc_flags);
10586a294a8SMichal Hocko 
106833dfc00SMiaohe Lin extern void __meminit kcompactd_run(int nid);
107833dfc00SMiaohe Lin extern void __meminit kcompactd_stop(int nid);
10897a225e6SJoonsoo Kim extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx);
109698b1b30SVlastimil Babka 
11056de7263SMel Gorman #else
reset_isolation_suitable(pg_data_t * pgdat)11162997027SMel Gorman static inline void reset_isolation_suitable(pg_data_t *pgdat)
11262997027SMel Gorman {
11362997027SMel Gorman }
11462997027SMel Gorman 
compaction_suitable(struct zone * zone,int order,unsigned long watermark,int highest_zoneidx)1153cf04937SJohannes Weiner static inline bool compaction_suitable(struct zone *zone, int order,
116*67914ac0SJohannes Weiner 				       unsigned long watermark,
117e8606320SJohannes Weiner 				       int highest_zoneidx)
1183e7d3449SMel Gorman {
1193cf04937SJohannes Weiner 	return false;
1203e7d3449SMel Gorman }
1213e7d3449SMel Gorman 
kcompactd_run(int nid)122024c61eaSMiaohe Lin static inline void kcompactd_run(int nid)
123698b1b30SVlastimil Babka {
124698b1b30SVlastimil Babka }
kcompactd_stop(int nid)125698b1b30SVlastimil Babka static inline void kcompactd_stop(int nid)
126698b1b30SVlastimil Babka {
127698b1b30SVlastimil Babka }
128698b1b30SVlastimil Babka 
wakeup_kcompactd(pg_data_t * pgdat,int order,int highest_zoneidx)12997a225e6SJoonsoo Kim static inline void wakeup_kcompactd(pg_data_t *pgdat,
13097a225e6SJoonsoo Kim 				int order, int highest_zoneidx)
131698b1b30SVlastimil Babka {
132698b1b30SVlastimil Babka }
133698b1b30SVlastimil Babka 
13476ab0f53SMel Gorman #endif /* CONFIG_COMPACTION */
13576ab0f53SMel Gorman 
136bda807d4SMinchan Kim struct node;
137ace451ebSYu Zhao #if defined(CONFIG_COMPACTION) && defined(CONFIG_SYSFS) && defined(CONFIG_NUMA)
138ed4a6d7fSMel Gorman extern int compaction_register_node(struct node *node);
139ed4a6d7fSMel Gorman extern void compaction_unregister_node(struct node *node);
140ed4a6d7fSMel Gorman 
141ed4a6d7fSMel Gorman #else
142ed4a6d7fSMel Gorman 
compaction_register_node(struct node * node)143ed4a6d7fSMel Gorman static inline int compaction_register_node(struct node *node)
144ed4a6d7fSMel Gorman {
145ed4a6d7fSMel Gorman 	return 0;
146ed4a6d7fSMel Gorman }
147ed4a6d7fSMel Gorman 
compaction_unregister_node(struct node * node)148ed4a6d7fSMel Gorman static inline void compaction_unregister_node(struct node *node)
149ed4a6d7fSMel Gorman {
150ed4a6d7fSMel Gorman }
151ed4a6d7fSMel Gorman #endif /* CONFIG_COMPACTION && CONFIG_SYSFS && CONFIG_NUMA */
152ed4a6d7fSMel Gorman 
153748446bbSMel Gorman #endif /* _LINUX_COMPACTION_H */
154