Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * z3fold.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Author: Vitaly Wool <vitaly.wool@konsulko.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * Copyright (C) 2016, Sony Mobile Communications Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * This implementation is based on zbud written by Seth Jennings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * z3fold is an special purpose allocator for storing compressed pages. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  * can store up to three compressed pages per page which improves the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * compression ratio of zbud while retaining its main concepts (e. g. always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * storing an integral number of objects per page) and simplicity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * It still has simple and deterministic reclaim properties that make it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  * preferable to a higher density approach (with no requirement on integral
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * number of object per page) when reclaim is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  * As in zbud, pages are divided into "chunks".  The size of the chunks is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * fixed at compile time and is determined by NCHUNKS_ORDER below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  * z3fold doesn't export any API and is meant to be used via zpool API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/cpumask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/page-flags.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/migrate.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/node.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/compaction.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/percpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/pseudo_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <linux/preempt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <linux/zpool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <linux/magic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include <linux/kmemleak.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  * NCHUNKS_ORDER determines the internal allocation granularity, effectively
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50)  * adjusting internal fragmentation.  It also determines the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51)  * freelists maintained in each pool. NCHUNKS_ORDER of 6 means that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52)  * allocation granularity will be in chunks of size PAGE_SIZE/64. Some chunks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53)  * in the beginning of an allocated page are occupied by z3fold header, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  * NCHUNKS will be calculated to 63 (or 62 in case CONFIG_DEBUG_SPINLOCK=y),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  * which shows the max number of free chunks in z3fold page, also there will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56)  * be 63, or 62, respectively, freelists per pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define NCHUNKS_ORDER	6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define CHUNK_SHIFT	(PAGE_SHIFT - NCHUNKS_ORDER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define CHUNK_SIZE	(1 << CHUNK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define ZHDR_SIZE_ALIGNED round_up(sizeof(struct z3fold_header), CHUNK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define ZHDR_CHUNKS	(ZHDR_SIZE_ALIGNED >> CHUNK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define TOTAL_CHUNKS	(PAGE_SIZE >> CHUNK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define NCHUNKS		((PAGE_SIZE - ZHDR_SIZE_ALIGNED) >> CHUNK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define BUDDY_MASK	(0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define BUDDY_SHIFT	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define SLOTS_ALIGN	(0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) /*****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72)  * Structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) *****************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) struct z3fold_pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) struct z3fold_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	int (*evict)(struct z3fold_pool *pool, unsigned long handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) enum buddy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 	HEADLESS = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	FIRST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 	MIDDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	LAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	BUDDIES_MAX = LAST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) struct z3fold_buddy_slots {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	 * we are using BUDDY_MASK in handle_to_buddy etc. so there should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	 * be enough slots to hold all possible variants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	unsigned long slot[BUDDY_MASK + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	unsigned long pool; /* back link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	rwlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define HANDLE_FLAG_MASK	(0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  * struct z3fold_header - z3fold page metadata occupying first chunks of each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  *			z3fold page, except for HEADLESS pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  * @buddy:		links the z3fold page into the relevant list in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  *			pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)  * @page_lock:		per-page lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  * @refcount:		reference count for the z3fold page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * @work:		work_struct for page layout optimization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  * @slots:		pointer to the structure holding buddy slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107)  * @pool:		pointer to the containing pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108)  * @cpu:		CPU which this page "belongs" to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109)  * @first_chunks:	the size of the first buddy in chunks, 0 if free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110)  * @middle_chunks:	the size of the middle buddy in chunks, 0 if free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111)  * @last_chunks:	the size of the last buddy in chunks, 0 if free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112)  * @first_num:		the starting number (for the first handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113)  * @mapped_count:	the number of objects currently mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) struct z3fold_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 	struct list_head buddy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	spinlock_t page_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	struct kref refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	struct z3fold_buddy_slots *slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	struct z3fold_pool *pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	short cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	unsigned short first_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	unsigned short middle_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	unsigned short last_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	unsigned short start_middle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	unsigned short first_num:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 	unsigned short mapped_count:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	unsigned short foreign_handles:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133)  * struct z3fold_pool - stores metadata for each z3fold pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134)  * @name:	pool name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135)  * @lock:	protects pool unbuddied/lru lists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136)  * @stale_lock:	protects pool stale page list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137)  * @unbuddied:	per-cpu array of lists tracking z3fold pages that contain 2-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138)  *		buddies; the list each z3fold page is added to depends on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139)  *		the size of its free region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140)  * @lru:	list tracking the z3fold pages in LRU order by most recently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141)  *		added buddy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142)  * @stale:	list of pages marked for freeing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143)  * @pages_nr:	number of z3fold pages in the pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144)  * @c_handle:	cache for z3fold_buddy_slots allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145)  * @ops:	pointer to a structure of user defined operations specified at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146)  *		pool creation time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147)  * @compact_wq:	workqueue for page layout background optimization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148)  * @release_wq:	workqueue for safe page release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149)  * @work:	work_struct for safe page release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150)  * @inode:	inode for z3fold pseudo filesystem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  * This structure is allocated at pool creation time and maintains metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  * pertaining to a particular z3fold pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) struct z3fold_pool {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	spinlock_t stale_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	struct list_head *unbuddied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	struct list_head lru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	struct list_head stale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	atomic64_t pages_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	struct kmem_cache *c_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	const struct z3fold_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	struct zpool *zpool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	const struct zpool_ops *zpool_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	struct workqueue_struct *compact_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	struct workqueue_struct *release_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174)  * Internal z3fold page flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) enum z3fold_page_flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	PAGE_HEADLESS = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	MIDDLE_CHUNK_MAPPED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	NEEDS_COMPACTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	PAGE_STALE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	PAGE_CLAIMED, /* by either reclaim or free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185)  * handle flags, go under HANDLE_FLAG_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) enum z3fold_handle_flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	HANDLES_NOFREE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192)  * Forward declarations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) static struct z3fold_header *__z3fold_alloc(struct z3fold_pool *, size_t, bool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) static void compact_page_work(struct work_struct *w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) /*****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)  * Helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) *****************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) /* Converts an allocation size in bytes to size in z3fold chunks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) static int size_to_chunks(size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) #define for_each_unbuddied_list(_iter, _begin) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) static inline struct z3fold_buddy_slots *alloc_slots(struct z3fold_pool *pool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 							gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	struct z3fold_buddy_slots *slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	slots = kmem_cache_zalloc(pool->c_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 				 (gfp & ~(__GFP_HIGHMEM | __GFP_MOVABLE)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	if (slots) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 		/* It will be freed separately in free_handle(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 		kmemleak_not_leak(slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 		slots->pool = (unsigned long)pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 		rwlock_init(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	return slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) static inline struct z3fold_pool *slots_to_pool(struct z3fold_buddy_slots *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	return (struct z3fold_pool *)(s->pool & ~HANDLE_FLAG_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) static inline struct z3fold_buddy_slots *handle_to_slots(unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	return (struct z3fold_buddy_slots *)(handle & ~(SLOTS_ALIGN - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) /* Lock a z3fold page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) static inline void z3fold_page_lock(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	spin_lock(&zhdr->page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) /* Try to lock a z3fold page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) static inline int z3fold_page_trylock(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	return spin_trylock(&zhdr->page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) /* Unlock a z3fold page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) static inline void z3fold_page_unlock(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	spin_unlock(&zhdr->page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) static inline struct z3fold_header *__get_z3fold_header(unsigned long handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 							bool lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	struct z3fold_buddy_slots *slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	int locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	if (!(handle & (1 << PAGE_HEADLESS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 		slots = handle_to_slots(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 			unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 			read_lock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 			addr = *(unsigned long *)handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 			zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 			if (lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 				locked = z3fold_page_trylock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 			read_unlock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 			if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 			cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 		} while (lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		zhdr = (struct z3fold_header *)(handle & PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	return zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) /* Returns the z3fold page where a given handle is stored */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) static inline struct z3fold_header *handle_to_z3fold_header(unsigned long h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	return __get_z3fold_header(h, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) /* return locked z3fold page if it's not headless */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) static inline struct z3fold_header *get_z3fold_header(unsigned long h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	return __get_z3fold_header(h, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) static inline void put_z3fold_header(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	struct page *page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	if (!test_bit(PAGE_HEADLESS, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) static inline void free_handle(unsigned long handle, struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	struct z3fold_buddy_slots *slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	bool is_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	if (handle & (1 << PAGE_HEADLESS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	if (WARN_ON(*(unsigned long *)handle == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	slots = handle_to_slots(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	write_lock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	*(unsigned long *)handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	if (test_bit(HANDLES_NOFREE, &slots->pool)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 		write_unlock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		return; /* simple case, nothing else to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	if (zhdr->slots != slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		zhdr->foreign_handles--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	is_free = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	for (i = 0; i <= BUDDY_MASK; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 		if (slots->slot[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 			is_free = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	write_unlock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	if (is_free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		struct z3fold_pool *pool = slots_to_pool(slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		if (zhdr->slots == slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 			zhdr->slots = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 		kmem_cache_free(pool->c_handle, slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) static int z3fold_init_fs_context(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	return init_pseudo(fc, Z3FOLD_MAGIC) ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) static struct file_system_type z3fold_fs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	.name		= "z3fold",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	.init_fs_context = z3fold_init_fs_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	.kill_sb	= kill_anon_super,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) static struct vfsmount *z3fold_mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) static int z3fold_mount(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	z3fold_mnt = kern_mount(&z3fold_fs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	if (IS_ERR(z3fold_mnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		ret = PTR_ERR(z3fold_mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) static void z3fold_unmount(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	kern_unmount(z3fold_mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) static const struct address_space_operations z3fold_aops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) static int z3fold_register_migration(struct z3fold_pool *pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	pool->inode = alloc_anon_inode(z3fold_mnt->mnt_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	if (IS_ERR(pool->inode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		pool->inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	pool->inode->i_mapping->private_data = pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	pool->inode->i_mapping->a_ops = &z3fold_aops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) static void z3fold_unregister_migration(struct z3fold_pool *pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	if (pool->inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 		iput(pool->inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)  }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) /* Initializes the z3fold header of a newly allocated z3fold page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) static struct z3fold_header *init_z3fold_page(struct page *page, bool headless,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 					struct z3fold_pool *pool, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	struct z3fold_header *zhdr = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	struct z3fold_buddy_slots *slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	INIT_LIST_HEAD(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	clear_bit(PAGE_HEADLESS, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	clear_bit(NEEDS_COMPACTING, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	clear_bit(PAGE_STALE, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	if (headless)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		return zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	slots = alloc_slots(pool, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	if (!slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	spin_lock_init(&zhdr->page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	kref_init(&zhdr->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	zhdr->first_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	zhdr->middle_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	zhdr->last_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	zhdr->first_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	zhdr->start_middle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	zhdr->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	zhdr->foreign_handles = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	zhdr->mapped_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	zhdr->slots = slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	zhdr->pool = pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	INIT_LIST_HEAD(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	INIT_WORK(&zhdr->work, compact_page_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	return zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) /* Resets the struct page fields and frees the page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) static void free_z3fold_page(struct page *page, bool headless)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	if (!headless) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 		lock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		__ClearPageMovable(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		unlock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	ClearPagePrivate(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	__free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) /* Helper function to build the index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) static inline int __idx(struct z3fold_header *zhdr, enum buddy bud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	return (bud + zhdr->first_num) & BUDDY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452)  * Encodes the handle of a particular buddy within a z3fold page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453)  * Pool lock should be held as this function accesses first_num
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) static unsigned long __encode_handle(struct z3fold_header *zhdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 				struct z3fold_buddy_slots *slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 				enum buddy bud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	unsigned long h = (unsigned long)zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	 * For a headless page, its handle is its pointer with the extra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	 * PAGE_HEADLESS bit set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	if (bud == HEADLESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		return h | (1 << PAGE_HEADLESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	/* otherwise, return pointer to encoded handle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	idx = __idx(zhdr, bud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	h += idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	if (bud == LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		h |= (zhdr->last_chunks << BUDDY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	write_lock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	slots->slot[idx] = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	write_unlock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	return (unsigned long)&slots->slot[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) static unsigned long encode_handle(struct z3fold_header *zhdr, enum buddy bud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	return __encode_handle(zhdr, zhdr->slots, bud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) /* only for LAST bud, returns zero otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) static unsigned short handle_to_chunks(unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	struct z3fold_buddy_slots *slots = handle_to_slots(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	read_lock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	addr = *(unsigned long *)handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	read_unlock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	return (addr & ~PAGE_MASK) >> BUDDY_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  * (handle & BUDDY_MASK) < zhdr->first_num is possible in encode_handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  *  but that doesn't matter. because the masking will result in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  *  correct buddy number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) static enum buddy handle_to_buddy(unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	struct z3fold_buddy_slots *slots = handle_to_slots(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	read_lock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	WARN_ON(handle & (1 << PAGE_HEADLESS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	addr = *(unsigned long *)handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	read_unlock(&slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	return (addr - zhdr->first_num) & BUDDY_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) static inline struct z3fold_pool *zhdr_to_pool(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	return zhdr->pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	struct page *page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	struct z3fold_pool *pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	WARN_ON(!list_empty(&zhdr->buddy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	set_bit(PAGE_STALE, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	clear_bit(NEEDS_COMPACTING, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	if (!list_empty(&page->lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		list_del_init(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	spin_lock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	list_add(&zhdr->buddy, &pool->stale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	queue_work(pool->release_wq, &pool->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	spin_unlock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) static void __attribute__((__unused__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 			release_z3fold_page(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 						refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	__release_z3fold_page(zhdr, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) static void release_z3fold_page_locked(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 						refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	WARN_ON(z3fold_page_trylock(zhdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	__release_z3fold_page(zhdr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) static void release_z3fold_page_locked_list(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	struct z3fold_header *zhdr = container_of(ref, struct z3fold_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 					       refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	struct z3fold_pool *pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	WARN_ON(z3fold_page_trylock(zhdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	__release_z3fold_page(zhdr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) static void free_pages_work(struct work_struct *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	struct z3fold_pool *pool = container_of(w, struct z3fold_pool, work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	spin_lock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	while (!list_empty(&pool->stale)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		struct z3fold_header *zhdr = list_first_entry(&pool->stale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 						struct z3fold_header, buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		struct page *page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		list_del(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		if (WARN_ON(!test_bit(PAGE_STALE, &page->private)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		spin_unlock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		cancel_work_sync(&zhdr->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		free_z3fold_page(page, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		spin_lock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	spin_unlock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)  * Returns the number of free chunks in a z3fold page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598)  * NB: can't be used with HEADLESS pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) static int num_free_chunks(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	int nfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	 * If there is a middle object, pick up the bigger free space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	 * either before or after it. Otherwise just subtract the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	 * of chunks occupied by the first and the last objects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	if (zhdr->middle_chunks != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		int nfree_before = zhdr->first_chunks ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 			0 : zhdr->start_middle - ZHDR_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		int nfree_after = zhdr->last_chunks ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 			0 : TOTAL_CHUNKS -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 				(zhdr->start_middle + zhdr->middle_chunks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		nfree = max(nfree_before, nfree_after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		nfree = NCHUNKS - zhdr->first_chunks - zhdr->last_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	return nfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) /* Add to the appropriate unbuddied list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) static inline void add_to_unbuddied(struct z3fold_pool *pool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 				struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 			zhdr->middle_chunks == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		struct list_head *unbuddied = get_cpu_ptr(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		int freechunks = num_free_chunks(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 		spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		list_add(&zhdr->buddy, &unbuddied[freechunks]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		zhdr->cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		put_cpu_ptr(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) static inline enum buddy get_free_buddy(struct z3fold_header *zhdr, int chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	enum buddy bud = HEADLESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	if (zhdr->middle_chunks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		if (!zhdr->first_chunks &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		    chunks <= zhdr->start_middle - ZHDR_CHUNKS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 			bud = FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 		else if (!zhdr->last_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 			bud = LAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 		if (!zhdr->first_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 			bud = FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 		else if (!zhdr->last_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 			bud = LAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 			bud = MIDDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	return bud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) static inline void *mchunk_memmove(struct z3fold_header *zhdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 				unsigned short dst_chunk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	void *beg = zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	return memmove(beg + (dst_chunk << CHUNK_SHIFT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		       beg + (zhdr->start_middle << CHUNK_SHIFT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		       zhdr->middle_chunks << CHUNK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) static inline bool buddy_single(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	return !((zhdr->first_chunks && zhdr->middle_chunks) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 			(zhdr->first_chunks && zhdr->last_chunks) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 			(zhdr->middle_chunks && zhdr->last_chunks));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) static struct z3fold_header *compact_single_buddy(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	struct z3fold_pool *pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	void *p = zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	unsigned long old_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	size_t sz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 	struct z3fold_header *new_zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	int first_idx = __idx(zhdr, FIRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	int middle_idx = __idx(zhdr, MIDDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	int last_idx = __idx(zhdr, LAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 	unsigned short *moved_chunks = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	 * No need to protect slots here -- all the slots are "local" and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	 * the page lock is already taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	if (zhdr->first_chunks && zhdr->slots->slot[first_idx]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		p += ZHDR_SIZE_ALIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		sz = zhdr->first_chunks << CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		old_handle = (unsigned long)&zhdr->slots->slot[first_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		moved_chunks = &zhdr->first_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	} else if (zhdr->middle_chunks && zhdr->slots->slot[middle_idx]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		p += zhdr->start_middle << CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		sz = zhdr->middle_chunks << CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		old_handle = (unsigned long)&zhdr->slots->slot[middle_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		moved_chunks = &zhdr->middle_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	} else if (zhdr->last_chunks && zhdr->slots->slot[last_idx]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		p += PAGE_SIZE - (zhdr->last_chunks << CHUNK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		sz = zhdr->last_chunks << CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		old_handle = (unsigned long)&zhdr->slots->slot[last_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		moved_chunks = &zhdr->last_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	if (sz > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		enum buddy new_bud = HEADLESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		short chunks = size_to_chunks(sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		void *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		new_zhdr = __z3fold_alloc(pool, sz, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		if (!new_zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		if (WARN_ON(new_zhdr == zhdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 			goto out_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		new_bud = get_free_buddy(new_zhdr, chunks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 		q = new_zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 		switch (new_bud) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 		case FIRST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 			new_zhdr->first_chunks = chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 			q += ZHDR_SIZE_ALIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		case MIDDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 			new_zhdr->middle_chunks = chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 			new_zhdr->start_middle =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 				new_zhdr->first_chunks + ZHDR_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 			q += new_zhdr->start_middle << CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		case LAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 			new_zhdr->last_chunks = chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 			q += PAGE_SIZE - (new_zhdr->last_chunks << CHUNK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 			goto out_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		new_zhdr->foreign_handles++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		memcpy(q, p, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		write_lock(&zhdr->slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		*(unsigned long *)old_handle = (unsigned long)new_zhdr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 			__idx(new_zhdr, new_bud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 		if (new_bud == LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 			*(unsigned long *)old_handle |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 					(new_zhdr->last_chunks << BUDDY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		write_unlock(&zhdr->slots->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		add_to_unbuddied(pool, new_zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 		z3fold_page_unlock(new_zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 		*moved_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	return new_zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) out_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	if (new_zhdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 		if (kref_put(&new_zhdr->refcount, release_z3fold_page_locked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 			atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 			add_to_unbuddied(pool, new_zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 			z3fold_page_unlock(new_zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) #define BIG_CHUNK_GAP	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) /* Has to be called with lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) static int z3fold_compact_page(struct z3fold_header *zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	struct page *page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	if (test_bit(MIDDLE_CHUNK_MAPPED, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 		return 0; /* can't move middle chunk, it's used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	if (unlikely(PageIsolated(page)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	if (zhdr->middle_chunks == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		return 0; /* nothing to compact */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		/* move to the beginning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		mchunk_memmove(zhdr, ZHDR_CHUNKS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		zhdr->first_chunks = zhdr->middle_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		zhdr->middle_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		zhdr->start_middle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		zhdr->first_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	 * moving data is expensive, so let's only do that if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	 * there's substantial gain (at least BIG_CHUNK_GAP chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	if (zhdr->first_chunks != 0 && zhdr->last_chunks == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	    zhdr->start_middle - (zhdr->first_chunks + ZHDR_CHUNKS) >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 			BIG_CHUNK_GAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		mchunk_memmove(zhdr, zhdr->first_chunks + ZHDR_CHUNKS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	} else if (zhdr->last_chunks != 0 && zhdr->first_chunks == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		   TOTAL_CHUNKS - (zhdr->last_chunks + zhdr->start_middle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 					+ zhdr->middle_chunks) >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 			BIG_CHUNK_GAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		unsigned short new_start = TOTAL_CHUNKS - zhdr->last_chunks -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 			zhdr->middle_chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 		mchunk_memmove(zhdr, new_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 		zhdr->start_middle = new_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) static void do_compact_page(struct z3fold_header *zhdr, bool locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	struct z3fold_pool *pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	if (locked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 		WARN_ON(z3fold_page_trylock(zhdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		z3fold_page_lock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	if (WARN_ON(!test_and_clear_bit(NEEDS_COMPACTING, &page->private))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	if (test_bit(PAGE_STALE, &page->private) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	    test_and_set_bit(PAGE_CLAIMED, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	if (!zhdr->foreign_handles && buddy_single(zhdr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	    zhdr->mapped_count == 0 && compact_single_buddy(zhdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		if (kref_put(&zhdr->refcount, release_z3fold_page_locked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 			clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 			z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	z3fold_compact_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	add_to_unbuddied(pool, zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) static void compact_page_work(struct work_struct *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	struct z3fold_header *zhdr = container_of(w, struct z3fold_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 						work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	do_compact_page(zhdr, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) /* returns _locked_ z3fold page header or NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) static inline struct z3fold_header *__z3fold_alloc(struct z3fold_pool *pool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 						size_t size, bool can_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	struct z3fold_header *zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	struct list_head *unbuddied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	int chunks = size_to_chunks(size), i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) lookup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	/* First, try to find an unbuddied z3fold page. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	unbuddied = get_cpu_ptr(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	for_each_unbuddied_list(i, chunks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		struct list_head *l = &unbuddied[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		zhdr = list_first_entry_or_null(READ_ONCE(l),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 					struct z3fold_header, buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 		if (!zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 		/* Re-check under lock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 		spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 		l = &unbuddied[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 		if (unlikely(zhdr != list_first_entry(READ_ONCE(l),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 						struct z3fold_header, buddy)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		    !z3fold_page_trylock(zhdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 			zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 			put_cpu_ptr(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 			if (can_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 				cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 			goto lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		zhdr->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		if (test_bit(NEEDS_COMPACTING, &page->private) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		    test_bit(PAGE_CLAIMED, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 			z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 			zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 			put_cpu_ptr(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 			if (can_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 				cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 			goto lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		 * this page could not be removed from its unbuddied
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		 * list while pool lock was held, and then we've taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		 * page lock so kref_put could not be called before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		 * we got here, so it's safe to just call kref_get()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		kref_get(&zhdr->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	put_cpu_ptr(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	if (!zhdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		/* look for _exact_ match on other cpus' lists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		for_each_online_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 			struct list_head *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 			unbuddied = per_cpu_ptr(pool->unbuddied, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 			spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 			l = &unbuddied[chunks];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 			zhdr = list_first_entry_or_null(READ_ONCE(l),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 						struct z3fold_header, buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 			if (!zhdr || !z3fold_page_trylock(zhdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 				spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 				zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 			list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 			zhdr->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 			spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 			page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 			if (test_bit(NEEDS_COMPACTING, &page->private) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 			    test_bit(PAGE_CLAIMED, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 				z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 				zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 				if (can_sleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 					cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			kref_get(&zhdr->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	if (zhdr && !zhdr->slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		zhdr->slots = alloc_slots(pool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 					can_sleep ? GFP_NOIO : GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	return zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977)  * API Functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981)  * z3fold_create_pool() - create a new z3fold pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982)  * @name:	pool name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983)  * @gfp:	gfp flags when allocating the z3fold pool structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984)  * @ops:	user-defined operations for the z3fold pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986)  * Return: pointer to the new z3fold pool or NULL if the metadata allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987)  * failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		const struct z3fold_ops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	struct z3fold_pool *pool = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	int i, cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	pool = kzalloc(sizeof(struct z3fold_pool), gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	if (!pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	pool->c_handle = kmem_cache_create("z3fold_handle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 				sizeof(struct z3fold_buddy_slots),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 				SLOTS_ALIGN, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	if (!pool->c_handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		goto out_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	spin_lock_init(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	spin_lock_init(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	if (!pool->unbuddied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 		goto out_pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 	for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		struct list_head *unbuddied =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 				per_cpu_ptr(pool->unbuddied, cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		for_each_unbuddied_list(i, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 			INIT_LIST_HEAD(&unbuddied[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	INIT_LIST_HEAD(&pool->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	INIT_LIST_HEAD(&pool->stale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	atomic64_set(&pool->pages_nr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	pool->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	pool->compact_wq = create_singlethread_workqueue(pool->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	if (!pool->compact_wq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		goto out_unbuddied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	pool->release_wq = create_singlethread_workqueue(pool->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	if (!pool->release_wq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		goto out_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	if (z3fold_register_migration(pool))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		goto out_rwq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	INIT_WORK(&pool->work, free_pages_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	pool->ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	return pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) out_rwq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	destroy_workqueue(pool->release_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) out_wq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	destroy_workqueue(pool->compact_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) out_unbuddied:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	free_percpu(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) out_pool:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	kmem_cache_destroy(pool->c_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) out_c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	kfree(pool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)  * z3fold_destroy_pool() - destroys an existing z3fold pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)  * @pool:	the z3fold pool to be destroyed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)  * The pool should be emptied before this function is called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static void z3fold_destroy_pool(struct z3fold_pool *pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	kmem_cache_destroy(pool->c_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	 * We need to destroy pool->compact_wq before pool->release_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	 * as any pending work on pool->compact_wq will call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	 * queue_work(pool->release_wq, &pool->work).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	 * There are still outstanding pages until both workqueues are drained,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	 * so we cannot unregister migration until then.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	destroy_workqueue(pool->compact_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	destroy_workqueue(pool->release_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	z3fold_unregister_migration(pool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	free_percpu(pool->unbuddied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	kfree(pool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)  * z3fold_alloc() - allocates a region of a given size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)  * @pool:	z3fold pool from which to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)  * @size:	size in bytes of the desired allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)  * @gfp:	gfp flags used if the pool needs to grow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)  * @handle:	handle of the new allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)  * This function will attempt to find a free region in the pool large enough to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)  * satisfy the allocation request.  A search of the unbuddied lists is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)  * performed first. If no suitable free region is found, then a new page is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)  * allocated and added to the pool to satisfy the request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)  * gfp should not set __GFP_HIGHMEM as highmem pages cannot be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)  * as z3fold pool pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)  * Return: 0 if success and handle is set, otherwise -EINVAL if the size or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)  * gfp arguments are invalid or -ENOMEM if the pool was unable to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)  * a new page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			unsigned long *handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	int chunks = size_to_chunks(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	struct z3fold_header *zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	struct page *page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 	enum buddy bud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 	bool can_sleep = gfpflags_allow_blocking(gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 	if (!size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	if (size > PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED - CHUNK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		bud = HEADLESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		zhdr = __z3fold_alloc(pool, size, can_sleep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 		if (zhdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 			bud = get_free_buddy(zhdr, chunks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			if (bud == HEADLESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 				if (kref_put(&zhdr->refcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 					     release_z3fold_page_locked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 					atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 					z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 				pr_err("No free chunks in unbuddied\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 				WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 				goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 			page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 			goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 		bud = FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	if (can_sleep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 		spin_lock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		zhdr = list_first_entry_or_null(&pool->stale,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 						struct z3fold_header, buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		 * Before allocating a page, let's see if we can take one from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 		 * the stale pages list. cancel_work_sync() can sleep so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		 * limit this case to the contexts where we can sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 		if (zhdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 			list_del(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 			spin_unlock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 			cancel_work_sync(&zhdr->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 			page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 			spin_unlock(&pool->stale_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 		page = alloc_page(gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	zhdr = init_z3fold_page(page, bud == HEADLESS, pool, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	if (!zhdr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 		__free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	atomic64_inc(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	if (bud == HEADLESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 		set_bit(PAGE_HEADLESS, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 		goto headless;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	if (can_sleep) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		lock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		__SetPageMovable(page, pool->inode->i_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		unlock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		if (trylock_page(page)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 			__SetPageMovable(page, pool->inode->i_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 			unlock_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	z3fold_page_lock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	if (bud == FIRST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 		zhdr->first_chunks = chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	else if (bud == LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		zhdr->last_chunks = chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 		zhdr->middle_chunks = chunks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	add_to_unbuddied(pool, zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) headless:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	/* Add/move z3fold page to beginning of LRU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	if (!list_empty(&page->lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		list_del(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	list_add(&page->lru, &pool->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	*handle = encode_handle(zhdr, bud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	if (bud != HEADLESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)  * z3fold_free() - frees the allocation associated with the given handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)  * @pool:	pool in which the allocation resided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)  * @handle:	handle associated with the allocation returned by z3fold_alloc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)  * In the case that the z3fold page in which the allocation resides is under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)  * reclaim, as indicated by the PG_reclaim flag being set, this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)  * only sets the first|last_chunks to 0.  The page is actually freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)  * once both buddies are evicted (see z3fold_reclaim_page() below).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	enum buddy bud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	bool page_claimed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	zhdr = get_z3fold_header(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	page_claimed = test_and_set_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	if (test_bit(PAGE_HEADLESS, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 		/* if a headless page is under reclaim, just leave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		 * NB: we use test_and_set_bit for a reason: if the bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		 * has not been set before, we release this page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		 * immediately so we don't care about its value any more.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 		if (!page_claimed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 			spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 			list_del(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 			spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 			put_z3fold_header(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 			free_z3fold_page(page, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 			atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	/* Non-headless case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	bud = handle_to_buddy(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	switch (bud) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	case FIRST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 		zhdr->first_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	case MIDDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		zhdr->middle_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	case LAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		zhdr->last_chunks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		pr_err("%s: unknown bud %d\n", __func__, bud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		put_z3fold_header(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	if (!page_claimed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 		free_handle(handle, zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 	if (kref_put(&zhdr->refcount, release_z3fold_page_locked_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 		atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	if (page_claimed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		/* the page has not been claimed by us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 	if (test_and_set_bit(NEEDS_COMPACTING, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		put_z3fold_header(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 		clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	if (zhdr->cpu < 0 || !cpu_online(zhdr->cpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 		spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 		list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 		spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 		zhdr->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 		kref_get(&zhdr->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 		clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 		do_compact_page(zhdr, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	kref_get(&zhdr->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	queue_work_on(zhdr->cpu, pool->compact_wq, &zhdr->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	put_z3fold_header(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)  * z3fold_reclaim_page() - evicts allocations from a pool page and frees it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)  * @pool:	pool from which a page will attempt to be evicted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)  * @retries:	number of pages on the LRU list for which eviction will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)  *		be attempted before failing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)  * z3fold reclaim is different from normal system reclaim in that it is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)  * from the bottom, up. This is because only the bottom layer, z3fold, has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)  * information on how the allocations are organized within each z3fold page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)  * This has the potential to create interesting locking situations between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)  * z3fold and the user, however.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)  * To avoid these, this is how z3fold_reclaim_page() should be called:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)  * The user detects a page should be reclaimed and calls z3fold_reclaim_page().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)  * z3fold_reclaim_page() will remove a z3fold page from the pool LRU list and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)  * call the user-defined eviction handler with the pool and handle as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)  * arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)  * If the handle can not be evicted, the eviction handler should return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)  * non-zero. z3fold_reclaim_page() will add the z3fold page back to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)  * appropriate list and try the next z3fold page on the LRU up to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)  * a user defined number of retries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)  * If the handle is successfully evicted, the eviction handler should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)  * return 0 _and_ should have called z3fold_free() on the handle. z3fold_free()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)  * contains logic to delay freeing the page if the page is under reclaim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)  * as indicated by the setting of the PG_reclaim flag on the underlying page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)  * If all buddies in the z3fold page are successfully evicted, then the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)  * z3fold page can be freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)  * Returns: 0 if page is successfully freed, otherwise -EINVAL if there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)  * no pages to evict or an eviction handler is not registered, -EAGAIN if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)  * the retry limit was hit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	int i, ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	struct z3fold_header *zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 	struct page *page = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	struct list_head *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 	unsigned long first_handle = 0, middle_handle = 0, last_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	struct z3fold_buddy_slots slots __attribute__((aligned(SLOTS_ALIGN)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	rwlock_init(&slots.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 	slots.pool = (unsigned long)pool | (1 << HANDLES_NOFREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 	if (!pool->ops || !pool->ops->evict || retries == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 	for (i = 0; i < retries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		if (list_empty(&pool->lru)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 			spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 		list_for_each_prev(pos, &pool->lru) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 			page = list_entry(pos, struct page, lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 			zhdr = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 			if (test_bit(PAGE_HEADLESS, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 				 * For non-headless pages, we wait to do this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 				 * until we have the page lock to avoid racing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 				 * with __z3fold_alloc(). Headless pages don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 				 * have a lock (and __z3fold_alloc() will never
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 				 * see them), but we still need to test and set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 				 * PAGE_CLAIMED to avoid racing with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 				 * z3fold_free(), so just do it now before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 				 * leaving the loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 				if (test_and_set_bit(PAGE_CLAIMED, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 			if (kref_get_unless_zero(&zhdr->refcount) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 				zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 			if (!z3fold_page_trylock(zhdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 				if (kref_put(&zhdr->refcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 						release_z3fold_page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 					atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 				zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 				continue; /* can't evict at this point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 			/* test_and_set_bit is of course atomic, but we still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 			 * need to do it under page lock, otherwise checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 			 * that bit in __z3fold_alloc wouldn't make sense
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 			if (zhdr->foreign_handles ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 			    test_and_set_bit(PAGE_CLAIMED, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 				if (kref_put(&zhdr->refcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 						release_z3fold_page_locked))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 					atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 					z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 				zhdr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 				continue; /* can't evict such page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 			list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 			zhdr->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		if (!zhdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 		list_del_init(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 		spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 		if (!test_bit(PAGE_HEADLESS, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 			 * We need encode the handles before unlocking, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 			 * use our local slots structure because z3fold_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 			 * can zero out zhdr->slots and we can't do much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 			 * about that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 			first_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 			last_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 			middle_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 			memset(slots.slot, 0, sizeof(slots.slot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 			if (zhdr->first_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 				first_handle = __encode_handle(zhdr, &slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 								FIRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 			if (zhdr->middle_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 				middle_handle = __encode_handle(zhdr, &slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 								MIDDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 			if (zhdr->last_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 				last_handle = __encode_handle(zhdr, &slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 								LAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 			 * it's safe to unlock here because we hold a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 			 * reference to this page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 			z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 			first_handle = encode_handle(zhdr, HEADLESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 			last_handle = middle_handle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 		/* Issue the eviction callback(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		if (middle_handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 			ret = pool->ops->evict(pool, middle_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 				goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		if (first_handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 			ret = pool->ops->evict(pool, first_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 				goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		if (last_handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 			ret = pool->ops->evict(pool, last_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 				goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		if (test_bit(PAGE_HEADLESS, &page->private)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 			if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 				free_z3fold_page(page, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 				atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 			spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 			list_add(&page->lru, &pool->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 			spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 			clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 			struct z3fold_buddy_slots *slots = zhdr->slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 			z3fold_page_lock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 			if (kref_put(&zhdr->refcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 					release_z3fold_page_locked)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 				kmem_cache_free(pool->c_handle, slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 				atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 			 * if we are here, the page is still not completely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 			 * free. Take the global pool lock then to be able
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 			 * to add it back to the lru list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 			spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 			list_add(&page->lru, &pool->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 			spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 			z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 			clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 		/* We started off locked to we need to lock the pool back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 		spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 	return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)  * z3fold_map() - maps the allocation associated with the given handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)  * @pool:	pool in which the allocation resides
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)  * @handle:	handle associated with the allocation to be mapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)  * Extracts the buddy number from handle and constructs the pointer to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)  * correct starting chunk within the page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)  * Returns: a pointer to the mapped allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) static void *z3fold_map(struct z3fold_pool *pool, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	enum buddy buddy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	zhdr = get_z3fold_header(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	addr = zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 	page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 	if (test_bit(PAGE_HEADLESS, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 	buddy = handle_to_buddy(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	switch (buddy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 	case FIRST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 		addr += ZHDR_SIZE_ALIGNED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 	case MIDDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 		addr += zhdr->start_middle << CHUNK_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 		set_bit(MIDDLE_CHUNK_MAPPED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	case LAST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 		addr += PAGE_SIZE - (handle_to_chunks(handle) << CHUNK_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 		pr_err("unknown buddy id %d\n", buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 		WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 		addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	if (addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 		zhdr->mapped_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 	put_z3fold_header(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 	return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)  * z3fold_unmap() - unmaps the allocation associated with the given handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)  * @pool:	pool in which the allocation resides
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)  * @handle:	handle associated with the allocation to be unmapped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) static void z3fold_unmap(struct z3fold_pool *pool, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	enum buddy buddy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	zhdr = get_z3fold_header(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	page = virt_to_page(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 	if (test_bit(PAGE_HEADLESS, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 	buddy = handle_to_buddy(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 	if (buddy == MIDDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 		clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 	zhdr->mapped_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 	put_z3fold_header(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)  * z3fold_get_pool_size() - gets the z3fold pool size in pages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)  * @pool:	pool whose size is being queried
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)  * Returns: size in pages of the given pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) static u64 z3fold_get_pool_size(struct z3fold_pool *pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 	return atomic64_read(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static bool z3fold_page_isolate(struct page *page, isolate_mode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 	struct z3fold_pool *pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 	VM_BUG_ON_PAGE(!PageMovable(page), page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 	VM_BUG_ON_PAGE(PageIsolated(page), page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 	if (test_bit(PAGE_HEADLESS, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 	zhdr = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 	z3fold_page_lock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 	if (test_bit(NEEDS_COMPACTING, &page->private) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 	    test_bit(PAGE_STALE, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 	if (zhdr->mapped_count != 0 || zhdr->foreign_handles != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 	if (test_and_set_bit(PAGE_CLAIMED, &page->private))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	if (!list_empty(&zhdr->buddy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 		list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	if (!list_empty(&page->lru))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 		list_del_init(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	kref_get(&zhdr->refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 	z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) static int z3fold_page_migrate(struct address_space *mapping, struct page *newpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 			       struct page *page, enum migrate_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 	struct z3fold_header *zhdr, *new_zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	struct z3fold_pool *pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 	struct address_space *new_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) 	VM_BUG_ON_PAGE(!PageMovable(page), page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 	VM_BUG_ON_PAGE(!PageIsolated(page), page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) 	VM_BUG_ON_PAGE(!test_bit(PAGE_CLAIMED, &page->private), page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 	VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 	zhdr = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 	pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 	if (!z3fold_page_trylock(zhdr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 	if (zhdr->mapped_count != 0 || zhdr->foreign_handles != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 		clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	if (work_pending(&zhdr->work)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 		z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 	new_zhdr = page_address(newpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 	memcpy(new_zhdr, zhdr, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 	newpage->private = page->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	page->private = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 	z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 	spin_lock_init(&new_zhdr->page_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 	INIT_WORK(&new_zhdr->work, compact_page_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 	 * z3fold_page_isolate() ensures that new_zhdr->buddy is empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 	 * so we only have to reinitialize it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 	INIT_LIST_HEAD(&new_zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 	new_mapping = page_mapping(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 	__ClearPageMovable(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 	ClearPagePrivate(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 	get_page(newpage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 	z3fold_page_lock(new_zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 	if (new_zhdr->first_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 		encode_handle(new_zhdr, FIRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 	if (new_zhdr->last_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 		encode_handle(new_zhdr, LAST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 	if (new_zhdr->middle_chunks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 		encode_handle(new_zhdr, MIDDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	set_bit(NEEDS_COMPACTING, &newpage->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 	new_zhdr->cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 	list_add(&newpage->lru, &pool->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 	__SetPageMovable(newpage, new_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 	z3fold_page_unlock(new_zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	queue_work_on(new_zhdr->cpu, pool->compact_wq, &new_zhdr->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 	page_mapcount_reset(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 	clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 	put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) static void z3fold_page_putback(struct page *page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 	struct z3fold_header *zhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 	struct z3fold_pool *pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 	zhdr = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 	pool = zhdr_to_pool(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 	z3fold_page_lock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	if (!list_empty(&zhdr->buddy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 		list_del_init(&zhdr->buddy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 	INIT_LIST_HEAD(&page->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 	if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 		atomic64_dec(&pool->pages_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 	spin_lock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 	list_add(&page->lru, &pool->lru);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	spin_unlock(&pool->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 	clear_bit(PAGE_CLAIMED, &page->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 	z3fold_page_unlock(zhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) static const struct address_space_operations z3fold_aops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 	.isolate_page = z3fold_page_isolate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 	.migratepage = z3fold_page_migrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 	.putback_page = z3fold_page_putback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) /*****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)  * zpool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)  ****************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) static int z3fold_zpool_evict(struct z3fold_pool *pool, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 	if (pool->zpool && pool->zpool_ops && pool->zpool_ops->evict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 		return pool->zpool_ops->evict(pool->zpool, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) static const struct z3fold_ops z3fold_zpool_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 	.evict =	z3fold_zpool_evict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) static void *z3fold_zpool_create(const char *name, gfp_t gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 			       const struct zpool_ops *zpool_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 			       struct zpool *zpool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 	struct z3fold_pool *pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 	pool = z3fold_create_pool(name, gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 				zpool_ops ? &z3fold_zpool_ops : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 	if (pool) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 		pool->zpool = zpool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 		pool->zpool_ops = zpool_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 	return pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) static void z3fold_zpool_destroy(void *pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 	z3fold_destroy_pool(pool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) static int z3fold_zpool_malloc(void *pool, size_t size, gfp_t gfp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 			unsigned long *handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 	return z3fold_alloc(pool, size, gfp, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) static void z3fold_zpool_free(void *pool, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 	z3fold_free(pool, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) static int z3fold_zpool_shrink(void *pool, unsigned int pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 			unsigned int *reclaimed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 	unsigned int total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 	int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 	while (total < pages) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 		ret = z3fold_reclaim_page(pool, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 		if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 		total++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	if (reclaimed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 		*reclaimed = total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) static void *z3fold_zpool_map(void *pool, unsigned long handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 			enum zpool_mapmode mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	return z3fold_map(pool, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) static void z3fold_zpool_unmap(void *pool, unsigned long handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 	z3fold_unmap(pool, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) static u64 z3fold_zpool_total_size(void *pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 	return z3fold_get_pool_size(pool) * PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) static struct zpool_driver z3fold_zpool_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	.type =		"z3fold",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 	.owner =	THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 	.create =	z3fold_zpool_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 	.destroy =	z3fold_zpool_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 	.malloc =	z3fold_zpool_malloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 	.free =		z3fold_zpool_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 	.shrink =	z3fold_zpool_shrink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 	.map =		z3fold_zpool_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 	.unmap =	z3fold_zpool_unmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	.total_size =	z3fold_zpool_total_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) MODULE_ALIAS("zpool-z3fold");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) static int __init init_z3fold(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 	/* Make sure the z3fold header is not larger than the page size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 	BUILD_BUG_ON(ZHDR_SIZE_ALIGNED > PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 	ret = z3fold_mount();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 	zpool_register_driver(&z3fold_zpool_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) static void __exit exit_z3fold(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 	z3fold_unmount();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	zpool_unregister_driver(&z3fold_zpool_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) module_init(init_z3fold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) module_exit(exit_z3fold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) MODULE_AUTHOR("Vitaly Wool <vitalywool@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) MODULE_DESCRIPTION("3-Fold Allocator for Compressed Pages");