162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * zpool memory storage api
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2014 Dan Streetman
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This is a common frontend for memory storage pool implementations.
862306a36Sopenharmony_ci * Typically, this is used to store compressed memory.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/list.h>
1462306a36Sopenharmony_ci#include <linux/types.h>
1562306a36Sopenharmony_ci#include <linux/mm.h>
1662306a36Sopenharmony_ci#include <linux/slab.h>
1762306a36Sopenharmony_ci#include <linux/spinlock.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/zpool.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistruct zpool {
2262306a36Sopenharmony_ci	struct zpool_driver *driver;
2362306a36Sopenharmony_ci	void *pool;
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistatic LIST_HEAD(drivers_head);
2762306a36Sopenharmony_cistatic DEFINE_SPINLOCK(drivers_lock);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/**
3062306a36Sopenharmony_ci * zpool_register_driver() - register a zpool implementation.
3162306a36Sopenharmony_ci * @driver:	driver to register
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_civoid zpool_register_driver(struct zpool_driver *driver)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	spin_lock(&drivers_lock);
3662306a36Sopenharmony_ci	atomic_set(&driver->refcount, 0);
3762306a36Sopenharmony_ci	list_add(&driver->list, &drivers_head);
3862306a36Sopenharmony_ci	spin_unlock(&drivers_lock);
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ciEXPORT_SYMBOL(zpool_register_driver);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/**
4362306a36Sopenharmony_ci * zpool_unregister_driver() - unregister a zpool implementation.
4462306a36Sopenharmony_ci * @driver:	driver to unregister.
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * Module usage counting is used to prevent using a driver
4762306a36Sopenharmony_ci * while/after unloading, so if this is called from module
4862306a36Sopenharmony_ci * exit function, this should never fail; if called from
4962306a36Sopenharmony_ci * other than the module exit function, and this returns
5062306a36Sopenharmony_ci * failure, the driver is in use and must remain available.
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_ciint zpool_unregister_driver(struct zpool_driver *driver)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	int ret = 0, refcount;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	spin_lock(&drivers_lock);
5762306a36Sopenharmony_ci	refcount = atomic_read(&driver->refcount);
5862306a36Sopenharmony_ci	WARN_ON(refcount < 0);
5962306a36Sopenharmony_ci	if (refcount > 0)
6062306a36Sopenharmony_ci		ret = -EBUSY;
6162306a36Sopenharmony_ci	else
6262306a36Sopenharmony_ci		list_del(&driver->list);
6362306a36Sopenharmony_ci	spin_unlock(&drivers_lock);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return ret;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ciEXPORT_SYMBOL(zpool_unregister_driver);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/* this assumes @type is null-terminated. */
7062306a36Sopenharmony_cistatic struct zpool_driver *zpool_get_driver(const char *type)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	struct zpool_driver *driver;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	spin_lock(&drivers_lock);
7562306a36Sopenharmony_ci	list_for_each_entry(driver, &drivers_head, list) {
7662306a36Sopenharmony_ci		if (!strcmp(driver->type, type)) {
7762306a36Sopenharmony_ci			bool got = try_module_get(driver->owner);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci			if (got)
8062306a36Sopenharmony_ci				atomic_inc(&driver->refcount);
8162306a36Sopenharmony_ci			spin_unlock(&drivers_lock);
8262306a36Sopenharmony_ci			return got ? driver : NULL;
8362306a36Sopenharmony_ci		}
8462306a36Sopenharmony_ci	}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	spin_unlock(&drivers_lock);
8762306a36Sopenharmony_ci	return NULL;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic void zpool_put_driver(struct zpool_driver *driver)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	atomic_dec(&driver->refcount);
9362306a36Sopenharmony_ci	module_put(driver->owner);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/**
9762306a36Sopenharmony_ci * zpool_has_pool() - Check if the pool driver is available
9862306a36Sopenharmony_ci * @type:	The type of the zpool to check (e.g. zbud, zsmalloc)
9962306a36Sopenharmony_ci *
10062306a36Sopenharmony_ci * This checks if the @type pool driver is available.  This will try to load
10162306a36Sopenharmony_ci * the requested module, if needed, but there is no guarantee the module will
10262306a36Sopenharmony_ci * still be loaded and available immediately after calling.  If this returns
10362306a36Sopenharmony_ci * true, the caller should assume the pool is available, but must be prepared
10462306a36Sopenharmony_ci * to handle the @zpool_create_pool() returning failure.  However if this
10562306a36Sopenharmony_ci * returns false, the caller should assume the requested pool type is not
10662306a36Sopenharmony_ci * available; either the requested pool type module does not exist, or could
10762306a36Sopenharmony_ci * not be loaded, and calling @zpool_create_pool() with the pool type will
10862306a36Sopenharmony_ci * fail.
10962306a36Sopenharmony_ci *
11062306a36Sopenharmony_ci * The @type string must be null-terminated.
11162306a36Sopenharmony_ci *
11262306a36Sopenharmony_ci * Returns: true if @type pool is available, false if not
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_cibool zpool_has_pool(char *type)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	struct zpool_driver *driver = zpool_get_driver(type);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (!driver) {
11962306a36Sopenharmony_ci		request_module("zpool-%s", type);
12062306a36Sopenharmony_ci		driver = zpool_get_driver(type);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	if (!driver)
12462306a36Sopenharmony_ci		return false;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	zpool_put_driver(driver);
12762306a36Sopenharmony_ci	return true;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ciEXPORT_SYMBOL(zpool_has_pool);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/**
13262306a36Sopenharmony_ci * zpool_create_pool() - Create a new zpool
13362306a36Sopenharmony_ci * @type:	The type of the zpool to create (e.g. zbud, zsmalloc)
13462306a36Sopenharmony_ci * @name:	The name of the zpool (e.g. zram0, zswap)
13562306a36Sopenharmony_ci * @gfp:	The GFP flags to use when allocating the pool.
13662306a36Sopenharmony_ci *
13762306a36Sopenharmony_ci * This creates a new zpool of the specified type.  The gfp flags will be
13862306a36Sopenharmony_ci * used when allocating memory, if the implementation supports it.  If the
13962306a36Sopenharmony_ci * ops param is NULL, then the created zpool will not be evictable.
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
14262306a36Sopenharmony_ci *
14362306a36Sopenharmony_ci * The @type and @name strings must be null-terminated.
14462306a36Sopenharmony_ci *
14562306a36Sopenharmony_ci * Returns: New zpool on success, NULL on failure.
14662306a36Sopenharmony_ci */
14762306a36Sopenharmony_cistruct zpool *zpool_create_pool(const char *type, const char *name, gfp_t gfp)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	struct zpool_driver *driver;
15062306a36Sopenharmony_ci	struct zpool *zpool;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	pr_debug("creating pool type %s\n", type);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	driver = zpool_get_driver(type);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	if (!driver) {
15762306a36Sopenharmony_ci		request_module("zpool-%s", type);
15862306a36Sopenharmony_ci		driver = zpool_get_driver(type);
15962306a36Sopenharmony_ci	}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (!driver) {
16262306a36Sopenharmony_ci		pr_err("no driver for type %s\n", type);
16362306a36Sopenharmony_ci		return NULL;
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	zpool = kmalloc(sizeof(*zpool), gfp);
16762306a36Sopenharmony_ci	if (!zpool) {
16862306a36Sopenharmony_ci		pr_err("couldn't create zpool - out of memory\n");
16962306a36Sopenharmony_ci		zpool_put_driver(driver);
17062306a36Sopenharmony_ci		return NULL;
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	zpool->driver = driver;
17462306a36Sopenharmony_ci	zpool->pool = driver->create(name, gfp);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (!zpool->pool) {
17762306a36Sopenharmony_ci		pr_err("couldn't create %s pool\n", type);
17862306a36Sopenharmony_ci		zpool_put_driver(driver);
17962306a36Sopenharmony_ci		kfree(zpool);
18062306a36Sopenharmony_ci		return NULL;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	pr_debug("created pool type %s\n", type);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	return zpool;
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/**
18962306a36Sopenharmony_ci * zpool_destroy_pool() - Destroy a zpool
19062306a36Sopenharmony_ci * @zpool:	The zpool to destroy.
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * Implementations must guarantee this to be thread-safe,
19362306a36Sopenharmony_ci * however only when destroying different pools.  The same
19462306a36Sopenharmony_ci * pool should only be destroyed once, and should not be used
19562306a36Sopenharmony_ci * after it is destroyed.
19662306a36Sopenharmony_ci *
19762306a36Sopenharmony_ci * This destroys an existing zpool.  The zpool should not be in use.
19862306a36Sopenharmony_ci */
19962306a36Sopenharmony_civoid zpool_destroy_pool(struct zpool *zpool)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	pr_debug("destroying pool type %s\n", zpool->driver->type);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	zpool->driver->destroy(zpool->pool);
20462306a36Sopenharmony_ci	zpool_put_driver(zpool->driver);
20562306a36Sopenharmony_ci	kfree(zpool);
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/**
20962306a36Sopenharmony_ci * zpool_get_type() - Get the type of the zpool
21062306a36Sopenharmony_ci * @zpool:	The zpool to check
21162306a36Sopenharmony_ci *
21262306a36Sopenharmony_ci * This returns the type of the pool.
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * Returns: The type of zpool.
21762306a36Sopenharmony_ci */
21862306a36Sopenharmony_ciconst char *zpool_get_type(struct zpool *zpool)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	return zpool->driver->type;
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci/**
22462306a36Sopenharmony_ci * zpool_malloc_support_movable() - Check if the zpool supports
22562306a36Sopenharmony_ci *	allocating movable memory
22662306a36Sopenharmony_ci * @zpool:	The zpool to check
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci * This returns if the zpool supports allocating movable memory.
22962306a36Sopenharmony_ci *
23062306a36Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
23162306a36Sopenharmony_ci *
23262306a36Sopenharmony_ci * Returns: true if the zpool supports allocating movable memory, false if not
23362306a36Sopenharmony_ci */
23462306a36Sopenharmony_cibool zpool_malloc_support_movable(struct zpool *zpool)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	return zpool->driver->malloc_support_movable;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci/**
24062306a36Sopenharmony_ci * zpool_malloc() - Allocate memory
24162306a36Sopenharmony_ci * @zpool:	The zpool to allocate from.
24262306a36Sopenharmony_ci * @size:	The amount of memory to allocate.
24362306a36Sopenharmony_ci * @gfp:	The GFP flags to use when allocating memory.
24462306a36Sopenharmony_ci * @handle:	Pointer to the handle to set
24562306a36Sopenharmony_ci *
24662306a36Sopenharmony_ci * This allocates the requested amount of memory from the pool.
24762306a36Sopenharmony_ci * The gfp flags will be used when allocating memory, if the
24862306a36Sopenharmony_ci * implementation supports it.  The provided @handle will be
24962306a36Sopenharmony_ci * set to the allocated object handle.
25062306a36Sopenharmony_ci *
25162306a36Sopenharmony_ci * Implementations must guarantee this to be thread-safe.
25262306a36Sopenharmony_ci *
25362306a36Sopenharmony_ci * Returns: 0 on success, negative value on error.
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_ciint zpool_malloc(struct zpool *zpool, size_t size, gfp_t gfp,
25662306a36Sopenharmony_ci			unsigned long *handle)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	return zpool->driver->malloc(zpool->pool, size, gfp, handle);
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci/**
26262306a36Sopenharmony_ci * zpool_free() - Free previously allocated memory
26362306a36Sopenharmony_ci * @zpool:	The zpool that allocated the memory.
26462306a36Sopenharmony_ci * @handle:	The handle to the memory to free.
26562306a36Sopenharmony_ci *
26662306a36Sopenharmony_ci * This frees previously allocated memory.  This does not guarantee
26762306a36Sopenharmony_ci * that the pool will actually free memory, only that the memory
26862306a36Sopenharmony_ci * in the pool will become available for use by the pool.
26962306a36Sopenharmony_ci *
27062306a36Sopenharmony_ci * Implementations must guarantee this to be thread-safe,
27162306a36Sopenharmony_ci * however only when freeing different handles.  The same
27262306a36Sopenharmony_ci * handle should only be freed once, and should not be used
27362306a36Sopenharmony_ci * after freeing.
27462306a36Sopenharmony_ci */
27562306a36Sopenharmony_civoid zpool_free(struct zpool *zpool, unsigned long handle)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	zpool->driver->free(zpool->pool, handle);
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci/**
28162306a36Sopenharmony_ci * zpool_map_handle() - Map a previously allocated handle into memory
28262306a36Sopenharmony_ci * @zpool:	The zpool that the handle was allocated from
28362306a36Sopenharmony_ci * @handle:	The handle to map
28462306a36Sopenharmony_ci * @mapmode:	How the memory should be mapped
28562306a36Sopenharmony_ci *
28662306a36Sopenharmony_ci * This maps a previously allocated handle into memory.  The @mapmode
28762306a36Sopenharmony_ci * param indicates to the implementation how the memory will be
28862306a36Sopenharmony_ci * used, i.e. read-only, write-only, read-write.  If the
28962306a36Sopenharmony_ci * implementation does not support it, the memory will be treated
29062306a36Sopenharmony_ci * as read-write.
29162306a36Sopenharmony_ci *
29262306a36Sopenharmony_ci * This may hold locks, disable interrupts, and/or preemption,
29362306a36Sopenharmony_ci * and the zpool_unmap_handle() must be called to undo those
29462306a36Sopenharmony_ci * actions.  The code that uses the mapped handle should complete
29562306a36Sopenharmony_ci * its operations on the mapped handle memory quickly and unmap
29662306a36Sopenharmony_ci * as soon as possible.  As the implementation may use per-cpu
29762306a36Sopenharmony_ci * data, multiple handles should not be mapped concurrently on
29862306a36Sopenharmony_ci * any cpu.
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci * Returns: A pointer to the handle's mapped memory area.
30162306a36Sopenharmony_ci */
30262306a36Sopenharmony_civoid *zpool_map_handle(struct zpool *zpool, unsigned long handle,
30362306a36Sopenharmony_ci			enum zpool_mapmode mapmode)
30462306a36Sopenharmony_ci{
30562306a36Sopenharmony_ci	return zpool->driver->map(zpool->pool, handle, mapmode);
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci/**
30962306a36Sopenharmony_ci * zpool_unmap_handle() - Unmap a previously mapped handle
31062306a36Sopenharmony_ci * @zpool:	The zpool that the handle was allocated from
31162306a36Sopenharmony_ci * @handle:	The handle to unmap
31262306a36Sopenharmony_ci *
31362306a36Sopenharmony_ci * This unmaps a previously mapped handle.  Any locks or other
31462306a36Sopenharmony_ci * actions that the implementation took in zpool_map_handle()
31562306a36Sopenharmony_ci * will be undone here.  The memory area returned from
31662306a36Sopenharmony_ci * zpool_map_handle() should no longer be used after this.
31762306a36Sopenharmony_ci */
31862306a36Sopenharmony_civoid zpool_unmap_handle(struct zpool *zpool, unsigned long handle)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	zpool->driver->unmap(zpool->pool, handle);
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci/**
32462306a36Sopenharmony_ci * zpool_get_total_size() - The total size of the pool
32562306a36Sopenharmony_ci * @zpool:	The zpool to check
32662306a36Sopenharmony_ci *
32762306a36Sopenharmony_ci * This returns the total size in bytes of the pool.
32862306a36Sopenharmony_ci *
32962306a36Sopenharmony_ci * Returns: Total size of the zpool in bytes.
33062306a36Sopenharmony_ci */
33162306a36Sopenharmony_ciu64 zpool_get_total_size(struct zpool *zpool)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	return zpool->driver->total_size(zpool->pool);
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci/**
33762306a36Sopenharmony_ci * zpool_can_sleep_mapped - Test if zpool can sleep when do mapped.
33862306a36Sopenharmony_ci * @zpool:	The zpool to test
33962306a36Sopenharmony_ci *
34062306a36Sopenharmony_ci * Some allocators enter non-preemptible context in ->map() callback (e.g.
34162306a36Sopenharmony_ci * disable pagefaults) and exit that context in ->unmap(), which limits what
34262306a36Sopenharmony_ci * we can do with the mapped object. For instance, we cannot wait for
34362306a36Sopenharmony_ci * asynchronous crypto API to decompress such an object or take mutexes
34462306a36Sopenharmony_ci * since those will call into the scheduler. This function tells us whether
34562306a36Sopenharmony_ci * we use such an allocator.
34662306a36Sopenharmony_ci *
34762306a36Sopenharmony_ci * Returns: true if zpool can sleep; false otherwise.
34862306a36Sopenharmony_ci */
34962306a36Sopenharmony_cibool zpool_can_sleep_mapped(struct zpool *zpool)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	return zpool->driver->sleep_mapped;
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ciMODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
35562306a36Sopenharmony_ciMODULE_DESCRIPTION("Common API for compressed memory storage");
356