18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Frontswap frontend
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This code provides the generic "frontend" layer to call a matching
68c2ecf20Sopenharmony_ci * "backend" driver implementation of frontswap.  See
78c2ecf20Sopenharmony_ci * Documentation/vm/frontswap.rst for more information.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2009-2012 Oracle Corp.  All rights reserved.
108c2ecf20Sopenharmony_ci * Author: Dan Magenheimer
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/mman.h>
148c2ecf20Sopenharmony_ci#include <linux/swap.h>
158c2ecf20Sopenharmony_ci#include <linux/swapops.h>
168c2ecf20Sopenharmony_ci#include <linux/security.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
198c2ecf20Sopenharmony_ci#include <linux/frontswap.h>
208c2ecf20Sopenharmony_ci#include <linux/swapfile.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciDEFINE_STATIC_KEY_FALSE(frontswap_enabled_key);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/*
258c2ecf20Sopenharmony_ci * frontswap_ops are added by frontswap_register_ops, and provide the
268c2ecf20Sopenharmony_ci * frontswap "backend" implementation functions.  Multiple implementations
278c2ecf20Sopenharmony_ci * may be registered, but implementations can never deregister.  This
288c2ecf20Sopenharmony_ci * is a simple singly-linked list of all registered implementations.
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_cistatic struct frontswap_ops *frontswap_ops __read_mostly;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define for_each_frontswap_ops(ops)		\
338c2ecf20Sopenharmony_ci	for ((ops) = frontswap_ops; (ops); (ops) = (ops)->next)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/*
368c2ecf20Sopenharmony_ci * If enabled, frontswap_store will return failure even on success.  As
378c2ecf20Sopenharmony_ci * a result, the swap subsystem will always write the page to swap, in
388c2ecf20Sopenharmony_ci * effect converting frontswap into a writethrough cache.  In this mode,
398c2ecf20Sopenharmony_ci * there is no direct reduction in swap writes, but a frontswap backend
408c2ecf20Sopenharmony_ci * can unilaterally "reclaim" any pages in use with no data loss, thus
418c2ecf20Sopenharmony_ci * providing increases control over maximum memory usage due to frontswap.
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_cistatic bool frontswap_writethrough_enabled __read_mostly;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/*
468c2ecf20Sopenharmony_ci * If enabled, the underlying tmem implementation is capable of doing
478c2ecf20Sopenharmony_ci * exclusive gets, so frontswap_load, on a successful tmem_get must
488c2ecf20Sopenharmony_ci * mark the page as no longer in frontswap AND mark it dirty.
498c2ecf20Sopenharmony_ci */
508c2ecf20Sopenharmony_cistatic bool frontswap_tmem_exclusive_gets_enabled __read_mostly;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
538c2ecf20Sopenharmony_ci/*
548c2ecf20Sopenharmony_ci * Counters available via /sys/kernel/debug/frontswap (if debugfs is
558c2ecf20Sopenharmony_ci * properly configured).  These are for information only so are not protected
568c2ecf20Sopenharmony_ci * against increment races.
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_cistatic u64 frontswap_loads;
598c2ecf20Sopenharmony_cistatic u64 frontswap_succ_stores;
608c2ecf20Sopenharmony_cistatic u64 frontswap_failed_stores;
618c2ecf20Sopenharmony_cistatic u64 frontswap_invalidates;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic inline void inc_frontswap_loads(void) {
648c2ecf20Sopenharmony_ci	data_race(frontswap_loads++);
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_cistatic inline void inc_frontswap_succ_stores(void) {
678c2ecf20Sopenharmony_ci	data_race(frontswap_succ_stores++);
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_cistatic inline void inc_frontswap_failed_stores(void) {
708c2ecf20Sopenharmony_ci	data_race(frontswap_failed_stores++);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_cistatic inline void inc_frontswap_invalidates(void) {
738c2ecf20Sopenharmony_ci	data_race(frontswap_invalidates++);
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci#else
768c2ecf20Sopenharmony_cistatic inline void inc_frontswap_loads(void) { }
778c2ecf20Sopenharmony_cistatic inline void inc_frontswap_succ_stores(void) { }
788c2ecf20Sopenharmony_cistatic inline void inc_frontswap_failed_stores(void) { }
798c2ecf20Sopenharmony_cistatic inline void inc_frontswap_invalidates(void) { }
808c2ecf20Sopenharmony_ci#endif
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/*
838c2ecf20Sopenharmony_ci * Due to the asynchronous nature of the backends loading potentially
848c2ecf20Sopenharmony_ci * _after_ the swap system has been activated, we have chokepoints
858c2ecf20Sopenharmony_ci * on all frontswap functions to not call the backend until the backend
868c2ecf20Sopenharmony_ci * has registered.
878c2ecf20Sopenharmony_ci *
888c2ecf20Sopenharmony_ci * This would not guards us against the user deciding to call swapoff right as
898c2ecf20Sopenharmony_ci * we are calling the backend to initialize (so swapon is in action).
908c2ecf20Sopenharmony_ci * Fortunately for us, the swapon_mutex has been taken by the callee so we are
918c2ecf20Sopenharmony_ci * OK. The other scenario where calls to frontswap_store (called via
928c2ecf20Sopenharmony_ci * swap_writepage) is racing with frontswap_invalidate_area (called via
938c2ecf20Sopenharmony_ci * swapoff) is again guarded by the swap subsystem.
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * While no backend is registered all calls to frontswap_[store|load|
968c2ecf20Sopenharmony_ci * invalidate_area|invalidate_page] are ignored or fail.
978c2ecf20Sopenharmony_ci *
988c2ecf20Sopenharmony_ci * The time between the backend being registered and the swap file system
998c2ecf20Sopenharmony_ci * calling the backend (via the frontswap_* functions) is indeterminate as
1008c2ecf20Sopenharmony_ci * frontswap_ops is not atomic_t (or a value guarded by a spinlock).
1018c2ecf20Sopenharmony_ci * That is OK as we are comfortable missing some of these calls to the newly
1028c2ecf20Sopenharmony_ci * registered backend.
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci * Obviously the opposite (unloading the backend) must be done after all
1058c2ecf20Sopenharmony_ci * the frontswap_[store|load|invalidate_area|invalidate_page] start
1068c2ecf20Sopenharmony_ci * ignoring or failing the requests.  However, there is currently no way
1078c2ecf20Sopenharmony_ci * to unload a backend once it is registered.
1088c2ecf20Sopenharmony_ci */
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/*
1118c2ecf20Sopenharmony_ci * Register operations for frontswap
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_civoid frontswap_register_ops(struct frontswap_ops *ops)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	DECLARE_BITMAP(a, MAX_SWAPFILES);
1168c2ecf20Sopenharmony_ci	DECLARE_BITMAP(b, MAX_SWAPFILES);
1178c2ecf20Sopenharmony_ci	struct swap_info_struct *si;
1188c2ecf20Sopenharmony_ci	unsigned int i;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	bitmap_zero(a, MAX_SWAPFILES);
1218c2ecf20Sopenharmony_ci	bitmap_zero(b, MAX_SWAPFILES);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	spin_lock(&swap_lock);
1248c2ecf20Sopenharmony_ci	plist_for_each_entry(si, &swap_active_head, list) {
1258c2ecf20Sopenharmony_ci		if (!WARN_ON(!si->frontswap_map))
1268c2ecf20Sopenharmony_ci			set_bit(si->type, a);
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci	spin_unlock(&swap_lock);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* the new ops needs to know the currently active swap devices */
1318c2ecf20Sopenharmony_ci	for_each_set_bit(i, a, MAX_SWAPFILES)
1328c2ecf20Sopenharmony_ci		ops->init(i);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	/*
1358c2ecf20Sopenharmony_ci	 * Setting frontswap_ops must happen after the ops->init() calls
1368c2ecf20Sopenharmony_ci	 * above; cmpxchg implies smp_mb() which will ensure the init is
1378c2ecf20Sopenharmony_ci	 * complete at this point.
1388c2ecf20Sopenharmony_ci	 */
1398c2ecf20Sopenharmony_ci	do {
1408c2ecf20Sopenharmony_ci		ops->next = frontswap_ops;
1418c2ecf20Sopenharmony_ci	} while (cmpxchg(&frontswap_ops, ops->next, ops) != ops->next);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	static_branch_inc(&frontswap_enabled_key);
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	spin_lock(&swap_lock);
1468c2ecf20Sopenharmony_ci	plist_for_each_entry(si, &swap_active_head, list) {
1478c2ecf20Sopenharmony_ci		if (si->frontswap_map)
1488c2ecf20Sopenharmony_ci			set_bit(si->type, b);
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci	spin_unlock(&swap_lock);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/*
1538c2ecf20Sopenharmony_ci	 * On the very unlikely chance that a swap device was added or
1548c2ecf20Sopenharmony_ci	 * removed between setting the "a" list bits and the ops init
1558c2ecf20Sopenharmony_ci	 * calls, we re-check and do init or invalidate for any changed
1568c2ecf20Sopenharmony_ci	 * bits.
1578c2ecf20Sopenharmony_ci	 */
1588c2ecf20Sopenharmony_ci	if (unlikely(!bitmap_equal(a, b, MAX_SWAPFILES))) {
1598c2ecf20Sopenharmony_ci		for (i = 0; i < MAX_SWAPFILES; i++) {
1608c2ecf20Sopenharmony_ci			if (!test_bit(i, a) && test_bit(i, b))
1618c2ecf20Sopenharmony_ci				ops->init(i);
1628c2ecf20Sopenharmony_ci			else if (test_bit(i, a) && !test_bit(i, b))
1638c2ecf20Sopenharmony_ci				ops->invalidate_area(i);
1648c2ecf20Sopenharmony_ci		}
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(frontswap_register_ops);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/*
1708c2ecf20Sopenharmony_ci * Enable/disable frontswap writethrough (see above).
1718c2ecf20Sopenharmony_ci */
1728c2ecf20Sopenharmony_civoid frontswap_writethrough(bool enable)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	frontswap_writethrough_enabled = enable;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(frontswap_writethrough);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/*
1798c2ecf20Sopenharmony_ci * Enable/disable frontswap exclusive gets (see above).
1808c2ecf20Sopenharmony_ci */
1818c2ecf20Sopenharmony_civoid frontswap_tmem_exclusive_gets(bool enable)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	frontswap_tmem_exclusive_gets_enabled = enable;
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(frontswap_tmem_exclusive_gets);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/*
1888c2ecf20Sopenharmony_ci * Called when a swap device is swapon'd.
1898c2ecf20Sopenharmony_ci */
1908c2ecf20Sopenharmony_civoid __frontswap_init(unsigned type, unsigned long *map)
1918c2ecf20Sopenharmony_ci{
1928c2ecf20Sopenharmony_ci	struct swap_info_struct *sis = swap_info[type];
1938c2ecf20Sopenharmony_ci	struct frontswap_ops *ops;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	VM_BUG_ON(sis == NULL);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	/*
1988c2ecf20Sopenharmony_ci	 * p->frontswap is a bitmap that we MUST have to figure out which page
1998c2ecf20Sopenharmony_ci	 * has gone in frontswap. Without it there is no point of continuing.
2008c2ecf20Sopenharmony_ci	 */
2018c2ecf20Sopenharmony_ci	if (WARN_ON(!map))
2028c2ecf20Sopenharmony_ci		return;
2038c2ecf20Sopenharmony_ci	/*
2048c2ecf20Sopenharmony_ci	 * Irregardless of whether the frontswap backend has been loaded
2058c2ecf20Sopenharmony_ci	 * before this function or it will be later, we _MUST_ have the
2068c2ecf20Sopenharmony_ci	 * p->frontswap set to something valid to work properly.
2078c2ecf20Sopenharmony_ci	 */
2088c2ecf20Sopenharmony_ci	frontswap_map_set(sis, map);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	for_each_frontswap_ops(ops)
2118c2ecf20Sopenharmony_ci		ops->init(type);
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__frontswap_init);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cibool __frontswap_test(struct swap_info_struct *sis,
2168c2ecf20Sopenharmony_ci				pgoff_t offset)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	if (sis->frontswap_map)
2198c2ecf20Sopenharmony_ci		return test_bit(offset, sis->frontswap_map);
2208c2ecf20Sopenharmony_ci	return false;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__frontswap_test);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic inline void __frontswap_set(struct swap_info_struct *sis,
2258c2ecf20Sopenharmony_ci				   pgoff_t offset)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	set_bit(offset, sis->frontswap_map);
2288c2ecf20Sopenharmony_ci	atomic_inc(&sis->frontswap_pages);
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic inline void __frontswap_clear(struct swap_info_struct *sis,
2328c2ecf20Sopenharmony_ci				     pgoff_t offset)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	clear_bit(offset, sis->frontswap_map);
2358c2ecf20Sopenharmony_ci	atomic_dec(&sis->frontswap_pages);
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci/*
2398c2ecf20Sopenharmony_ci * "Store" data from a page to frontswap and associate it with the page's
2408c2ecf20Sopenharmony_ci * swaptype and offset.  Page must be locked and in the swap cache.
2418c2ecf20Sopenharmony_ci * If frontswap already contains a page with matching swaptype and
2428c2ecf20Sopenharmony_ci * offset, the frontswap implementation may either overwrite the data and
2438c2ecf20Sopenharmony_ci * return success or invalidate the page from frontswap and return failure.
2448c2ecf20Sopenharmony_ci */
2458c2ecf20Sopenharmony_ciint __frontswap_store(struct page *page)
2468c2ecf20Sopenharmony_ci{
2478c2ecf20Sopenharmony_ci	int ret = -1;
2488c2ecf20Sopenharmony_ci	swp_entry_t entry = { .val = page_private(page), };
2498c2ecf20Sopenharmony_ci	int type = swp_type(entry);
2508c2ecf20Sopenharmony_ci	struct swap_info_struct *sis = swap_info[type];
2518c2ecf20Sopenharmony_ci	pgoff_t offset = swp_offset(entry);
2528c2ecf20Sopenharmony_ci	struct frontswap_ops *ops;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	VM_BUG_ON(!frontswap_ops);
2558c2ecf20Sopenharmony_ci	VM_BUG_ON(!PageLocked(page));
2568c2ecf20Sopenharmony_ci	VM_BUG_ON(sis == NULL);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	/*
2598c2ecf20Sopenharmony_ci	 * If a dup, we must remove the old page first; we can't leave the
2608c2ecf20Sopenharmony_ci	 * old page no matter if the store of the new page succeeds or fails,
2618c2ecf20Sopenharmony_ci	 * and we can't rely on the new page replacing the old page as we may
2628c2ecf20Sopenharmony_ci	 * not store to the same implementation that contains the old page.
2638c2ecf20Sopenharmony_ci	 */
2648c2ecf20Sopenharmony_ci	if (__frontswap_test(sis, offset)) {
2658c2ecf20Sopenharmony_ci		__frontswap_clear(sis, offset);
2668c2ecf20Sopenharmony_ci		for_each_frontswap_ops(ops)
2678c2ecf20Sopenharmony_ci			ops->invalidate_page(type, offset);
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* Try to store in each implementation, until one succeeds. */
2718c2ecf20Sopenharmony_ci	for_each_frontswap_ops(ops) {
2728c2ecf20Sopenharmony_ci		ret = ops->store(type, offset, page);
2738c2ecf20Sopenharmony_ci		if (!ret) /* successful store */
2748c2ecf20Sopenharmony_ci			break;
2758c2ecf20Sopenharmony_ci	}
2768c2ecf20Sopenharmony_ci	if (ret == 0) {
2778c2ecf20Sopenharmony_ci		__frontswap_set(sis, offset);
2788c2ecf20Sopenharmony_ci		inc_frontswap_succ_stores();
2798c2ecf20Sopenharmony_ci	} else {
2808c2ecf20Sopenharmony_ci		inc_frontswap_failed_stores();
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci	if (frontswap_writethrough_enabled)
2838c2ecf20Sopenharmony_ci		/* report failure so swap also writes to swap device */
2848c2ecf20Sopenharmony_ci		ret = -1;
2858c2ecf20Sopenharmony_ci	return ret;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__frontswap_store);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci/*
2908c2ecf20Sopenharmony_ci * "Get" data from frontswap associated with swaptype and offset that were
2918c2ecf20Sopenharmony_ci * specified when the data was put to frontswap and use it to fill the
2928c2ecf20Sopenharmony_ci * specified page with data. Page must be locked and in the swap cache.
2938c2ecf20Sopenharmony_ci */
2948c2ecf20Sopenharmony_ciint __frontswap_load(struct page *page)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	int ret = -1;
2978c2ecf20Sopenharmony_ci	swp_entry_t entry = { .val = page_private(page), };
2988c2ecf20Sopenharmony_ci	int type = swp_type(entry);
2998c2ecf20Sopenharmony_ci	struct swap_info_struct *sis = swap_info[type];
3008c2ecf20Sopenharmony_ci	pgoff_t offset = swp_offset(entry);
3018c2ecf20Sopenharmony_ci	struct frontswap_ops *ops;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	VM_BUG_ON(!frontswap_ops);
3048c2ecf20Sopenharmony_ci	VM_BUG_ON(!PageLocked(page));
3058c2ecf20Sopenharmony_ci	VM_BUG_ON(sis == NULL);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (!__frontswap_test(sis, offset))
3088c2ecf20Sopenharmony_ci		return -1;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	/* Try loading from each implementation, until one succeeds. */
3118c2ecf20Sopenharmony_ci	for_each_frontswap_ops(ops) {
3128c2ecf20Sopenharmony_ci		ret = ops->load(type, offset, page);
3138c2ecf20Sopenharmony_ci		if (!ret) /* successful load */
3148c2ecf20Sopenharmony_ci			break;
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci	if (ret == 0) {
3178c2ecf20Sopenharmony_ci		inc_frontswap_loads();
3188c2ecf20Sopenharmony_ci		if (frontswap_tmem_exclusive_gets_enabled) {
3198c2ecf20Sopenharmony_ci			SetPageDirty(page);
3208c2ecf20Sopenharmony_ci			__frontswap_clear(sis, offset);
3218c2ecf20Sopenharmony_ci		}
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci	return ret;
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__frontswap_load);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci/*
3288c2ecf20Sopenharmony_ci * Invalidate any data from frontswap associated with the specified swaptype
3298c2ecf20Sopenharmony_ci * and offset so that a subsequent "get" will fail.
3308c2ecf20Sopenharmony_ci */
3318c2ecf20Sopenharmony_civoid __frontswap_invalidate_page(unsigned type, pgoff_t offset)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	struct swap_info_struct *sis = swap_info[type];
3348c2ecf20Sopenharmony_ci	struct frontswap_ops *ops;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	VM_BUG_ON(!frontswap_ops);
3378c2ecf20Sopenharmony_ci	VM_BUG_ON(sis == NULL);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	if (!__frontswap_test(sis, offset))
3408c2ecf20Sopenharmony_ci		return;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	for_each_frontswap_ops(ops)
3438c2ecf20Sopenharmony_ci		ops->invalidate_page(type, offset);
3448c2ecf20Sopenharmony_ci	__frontswap_clear(sis, offset);
3458c2ecf20Sopenharmony_ci	inc_frontswap_invalidates();
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__frontswap_invalidate_page);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/*
3508c2ecf20Sopenharmony_ci * Invalidate all data from frontswap associated with all offsets for the
3518c2ecf20Sopenharmony_ci * specified swaptype.
3528c2ecf20Sopenharmony_ci */
3538c2ecf20Sopenharmony_civoid __frontswap_invalidate_area(unsigned type)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	struct swap_info_struct *sis = swap_info[type];
3568c2ecf20Sopenharmony_ci	struct frontswap_ops *ops;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	VM_BUG_ON(!frontswap_ops);
3598c2ecf20Sopenharmony_ci	VM_BUG_ON(sis == NULL);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	if (sis->frontswap_map == NULL)
3628c2ecf20Sopenharmony_ci		return;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	for_each_frontswap_ops(ops)
3658c2ecf20Sopenharmony_ci		ops->invalidate_area(type);
3668c2ecf20Sopenharmony_ci	atomic_set(&sis->frontswap_pages, 0);
3678c2ecf20Sopenharmony_ci	bitmap_zero(sis->frontswap_map, sis->max);
3688c2ecf20Sopenharmony_ci}
3698c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__frontswap_invalidate_area);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic unsigned long __frontswap_curr_pages(void)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	unsigned long totalpages = 0;
3748c2ecf20Sopenharmony_ci	struct swap_info_struct *si = NULL;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	assert_spin_locked(&swap_lock);
3778c2ecf20Sopenharmony_ci	plist_for_each_entry(si, &swap_active_head, list)
3788c2ecf20Sopenharmony_ci		totalpages += atomic_read(&si->frontswap_pages);
3798c2ecf20Sopenharmony_ci	return totalpages;
3808c2ecf20Sopenharmony_ci}
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cistatic int __frontswap_unuse_pages(unsigned long total, unsigned long *unused,
3838c2ecf20Sopenharmony_ci					int *swapid)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	int ret = -EINVAL;
3868c2ecf20Sopenharmony_ci	struct swap_info_struct *si = NULL;
3878c2ecf20Sopenharmony_ci	int si_frontswap_pages;
3888c2ecf20Sopenharmony_ci	unsigned long total_pages_to_unuse = total;
3898c2ecf20Sopenharmony_ci	unsigned long pages = 0, pages_to_unuse = 0;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	assert_spin_locked(&swap_lock);
3928c2ecf20Sopenharmony_ci	plist_for_each_entry(si, &swap_active_head, list) {
3938c2ecf20Sopenharmony_ci		si_frontswap_pages = atomic_read(&si->frontswap_pages);
3948c2ecf20Sopenharmony_ci		if (total_pages_to_unuse < si_frontswap_pages) {
3958c2ecf20Sopenharmony_ci			pages = pages_to_unuse = total_pages_to_unuse;
3968c2ecf20Sopenharmony_ci		} else {
3978c2ecf20Sopenharmony_ci			pages = si_frontswap_pages;
3988c2ecf20Sopenharmony_ci			pages_to_unuse = 0; /* unuse all */
3998c2ecf20Sopenharmony_ci		}
4008c2ecf20Sopenharmony_ci		/* ensure there is enough RAM to fetch pages from frontswap */
4018c2ecf20Sopenharmony_ci		if (security_vm_enough_memory_mm(current->mm, pages)) {
4028c2ecf20Sopenharmony_ci			ret = -ENOMEM;
4038c2ecf20Sopenharmony_ci			continue;
4048c2ecf20Sopenharmony_ci		}
4058c2ecf20Sopenharmony_ci		vm_unacct_memory(pages);
4068c2ecf20Sopenharmony_ci		*unused = pages_to_unuse;
4078c2ecf20Sopenharmony_ci		*swapid = si->type;
4088c2ecf20Sopenharmony_ci		ret = 0;
4098c2ecf20Sopenharmony_ci		break;
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	return ret;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci/*
4168c2ecf20Sopenharmony_ci * Used to check if it's necessary and feasible to unuse pages.
4178c2ecf20Sopenharmony_ci * Return 1 when nothing to do, 0 when need to shrink pages,
4188c2ecf20Sopenharmony_ci * error code when there is an error.
4198c2ecf20Sopenharmony_ci */
4208c2ecf20Sopenharmony_cistatic int __frontswap_shrink(unsigned long target_pages,
4218c2ecf20Sopenharmony_ci				unsigned long *pages_to_unuse,
4228c2ecf20Sopenharmony_ci				int *type)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	unsigned long total_pages = 0, total_pages_to_unuse;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	assert_spin_locked(&swap_lock);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	total_pages = __frontswap_curr_pages();
4298c2ecf20Sopenharmony_ci	if (total_pages <= target_pages) {
4308c2ecf20Sopenharmony_ci		/* Nothing to do */
4318c2ecf20Sopenharmony_ci		*pages_to_unuse = 0;
4328c2ecf20Sopenharmony_ci		return 1;
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci	total_pages_to_unuse = total_pages - target_pages;
4358c2ecf20Sopenharmony_ci	return __frontswap_unuse_pages(total_pages_to_unuse, pages_to_unuse, type);
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci/*
4398c2ecf20Sopenharmony_ci * Frontswap, like a true swap device, may unnecessarily retain pages
4408c2ecf20Sopenharmony_ci * under certain circumstances; "shrink" frontswap is essentially a
4418c2ecf20Sopenharmony_ci * "partial swapoff" and works by calling try_to_unuse to attempt to
4428c2ecf20Sopenharmony_ci * unuse enough frontswap pages to attempt to -- subject to memory
4438c2ecf20Sopenharmony_ci * constraints -- reduce the number of pages in frontswap to the
4448c2ecf20Sopenharmony_ci * number given in the parameter target_pages.
4458c2ecf20Sopenharmony_ci */
4468c2ecf20Sopenharmony_civoid frontswap_shrink(unsigned long target_pages)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	unsigned long pages_to_unuse = 0;
4498c2ecf20Sopenharmony_ci	int type, ret;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	/*
4528c2ecf20Sopenharmony_ci	 * we don't want to hold swap_lock while doing a very
4538c2ecf20Sopenharmony_ci	 * lengthy try_to_unuse, but swap_list may change
4548c2ecf20Sopenharmony_ci	 * so restart scan from swap_active_head each time
4558c2ecf20Sopenharmony_ci	 */
4568c2ecf20Sopenharmony_ci	spin_lock(&swap_lock);
4578c2ecf20Sopenharmony_ci	ret = __frontswap_shrink(target_pages, &pages_to_unuse, &type);
4588c2ecf20Sopenharmony_ci	spin_unlock(&swap_lock);
4598c2ecf20Sopenharmony_ci	if (ret == 0)
4608c2ecf20Sopenharmony_ci		try_to_unuse(type, true, pages_to_unuse);
4618c2ecf20Sopenharmony_ci	return;
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(frontswap_shrink);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci/*
4668c2ecf20Sopenharmony_ci * Count and return the number of frontswap pages across all
4678c2ecf20Sopenharmony_ci * swap devices.  This is exported so that backend drivers can
4688c2ecf20Sopenharmony_ci * determine current usage without reading debugfs.
4698c2ecf20Sopenharmony_ci */
4708c2ecf20Sopenharmony_ciunsigned long frontswap_curr_pages(void)
4718c2ecf20Sopenharmony_ci{
4728c2ecf20Sopenharmony_ci	unsigned long totalpages = 0;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	spin_lock(&swap_lock);
4758c2ecf20Sopenharmony_ci	totalpages = __frontswap_curr_pages();
4768c2ecf20Sopenharmony_ci	spin_unlock(&swap_lock);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	return totalpages;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(frontswap_curr_pages);
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_cistatic int __init init_frontswap(void)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
4858c2ecf20Sopenharmony_ci	struct dentry *root = debugfs_create_dir("frontswap", NULL);
4868c2ecf20Sopenharmony_ci	if (root == NULL)
4878c2ecf20Sopenharmony_ci		return -ENXIO;
4888c2ecf20Sopenharmony_ci	debugfs_create_u64("loads", 0444, root, &frontswap_loads);
4898c2ecf20Sopenharmony_ci	debugfs_create_u64("succ_stores", 0444, root, &frontswap_succ_stores);
4908c2ecf20Sopenharmony_ci	debugfs_create_u64("failed_stores", 0444, root,
4918c2ecf20Sopenharmony_ci			   &frontswap_failed_stores);
4928c2ecf20Sopenharmony_ci	debugfs_create_u64("invalidates", 0444, root, &frontswap_invalidates);
4938c2ecf20Sopenharmony_ci#endif
4948c2ecf20Sopenharmony_ci	return 0;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cimodule_init(init_frontswap);
498