122d651c3SSergey Senozhatsky #include <linux/kernel.h> 222d651c3SSergey Senozhatsky #include <linux/lz4.h> 322d651c3SSergey Senozhatsky #include <linux/slab.h> 422d651c3SSergey Senozhatsky #include <linux/vmalloc.h> 522d651c3SSergey Senozhatsky 622d651c3SSergey Senozhatsky #include "backend_lz4.h" 722d651c3SSergey Senozhatsky 8*fb4f644eSSergey Senozhatsky struct lz4_ctx { 9*fb4f644eSSergey Senozhatsky void *mem; 10*fb4f644eSSergey Senozhatsky 11*fb4f644eSSergey Senozhatsky LZ4_streamDecode_t *dstrm; 12*fb4f644eSSergey Senozhatsky LZ4_stream_t *cstrm; 13*fb4f644eSSergey Senozhatsky }; 14*fb4f644eSSergey Senozhatsky 15b8f03cb7SSergey Senozhatsky static void lz4_release_params(struct zcomp_params *params) 16b8f03cb7SSergey Senozhatsky { 17b8f03cb7SSergey Senozhatsky } 18b8f03cb7SSergey Senozhatsky 19b8f03cb7SSergey Senozhatsky static int lz4_setup_params(struct zcomp_params *params) 20b8f03cb7SSergey Senozhatsky { 21b8f03cb7SSergey Senozhatsky if (params->level == ZCOMP_PARAM_NO_LEVEL) 22b8f03cb7SSergey Senozhatsky params->level = LZ4_ACCELERATION_DEFAULT; 23b8f03cb7SSergey Senozhatsky 24b8f03cb7SSergey Senozhatsky return 0; 25b8f03cb7SSergey Senozhatsky } 2622d651c3SSergey Senozhatsky 276a81bdfeSSergey Senozhatsky static void lz4_destroy(struct zcomp_ctx *ctx) 2822d651c3SSergey Senozhatsky { 29*fb4f644eSSergey Senozhatsky struct lz4_ctx *zctx = ctx->context; 30*fb4f644eSSergey Senozhatsky 31*fb4f644eSSergey Senozhatsky if (!zctx) 32*fb4f644eSSergey Senozhatsky return; 33*fb4f644eSSergey Senozhatsky 34*fb4f644eSSergey Senozhatsky vfree(zctx->mem); 35*fb4f644eSSergey Senozhatsky kfree(zctx->dstrm); 36*fb4f644eSSergey Senozhatsky kfree(zctx->cstrm); 37*fb4f644eSSergey Senozhatsky kfree(zctx); 3822d651c3SSergey Senozhatsky } 3922d651c3SSergey Senozhatsky 406a81bdfeSSergey Senozhatsky static int lz4_create(struct zcomp_params *params, struct zcomp_ctx *ctx) 4122d651c3SSergey Senozhatsky { 42*fb4f644eSSergey Senozhatsky struct lz4_ctx *zctx; 43*fb4f644eSSergey Senozhatsky 44*fb4f644eSSergey Senozhatsky zctx = kzalloc(sizeof(*zctx), GFP_KERNEL); 45*fb4f644eSSergey Senozhatsky if (!zctx) 466a81bdfeSSergey Senozhatsky return -ENOMEM; 4722d651c3SSergey Senozhatsky 48*fb4f644eSSergey Senozhatsky ctx->context = zctx; 49*fb4f644eSSergey Senozhatsky if (params->dict_sz == 0) { 50*fb4f644eSSergey Senozhatsky zctx->mem = vmalloc(LZ4_MEM_COMPRESS); 51*fb4f644eSSergey Senozhatsky if (!zctx->mem) 52*fb4f644eSSergey Senozhatsky goto error; 53*fb4f644eSSergey Senozhatsky } else { 54*fb4f644eSSergey Senozhatsky zctx->dstrm = kzalloc(sizeof(*zctx->dstrm), GFP_KERNEL); 55*fb4f644eSSergey Senozhatsky if (!zctx->dstrm) 56*fb4f644eSSergey Senozhatsky goto error; 57*fb4f644eSSergey Senozhatsky 58*fb4f644eSSergey Senozhatsky zctx->cstrm = kzalloc(sizeof(*zctx->cstrm), GFP_KERNEL); 59*fb4f644eSSergey Senozhatsky if (!zctx->cstrm) 60*fb4f644eSSergey Senozhatsky goto error; 61*fb4f644eSSergey Senozhatsky } 62*fb4f644eSSergey Senozhatsky 636a81bdfeSSergey Senozhatsky return 0; 64*fb4f644eSSergey Senozhatsky 65*fb4f644eSSergey Senozhatsky error: 66*fb4f644eSSergey Senozhatsky lz4_destroy(ctx); 67*fb4f644eSSergey Senozhatsky return -ENOMEM; 6822d651c3SSergey Senozhatsky } 6922d651c3SSergey Senozhatsky 70b8f03cb7SSergey Senozhatsky static int lz4_compress(struct zcomp_params *params, struct zcomp_ctx *ctx, 71b8f03cb7SSergey Senozhatsky struct zcomp_req *req) 7222d651c3SSergey Senozhatsky { 73*fb4f644eSSergey Senozhatsky struct lz4_ctx *zctx = ctx->context; 7422d651c3SSergey Senozhatsky int ret; 7522d651c3SSergey Senozhatsky 76*fb4f644eSSergey Senozhatsky if (!zctx->cstrm) { 7752c7b4e2SSergey Senozhatsky ret = LZ4_compress_fast(req->src, req->dst, req->src_len, 78*fb4f644eSSergey Senozhatsky req->dst_len, params->level, 79*fb4f644eSSergey Senozhatsky zctx->mem); 80*fb4f644eSSergey Senozhatsky } else { 81*fb4f644eSSergey Senozhatsky /* Cstrm needs to be reset */ 82*fb4f644eSSergey Senozhatsky ret = LZ4_loadDict(zctx->cstrm, params->dict, params->dict_sz); 83*fb4f644eSSergey Senozhatsky if (ret != params->dict_sz) 84*fb4f644eSSergey Senozhatsky return -EINVAL; 85*fb4f644eSSergey Senozhatsky ret = LZ4_compress_fast_continue(zctx->cstrm, req->src, 86*fb4f644eSSergey Senozhatsky req->dst, req->src_len, 87*fb4f644eSSergey Senozhatsky req->dst_len, params->level); 88*fb4f644eSSergey Senozhatsky } 8922d651c3SSergey Senozhatsky if (!ret) 9022d651c3SSergey Senozhatsky return -EINVAL; 9152c7b4e2SSergey Senozhatsky req->dst_len = ret; 9222d651c3SSergey Senozhatsky return 0; 9322d651c3SSergey Senozhatsky } 9422d651c3SSergey Senozhatsky 95b8f03cb7SSergey Senozhatsky static int lz4_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx, 96b8f03cb7SSergey Senozhatsky struct zcomp_req *req) 9722d651c3SSergey Senozhatsky { 98*fb4f644eSSergey Senozhatsky struct lz4_ctx *zctx = ctx->context; 9922d651c3SSergey Senozhatsky int ret; 10022d651c3SSergey Senozhatsky 101*fb4f644eSSergey Senozhatsky if (!zctx->dstrm) { 10252c7b4e2SSergey Senozhatsky ret = LZ4_decompress_safe(req->src, req->dst, req->src_len, 10352c7b4e2SSergey Senozhatsky req->dst_len); 104*fb4f644eSSergey Senozhatsky } else { 105*fb4f644eSSergey Senozhatsky /* Dstrm needs to be reset */ 106*fb4f644eSSergey Senozhatsky ret = LZ4_setStreamDecode(zctx->dstrm, params->dict, 107*fb4f644eSSergey Senozhatsky params->dict_sz); 108*fb4f644eSSergey Senozhatsky if (!ret) 109*fb4f644eSSergey Senozhatsky return -EINVAL; 110*fb4f644eSSergey Senozhatsky ret = LZ4_decompress_safe_continue(zctx->dstrm, req->src, 111*fb4f644eSSergey Senozhatsky req->dst, req->src_len, 112*fb4f644eSSergey Senozhatsky req->dst_len); 113*fb4f644eSSergey Senozhatsky } 11422d651c3SSergey Senozhatsky if (ret < 0) 11522d651c3SSergey Senozhatsky return -EINVAL; 11622d651c3SSergey Senozhatsky return 0; 11722d651c3SSergey Senozhatsky } 11822d651c3SSergey Senozhatsky 11922d651c3SSergey Senozhatsky const struct zcomp_ops backend_lz4 = { 12022d651c3SSergey Senozhatsky .compress = lz4_compress, 12122d651c3SSergey Senozhatsky .decompress = lz4_decompress, 12222d651c3SSergey Senozhatsky .create_ctx = lz4_create, 12322d651c3SSergey Senozhatsky .destroy_ctx = lz4_destroy, 124b8f03cb7SSergey Senozhatsky .setup_params = lz4_setup_params, 125b8f03cb7SSergey Senozhatsky .release_params = lz4_release_params, 12622d651c3SSergey Senozhatsky .name = "lz4", 12722d651c3SSergey Senozhatsky }; 128