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