1 /* SPDX-License-Identifier: GPL-2.0+ */
2 #ifndef __EROFS_INTERNAL_H
3 #define __EROFS_INTERNAL_H
4
5 #include "linux/compat.h"
6 #define __packed __attribute__((__packed__))
7
8 #include <linux/stat.h>
9 #include <linux/bug.h>
10 #include <linux/err.h>
11 #include <linux/printk.h>
12 #include <linux/log2.h>
13 #include <inttypes.h>
14 #include "erofs_fs.h"
15
16 #define erofs_err(fmt, ...) \
17 pr_err(fmt "\n", ##__VA_ARGS__)
18
19 #define erofs_info(fmt, ...) \
20 pr_info(fmt "\n", ##__VA_ARGS__)
21
22 #define erofs_dbg(fmt, ...) \
23 pr_debug(fmt "\n", ##__VA_ARGS__)
24
25 #define DBG_BUGON(condition) BUG_ON(condition)
26
27 /* no obvious reason to support explicit PAGE_SIZE != 4096 for now */
28 #if PAGE_SIZE != 4096
29 #error incompatible PAGE_SIZE is already defined
30 #endif
31
32 #define PAGE_MASK (~(PAGE_SIZE - 1))
33
34 #ifndef EROFS_MAX_BLOCK_SIZE
35 #define EROFS_MAX_BLOCK_SIZE PAGE_SIZE
36 #endif
37
38 #define EROFS_ISLOTBITS 5
39 #define EROFS_SLOTSIZE (1U << EROFS_ISLOTBITS)
40
41 typedef u64 erofs_off_t;
42 typedef u64 erofs_nid_t;
43 /* data type for filesystem-wide blocks number */
44 typedef u32 erofs_blk_t;
45
46 #define NULL_ADDR ((unsigned int)-1)
47 #define NULL_ADDR_UL ((unsigned long)-1)
48
49 /* global sbi */
50 extern struct erofs_sb_info sbi;
51
52 #define erofs_blksiz() (1u << sbi.blkszbits)
53 #define erofs_blknr(addr) ((addr) >> sbi.blkszbits)
54 #define erofs_blkoff(addr) ((addr) & (erofs_blksiz() - 1))
55 #define erofs_pos(nr) ((erofs_off_t)(nr) << sbi.blkszbits)
56
57 #define BLK_ROUND_UP(addr) DIV_ROUND_UP(addr, 1u << sbi.blkszbits)
58
59 struct erofs_buffer_head;
60
61 struct erofs_device_info {
62 u32 blocks;
63 u32 mapped_blkaddr;
64 };
65
66 #define EROFS_PACKED_NID_UNALLOCATED -1
67
68 struct erofs_sb_info {
69 struct erofs_device_info *devs;
70
71 u64 total_blocks;
72 u64 primarydevice_blocks;
73
74 erofs_blk_t meta_blkaddr;
75 erofs_blk_t xattr_blkaddr;
76
77 u32 feature_compat;
78 u32 feature_incompat;
79 u64 build_time;
80 u32 build_time_nsec;
81
82 unsigned char islotbits;
83 unsigned char blkszbits;
84
85 /* what we really care is nid, rather than ino.. */
86 erofs_nid_t root_nid;
87 /* used for statfs, f_files - f_favail */
88 u64 inos;
89
90 u8 uuid[16];
91 char volume_name[16];
92
93 u16 available_compr_algs;
94 u16 lz4_max_distance;
95
96 u32 checksum;
97 u16 extra_devices;
98 union {
99 u16 devt_slotoff; /* used for mkfs */
100 u16 device_id_mask; /* used for others */
101 };
102 erofs_nid_t packed_nid;
103
104 u32 xattr_prefix_start;
105 u8 xattr_prefix_count;
106 };
107
iloc(erofs_nid_t nid)108 static inline erofs_off_t iloc(erofs_nid_t nid)
109 {
110 return erofs_pos(sbi.meta_blkaddr) + (nid << sbi.islotbits);
111 }
112
113 #define EROFS_FEATURE_FUNCS(name, compat, feature) \
114 static inline bool erofs_sb_has_##name(void) \
115 { \
116 return sbi.feature_##compat & EROFS_FEATURE_##feature; \
117 } \
118 static inline void erofs_sb_set_##name(void) \
119 { \
120 sbi.feature_##compat |= EROFS_FEATURE_##feature; \
121 } \
122 static inline void erofs_sb_clear_##name(void) \
123 { \
124 sbi.feature_##compat &= ~EROFS_FEATURE_##feature; \
125 }
126
127 EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_ZERO_PADDING)
128 EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
129 EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
130 EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
131 EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
132 EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
133 EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
134 EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
135 EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
136 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
137
138 #define EROFS_I_EA_INITED (1 << 0)
139 #define EROFS_I_Z_INITED (1 << 1)
140
141 struct erofs_inode {
142 struct list_head i_hash, i_subdirs, i_xattrs;
143
144 union {
145 /* (erofsfuse) runtime flags */
146 unsigned int flags;
147 /* (mkfs.erofs) device ID containing source file */
148 u32 dev;
149 /* (mkfs.erofs) queued sub-directories blocking dump */
150 u32 subdirs_queued;
151 };
152 unsigned int i_count;
153 struct erofs_inode *i_parent;
154
155 umode_t i_mode;
156 erofs_off_t i_size;
157
158 u64 i_ino[2];
159 u32 i_uid;
160 u32 i_gid;
161 u64 i_mtime;
162 u32 i_mtime_nsec;
163 u32 i_nlink;
164
165 union {
166 u32 i_blkaddr;
167 u32 i_blocks;
168 u32 i_rdev;
169 struct {
170 unsigned short chunkformat;
171 unsigned char chunkbits;
172 };
173 } u;
174
175 char *i_srcpath;
176
177 unsigned char datalayout;
178 unsigned char inode_isize;
179 /* inline tail-end packing size */
180 unsigned short idata_size;
181 bool compressed_idata;
182 bool lazy_tailblock;
183
184 unsigned int xattr_isize;
185 unsigned int extent_isize;
186
187 unsigned int xattr_shared_count;
188 unsigned int *xattr_shared_xattrs;
189
190 erofs_nid_t nid;
191 struct erofs_buffer_head *bh;
192 struct erofs_buffer_head *bh_inline, *bh_data;
193
194 void *idata;
195
196 /* (ztailpacking) in order to recover uncompressed EOF data */
197 void *eof_tailraw;
198 unsigned int eof_tailrawsize;
199
200 union {
201 void *compressmeta;
202 void *chunkindexes;
203 struct {
204 uint16_t z_advise;
205 uint8_t z_algorithmtype[2];
206 uint8_t z_logical_clusterbits;
207 uint8_t z_physical_clusterblks;
208 uint64_t z_tailextent_headlcn;
209 unsigned int z_idataoff;
210 #define z_idata_size idata_size
211 };
212 };
213 uint64_t capabilities;
214 erofs_off_t fragmentoff;
215 unsigned int fragment_size;
216 };
217
is_inode_layout_compression(struct erofs_inode * inode)218 static inline bool is_inode_layout_compression(struct erofs_inode *inode)
219 {
220 return erofs_inode_is_data_compressed(inode->datalayout);
221 }
222
erofs_bitrange(unsigned int value,unsigned int bit,unsigned int bits)223 static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
224 unsigned int bits)
225 {
226 return (value >> bit) & ((1 << bits) - 1);
227 }
228
erofs_inode_version(unsigned int value)229 static inline unsigned int erofs_inode_version(unsigned int value)
230 {
231 return erofs_bitrange(value, EROFS_I_VERSION_BIT,
232 EROFS_I_VERSION_BITS);
233 }
234
erofs_inode_datalayout(unsigned int value)235 static inline unsigned int erofs_inode_datalayout(unsigned int value)
236 {
237 return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
238 EROFS_I_DATALAYOUT_BITS);
239 }
240
241 #define IS_ROOT(x) ((x) == (x)->i_parent)
242
243 struct erofs_dentry {
244 struct list_head d_child; /* child of parent list */
245
246 unsigned int type;
247 char name[EROFS_NAME_LEN];
248 union {
249 struct erofs_inode *inode;
250 erofs_nid_t nid;
251 };
252 };
253
is_dot_dotdot_len(const char * name,unsigned int len)254 static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
255 {
256 if (len >= 1 && name[0] != '.')
257 return false;
258
259 return len == 1 || (len == 2 && name[1] == '.');
260 }
261
is_dot_dotdot(const char * name)262 static inline bool is_dot_dotdot(const char *name)
263 {
264 if (name[0] != '.')
265 return false;
266
267 return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
268 }
269
270 enum {
271 BH_Meta,
272 BH_Mapped,
273 BH_Encoded,
274 BH_FullMapped,
275 BH_Fragment,
276 BH_Partialref,
277 };
278
279 /* Has a disk mapping */
280 #define EROFS_MAP_MAPPED (1 << BH_Mapped)
281 /* Located in metadata (could be copied from bd_inode) */
282 #define EROFS_MAP_META (1 << BH_Meta)
283 /* The extent is encoded */
284 #define EROFS_MAP_ENCODED (1 << BH_Encoded)
285 /* The length of extent is full */
286 #define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
287 /* Located in the special packed inode */
288 #define EROFS_MAP_FRAGMENT (1 << BH_Fragment)
289 /* The extent refers to partial decompressed data */
290 #define EROFS_MAP_PARTIAL_REF (1 << BH_Partialref)
291
292 struct erofs_map_blocks {
293 char mpage[EROFS_MAX_BLOCK_SIZE];
294
295 erofs_off_t m_pa, m_la;
296 u64 m_plen, m_llen;
297
298 unsigned short m_deviceid;
299 char m_algorithmformat;
300 unsigned int m_flags;
301 erofs_blk_t index;
302 };
303
304 /*
305 * Used to get the exact decompressed length, e.g. fiemap (consider lookback
306 * approach instead if possible since it's more metadata lightweight.)
307 */
308 #define EROFS_GET_BLOCKS_FIEMAP 0x0002
309 /* Used to map tail extent for tailpacking inline or fragment pcluster */
310 #define EROFS_GET_BLOCKS_FINDTAIL 0x0008
311
312 enum {
313 Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
314 Z_EROFS_COMPRESSION_INTERLACED,
315 Z_EROFS_COMPRESSION_RUNTIME_MAX
316 };
317
318 struct erofs_map_dev {
319 erofs_off_t m_pa;
320 unsigned int m_deviceid;
321 };
322
323 /* fs.c */
324 int erofs_blk_read(void *buf, erofs_blk_t start, u32 nblocks);
325 int erofs_dev_read(int device_id, void *buf, u64 offset, size_t len);
326
327 /* super.c */
328 int erofs_read_superblock(void);
329 void erofs_put_super(void);
330
331 /* namei.c */
332 int erofs_read_inode_from_disk(struct erofs_inode *vi);
333 int erofs_ilookup(const char *path, struct erofs_inode *vi);
334 int erofs_read_inode_from_disk(struct erofs_inode *vi);
335
336 /* data.c */
337 int erofs_pread(struct erofs_inode *inode, char *buf,
338 erofs_off_t count, erofs_off_t offset);
339 int erofs_map_blocks(struct erofs_inode *inode, struct erofs_map_blocks *map,
340 int flags);
341 int erofs_map_dev(struct erofs_map_dev *map);
342 int erofs_read_one_data(struct erofs_map_blocks *map, char *buffer, u64 offset,
343 size_t len);
344 int z_erofs_read_one_data(struct erofs_inode *inode,
345 struct erofs_map_blocks *map, char *raw, char *buffer,
346 erofs_off_t skip, erofs_off_t length, bool trimmed);
347
erofs_get_occupied_size(const struct erofs_inode * inode,erofs_off_t * size)348 static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
349 erofs_off_t *size)
350 {
351 *size = 0;
352 switch (inode->datalayout) {
353 case EROFS_INODE_FLAT_INLINE:
354 case EROFS_INODE_FLAT_PLAIN:
355 case EROFS_INODE_CHUNK_BASED:
356 *size = inode->i_size;
357 break;
358 case EROFS_INODE_COMPRESSED_FULL:
359 case EROFS_INODE_COMPRESSED_COMPACT:
360 *size = inode->u.i_blocks * erofs_blksiz();
361 break;
362 default:
363 return -EOPNOTSUPP;
364 }
365 return 0;
366 }
367
368 /* data.c */
369 int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
370 size_t buffer_size);
371 int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
372
373 /* zmap.c */
374 int z_erofs_fill_inode(struct erofs_inode *vi);
375 int z_erofs_map_blocks_iter(struct erofs_inode *vi,
376 struct erofs_map_blocks *map, int flags);
377
378 #ifdef EUCLEAN
379 #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
380 #else
381 #define EFSCORRUPTED EIO
382 #endif
383
384 #define CRC32C_POLY_LE 0x82F63B78
erofs_crc32c(u32 crc,const u8 * in,size_t len)385 static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
386 {
387 int i;
388
389 while (len--) {
390 crc ^= *in++;
391 for (i = 0; i < 8; i++)
392 crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
393 }
394 return crc;
395 }
396
397 #endif
398