• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2 /*
3  * Copyright (C), 2008-2021, OPPO Mobile Comm Corp., Ltd.
4  * Created by Huang Jianan <huangjianan@oppo.com>
5  */
6 #include <string.h>
7 #include <stdlib.h>
8 #include "erofs/err.h"
9 #include "erofs/list.h"
10 #include "erofs/print.h"
11 #include "erofs/compress_hints.h"
12 
13 static LIST_HEAD(compress_hints_head);
14 
dump_regerror(int errcode,const char * s,const regex_t * preg)15 static void dump_regerror(int errcode, const char *s, const regex_t *preg)
16 {
17 	char str[512];
18 
19 	regerror(errcode, preg, str, sizeof(str));
20 	erofs_err("invalid regex %s (%s)\n", s, str);
21 }
22 
erofs_insert_compress_hints(const char * s,unsigned int blks)23 static int erofs_insert_compress_hints(const char *s, unsigned int blks)
24 {
25 	struct erofs_compress_hints *r;
26 	int ret;
27 
28 	r = malloc(sizeof(struct erofs_compress_hints));
29 	if (!r)
30 		return -ENOMEM;
31 
32 	ret = regcomp(&r->reg, s, REG_EXTENDED|REG_NOSUB);
33 	if (ret) {
34 		dump_regerror(ret, s, &r->reg);
35 		goto err_out;
36 	}
37 	r->physical_clusterblks = blks;
38 
39 	list_add_tail(&r->list, &compress_hints_head);
40 	erofs_info("compress hint %s (%u) is inserted", s, blks);
41 	return ret;
42 
43 err_out:
44 	free(r);
45 	return ret;
46 }
47 
z_erofs_apply_compress_hints(struct erofs_inode * inode)48 bool z_erofs_apply_compress_hints(struct erofs_inode *inode)
49 {
50 	const char *s;
51 	struct erofs_compress_hints *r;
52 	unsigned int pclusterblks;
53 
54 	if (inode->z_physical_clusterblks)
55 		return true;
56 
57 	s = erofs_fspath(inode->i_srcpath);
58 	pclusterblks = cfg.c_pclusterblks_def;
59 
60 	list_for_each_entry(r, &compress_hints_head, list) {
61 		int ret = regexec(&r->reg, s, (size_t)0, NULL, 0);
62 
63 		if (!ret) {
64 			pclusterblks = r->physical_clusterblks;
65 			break;
66 		}
67 		if (ret != REG_NOMATCH)
68 			dump_regerror(ret, s, &r->reg);
69 	}
70 	inode->z_physical_clusterblks = pclusterblks;
71 
72 	/* pclusterblks is 0 means this file shouldn't be compressed */
73 	return !!pclusterblks;
74 }
75 
erofs_cleanup_compress_hints(void)76 void erofs_cleanup_compress_hints(void)
77 {
78 	struct erofs_compress_hints *r, *n;
79 
80 	list_for_each_entry_safe(r, n, &compress_hints_head, list) {
81 		list_del(&r->list);
82 		free(r);
83 	}
84 }
85 
erofs_load_compress_hints(void)86 int erofs_load_compress_hints(void)
87 {
88 	char buf[PATH_MAX + 100];
89 	FILE *f;
90 	unsigned int line, max_pclustersize = 0;
91 	int ret = 0;
92 
93 	if (!cfg.c_compress_hints_file)
94 		return 0;
95 
96 	f = fopen(cfg.c_compress_hints_file, "r");
97 	if (!f)
98 		return -errno;
99 
100 	for (line = 1; fgets(buf, sizeof(buf), f); ++line) {
101 		unsigned int pclustersize;
102 		char *pattern;
103 
104 		pclustersize = atoi(strtok(buf, "\t "));
105 		pattern = strtok(NULL, "\n");
106 		if (!pattern || *pattern == '\0') {
107 			erofs_err("cannot find a match pattern at line %u",
108 				  line);
109 			ret = -EINVAL;
110 			goto out;
111 		}
112 		if (pclustersize % EROFS_BLKSIZ) {
113 			erofs_warn("invalid physical clustersize %u, "
114 				   "use default pclusterblks %u",
115 				   pclustersize, cfg.c_pclusterblks_def);
116 			continue;
117 		}
118 		erofs_insert_compress_hints(pattern,
119 					    pclustersize / EROFS_BLKSIZ);
120 
121 		if (pclustersize > max_pclustersize)
122 			max_pclustersize = pclustersize;
123 	}
124 
125 	if (cfg.c_pclusterblks_max * EROFS_BLKSIZ < max_pclustersize) {
126 		cfg.c_pclusterblks_max = max_pclustersize / EROFS_BLKSIZ;
127 		erofs_warn("update max pclusterblks to %u", cfg.c_pclusterblks_max);
128 	}
129 out:
130 	fclose(f);
131 	return ret;
132 }
133