blob: 1875f37fcd2e9e30798df0e9dae71c19ca98d3c9 [file] [log] [blame]
Huang Jianan024fb2f2022-02-26 15:05:47 +08001/* SPDX-License-Identifier: GPL-2.0+ */
2#ifndef __EROFS_INTERNAL_H
3#define __EROFS_INTERNAL_H
4
Yifan Zhao39ace5c2023-07-07 23:52:12 +08005#include "linux/compat.h"
Huang Jianan024fb2f2022-02-26 15:05:47 +08006#define __packed __attribute__((__packed__))
7
8#include <linux/stat.h>
9#include <linux/bug.h>
10#include <linux/err.h>
11#include <linux/printk.h>
12#include <linux/log2.h>
13#include <inttypes.h>
14#include "erofs_fs.h"
15
16#define erofs_err(fmt, ...) \
17 pr_err(fmt "\n", ##__VA_ARGS__)
18
19#define erofs_info(fmt, ...) \
20 pr_info(fmt "\n", ##__VA_ARGS__)
21
22#define erofs_dbg(fmt, ...) \
23 pr_debug(fmt "\n", ##__VA_ARGS__)
24
25#define DBG_BUGON(condition) BUG_ON(condition)
26
27/* no obvious reason to support explicit PAGE_SIZE != 4096 for now */
28#if PAGE_SIZE != 4096
29#error incompatible PAGE_SIZE is already defined
30#endif
31
32#define PAGE_MASK (~(PAGE_SIZE - 1))
33
Yifan Zhao39ace5c2023-07-07 23:52:12 +080034#ifndef EROFS_MAX_BLOCK_SIZE
35#define EROFS_MAX_BLOCK_SIZE PAGE_SIZE
36#endif
Huang Jianan024fb2f2022-02-26 15:05:47 +080037
38#define EROFS_ISLOTBITS 5
39#define EROFS_SLOTSIZE (1U << EROFS_ISLOTBITS)
40
41typedef u64 erofs_off_t;
42typedef u64 erofs_nid_t;
43/* data type for filesystem-wide blocks number */
44typedef u32 erofs_blk_t;
45
46#define NULL_ADDR ((unsigned int)-1)
47#define NULL_ADDR_UL ((unsigned long)-1)
48
Yifan Zhao39ace5c2023-07-07 23:52:12 +080049/* global sbi */
50extern struct erofs_sb_info sbi;
51
52#define erofs_blksiz() (1u << sbi.blkszbits)
53#define erofs_blknr(addr) ((addr) >> sbi.blkszbits)
54#define erofs_blkoff(addr) ((addr) & (erofs_blksiz() - 1))
55#define erofs_pos(nr) ((erofs_off_t)(nr) << sbi.blkszbits)
Huang Jianan024fb2f2022-02-26 15:05:47 +080056
Yifan Zhao39ace5c2023-07-07 23:52:12 +080057#define BLK_ROUND_UP(addr) DIV_ROUND_UP(addr, 1u << sbi.blkszbits)
Huang Jianan024fb2f2022-02-26 15:05:47 +080058
59struct erofs_buffer_head;
60
61struct erofs_device_info {
62 u32 blocks;
63 u32 mapped_blkaddr;
64};
65
Yifan Zhao39ace5c2023-07-07 23:52:12 +080066#define EROFS_PACKED_NID_UNALLOCATED -1
67
Huang Jianan024fb2f2022-02-26 15:05:47 +080068struct erofs_sb_info {
69 struct erofs_device_info *devs;
70
71 u64 total_blocks;
72 u64 primarydevice_blocks;
73
74 erofs_blk_t meta_blkaddr;
75 erofs_blk_t xattr_blkaddr;
76
77 u32 feature_compat;
78 u32 feature_incompat;
79 u64 build_time;
80 u32 build_time_nsec;
81
82 unsigned char islotbits;
Yifan Zhao39ace5c2023-07-07 23:52:12 +080083 unsigned char blkszbits;
Huang Jianan024fb2f2022-02-26 15:05:47 +080084
85 /* what we really care is nid, rather than ino.. */
86 erofs_nid_t root_nid;
87 /* used for statfs, f_files - f_favail */
88 u64 inos;
89
90 u8 uuid[16];
Yifan Zhao39ace5c2023-07-07 23:52:12 +080091 char volume_name[16];
Huang Jianan024fb2f2022-02-26 15:05:47 +080092
93 u16 available_compr_algs;
94 u16 lz4_max_distance;
Yifan Zhao39ace5c2023-07-07 23:52:12 +080095
Huang Jianan024fb2f2022-02-26 15:05:47 +080096 u32 checksum;
97 u16 extra_devices;
98 union {
99 u16 devt_slotoff; /* used for mkfs */
100 u16 device_id_mask; /* used for others */
101 };
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800102 erofs_nid_t packed_nid;
103
104 u32 xattr_prefix_start;
105 u8 xattr_prefix_count;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800106};
107
Huang Jianan024fb2f2022-02-26 15:05:47 +0800108static inline erofs_off_t iloc(erofs_nid_t nid)
109{
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800110 return erofs_pos(sbi.meta_blkaddr) + (nid << sbi.islotbits);
Huang Jianan024fb2f2022-02-26 15:05:47 +0800111}
112
113#define EROFS_FEATURE_FUNCS(name, compat, feature) \
114static inline bool erofs_sb_has_##name(void) \
115{ \
116 return sbi.feature_##compat & EROFS_FEATURE_##feature; \
117} \
118static inline void erofs_sb_set_##name(void) \
119{ \
120 sbi.feature_##compat |= EROFS_FEATURE_##feature; \
121} \
122static inline void erofs_sb_clear_##name(void) \
123{ \
124 sbi.feature_##compat &= ~EROFS_FEATURE_##feature; \
125}
126
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800127EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_ZERO_PADDING)
Huang Jianan024fb2f2022-02-26 15:05:47 +0800128EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
129EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
130EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
131EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800132EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
133EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
134EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
135EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
Huang Jianan024fb2f2022-02-26 15:05:47 +0800136EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
137
138#define EROFS_I_EA_INITED (1 << 0)
139#define EROFS_I_Z_INITED (1 << 1)
140
141struct erofs_inode {
142 struct list_head i_hash, i_subdirs, i_xattrs;
143
144 union {
145 /* (erofsfuse) runtime flags */
146 unsigned int flags;
147 /* (mkfs.erofs) device ID containing source file */
148 u32 dev;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800149 /* (mkfs.erofs) queued sub-directories blocking dump */
150 u32 subdirs_queued;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800151 };
152 unsigned int i_count;
153 struct erofs_inode *i_parent;
154
155 umode_t i_mode;
156 erofs_off_t i_size;
157
158 u64 i_ino[2];
159 u32 i_uid;
160 u32 i_gid;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800161 u64 i_mtime;
162 u32 i_mtime_nsec;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800163 u32 i_nlink;
164
165 union {
166 u32 i_blkaddr;
167 u32 i_blocks;
168 u32 i_rdev;
169 struct {
170 unsigned short chunkformat;
171 unsigned char chunkbits;
172 };
173 } u;
174
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800175 char *i_srcpath;
176
Huang Jianan024fb2f2022-02-26 15:05:47 +0800177 unsigned char datalayout;
178 unsigned char inode_isize;
179 /* inline tail-end packing size */
180 unsigned short idata_size;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800181 bool compressed_idata;
182 bool lazy_tailblock;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800183
184 unsigned int xattr_isize;
185 unsigned int extent_isize;
186
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800187 unsigned int xattr_shared_count;
188 unsigned int *xattr_shared_xattrs;
189
Huang Jianan024fb2f2022-02-26 15:05:47 +0800190 erofs_nid_t nid;
191 struct erofs_buffer_head *bh;
192 struct erofs_buffer_head *bh_inline, *bh_data;
193
194 void *idata;
195
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800196 /* (ztailpacking) in order to recover uncompressed EOF data */
197 void *eof_tailraw;
198 unsigned int eof_tailrawsize;
199
Huang Jianan024fb2f2022-02-26 15:05:47 +0800200 union {
201 void *compressmeta;
202 void *chunkindexes;
203 struct {
204 uint16_t z_advise;
205 uint8_t z_algorithmtype[2];
206 uint8_t z_logical_clusterbits;
207 uint8_t z_physical_clusterblks;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800208 uint64_t z_tailextent_headlcn;
209 unsigned int z_idataoff;
210#define z_idata_size idata_size
Huang Jianan024fb2f2022-02-26 15:05:47 +0800211 };
212 };
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800213 uint64_t capabilities;
214 erofs_off_t fragmentoff;
215 unsigned int fragment_size;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800216};
217
218static inline bool is_inode_layout_compression(struct erofs_inode *inode)
219{
220 return erofs_inode_is_data_compressed(inode->datalayout);
221}
222
223static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
224 unsigned int bits)
225{
226 return (value >> bit) & ((1 << bits) - 1);
227}
228
229static inline unsigned int erofs_inode_version(unsigned int value)
230{
231 return erofs_bitrange(value, EROFS_I_VERSION_BIT,
232 EROFS_I_VERSION_BITS);
233}
234
235static inline unsigned int erofs_inode_datalayout(unsigned int value)
236{
237 return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
238 EROFS_I_DATALAYOUT_BITS);
239}
240
241#define IS_ROOT(x) ((x) == (x)->i_parent)
242
243struct erofs_dentry {
244 struct list_head d_child; /* child of parent list */
245
246 unsigned int type;
247 char name[EROFS_NAME_LEN];
248 union {
249 struct erofs_inode *inode;
250 erofs_nid_t nid;
251 };
252};
253
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800254static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
255{
256 if (len >= 1 && name[0] != '.')
257 return false;
258
259 return len == 1 || (len == 2 && name[1] == '.');
260}
261
Huang Jianan024fb2f2022-02-26 15:05:47 +0800262static inline bool is_dot_dotdot(const char *name)
263{
264 if (name[0] != '.')
265 return false;
266
267 return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
268}
269
270enum {
271 BH_Meta,
272 BH_Mapped,
273 BH_Encoded,
274 BH_FullMapped,
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800275 BH_Fragment,
276 BH_Partialref,
Huang Jianan024fb2f2022-02-26 15:05:47 +0800277};
278
279/* Has a disk mapping */
280#define EROFS_MAP_MAPPED (1 << BH_Mapped)
281/* Located in metadata (could be copied from bd_inode) */
282#define EROFS_MAP_META (1 << BH_Meta)
283/* The extent is encoded */
284#define EROFS_MAP_ENCODED (1 << BH_Encoded)
285/* The length of extent is full */
286#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800287/* Located in the special packed inode */
288#define EROFS_MAP_FRAGMENT (1 << BH_Fragment)
289/* The extent refers to partial decompressed data */
290#define EROFS_MAP_PARTIAL_REF (1 << BH_Partialref)
Huang Jianan024fb2f2022-02-26 15:05:47 +0800291
292struct erofs_map_blocks {
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800293 char mpage[EROFS_MAX_BLOCK_SIZE];
Huang Jianan024fb2f2022-02-26 15:05:47 +0800294
295 erofs_off_t m_pa, m_la;
296 u64 m_plen, m_llen;
297
298 unsigned short m_deviceid;
299 char m_algorithmformat;
300 unsigned int m_flags;
301 erofs_blk_t index;
302};
303
304/*
305 * Used to get the exact decompressed length, e.g. fiemap (consider lookback
306 * approach instead if possible since it's more metadata lightweight.)
307 */
308#define EROFS_GET_BLOCKS_FIEMAP 0x0002
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800309/* Used to map tail extent for tailpacking inline or fragment pcluster */
310#define EROFS_GET_BLOCKS_FINDTAIL 0x0008
Huang Jianan024fb2f2022-02-26 15:05:47 +0800311
312enum {
313 Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800314 Z_EROFS_COMPRESSION_INTERLACED,
Huang Jianan024fb2f2022-02-26 15:05:47 +0800315 Z_EROFS_COMPRESSION_RUNTIME_MAX
316};
317
318struct erofs_map_dev {
319 erofs_off_t m_pa;
320 unsigned int m_deviceid;
321};
322
323/* fs.c */
324int erofs_blk_read(void *buf, erofs_blk_t start, u32 nblocks);
325int erofs_dev_read(int device_id, void *buf, u64 offset, size_t len);
326
327/* super.c */
328int erofs_read_superblock(void);
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800329void erofs_put_super(void);
Huang Jianan024fb2f2022-02-26 15:05:47 +0800330
331/* namei.c */
332int erofs_read_inode_from_disk(struct erofs_inode *vi);
333int erofs_ilookup(const char *path, struct erofs_inode *vi);
334int erofs_read_inode_from_disk(struct erofs_inode *vi);
335
336/* data.c */
337int erofs_pread(struct erofs_inode *inode, char *buf,
338 erofs_off_t count, erofs_off_t offset);
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800339int erofs_map_blocks(struct erofs_inode *inode, struct erofs_map_blocks *map,
340 int flags);
341int erofs_map_dev(struct erofs_map_dev *map);
342int erofs_read_one_data(struct erofs_map_blocks *map, char *buffer, u64 offset,
343 size_t len);
344int z_erofs_read_one_data(struct erofs_inode *inode,
345 struct erofs_map_blocks *map, char *raw, char *buffer,
346 erofs_off_t skip, erofs_off_t length, bool trimmed);
347
348static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
349 erofs_off_t *size)
350{
351 *size = 0;
352 switch (inode->datalayout) {
353 case EROFS_INODE_FLAT_INLINE:
354 case EROFS_INODE_FLAT_PLAIN:
355 case EROFS_INODE_CHUNK_BASED:
356 *size = inode->i_size;
357 break;
358 case EROFS_INODE_COMPRESSED_FULL:
359 case EROFS_INODE_COMPRESSED_COMPACT:
360 *size = inode->u.i_blocks * erofs_blksiz();
361 break;
362 default:
363 return -EOPNOTSUPP;
364 }
365 return 0;
366}
367
368/* data.c */
369int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
370 size_t buffer_size);
371int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
372
Huang Jianan024fb2f2022-02-26 15:05:47 +0800373/* zmap.c */
374int z_erofs_fill_inode(struct erofs_inode *vi);
375int z_erofs_map_blocks_iter(struct erofs_inode *vi,
376 struct erofs_map_blocks *map, int flags);
377
378#ifdef EUCLEAN
379#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
380#else
381#define EFSCORRUPTED EIO
382#endif
383
384#define CRC32C_POLY_LE 0x82F63B78
385static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
386{
387 int i;
388
389 while (len--) {
390 crc ^= *in++;
391 for (i = 0; i < 8; i++)
392 crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
393 }
394 return crc;
395}
396
397#endif