Commit a55cf964 authored by Sergey Senozhatsky's avatar Sergey Senozhatsky Committed by Andrew Morton

zram: add algo parameter support to zram_recompress()

Recompression iterates through all the registered secondary compression
algorithms in order of their priorities so that we have higher chances of
finding the algorithm that compresses a particular page.  This, however,
may not always be best approach and sometimes we may want to limit
recompression to only one particular algorithm.  For instance, when a
higher priority algorithm uses too much power and device has a relatively
low battery level we may want to limit recompression to use only a lower
priority algorithm, which uses less power.

Introduce algo= parameter support to recompression sysfs knob so that
user-sapce can request recompression with particular algorithm only:

  echo "type=idle algo=zstd" > /sys/block/zramX/recompress

Link: https://lkml.kernel.org/r/20221109115047.2921851-11-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 4942cf6a
...@@ -1674,6 +1674,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page, ...@@ -1674,6 +1674,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
unsigned int comp_len_new; unsigned int comp_len_new;
unsigned int class_index_old; unsigned int class_index_old;
unsigned int class_index_new; unsigned int class_index_new;
u32 num_recomps = 0;
void *src, *dst; void *src, *dst;
int ret; int ret;
...@@ -1708,6 +1709,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page, ...@@ -1708,6 +1709,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
if (prio <= zram_get_priority(zram, index)) if (prio <= zram_get_priority(zram, index))
continue; continue;
num_recomps++;
zstrm = zcomp_stream_get(zram->comps[prio]); zstrm = zcomp_stream_get(zram->comps[prio]);
src = kmap_atomic(page); src = kmap_atomic(page);
ret = zcomp_compress(zstrm, src, &comp_len_new); ret = zcomp_compress(zstrm, src, &comp_len_new);
...@@ -1740,13 +1742,19 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page, ...@@ -1740,13 +1742,19 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
if (!zstrm) if (!zstrm)
return 0; return 0;
/*
* All secondary algorithms failed to re-compress the page in a way
* that would save memory, mark the object as incompressible so that
* we will not try to compress it again.
*/
if (class_index_new >= class_index_old) { if (class_index_new >= class_index_old) {
zram_set_flag(zram, index, ZRAM_INCOMPRESSIBLE); /*
* Secondary algorithms failed to re-compress the page
* in a way that would save memory, mark the object as
* incompressible so that we will not try to compress
* it again.
*
* We need to make sure that all secondary algorithms have
* failed, so we test if the number of recompressions matches
* the number of active secondary algorithms.
*/
if (num_recomps == zram->num_active_comps - 1)
zram_set_flag(zram, index, ZRAM_INCOMPRESSIBLE);
return 0; return 0;
} }
...@@ -1795,10 +1803,11 @@ static ssize_t recompress_store(struct device *dev, ...@@ -1795,10 +1803,11 @@ static ssize_t recompress_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
{ {
u32 prio = ZRAM_SECONDARY_COMP, prio_max = ZRAM_MAX_COMPS;
struct zram *zram = dev_to_zram(dev); struct zram *zram = dev_to_zram(dev);
u32 mode = 0, threshold = 0, prio = ZRAM_SECONDARY_COMP;
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
char *args, *param, *val; char *args, *param, *val, *algo = NULL;
u32 mode = 0, threshold = 0;
unsigned long index; unsigned long index;
struct page *page; struct page *page;
ssize_t ret; ssize_t ret;
...@@ -1830,6 +1839,11 @@ static ssize_t recompress_store(struct device *dev, ...@@ -1830,6 +1839,11 @@ static ssize_t recompress_store(struct device *dev,
return ret; return ret;
continue; continue;
} }
if (!strcmp(param, "algo")) {
algo = val;
continue;
}
} }
if (threshold >= PAGE_SIZE) if (threshold >= PAGE_SIZE)
...@@ -1841,6 +1855,26 @@ static ssize_t recompress_store(struct device *dev, ...@@ -1841,6 +1855,26 @@ static ssize_t recompress_store(struct device *dev,
goto release_init_lock; goto release_init_lock;
} }
if (algo) {
bool found = false;
for (; prio < ZRAM_MAX_COMPS; prio++) {
if (!zram->comp_algs[prio])
continue;
if (!strcmp(zram->comp_algs[prio], algo)) {
prio_max = min(prio + 1, ZRAM_MAX_COMPS);
found = true;
break;
}
}
if (!found) {
ret = -EINVAL;
goto release_init_lock;
}
}
page = alloc_page(GFP_KERNEL); page = alloc_page(GFP_KERNEL);
if (!page) { if (!page) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1871,7 +1905,7 @@ static ssize_t recompress_store(struct device *dev, ...@@ -1871,7 +1905,7 @@ static ssize_t recompress_store(struct device *dev,
goto next; goto next;
err = zram_recompress(zram, index, page, threshold, err = zram_recompress(zram, index, page, threshold,
prio, ZRAM_MAX_COMPS); prio, prio_max);
next: next:
zram_slot_unlock(zram, index); zram_slot_unlock(zram, index);
if (err) { if (err) {
...@@ -2107,6 +2141,7 @@ static void zram_destroy_comps(struct zram *zram) ...@@ -2107,6 +2141,7 @@ static void zram_destroy_comps(struct zram *zram)
if (!comp) if (!comp)
continue; continue;
zcomp_destroy(comp); zcomp_destroy(comp);
zram->num_active_comps--;
} }
} }
...@@ -2174,6 +2209,7 @@ static ssize_t disksize_store(struct device *dev, ...@@ -2174,6 +2209,7 @@ static ssize_t disksize_store(struct device *dev,
} }
zram->comps[prio] = comp; zram->comps[prio] = comp;
zram->num_active_comps++;
} }
zram->disksize = disksize; zram->disksize = disksize;
set_capacity_and_notify(zram->disk, zram->disksize >> SECTOR_SHIFT); set_capacity_and_notify(zram->disk, zram->disksize >> SECTOR_SHIFT);
......
...@@ -125,6 +125,7 @@ struct zram { ...@@ -125,6 +125,7 @@ struct zram {
*/ */
u64 disksize; /* bytes */ u64 disksize; /* bytes */
const char *comp_algs[ZRAM_MAX_COMPS]; const char *comp_algs[ZRAM_MAX_COMPS];
s8 num_active_comps;
/* /*
* zram is claimed so open request will be failed * zram is claimed so open request will be failed
*/ */
......
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