From: Sergey Senozhatsky <senozhatsky@chromium.org>
To: Andrew Morton <akpm@linux-foundation.org>,
Minchan Kim <minchan@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-block@vger.kernel.org,
linux-mm@kvack.org, Brian Geffon <bgeffon@google.com>,
Sergey Senozhatsky <senozhatsky@chromium.org>
Subject: [PATCH 5/5] zram: remove chained recompression
Date: Fri, 27 Feb 2026 17:21:11 +0900 [thread overview]
Message-ID: <cf100b13afb62641d7f3bc10fd77068833f56af0.1772180459.git.senozhatsky@chromium.org> (raw)
In-Reply-To: <8a5d53d19a8dbd51d7d81d153676895163e0735e.1772180459.git.senozhatsky@chromium.org>
Chained recompression has unpredictable behavior and is not useful
in practice.
First, systems usually configure just one alternative recompression
algorithm, which has slower compression/decompression but better
compression ratio. A single alternative algorithm doesn't need
chaining.
Second, even with multiple recompression algorithms, chained
recompression is suboptimal. If a lower priority algorithm
succeeds, the page is never attempted with a higher priority
algorithm, leading to worse memory savings. If a lower priority
algorithm fails, the page is still attempted with a higher priority
algorithm, wasting resources on the failed lower priority attempt.
In either case, the system would be better off targeting a specific
priority directly.
Chained recompression also significantly complicates the code.
Remove it.
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
Documentation/admin-guide/blockdev/zram.rst | 9 ---
drivers/block/zram/zram_drv.c | 83 ++++++---------------
2 files changed, 24 insertions(+), 68 deletions(-)
diff --git a/Documentation/admin-guide/blockdev/zram.rst b/Documentation/admin-guide/blockdev/zram.rst
index 967b58c3aad2..60b07a7e30cd 100644
--- a/Documentation/admin-guide/blockdev/zram.rst
+++ b/Documentation/admin-guide/blockdev/zram.rst
@@ -533,15 +533,6 @@ unexpected results when the same algorithm is configured with different
priorities (e.g. different parameters). `priority` is the only way to
guarantee that the expected algorithm will be used.
-During re-compression for every page, that matches re-compression criteria,
-ZRAM iterates the list of registered alternative compression algorithms in
-order of their priorities. ZRAM stops either when re-compression was
-successful (re-compressed object is smaller in size than the original one)
-and matches re-compression criteria (e.g. size threshold) or when there are
-no secondary algorithms left to try. If none of the secondary algorithms can
-successfully re-compressed the page such a page is marked as incompressible,
-so ZRAM will not attempt to re-compress it in the future.
-
memory tracking
===============
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 118b0b277e37..ff1931e700c3 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2331,7 +2331,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
#define RECOMPRESS_IDLE (1 << 0)
#define RECOMPRESS_HUGE (1 << 1)
-static int scan_slots_for_recompress(struct zram *zram, u32 mode, u32 prio_max,
+static int scan_slots_for_recompress(struct zram *zram, u32 mode, u32 prio,
struct zram_pp_ctl *ctl)
{
unsigned long nr_pages = zram->disksize >> PAGE_SHIFT;
@@ -2357,8 +2357,8 @@ static int scan_slots_for_recompress(struct zram *zram, u32 mode, u32 prio_max,
test_slot_flag(zram, index, ZRAM_INCOMPRESSIBLE))
goto next;
- /* Already compressed with same of higher priority */
- if (get_slot_comp_priority(zram, index) + 1 >= prio_max)
+ /* Already compressed with same or higher priority */
+ if (get_slot_comp_priority(zram, index) >= prio)
goto next;
ok = place_pp_slot(zram, ctl, index);
@@ -2391,8 +2391,7 @@ static bool highest_priority_algorithm(struct zram *zram, u32 prio)
* Corresponding ZRAM slot should be locked.
*/
static int recompress_slot(struct zram *zram, u32 index, struct page *page,
- u64 *num_recomp_pages, u32 threshold, u32 prio,
- u32 prio_max)
+ u64 *num_recomp_pages, u32 threshold, u32 prio)
{
struct zcomp_strm *zstrm = NULL;
unsigned long handle_old;
@@ -2404,6 +2403,9 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
void *src;
int ret = 0;
+ if (!zram->comps[prio])
+ return -EINVAL;
+
handle_old = get_slot_handle(zram, index);
if (!handle_old)
return -EINVAL;
@@ -2426,51 +2428,10 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
*/
clear_slot_flag(zram, index, ZRAM_IDLE);
- class_index_old = zs_lookup_class_index(zram->mem_pool, comp_len_old);
-
- prio = max(prio, get_slot_comp_priority(zram, index) + 1);
- /*
- * Recompression slots scan should not select slots that are
- * already compressed with a higher priority algorithm, but
- * just in case
- */
- if (prio >= prio_max)
- return 0;
-
- /*
- * Iterate the secondary comp algorithms list (in order of priority)
- * and try to recompress the page.
- */
- for (; prio < prio_max; prio++) {
- if (!zram->comps[prio])
- continue;
-
- zstrm = zcomp_stream_get(zram->comps[prio]);
- src = kmap_local_page(page);
- ret = zcomp_compress(zram->comps[prio], zstrm,
- src, &comp_len_new);
- kunmap_local(src);
-
- if (ret) {
- zcomp_stream_put(zstrm);
- zstrm = NULL;
- break;
- }
-
- class_index_new = zs_lookup_class_index(zram->mem_pool,
- comp_len_new);
-
- /* Continue until we make progress */
- if (class_index_new >= class_index_old ||
- (threshold && comp_len_new >= threshold)) {
- zcomp_stream_put(zstrm);
- zstrm = NULL;
- continue;
- }
-
- /* Recompression was successful so break out */
- break;
- }
+ zstrm = zcomp_stream_get(zram->comps[prio]);
+ src = kmap_local_page(page);
+ ret = zcomp_compress(zram->comps[prio], zstrm, src, &comp_len_new);
+ kunmap_local(src);
/*
* Decrement the limit (if set) on pages we can recompress, even
@@ -2481,11 +2442,18 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
if (*num_recomp_pages)
*num_recomp_pages -= 1;
- /* Compression error */
- if (ret)
+ if (ret) {
+ zcomp_stream_put(zstrm);
return ret;
+ }
+
+ class_index_old = zs_lookup_class_index(zram->mem_pool, comp_len_old);
+ class_index_new = zs_lookup_class_index(zram->mem_pool, comp_len_new);
+
+ if (class_index_new >= class_index_old ||
+ (threshold && comp_len_new >= threshold)) {
+ zcomp_stream_put(zstrm);
- if (!zstrm) {
/*
* Secondary algorithms failed to re-compress the page
* in a way that would save memory.
@@ -2535,11 +2503,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);
char *args, *param, *val, *algo = NULL;
u64 num_recomp_pages = ULLONG_MAX;
struct zram_pp_ctl *ctl = NULL;
+ u32 prio = ZRAM_SECONDARY_COMP;
struct zram_pp_slot *pps;
u32 mode = 0, threshold = 0;
struct page *page = NULL;
@@ -2604,7 +2572,6 @@ static ssize_t recompress_store(struct device *dev,
* "algorithm" name lookup is ambiguous.
*/
algo = NULL;
- prio_max = min(prio + 1, ZRAM_MAX_COMPS);
continue;
}
}
@@ -2624,7 +2591,6 @@ static ssize_t recompress_store(struct device *dev,
continue;
if (!strcmp(zram->comp_algs[prio], algo)) {
- prio_max = min(prio + 1, ZRAM_MAX_COMPS);
found = true;
break;
}
@@ -2653,7 +2619,7 @@ static ssize_t recompress_store(struct device *dev,
goto out;
}
- scan_slots_for_recompress(zram, mode, prio_max, ctl);
+ scan_slots_for_recompress(zram, mode, prio, ctl);
ret = len;
while ((pps = select_pp_slot(ctl))) {
@@ -2667,8 +2633,7 @@ static ssize_t recompress_store(struct device *dev,
goto next;
err = recompress_slot(zram, pps->index, page,
- &num_recomp_pages, threshold,
- prio, prio_max);
+ &num_recomp_pages, threshold, prio);
next:
slot_unlock(zram, pps->index);
release_pp_slot(zram, pps);
--
2.53.0.473.g4a7958ca14-goog
prev parent reply other threads:[~2026-02-27 8:21 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-27 8:21 [PATCH 1/5] zram: do not autocorrect bad recompression parameters Sergey Senozhatsky
2026-02-27 8:21 ` [PATCH 2/5] zram: drop ->num_active_comps Sergey Senozhatsky
2026-02-27 8:21 ` [PATCH 3/5] zram: recompression priority param should override algo Sergey Senozhatsky
2026-02-27 8:21 ` [PATCH 4/5] zram: update recompression documentation Sergey Senozhatsky
2026-02-27 8:21 ` Sergey Senozhatsky [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cf100b13afb62641d7f3bc10fd77068833f56af0.1772180459.git.senozhatsky@chromium.org \
--to=senozhatsky@chromium.org \
--cc=akpm@linux-foundation.org \
--cc=bgeffon@google.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=minchan@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox