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