diff options
Diffstat (limited to 'drivers/staging/zcache/zcache-main.c')
-rw-r--r-- | drivers/staging/zcache/zcache-main.c | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 784c796b9848..c9e08bbeb519 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -31,6 +31,7 @@ #include <linux/math64.h> #include <linux/crypto.h> #include <linux/string.h> +#include <linux/idr.h> #include "tmem.h" #include "../zsmalloc/zsmalloc.h" @@ -53,15 +54,13 @@ (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) #endif -#define MAX_POOLS_PER_CLIENT 16 - #define MAX_CLIENTS 16 #define LOCAL_CLIENT ((uint16_t)-1) MODULE_LICENSE("GPL"); struct zcache_client { - struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT]; + struct idr tmem_pools; struct zs_pool *zspool; bool allocated; atomic_t refcount; @@ -693,14 +692,14 @@ static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; static atomic_t zv_curr_dist_counts[NCHUNKS]; static atomic_t zv_cumul_dist_counts[NCHUNKS]; -static struct zv_hdr *zv_create(struct zs_pool *pool, uint32_t pool_id, +static unsigned long zv_create(struct zs_pool *pool, uint32_t pool_id, struct tmem_oid *oid, uint32_t index, void *cdata, unsigned clen) { struct zv_hdr *zv; u32 size = clen + sizeof(struct zv_hdr); int chunks = (size + (CHUNK_SIZE - 1)) >> CHUNK_SHIFT; - void *handle = NULL; + unsigned long handle = 0; BUG_ON(!irqs_disabled()); BUG_ON(chunks >= NCHUNKS); @@ -721,7 +720,7 @@ out: return handle; } -static void zv_free(struct zs_pool *pool, void *handle) +static void zv_free(struct zs_pool *pool, unsigned long handle) { unsigned long flags; struct zv_hdr *zv; @@ -743,7 +742,7 @@ static void zv_free(struct zs_pool *pool, void *handle) local_irq_restore(flags); } -static void zv_decompress(struct page *page, void *handle) +static void zv_decompress(struct page *page, unsigned long handle) { unsigned int clen = PAGE_SIZE; char *to_va; @@ -949,11 +948,9 @@ static struct tmem_pool *zcache_get_pool_by_id(uint16_t cli_id, uint16_t poolid) goto out; atomic_inc(&cli->refcount); } - if (poolid < MAX_POOLS_PER_CLIENT) { - pool = cli->tmem_pools[poolid]; - if (pool != NULL) - atomic_inc(&pool->refcount); - } + pool = idr_find(&cli->tmem_pools, poolid); + if (pool != NULL) + atomic_inc(&pool->refcount); out: return pool; } @@ -987,6 +984,7 @@ int zcache_new_client(uint16_t cli_id) cli->zspool = zs_create_pool("zcache", ZCACHE_GFP_MASK); if (cli->zspool == NULL) goto out; + idr_init(&cli->tmem_pools); #endif ret = 0; out: @@ -1247,7 +1245,7 @@ static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, int ret = 0; BUG_ON(is_ephemeral(pool)); - zv_decompress((struct page *)(data), pampd); + zv_decompress((struct page *)(data), (unsigned long)pampd); return ret; } @@ -1282,7 +1280,7 @@ static void zcache_pampd_free(void *pampd, struct tmem_pool *pool, atomic_dec(&zcache_curr_eph_pampd_count); BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0); } else { - zv_free(cli->zspool, pampd); + zv_free(cli->zspool, (unsigned long)pampd); atomic_dec(&zcache_curr_pers_pampd_count); BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0); } @@ -1673,10 +1671,10 @@ static int zcache_destroy_pool(int cli_id, int pool_id) if (cli == NULL) goto out; atomic_inc(&cli->refcount); - pool = cli->tmem_pools[pool_id]; + pool = idr_find(&cli->tmem_pools, pool_id); if (pool == NULL) goto out; - cli->tmem_pools[pool_id] = NULL; + idr_remove(&cli->tmem_pools, pool_id); /* wait for pool activity on other cpus to quiesce */ while (atomic_read(&pool->refcount) != 0) ; @@ -1696,6 +1694,7 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) int poolid = -1; struct tmem_pool *pool; struct zcache_client *cli = NULL; + int r; if (cli_id == LOCAL_CLIENT) cli = &zcache_host; @@ -1710,20 +1709,25 @@ static int zcache_new_pool(uint16_t cli_id, uint32_t flags) goto out; } - for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++) - if (cli->tmem_pools[poolid] == NULL) - break; - if (poolid >= MAX_POOLS_PER_CLIENT) { - pr_info("zcache: pool creation failed: max exceeded\n"); + do { + r = idr_pre_get(&cli->tmem_pools, GFP_ATOMIC); + if (r != 1) { + kfree(pool); + pr_info("zcache: pool creation failed: out of memory\n"); + goto out; + } + r = idr_get_new(&cli->tmem_pools, pool, &poolid); + } while (r == -EAGAIN); + if (r) { + pr_info("zcache: pool creation failed: error %d\n", r); kfree(pool); - poolid = -1; goto out; } + atomic_set(&pool->refcount, 0); pool->client = cli; pool->pool_id = poolid; tmem_new_pool(pool, flags); - cli->tmem_pools[poolid] = pool; pr_info("zcache: created %s tmem pool, id=%d, client=%d\n", flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", poolid, cli_id); |