summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/block/zram/zcomp.c84
-rw-r--r--drivers/block/zram/zcomp.h6
-rw-r--r--drivers/block/zram/zram_drv.c54
-rw-r--r--drivers/block/zram/zram_drv.h2
4 files changed, 48 insertions, 98 deletions
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index a02f08daf87a..1a8564a79d8d 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -63,6 +63,24 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
return zstrm;
}
+bool zcomp_available_algorithm(const char *comp)
+{
+ int i;
+
+ i = __sysfs_match_string(backends, -1, comp);
+ if (i >= 0)
+ return true;
+
+ /*
+ * Crypto does not ignore a trailing new line symbol,
+ * so make sure you don't supply a string containing
+ * one.
+ * This also means that we permit zcomp initialisation
+ * with any compressing algorithm known to crypto api.
+ */
+ return crypto_has_comp(comp, 0, 0) == 1;
+}
+
/* show available compressors */
ssize_t zcomp_available_show(const char *comp, char *buf)
{
@@ -184,43 +202,29 @@ cleanup:
return ret;
}
-static void zcomp_destroy(struct zcomp *comp)
+void zcomp_destroy(struct zcomp *comp)
{
cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
free_percpu(comp->stream);
kfree(comp);
}
-void zcomp_reset(struct list_head *blist)
-{
- struct list_head *curr, *next;
- struct zcomp *comp;
- int i;
-
- list_for_each_safe(curr, next, blist) {
- comp = list_entry(curr, struct zcomp, list);
- list_del(&comp->list);
-
- i = __sysfs_match_string(backends, -1, comp->name);
- if (i < 0)
- kfree(comp->name);
-
- zcomp_destroy(comp);
- }
-}
-
/*
+ * search available compressors for requested algorithm.
* allocate new zcomp and initialize it. return compressing
* backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
* if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
* case of allocation error, or any other error potentially
* returned by zcomp_init().
*/
-static struct zcomp *zcomp_create(const char *compress)
+struct zcomp *zcomp_create(const char *compress)
{
struct zcomp *comp;
int error;
+ if (!zcomp_available_algorithm(compress))
+ return ERR_PTR(-EINVAL);
+
comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
if (!comp)
return ERR_PTR(-ENOMEM);
@@ -233,43 +237,3 @@ static struct zcomp *zcomp_create(const char *compress)
}
return comp;
}
-
-struct zcomp *zcomp_get_instance(struct list_head *blist, const char *name)
-{
- struct zcomp *comp;
- const char *comp_name = NULL;
- int i;
-
- list_for_each_entry(comp, blist, list)
- if (sysfs_streq(name, comp->name))
- return comp;
-
- i = __sysfs_match_string(backends, -1, name);
- if (i >= 0)
- comp_name = backends[i];
- else {
- /*
- * Crypto does not ignore a trailing new line symbol,
- * so make sure you don't supply a string containing
- * one.
- * This also means that we permit zcomp initialisation
- * with any compressing algorithm known to crypto api.
- */
- if (crypto_has_comp(name, 0, 0) == 1)
- comp_name = kstrdup(name, GFP_KERNEL);
- else
- return ERR_PTR(-ENOENT);
- }
-
- comp = zcomp_create(comp_name);
- if (IS_ERR(comp)) {
- pr_err("Cannot initialise %s compressing backend\n", name);
- if (i < 0)
- kfree(comp_name);
- return comp;
- }
-
- list_add(&comp->list, blist);
-
- return comp;
-}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index aff688d16245..1806475b919d 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -17,15 +17,15 @@ struct zcomp {
struct zcomp_strm * __percpu *stream;
const char *name;
struct hlist_node node;
- struct list_head list;
};
int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node);
int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node);
ssize_t zcomp_available_show(const char *comp, char *buf);
+bool zcomp_available_algorithm(const char *comp);
-struct zcomp *zcomp_get_instance(struct list_head *blist, const char *name);
-void zcomp_reset(struct list_head *blist);
+struct zcomp *zcomp_create(const char *comp);
+void zcomp_destroy(struct zcomp *comp);
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp);
void zcomp_stream_put(struct zcomp *comp);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 6335e660d22a..1bf4a908a0bd 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -121,17 +121,6 @@ static unsigned long zram_get_element(struct zram *zram, u32 index)
return zram->table[index].element;
}
-static inline void zram_set_compressor(struct zram *zram, u32 index,
- struct zcomp *comp)
-{
- zram->table[index].compressor = comp;
-}
-
-static struct zcomp *zram_get_compressor(struct zram *zram, u32 index)
-{
- return zram->table[index].compressor;
-}
-
static size_t zram_get_obj_size(struct zram *zram, u32 index)
{
return zram->table[index].flags & (BIT(ZRAM_FLAG_SHIFT) - 1);
@@ -996,7 +985,6 @@ static ssize_t comp_algorithm_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct zram *zram = dev_to_zram(dev);
- struct zcomp *comp;
char compressor[ARRAY_SIZE(zram->compressor)];
size_t sz;
@@ -1006,12 +994,16 @@ static ssize_t comp_algorithm_store(struct device *dev,
if (sz > 0 && compressor[sz - 1] == '\n')
compressor[sz - 1] = 0x00;
- comp = zcomp_get_instance(&zram->backend_list, compressor);
- if (IS_ERR_OR_NULL(comp))
+ if (!zcomp_available_algorithm(compressor))
return -EINVAL;
down_write(&zram->init_lock);
- zram->comp = comp;
+ if (init_done(zram)) {
+ up_write(&zram->init_lock);
+ pr_info("Can't change algorithm for initialized device\n");
+ return -EBUSY;
+ }
+
strcpy(zram->compressor, compressor);
up_write(&zram->init_lock);
return len;
@@ -1206,7 +1198,6 @@ static void zram_free_page(struct zram *zram, size_t index)
return;
zs_free(zram->mem_pool, handle);
- zram->table[index].compressor = NULL;
atomic64_sub(zram_get_obj_size(zram, index),
&zram->stats.compr_data_size);
@@ -1262,13 +1253,12 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
kunmap_atomic(dst);
ret = 0;
} else {
- struct zcomp *comp = zram_get_compressor(zram, index);
- struct zcomp_strm *zstrm = zcomp_stream_get(comp);
+ struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
dst = kmap_atomic(page);
ret = zcomp_decompress(zstrm, src, size, dst);
kunmap_atomic(dst);
- zcomp_stream_put(comp);
+ zcomp_stream_put(zram->comp);
}
zs_unmap_object(zram->mem_pool, handle);
zram_slot_unlock(zram, index);
@@ -1322,7 +1312,6 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
unsigned int comp_len = 0;
void *src, *dst, *mem;
struct zcomp_strm *zstrm;
- struct zcomp *comp = NULL;
struct page *page = bvec->bv_page;
unsigned long element = 0;
enum zram_pageflags flags = 0;
@@ -1338,14 +1327,13 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
kunmap_atomic(mem);
compress_again:
- comp = zram->comp;
- zstrm = zcomp_stream_get(comp);
+ zstrm = zcomp_stream_get(zram->comp);
src = kmap_atomic(page);
ret = zcomp_compress(zstrm, src, &comp_len);
kunmap_atomic(src);
if (unlikely(ret)) {
- zcomp_stream_put(comp);
+ zcomp_stream_put(zram->comp);
pr_err("Compression failed! err=%d\n", ret);
zs_free(zram->mem_pool, handle);
return ret;
@@ -1373,7 +1361,7 @@ compress_again:
__GFP_HIGHMEM |
__GFP_MOVABLE);
if (!handle) {
- zcomp_stream_put(comp);
+ zcomp_stream_put(zram->comp);
atomic64_inc(&zram->stats.writestall);
handle = zs_malloc(zram->mem_pool, comp_len,
GFP_NOIO | __GFP_HIGHMEM |
@@ -1387,7 +1375,7 @@ compress_again:
update_used_max(zram, alloced_pages);
if (zram->limit_pages && alloced_pages > zram->limit_pages) {
- zcomp_stream_put(comp);
+ zcomp_stream_put(zram->comp);
zs_free(zram->mem_pool, handle);
return -ENOMEM;
}
@@ -1401,7 +1389,7 @@ compress_again:
if (comp_len == PAGE_SIZE)
kunmap_atomic(src);
- zcomp_stream_put(comp);
+ zcomp_stream_put(zram->comp);
zs_unmap_object(zram->mem_pool, handle);
atomic64_add(comp_len, &zram->stats.compr_data_size);
out:
@@ -1423,8 +1411,6 @@ out:
} else {
zram_set_handle(zram, index, handle);
zram_set_obj_size(zram, index, comp_len);
- if (comp_len < PAGE_SIZE)
- zram_set_compressor(zram, index, comp);
}
zram_slot_unlock(zram, index);
@@ -1689,6 +1675,7 @@ out:
static void zram_reset_device(struct zram *zram)
{
+ struct zcomp *comp;
u64 disksize;
down_write(&zram->init_lock);
@@ -1700,6 +1687,7 @@ static void zram_reset_device(struct zram *zram)
return;
}
+ comp = zram->comp;
disksize = zram->disksize;
zram->disksize = 0;
@@ -1710,8 +1698,7 @@ static void zram_reset_device(struct zram *zram)
/* I/O operation under all of CPU are done so let's free */
zram_meta_free(zram, disksize);
memset(&zram->stats, 0, sizeof(zram->stats));
- zram->comp = NULL;
- zcomp_reset(&zram->backend_list);
+ zcomp_destroy(comp);
reset_bdev(zram);
}
@@ -1740,8 +1727,10 @@ static ssize_t disksize_store(struct device *dev,
goto out_unlock;
}
- comp = zcomp_get_instance(&zram->backend_list, zram->compressor);
- if (IS_ERR_OR_NULL(comp)) {
+ comp = zcomp_create(zram->compressor);
+ if (IS_ERR(comp)) {
+ pr_err("Cannot initialise %s compressing backend\n",
+ zram->compressor);
err = PTR_ERR(comp);
goto out_free_meta;
}
@@ -1964,7 +1953,6 @@ static int zram_add(void)
device_add_disk(NULL, zram->disk, zram_disk_attr_groups);
strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
- INIT_LIST_HEAD(&zram->backend_list);
zram_debugfs_register(zram);
pr_info("Added device: %s\n", zram->disk->disk_name);
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 83b320fb5d6c..f2fd46daa760 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -63,7 +63,6 @@ struct zram_table_entry {
unsigned long element;
};
unsigned long flags;
- struct zcomp *compressor;
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
ktime_t ac_time;
#endif
@@ -113,7 +112,6 @@ struct zram {
* zram is claimed so open request will be failed
*/
bool claim; /* Protected by bdev->bd_mutex */
- struct list_head backend_list;
struct file *backing_dev;
#ifdef CONFIG_ZRAM_WRITEBACK
spinlock_t wb_limit_lock;