• 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 #include "erofs_fs.h"
21 #include <fcntl.h>
22 #include <sys/types.h> /* for off_t definition */
23 #include <sys/stat.h> /* for S_ISCHR definition */
24 #include <stdio.h>
25 
26 #ifndef PATH_MAX
27 #define PATH_MAX        4096    /* # chars in a path name including nul */
28 #endif
29 
30 #ifndef EROFS_MAX_BLOCK_SIZE
31 #define EROFS_MAX_BLOCK_SIZE	4096
32 #endif
33 
34 #define EROFS_ISLOTBITS		5
35 #define EROFS_SLOTSIZE		(1U << EROFS_ISLOTBITS)
36 
37 typedef u64 erofs_off_t;
38 typedef u64 erofs_nid_t;
39 /* data type for filesystem-wide blocks number */
40 typedef u32 erofs_blk_t;
41 
42 #define NULL_ADDR	((unsigned int)-1)
43 #define NULL_ADDR_UL	((unsigned long)-1)
44 
45 /* global sbi */
46 extern struct erofs_sb_info sbi;
47 
48 #define erofs_blksiz(sbi)	(1u << (sbi)->blkszbits)
49 #define erofs_blknr(sbi, addr)  ((addr) >> (sbi)->blkszbits)
50 #define erofs_blkoff(sbi, addr) ((addr) & (erofs_blksiz(sbi) - 1))
51 #define erofs_pos(sbi, nr)      ((erofs_off_t)(nr) << (sbi)->blkszbits)
52 #define BLK_ROUND_UP(sbi, addr)	DIV_ROUND_UP(addr, erofs_blksiz(sbi))
53 
54 struct erofs_buffer_head;
55 
56 struct erofs_device_info {
57 	u8 tag[64];
58 	u32 blocks;
59 	u32 mapped_blkaddr;
60 };
61 
62 struct erofs_xattr_prefix_item {
63 	struct erofs_xattr_long_prefix *prefix;
64 	u8 infix_len;
65 };
66 
67 #define EROFS_PACKED_NID_UNALLOCATED	-1
68 
69 struct erofs_sb_info {
70 	struct erofs_device_info *devs;
71 	char *devname;
72 
73 	u64 total_blocks;
74 	u64 primarydevice_blocks;
75 
76 	erofs_blk_t meta_blkaddr;
77 	erofs_blk_t xattr_blkaddr;
78 
79 	u32 feature_compat;
80 	u32 feature_incompat;
81 	u64 build_time;
82 	u32 build_time_nsec;
83 
84 	u8  extslots;
85 	unsigned char islotbits;
86 	unsigned char blkszbits;
87 
88 	/* what we really care is nid, rather than ino.. */
89 	erofs_nid_t root_nid;
90 	/* used for statfs, f_files - f_favail */
91 	u64 inos;
92 
93 	u8 uuid[16];
94 	char volume_name[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 	erofs_nid_t packed_nid;
106 
107 	u32 xattr_prefix_start;
108 	u8 xattr_prefix_count;
109 	struct erofs_xattr_prefix_item *xattr_prefixes;
110 
111 	int devfd, devblksz;
112 	u64 devsz;
113 	dev_t dev;
114 	unsigned int nblobs;
115 	unsigned int blobfd[256];
116 
117 	struct list_head list;
118 
119 	u64 saved_by_deduplication;
120 };
121 
122 /* make sure that any user of the erofs headers has atleast 64bit off_t type */
123 extern int erofs_assert_largefile[sizeof(off_t)-8];
124 
125 #define EROFS_FEATURE_FUNCS(name, compat, feature) \
126 static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \
127 { \
128 	return sbi->feature_##compat & EROFS_FEATURE_##feature; \
129 } \
130 static inline void erofs_sb_set_##name(struct erofs_sb_info *sbi) \
131 { \
132 	sbi->feature_##compat |= EROFS_FEATURE_##feature; \
133 } \
134 static inline void erofs_sb_clear_##name(struct erofs_sb_info *sbi) \
135 { \
136 	sbi->feature_##compat &= ~EROFS_FEATURE_##feature; \
137 }
138 
139 EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_ZERO_PADDING)
140 EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
141 EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
142 EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
143 EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
144 EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
145 EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
146 EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
147 EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
148 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
149 EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER)
150 
151 #define EROFS_I_EA_INITED	(1 << 0)
152 #define EROFS_I_Z_INITED	(1 << 1)
153 
154 struct erofs_diskbuf;
155 
156 struct erofs_inode {
157 	struct list_head i_hash, i_subdirs, i_xattrs;
158 
159 	union {
160 		/* (erofsfuse) runtime flags */
161 		unsigned int flags;
162 
163 		/* (mkfs.erofs) next pointer for directory dumping */
164 		struct erofs_inode *next_dirwrite;
165 	};
166 	unsigned int i_count;
167 	struct erofs_sb_info *sbi;
168 	struct erofs_inode *i_parent;
169 
170 	/* (mkfs.erofs) device ID containing source file */
171 	u32 dev;
172 
173 	umode_t i_mode;
174 	erofs_off_t i_size;
175 
176 	u64 i_ino[2];
177 	u32 i_uid;
178 	u32 i_gid;
179 	u64 i_mtime;
180 	u32 i_mtime_nsec;
181 	u32 i_nlink;
182 
183 	union {
184 		u32 i_blkaddr;
185 		u32 i_blocks;
186 		u32 i_rdev;
187 		struct {
188 			unsigned short	chunkformat;
189 			unsigned char	chunkbits;
190 		};
191 	} u;
192 
193 	char *i_srcpath;
194 	union {
195 		char *i_link;
196 		struct erofs_diskbuf *i_diskbuf;
197 	};
198 	unsigned char datalayout;
199 	unsigned char inode_isize;
200 	/* inline tail-end packing size */
201 	unsigned short idata_size;
202 	bool compressed_idata;
203 	bool lazy_tailblock;
204 	bool with_diskbuf;
205 	bool opaque;
206 	/* OVL: non-merge dir that may contain whiteout entries */
207 	bool whiteouts;
208 
209 	unsigned int xattr_isize;
210 	unsigned int extent_isize;
211 
212 	unsigned int xattr_shared_count;
213 	unsigned int *xattr_shared_xattrs;
214 
215 	erofs_nid_t nid;
216 	struct erofs_buffer_head *bh;
217 	struct erofs_buffer_head *bh_inline, *bh_data;
218 
219 	void *idata;
220 
221 	/* (ztailpacking) in order to recover uncompressed EOF data */
222 	void *eof_tailraw;
223 	unsigned int eof_tailrawsize;
224 
225 	union {
226 		void *compressmeta;
227 		void *chunkindexes;
228 		struct {
229 			uint16_t z_advise;
230 			uint8_t  z_algorithmtype[2];
231 			uint8_t  z_logical_clusterbits;
232 			uint8_t  z_physical_clusterblks;
233 			uint64_t z_tailextent_headlcn;
234 			unsigned int    z_idataoff;
235 #define z_idata_size	idata_size
236 		};
237 	};
238 #ifdef WITH_ANDROID
239 	uint64_t capabilities;
240 #endif
241 	erofs_off_t fragmentoff;
242 	unsigned int fragment_size;
243 };
244 
erofs_iloc(struct erofs_inode * inode)245 static inline erofs_off_t erofs_iloc(struct erofs_inode *inode)
246 {
247 	struct erofs_sb_info *sbi = inode->sbi;
248 
249 	return erofs_pos(sbi, sbi->meta_blkaddr) +
250 			(inode->nid << sbi->islotbits);
251 }
252 
is_inode_layout_compression(struct erofs_inode * inode)253 static inline bool is_inode_layout_compression(struct erofs_inode *inode)
254 {
255 	return erofs_inode_is_data_compressed(inode->datalayout);
256 }
257 
erofs_bitrange(unsigned int value,unsigned int bit,unsigned int bits)258 static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
259 					  unsigned int bits)
260 {
261 	return (value >> bit) & ((1 << bits) - 1);
262 }
263 
erofs_inode_version(unsigned int value)264 static inline unsigned int erofs_inode_version(unsigned int value)
265 {
266 	return erofs_bitrange(value, EROFS_I_VERSION_BIT,
267 			      EROFS_I_VERSION_BITS);
268 }
269 
erofs_inode_datalayout(unsigned int value)270 static inline unsigned int erofs_inode_datalayout(unsigned int value)
271 {
272 	return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
273 			      EROFS_I_DATALAYOUT_BITS);
274 }
275 
276 #define IS_ROOT(x)	((x) == (x)->i_parent)
277 
278 struct erofs_dentry {
279 	struct list_head d_child;	/* child of parent list */
280 
281 	unsigned int type;
282 	char name[EROFS_NAME_LEN];
283 	union {
284 		struct erofs_inode *inode;
285 		erofs_nid_t nid;
286 	};
287 };
288 
is_dot_dotdot_len(const char * name,unsigned int len)289 static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
290 {
291 	if (len >= 1 && name[0] != '.')
292 		return false;
293 
294 	return len == 1 || (len == 2 && name[1] == '.');
295 }
296 
is_dot_dotdot(const char * name)297 static inline bool is_dot_dotdot(const char *name)
298 {
299 	if (name[0] != '.')
300 		return false;
301 
302 	return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
303 }
304 
305 #include <stdio.h>
306 #include <string.h>
307 
erofs_strerror(int err)308 static inline const char *erofs_strerror(int err)
309 {
310 	static char msg[256];
311 
312 	sprintf(msg, "[Error %d] %s", -err, strerror(-err));
313 	return msg;
314 }
315 
316 enum {
317 	BH_Meta,
318 	BH_Mapped,
319 	BH_Encoded,
320 	BH_FullMapped,
321 	BH_Fragment,
322 	BH_Partialref,
323 };
324 
325 /* Has a disk mapping */
326 #define EROFS_MAP_MAPPED	(1 << BH_Mapped)
327 /* Located in metadata (could be copied from bd_inode) */
328 #define EROFS_MAP_META		(1 << BH_Meta)
329 /* The extent is encoded */
330 #define EROFS_MAP_ENCODED	(1 << BH_Encoded)
331 /* The length of extent is full */
332 #define EROFS_MAP_FULL_MAPPED	(1 << BH_FullMapped)
333 /* Located in the special packed inode */
334 #define EROFS_MAP_FRAGMENT	(1 << BH_Fragment)
335 /* The extent refers to partial decompressed data */
336 #define EROFS_MAP_PARTIAL_REF	(1 << BH_Partialref)
337 
338 struct erofs_map_blocks {
339 	char mpage[EROFS_MAX_BLOCK_SIZE];
340 
341 	erofs_off_t m_pa, m_la;
342 	u64 m_plen, m_llen;
343 
344 	unsigned short m_deviceid;
345 	char m_algorithmformat;
346 	unsigned int m_flags;
347 	erofs_blk_t index;
348 };
349 
350 /*
351  * Used to get the exact decompressed length, e.g. fiemap (consider lookback
352  * approach instead if possible since it's more metadata lightweight.)
353  */
354 #define EROFS_GET_BLOCKS_FIEMAP	0x0002
355 /* Used to map tail extent for tailpacking inline or fragment pcluster */
356 #define EROFS_GET_BLOCKS_FINDTAIL	0x0008
357 
358 enum {
359 	Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
360 	Z_EROFS_COMPRESSION_INTERLACED,
361 	Z_EROFS_COMPRESSION_RUNTIME_MAX
362 };
363 
364 struct erofs_map_dev {
365 	erofs_off_t m_pa;
366 	unsigned int m_deviceid;
367 };
368 
369 /* super.c */
370 int erofs_read_superblock(struct erofs_sb_info *sbi);
371 void erofs_put_super(struct erofs_sb_info *sbi);
372 
373 /* namei.c */
374 int erofs_read_inode_from_disk(struct erofs_inode *vi);
375 int erofs_ilookup(const char *path, struct erofs_inode *vi);
376 
377 /* data.c */
378 int erofs_pread(struct erofs_inode *inode, char *buf,
379 		erofs_off_t count, erofs_off_t offset);
380 int erofs_map_blocks(struct erofs_inode *inode,
381 		struct erofs_map_blocks *map, int flags);
382 int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map);
383 int erofs_read_one_data(struct erofs_inode *inode, struct erofs_map_blocks *map,
384 			char *buffer, u64 offset, size_t len);
385 int z_erofs_read_one_data(struct erofs_inode *inode,
386 			struct erofs_map_blocks *map, char *raw, char *buffer,
387 			erofs_off_t skip, erofs_off_t length, bool trimmed);
388 void *erofs_read_metadata(struct erofs_sb_info *sbi, erofs_nid_t nid,
389 			  erofs_off_t *offset, int *lengthp);
390 
erofs_get_occupied_size(const struct erofs_inode * inode,erofs_off_t * size)391 static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
392 					  erofs_off_t *size)
393 {
394 	*size = 0;
395 	switch (inode->datalayout) {
396 	case EROFS_INODE_FLAT_INLINE:
397 	case EROFS_INODE_FLAT_PLAIN:
398 	case EROFS_INODE_CHUNK_BASED:
399 		*size = inode->i_size;
400 		break;
401 	case EROFS_INODE_COMPRESSED_FULL:
402 	case EROFS_INODE_COMPRESSED_COMPACT:
403 		*size = inode->u.i_blocks * erofs_blksiz(inode->sbi);
404 		break;
405 	default:
406 		return -EOPNOTSUPP;
407 	}
408 	return 0;
409 }
410 
411 /* data.c */
412 int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
413 		   size_t buffer_size);
414 int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
415 
416 /* zmap.c */
417 int z_erofs_fill_inode(struct erofs_inode *vi);
418 int z_erofs_map_blocks_iter(struct erofs_inode *vi,
419 			    struct erofs_map_blocks *map, int flags);
420 
421 #ifdef EUCLEAN
422 #define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
423 #else
424 #define EFSCORRUPTED	EIO
425 #endif
426 
427 #define CRC32C_POLY_LE	0x82F63B78
erofs_crc32c(u32 crc,const u8 * in,size_t len)428 static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
429 {
430 	int i;
431 
432 	while (len--) {
433 		crc ^= *in++;
434 		for (i = 0; i < 8; i++)
435 			crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
436 	}
437 	return crc;
438 }
439 
440 #define EROFS_WHITEOUT_DEV	0
erofs_inode_is_whiteout(struct erofs_inode * inode)441 static inline bool erofs_inode_is_whiteout(struct erofs_inode *inode)
442 {
443 	return S_ISCHR(inode->i_mode) && inode->u.i_rdev == EROFS_WHITEOUT_DEV;
444 }
445 
446 #ifdef __cplusplus
447 }
448 #endif
449 
450 #endif
451