• Alexander Duyck's avatar
    mm: adjust shuffle code to allow for future coalescing · a2129f24
    Alexander Duyck authored
    Patch series "mm / virtio: Provide support for free page reporting", v17.
    
    This series provides an asynchronous means of reporting free guest pages
    to a hypervisor so that the memory associated with those pages can be
    dropped and reused by other processes and/or guests on the host.  Using
    this it is possible to avoid unnecessary I/O to disk and greatly improve
    performance in the case of memory overcommit on the host.
    
    When enabled we will be performing a scan of free memory every 2 seconds
    while pages of sufficiently high order are being freed.  In each pass at
    least one sixteenth of each free list will be reported.  By doing this we
    avoid racing against other threads that may be causing a high amount of
    memory churn.
    
    The lowest page order currently scanned when reporting pages is
    pageblock_order so that this feature will not interfere with the use of
    Transparent Huge Pages in the case of virtualization.
    
    Currently this is only in use by virtio-ballo...
    a2129f24
shuffle.h 1.61 KB
// SPDX-License-Identifier: GPL-2.0
// Copyright(c) 2018 Intel Corporation. All rights reserved.
#ifndef _MM_SHUFFLE_H
#define _MM_SHUFFLE_H
#include <linux/jump_label.h>

/*
 * SHUFFLE_ENABLE is called from the command line enabling path, or by
 * platform-firmware enabling that indicates the presence of a
 * direct-mapped memory-side-cache. SHUFFLE_FORCE_DISABLE is called from
 * the command line path and overrides any previous or future
 * SHUFFLE_ENABLE.
 */
enum mm_shuffle_ctl {
	SHUFFLE_ENABLE,
	SHUFFLE_FORCE_DISABLE,
};

#define SHUFFLE_ORDER (MAX_ORDER-1)

#ifdef CONFIG_SHUFFLE_PAGE_ALLOCATOR
DECLARE_STATIC_KEY_FALSE(page_alloc_shuffle_key);
extern void page_alloc_shuffle(enum mm_shuffle_ctl ctl);
extern void __shuffle_free_memory(pg_data_t *pgdat);
extern bool shuffle_pick_tail(void);
static inline void shuffle_free_memory(pg_data_t *pgdat)
{
	if (!static_branch_unlikely(&page_alloc_shuffle_key))
		return;
	__shuffle_free_memory(pgdat);
}

extern void __shuffle_zone(struct zone *z);
static inline void shuffle_zone(struct zone *z)
{
	if (!static_branch_unlikely(&page_alloc_shuffle_key))
		return;
	__shuffle_zone(z);
}

static inline bool is_shuffle_order(int order)
{
	if (!static_branch_unlikely(&page_alloc_shuffle_key))
		return false;
	return order >= SHUFFLE_ORDER;
}
#else
static inline bool shuffle_pick_tail(void)
{
	return false;
}

static inline void shuffle_free_memory(pg_data_t *pgdat)
{
}

static inline void shuffle_zone(struct zone *z)
{
}

static inline void page_alloc_shuffle(enum mm_shuffle_ctl ctl)
{
}

static inline bool is_shuffle_order(int order)
{
	return false;
}
#endif
#endif /* _MM_SHUFFLE_H */