Merge 3.5-rc4 into staging-next
[deliverable/linux.git] / drivers / staging / zcache / zcache-main.c
index 784c796b9848a12b6167150d3a94d20a086e68b8..c9e08bbeb519884ab63f9e557a313e438829aaf2 100644 (file)
@@ -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"
        (__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);
This page took 0.036457 seconds and 5 git commands to generate.