18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * zpool memory storage api
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Dan Streetman
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This is a common frontend for memory storage pool implementations.
88c2ecf20Sopenharmony_ci * Typically, this is used to store compressed memory.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/list.h>
148c2ecf20Sopenharmony_ci#include <linux/types.h>
158c2ecf20Sopenharmony_ci#include <linux/mm.h>
168c2ecf20Sopenharmony_ci#include <linux/slab.h>
178c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/zpool.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct zpool {
228c2ecf20Sopenharmony_ci	struct zpool_driver *driver;
238c2ecf20Sopenharmony_ci	void *pool;
248c2ecf20Sopenharmony_ci	const struct zpool_ops *ops;
258c2ecf20Sopenharmony_ci	bool evictable;
268c2ecf20Sopenharmony_ci	bool can_sleep_mapped;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	struct list_head list;
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic LIST_HEAD(drivers_head);
328c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(drivers_lock);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic LIST_HEAD(pools_head);
358c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(pools_lock);
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/**
388c2ecf20Sopenharmony_ci * zpool_register_driver() - register a zpool implementation.
398c2ecf20Sopenharmony_ci * @driver:	driver to register
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_civoid zpool_register_driver(struct zpool_driver *driver)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	spin_lock(&drivers_lock);
448c2ecf20Sopenharmony_ci	atomic_set(&driver->refcount, 0);
458c2ecf20Sopenharmony_ci	list_add(&driver->list, &drivers_head);
468c2ecf20Sopenharmony_ci	spin_unlock(&drivers_lock);
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(zpool_register_driver);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/**
518c2ecf20Sopenharmony_ci * zpool_unregister_driver() - unregister a zpool implementation.
528c2ecf20Sopenharmony_ci * @driver:	driver to unregister.
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * Module usage counting is used to prevent using a driver
558c2ecf20Sopenharmony_ci * while/after unloading, so if this is called from module
568c2ecf20Sopenharmony_ci * exit function, this should never fail; if called from
578c2ecf20Sopenharmony_ci * other than the module exit function, and this returns
588c2ecf20Sopenharmony_ci * failure, the driver is in use and must remain available.
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_ciint zpool_unregister_driver(struct zpool_driver *driver)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	int ret = 0, refcount;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	spin_lock(&drivers_lock);
658c2ecf20Sopenharmony_ci	refcount = atomic_read(&driver->refcount);
668c2ecf20Sopenharmony_ci	WARN_ON(refcount < 0);
678c2ecf20Sopenharmony_ci	if (refcount > 0)
688c2ecf20Sopenharmony_ci		ret = -EBUSY;
698c2ecf20Sopenharmony_ci	else
708c2ecf20Sopenharmony_ci		list_del(&driver->list);
718c2ecf20Sopenharmony_ci	spin_unlock(&drivers_lock);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	return ret;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(zpool_unregister_driver);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci/* this assumes @type is null-terminated. */
788c2ecf20Sopenharmony_cistatic struct zpool_driver *zpool_get_driver(const char *type)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	struct zpool_driver *driver;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	spin_lock(&drivers_lock);
838c2ecf20Sopenharmony_ci	list_for_each_entry(driver, &drivers_head, list) {
848c2ecf20Sopenharmony_ci		if (!strcmp(driver->type, type)) {
858c2ecf20Sopenharmony_ci			bool got = try_module_get(driver->owner);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci			if (got)
888c2ecf20Sopenharmony_ci				atomic_inc(&driver->refcount);
898c2ecf20Sopenharmony_ci			spin_unlock(&drivers_lock);
908c2ecf20Sopenharmony_ci			return got ? driver : NULL;
918c2ecf20Sopenharmony_ci		}
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	spin_unlock(&drivers_lock);
958c2ecf20Sopenharmony_ci	return NULL;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic void zpool_put_driver(struct zpool_driver *driver)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	atomic_dec(&driver->refcount);
1018c2ecf20Sopenharmony_ci	module_put(driver->owner);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci/**
1058c2ecf20Sopenharmony_ci * zpool_has_pool() - Check if the pool driver is available
1068c2ecf20Sopenharmony_ci * @type:	The type of the zpool to check (e.g. zbud, zsmalloc)
1078c2ecf20Sopenharmony_ci *
1088c2ecf20Sopenharmony_ci * This checks if the @type pool driver is available.  This will try to load
1098c2ecf20Sopenharmony_ci * the requested module, if needed, but there is no guarantee the module will
1108c2ecf20Sopenharmony_ci * still be loaded and available immediately after calling.  If this returns
1118c2ecf20Sopenharmony_ci * true, the caller should assume the pool is available, but must be prepared
1128c2ecf20Sopenharmony_ci * to handle the @zpool_create_pool() returning failure.  However if this
1138c2ecf20Sopenharmony_ci * returns false, the caller should assume the requested pool type is not
1148c2ecf20Sopenharmony_ci * available; either the requested pool type module does not exist, or could
1158c2ecf20Sopenharmony_ci * not be loaded, and calling @zpool_create_pool() with the pool type will
1168c2ecf20Sopenharmony_ci * fail.
1178c2ecf20Sopenharmony_ci *
1188c2ecf20Sopenharmony_ci * The @type string must be null-terminated.
1198c2ecf20Sopenharmony_ci *
1208c2ecf20Sopenharmony_ci * Returns: true if @type pool is available, false if not
1218c2ecf20Sopenharmony_ci */
1228c2ecf20Sopenharmony_cibool zpool_has_pool(char *type)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct zpool_driver *driver = zpool_get_driver(type);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (!driver) {
1278c2ecf20Sopenharmony_ci		request_module("zpool-%s", type);
1288c2ecf20Sopenharmony_ci		driver = zpool_get_driver(type);
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (!driver)
1328c2ecf20Sopenharmony_ci		return false;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	zpool_put_driver(driver);
1358c2ecf20Sopenharmony_ci	return true;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(zpool_has_pool);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/**
1408c2ecf20Sopenharmony_ci * zpool_create_pool() - Create a new zpool
1418c2ecf20Sopenharmony_ci * @type:	The type of the zpool to create (e.g. zbud, zsmalloc)
1428c2ecf20Sopenharmony_ci * @name:	The name of the zpool (e.g. zram0, zswap)
1438c2ecf20Sopenharmony_ci * @gfp:	The GFP flags to use when allocating the pool.
1448c2ecf20Sopenharmony_ci * @ops:	The optional ops callback.
1458c2ecf20Sopenharmony_ci *
1468c2ecf20Sopenharmony_ci * This creates a new zpool of the specified type.  The gfp flags will be
1478c2ecf20Sopenharmony_ci * used when allocating memory, if the implementation supports it.  If the
1488c2ecf20Sopenharmony_ci * ops param is NULL, then the created zpool will not be evictable.
1498c2ecf20Sopenharmony_ci *
1508c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
1518c2ecf20Sopenharmony_ci *
1528c2ecf20Sopenharmony_ci * The @type and @name strings must be null-terminated.
1538c2ecf20Sopenharmony_ci *
1548c2ecf20Sopenharmony_ci * Returns: New zpool on success, NULL on failure.
1558c2ecf20Sopenharmony_ci */
1568c2ecf20Sopenharmony_cistruct zpool *zpool_create_pool(const char *type, const char *name, gfp_t gfp,
1578c2ecf20Sopenharmony_ci		const struct zpool_ops *ops)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct zpool_driver *driver;
1608c2ecf20Sopenharmony_ci	struct zpool *zpool;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	pr_debug("creating pool type %s\n", type);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	driver = zpool_get_driver(type);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	if (!driver) {
1678c2ecf20Sopenharmony_ci		request_module("zpool-%s", type);
1688c2ecf20Sopenharmony_ci		driver = zpool_get_driver(type);
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (!driver) {
1728c2ecf20Sopenharmony_ci		pr_err("no driver for type %s\n", type);
1738c2ecf20Sopenharmony_ci		return NULL;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	zpool = kmalloc(sizeof(*zpool), gfp);
1778c2ecf20Sopenharmony_ci	if (!zpool) {
1788c2ecf20Sopenharmony_ci		pr_err("couldn't create zpool - out of memory\n");
1798c2ecf20Sopenharmony_ci		zpool_put_driver(driver);
1808c2ecf20Sopenharmony_ci		return NULL;
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	zpool->driver = driver;
1848c2ecf20Sopenharmony_ci	zpool->pool = driver->create(name, gfp, ops, zpool);
1858c2ecf20Sopenharmony_ci	zpool->ops = ops;
1868c2ecf20Sopenharmony_ci	zpool->evictable = driver->shrink && ops && ops->evict;
1878c2ecf20Sopenharmony_ci	zpool->can_sleep_mapped = driver->sleep_mapped;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	if (!zpool->pool) {
1908c2ecf20Sopenharmony_ci		pr_err("couldn't create %s pool\n", type);
1918c2ecf20Sopenharmony_ci		zpool_put_driver(driver);
1928c2ecf20Sopenharmony_ci		kfree(zpool);
1938c2ecf20Sopenharmony_ci		return NULL;
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	pr_debug("created pool type %s\n", type);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	spin_lock(&pools_lock);
1998c2ecf20Sopenharmony_ci	list_add(&zpool->list, &pools_head);
2008c2ecf20Sopenharmony_ci	spin_unlock(&pools_lock);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	return zpool;
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/**
2068c2ecf20Sopenharmony_ci * zpool_destroy_pool() - Destroy a zpool
2078c2ecf20Sopenharmony_ci * @zpool:	The zpool to destroy.
2088c2ecf20Sopenharmony_ci *
2098c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe,
2108c2ecf20Sopenharmony_ci * however only when destroying different pools.  The same
2118c2ecf20Sopenharmony_ci * pool should only be destroyed once, and should not be used
2128c2ecf20Sopenharmony_ci * after it is destroyed.
2138c2ecf20Sopenharmony_ci *
2148c2ecf20Sopenharmony_ci * This destroys an existing zpool.  The zpool should not be in use.
2158c2ecf20Sopenharmony_ci */
2168c2ecf20Sopenharmony_civoid zpool_destroy_pool(struct zpool *zpool)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	pr_debug("destroying pool type %s\n", zpool->driver->type);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	spin_lock(&pools_lock);
2218c2ecf20Sopenharmony_ci	list_del(&zpool->list);
2228c2ecf20Sopenharmony_ci	spin_unlock(&pools_lock);
2238c2ecf20Sopenharmony_ci	zpool->driver->destroy(zpool->pool);
2248c2ecf20Sopenharmony_ci	zpool_put_driver(zpool->driver);
2258c2ecf20Sopenharmony_ci	kfree(zpool);
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/**
2298c2ecf20Sopenharmony_ci * zpool_get_type() - Get the type of the zpool
2308c2ecf20Sopenharmony_ci * @zpool:	The zpool to check
2318c2ecf20Sopenharmony_ci *
2328c2ecf20Sopenharmony_ci * This returns the type of the pool.
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * Returns: The type of zpool.
2378c2ecf20Sopenharmony_ci */
2388c2ecf20Sopenharmony_ciconst char *zpool_get_type(struct zpool *zpool)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	return zpool->driver->type;
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/**
2448c2ecf20Sopenharmony_ci * zpool_malloc_support_movable() - Check if the zpool supports
2458c2ecf20Sopenharmony_ci *	allocating movable memory
2468c2ecf20Sopenharmony_ci * @zpool:	The zpool to check
2478c2ecf20Sopenharmony_ci *
2488c2ecf20Sopenharmony_ci * This returns if the zpool supports allocating movable memory.
2498c2ecf20Sopenharmony_ci *
2508c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
2518c2ecf20Sopenharmony_ci *
2528c2ecf20Sopenharmony_ci * Returns: true if the zpool supports allocating movable memory, false if not
2538c2ecf20Sopenharmony_ci */
2548c2ecf20Sopenharmony_cibool zpool_malloc_support_movable(struct zpool *zpool)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	return zpool->driver->malloc_support_movable;
2578c2ecf20Sopenharmony_ci}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci/**
2608c2ecf20Sopenharmony_ci * zpool_malloc() - Allocate memory
2618c2ecf20Sopenharmony_ci * @zpool:	The zpool to allocate from.
2628c2ecf20Sopenharmony_ci * @size:	The amount of memory to allocate.
2638c2ecf20Sopenharmony_ci * @gfp:	The GFP flags to use when allocating memory.
2648c2ecf20Sopenharmony_ci * @handle:	Pointer to the handle to set
2658c2ecf20Sopenharmony_ci *
2668c2ecf20Sopenharmony_ci * This allocates the requested amount of memory from the pool.
2678c2ecf20Sopenharmony_ci * The gfp flags will be used when allocating memory, if the
2688c2ecf20Sopenharmony_ci * implementation supports it.  The provided @handle will be
2698c2ecf20Sopenharmony_ci * set to the allocated object handle.
2708c2ecf20Sopenharmony_ci *
2718c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
2728c2ecf20Sopenharmony_ci *
2738c2ecf20Sopenharmony_ci * Returns: 0 on success, negative value on error.
2748c2ecf20Sopenharmony_ci */
2758c2ecf20Sopenharmony_ciint zpool_malloc(struct zpool *zpool, size_t size, gfp_t gfp,
2768c2ecf20Sopenharmony_ci			unsigned long *handle)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	return zpool->driver->malloc(zpool->pool, size, gfp, handle);
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci/**
2828c2ecf20Sopenharmony_ci * zpool_free() - Free previously allocated memory
2838c2ecf20Sopenharmony_ci * @zpool:	The zpool that allocated the memory.
2848c2ecf20Sopenharmony_ci * @handle:	The handle to the memory to free.
2858c2ecf20Sopenharmony_ci *
2868c2ecf20Sopenharmony_ci * This frees previously allocated memory.  This does not guarantee
2878c2ecf20Sopenharmony_ci * that the pool will actually free memory, only that the memory
2888c2ecf20Sopenharmony_ci * in the pool will become available for use by the pool.
2898c2ecf20Sopenharmony_ci *
2908c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe,
2918c2ecf20Sopenharmony_ci * however only when freeing different handles.  The same
2928c2ecf20Sopenharmony_ci * handle should only be freed once, and should not be used
2938c2ecf20Sopenharmony_ci * after freeing.
2948c2ecf20Sopenharmony_ci */
2958c2ecf20Sopenharmony_civoid zpool_free(struct zpool *zpool, unsigned long handle)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	zpool->driver->free(zpool->pool, handle);
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci/**
3018c2ecf20Sopenharmony_ci * zpool_shrink() - Shrink the pool size
3028c2ecf20Sopenharmony_ci * @zpool:	The zpool to shrink.
3038c2ecf20Sopenharmony_ci * @pages:	The number of pages to shrink the pool.
3048c2ecf20Sopenharmony_ci * @reclaimed:	The number of pages successfully evicted.
3058c2ecf20Sopenharmony_ci *
3068c2ecf20Sopenharmony_ci * This attempts to shrink the actual memory size of the pool
3078c2ecf20Sopenharmony_ci * by evicting currently used handle(s).  If the pool was
3088c2ecf20Sopenharmony_ci * created with no zpool_ops, or the evict call fails for any
3098c2ecf20Sopenharmony_ci * of the handles, this will fail.  If non-NULL, the @reclaimed
3108c2ecf20Sopenharmony_ci * parameter will be set to the number of pages reclaimed,
3118c2ecf20Sopenharmony_ci * which may be more than the number of pages requested.
3128c2ecf20Sopenharmony_ci *
3138c2ecf20Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
3148c2ecf20Sopenharmony_ci *
3158c2ecf20Sopenharmony_ci * Returns: 0 on success, negative value on error/failure.
3168c2ecf20Sopenharmony_ci */
3178c2ecf20Sopenharmony_ciint zpool_shrink(struct zpool *zpool, unsigned int pages,
3188c2ecf20Sopenharmony_ci			unsigned int *reclaimed)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	return zpool->driver->shrink ?
3218c2ecf20Sopenharmony_ci	       zpool->driver->shrink(zpool->pool, pages, reclaimed) : -EINVAL;
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci/**
3258c2ecf20Sopenharmony_ci * zpool_map_handle() - Map a previously allocated handle into memory
3268c2ecf20Sopenharmony_ci * @zpool:	The zpool that the handle was allocated from
3278c2ecf20Sopenharmony_ci * @handle:	The handle to map
3288c2ecf20Sopenharmony_ci * @mapmode:	How the memory should be mapped
3298c2ecf20Sopenharmony_ci *
3308c2ecf20Sopenharmony_ci * This maps a previously allocated handle into memory.  The @mapmode
3318c2ecf20Sopenharmony_ci * param indicates to the implementation how the memory will be
3328c2ecf20Sopenharmony_ci * used, i.e. read-only, write-only, read-write.  If the
3338c2ecf20Sopenharmony_ci * implementation does not support it, the memory will be treated
3348c2ecf20Sopenharmony_ci * as read-write.
3358c2ecf20Sopenharmony_ci *
3368c2ecf20Sopenharmony_ci * This may hold locks, disable interrupts, and/or preemption,
3378c2ecf20Sopenharmony_ci * and the zpool_unmap_handle() must be called to undo those
3388c2ecf20Sopenharmony_ci * actions.  The code that uses the mapped handle should complete
3398c2ecf20Sopenharmony_ci * its operatons on the mapped handle memory quickly and unmap
3408c2ecf20Sopenharmony_ci * as soon as possible.  As the implementation may use per-cpu
3418c2ecf20Sopenharmony_ci * data, multiple handles should not be mapped concurrently on
3428c2ecf20Sopenharmony_ci * any cpu.
3438c2ecf20Sopenharmony_ci *
3448c2ecf20Sopenharmony_ci * Returns: A pointer to the handle's mapped memory area.
3458c2ecf20Sopenharmony_ci */
3468c2ecf20Sopenharmony_civoid *zpool_map_handle(struct zpool *zpool, unsigned long handle,
3478c2ecf20Sopenharmony_ci			enum zpool_mapmode mapmode)
3488c2ecf20Sopenharmony_ci{
3498c2ecf20Sopenharmony_ci	return zpool->driver->map(zpool->pool, handle, mapmode);
3508c2ecf20Sopenharmony_ci}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci/**
3538c2ecf20Sopenharmony_ci * zpool_unmap_handle() - Unmap a previously mapped handle
3548c2ecf20Sopenharmony_ci * @zpool:	The zpool that the handle was allocated from
3558c2ecf20Sopenharmony_ci * @handle:	The handle to unmap
3568c2ecf20Sopenharmony_ci *
3578c2ecf20Sopenharmony_ci * This unmaps a previously mapped handle.  Any locks or other
3588c2ecf20Sopenharmony_ci * actions that the implementation took in zpool_map_handle()
3598c2ecf20Sopenharmony_ci * will be undone here.  The memory area returned from
3608c2ecf20Sopenharmony_ci * zpool_map_handle() should no longer be used after this.
3618c2ecf20Sopenharmony_ci */
3628c2ecf20Sopenharmony_civoid zpool_unmap_handle(struct zpool *zpool, unsigned long handle)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	zpool->driver->unmap(zpool->pool, handle);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci/**
3688c2ecf20Sopenharmony_ci * zpool_get_total_size() - The total size of the pool
3698c2ecf20Sopenharmony_ci * @zpool:	The zpool to check
3708c2ecf20Sopenharmony_ci *
3718c2ecf20Sopenharmony_ci * This returns the total size in bytes of the pool.
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * Returns: Total size of the zpool in bytes.
3748c2ecf20Sopenharmony_ci */
3758c2ecf20Sopenharmony_ciu64 zpool_get_total_size(struct zpool *zpool)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	return zpool->driver->total_size(zpool->pool);
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci/**
3818c2ecf20Sopenharmony_ci * zpool_evictable() - Test if zpool is potentially evictable
3828c2ecf20Sopenharmony_ci * @zpool:	The zpool to test
3838c2ecf20Sopenharmony_ci *
3848c2ecf20Sopenharmony_ci * Zpool is only potentially evictable when it's created with struct
3858c2ecf20Sopenharmony_ci * zpool_ops.evict and its driver implements struct zpool_driver.shrink.
3868c2ecf20Sopenharmony_ci *
3878c2ecf20Sopenharmony_ci * However, it doesn't necessarily mean driver will use zpool_ops.evict
3888c2ecf20Sopenharmony_ci * in its implementation of zpool_driver.shrink. It could do internal
3898c2ecf20Sopenharmony_ci * defragmentation instead.
3908c2ecf20Sopenharmony_ci *
3918c2ecf20Sopenharmony_ci * Returns: true if potentially evictable; false otherwise.
3928c2ecf20Sopenharmony_ci */
3938c2ecf20Sopenharmony_cibool zpool_evictable(struct zpool *zpool)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	return zpool->evictable;
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci/**
3998c2ecf20Sopenharmony_ci * zpool_can_sleep_mapped - Test if zpool can sleep when do mapped.
4008c2ecf20Sopenharmony_ci * @zpool:	The zpool to test
4018c2ecf20Sopenharmony_ci *
4028c2ecf20Sopenharmony_ci * Returns: true if zpool can sleep; false otherwise.
4038c2ecf20Sopenharmony_ci */
4048c2ecf20Sopenharmony_cibool zpool_can_sleep_mapped(struct zpool *zpool)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	return zpool->can_sleep_mapped;
4078c2ecf20Sopenharmony_ci}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
4108c2ecf20Sopenharmony_ciMODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
4118c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Common API for compressed memory storage");
412