diff options
Diffstat (limited to 'include/linux/compaction.h')
| -rw-r--r-- | include/linux/compaction.h | 151 | 
1 files changed, 130 insertions, 21 deletions
| diff --git a/include/linux/compaction.h b/include/linux/compaction.h index d7c8de583a23..a58c852a268f 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -2,21 +2,46 @@  #define _LINUX_COMPACTION_H  /* Return values for compact_zone() and try_to_compact_pages() */ -/* compaction didn't start as it was deferred due to past failures */ -#define COMPACT_DEFERRED	0 -/* compaction didn't start as it was not possible or direct reclaim was more suitable */ -#define COMPACT_SKIPPED		1 -/* compaction should continue to another pageblock */ -#define COMPACT_CONTINUE	2 -/* direct compaction partially compacted a zone and there are suitable pages */ -#define COMPACT_PARTIAL		3 -/* The full zone was compacted */ -#define COMPACT_COMPLETE	4 -/* For more detailed tracepoint output */ -#define COMPACT_NO_SUITABLE_PAGE	5 -#define COMPACT_NOT_SUITABLE_ZONE	6 -#define COMPACT_CONTENDED		7  /* When adding new states, please adjust include/trace/events/compaction.h */ +enum compact_result { +	/* For more detailed tracepoint output - internal to compaction */ +	COMPACT_NOT_SUITABLE_ZONE, +	/* +	 * compaction didn't start as it was not possible or direct reclaim +	 * was more suitable +	 */ +	COMPACT_SKIPPED, +	/* compaction didn't start as it was deferred due to past failures */ +	COMPACT_DEFERRED, + +	/* compaction not active last round */ +	COMPACT_INACTIVE = COMPACT_DEFERRED, + +	/* For more detailed tracepoint output - internal to compaction */ +	COMPACT_NO_SUITABLE_PAGE, +	/* compaction should continue to another pageblock */ +	COMPACT_CONTINUE, + +	/* +	 * The full zone was compacted scanned but wasn't successfull to compact +	 * suitable pages. +	 */ +	COMPACT_COMPLETE, +	/* +	 * direct compaction has scanned part of the zone but wasn't successfull +	 * to compact suitable pages. +	 */ +	COMPACT_PARTIAL_SKIPPED, + +	/* compaction terminated prematurely due to lock contentions */ +	COMPACT_CONTENDED, + +	/* +	 * direct compaction partially compacted a zone and there might be +	 * suitable pages +	 */ +	COMPACT_PARTIAL, +};  /* Used to signal whether compaction detected need_sched() or lock contention */  /* No contention detected */ @@ -38,13 +63,14 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write,  extern int sysctl_compact_unevictable_allowed;  extern int fragmentation_index(struct zone *zone, unsigned int order); -extern unsigned long try_to_compact_pages(gfp_t gfp_mask, unsigned int order, -			int alloc_flags, const struct alloc_context *ac, -			enum migrate_mode mode, int *contended); +extern enum compact_result try_to_compact_pages(gfp_t gfp_mask, +			unsigned int order, +		unsigned int alloc_flags, const struct alloc_context *ac, +		enum migrate_mode mode, int *contended);  extern void compact_pgdat(pg_data_t *pgdat, int order);  extern void reset_isolation_suitable(pg_data_t *pgdat); -extern unsigned long compaction_suitable(struct zone *zone, int order, -					int alloc_flags, int classzone_idx); +extern enum compact_result compaction_suitable(struct zone *zone, int order, +		unsigned int alloc_flags, int classzone_idx);  extern void defer_compaction(struct zone *zone, int order);  extern bool compaction_deferred(struct zone *zone, int order); @@ -52,12 +78,80 @@ extern void compaction_defer_reset(struct zone *zone, int order,  				bool alloc_success);  extern bool compaction_restarting(struct zone *zone, int order); +/* Compaction has made some progress and retrying makes sense */ +static inline bool compaction_made_progress(enum compact_result result) +{ +	/* +	 * Even though this might sound confusing this in fact tells us +	 * that the compaction successfully isolated and migrated some +	 * pageblocks. +	 */ +	if (result == COMPACT_PARTIAL) +		return true; + +	return false; +} + +/* Compaction has failed and it doesn't make much sense to keep retrying. */ +static inline bool compaction_failed(enum compact_result result) +{ +	/* All zones were scanned completely and still not result. */ +	if (result == COMPACT_COMPLETE) +		return true; + +	return false; +} + +/* + * Compaction  has backed off for some reason. It might be throttling or + * lock contention. Retrying is still worthwhile. + */ +static inline bool compaction_withdrawn(enum compact_result result) +{ +	/* +	 * Compaction backed off due to watermark checks for order-0 +	 * so the regular reclaim has to try harder and reclaim something. +	 */ +	if (result == COMPACT_SKIPPED) +		return true; + +	/* +	 * If compaction is deferred for high-order allocations, it is +	 * because sync compaction recently failed. If this is the case +	 * and the caller requested a THP allocation, we do not want +	 * to heavily disrupt the system, so we fail the allocation +	 * instead of entering direct reclaim. +	 */ +	if (result == COMPACT_DEFERRED) +		return true; + +	/* +	 * If compaction in async mode encounters contention or blocks higher +	 * priority task we back off early rather than cause stalls. +	 */ +	if (result == COMPACT_CONTENDED) +		return true; + +	/* +	 * Page scanners have met but we haven't scanned full zones so this +	 * is a back off in fact. +	 */ +	if (result == COMPACT_PARTIAL_SKIPPED) +		return true; + +	return false; +} + + +bool compaction_zonelist_suitable(struct alloc_context *ac, int order, +					int alloc_flags); +  extern int kcompactd_run(int nid);  extern void kcompactd_stop(int nid);  extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx);  #else -static inline unsigned long try_to_compact_pages(gfp_t gfp_mask, +static inline enum compact_result try_to_compact_pages(gfp_t gfp_mask,  			unsigned int order, int alloc_flags,  			const struct alloc_context *ac,  			enum migrate_mode mode, int *contended) @@ -73,7 +167,7 @@ static inline void reset_isolation_suitable(pg_data_t *pgdat)  {  } -static inline unsigned long compaction_suitable(struct zone *zone, int order, +static inline enum compact_result compaction_suitable(struct zone *zone, int order,  					int alloc_flags, int classzone_idx)  {  	return COMPACT_SKIPPED; @@ -88,6 +182,21 @@ static inline bool compaction_deferred(struct zone *zone, int order)  	return true;  } +static inline bool compaction_made_progress(enum compact_result result) +{ +	return false; +} + +static inline bool compaction_failed(enum compact_result result) +{ +	return false; +} + +static inline bool compaction_withdrawn(enum compact_result result) +{ +	return true; +} +  static inline int kcompactd_run(int nid)  {  	return 0; |