]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
zram: rework recompression loop
authorSergey Senozhatsky <senozhatsky@chromium.org>
Fri, 21 Feb 2025 22:25:40 +0000 (07:25 +0900)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 28 Feb 2025 01:00:24 +0000 (17:00 -0800)
This reworks recompression loop handling:

- set a rule that stream-put NULLs the stream pointer If the loop
  returns with a non-NULL stream then it's a successfull recompression,
  otherwise the stream should always be NULL.

- do not count the number of recompressions Mark object as
  incompressible as soon as the algorithm with the highest priority failed
  to compress that object.

- count compression errors as resource usage Even if compression has
  failed, we still need to bump num_recomp_pages counter.

Link: https://lkml.kernel.org/r/20250221222958.2225035-10-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Yosry Ahmed <yosry.ahmed@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
drivers/block/zram/zram_drv.c

index 92908495c90408166a600c50db6d623dfb852f6b..b96be8576cbc280aa597ddb01c65c411fd3a7733 100644 (file)
@@ -1892,9 +1892,8 @@ static int recompress_slot(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;
+       int ret = 0;
 
        handle_old = zram_get_handle(zram, index);
        if (!handle_old)
@@ -1937,7 +1936,6 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
                if (!zram->comps[prio])
                        continue;
 
-               num_recomps++;
                zstrm = zcomp_stream_get(zram->comps[prio]);
                src = kmap_local_page(page);
                ret = zcomp_compress(zram->comps[prio], zstrm,
@@ -1946,7 +1944,8 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
 
                if (ret) {
                        zcomp_stream_put(zstrm);
-                       return ret;
+                       zstrm = NULL;
+                       break;
                }
 
                class_index_new = zs_lookup_class_index(zram->mem_pool,
@@ -1956,6 +1955,7 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
                if (class_index_new >= class_index_old ||
                    (threshold && comp_len_new >= threshold)) {
                        zcomp_stream_put(zstrm);
+                       zstrm = NULL;
                        continue;
                }
 
@@ -1963,14 +1963,6 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
                break;
        }
 
-       /*
-        * We did not try to recompress, e.g. when we have only one
-        * secondary algorithm and the page is already recompressed
-        * using that algorithm
-        */
-       if (!zstrm)
-               return 0;
-
        /*
         * Decrement the limit (if set) on pages we can recompress, even
         * when current recompression was unsuccessful or did not compress
@@ -1980,38 +1972,31 @@ static int recompress_slot(struct zram *zram, u32 index, struct page *page,
        if (*num_recomp_pages)
                *num_recomp_pages -= 1;
 
-       if (class_index_new >= class_index_old) {
+       /* Compression error */
+       if (ret)
+               return ret;
+
+       if (!zstrm) {
                /*
                 * 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.
+                * in a way that would save memory.
                 *
-                * 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.
+                * Mark the object incompressible if the max-priority
+                * algorithm couldn't re-compress it.
                 */
-               if (num_recomps == zram->num_active_comps - 1)
-                       zram_set_flag(zram, index, ZRAM_INCOMPRESSIBLE);
+               if (prio < zram->num_active_comps)
+                       return 0;
+               zram_set_flag(zram, index, ZRAM_INCOMPRESSIBLE);
                return 0;
        }
 
-       /* Successful recompression but above threshold */
-       if (threshold && comp_len_new >= threshold)
-               return 0;
-
        /*
-        * No direct reclaim (slow path) for handle allocation and no
-        * re-compression attempt (unlike in zram_write_bvec()) since
-        * we already have stored that object in zsmalloc. If we cannot
-        * alloc memory for recompressed object then we bail out and
-        * simply keep the old (existing) object in zsmalloc.
+        * We are holding per-CPU stream mutex and entry lock so better
+        * avoid direct reclaim.  Allocation error is not fatal since
+        * we still have the old object in the mem_pool.
         */
        handle_new = zs_malloc(zram->mem_pool, comp_len_new,
-                              __GFP_KSWAPD_RECLAIM |
-                              __GFP_NOWARN |
-                              __GFP_HIGHMEM |
-                              __GFP_MOVABLE);
+                              GFP_NOWAIT | __GFP_HIGHMEM | __GFP_MOVABLE);
        if (IS_ERR_VALUE(handle_new)) {
                zcomp_stream_put(zstrm);
                return PTR_ERR((void *)handle_new);