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