Merge tag 'irqchip-core-4.8' of git://git.infradead.org/users/jcooper/linux into...
[cascardo/linux.git] / mm / zswap.c
index 91dad80..275b22c 100644 (file)
@@ -117,7 +117,7 @@ struct zswap_pool {
        struct crypto_comp * __percpu *tfm;
        struct kref kref;
        struct list_head list;
-       struct rcu_head rcu_head;
+       struct work_struct work;
        struct notifier_block notifier;
        char tfm_name[CRYPTO_MAX_ALG_NAME];
 };
@@ -170,6 +170,8 @@ static struct zswap_tree *zswap_trees[MAX_SWAPFILES];
 static LIST_HEAD(zswap_pools);
 /* protects zswap_pools list modification */
 static DEFINE_SPINLOCK(zswap_pools_lock);
+/* pool counter to provide unique names to zpool */
+static atomic_t zswap_pools_count = ATOMIC_INIT(0);
 
 /* used by param callback function */
 static bool zswap_init_started;
@@ -565,6 +567,7 @@ static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
 static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
 {
        struct zswap_pool *pool;
+       char name[38]; /* 'zswap' + 32 char (max) num + \0 */
        gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
 
        pool = kzalloc(sizeof(*pool), GFP_KERNEL);
@@ -573,7 +576,10 @@ static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
                return NULL;
        }
 
-       pool->zpool = zpool_create_pool(type, "zswap", gfp, &zswap_zpool_ops);
+       /* unique name for each pool specifically required by zsmalloc */
+       snprintf(name, 38, "zswap%x", atomic_inc_return(&zswap_pools_count));
+
+       pool->zpool = zpool_create_pool(type, name, gfp, &zswap_zpool_ops);
        if (!pool->zpool) {
                pr_err("%s zpool not available\n", type);
                goto error;
@@ -652,9 +658,11 @@ static int __must_check zswap_pool_get(struct zswap_pool *pool)
        return kref_get_unless_zero(&pool->kref);
 }
 
-static void __zswap_pool_release(struct rcu_head *head)
+static void __zswap_pool_release(struct work_struct *work)
 {
-       struct zswap_pool *pool = container_of(head, typeof(*pool), rcu_head);
+       struct zswap_pool *pool = container_of(work, typeof(*pool), work);
+
+       synchronize_rcu();
 
        /* nobody should have been able to get a kref... */
        WARN_ON(kref_get_unless_zero(&pool->kref));
@@ -674,7 +682,9 @@ static void __zswap_pool_empty(struct kref *kref)
        WARN_ON(pool == zswap_pool_current());
 
        list_del_rcu(&pool->list);
-       call_rcu(&pool->rcu_head, __zswap_pool_release);
+
+       INIT_WORK(&pool->work, __zswap_pool_release);
+       schedule_work(&pool->work);
 
        spin_unlock(&zswap_pools_lock);
 }