zram: introduce zcomp_ctx structure
authorSergey Senozhatsky <senozhatsky@chromium.org>
Mon, 2 Sep 2024 10:56:06 +0000 (19:56 +0900)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 9 Sep 2024 23:39:10 +0000 (16:39 -0700)
Keep run-time driver data (scratch buffers, etc.) in zcomp_ctx structure.
This structure is allocated per-CPU because drivers (backends) need to
modify its content during requests execution.

We will split mutable and immutable driver data, this is a preparation
path.

Link: https://lkml.kernel.org/r/20240902105656.1383858-19-senozhatsky@chromium.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nick Terrell <terrelln@fb.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
drivers/block/zram/backend_842.c
drivers/block/zram/backend_deflate.c
drivers/block/zram/backend_lz4.c
drivers/block/zram/backend_lz4hc.c
drivers/block/zram/backend_lzo.c
drivers/block/zram/backend_lzorle.c
drivers/block/zram/backend_zstd.c
drivers/block/zram/zcomp.c
drivers/block/zram/zcomp.h

index 1597dc4d4f1c5653d7395b9deafffccddc260163..2f12023222642a2b775ba5775416533e5f6df2b2 100644 (file)
@@ -7,51 +7,32 @@
 
 #include "backend_842.h"
 
-struct sw842_ctx {
-       void *mem;
-};
-
-static void destroy_842(void *ctx)
+static void destroy_842(struct zcomp_ctx *ctx)
 {
-       struct sw842_ctx *zctx = ctx;
-
-       kfree(zctx->mem);
-       kfree(zctx);
+       kfree(ctx->context);
 }
 
-static void *create_842(struct zcomp_params *params)
+static int create_842(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
-       struct sw842_ctx *ctx;
-
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return NULL;
-
-       ctx->mem = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
-       if (!ctx->mem)
-               goto error;
-
-       return ctx;
-
-error:
-       destroy_842(ctx);
-       return NULL;
+       ctx->context = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
+       if (!ctx->context)
+               return -ENOMEM;
+       return 0;
 }
 
-static int compress_842(void *ctx, struct zcomp_req *req)
+static int compress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct sw842_ctx *zctx = ctx;
        unsigned int dlen = req->dst_len;
        int ret;
 
        ret = sw842_compress(req->src, req->src_len, req->dst, &dlen,
-                            zctx->mem);
+                            ctx->context);
        if (ret == 0)
                req->dst_len = dlen;
        return ret;
 }
 
