1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * Copyright (C) 2019 HUAWEI, Inc.
4 * http://www.huawei.com/
5 * Created by Gao Xiang <gaoxiang25@huawei.com>
6 */
7 #ifndef __EROFS_INTERNAL_H
8 #define __EROFS_INTERNAL_H
9
10 #ifdef __cplusplus
11 extern "C"
12 {
13 #endif
14
15 #include "list.h"
16 #include "err.h"
17
18 typedef unsigned short umode_t;
19
20 #define __packed __attribute__((__packed__))
21
22 #include "erofs_fs.h"
23 #include <fcntl.h>
24
25 #ifndef PATH_MAX
26 #define PATH_MAX 4096 /* # chars in a path name including nul */
27 #endif
28
29 #ifndef PAGE_SHIFT
30 #define PAGE_SHIFT (12)
31 #endif
32
33 #ifndef PAGE_SIZE
34 #define PAGE_SIZE (1U << PAGE_SHIFT)
35 #endif
36
37 /* no obvious reason to support explicit PAGE_SIZE != 4096 for now */
38 #if PAGE_SIZE != 4096
39 #error incompatible PAGE_SIZE is already defined
40 #endif
41
42 #ifndef PAGE_MASK
43 #define PAGE_MASK (~(PAGE_SIZE-1))
44 #endif
45
46 #define LOG_BLOCK_SIZE (12)
47 #define EROFS_BLKSIZ (1U << LOG_BLOCK_SIZE)
48
49 #define EROFS_ISLOTBITS 5
50 #define EROFS_SLOTSIZE (1U << EROFS_ISLOTBITS)
51
52 typedef u64 erofs_off_t;
53 typedef u64 erofs_nid_t;
54 /* data type for filesystem-wide blocks number */
55 typedef u32 erofs_blk_t;
56
57 #define NULL_ADDR ((unsigned int)-1)
58 #define NULL_ADDR_UL ((unsigned long)-1)
59
60 #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ)
61 #define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ)
62 #define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ)
63
64 #define BLK_ROUND_UP(addr) DIV_ROUND_UP(addr, EROFS_BLKSIZ)
65
66 struct erofs_buffer_head;
67
68 struct erofs_device_info {
69 u32 blocks;
70 u32 mapped_blkaddr;
71 };
72
73 struct erofs_sb_info {
74 struct erofs_device_info *devs;
75
76 u64 total_blocks;
77 u64 primarydevice_blocks;
78
79 erofs_blk_t meta_blkaddr;
80 erofs_blk_t xattr_blkaddr;
81
82 u32 feature_compat;
83 u32 feature_incompat;
84 u64 build_time;
85 u32 build_time_nsec;
86
87 unsigned char islotbits;
88
89 /* what we really care is nid, rather than ino.. */
90 erofs_nid_t root_nid;
91 /* used for statfs, f_files - f_favail */
92 u64 inos;
93
94 u8 uuid[16];
95
96 u16 available_compr_algs;
97 u16 lz4_max_distance;
98
99 u32 checksum;
100 u16 extra_devices;
101 union {
102 u16 devt_slotoff; /* used for mkfs */
103 u16 device_id_mask; /* used for others */
104 };
105 };
106
107 /* global sbi */
108 extern struct erofs_sb_info sbi;
109
iloc(erofs_nid_t nid)110 static inline erofs_off_t iloc(erofs_nid_t nid)
111 {
112 return blknr_to_addr(sbi.meta_blkaddr) + (nid << sbi.islotbits);
113 }
114
115 #define EROFS_FEATURE_FUNCS(name, compat, feature) \
116 static inline bool erofs_sb_has_##name(void) \
117 { \
118 return sbi.feature_##compat & EROFS_FEATURE_##feature; \
119 } \
120 static inline void erofs_sb_set_##name(void) \
121 { \
122 sbi.feature_##compat |= EROFS_FEATURE_##feature; \
123 } \
124 static inline void erofs_sb_clear_##name(void) \
125 { \
126 sbi.feature_##compat &= ~EROFS_FEATURE_##feature; \
127 }
128
129 EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING)
130 EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
131 EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
132 EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
133 EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
134 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
135
136 #define EROFS_I_EA_INITED (1 << 0)
137 #define EROFS_I_Z_INITED (1 << 1)
138
139 struct erofs_inode {
140 struct list_head i_hash, i_subdirs, i_xattrs;
141
142 union {
143 /* (erofsfuse) runtime flags */
144 unsigned int flags;
145 /* (mkfs.erofs) device ID containing source file */
146 u32 dev;
147 };
148 unsigned int i_count;
149 struct erofs_inode *i_parent;
150
151 umode_t i_mode;
152 erofs_off_t i_size;
153
154 u64 i_ino[2];
155 u32 i_uid;
156 u32 i_gid;
157 u64 i_mtime;
158 u32 i_mtime_nsec;
159 u32 i_nlink;
160
161 union {
162 u32 i_blkaddr;
163 u32 i_blocks;
164 u32 i_rdev;
165 struct {
166 unsigned short chunkformat;
167 unsigned char chunkbits;
168 };
169 } u;
170
171 char i_srcpath[PATH_MAX + 1];
172
173 unsigned char datalayout;
174 unsigned char inode_isize;
175 /* inline tail-end packing size */
176 unsigned short idata_size;
177
178 unsigned int xattr_isize;
179 unsigned int extent_isize;
180
181 erofs_nid_t nid;
182 struct erofs_buffer_head *bh;
183 struct erofs_buffer_head *bh_inline, *bh_data;
184
185 void *idata;
186
187 union {
188 void *compressmeta;
189 void *chunkindexes;
190 struct {
191 uint16_t z_advise;
192 uint8_t z_algorithmtype[2];
193 uint8_t z_logical_clusterbits;
194 uint8_t z_physical_clusterblks;
195 };
196 };
197 #ifdef WITH_ANDROID
198 uint64_t capabilities;
199 #endif
200 };
201
is_inode_layout_compression(struct erofs_inode * inode)202 static inline bool is_inode_layout_compression(struct erofs_inode *inode)
203 {
204 return erofs_inode_is_data_compressed(inode->datalayout);
205 }
206
erofs_bitrange(unsigned int value,unsigned int bit,unsigned int bits)207 static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
208 unsigned int bits)
209 {
210 return (value >> bit) & ((1 << bits) - 1);
211 }
212
erofs_inode_version(unsigned int value)213 static inline unsigned int erofs_inode_version(unsigned int value)
214 {
215 return erofs_bitrange(value, EROFS_I_VERSION_BIT,
216 EROFS_I_VERSION_BITS);
217 }
218
erofs_inode_datalayout(unsigned int value)219 static inline unsigned int erofs_inode_datalayout(unsigned int value)
220 {
221 return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
222 EROFS_I_DATALAYOUT_BITS);
223 }
224
225 #define IS_ROOT(x) ((x) == (x)->i_parent)
226
227 struct erofs_dentry {
228 struct list_head d_child; /* child of parent list */
229
230 unsigned int type;
231 char name[EROFS_NAME_LEN];
232 union {
233 struct erofs_inode *inode;
234 erofs_nid_t nid;
235 };
236 };
237
is_dot_dotdot_len(const char * name,unsigned int len)238 static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
239 {
240 if (len >= 1 && name[0] != '.')
241 return false;
242
243 return len == 1 || (len == 2 && name[1] == '.');
244 }
245
is_dot_dotdot(const char * name)246 static inline bool is_dot_dotdot(const char *name)
247 {
248 if (name[0] != '.')
249 return false;
250
251 return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
252 }
253
254 #include <stdio.h>
255 #include <string.h>
256
erofs_strerror(int err)257 static inline const char *erofs_strerror(int err)
258 {
259 static char msg[256];
260
261 sprintf(msg, "[Error %d] %s", -err, strerror(-err));
262 return msg;
263 }
264
265 enum {
266 BH_Meta,
267 BH_Mapped,
268 BH_Encoded,
269 BH_FullMapped,
270 };
271
272 /* Has a disk mapping */
273 #define EROFS_MAP_MAPPED (1 << BH_Mapped)
274 /* Located in metadata (could be copied from bd_inode) */
275 #define EROFS_MAP_META (1 << BH_Meta)
276 /* The extent is encoded */
277 #define EROFS_MAP_ENCODED (1 << BH_Encoded)
278 /* The length of extent is full */
279 #define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
280
281 struct erofs_map_blocks {
282 char mpage[EROFS_BLKSIZ];
283
284 erofs_off_t m_pa, m_la;
285 u64 m_plen, m_llen;
286
287 unsigned short m_deviceid;
288 char m_algorithmformat;
289 unsigned int m_flags;
290 erofs_blk_t index;
291 };
292
293 /*
294 * Used to get the exact decompressed length, e.g. fiemap (consider lookback
295 * approach instead if possible since it's more metadata lightweight.)
296 */
297 #define EROFS_GET_BLOCKS_FIEMAP 0x0002
298
299 enum {
300 Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
301 Z_EROFS_COMPRESSION_RUNTIME_MAX
302 };
303
304 struct erofs_map_dev {
305 erofs_off_t m_pa;
306 unsigned int m_deviceid;
307 };
308
309 /* super.c */
310 int erofs_read_superblock(void);
311
312 /* namei.c */
313 int erofs_read_inode_from_disk(struct erofs_inode *vi);
314 int erofs_ilookup(const char *path, struct erofs_inode *vi);
315 int erofs_read_inode_from_disk(struct erofs_inode *vi);
316
317 /* data.c */
318 int erofs_pread(struct erofs_inode *inode, char *buf,
319 erofs_off_t count, erofs_off_t offset);
320 int erofs_map_blocks(struct erofs_inode *inode,
321 struct erofs_map_blocks *map, int flags);
322 int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map);
323 /* zmap.c */
324 int z_erofs_fill_inode(struct erofs_inode *vi);
325 int z_erofs_map_blocks_iter(struct erofs_inode *vi,
326 struct erofs_map_blocks *map, int flags);
327
328 #ifdef EUCLEAN
329 #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
330 #else
331 #define EFSCORRUPTED EIO
332 #endif
333
334 #define CRC32C_POLY_LE 0x82F63B78
erofs_crc32c(u32 crc,const u8 * in,size_t len)335 static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
336 {
337 int i;
338
339 while (len--) {
340 crc ^= *in++;
341 for (i = 0; i < 8; i++)
342 crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
343 }
344 return crc;
345 }
346
347 #ifdef __cplusplus
348 }
349 #endif
350
351 #endif
352