• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0+ OR Apache-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 #warning EROFS may be incompatible on your platform
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(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
135 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
136 
137 #define EROFS_I_EA_INITED	(1 << 0)
138 #define EROFS_I_Z_INITED	(1 << 1)
139 
140 struct erofs_inode {
141 	struct list_head i_hash, i_subdirs, i_xattrs;
142 
143 	union {
144 		/* (erofsfuse) runtime flags */
145 		unsigned int flags;
146 		/* (mkfs.erofs) device ID containing source file */
147 		u32 dev;
148 	};
149 	unsigned int i_count;
150 	struct erofs_inode *i_parent;
151 
152 	umode_t i_mode;
153 	erofs_off_t i_size;
154 
155 	u64 i_ino[2];
156 	u32 i_uid;
157 	u32 i_gid;
158 	u64 i_mtime;
159 	u32 i_mtime_nsec;
160 	u32 i_nlink;
161 
162 	union {
163 		u32 i_blkaddr;
164 		u32 i_blocks;
165 		u32 i_rdev;
166 		struct {
167 			unsigned short	chunkformat;
168 			unsigned char	chunkbits;
169 		};
170 	} u;
171 
172 	char i_srcpath[PATH_MAX + 1];
173 
174 	unsigned char datalayout;
175 	unsigned char inode_isize;
176 	/* inline tail-end packing size */
177 	unsigned short idata_size;
178 	bool compressed_idata;
179 
180 	unsigned int xattr_isize;
181 	unsigned int extent_isize;
182 
183 	erofs_nid_t nid;
184 	struct erofs_buffer_head *bh;
185 	struct erofs_buffer_head *bh_inline, *bh_data;
186 
187 	void *idata;
188 
189 	/* (ztailpacking) in order to recover uncompressed EOF data */
190 	void *eof_tailraw;
191 	unsigned int eof_tailrawsize;
192 
193 	union {
194 		void *compressmeta;
195 		void *chunkindexes;
196 		struct {
197 			uint16_t z_advise;
198 			uint8_t  z_algorithmtype[2];
199 			uint8_t  z_logical_clusterbits;
200 			uint8_t  z_physical_clusterblks;
201 			uint64_t z_tailextent_headlcn;
202 			unsigned int    z_idataoff;
203 #define z_idata_size	idata_size
204 		};
205 	};
206 #ifdef WITH_ANDROID
207 	uint64_t capabilities;
208 #endif
209 };
210 
is_inode_layout_compression(struct erofs_inode * inode)211 static inline bool is_inode_layout_compression(struct erofs_inode *inode)
212 {
213 	return erofs_inode_is_data_compressed(inode->datalayout);
214 }
215 
erofs_bitrange(unsigned int value,unsigned int bit,unsigned int bits)216 static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
217 					  unsigned int bits)
218 {
219 	return (value >> bit) & ((1 << bits) - 1);
220 }
221 
erofs_inode_version(unsigned int value)222 static inline unsigned int erofs_inode_version(unsigned int value)
223 {
224 	return erofs_bitrange(value, EROFS_I_VERSION_BIT,
225 			      EROFS_I_VERSION_BITS);
226 }
227 
erofs_inode_datalayout(unsigned int value)228 static inline unsigned int erofs_inode_datalayout(unsigned int value)
229 {
230 	return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
231 			      EROFS_I_DATALAYOUT_BITS);
232 }
233 
234 #define IS_ROOT(x)	((x) == (x)->i_parent)
235 
236 struct erofs_dentry {
237 	struct list_head d_child;	/* child of parent list */
238 
239 	unsigned int type;
240 	char name[EROFS_NAME_LEN];
241 	union {
242 		struct erofs_inode *inode;
243 		erofs_nid_t nid;
244 	};
245 };
246 
is_dot_dotdot_len(const char * name,unsigned int len)247 static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
248 {
249 	if (len >= 1 && name[0] != '.')
250 		return false;
251 
252 	return len == 1 || (len == 2 && name[1] == '.');
253 }
254 
is_dot_dotdot(const char * name)255 static inline bool is_dot_dotdot(const char *name)
256 {
257 	if (name[0] != '.')
258 		return false;
259 
260 	return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
261 }
262 
263 #include <stdio.h>
264 #include <string.h>
265 
erofs_strerror(int err)266 static inline const char *erofs_strerror(int err)
267 {
268 	static char msg[256];
269 
270 	sprintf(msg, "[Error %d] %s", -err, strerror(-err));
271 	return msg;
272 }
273 
274 enum {
275 	BH_Meta,
276 	BH_Mapped,
277 	BH_Encoded,
278 	BH_FullMapped,
279 };
280 
281 /* Has a disk mapping */
282 #define EROFS_MAP_MAPPED	(1 << BH_Mapped)
283 /* Located in metadata (could be copied from bd_inode) */
284 #define EROFS_MAP_META		(1 << BH_Meta)
285 /* The extent is encoded */
286 #define EROFS_MAP_ENCODED	(1 << BH_Encoded)
287 /* The length of extent is full */
288 #define EROFS_MAP_FULL_MAPPED	(1 << BH_FullMapped)
289 
290 struct erofs_map_blocks {
291 	char mpage[EROFS_BLKSIZ];
292 
293 	erofs_off_t m_pa, m_la;
294 	u64 m_plen, m_llen;
295 
296 	unsigned short m_deviceid;
297 	char m_algorithmformat;
298 	unsigned int m_flags;
299 	erofs_blk_t index;
300 };
301 
302 /*
303  * Used to get the exact decompressed length, e.g. fiemap (consider lookback
304  * approach instead if possible since it's more metadata lightweight.)
305  */
306 #define EROFS_GET_BLOCKS_FIEMAP	0x0002
307 #define EROFS_GET_BLOCKS_FINDTAIL	0x0008
308 
309 enum {
310 	Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
311 	Z_EROFS_COMPRESSION_RUNTIME_MAX
312 };
313 
314 struct erofs_map_dev {
315 	erofs_off_t m_pa;
316 	unsigned int m_deviceid;
317 };
318 
319 /* super.c */
320 int erofs_read_superblock(void);
321 
322 /* namei.c */
323 int erofs_read_inode_from_disk(struct erofs_inode *vi);
324 int erofs_ilookup(const char *path, struct erofs_inode *vi);
325 int erofs_read_inode_from_disk(struct erofs_inode *vi);
326 
327 /* data.c */
328 int erofs_pread(struct erofs_inode *inode, char *buf,
329 		erofs_off_t count, erofs_off_t offset);
330 int erofs_map_blocks(struct erofs_inode *inode,
331 		struct erofs_map_blocks *map, int flags);
332 int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map);
333 
erofs_get_occupied_size(const struct erofs_inode * inode,erofs_off_t * size)334 static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
335 					  erofs_off_t *size)
336 {
337 	*size = 0;
338 	switch (inode->datalayout) {
339 	case EROFS_INODE_FLAT_INLINE:
340 	case EROFS_INODE_FLAT_PLAIN:
341 	case EROFS_INODE_CHUNK_BASED:
342 		*size = inode->i_size;
343 		break;
344 	case EROFS_INODE_FLAT_COMPRESSION_LEGACY:
345 	case EROFS_INODE_FLAT_COMPRESSION:
346 		*size = inode->u.i_blocks * EROFS_BLKSIZ;
347 		break;
348 	default:
349 		return -ENOTSUP;
350 	}
351 	return 0;
352 }
353 
354 /* zmap.c */
355 int z_erofs_fill_inode(struct erofs_inode *vi);
356 int z_erofs_map_blocks_iter(struct erofs_inode *vi,
357 			    struct erofs_map_blocks *map, int flags);
358 
359 #ifdef EUCLEAN
360 #define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
361 #else
362 #define EFSCORRUPTED	EIO
363 #endif
364 
365 #define CRC32C_POLY_LE	0x82F63B78
erofs_crc32c(u32 crc,const u8 * in,size_t len)366 static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
367 {
368 	int i;
369 
370 	while (len--) {
371 		crc ^= *in++;
372 		for (i = 0; i < 8; i++)
373 			crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
374 	}
375 	return crc;
376 }
377 
378 #ifdef __cplusplus
379 }
380 #endif
381 
382 #endif
383