• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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