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)
{
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);
}
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;
-}
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);
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;
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;
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);
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);
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;
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;
__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 |
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;
}
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:
} 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);
static void zram_reset_device(struct zram *zram)
{
+ struct zcomp *comp;
u64 disksize;
down_write(&zram->init_lock);
return;
}
+ comp = zram->comp;
disksize = zram->disksize;
zram->disksize = 0;
/* 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);
}
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;
}
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);