1 #include <linux/kernel.h> 2 #include <linux/lz4.h> 3 #include <linux/slab.h> 4 #include <linux/vmalloc.h> 5 6 #include "backend_lz4.h" 7 8 struct lz4_ctx { 9 void *mem; 10 11 LZ4_streamDecode_t *dstrm; 12 LZ4_stream_t *cstrm; 13 }; 14 15 static void lz4_release_params(struct zcomp_params *params) 16 { 17 } 18 19 static int lz4_setup_params(struct zcomp_params *params) 20 { 21 if (params->level == ZCOMP_PARAM_NO_LEVEL) 22 params->level = LZ4_ACCELERATION_DEFAULT; 23 24 return 0; 25 } 26 27 static void lz4_destroy(struct zcomp_ctx *ctx) 28 { 29 struct lz4_ctx *zctx = ctx->context; 30 31 if (!zctx) 32 return; 33 34 vfree(zctx->mem); 35 kfree(zctx->dstrm); 36 kfree(zctx->cstrm); 37 kfree(zctx); 38 } 39 40 static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx) 41 { 42 struct lz4_ctx *zctx; 43 44 zctx = kzalloc(sizeof(*zctx), GFP_KERNEL); 45 if (!zctx) 46 return -ENOMEM; 47 48 ctx->context = zctx; 49 if (params->dict_sz == 0) { 50 zctx->mem = vmalloc(LZ4_MEM_COMPRESS); 51 if (!zctx->mem) 52 goto error; 53 } else { 54 zctx->dstrm = kzalloc(sizeof(*zctx->dstrm), GFP_KERNEL); 55 if (!zctx->dstrm) 56 goto error; 57 58 zctx->cstrm = kzalloc(sizeof(*zctx->cstrm), GFP_KERNEL); 59 if (!zctx->cstrm) 60 goto error; 61 } 62 63 return 0; 64 65 error: 66 lz4_destroy(ctx); 67 return -ENOMEM; 68 } 69 70 static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx, 71 struct zcomp_req *req) 72 { 73 struct lz4_ctx *zctx = ctx->context; 74 int ret; 75 76 if (!zctx->cstrm) { 77 ret = LZ4_compress_fast(req->src, req->dst, req->src_len, 78 req->dst_len, params->level, 79 zctx->mem); 80 } else { 81 /* Cstrm needs to be reset */ 82 ret = LZ4_loadDict(zctx->cstrm, params->dict, params->dict_sz); 83 if (ret != params->dict_sz) 84 return -EINVAL; 85 ret = LZ4_compress_fast_continue(zctx->cstrm, req->src, 86 req->dst, req->src_len, 87 req->dst_len, params->level); 88 } 89 if (!ret) 90 return -EINVAL; 91 req->dst_len = ret; 92 return 0; 93 } 94 95 static int lz4_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx, 96 struct zcomp_req *req) 97 { 98 struct lz4_ctx *zctx = ctx->context; 99 int ret; 100 101 if (!zctx->dstrm) { 102 ret = LZ4_decompress_safe(req->src, req->dst, req->src_len, 103 req->dst_len); 104 } else { 105 /* Dstrm needs to be reset */ 106 ret = LZ4_setStreamDecode(zctx->dstrm, params->dict, 107 params->dict_sz); 108 if (!ret) 109 return -EINVAL; 110 ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src, 111 req->dst, req->src_len, 112 req->dst_len); 113 } 114 if (ret < 0) 115 return -EINVAL; 116 return 0; 117 } 118 119 const struct zcomp_ops backend_lz4 = { 120 .compress = lz4_compress, 121 .decompress = lz4_decompress, 122 .create_ctx = lz4_create, 123 .destroy_ctx = lz4_destroy, 124 .setup_params = lz4_setup_params, 125 .release_params = lz4_release_params, 126 .name = "lz4", 127 }; 128