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