#define pr_fmt(fmt) …
#include <linux/module.h>
#include <linux/cpu.h>
#include <linux/highmem.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/atomic.h>
#include <linux/swap.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/mempolicy.h>
#include <linux/mempool.h>
#include <linux/zpool.h>
#include <crypto/acompress.h>
#include <linux/zswap.h>
#include <linux/mm_types.h>
#include <linux/page-flags.h>
#include <linux/swapops.h>
#include <linux/writeback.h>
#include <linux/pagemap.h>
#include <linux/workqueue.h>
#include <linux/list_lru.h>
#include "swap.h"
#include "internal.h"
atomic_t zswap_stored_pages = …;
static atomic_t zswap_same_filled_pages = …;
static u64 zswap_pool_limit_hit;
static u64 zswap_written_back_pages;
static u64 zswap_reject_reclaim_fail;
static u64 zswap_reject_compress_fail;
static u64 zswap_reject_compress_poor;
static u64 zswap_reject_alloc_fail;
static u64 zswap_reject_kmemcache_fail;
static struct workqueue_struct *shrink_wq;
static bool zswap_pool_reached_full;
#define ZSWAP_PARAM_UNSET …
static int zswap_setup(void);
static DEFINE_STATIC_KEY_MAYBE(CONFIG_ZSWAP_DEFAULT_ON, zswap_ever_enabled);
static bool zswap_enabled = … IS_ENABLED(…);
static int zswap_enabled_param_set(const char *,
const struct kernel_param *);
static const struct kernel_param_ops zswap_enabled_param_ops = …;
module_param_cb(…);
static char *zswap_compressor = …;
static int zswap_compressor_param_set(const char *,
const struct kernel_param *);
static const struct kernel_param_ops zswap_compressor_param_ops = …;
module_param_cb(…);
static char *zswap_zpool_type = …;
static int zswap_zpool_param_set(const char *, const struct kernel_param *);
static const struct kernel_param_ops zswap_zpool_param_ops = …;
module_param_cb(…);
static unsigned int zswap_max_pool_percent = …;
module_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644);
static unsigned int zswap_accept_thr_percent = …;
module_param_named(accept_threshold_percent, zswap_accept_thr_percent,
uint, 0644);
static bool zswap_shrinker_enabled = … IS_ENABLED(…);
module_param_named(shrinker_enabled, zswap_shrinker_enabled, bool, 0644);
bool zswap_is_enabled(void)
{ … }
bool zswap_never_enabled(void)
{ … }
struct crypto_acomp_ctx { … };
struct zswap_pool { … };
static struct list_lru zswap_list_lru;
static DEFINE_SPINLOCK(zswap_shrink_lock);
static struct mem_cgroup *zswap_next_shrink;
static struct work_struct zswap_shrink_work;
static struct shrinker *zswap_shrinker;
struct zswap_entry { … };
static struct xarray *zswap_trees[MAX_SWAPFILES];
static unsigned int nr_zswap_trees[MAX_SWAPFILES];
static LIST_HEAD(zswap_pools);
static DEFINE_SPINLOCK(zswap_pools_lock);
static atomic_t zswap_pools_count = …;
enum zswap_init_type { … };
static enum zswap_init_type zswap_init_state;
static DEFINE_MUTEX(zswap_init_lock);
static bool zswap_has_pool;
static inline struct xarray *swap_zswap_tree(swp_entry_t swp)
{ … }
#define zswap_pool_debug(msg, p) …
static void __zswap_pool_empty(struct percpu_ref *ref);
static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
{ … }
static struct zswap_pool *__zswap_pool_create_fallback(void)
{ … }
static void zswap_pool_destroy(struct zswap_pool *pool)
{ … }
static void __zswap_pool_release(struct work_struct *work)
{ … }
static struct zswap_pool *zswap_pool_current(void);
static void __zswap_pool_empty(struct percpu_ref *ref)
{ … }
static int __must_check zswap_pool_get(struct zswap_pool *pool)
{ … }
static void zswap_pool_put(struct zswap_pool *pool)
{ … }
static struct zswap_pool *__zswap_pool_current(void)
{ … }
static struct zswap_pool *zswap_pool_current(void)
{ … }
static struct zswap_pool *zswap_pool_current_get(void)
{ … }
static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
{ … }
static unsigned long zswap_max_pages(void)
{ … }
static unsigned long zswap_accept_thr_pages(void)
{ … }
unsigned long zswap_total_pages(void)
{ … }
static bool zswap_check_limits(void)
{ … }
static bool zswap_pool_changed(const char *s, const struct kernel_param *kp)
{ … }
static int __zswap_param_set(const char *val, const struct kernel_param *kp,
char *type, char *compressor)
{ … }
static int zswap_compressor_param_set(const char *val,
const struct kernel_param *kp)
{ … }
static int zswap_zpool_param_set(const char *val,
const struct kernel_param *kp)
{ … }
static int zswap_enabled_param_set(const char *val,
const struct kernel_param *kp)
{ … }
#ifdef CONFIG_MEMCG
static inline struct mem_cgroup *mem_cgroup_from_entry(struct zswap_entry *entry)
{ … }
#else
static inline struct mem_cgroup *mem_cgroup_from_entry(struct zswap_entry *entry)
{
return NULL;
}
#endif
static inline int entry_to_nid(struct zswap_entry *entry)
{ … }
static void zswap_lru_add(struct list_lru *list_lru, struct zswap_entry *entry)
{ … }
static void zswap_lru_del(struct list_lru *list_lru, struct zswap_entry *entry)
{ … }
void zswap_lruvec_state_init(struct lruvec *lruvec)
{ … }
void zswap_folio_swapin(struct folio *folio)
{ … }
void zswap_memcg_offline_cleanup(struct mem_cgroup *memcg)
{ … }
static struct kmem_cache *zswap_entry_cache;
static struct zswap_entry *zswap_entry_cache_alloc(gfp_t gfp, int nid)
{ … }
static void zswap_entry_cache_free(struct zswap_entry *entry)
{ … }
static void zswap_entry_free(struct zswap_entry *entry)
{ … }
static int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)
{ … }
static int zswap_cpu_comp_dead(unsigned int cpu, struct hlist_node *node)
{ … }
static bool zswap_compress(struct folio *folio, struct zswap_entry *entry)
{ … }
static void zswap_decompress(struct zswap_entry *entry, struct folio *folio)
{ … }
static int zswap_writeback_entry(struct zswap_entry *entry,
swp_entry_t swpentry)
{ … }
static enum lru_status shrink_memcg_cb(struct list_head *item, struct list_lru_one *l,
spinlock_t *lock, void *arg)
{ … }
static unsigned long zswap_shrinker_scan(struct shrinker *shrinker,
struct shrink_control *sc)
{ … }
static unsigned long zswap_shrinker_count(struct shrinker *shrinker,
struct shrink_control *sc)
{ … }
static struct shrinker *zswap_alloc_shrinker(void)
{ … }
static int shrink_memcg(struct mem_cgroup *memcg)
{ … }
static void shrink_worker(struct work_struct *w)
{ … }
static bool zswap_is_folio_same_filled(struct folio *folio, unsigned long *value)
{ … }
static void zswap_fill_folio(struct folio *folio, unsigned long value)
{ … }
bool zswap_store(struct folio *folio)
{ … }
bool zswap_load(struct folio *folio)
{ … }
void zswap_invalidate(swp_entry_t swp)
{ … }
int zswap_swapon(int type, unsigned long nr_pages)
{ … }
void zswap_swapoff(int type)
{ … }
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
static struct dentry *zswap_debugfs_root;
static int debugfs_get_total_size(void *data, u64 *val)
{ … }
DEFINE_DEBUGFS_ATTRIBUTE(…);
static int zswap_debugfs_init(void)
{ … }
#else
static int zswap_debugfs_init(void)
{
return 0;
}
#endif
static int zswap_setup(void)
{ … }
static int __init zswap_init(void)
{ … }
late_initcall(zswap_init);
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;