-static int decompress_842(void *ctx, struct zcomp_req *req)
+static int decompress_842(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        unsigned int dlen = req->dst_len;
 
index 117852d45aa4aa254afdde4cbe8230209f078934..eae4ee35c1dfb7d0b197d840f5c904a6fbb29b83 100644 (file)
@@ -17,9 +17,12 @@ struct deflate_ctx {
        s32 level;
 };
 
-static void deflate_destroy(void *ctx)
+static void deflate_destroy(struct zcomp_ctx *ctx)
 {
-       struct deflate_ctx *zctx = ctx;
+       struct deflate_ctx *zctx = ctx->context;
+
+       if (!zctx)
+               return;
 
        if (zctx->cctx.workspace) {
                zlib_deflateEnd(&zctx->cctx);
@@ -32,51 +35,52 @@ static void deflate_destroy(void *ctx)
        kfree(zctx);
 }
 
-static void *deflate_create(struct zcomp_params *params)
+static int deflate_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
-       struct deflate_ctx *ctx;
+       struct deflate_ctx *zctx;
        size_t sz;
        int ret;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return NULL;
+       zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+       if (!zctx)
+               return -ENOMEM;
 
+       ctx->context = zctx;
        if (params->level != ZCOMP_PARAM_NO_LEVEL)
-               ctx->level = params->level;
+               zctx->level = params->level;
        else
-               ctx->level = Z_DEFAULT_COMPRESSION;
+               zctx->level = Z_DEFAULT_COMPRESSION;
 
        sz = zlib_deflate_workspacesize(-DEFLATE_DEF_WINBITS, MAX_MEM_LEVEL);
-       ctx->cctx.workspace = vzalloc(sz);
-       if (!ctx->cctx.workspace)
+       zctx->cctx.workspace = vzalloc(sz);
+       if (!zctx->cctx.workspace)
                goto error;
 
-       ret = zlib_deflateInit2(&ctx->cctx, ctx->level, Z_DEFLATED,
+       ret = zlib_deflateInit2(&zctx->cctx, zctx->level, Z_DEFLATED,
                                -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL,
                                Z_DEFAULT_STRATEGY);
        if (ret != Z_OK)
                goto error;
 
        sz = zlib_inflate_workspacesize();
-       ctx->dctx.workspace = vzalloc(sz);
-       if (!ctx->dctx.workspace)
+       zctx->dctx.workspace = vzalloc(sz);
+       if (!zctx->dctx.workspace)
                goto error;
 
-       ret = zlib_inflateInit2(&ctx->dctx, -DEFLATE_DEF_WINBITS);
+       ret = zlib_inflateInit2(&zctx->dctx, -DEFLATE_DEF_WINBITS);
        if (ret != Z_OK)
                goto error;
 
-       return ctx;
+       return 0;
 
 error:
        deflate_destroy(ctx);
-       return NULL;
+       return -EINVAL;
 }
 
-static int deflate_compress(void *ctx, struct zcomp_req *req)
+static int deflate_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct deflate_ctx *zctx = ctx;
+       struct deflate_ctx *zctx = ctx->context;
        struct z_stream_s *deflate;
        int ret;
 
@@ -98,9 +102,9 @@ static int deflate_compress(void *ctx, struct zcomp_req *req)
        return 0;
 }
 
-static int deflate_decompress(void *ctx, struct zcomp_req *req)
+static int deflate_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct deflate_ctx *zctx = ctx;
+       struct deflate_ctx *zctx = ctx->context;
        struct z_stream_s *inflate;
        int ret;
 
index cc4ae409787033c80056dbcd6cf06849520a51fd..e2d951e627462559ae9218c515b6fe050af54b8a 100644 (file)
@@ -10,40 +10,44 @@ struct lz4_ctx {
        s32 level;
 };
 
-static void lz4_destroy(void *ctx)
+static void lz4_destroy(struct zcomp_ctx *ctx)
 {
-       struct lz4_ctx *zctx = ctx;
+       struct lz4_ctx *zctx = ctx->context;
+
+       if (!zctx)
+               return;
 
        vfree(zctx->mem);
        kfree(zctx);
 }
 
-static void *lz4_create(struct zcomp_params *params)
+static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
-       struct lz4_ctx *ctx;
+       struct lz4_ctx *zctx;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return NULL;
+       zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+       if (!zctx)
+               return -ENOMEM;
 
+       ctx->context = zctx;
        if (params->level != ZCOMP_PARAM_NO_LEVEL)
-               ctx->level = params->level;
+               zctx->level = params->level;
        else
-               ctx->level = LZ4_ACCELERATION_DEFAULT;
+               zctx->level = LZ4_ACCELERATION_DEFAULT;
 
-       ctx->mem = vmalloc(LZ4_MEM_COMPRESS);
-       if (!ctx->mem)
+       zctx->mem = vmalloc(LZ4_MEM_COMPRESS);
+       if (!zctx->mem)
                goto error;
 
-       return ctx;
+       return 0;
 error:
        lz4_destroy(ctx);
-       return NULL;
+       return -EINVAL;
 }
 
-static int lz4_compress(void *ctx, struct zcomp_req *req)
+static int lz4_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct lz4_ctx *zctx = ctx;
+       struct lz4_ctx *zctx = ctx->context;
        int ret;
 
        ret = LZ4_compress_fast(req->src, req->dst, req->src_len,
@@ -54,7 +58,7 @@ static int lz4_compress(void *ctx, struct zcomp_req *req)
        return 0;
 }
 
