Commit 001d9273 authored by Sergey Senozhatsky's avatar Sergey Senozhatsky Committed by Andrew Morton

zram: add recompression algorithm sysfs knob

Introduce recomp_algorithm sysfs knob that controls secondary algorithm
selection used for recompression.

We will support up to 3 secondary compression algorithms which are sorted
in order of their priority.  To select an algorithm user has to provide
its name and priority:

  echo "algo=zstd priority=1" > /sys/block/zramX/recomp_algorithm
  echo "algo=deflate priority=2" > /sys/block/zramX/recomp_algorithm

During recompression zram iterates through the list of registered
secondary algorithms in order of their priorities.

We also have a short version for cases when there is only
one secondary compression algorithm:

  echo "algo=zstd" > /sys/block/zramX/recomp_algorithm

This will register zstd as the secondary algorithm with priority 1.

Link: https://lkml.kernel.org/r/20221109115047.2921851-3-senozhatsky@chromium.orgSigned-off-by: default avatarSergey Senozhatsky <senozhatsky@chromium.org>
Acked-by: default avatarMinchan Kim <minchan@kernel.org>
Cc: Alexey Romanov <avromanov@sberdevices.ru>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Nitin Gupta <ngupta@vflare.org>
Cc: Suleiman Souhlal <suleiman@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 7ac07a26
...@@ -997,31 +997,28 @@ static ssize_t max_comp_streams_store(struct device *dev, ...@@ -997,31 +997,28 @@ static ssize_t max_comp_streams_store(struct device *dev,
return len; return len;
} }
static ssize_t comp_algorithm_show(struct device *dev, static void comp_algorithm_set(struct zram *zram, u32 prio, const char *alg)
struct device_attribute *attr, char *buf)
{ {
size_t sz; /* Do not free statically defined compression algorithms */
struct zram *zram = dev_to_zram(dev); if (zram->comp_algs[prio] != default_compressor)
kfree(zram->comp_algs[prio]);
zram->comp_algs[prio] = alg;
}
static ssize_t __comp_algorithm_show(struct zram *zram, u32 prio, char *buf)
{
ssize_t sz;
down_read(&zram->init_lock); down_read(&zram->init_lock);
sz = zcomp_available_show(zram->comp_algs[ZRAM_PRIMARY_COMP], buf); sz = zcomp_available_show(zram->comp_algs[prio], buf);
up_read(&zram->init_lock); up_read(&zram->init_lock);
return sz; return sz;
} }
static void comp_algorithm_set(struct zram *zram, u32 prio, const char *alg) static int __comp_algorithm_store(struct zram *zram, u32 prio, const char *buf)
{ {
/* Do not kfree() algs that we didn't allocate, IOW the default ones */
if (zram->comp_algs[prio] != default_compressor)
kfree(zram->comp_algs[prio]);
zram->comp_algs[prio] = alg;
}
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);
char *compressor; char *compressor;
size_t sz; size_t sz;
...@@ -1050,11 +1047,94 @@ static ssize_t comp_algorithm_store(struct device *dev, ...@@ -1050,11 +1047,94 @@ static ssize_t comp_algorithm_store(struct device *dev,
return -EBUSY; return -EBUSY;
} }
comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, compressor); comp_algorithm_set(zram, prio, compressor);
up_write(&zram->init_lock); up_write(&zram->init_lock);
return len; return 0;
}
static ssize_t comp_algorithm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct zram *zram = dev_to_zram(dev);
return __comp_algorithm_show(zram, ZRAM_PRIMARY_COMP, buf);
}
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);
int ret;
ret = __comp_algorithm_store(zram, ZRAM_PRIMARY_COMP, buf);
return ret ? ret : len;
} }
#ifdef CONFIG_ZRAM_MULTI_COMP
static ssize_t recomp_algorithm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct zram *zram = dev_to_zram(dev);
ssize_t sz = 0;
u32 prio;
for (prio = ZRAM_SECONDARY_COMP; prio < ZRAM_MAX_COMPS; prio++) {
if (!zram->comp_algs[prio])
continue;
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2, "#%d: ", prio);
sz += __comp_algorithm_show(zram, prio, buf + sz);
}
return sz;
}
static ssize_t recomp_algorithm_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct zram *zram = dev_to_zram(dev);
int prio = ZRAM_SECONDARY_COMP;
char *args, *param, *val;
char *alg = NULL;
int ret;
args = skip_spaces(buf);
while (*args) {
args = next_arg(args, &param, &val);
if (!*val)
return -EINVAL;
if (!strcmp(param, "algo")) {
alg = val;
continue;
}
if (!strcmp(param, "priority")) {
ret = kstrtoint(val, 10, &prio);
if (ret)
return ret;
continue;
}
}
if (!alg)
return -EINVAL;
if (prio < ZRAM_SECONDARY_COMP || prio >= ZRAM_MAX_COMPS)
return -EINVAL;
ret = __comp_algorithm_store(zram, prio, alg);
return ret ? ret : len;
}
#endif
static ssize_t compact_store(struct device *dev, static ssize_t compact_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len) struct device_attribute *attr, const char *buf, size_t len)
{ {
...@@ -1895,6 +1975,9 @@ static DEVICE_ATTR_WO(writeback); ...@@ -1895,6 +1975,9 @@ static DEVICE_ATTR_WO(writeback);
static DEVICE_ATTR_RW(writeback_limit); static DEVICE_ATTR_RW(writeback_limit);
static DEVICE_ATTR_RW(writeback_limit_enable); static DEVICE_ATTR_RW(writeback_limit_enable);
#endif #endif
#ifdef CONFIG_ZRAM_MULTI_COMP
static DEVICE_ATTR_RW(recomp_algorithm);
#endif
static struct attribute *zram_disk_attrs[] = { static struct attribute *zram_disk_attrs[] = {
&dev_attr_disksize.attr, &dev_attr_disksize.attr,
...@@ -1918,6 +2001,9 @@ static struct attribute *zram_disk_attrs[] = { ...@@ -1918,6 +2001,9 @@ static struct attribute *zram_disk_attrs[] = {
&dev_attr_bd_stat.attr, &dev_attr_bd_stat.attr,
#endif #endif
&dev_attr_debug_stat.attr, &dev_attr_debug_stat.attr,
#ifdef CONFIG_ZRAM_MULTI_COMP
&dev_attr_recomp_algorithm.attr,
#endif
NULL, NULL,
}; };
...@@ -1997,7 +2083,7 @@ static int zram_add(void) ...@@ -1997,7 +2083,7 @@ static int zram_add(void)
if (ret) if (ret)
goto out_cleanup_disk; goto out_cleanup_disk;
zram->comp_algs[ZRAM_PRIMARY_COMP] = default_compressor; comp_algorithm_set(zram, ZRAM_PRIMARY_COMP, default_compressor);
zram_debugfs_register(zram); zram_debugfs_register(zram);
pr_info("Added device: %s\n", zram->disk->disk_name); pr_info("Added device: %s\n", zram->disk->disk_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment