1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2018-2019 HUAWEI, Inc.
4 * http://www.huawei.com/
5 * Created by Gao Xiang <gaoxiang25@huawei.com>
6 */
7 #include "erofs/internal.h"
8 #include "compressor.h"
9 #include "erofs/print.h"
10
11 #define EROFS_CONFIG_COMPR_DEF_BOUNDARY (128)
12
13 static struct erofs_compressor *compressors[] = {
14 #if LZ4_ENABLED
15 #if LZ4HC_ENABLED
16 &erofs_compressor_lz4hc,
17 #endif
18 &erofs_compressor_lz4,
19 #endif
20 #if HAVE_LIBLZMA
21 &erofs_compressor_lzma,
22 #endif
23 };
24
erofs_compress_destsize(struct erofs_compress * c,void * src,unsigned int * srcsize,void * dst,unsigned int dstsize)25 int erofs_compress_destsize(struct erofs_compress *c,
26 void *src, unsigned int *srcsize,
27 void *dst, unsigned int dstsize)
28 {
29 unsigned int uncompressed_size;
30 int ret;
31
32 DBG_BUGON(!c->alg);
33 if (!c->alg->compress_destsize)
34 return -ENOTSUP;
35
36 ret = c->alg->compress_destsize(c, src, srcsize, dst, dstsize);
37 if (ret < 0)
38 return ret;
39
40 /* check if there is enough gains to compress */
41 uncompressed_size = *srcsize;
42 if (roundup(ret, EROFS_BLKSIZ) >= uncompressed_size *
43 c->compress_threshold / 100)
44 return -EAGAIN;
45 return ret;
46 }
47
z_erofs_list_available_compressors(unsigned int i)48 const char *z_erofs_list_available_compressors(unsigned int i)
49 {
50 return i >= ARRAY_SIZE(compressors) ? NULL : compressors[i]->name;
51 }
52
erofs_compressor_setlevel(struct erofs_compress * c,int compression_level)53 int erofs_compressor_setlevel(struct erofs_compress *c, int compression_level)
54 {
55 DBG_BUGON(!c->alg);
56 if (c->alg->setlevel)
57 return c->alg->setlevel(c, compression_level);
58
59 if (compression_level >= 0)
60 return -EINVAL;
61 c->compression_level = 0;
62 return 0;
63 }
64
erofs_compressor_init(struct erofs_compress * c,char * alg_name)65 int erofs_compressor_init(struct erofs_compress *c, char *alg_name)
66 {
67 int ret, i;
68
69 /* should be written in "minimum compression ratio * 100" */
70 c->compress_threshold = 100;
71
72 /* optimize for 4k size page */
73 c->destsize_alignsize = PAGE_SIZE;
74 c->destsize_redzone_begin = PAGE_SIZE - 16;
75 c->destsize_redzone_end = EROFS_CONFIG_COMPR_DEF_BOUNDARY;
76
77 if (!alg_name) {
78 c->alg = NULL;
79 return 0;
80 }
81
82 ret = -EINVAL;
83 for (i = 0; i < ARRAY_SIZE(compressors); ++i) {
84 if (alg_name && strcmp(alg_name, compressors[i]->name))
85 continue;
86
87 ret = compressors[i]->init(c);
88 if (!ret) {
89 DBG_BUGON(!c->alg);
90 return 0;
91 }
92 }
93 erofs_err("Cannot find a valid compressor %s", alg_name);
94 return ret;
95 }
96
erofs_compressor_exit(struct erofs_compress * c)97 int erofs_compressor_exit(struct erofs_compress *c)
98 {
99 if (c->alg && c->alg->exit)
100 return c->alg->exit(c);
101 return 0;
102 }
103