1 #include <linux/kernel.h> 2 #include <linux/lz4.h> 3 #include <linux/slab.h> 4 #include <linux/vmalloc.h> 5 6 #include "backend_lz4hc.h" 7 8 struct lz4hc_ctx { 9 void *mem; 10 11 LZ4_streamDecode_t *dstrm; 12 LZ4_streamHC_t *cstrm; 13 }; 14 15 static void lz4hc_release_params(struct zcomp_params *params) 16 { 17 } 18 19 static int lz4hc_setup_params(struct zcomp_params *params) 20 { 21 if (params->level == ZCOMP_PARAM_NO_LEVEL) 22 params->level = LZ4HC_DEFAULT_CLEVEL; 23 24 return 0; 25 } 26 27 static void lz4hc_destroy(struct zcomp_ctx *ctx) 28 { 29 struct lz4hc_ctx *zctx = ctx->context; 30 31 if (!zctx) 32 return; 33 34 kfree(zctx->dstrm); 35 kfree(zctx->cstrm); 36 vfree(zctx->mem); 37 kfree(zctx); 38 } 39 40 static int lz4hc_create(struct zcomp_params *params, struct zcomp_ctx *ctx) 41 { 42 struct lz4hc_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(LZ4HC_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 lz4hc_destroy(ctx); 67 return -EINVAL; 68 } 69 70 static int lz4hc_compress(struct zcomp_params *params, struct zcomp_ctx *ctx, 71 struct zcomp_req *req) 72 { 73 struct lz4hc_ctx *zctx = ctx->context; 74 int ret; 75 76 if (!zctx->cstrm) { 77 ret = LZ4_compress_HC(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 LZ4_resetStreamHC(zctx->cstrm, params->level); 83 ret = LZ4_loadDictHC(zctx->cstrm, params->dict, 84 params->dict_sz); 85 if (ret != params->dict_sz) 86 return -EINVAL; 87 ret = LZ4_compress_HC_continue(zctx->cstrm, req->src, req->dst, 88 req->src_len, req->dst_len); 89 } 90 if (!ret) 91 return -EINVAL; 92 req->dst_len = ret; 93 return 0; 94 } 95 96 static int lz4hc_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx, 97 struct zcomp_req *req) 98 { 99 struct lz4hc_ctx *zctx = ctx->context; 100 int ret; 101 102 if (!zctx->dstrm) { 103 ret = LZ4_decompress_safe(req->src, req->dst, req->src_len, 104 req->dst_len); 105 } else { 106 /* Dstrm needs to be reset */ 107 ret = LZ4_setStreamDecode(zctx->dstrm, params->dict, 108 params->dict_sz); 109 if (!ret) 110 return -EINVAL; 111 ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src, 112 req->dst, req->src_len, 113 req->dst_len); 114 } 115 if (ret < 0) 116 return -EINVAL; 117 return 0; 118 } 119 120 const struct zcomp_ops backend_lz4hc = { 121 .compress = lz4hc_compress, 122 .decompress = lz4hc_decompress, 123 .create_ctx = lz4hc_create, 124 .destroy_ctx = lz4hc_destroy, 125 .setup_params = lz4hc_setup_params, 126 .release_params = lz4hc_release_params, 127 .name = "lz4hc", 128 }; 129