From: Sergey Senozhatsky senozhatsky@chromium.org
mainline inclusion from mainline-v6.2-rc1 commit a55cf9648d3de486ccf0eca980a02f0faff8ec45 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7TWVA CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
-------------------------------------------
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.org Signed-off-by: Sergey Senozhatsky senozhatsky@chromium.org Acked-by: Minchan 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: Andrew Morton akpm@linux-foundation.org
Conflicts: drivers/block/zram/zram_drv.c
Signed-off-by: Jinjiang Tu tujinjiang@huawei.com --- drivers/block/zram/zram_drv.c | 54 +++++++++++++++++++++++++++++------ drivers/block/zram/zram_drv.h | 1 + 2 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 07fbba6c35f2..b1335250674a 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1649,6 +1649,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page, unsigned int comp_len_new; unsigned int class_index_old; unsigned int class_index_new; + u32 num_recomps = 0; void *src, *dst; int ret;
@@ -1683,6 +1684,7 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page, if (prio <= zram_get_priority(zram, index)) continue;
+ num_recomps++; zstrm = zcomp_stream_get(zram->comps[prio]); src = kmap_atomic(page); ret = zcomp_compress(zstrm, src, &comp_len_new); @@ -1715,13 +1717,19 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page, if (!zstrm) 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) { - 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; }
@@ -1770,10 +1778,11 @@ static ssize_t recompress_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { + u32 prio = ZRAM_SECONDARY_COMP, prio_max = ZRAM_MAX_COMPS; struct zram *zram = dev_to_zram(dev); - u32 mode = 0, threshold = 0, prio = ZRAM_SECONDARY_COMP; 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; struct page *page; ssize_t ret; @@ -1805,6 +1814,11 @@ static ssize_t recompress_store(struct device *dev, return ret; continue; } + + if (!strcmp(param, "algo")) { + algo = val; + continue; + } }
if (threshold >= PAGE_SIZE) @@ -1816,6 +1830,26 @@ static ssize_t recompress_store(struct device *dev, 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); if (!page) { ret = -ENOMEM; @@ -1846,7 +1880,7 @@ static ssize_t recompress_store(struct device *dev, goto next;
err = zram_recompress(zram, index, page, threshold, - prio, ZRAM_MAX_COMPS); + prio, prio_max); next: zram_slot_unlock(zram, index); if (err) { @@ -2085,6 +2119,7 @@ static void zram_destroy_comps(struct zram *zram) if (!comp) continue; zcomp_destroy(comp); + zram->num_active_comps--; } }
@@ -2156,6 +2191,7 @@ static ssize_t disksize_store(struct device *dev, }
zram->comps[prio] = comp; + zram->num_active_comps++; } zram->disksize = disksize; set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index c56e216f928d..b5b94e6b6ec8 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -125,6 +125,7 @@ struct zram { */ u64 disksize; /* bytes */ const char *comp_algs[ZRAM_MAX_COMPS]; + s8 num_active_comps; /* * zram is claimed so open request will be failed */