-static int lz4_decompress(void *ctx, struct zcomp_req *req)
+static int lz4_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        int ret;
 
index 610dadc09751657c1037f2121fd707d3ab3e6da5..6da71ec5fc05ee222de42dbd441bc111808cf4ba 100644 (file)
@@ -10,40 +10,44 @@ struct lz4hc_ctx {
        s32 level;
 };
 
-static void lz4hc_destroy(void *ctx)
+static void lz4hc_destroy(struct zcomp_ctx *ctx)
 {
-       struct lz4hc_ctx *zctx = ctx;
+       struct lz4hc_ctx *zctx = ctx->context;
+
+       if (!zctx)
+               return;
 
        vfree(zctx->mem);
        kfree(zctx);
 }
 
-static void *lz4hc_create(struct zcomp_params *params)
+static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
-       struct lz4hc_ctx *ctx;
+       struct lz4hc_ctx *zctx;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return NULL;
+       zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+       if (!zctx)
+               return -ENOMEM;
 
+       ctx->context = zctx;
        if (params->level != ZCOMP_PARAM_NO_LEVEL)
-               ctx->level = params->level;
+               zctx->level = params->level;
        else
-               ctx->level = LZ4HC_DEFAULT_CLEVEL;
+               zctx->level = LZ4HC_DEFAULT_CLEVEL;
 
-       ctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
-       if (!ctx->mem)
+       zctx->mem = vmalloc(LZ4HC_MEM_COMPRESS);
+       if (!zctx->mem)
                goto error;
 
-       return ctx;
+       return 0;
 error:
        lz4hc_destroy(ctx);
-       return NULL;
+       return -EINVAL;
 }
 
-static int lz4hc_compress(void *ctx, struct zcomp_req *req)
+static int lz4hc_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct lz4hc_ctx *zctx = ctx;
+       struct lz4hc_ctx *zctx = ctx->context;
        int ret;
 
        ret = LZ4_compress_HC(req->src, req->dst, req->src_len, req->dst_len,
@@ -54,7 +58,7 @@ static int lz4hc_compress(void *ctx, struct zcomp_req *req)
        return 0;
 }
 
-static int lz4hc_decompress(void *ctx, struct zcomp_req *req)
+static int lz4hc_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        int ret;
 
index 88f1aa5683f3fe1fe5a50e9dffd098b3c1b9c926..81fbad286092110dadeba6cb328a57f8ccef9ff8 100644 (file)
@@ -6,26 +6,29 @@
 
 #include "backend_lzo.h"
 
-static void *lzo_create(struct zcomp_params *params)
+static int lzo_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
-       return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+       ctx->context = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+       if (!ctx->context)
+               return -ENOMEM;
+       return 0;
 }
 
-static void lzo_destroy(void *ctx)
+static void lzo_destroy(struct zcomp_ctx *ctx)
 {
-       kfree(ctx);
+       kfree(ctx->context);
 }
 
-static int lzo_compress(void *ctx, struct zcomp_req *req)
+static int lzo_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        int ret;
 
        ret = lzo1x_1_compress(req->src, req->src_len, req->dst,
-                              &req->dst_len, ctx);
+                              &req->dst_len, ctx->context);
        return ret == LZO_E_OK ? 0 : ret;
 }
 
-static int lzo_decompress(void *ctx, struct zcomp_req *req)
+static int lzo_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        int ret;
 
index f05820929a74053ddda86aa7e8a1a3e7b4ac4adb..99c9da8f116e4e7ebe6f5bd4f056637e8b0c318c 100644 (file)
@@ -6,26 +6,29 @@
 
 #include "backend_lzorle.h"
 
-static void *lzorle_create(struct zcomp_params *params)
+static int lzorle_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
-       return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+       ctx->context = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+       if (!ctx->context)
+               return -ENOMEM;
+       return 0;
 }
 
