162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * zswap.c - zswap driver file
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * zswap is a cache that takes pages that are in the process
662306a36Sopenharmony_ci * of being swapped out and attempts to compress and store them in a
762306a36Sopenharmony_ci * RAM-based memory pool.  This can result in a significant I/O reduction on
862306a36Sopenharmony_ci * the swap device and, in the case where decompressing from RAM is faster
962306a36Sopenharmony_ci * than reading from the swap device, can also improve workload performance.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Copyright (C) 2012  Seth Jennings <sjenning@linux.vnet.ibm.com>
1262306a36Sopenharmony_ci*/
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/cpu.h>
1862306a36Sopenharmony_ci#include <linux/highmem.h>
1962306a36Sopenharmony_ci#include <linux/slab.h>
2062306a36Sopenharmony_ci#include <linux/spinlock.h>
2162306a36Sopenharmony_ci#include <linux/types.h>
2262306a36Sopenharmony_ci#include <linux/atomic.h>
2362306a36Sopenharmony_ci#include <linux/rbtree.h>
2462306a36Sopenharmony_ci#include <linux/swap.h>
2562306a36Sopenharmony_ci#include <linux/crypto.h>
2662306a36Sopenharmony_ci#include <linux/scatterlist.h>
2762306a36Sopenharmony_ci#include <linux/mempool.h>
2862306a36Sopenharmony_ci#include <linux/zpool.h>
2962306a36Sopenharmony_ci#include <crypto/acompress.h>
3062306a36Sopenharmony_ci#include <linux/zswap.h>
3162306a36Sopenharmony_ci#include <linux/mm_types.h>
3262306a36Sopenharmony_ci#include <linux/page-flags.h>
3362306a36Sopenharmony_ci#include <linux/swapops.h>
3462306a36Sopenharmony_ci#include <linux/writeback.h>
3562306a36Sopenharmony_ci#include <linux/pagemap.h>
3662306a36Sopenharmony_ci#include <linux/workqueue.h>
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include "swap.h"
3962306a36Sopenharmony_ci#include "internal.h"
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*********************************
4262306a36Sopenharmony_ci* statistics
4362306a36Sopenharmony_ci**********************************/
4462306a36Sopenharmony_ci/* Total bytes used by the compressed storage */
4562306a36Sopenharmony_ciu64 zswap_pool_total_size;
4662306a36Sopenharmony_ci/* The number of compressed pages currently stored in zswap */
4762306a36Sopenharmony_ciatomic_t zswap_stored_pages = ATOMIC_INIT(0);
4862306a36Sopenharmony_ci/* The number of same-value filled pages currently stored in zswap */
4962306a36Sopenharmony_cistatic atomic_t zswap_same_filled_pages = ATOMIC_INIT(0);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * The statistics below are not protected from concurrent access for
5362306a36Sopenharmony_ci * performance reasons so they may not be a 100% accurate.  However,
5462306a36Sopenharmony_ci * they do provide useful information on roughly how many times a
5562306a36Sopenharmony_ci * certain event is occurring.
5662306a36Sopenharmony_ci*/
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* Pool limit was hit (see zswap_max_pool_percent) */
5962306a36Sopenharmony_cistatic u64 zswap_pool_limit_hit;
6062306a36Sopenharmony_ci/* Pages written back when pool limit was reached */
6162306a36Sopenharmony_cistatic u64 zswap_written_back_pages;
6262306a36Sopenharmony_ci/* Store failed due to a reclaim failure after pool limit was reached */
6362306a36Sopenharmony_cistatic u64 zswap_reject_reclaim_fail;
6462306a36Sopenharmony_ci/* Compressed page was too big for the allocator to (optimally) store */
6562306a36Sopenharmony_cistatic u64 zswap_reject_compress_poor;
6662306a36Sopenharmony_ci/* Store failed because underlying allocator could not get memory */
6762306a36Sopenharmony_cistatic u64 zswap_reject_alloc_fail;
6862306a36Sopenharmony_ci/* Store failed because the entry metadata could not be allocated (rare) */
6962306a36Sopenharmony_cistatic u64 zswap_reject_kmemcache_fail;
7062306a36Sopenharmony_ci/* Duplicate store was encountered (rare) */
7162306a36Sopenharmony_cistatic u64 zswap_duplicate_entry;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* Shrinker work queue */
7462306a36Sopenharmony_cistatic struct workqueue_struct *shrink_wq;
7562306a36Sopenharmony_ci/* Pool limit was hit, we need to calm down */
7662306a36Sopenharmony_cistatic bool zswap_pool_reached_full;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/*********************************
7962306a36Sopenharmony_ci* tunables
8062306a36Sopenharmony_ci**********************************/
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define ZSWAP_PARAM_UNSET ""
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic int zswap_setup(void);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/* Enable/disable zswap */
8762306a36Sopenharmony_cistatic bool zswap_enabled = IS_ENABLED(CONFIG_ZSWAP_DEFAULT_ON);
8862306a36Sopenharmony_cistatic int zswap_enabled_param_set(const char *,
8962306a36Sopenharmony_ci				   const struct kernel_param *);
9062306a36Sopenharmony_cistatic const struct kernel_param_ops zswap_enabled_param_ops = {
9162306a36Sopenharmony_ci	.set =		zswap_enabled_param_set,
9262306a36Sopenharmony_ci	.get =		param_get_bool,
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_cimodule_param_cb(enabled, &zswap_enabled_param_ops, &zswap_enabled, 0644);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* Crypto compressor to use */
9762306a36Sopenharmony_cistatic char *zswap_compressor = CONFIG_ZSWAP_COMPRESSOR_DEFAULT;
9862306a36Sopenharmony_cistatic int zswap_compressor_param_set(const char *,
9962306a36Sopenharmony_ci				      const struct kernel_param *);
10062306a36Sopenharmony_cistatic const struct kernel_param_ops zswap_compressor_param_ops = {
10162306a36Sopenharmony_ci	.set =		zswap_compressor_param_set,
10262306a36Sopenharmony_ci	.get =		param_get_charp,
10362306a36Sopenharmony_ci	.free =		param_free_charp,
10462306a36Sopenharmony_ci};
10562306a36Sopenharmony_cimodule_param_cb(compressor, &zswap_compressor_param_ops,
10662306a36Sopenharmony_ci		&zswap_compressor, 0644);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci/* Compressed storage zpool to use */
10962306a36Sopenharmony_cistatic char *zswap_zpool_type = CONFIG_ZSWAP_ZPOOL_DEFAULT;
11062306a36Sopenharmony_cistatic int zswap_zpool_param_set(const char *, const struct kernel_param *);
11162306a36Sopenharmony_cistatic const struct kernel_param_ops zswap_zpool_param_ops = {
11262306a36Sopenharmony_ci	.set =		zswap_zpool_param_set,
11362306a36Sopenharmony_ci	.get =		param_get_charp,
11462306a36Sopenharmony_ci	.free =		param_free_charp,
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_cimodule_param_cb(zpool, &zswap_zpool_param_ops, &zswap_zpool_type, 0644);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/* The maximum percentage of memory that the compressed pool can occupy */
11962306a36Sopenharmony_cistatic unsigned int zswap_max_pool_percent = 20;
12062306a36Sopenharmony_cimodule_param_named(max_pool_percent, zswap_max_pool_percent, uint, 0644);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/* The threshold for accepting new pages after the max_pool_percent was hit */
12362306a36Sopenharmony_cistatic unsigned int zswap_accept_thr_percent = 90; /* of max pool size */
12462306a36Sopenharmony_cimodule_param_named(accept_threshold_percent, zswap_accept_thr_percent,
12562306a36Sopenharmony_ci		   uint, 0644);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/*
12862306a36Sopenharmony_ci * Enable/disable handling same-value filled pages (enabled by default).
12962306a36Sopenharmony_ci * If disabled every page is considered non-same-value filled.
13062306a36Sopenharmony_ci */
13162306a36Sopenharmony_cistatic bool zswap_same_filled_pages_enabled = true;
13262306a36Sopenharmony_cimodule_param_named(same_filled_pages_enabled, zswap_same_filled_pages_enabled,
13362306a36Sopenharmony_ci		   bool, 0644);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/* Enable/disable handling non-same-value filled pages (enabled by default) */
13662306a36Sopenharmony_cistatic bool zswap_non_same_filled_pages_enabled = true;
13762306a36Sopenharmony_cimodule_param_named(non_same_filled_pages_enabled, zswap_non_same_filled_pages_enabled,
13862306a36Sopenharmony_ci		   bool, 0644);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic bool zswap_exclusive_loads_enabled = IS_ENABLED(
14162306a36Sopenharmony_ci		CONFIG_ZSWAP_EXCLUSIVE_LOADS_DEFAULT_ON);
14262306a36Sopenharmony_cimodule_param_named(exclusive_loads, zswap_exclusive_loads_enabled, bool, 0644);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/* Number of zpools in zswap_pool (empirically determined for scalability) */
14562306a36Sopenharmony_ci#define ZSWAP_NR_ZPOOLS 32
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/*********************************
14862306a36Sopenharmony_ci* data structures
14962306a36Sopenharmony_ci**********************************/
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistruct crypto_acomp_ctx {
15262306a36Sopenharmony_ci	struct crypto_acomp *acomp;
15362306a36Sopenharmony_ci	struct acomp_req *req;
15462306a36Sopenharmony_ci	struct crypto_wait wait;
15562306a36Sopenharmony_ci	u8 *dstmem;
15662306a36Sopenharmony_ci	struct mutex *mutex;
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/*
16062306a36Sopenharmony_ci * The lock ordering is zswap_tree.lock -> zswap_pool.lru_lock.
16162306a36Sopenharmony_ci * The only case where lru_lock is not acquired while holding tree.lock is
16262306a36Sopenharmony_ci * when a zswap_entry is taken off the lru for writeback, in that case it
16362306a36Sopenharmony_ci * needs to be verified that it's still valid in the tree.
16462306a36Sopenharmony_ci */
16562306a36Sopenharmony_cistruct zswap_pool {
16662306a36Sopenharmony_ci	struct zpool *zpools[ZSWAP_NR_ZPOOLS];
16762306a36Sopenharmony_ci	struct crypto_acomp_ctx __percpu *acomp_ctx;
16862306a36Sopenharmony_ci	struct kref kref;
16962306a36Sopenharmony_ci	struct list_head list;
17062306a36Sopenharmony_ci	struct work_struct release_work;
17162306a36Sopenharmony_ci	struct work_struct shrink_work;
17262306a36Sopenharmony_ci	struct hlist_node node;
17362306a36Sopenharmony_ci	char tfm_name[CRYPTO_MAX_ALG_NAME];
17462306a36Sopenharmony_ci	struct list_head lru;
17562306a36Sopenharmony_ci	spinlock_t lru_lock;
17662306a36Sopenharmony_ci};
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/*
17962306a36Sopenharmony_ci * struct zswap_entry
18062306a36Sopenharmony_ci *
18162306a36Sopenharmony_ci * This structure contains the metadata for tracking a single compressed
18262306a36Sopenharmony_ci * page within zswap.
18362306a36Sopenharmony_ci *
18462306a36Sopenharmony_ci * rbnode - links the entry into red-black tree for the appropriate swap type
18562306a36Sopenharmony_ci * swpentry - associated swap entry, the offset indexes into the red-black tree
18662306a36Sopenharmony_ci * refcount - the number of outstanding reference to the entry. This is needed
18762306a36Sopenharmony_ci *            to protect against premature freeing of the entry by code
18862306a36Sopenharmony_ci *            concurrent calls to load, invalidate, and writeback.  The lock
18962306a36Sopenharmony_ci *            for the zswap_tree structure that contains the entry must
19062306a36Sopenharmony_ci *            be held while changing the refcount.  Since the lock must
19162306a36Sopenharmony_ci *            be held, there is no reason to also make refcount atomic.
19262306a36Sopenharmony_ci * length - the length in bytes of the compressed page data.  Needed during
19362306a36Sopenharmony_ci *          decompression. For a same value filled page length is 0, and both
19462306a36Sopenharmony_ci *          pool and lru are invalid and must be ignored.
19562306a36Sopenharmony_ci * pool - the zswap_pool the entry's data is in
19662306a36Sopenharmony_ci * handle - zpool allocation handle that stores the compressed page data
19762306a36Sopenharmony_ci * value - value of the same-value filled pages which have same content
19862306a36Sopenharmony_ci * objcg - the obj_cgroup that the compressed memory is charged to
19962306a36Sopenharmony_ci * lru - handle to the pool's lru used to evict pages.
20062306a36Sopenharmony_ci */
20162306a36Sopenharmony_cistruct zswap_entry {
20262306a36Sopenharmony_ci	struct rb_node rbnode;
20362306a36Sopenharmony_ci	swp_entry_t swpentry;
20462306a36Sopenharmony_ci	int refcount;
20562306a36Sopenharmony_ci	unsigned int length;
20662306a36Sopenharmony_ci	struct zswap_pool *pool;
20762306a36Sopenharmony_ci	union {
20862306a36Sopenharmony_ci		unsigned long handle;
20962306a36Sopenharmony_ci		unsigned long value;
21062306a36Sopenharmony_ci	};
21162306a36Sopenharmony_ci	struct obj_cgroup *objcg;
21262306a36Sopenharmony_ci	struct list_head lru;
21362306a36Sopenharmony_ci};
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/*
21662306a36Sopenharmony_ci * The tree lock in the zswap_tree struct protects a few things:
21762306a36Sopenharmony_ci * - the rbtree
21862306a36Sopenharmony_ci * - the refcount field of each entry in the tree
21962306a36Sopenharmony_ci */
22062306a36Sopenharmony_cistruct zswap_tree {
22162306a36Sopenharmony_ci	struct rb_root rbroot;
22262306a36Sopenharmony_ci	spinlock_t lock;
22362306a36Sopenharmony_ci};
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic struct zswap_tree *zswap_trees[MAX_SWAPFILES];
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci/* RCU-protected iteration */
22862306a36Sopenharmony_cistatic LIST_HEAD(zswap_pools);
22962306a36Sopenharmony_ci/* protects zswap_pools list modification */
23062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(zswap_pools_lock);
23162306a36Sopenharmony_ci/* pool counter to provide unique names to zpool */
23262306a36Sopenharmony_cistatic atomic_t zswap_pools_count = ATOMIC_INIT(0);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cienum zswap_init_type {
23562306a36Sopenharmony_ci	ZSWAP_UNINIT,
23662306a36Sopenharmony_ci	ZSWAP_INIT_SUCCEED,
23762306a36Sopenharmony_ci	ZSWAP_INIT_FAILED
23862306a36Sopenharmony_ci};
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic enum zswap_init_type zswap_init_state;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci/* used to ensure the integrity of initialization */
24362306a36Sopenharmony_cistatic DEFINE_MUTEX(zswap_init_lock);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci/* init completed, but couldn't create the initial pool */
24662306a36Sopenharmony_cistatic bool zswap_has_pool;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci/*********************************
24962306a36Sopenharmony_ci* helpers and fwd declarations
25062306a36Sopenharmony_ci**********************************/
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci#define zswap_pool_debug(msg, p)				\
25362306a36Sopenharmony_ci	pr_debug("%s pool %s/%s\n", msg, (p)->tfm_name,		\
25462306a36Sopenharmony_ci		 zpool_get_type((p)->zpools[0]))
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic int zswap_writeback_entry(struct zswap_entry *entry,
25762306a36Sopenharmony_ci				 struct zswap_tree *tree);
25862306a36Sopenharmony_cistatic int zswap_pool_get(struct zswap_pool *pool);
25962306a36Sopenharmony_cistatic void zswap_pool_put(struct zswap_pool *pool);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic bool zswap_is_full(void)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	return totalram_pages() * zswap_max_pool_percent / 100 <
26462306a36Sopenharmony_ci			DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic bool zswap_can_accept(void)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	return totalram_pages() * zswap_accept_thr_percent / 100 *
27062306a36Sopenharmony_ci				zswap_max_pool_percent / 100 >
27162306a36Sopenharmony_ci			DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE);
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistatic void zswap_update_total_size(void)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	struct zswap_pool *pool;
27762306a36Sopenharmony_ci	u64 total = 0;
27862306a36Sopenharmony_ci	int i;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	rcu_read_lock();
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	list_for_each_entry_rcu(pool, &zswap_pools, list)
28362306a36Sopenharmony_ci		for (i = 0; i < ZSWAP_NR_ZPOOLS; i++)
28462306a36Sopenharmony_ci			total += zpool_get_total_size(pool->zpools[i]);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	rcu_read_unlock();
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	zswap_pool_total_size = total;
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci/*********************************
29262306a36Sopenharmony_ci* zswap entry functions
29362306a36Sopenharmony_ci**********************************/
29462306a36Sopenharmony_cistatic struct kmem_cache *zswap_entry_cache;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic struct zswap_entry *zswap_entry_cache_alloc(gfp_t gfp)
29762306a36Sopenharmony_ci{
29862306a36Sopenharmony_ci	struct zswap_entry *entry;
29962306a36Sopenharmony_ci	entry = kmem_cache_alloc(zswap_entry_cache, gfp);
30062306a36Sopenharmony_ci	if (!entry)
30162306a36Sopenharmony_ci		return NULL;
30262306a36Sopenharmony_ci	entry->refcount = 1;
30362306a36Sopenharmony_ci	RB_CLEAR_NODE(&entry->rbnode);
30462306a36Sopenharmony_ci	return entry;
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic void zswap_entry_cache_free(struct zswap_entry *entry)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	kmem_cache_free(zswap_entry_cache, entry);
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci/*********************************
31362306a36Sopenharmony_ci* rbtree functions
31462306a36Sopenharmony_ci**********************************/
31562306a36Sopenharmony_cistatic struct zswap_entry *zswap_rb_search(struct rb_root *root, pgoff_t offset)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	struct rb_node *node = root->rb_node;
31862306a36Sopenharmony_ci	struct zswap_entry *entry;
31962306a36Sopenharmony_ci	pgoff_t entry_offset;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	while (node) {
32262306a36Sopenharmony_ci		entry = rb_entry(node, struct zswap_entry, rbnode);
32362306a36Sopenharmony_ci		entry_offset = swp_offset(entry->swpentry);
32462306a36Sopenharmony_ci		if (entry_offset > offset)
32562306a36Sopenharmony_ci			node = node->rb_left;
32662306a36Sopenharmony_ci		else if (entry_offset < offset)
32762306a36Sopenharmony_ci			node = node->rb_right;
32862306a36Sopenharmony_ci		else
32962306a36Sopenharmony_ci			return entry;
33062306a36Sopenharmony_ci	}
33162306a36Sopenharmony_ci	return NULL;
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci/*
33562306a36Sopenharmony_ci * In the case that a entry with the same offset is found, a pointer to
33662306a36Sopenharmony_ci * the existing entry is stored in dupentry and the function returns -EEXIST
33762306a36Sopenharmony_ci */
33862306a36Sopenharmony_cistatic int zswap_rb_insert(struct rb_root *root, struct zswap_entry *entry,
33962306a36Sopenharmony_ci			struct zswap_entry **dupentry)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	struct rb_node **link = &root->rb_node, *parent = NULL;
34262306a36Sopenharmony_ci	struct zswap_entry *myentry;
34362306a36Sopenharmony_ci	pgoff_t myentry_offset, entry_offset = swp_offset(entry->swpentry);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	while (*link) {
34662306a36Sopenharmony_ci		parent = *link;
34762306a36Sopenharmony_ci		myentry = rb_entry(parent, struct zswap_entry, rbnode);
34862306a36Sopenharmony_ci		myentry_offset = swp_offset(myentry->swpentry);
34962306a36Sopenharmony_ci		if (myentry_offset > entry_offset)
35062306a36Sopenharmony_ci			link = &(*link)->rb_left;
35162306a36Sopenharmony_ci		else if (myentry_offset < entry_offset)
35262306a36Sopenharmony_ci			link = &(*link)->rb_right;
35362306a36Sopenharmony_ci		else {
35462306a36Sopenharmony_ci			*dupentry = myentry;
35562306a36Sopenharmony_ci			return -EEXIST;
35662306a36Sopenharmony_ci		}
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci	rb_link_node(&entry->rbnode, parent, link);
35962306a36Sopenharmony_ci	rb_insert_color(&entry->rbnode, root);
36062306a36Sopenharmony_ci	return 0;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic bool zswap_rb_erase(struct rb_root *root, struct zswap_entry *entry)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	if (!RB_EMPTY_NODE(&entry->rbnode)) {
36662306a36Sopenharmony_ci		rb_erase(&entry->rbnode, root);
36762306a36Sopenharmony_ci		RB_CLEAR_NODE(&entry->rbnode);
36862306a36Sopenharmony_ci		return true;
36962306a36Sopenharmony_ci	}
37062306a36Sopenharmony_ci	return false;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic struct zpool *zswap_find_zpool(struct zswap_entry *entry)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	int i = 0;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (ZSWAP_NR_ZPOOLS > 1)
37862306a36Sopenharmony_ci		i = hash_ptr(entry, ilog2(ZSWAP_NR_ZPOOLS));
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	return entry->pool->zpools[i];
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/*
38462306a36Sopenharmony_ci * Carries out the common pattern of freeing and entry's zpool allocation,
38562306a36Sopenharmony_ci * freeing the entry itself, and decrementing the number of stored pages.
38662306a36Sopenharmony_ci */
38762306a36Sopenharmony_cistatic void zswap_free_entry(struct zswap_entry *entry)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	if (entry->objcg) {
39062306a36Sopenharmony_ci		obj_cgroup_uncharge_zswap(entry->objcg, entry->length);
39162306a36Sopenharmony_ci		obj_cgroup_put(entry->objcg);
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci	if (!entry->length)
39462306a36Sopenharmony_ci		atomic_dec(&zswap_same_filled_pages);
39562306a36Sopenharmony_ci	else {
39662306a36Sopenharmony_ci		spin_lock(&entry->pool->lru_lock);
39762306a36Sopenharmony_ci		list_del(&entry->lru);
39862306a36Sopenharmony_ci		spin_unlock(&entry->pool->lru_lock);
39962306a36Sopenharmony_ci		zpool_free(zswap_find_zpool(entry), entry->handle);
40062306a36Sopenharmony_ci		zswap_pool_put(entry->pool);
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci	zswap_entry_cache_free(entry);
40362306a36Sopenharmony_ci	atomic_dec(&zswap_stored_pages);
40462306a36Sopenharmony_ci	zswap_update_total_size();
40562306a36Sopenharmony_ci}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci/* caller must hold the tree lock */
40862306a36Sopenharmony_cistatic void zswap_entry_get(struct zswap_entry *entry)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	entry->refcount++;
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci/* caller must hold the tree lock
41462306a36Sopenharmony_ci* remove from the tree and free it, if nobody reference the entry
41562306a36Sopenharmony_ci*/
41662306a36Sopenharmony_cistatic void zswap_entry_put(struct zswap_tree *tree,
41762306a36Sopenharmony_ci			struct zswap_entry *entry)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	int refcount = --entry->refcount;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	WARN_ON_ONCE(refcount < 0);
42262306a36Sopenharmony_ci	if (refcount == 0) {
42362306a36Sopenharmony_ci		WARN_ON_ONCE(!RB_EMPTY_NODE(&entry->rbnode));
42462306a36Sopenharmony_ci		zswap_free_entry(entry);
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci/* caller must hold the tree lock */
42962306a36Sopenharmony_cistatic struct zswap_entry *zswap_entry_find_get(struct rb_root *root,
43062306a36Sopenharmony_ci				pgoff_t offset)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	struct zswap_entry *entry;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	entry = zswap_rb_search(root, offset);
43562306a36Sopenharmony_ci	if (entry)
43662306a36Sopenharmony_ci		zswap_entry_get(entry);
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	return entry;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci/*********************************
44262306a36Sopenharmony_ci* per-cpu code
44362306a36Sopenharmony_ci**********************************/
44462306a36Sopenharmony_cistatic DEFINE_PER_CPU(u8 *, zswap_dstmem);
44562306a36Sopenharmony_ci/*
44662306a36Sopenharmony_ci * If users dynamically change the zpool type and compressor at runtime, i.e.
44762306a36Sopenharmony_ci * zswap is running, zswap can have more than one zpool on one cpu, but they
44862306a36Sopenharmony_ci * are sharing dtsmem. So we need this mutex to be per-cpu.
44962306a36Sopenharmony_ci */
45062306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct mutex *, zswap_mutex);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cistatic int zswap_dstmem_prepare(unsigned int cpu)
45362306a36Sopenharmony_ci{
45462306a36Sopenharmony_ci	struct mutex *mutex;
45562306a36Sopenharmony_ci	u8 *dst;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	dst = kmalloc_node(PAGE_SIZE * 2, GFP_KERNEL, cpu_to_node(cpu));
45862306a36Sopenharmony_ci	if (!dst)
45962306a36Sopenharmony_ci		return -ENOMEM;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	mutex = kmalloc_node(sizeof(*mutex), GFP_KERNEL, cpu_to_node(cpu));
46262306a36Sopenharmony_ci	if (!mutex) {
46362306a36Sopenharmony_ci		kfree(dst);
46462306a36Sopenharmony_ci		return -ENOMEM;
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	mutex_init(mutex);
46862306a36Sopenharmony_ci	per_cpu(zswap_dstmem, cpu) = dst;
46962306a36Sopenharmony_ci	per_cpu(zswap_mutex, cpu) = mutex;
47062306a36Sopenharmony_ci	return 0;
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic int zswap_dstmem_dead(unsigned int cpu)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	struct mutex *mutex;
47662306a36Sopenharmony_ci	u8 *dst;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	mutex = per_cpu(zswap_mutex, cpu);
47962306a36Sopenharmony_ci	kfree(mutex);
48062306a36Sopenharmony_ci	per_cpu(zswap_mutex, cpu) = NULL;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	dst = per_cpu(zswap_dstmem, cpu);
48362306a36Sopenharmony_ci	kfree(dst);
48462306a36Sopenharmony_ci	per_cpu(zswap_dstmem, cpu) = NULL;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	return 0;
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_cistatic int zswap_cpu_comp_prepare(unsigned int cpu, struct hlist_node *node)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);
49262306a36Sopenharmony_ci	struct crypto_acomp_ctx *acomp_ctx = per_cpu_ptr(pool->acomp_ctx, cpu);
49362306a36Sopenharmony_ci	struct crypto_acomp *acomp;
49462306a36Sopenharmony_ci	struct acomp_req *req;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	acomp = crypto_alloc_acomp_node(pool->tfm_name, 0, 0, cpu_to_node(cpu));
49762306a36Sopenharmony_ci	if (IS_ERR(acomp)) {
49862306a36Sopenharmony_ci		pr_err("could not alloc crypto acomp %s : %ld\n",
49962306a36Sopenharmony_ci				pool->tfm_name, PTR_ERR(acomp));
50062306a36Sopenharmony_ci		return PTR_ERR(acomp);
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci	acomp_ctx->acomp = acomp;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	req = acomp_request_alloc(acomp_ctx->acomp);
50562306a36Sopenharmony_ci	if (!req) {
50662306a36Sopenharmony_ci		pr_err("could not alloc crypto acomp_request %s\n",
50762306a36Sopenharmony_ci		       pool->tfm_name);
50862306a36Sopenharmony_ci		crypto_free_acomp(acomp_ctx->acomp);
50962306a36Sopenharmony_ci		return -ENOMEM;
51062306a36Sopenharmony_ci	}
51162306a36Sopenharmony_ci	acomp_ctx->req = req;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	crypto_init_wait(&acomp_ctx->wait);
51462306a36Sopenharmony_ci	/*
51562306a36Sopenharmony_ci	 * if the backend of acomp is async zip, crypto_req_done() will wakeup
51662306a36Sopenharmony_ci	 * crypto_wait_req(); if the backend of acomp is scomp, the callback
51762306a36Sopenharmony_ci	 * won't be called, crypto_wait_req() will return without blocking.
51862306a36Sopenharmony_ci	 */
51962306a36Sopenharmony_ci	acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
52062306a36Sopenharmony_ci				   crypto_req_done, &acomp_ctx->wait);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	acomp_ctx->mutex = per_cpu(zswap_mutex, cpu);
52362306a36Sopenharmony_ci	acomp_ctx->dstmem = per_cpu(zswap_dstmem, cpu);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	return 0;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic int zswap_cpu_comp_dead(unsigned int cpu, struct hlist_node *node)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	struct zswap_pool *pool = hlist_entry(node, struct zswap_pool, node);
53162306a36Sopenharmony_ci	struct crypto_acomp_ctx *acomp_ctx = per_cpu_ptr(pool->acomp_ctx, cpu);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (!IS_ERR_OR_NULL(acomp_ctx)) {
53462306a36Sopenharmony_ci		if (!IS_ERR_OR_NULL(acomp_ctx->req))
53562306a36Sopenharmony_ci			acomp_request_free(acomp_ctx->req);
53662306a36Sopenharmony_ci		if (!IS_ERR_OR_NULL(acomp_ctx->acomp))
53762306a36Sopenharmony_ci			crypto_free_acomp(acomp_ctx->acomp);
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	return 0;
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci/*********************************
54462306a36Sopenharmony_ci* pool functions
54562306a36Sopenharmony_ci**********************************/
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_cistatic struct zswap_pool *__zswap_pool_current(void)
54862306a36Sopenharmony_ci{
54962306a36Sopenharmony_ci	struct zswap_pool *pool;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	pool = list_first_or_null_rcu(&zswap_pools, typeof(*pool), list);
55262306a36Sopenharmony_ci	WARN_ONCE(!pool && zswap_has_pool,
55362306a36Sopenharmony_ci		  "%s: no page storage pool!\n", __func__);
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	return pool;
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_cistatic struct zswap_pool *zswap_pool_current(void)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	assert_spin_locked(&zswap_pools_lock);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	return __zswap_pool_current();
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic struct zswap_pool *zswap_pool_current_get(void)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct zswap_pool *pool;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	rcu_read_lock();
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	pool = __zswap_pool_current();
57262306a36Sopenharmony_ci	if (!zswap_pool_get(pool))
57362306a36Sopenharmony_ci		pool = NULL;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	rcu_read_unlock();
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	return pool;
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic struct zswap_pool *zswap_pool_last_get(void)
58162306a36Sopenharmony_ci{
58262306a36Sopenharmony_ci	struct zswap_pool *pool, *last = NULL;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	rcu_read_lock();
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	list_for_each_entry_rcu(pool, &zswap_pools, list)
58762306a36Sopenharmony_ci		last = pool;
58862306a36Sopenharmony_ci	WARN_ONCE(!last && zswap_has_pool,
58962306a36Sopenharmony_ci		  "%s: no page storage pool!\n", __func__);
59062306a36Sopenharmony_ci	if (!zswap_pool_get(last))
59162306a36Sopenharmony_ci		last = NULL;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	rcu_read_unlock();
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	return last;
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci/* type and compressor must be null-terminated */
59962306a36Sopenharmony_cistatic struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
60062306a36Sopenharmony_ci{
60162306a36Sopenharmony_ci	struct zswap_pool *pool;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	assert_spin_locked(&zswap_pools_lock);
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	list_for_each_entry_rcu(pool, &zswap_pools, list) {
60662306a36Sopenharmony_ci		if (strcmp(pool->tfm_name, compressor))
60762306a36Sopenharmony_ci			continue;
60862306a36Sopenharmony_ci		/* all zpools share the same type */
60962306a36Sopenharmony_ci		if (strcmp(zpool_get_type(pool->zpools[0]), type))
61062306a36Sopenharmony_ci			continue;
61162306a36Sopenharmony_ci		/* if we can't get it, it's about to be destroyed */
61262306a36Sopenharmony_ci		if (!zswap_pool_get(pool))
61362306a36Sopenharmony_ci			continue;
61462306a36Sopenharmony_ci		return pool;
61562306a36Sopenharmony_ci	}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	return NULL;
61862306a36Sopenharmony_ci}
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci/*
62162306a36Sopenharmony_ci * If the entry is still valid in the tree, drop the initial ref and remove it
62262306a36Sopenharmony_ci * from the tree. This function must be called with an additional ref held,
62362306a36Sopenharmony_ci * otherwise it may race with another invalidation freeing the entry.
62462306a36Sopenharmony_ci */
62562306a36Sopenharmony_cistatic void zswap_invalidate_entry(struct zswap_tree *tree,
62662306a36Sopenharmony_ci				   struct zswap_entry *entry)
62762306a36Sopenharmony_ci{
62862306a36Sopenharmony_ci	if (zswap_rb_erase(&tree->rbroot, entry))
62962306a36Sopenharmony_ci		zswap_entry_put(tree, entry);
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_cistatic int zswap_reclaim_entry(struct zswap_pool *pool)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	struct zswap_entry *entry;
63562306a36Sopenharmony_ci	struct zswap_tree *tree;
63662306a36Sopenharmony_ci	pgoff_t swpoffset;
63762306a36Sopenharmony_ci	int ret;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	/* Get an entry off the LRU */
64062306a36Sopenharmony_ci	spin_lock(&pool->lru_lock);
64162306a36Sopenharmony_ci	if (list_empty(&pool->lru)) {
64262306a36Sopenharmony_ci		spin_unlock(&pool->lru_lock);
64362306a36Sopenharmony_ci		return -EINVAL;
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci	entry = list_last_entry(&pool->lru, struct zswap_entry, lru);
64662306a36Sopenharmony_ci	list_del_init(&entry->lru);
64762306a36Sopenharmony_ci	/*
64862306a36Sopenharmony_ci	 * Once the lru lock is dropped, the entry might get freed. The
64962306a36Sopenharmony_ci	 * swpoffset is copied to the stack, and entry isn't deref'd again
65062306a36Sopenharmony_ci	 * until the entry is verified to still be alive in the tree.
65162306a36Sopenharmony_ci	 */
65262306a36Sopenharmony_ci	swpoffset = swp_offset(entry->swpentry);
65362306a36Sopenharmony_ci	tree = zswap_trees[swp_type(entry->swpentry)];
65462306a36Sopenharmony_ci	spin_unlock(&pool->lru_lock);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	/* Check for invalidate() race */
65762306a36Sopenharmony_ci	spin_lock(&tree->lock);
65862306a36Sopenharmony_ci	if (entry != zswap_rb_search(&tree->rbroot, swpoffset)) {
65962306a36Sopenharmony_ci		ret = -EAGAIN;
66062306a36Sopenharmony_ci		goto unlock;
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci	/* Hold a reference to prevent a free during writeback */
66362306a36Sopenharmony_ci	zswap_entry_get(entry);
66462306a36Sopenharmony_ci	spin_unlock(&tree->lock);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	ret = zswap_writeback_entry(entry, tree);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	spin_lock(&tree->lock);
66962306a36Sopenharmony_ci	if (ret) {
67062306a36Sopenharmony_ci		/* Writeback failed, put entry back on LRU */
67162306a36Sopenharmony_ci		spin_lock(&pool->lru_lock);
67262306a36Sopenharmony_ci		list_move(&entry->lru, &pool->lru);
67362306a36Sopenharmony_ci		spin_unlock(&pool->lru_lock);
67462306a36Sopenharmony_ci		goto put_unlock;
67562306a36Sopenharmony_ci	}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	/*
67862306a36Sopenharmony_ci	 * Writeback started successfully, the page now belongs to the
67962306a36Sopenharmony_ci	 * swapcache. Drop the entry from zswap - unless invalidate already
68062306a36Sopenharmony_ci	 * took it out while we had the tree->lock released for IO.
68162306a36Sopenharmony_ci	 */
68262306a36Sopenharmony_ci	zswap_invalidate_entry(tree, entry);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ciput_unlock:
68562306a36Sopenharmony_ci	/* Drop local reference */
68662306a36Sopenharmony_ci	zswap_entry_put(tree, entry);
68762306a36Sopenharmony_ciunlock:
68862306a36Sopenharmony_ci	spin_unlock(&tree->lock);
68962306a36Sopenharmony_ci	return ret ? -EAGAIN : 0;
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic void shrink_worker(struct work_struct *w)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	struct zswap_pool *pool = container_of(w, typeof(*pool),
69562306a36Sopenharmony_ci						shrink_work);
69662306a36Sopenharmony_ci	int ret, failures = 0;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	do {
69962306a36Sopenharmony_ci		ret = zswap_reclaim_entry(pool);
70062306a36Sopenharmony_ci		if (ret) {
70162306a36Sopenharmony_ci			zswap_reject_reclaim_fail++;
70262306a36Sopenharmony_ci			if (ret != -EAGAIN)
70362306a36Sopenharmony_ci				break;
70462306a36Sopenharmony_ci			if (++failures == MAX_RECLAIM_RETRIES)
70562306a36Sopenharmony_ci				break;
70662306a36Sopenharmony_ci		}
70762306a36Sopenharmony_ci		cond_resched();
70862306a36Sopenharmony_ci	} while (!zswap_can_accept());
70962306a36Sopenharmony_ci	zswap_pool_put(pool);
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_cistatic struct zswap_pool *zswap_pool_create(char *type, char *compressor)
71362306a36Sopenharmony_ci{
71462306a36Sopenharmony_ci	int i;
71562306a36Sopenharmony_ci	struct zswap_pool *pool;
71662306a36Sopenharmony_ci	char name[38]; /* 'zswap' + 32 char (max) num + \0 */
71762306a36Sopenharmony_ci	gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
71862306a36Sopenharmony_ci	int ret;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	if (!zswap_has_pool) {
72162306a36Sopenharmony_ci		/* if either are unset, pool initialization failed, and we
72262306a36Sopenharmony_ci		 * need both params to be set correctly before trying to
72362306a36Sopenharmony_ci		 * create a pool.
72462306a36Sopenharmony_ci		 */
72562306a36Sopenharmony_ci		if (!strcmp(type, ZSWAP_PARAM_UNSET))
72662306a36Sopenharmony_ci			return NULL;
72762306a36Sopenharmony_ci		if (!strcmp(compressor, ZSWAP_PARAM_UNSET))
72862306a36Sopenharmony_ci			return NULL;
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
73262306a36Sopenharmony_ci	if (!pool)
73362306a36Sopenharmony_ci		return NULL;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	for (i = 0; i < ZSWAP_NR_ZPOOLS; i++) {
73662306a36Sopenharmony_ci		/* unique name for each pool specifically required by zsmalloc */
73762306a36Sopenharmony_ci		snprintf(name, 38, "zswap%x",
73862306a36Sopenharmony_ci			 atomic_inc_return(&zswap_pools_count));
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci		pool->zpools[i] = zpool_create_pool(type, name, gfp);
74162306a36Sopenharmony_ci		if (!pool->zpools[i]) {
74262306a36Sopenharmony_ci			pr_err("%s zpool not available\n", type);
74362306a36Sopenharmony_ci			goto error;
74462306a36Sopenharmony_ci		}
74562306a36Sopenharmony_ci	}
74662306a36Sopenharmony_ci	pr_debug("using %s zpool\n", zpool_get_type(pool->zpools[0]));
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	strscpy(pool->tfm_name, compressor, sizeof(pool->tfm_name));
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	pool->acomp_ctx = alloc_percpu(*pool->acomp_ctx);
75162306a36Sopenharmony_ci	if (!pool->acomp_ctx) {
75262306a36Sopenharmony_ci		pr_err("percpu alloc failed\n");
75362306a36Sopenharmony_ci		goto error;
75462306a36Sopenharmony_ci	}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	ret = cpuhp_state_add_instance(CPUHP_MM_ZSWP_POOL_PREPARE,
75762306a36Sopenharmony_ci				       &pool->node);
75862306a36Sopenharmony_ci	if (ret)
75962306a36Sopenharmony_ci		goto error;
76062306a36Sopenharmony_ci	pr_debug("using %s compressor\n", pool->tfm_name);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	/* being the current pool takes 1 ref; this func expects the
76362306a36Sopenharmony_ci	 * caller to always add the new pool as the current pool
76462306a36Sopenharmony_ci	 */
76562306a36Sopenharmony_ci	kref_init(&pool->kref);
76662306a36Sopenharmony_ci	INIT_LIST_HEAD(&pool->list);
76762306a36Sopenharmony_ci	INIT_LIST_HEAD(&pool->lru);
76862306a36Sopenharmony_ci	spin_lock_init(&pool->lru_lock);
76962306a36Sopenharmony_ci	INIT_WORK(&pool->shrink_work, shrink_worker);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	zswap_pool_debug("created", pool);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	return pool;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_cierror:
77662306a36Sopenharmony_ci	if (pool->acomp_ctx)
77762306a36Sopenharmony_ci		free_percpu(pool->acomp_ctx);
77862306a36Sopenharmony_ci	while (i--)
77962306a36Sopenharmony_ci		zpool_destroy_pool(pool->zpools[i]);
78062306a36Sopenharmony_ci	kfree(pool);
78162306a36Sopenharmony_ci	return NULL;
78262306a36Sopenharmony_ci}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic struct zswap_pool *__zswap_pool_create_fallback(void)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	bool has_comp, has_zpool;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	has_comp = crypto_has_acomp(zswap_compressor, 0, 0);
78962306a36Sopenharmony_ci	if (!has_comp && strcmp(zswap_compressor,
79062306a36Sopenharmony_ci				CONFIG_ZSWAP_COMPRESSOR_DEFAULT)) {
79162306a36Sopenharmony_ci		pr_err("compressor %s not available, using default %s\n",
79262306a36Sopenharmony_ci		       zswap_compressor, CONFIG_ZSWAP_COMPRESSOR_DEFAULT);
79362306a36Sopenharmony_ci		param_free_charp(&zswap_compressor);
79462306a36Sopenharmony_ci		zswap_compressor = CONFIG_ZSWAP_COMPRESSOR_DEFAULT;
79562306a36Sopenharmony_ci		has_comp = crypto_has_acomp(zswap_compressor, 0, 0);
79662306a36Sopenharmony_ci	}
79762306a36Sopenharmony_ci	if (!has_comp) {
79862306a36Sopenharmony_ci		pr_err("default compressor %s not available\n",
79962306a36Sopenharmony_ci		       zswap_compressor);
80062306a36Sopenharmony_ci		param_free_charp(&zswap_compressor);
80162306a36Sopenharmony_ci		zswap_compressor = ZSWAP_PARAM_UNSET;
80262306a36Sopenharmony_ci	}
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	has_zpool = zpool_has_pool(zswap_zpool_type);
80562306a36Sopenharmony_ci	if (!has_zpool && strcmp(zswap_zpool_type,
80662306a36Sopenharmony_ci				 CONFIG_ZSWAP_ZPOOL_DEFAULT)) {
80762306a36Sopenharmony_ci		pr_err("zpool %s not available, using default %s\n",
80862306a36Sopenharmony_ci		       zswap_zpool_type, CONFIG_ZSWAP_ZPOOL_DEFAULT);
80962306a36Sopenharmony_ci		param_free_charp(&zswap_zpool_type);
81062306a36Sopenharmony_ci		zswap_zpool_type = CONFIG_ZSWAP_ZPOOL_DEFAULT;
81162306a36Sopenharmony_ci		has_zpool = zpool_has_pool(zswap_zpool_type);
81262306a36Sopenharmony_ci	}
81362306a36Sopenharmony_ci	if (!has_zpool) {
81462306a36Sopenharmony_ci		pr_err("default zpool %s not available\n",
81562306a36Sopenharmony_ci		       zswap_zpool_type);
81662306a36Sopenharmony_ci		param_free_charp(&zswap_zpool_type);
81762306a36Sopenharmony_ci		zswap_zpool_type = ZSWAP_PARAM_UNSET;
81862306a36Sopenharmony_ci	}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	if (!has_comp || !has_zpool)
82162306a36Sopenharmony_ci		return NULL;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	return zswap_pool_create(zswap_zpool_type, zswap_compressor);
82462306a36Sopenharmony_ci}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_cistatic void zswap_pool_destroy(struct zswap_pool *pool)
82762306a36Sopenharmony_ci{
82862306a36Sopenharmony_ci	int i;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	zswap_pool_debug("destroying", pool);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	cpuhp_state_remove_instance(CPUHP_MM_ZSWP_POOL_PREPARE, &pool->node);
83362306a36Sopenharmony_ci	free_percpu(pool->acomp_ctx);
83462306a36Sopenharmony_ci	for (i = 0; i < ZSWAP_NR_ZPOOLS; i++)
83562306a36Sopenharmony_ci		zpool_destroy_pool(pool->zpools[i]);
83662306a36Sopenharmony_ci	kfree(pool);
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cistatic int __must_check zswap_pool_get(struct zswap_pool *pool)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	if (!pool)
84262306a36Sopenharmony_ci		return 0;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	return kref_get_unless_zero(&pool->kref);
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_cistatic void __zswap_pool_release(struct work_struct *work)
84862306a36Sopenharmony_ci{
84962306a36Sopenharmony_ci	struct zswap_pool *pool = container_of(work, typeof(*pool),
85062306a36Sopenharmony_ci						release_work);
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	synchronize_rcu();
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	/* nobody should have been able to get a kref... */
85562306a36Sopenharmony_ci	WARN_ON(kref_get_unless_zero(&pool->kref));
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	/* pool is now off zswap_pools list and has no references. */
85862306a36Sopenharmony_ci	zswap_pool_destroy(pool);
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic void __zswap_pool_empty(struct kref *kref)
86262306a36Sopenharmony_ci{
86362306a36Sopenharmony_ci	struct zswap_pool *pool;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	pool = container_of(kref, typeof(*pool), kref);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	spin_lock(&zswap_pools_lock);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	WARN_ON(pool == zswap_pool_current());
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	list_del_rcu(&pool->list);
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	INIT_WORK(&pool->release_work, __zswap_pool_release);
87462306a36Sopenharmony_ci	schedule_work(&pool->release_work);
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	spin_unlock(&zswap_pools_lock);
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistatic void zswap_pool_put(struct zswap_pool *pool)
88062306a36Sopenharmony_ci{
88162306a36Sopenharmony_ci	kref_put(&pool->kref, __zswap_pool_empty);
88262306a36Sopenharmony_ci}
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci/*********************************
88562306a36Sopenharmony_ci* param callbacks
88662306a36Sopenharmony_ci**********************************/
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_cistatic bool zswap_pool_changed(const char *s, const struct kernel_param *kp)
88962306a36Sopenharmony_ci{
89062306a36Sopenharmony_ci	/* no change required */
89162306a36Sopenharmony_ci	if (!strcmp(s, *(char **)kp->arg) && zswap_has_pool)
89262306a36Sopenharmony_ci		return false;
89362306a36Sopenharmony_ci	return true;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci/* val must be a null-terminated string */
89762306a36Sopenharmony_cistatic int __zswap_param_set(const char *val, const struct kernel_param *kp,
89862306a36Sopenharmony_ci			     char *type, char *compressor)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct zswap_pool *pool, *put_pool = NULL;
90162306a36Sopenharmony_ci	char *s = strstrip((char *)val);
90262306a36Sopenharmony_ci	int ret = 0;
90362306a36Sopenharmony_ci	bool new_pool = false;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	mutex_lock(&zswap_init_lock);
90662306a36Sopenharmony_ci	switch (zswap_init_state) {
90762306a36Sopenharmony_ci	case ZSWAP_UNINIT:
90862306a36Sopenharmony_ci		/* if this is load-time (pre-init) param setting,
90962306a36Sopenharmony_ci		 * don't create a pool; that's done during init.
91062306a36Sopenharmony_ci		 */
91162306a36Sopenharmony_ci		ret = param_set_charp(s, kp);
91262306a36Sopenharmony_ci		break;
91362306a36Sopenharmony_ci	case ZSWAP_INIT_SUCCEED:
91462306a36Sopenharmony_ci		new_pool = zswap_pool_changed(s, kp);
91562306a36Sopenharmony_ci		break;
91662306a36Sopenharmony_ci	case ZSWAP_INIT_FAILED:
91762306a36Sopenharmony_ci		pr_err("can't set param, initialization failed\n");
91862306a36Sopenharmony_ci		ret = -ENODEV;
91962306a36Sopenharmony_ci	}
92062306a36Sopenharmony_ci	mutex_unlock(&zswap_init_lock);
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	/* no need to create a new pool, return directly */
92362306a36Sopenharmony_ci	if (!new_pool)
92462306a36Sopenharmony_ci		return ret;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	if (!type) {
92762306a36Sopenharmony_ci		if (!zpool_has_pool(s)) {
92862306a36Sopenharmony_ci			pr_err("zpool %s not available\n", s);
92962306a36Sopenharmony_ci			return -ENOENT;
93062306a36Sopenharmony_ci		}
93162306a36Sopenharmony_ci		type = s;
93262306a36Sopenharmony_ci	} else if (!compressor) {
93362306a36Sopenharmony_ci		if (!crypto_has_acomp(s, 0, 0)) {
93462306a36Sopenharmony_ci			pr_err("compressor %s not available\n", s);
93562306a36Sopenharmony_ci			return -ENOENT;
93662306a36Sopenharmony_ci		}
93762306a36Sopenharmony_ci		compressor = s;
93862306a36Sopenharmony_ci	} else {
93962306a36Sopenharmony_ci		WARN_ON(1);
94062306a36Sopenharmony_ci		return -EINVAL;
94162306a36Sopenharmony_ci	}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	spin_lock(&zswap_pools_lock);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	pool = zswap_pool_find_get(type, compressor);
94662306a36Sopenharmony_ci	if (pool) {
94762306a36Sopenharmony_ci		zswap_pool_debug("using existing", pool);
94862306a36Sopenharmony_ci		WARN_ON(pool == zswap_pool_current());
94962306a36Sopenharmony_ci		list_del_rcu(&pool->list);
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	spin_unlock(&zswap_pools_lock);
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci	if (!pool)
95562306a36Sopenharmony_ci		pool = zswap_pool_create(type, compressor);
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	if (pool)
95862306a36Sopenharmony_ci		ret = param_set_charp(s, kp);
95962306a36Sopenharmony_ci	else
96062306a36Sopenharmony_ci		ret = -EINVAL;
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	spin_lock(&zswap_pools_lock);
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	if (!ret) {
96562306a36Sopenharmony_ci		put_pool = zswap_pool_current();
96662306a36Sopenharmony_ci		list_add_rcu(&pool->list, &zswap_pools);
96762306a36Sopenharmony_ci		zswap_has_pool = true;
96862306a36Sopenharmony_ci	} else if (pool) {
96962306a36Sopenharmony_ci		/* add the possibly pre-existing pool to the end of the pools
97062306a36Sopenharmony_ci		 * list; if it's new (and empty) then it'll be removed and
97162306a36Sopenharmony_ci		 * destroyed by the put after we drop the lock
97262306a36Sopenharmony_ci		 */
97362306a36Sopenharmony_ci		list_add_tail_rcu(&pool->list, &zswap_pools);
97462306a36Sopenharmony_ci		put_pool = pool;
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	spin_unlock(&zswap_pools_lock);
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	if (!zswap_has_pool && !pool) {
98062306a36Sopenharmony_ci		/* if initial pool creation failed, and this pool creation also
98162306a36Sopenharmony_ci		 * failed, maybe both compressor and zpool params were bad.
98262306a36Sopenharmony_ci		 * Allow changing this param, so pool creation will succeed
98362306a36Sopenharmony_ci		 * when the other param is changed. We already verified this
98462306a36Sopenharmony_ci		 * param is ok in the zpool_has_pool() or crypto_has_acomp()
98562306a36Sopenharmony_ci		 * checks above.
98662306a36Sopenharmony_ci		 */
98762306a36Sopenharmony_ci		ret = param_set_charp(s, kp);
98862306a36Sopenharmony_ci	}
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	/* drop the ref from either the old current pool,
99162306a36Sopenharmony_ci	 * or the new pool we failed to add
99262306a36Sopenharmony_ci	 */
99362306a36Sopenharmony_ci	if (put_pool)
99462306a36Sopenharmony_ci		zswap_pool_put(put_pool);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	return ret;
99762306a36Sopenharmony_ci}
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_cistatic int zswap_compressor_param_set(const char *val,
100062306a36Sopenharmony_ci				      const struct kernel_param *kp)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	return __zswap_param_set(val, kp, zswap_zpool_type, NULL);
100362306a36Sopenharmony_ci}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_cistatic int zswap_zpool_param_set(const char *val,
100662306a36Sopenharmony_ci				 const struct kernel_param *kp)
100762306a36Sopenharmony_ci{
100862306a36Sopenharmony_ci	return __zswap_param_set(val, kp, NULL, zswap_compressor);
100962306a36Sopenharmony_ci}
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_cistatic int zswap_enabled_param_set(const char *val,
101262306a36Sopenharmony_ci				   const struct kernel_param *kp)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	int ret = -ENODEV;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	/* if this is load-time (pre-init) param setting, only set param. */
101762306a36Sopenharmony_ci	if (system_state != SYSTEM_RUNNING)
101862306a36Sopenharmony_ci		return param_set_bool(val, kp);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	mutex_lock(&zswap_init_lock);
102162306a36Sopenharmony_ci	switch (zswap_init_state) {
102262306a36Sopenharmony_ci	case ZSWAP_UNINIT:
102362306a36Sopenharmony_ci		if (zswap_setup())
102462306a36Sopenharmony_ci			break;
102562306a36Sopenharmony_ci		fallthrough;
102662306a36Sopenharmony_ci	case ZSWAP_INIT_SUCCEED:
102762306a36Sopenharmony_ci		if (!zswap_has_pool)
102862306a36Sopenharmony_ci			pr_err("can't enable, no pool configured\n");
102962306a36Sopenharmony_ci		else
103062306a36Sopenharmony_ci			ret = param_set_bool(val, kp);
103162306a36Sopenharmony_ci		break;
103262306a36Sopenharmony_ci	case ZSWAP_INIT_FAILED:
103362306a36Sopenharmony_ci		pr_err("can't enable, initialization failed\n");
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci	mutex_unlock(&zswap_init_lock);
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	return ret;
103862306a36Sopenharmony_ci}
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci/*********************************
104162306a36Sopenharmony_ci* writeback code
104262306a36Sopenharmony_ci**********************************/
104362306a36Sopenharmony_ci/*
104462306a36Sopenharmony_ci * Attempts to free an entry by adding a page to the swap cache,
104562306a36Sopenharmony_ci * decompressing the entry data into the page, and issuing a
104662306a36Sopenharmony_ci * bio write to write the page back to the swap device.
104762306a36Sopenharmony_ci *
104862306a36Sopenharmony_ci * This can be thought of as a "resumed writeback" of the page
104962306a36Sopenharmony_ci * to the swap device.  We are basically resuming the same swap
105062306a36Sopenharmony_ci * writeback path that was intercepted with the zswap_store()
105162306a36Sopenharmony_ci * in the first place.  After the page has been decompressed into
105262306a36Sopenharmony_ci * the swap cache, the compressed version stored by zswap can be
105362306a36Sopenharmony_ci * freed.
105462306a36Sopenharmony_ci */
105562306a36Sopenharmony_cistatic int zswap_writeback_entry(struct zswap_entry *entry,
105662306a36Sopenharmony_ci				 struct zswap_tree *tree)
105762306a36Sopenharmony_ci{
105862306a36Sopenharmony_ci	swp_entry_t swpentry = entry->swpentry;
105962306a36Sopenharmony_ci	struct page *page;
106062306a36Sopenharmony_ci	struct scatterlist input, output;
106162306a36Sopenharmony_ci	struct crypto_acomp_ctx *acomp_ctx;
106262306a36Sopenharmony_ci	struct zpool *pool = zswap_find_zpool(entry);
106362306a36Sopenharmony_ci	bool page_was_allocated;
106462306a36Sopenharmony_ci	u8 *src, *tmp = NULL;
106562306a36Sopenharmony_ci	unsigned int dlen;
106662306a36Sopenharmony_ci	int ret;
106762306a36Sopenharmony_ci	struct writeback_control wbc = {
106862306a36Sopenharmony_ci		.sync_mode = WB_SYNC_NONE,
106962306a36Sopenharmony_ci	};
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	if (!zpool_can_sleep_mapped(pool)) {
107262306a36Sopenharmony_ci		tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
107362306a36Sopenharmony_ci		if (!tmp)
107462306a36Sopenharmony_ci			return -ENOMEM;
107562306a36Sopenharmony_ci	}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	/* try to allocate swap cache page */
107862306a36Sopenharmony_ci	page = __read_swap_cache_async(swpentry, GFP_KERNEL, NULL, 0,
107962306a36Sopenharmony_ci				       &page_was_allocated);
108062306a36Sopenharmony_ci	if (!page) {
108162306a36Sopenharmony_ci		ret = -ENOMEM;
108262306a36Sopenharmony_ci		goto fail;
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	/* Found an existing page, we raced with load/swapin */
108662306a36Sopenharmony_ci	if (!page_was_allocated) {
108762306a36Sopenharmony_ci		put_page(page);
108862306a36Sopenharmony_ci		ret = -EEXIST;
108962306a36Sopenharmony_ci		goto fail;
109062306a36Sopenharmony_ci	}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	/*
109362306a36Sopenharmony_ci	 * Page is locked, and the swapcache is now secured against
109462306a36Sopenharmony_ci	 * concurrent swapping to and from the slot. Verify that the
109562306a36Sopenharmony_ci	 * swap entry hasn't been invalidated and recycled behind our
109662306a36Sopenharmony_ci	 * backs (our zswap_entry reference doesn't prevent that), to
109762306a36Sopenharmony_ci	 * avoid overwriting a new swap page with old compressed data.
109862306a36Sopenharmony_ci	 */
109962306a36Sopenharmony_ci	spin_lock(&tree->lock);
110062306a36Sopenharmony_ci	if (zswap_rb_search(&tree->rbroot, swp_offset(entry->swpentry)) != entry) {
110162306a36Sopenharmony_ci		spin_unlock(&tree->lock);
110262306a36Sopenharmony_ci		delete_from_swap_cache(page_folio(page));
110362306a36Sopenharmony_ci		unlock_page(page);
110462306a36Sopenharmony_ci		put_page(page);
110562306a36Sopenharmony_ci		ret = -ENOMEM;
110662306a36Sopenharmony_ci		goto fail;
110762306a36Sopenharmony_ci	}
110862306a36Sopenharmony_ci	spin_unlock(&tree->lock);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	/* decompress */
111162306a36Sopenharmony_ci	acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
111262306a36Sopenharmony_ci	dlen = PAGE_SIZE;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	src = zpool_map_handle(pool, entry->handle, ZPOOL_MM_RO);
111562306a36Sopenharmony_ci	if (!zpool_can_sleep_mapped(pool)) {
111662306a36Sopenharmony_ci		memcpy(tmp, src, entry->length);
111762306a36Sopenharmony_ci		src = tmp;
111862306a36Sopenharmony_ci		zpool_unmap_handle(pool, entry->handle);
111962306a36Sopenharmony_ci	}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	mutex_lock(acomp_ctx->mutex);
112262306a36Sopenharmony_ci	sg_init_one(&input, src, entry->length);
112362306a36Sopenharmony_ci	sg_init_table(&output, 1);
112462306a36Sopenharmony_ci	sg_set_page(&output, page, PAGE_SIZE, 0);
112562306a36Sopenharmony_ci	acomp_request_set_params(acomp_ctx->req, &input, &output, entry->length, dlen);
112662306a36Sopenharmony_ci	ret = crypto_wait_req(crypto_acomp_decompress(acomp_ctx->req), &acomp_ctx->wait);
112762306a36Sopenharmony_ci	dlen = acomp_ctx->req->dlen;
112862306a36Sopenharmony_ci	mutex_unlock(acomp_ctx->mutex);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	if (!zpool_can_sleep_mapped(pool))
113162306a36Sopenharmony_ci		kfree(tmp);
113262306a36Sopenharmony_ci	else
113362306a36Sopenharmony_ci		zpool_unmap_handle(pool, entry->handle);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	BUG_ON(ret);
113662306a36Sopenharmony_ci	BUG_ON(dlen != PAGE_SIZE);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	/* page is up to date */
113962306a36Sopenharmony_ci	SetPageUptodate(page);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	/* move it to the tail of the inactive list after end_writeback */
114262306a36Sopenharmony_ci	SetPageReclaim(page);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	/* start writeback */
114562306a36Sopenharmony_ci	__swap_writepage(page, &wbc);
114662306a36Sopenharmony_ci	put_page(page);
114762306a36Sopenharmony_ci	zswap_written_back_pages++;
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	return ret;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_cifail:
115262306a36Sopenharmony_ci	if (!zpool_can_sleep_mapped(pool))
115362306a36Sopenharmony_ci		kfree(tmp);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	/*
115662306a36Sopenharmony_ci	 * If we get here because the page is already in swapcache, a
115762306a36Sopenharmony_ci	 * load may be happening concurrently. It is safe and okay to
115862306a36Sopenharmony_ci	 * not free the entry. It is also okay to return !0.
115962306a36Sopenharmony_ci	 */
116062306a36Sopenharmony_ci	return ret;
116162306a36Sopenharmony_ci}
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_cistatic int zswap_is_page_same_filled(void *ptr, unsigned long *value)
116462306a36Sopenharmony_ci{
116562306a36Sopenharmony_ci	unsigned long *page;
116662306a36Sopenharmony_ci	unsigned long val;
116762306a36Sopenharmony_ci	unsigned int pos, last_pos = PAGE_SIZE / sizeof(*page) - 1;
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	page = (unsigned long *)ptr;
117062306a36Sopenharmony_ci	val = page[0];
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	if (val != page[last_pos])
117362306a36Sopenharmony_ci		return 0;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	for (pos = 1; pos < last_pos; pos++) {
117662306a36Sopenharmony_ci		if (val != page[pos])
117762306a36Sopenharmony_ci			return 0;
117862306a36Sopenharmony_ci	}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	*value = val;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	return 1;
118362306a36Sopenharmony_ci}
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_cistatic void zswap_fill_page(void *ptr, unsigned long value)
118662306a36Sopenharmony_ci{
118762306a36Sopenharmony_ci	unsigned long *page;
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	page = (unsigned long *)ptr;
119062306a36Sopenharmony_ci	memset_l(page, value, PAGE_SIZE / sizeof(unsigned long));
119162306a36Sopenharmony_ci}
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_cibool zswap_store(struct folio *folio)
119462306a36Sopenharmony_ci{
119562306a36Sopenharmony_ci	swp_entry_t swp = folio->swap;
119662306a36Sopenharmony_ci	int type = swp_type(swp);
119762306a36Sopenharmony_ci	pgoff_t offset = swp_offset(swp);
119862306a36Sopenharmony_ci	struct page *page = &folio->page;
119962306a36Sopenharmony_ci	struct zswap_tree *tree = zswap_trees[type];
120062306a36Sopenharmony_ci	struct zswap_entry *entry, *dupentry;
120162306a36Sopenharmony_ci	struct scatterlist input, output;
120262306a36Sopenharmony_ci	struct crypto_acomp_ctx *acomp_ctx;
120362306a36Sopenharmony_ci	struct obj_cgroup *objcg = NULL;
120462306a36Sopenharmony_ci	struct zswap_pool *pool;
120562306a36Sopenharmony_ci	struct zpool *zpool;
120662306a36Sopenharmony_ci	unsigned int dlen = PAGE_SIZE;
120762306a36Sopenharmony_ci	unsigned long handle, value;
120862306a36Sopenharmony_ci	char *buf;
120962306a36Sopenharmony_ci	u8 *src, *dst;
121062306a36Sopenharmony_ci	gfp_t gfp;
121162306a36Sopenharmony_ci	int ret;
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	VM_WARN_ON_ONCE(!folio_test_locked(folio));
121462306a36Sopenharmony_ci	VM_WARN_ON_ONCE(!folio_test_swapcache(folio));
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	/* Large folios aren't supported */
121762306a36Sopenharmony_ci	if (folio_test_large(folio))
121862306a36Sopenharmony_ci		return false;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	if (!tree)
122162306a36Sopenharmony_ci		return false;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	/*
122462306a36Sopenharmony_ci	 * If this is a duplicate, it must be removed before attempting to store
122562306a36Sopenharmony_ci	 * it, otherwise, if the store fails the old page won't be removed from
122662306a36Sopenharmony_ci	 * the tree, and it might be written back overriding the new data.
122762306a36Sopenharmony_ci	 */
122862306a36Sopenharmony_ci	spin_lock(&tree->lock);
122962306a36Sopenharmony_ci	dupentry = zswap_rb_search(&tree->rbroot, offset);
123062306a36Sopenharmony_ci	if (dupentry) {
123162306a36Sopenharmony_ci		zswap_duplicate_entry++;
123262306a36Sopenharmony_ci		zswap_invalidate_entry(tree, dupentry);
123362306a36Sopenharmony_ci	}
123462306a36Sopenharmony_ci	spin_unlock(&tree->lock);
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	if (!zswap_enabled)
123762306a36Sopenharmony_ci		return false;
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	/*
124062306a36Sopenharmony_ci	 * XXX: zswap reclaim does not work with cgroups yet. Without a
124162306a36Sopenharmony_ci	 * cgroup-aware entry LRU, we will push out entries system-wide based on
124262306a36Sopenharmony_ci	 * local cgroup limits.
124362306a36Sopenharmony_ci	 */
124462306a36Sopenharmony_ci	objcg = get_obj_cgroup_from_folio(folio);
124562306a36Sopenharmony_ci	if (objcg && !obj_cgroup_may_zswap(objcg))
124662306a36Sopenharmony_ci		goto reject;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	/* reclaim space if needed */
124962306a36Sopenharmony_ci	if (zswap_is_full()) {
125062306a36Sopenharmony_ci		zswap_pool_limit_hit++;
125162306a36Sopenharmony_ci		zswap_pool_reached_full = true;
125262306a36Sopenharmony_ci		goto shrink;
125362306a36Sopenharmony_ci	}
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	if (zswap_pool_reached_full) {
125662306a36Sopenharmony_ci	       if (!zswap_can_accept())
125762306a36Sopenharmony_ci			goto shrink;
125862306a36Sopenharmony_ci		else
125962306a36Sopenharmony_ci			zswap_pool_reached_full = false;
126062306a36Sopenharmony_ci	}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	/* allocate entry */
126362306a36Sopenharmony_ci	entry = zswap_entry_cache_alloc(GFP_KERNEL);
126462306a36Sopenharmony_ci	if (!entry) {
126562306a36Sopenharmony_ci		zswap_reject_kmemcache_fail++;
126662306a36Sopenharmony_ci		goto reject;
126762306a36Sopenharmony_ci	}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	if (zswap_same_filled_pages_enabled) {
127062306a36Sopenharmony_ci		src = kmap_atomic(page);
127162306a36Sopenharmony_ci		if (zswap_is_page_same_filled(src, &value)) {
127262306a36Sopenharmony_ci			kunmap_atomic(src);
127362306a36Sopenharmony_ci			entry->swpentry = swp_entry(type, offset);
127462306a36Sopenharmony_ci			entry->length = 0;
127562306a36Sopenharmony_ci			entry->value = value;
127662306a36Sopenharmony_ci			atomic_inc(&zswap_same_filled_pages);
127762306a36Sopenharmony_ci			goto insert_entry;
127862306a36Sopenharmony_ci		}
127962306a36Sopenharmony_ci		kunmap_atomic(src);
128062306a36Sopenharmony_ci	}
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	if (!zswap_non_same_filled_pages_enabled)
128362306a36Sopenharmony_ci		goto freepage;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	/* if entry is successfully added, it keeps the reference */
128662306a36Sopenharmony_ci	entry->pool = zswap_pool_current_get();
128762306a36Sopenharmony_ci	if (!entry->pool)
128862306a36Sopenharmony_ci		goto freepage;
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	/* compress */
129162306a36Sopenharmony_ci	acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	mutex_lock(acomp_ctx->mutex);
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	dst = acomp_ctx->dstmem;
129662306a36Sopenharmony_ci	sg_init_table(&input, 1);
129762306a36Sopenharmony_ci	sg_set_page(&input, page, PAGE_SIZE, 0);
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	/* zswap_dstmem is of size (PAGE_SIZE * 2). Reflect same in sg_list */
130062306a36Sopenharmony_ci	sg_init_one(&output, dst, PAGE_SIZE * 2);
130162306a36Sopenharmony_ci	acomp_request_set_params(acomp_ctx->req, &input, &output, PAGE_SIZE, dlen);
130262306a36Sopenharmony_ci	/*
130362306a36Sopenharmony_ci	 * it maybe looks a little bit silly that we send an asynchronous request,
130462306a36Sopenharmony_ci	 * then wait for its completion synchronously. This makes the process look
130562306a36Sopenharmony_ci	 * synchronous in fact.
130662306a36Sopenharmony_ci	 * Theoretically, acomp supports users send multiple acomp requests in one
130762306a36Sopenharmony_ci	 * acomp instance, then get those requests done simultaneously. but in this
130862306a36Sopenharmony_ci	 * case, zswap actually does store and load page by page, there is no
130962306a36Sopenharmony_ci	 * existing method to send the second page before the first page is done
131062306a36Sopenharmony_ci	 * in one thread doing zwap.
131162306a36Sopenharmony_ci	 * but in different threads running on different cpu, we have different
131262306a36Sopenharmony_ci	 * acomp instance, so multiple threads can do (de)compression in parallel.
131362306a36Sopenharmony_ci	 */
131462306a36Sopenharmony_ci	ret = crypto_wait_req(crypto_acomp_compress(acomp_ctx->req), &acomp_ctx->wait);
131562306a36Sopenharmony_ci	dlen = acomp_ctx->req->dlen;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	if (ret)
131862306a36Sopenharmony_ci		goto put_dstmem;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	/* store */
132162306a36Sopenharmony_ci	zpool = zswap_find_zpool(entry);
132262306a36Sopenharmony_ci	gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
132362306a36Sopenharmony_ci	if (zpool_malloc_support_movable(zpool))
132462306a36Sopenharmony_ci		gfp |= __GFP_HIGHMEM | __GFP_MOVABLE;
132562306a36Sopenharmony_ci	ret = zpool_malloc(zpool, dlen, gfp, &handle);
132662306a36Sopenharmony_ci	if (ret == -ENOSPC) {
132762306a36Sopenharmony_ci		zswap_reject_compress_poor++;
132862306a36Sopenharmony_ci		goto put_dstmem;
132962306a36Sopenharmony_ci	}
133062306a36Sopenharmony_ci	if (ret) {
133162306a36Sopenharmony_ci		zswap_reject_alloc_fail++;
133262306a36Sopenharmony_ci		goto put_dstmem;
133362306a36Sopenharmony_ci	}
133462306a36Sopenharmony_ci	buf = zpool_map_handle(zpool, handle, ZPOOL_MM_WO);
133562306a36Sopenharmony_ci	memcpy(buf, dst, dlen);
133662306a36Sopenharmony_ci	zpool_unmap_handle(zpool, handle);
133762306a36Sopenharmony_ci	mutex_unlock(acomp_ctx->mutex);
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	/* populate entry */
134062306a36Sopenharmony_ci	entry->swpentry = swp_entry(type, offset);
134162306a36Sopenharmony_ci	entry->handle = handle;
134262306a36Sopenharmony_ci	entry->length = dlen;
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ciinsert_entry:
134562306a36Sopenharmony_ci	entry->objcg = objcg;
134662306a36Sopenharmony_ci	if (objcg) {
134762306a36Sopenharmony_ci		obj_cgroup_charge_zswap(objcg, entry->length);
134862306a36Sopenharmony_ci		/* Account before objcg ref is moved to tree */
134962306a36Sopenharmony_ci		count_objcg_event(objcg, ZSWPOUT);
135062306a36Sopenharmony_ci	}
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	/* map */
135362306a36Sopenharmony_ci	spin_lock(&tree->lock);
135462306a36Sopenharmony_ci	/*
135562306a36Sopenharmony_ci	 * A duplicate entry should have been removed at the beginning of this
135662306a36Sopenharmony_ci	 * function. Since the swap entry should be pinned, if a duplicate is
135762306a36Sopenharmony_ci	 * found again here it means that something went wrong in the swap
135862306a36Sopenharmony_ci	 * cache.
135962306a36Sopenharmony_ci	 */
136062306a36Sopenharmony_ci	while (zswap_rb_insert(&tree->rbroot, entry, &dupentry) == -EEXIST) {
136162306a36Sopenharmony_ci		WARN_ON(1);
136262306a36Sopenharmony_ci		zswap_duplicate_entry++;
136362306a36Sopenharmony_ci		zswap_invalidate_entry(tree, dupentry);
136462306a36Sopenharmony_ci	}
136562306a36Sopenharmony_ci	if (entry->length) {
136662306a36Sopenharmony_ci		spin_lock(&entry->pool->lru_lock);
136762306a36Sopenharmony_ci		list_add(&entry->lru, &entry->pool->lru);
136862306a36Sopenharmony_ci		spin_unlock(&entry->pool->lru_lock);
136962306a36Sopenharmony_ci	}
137062306a36Sopenharmony_ci	spin_unlock(&tree->lock);
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	/* update stats */
137362306a36Sopenharmony_ci	atomic_inc(&zswap_stored_pages);
137462306a36Sopenharmony_ci	zswap_update_total_size();
137562306a36Sopenharmony_ci	count_vm_event(ZSWPOUT);
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	return true;
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_ciput_dstmem:
138062306a36Sopenharmony_ci	mutex_unlock(acomp_ctx->mutex);
138162306a36Sopenharmony_ci	zswap_pool_put(entry->pool);
138262306a36Sopenharmony_cifreepage:
138362306a36Sopenharmony_ci	zswap_entry_cache_free(entry);
138462306a36Sopenharmony_cireject:
138562306a36Sopenharmony_ci	if (objcg)
138662306a36Sopenharmony_ci		obj_cgroup_put(objcg);
138762306a36Sopenharmony_ci	return false;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_cishrink:
139062306a36Sopenharmony_ci	pool = zswap_pool_last_get();
139162306a36Sopenharmony_ci	if (pool && !queue_work(shrink_wq, &pool->shrink_work))
139262306a36Sopenharmony_ci		zswap_pool_put(pool);
139362306a36Sopenharmony_ci	goto reject;
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_cibool zswap_load(struct folio *folio)
139762306a36Sopenharmony_ci{
139862306a36Sopenharmony_ci	swp_entry_t swp = folio->swap;
139962306a36Sopenharmony_ci	int type = swp_type(swp);
140062306a36Sopenharmony_ci	pgoff_t offset = swp_offset(swp);
140162306a36Sopenharmony_ci	struct page *page = &folio->page;
140262306a36Sopenharmony_ci	struct zswap_tree *tree = zswap_trees[type];
140362306a36Sopenharmony_ci	struct zswap_entry *entry;
140462306a36Sopenharmony_ci	struct scatterlist input, output;
140562306a36Sopenharmony_ci	struct crypto_acomp_ctx *acomp_ctx;
140662306a36Sopenharmony_ci	u8 *src, *dst, *tmp;
140762306a36Sopenharmony_ci	struct zpool *zpool;
140862306a36Sopenharmony_ci	unsigned int dlen;
140962306a36Sopenharmony_ci	bool ret;
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	VM_WARN_ON_ONCE(!folio_test_locked(folio));
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	/* find */
141462306a36Sopenharmony_ci	spin_lock(&tree->lock);
141562306a36Sopenharmony_ci	entry = zswap_entry_find_get(&tree->rbroot, offset);
141662306a36Sopenharmony_ci	if (!entry) {
141762306a36Sopenharmony_ci		spin_unlock(&tree->lock);
141862306a36Sopenharmony_ci		return false;
141962306a36Sopenharmony_ci	}
142062306a36Sopenharmony_ci	spin_unlock(&tree->lock);
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	if (!entry->length) {
142362306a36Sopenharmony_ci		dst = kmap_atomic(page);
142462306a36Sopenharmony_ci		zswap_fill_page(dst, entry->value);
142562306a36Sopenharmony_ci		kunmap_atomic(dst);
142662306a36Sopenharmony_ci		ret = true;
142762306a36Sopenharmony_ci		goto stats;
142862306a36Sopenharmony_ci	}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	zpool = zswap_find_zpool(entry);
143162306a36Sopenharmony_ci	if (!zpool_can_sleep_mapped(zpool)) {
143262306a36Sopenharmony_ci		tmp = kmalloc(entry->length, GFP_KERNEL);
143362306a36Sopenharmony_ci		if (!tmp) {
143462306a36Sopenharmony_ci			ret = false;
143562306a36Sopenharmony_ci			goto freeentry;
143662306a36Sopenharmony_ci		}
143762306a36Sopenharmony_ci	}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	/* decompress */
144062306a36Sopenharmony_ci	dlen = PAGE_SIZE;
144162306a36Sopenharmony_ci	src = zpool_map_handle(zpool, entry->handle, ZPOOL_MM_RO);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	if (!zpool_can_sleep_mapped(zpool)) {
144462306a36Sopenharmony_ci		memcpy(tmp, src, entry->length);
144562306a36Sopenharmony_ci		src = tmp;
144662306a36Sopenharmony_ci		zpool_unmap_handle(zpool, entry->handle);
144762306a36Sopenharmony_ci	}
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
145062306a36Sopenharmony_ci	mutex_lock(acomp_ctx->mutex);
145162306a36Sopenharmony_ci	sg_init_one(&input, src, entry->length);
145262306a36Sopenharmony_ci	sg_init_table(&output, 1);
145362306a36Sopenharmony_ci	sg_set_page(&output, page, PAGE_SIZE, 0);
145462306a36Sopenharmony_ci	acomp_request_set_params(acomp_ctx->req, &input, &output, entry->length, dlen);
145562306a36Sopenharmony_ci	if (crypto_wait_req(crypto_acomp_decompress(acomp_ctx->req), &acomp_ctx->wait))
145662306a36Sopenharmony_ci		WARN_ON(1);
145762306a36Sopenharmony_ci	mutex_unlock(acomp_ctx->mutex);
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	if (zpool_can_sleep_mapped(zpool))
146062306a36Sopenharmony_ci		zpool_unmap_handle(zpool, entry->handle);
146162306a36Sopenharmony_ci	else
146262306a36Sopenharmony_ci		kfree(tmp);
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	ret = true;
146562306a36Sopenharmony_cistats:
146662306a36Sopenharmony_ci	count_vm_event(ZSWPIN);
146762306a36Sopenharmony_ci	if (entry->objcg)
146862306a36Sopenharmony_ci		count_objcg_event(entry->objcg, ZSWPIN);
146962306a36Sopenharmony_cifreeentry:
147062306a36Sopenharmony_ci	spin_lock(&tree->lock);
147162306a36Sopenharmony_ci	if (ret && zswap_exclusive_loads_enabled) {
147262306a36Sopenharmony_ci		zswap_invalidate_entry(tree, entry);
147362306a36Sopenharmony_ci		folio_mark_dirty(folio);
147462306a36Sopenharmony_ci	} else if (entry->length) {
147562306a36Sopenharmony_ci		spin_lock(&entry->pool->lru_lock);
147662306a36Sopenharmony_ci		list_move(&entry->lru, &entry->pool->lru);
147762306a36Sopenharmony_ci		spin_unlock(&entry->pool->lru_lock);
147862306a36Sopenharmony_ci	}
147962306a36Sopenharmony_ci	zswap_entry_put(tree, entry);
148062306a36Sopenharmony_ci	spin_unlock(&tree->lock);
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	return ret;
148362306a36Sopenharmony_ci}
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_civoid zswap_invalidate(int type, pgoff_t offset)
148662306a36Sopenharmony_ci{
148762306a36Sopenharmony_ci	struct zswap_tree *tree = zswap_trees[type];
148862306a36Sopenharmony_ci	struct zswap_entry *entry;
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	/* find */
149162306a36Sopenharmony_ci	spin_lock(&tree->lock);
149262306a36Sopenharmony_ci	entry = zswap_rb_search(&tree->rbroot, offset);
149362306a36Sopenharmony_ci	if (!entry) {
149462306a36Sopenharmony_ci		/* entry was written back */
149562306a36Sopenharmony_ci		spin_unlock(&tree->lock);
149662306a36Sopenharmony_ci		return;
149762306a36Sopenharmony_ci	}
149862306a36Sopenharmony_ci	zswap_invalidate_entry(tree, entry);
149962306a36Sopenharmony_ci	spin_unlock(&tree->lock);
150062306a36Sopenharmony_ci}
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_civoid zswap_swapon(int type)
150362306a36Sopenharmony_ci{
150462306a36Sopenharmony_ci	struct zswap_tree *tree;
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci	tree = kzalloc(sizeof(*tree), GFP_KERNEL);
150762306a36Sopenharmony_ci	if (!tree) {
150862306a36Sopenharmony_ci		pr_err("alloc failed, zswap disabled for swap type %d\n", type);
150962306a36Sopenharmony_ci		return;
151062306a36Sopenharmony_ci	}
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	tree->rbroot = RB_ROOT;
151362306a36Sopenharmony_ci	spin_lock_init(&tree->lock);
151462306a36Sopenharmony_ci	zswap_trees[type] = tree;
151562306a36Sopenharmony_ci}
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_civoid zswap_swapoff(int type)
151862306a36Sopenharmony_ci{
151962306a36Sopenharmony_ci	struct zswap_tree *tree = zswap_trees[type];
152062306a36Sopenharmony_ci	struct zswap_entry *entry, *n;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	if (!tree)
152362306a36Sopenharmony_ci		return;
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	/* walk the tree and free everything */
152662306a36Sopenharmony_ci	spin_lock(&tree->lock);
152762306a36Sopenharmony_ci	rbtree_postorder_for_each_entry_safe(entry, n, &tree->rbroot, rbnode)
152862306a36Sopenharmony_ci		zswap_free_entry(entry);
152962306a36Sopenharmony_ci	tree->rbroot = RB_ROOT;
153062306a36Sopenharmony_ci	spin_unlock(&tree->lock);
153162306a36Sopenharmony_ci	kfree(tree);
153262306a36Sopenharmony_ci	zswap_trees[type] = NULL;
153362306a36Sopenharmony_ci}
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci/*********************************
153662306a36Sopenharmony_ci* debugfs functions
153762306a36Sopenharmony_ci**********************************/
153862306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
153962306a36Sopenharmony_ci#include <linux/debugfs.h>
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_cistatic struct dentry *zswap_debugfs_root;
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_cistatic int zswap_debugfs_init(void)
154462306a36Sopenharmony_ci{
154562306a36Sopenharmony_ci	if (!debugfs_initialized())
154662306a36Sopenharmony_ci		return -ENODEV;
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	zswap_debugfs_root = debugfs_create_dir("zswap", NULL);
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	debugfs_create_u64("pool_limit_hit", 0444,
155162306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_pool_limit_hit);
155262306a36Sopenharmony_ci	debugfs_create_u64("reject_reclaim_fail", 0444,
155362306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_reject_reclaim_fail);
155462306a36Sopenharmony_ci	debugfs_create_u64("reject_alloc_fail", 0444,
155562306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_reject_alloc_fail);
155662306a36Sopenharmony_ci	debugfs_create_u64("reject_kmemcache_fail", 0444,
155762306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_reject_kmemcache_fail);
155862306a36Sopenharmony_ci	debugfs_create_u64("reject_compress_poor", 0444,
155962306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_reject_compress_poor);
156062306a36Sopenharmony_ci	debugfs_create_u64("written_back_pages", 0444,
156162306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_written_back_pages);
156262306a36Sopenharmony_ci	debugfs_create_u64("duplicate_entry", 0444,
156362306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_duplicate_entry);
156462306a36Sopenharmony_ci	debugfs_create_u64("pool_total_size", 0444,
156562306a36Sopenharmony_ci			   zswap_debugfs_root, &zswap_pool_total_size);
156662306a36Sopenharmony_ci	debugfs_create_atomic_t("stored_pages", 0444,
156762306a36Sopenharmony_ci				zswap_debugfs_root, &zswap_stored_pages);
156862306a36Sopenharmony_ci	debugfs_create_atomic_t("same_filled_pages", 0444,
156962306a36Sopenharmony_ci				zswap_debugfs_root, &zswap_same_filled_pages);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	return 0;
157262306a36Sopenharmony_ci}
157362306a36Sopenharmony_ci#else
157462306a36Sopenharmony_cistatic int zswap_debugfs_init(void)
157562306a36Sopenharmony_ci{
157662306a36Sopenharmony_ci	return 0;
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci#endif
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci/*********************************
158162306a36Sopenharmony_ci* module init and exit
158262306a36Sopenharmony_ci**********************************/
158362306a36Sopenharmony_cistatic int zswap_setup(void)
158462306a36Sopenharmony_ci{
158562306a36Sopenharmony_ci	struct zswap_pool *pool;
158662306a36Sopenharmony_ci	int ret;
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	zswap_entry_cache = KMEM_CACHE(zswap_entry, 0);
158962306a36Sopenharmony_ci	if (!zswap_entry_cache) {
159062306a36Sopenharmony_ci		pr_err("entry cache creation failed\n");
159162306a36Sopenharmony_ci		goto cache_fail;
159262306a36Sopenharmony_ci	}
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	ret = cpuhp_setup_state(CPUHP_MM_ZSWP_MEM_PREPARE, "mm/zswap:prepare",
159562306a36Sopenharmony_ci				zswap_dstmem_prepare, zswap_dstmem_dead);
159662306a36Sopenharmony_ci	if (ret) {
159762306a36Sopenharmony_ci		pr_err("dstmem alloc failed\n");
159862306a36Sopenharmony_ci		goto dstmem_fail;
159962306a36Sopenharmony_ci	}
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci	ret = cpuhp_setup_state_multi(CPUHP_MM_ZSWP_POOL_PREPARE,
160262306a36Sopenharmony_ci				      "mm/zswap_pool:prepare",
160362306a36Sopenharmony_ci				      zswap_cpu_comp_prepare,
160462306a36Sopenharmony_ci				      zswap_cpu_comp_dead);
160562306a36Sopenharmony_ci	if (ret)
160662306a36Sopenharmony_ci		goto hp_fail;
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	pool = __zswap_pool_create_fallback();
160962306a36Sopenharmony_ci	if (pool) {
161062306a36Sopenharmony_ci		pr_info("loaded using pool %s/%s\n", pool->tfm_name,
161162306a36Sopenharmony_ci			zpool_get_type(pool->zpools[0]));
161262306a36Sopenharmony_ci		list_add(&pool->list, &zswap_pools);
161362306a36Sopenharmony_ci		zswap_has_pool = true;
161462306a36Sopenharmony_ci	} else {
161562306a36Sopenharmony_ci		pr_err("pool creation failed\n");
161662306a36Sopenharmony_ci		zswap_enabled = false;
161762306a36Sopenharmony_ci	}
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci	shrink_wq = create_workqueue("zswap-shrink");
162062306a36Sopenharmony_ci	if (!shrink_wq)
162162306a36Sopenharmony_ci		goto fallback_fail;
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	if (zswap_debugfs_init())
162462306a36Sopenharmony_ci		pr_warn("debugfs initialization failed\n");
162562306a36Sopenharmony_ci	zswap_init_state = ZSWAP_INIT_SUCCEED;
162662306a36Sopenharmony_ci	return 0;
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_cifallback_fail:
162962306a36Sopenharmony_ci	if (pool)
163062306a36Sopenharmony_ci		zswap_pool_destroy(pool);
163162306a36Sopenharmony_cihp_fail:
163262306a36Sopenharmony_ci	cpuhp_remove_state(CPUHP_MM_ZSWP_MEM_PREPARE);
163362306a36Sopenharmony_cidstmem_fail:
163462306a36Sopenharmony_ci	kmem_cache_destroy(zswap_entry_cache);
163562306a36Sopenharmony_cicache_fail:
163662306a36Sopenharmony_ci	/* if built-in, we aren't unloaded on failure; don't allow use */
163762306a36Sopenharmony_ci	zswap_init_state = ZSWAP_INIT_FAILED;
163862306a36Sopenharmony_ci	zswap_enabled = false;
163962306a36Sopenharmony_ci	return -ENOMEM;
164062306a36Sopenharmony_ci}
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_cistatic int __init zswap_init(void)
164362306a36Sopenharmony_ci{
164462306a36Sopenharmony_ci	if (!zswap_enabled)
164562306a36Sopenharmony_ci		return 0;
164662306a36Sopenharmony_ci	return zswap_setup();
164762306a36Sopenharmony_ci}
164862306a36Sopenharmony_ci/* must be late so crypto has time to come up */
164962306a36Sopenharmony_cilate_initcall(zswap_init);
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ciMODULE_AUTHOR("Seth Jennings <sjennings@variantweb.net>");
165262306a36Sopenharmony_ciMODULE_DESCRIPTION("Compressed cache for swap pages");
1653