• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-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 const 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(const struct erofs_compress * c,const void * src,unsigned int * srcsize,void * dst,unsigned int dstsize,bool inblocks)25 int erofs_compress_destsize(const struct erofs_compress *c,
26 			    const void *src, unsigned int *srcsize,
27 			    void *dst, unsigned int dstsize, bool inblocks)
28 {
29 	unsigned int uncompressed_capacity, compressed_size;
30 	int ret;
31 
32 	DBG_BUGON(!c->alg);
33 	if (!c->alg->compress_destsize)
34 		return -ENOTSUP;
35 
36 	uncompressed_capacity = *srcsize;
37 	ret = c->alg->compress_destsize(c, src, srcsize, dst, dstsize);
38 	if (ret < 0)
39 		return ret;
40 
41 	/* XXX: ret >= EROFS_BLKSIZ is a temporary hack for ztailpacking */
42 	if (inblocks || ret >= EROFS_BLKSIZ ||
43 	    uncompressed_capacity != *srcsize)
44 		compressed_size = roundup(ret, EROFS_BLKSIZ);
45 	else
46 		compressed_size = ret;
47 	DBG_BUGON(c->compress_threshold < 100);
48 	/* check if there is enough gains to compress */
49 	if (*srcsize <= compressed_size * c->compress_threshold / 100)
50 		return -EAGAIN;
51 	return ret;
52 }
53 
z_erofs_list_available_compressors(unsigned int i)54 const char *z_erofs_list_available_compressors(unsigned int i)
55 {
56 	return i >= ARRAY_SIZE(compressors) ? NULL : compressors[i]->name;
57 }
58 
erofs_compressor_setlevel(struct erofs_compress * c,int compression_level)59 int erofs_compressor_setlevel(struct erofs_compress *c, int compression_level)
60 {
61 	DBG_BUGON(!c->alg);
62 	if (c->alg->setlevel)
63 		return c->alg->setlevel(c, compression_level);
64 
65 	if (compression_level >= 0)
66 		return -EINVAL;
67 	c->compression_level = 0;
68 	return 0;
69 }
70 
erofs_compressor_init(struct erofs_compress * c,char * alg_name)71 int erofs_compressor_init(struct erofs_compress *c, char *alg_name)
72 {
73 	int ret, i;
74 
75 	/* should be written in "minimum compression ratio * 100" */
76 	c->compress_threshold = 100;
77 
78 	/* optimize for 4k size page */
79 	c->destsize_alignsize = EROFS_BLKSIZ;
80 	c->destsize_redzone_begin = EROFS_BLKSIZ - 16;
81 	c->destsize_redzone_end = EROFS_CONFIG_COMPR_DEF_BOUNDARY;
82 
83 	if (!alg_name) {
84 		c->alg = NULL;
85 		return 0;
86 	}
87 
88 	ret = -EINVAL;
89 	for (i = 0; i < ARRAY_SIZE(compressors); ++i) {
90 		if (alg_name && strcmp(alg_name, compressors[i]->name))
91 			continue;
92 
93 		ret = compressors[i]->init(c);
94 		if (!ret) {
95 			DBG_BUGON(!c->alg);
96 			return 0;
97 		}
98 	}
99 	erofs_err("Cannot find a valid compressor %s", alg_name);
100 	return ret;
101 }
102 
erofs_compressor_exit(struct erofs_compress * c)103 int erofs_compressor_exit(struct erofs_compress *c)
104 {
105 	if (c->alg && c->alg->exit)
106 		return c->alg->exit(c);
107 	return 0;
108 }
109