-static void lzorle_destroy(void *ctx)
+static void lzorle_destroy(struct zcomp_ctx *ctx)
 {
-       kfree(ctx);
+       kfree(ctx->context);
 }
 
-static int lzorle_compress(void *ctx, struct zcomp_req *req)
+static int lzorle_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        int ret;
 
        ret = lzorle1x_1_compress(req->src, req->src_len, req->dst,
-                                 &req->dst_len, ctx);
+                                 &req->dst_len, ctx->context);
        return ret == LZO_E_OK ? 0 : ret;
 }
 
-static int lzorle_decompress(void *ctx, struct zcomp_req *req)
+static int lzorle_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
        int ret;
 
index 19eba65f44c9f56f1965d5da9caea27959ae4854..9f000dedf1adebdb2d9c617e45ac014b9bc10a5a 100644 (file)
@@ -16,60 +16,64 @@ struct zstd_ctx {
        s32 level;
 };
 
-static void zstd_destroy(void *ctx)
+static void zstd_destroy(struct zcomp_ctx *ctx)
 {
-       struct zstd_ctx *zctx = ctx;
+       struct zstd_ctx *zctx = ctx->context;
+
+       if (!zctx)
+               return;
 
        vfree(zctx->cctx_mem);
        vfree(zctx->dctx_mem);
        kfree(zctx);
 }
 
-static void *zstd_create(struct zcomp_params *params)
+static int zstd_create(struct zcomp_params *params, struct zcomp_ctx *ctx)
 {
+       struct zstd_ctx *zctx;
        zstd_parameters prm;
-       struct zstd_ctx *ctx;
        size_t sz;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return NULL;
+       zctx = kzalloc(sizeof(*zctx), GFP_KERNEL);
+       if (!zctx)
+               return -ENOMEM;
 
+       ctx->context = zctx;
        if (params->level != ZCOMP_PARAM_NO_LEVEL)
-               ctx->level = params->level;
+               zctx->level = params->level;
        else
-               ctx->level = zstd_default_clevel();
+               zctx->level = zstd_default_clevel();
 
-       prm = zstd_get_params(ctx->level, PAGE_SIZE);
-       ctx->cprm = zstd_get_params(ctx->level, PAGE_SIZE);
+       prm = zstd_get_params(zctx->level, PAGE_SIZE);
+       zctx->cprm = zstd_get_params(zctx->level, PAGE_SIZE);
        sz = zstd_cctx_workspace_bound(&prm.cParams);
-       ctx->cctx_mem = vzalloc(sz);
-       if (!ctx->cctx_mem)
+       zctx->cctx_mem = vzalloc(sz);
+       if (!zctx->cctx_mem)
                goto error;
 
-       ctx->cctx = zstd_init_cctx(ctx->cctx_mem, sz);
-       if (!ctx->cctx)
+       zctx->cctx = zstd_init_cctx(zctx->cctx_mem, sz);
+       if (!zctx->cctx)
                goto error;
 
        sz = zstd_dctx_workspace_bound();
-       ctx->dctx_mem = vzalloc(sz);
-       if (!ctx->dctx_mem)
+       zctx->dctx_mem = vzalloc(sz);
+       if (!zctx->dctx_mem)
                goto error;
 
-       ctx->dctx = zstd_init_dctx(ctx->dctx_mem, sz);
-       if (!ctx->dctx)
+       zctx->dctx = zstd_init_dctx(zctx->dctx_mem, sz);
+       if (!zctx->dctx)
                goto error;
 
-       return ctx;
+       return 0;
 
 error:
        zstd_destroy(ctx);
-       return NULL;
+       return -EINVAL;
 }
 
-static int zstd_compress(void *ctx, struct zcomp_req *req)
+static int zstd_compress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct zstd_ctx *zctx = ctx;
+       struct zstd_ctx *zctx = ctx->context;
        size_t ret;
 
        ret = zstd_compress_cctx(zctx->cctx, req->dst, req->dst_len,
@@ -80,9 +84,9 @@ static int zstd_compress(void *ctx, struct zcomp_req *req)
        return 0;
 }
 
-static int zstd_decompress(void *ctx, struct zcomp_req *req)
+static int zstd_decompress(struct zcomp_ctx *ctx, struct zcomp_req *req)
 {
-       struct zstd_ctx *zctx = ctx;
+       struct zstd_ctx *zctx = ctx->context;
        size_t ret;
 
        ret = zstd_decompress_dctx(zctx->dctx, req->dst, req->dst_len,
index 20ad7b6fe62f39de67b41c0118504610ac0458d2..96f07287e5712628ce0e7d4bffc1e366e76498e6 100644 (file)
@@ -45,23 +45,25 @@ static const struct zcomp_ops *backends[] = {
 
 static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
 {
-       if (zstrm->ctx)
-               comp->ops->destroy_ctx(zstrm->ctx);
+       comp->ops->destroy_ctx(&zstrm->ctx);
        vfree(zstrm->buffer);
-       zstrm->ctx = NULL;
        zstrm->buffer = NULL;
 }
 
 static int zcomp_strm_init(struct zcomp *comp, struct zcomp_strm *zstrm)
 {
-       zstrm->ctx = comp->ops->create_ctx(comp->params);
+       int ret;
+
+       ret = comp->ops->create_ctx(comp->params, &zstrm->ctx);
+       if (ret)
+               return ret;
 
        /*
         * allocate 2 pages. 1 for compressed data, plus 1 extra for the
         * case when compressed size is larger than the original one
         */
        zstrm->buffer = vzalloc(2 * PAGE_SIZE);
-       if (!zstrm->ctx || !zstrm->buffer) {
+       if (!zstrm->buffer) {
                zcomp_strm_free(comp, zstrm);
                return -ENOMEM;
        }
@@ -127,7 +129,7 @@ int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
        };
        int ret;
 
-       ret = comp->ops->compress(zstrm->ctx, &req);
+       ret = comp->ops->compress(&zstrm->ctx, &req);
        if (!ret)
                *dst_len = req.dst_len;
        return ret;
@@ -143,7 +145,7 @@ int zcomp_decompress(struct zcomp *comp, struct zcomp_strm *zstrm,
                .dst_len = PAGE_SIZE,
        };
 
-       return comp->ops->decompress(zstrm->ctx, &req);
+       return comp->ops->decompress(&zstrm->ctx, &req);
 }
 
 int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
index bbc48094f826213641aeff8646aba7057ef3ae93..1d8920c2d449ea6c0b74944d50cd785b0250f38e 100644 (file)
@@ -13,12 +13,20 @@ struct zcomp_params {
        s32 level;
 };
 
+/*
+ * Run-time driver context - scratch buffers, etc. It is modified during
+ * request execution (compression/decompression), cannot be shared, so
+ * it's in per-CPU area.
+ */
+struct zcomp_ctx {
+       void *context;
+};
+
 struct zcomp_strm {
-       /* The members ->buffer and ->tfm are protected by ->lock. */
        local_lock_t lock;
-       /* compression/decompression buffer */
+       /* compression buffer */
        void *buffer;
-       void *ctx;
+       struct zcomp_ctx ctx;
 };
 
 struct zcomp_req {
@@ -30,11 +38,12 @@ struct zcomp_req {
 };
 
 struct zcomp_ops {
-       int (*compress)(void *ctx, struct zcomp_req *req);
-       int (*decompress)(void *ctx, struct zcomp_req *req);
+       int (*compress)(struct zcomp_ctx *ctx, struct zcomp_req *req);
+       int (*decompress)(struct zcomp_ctx *ctx, struct zcomp_req *req);
 
-       void *(*create_ctx)(struct zcomp_params *params);
-       void (*destroy_ctx)(void *ctx);
+       int (*create_ctx)(struct zcomp_params *params,
+                         struct zcomp_ctx *ctx);
+       void (*destroy_ctx)(struct zcomp_ctx *ctx);
 
        const char *name;
 };