blob: 4af7c91560cc5b5a006d7b06b5ad0e595d5ec0fd [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
5#define __packed __attribute__((__packed__))
6
7#include <linux/stat.h>
8#include <linux/bug.h>
9#include <linux/err.h>
10#include <linux/printk.h>
11#include <linux/log2.h>
12#include <inttypes.h>
13#include "erofs_fs.h"
14
15#define erofs_err(fmt, ...) \
16 pr_err(fmt "\n", ##__VA_ARGS__)
17
18#define erofs_info(fmt, ...) \
19 pr_info(fmt "\n", ##__VA_ARGS__)
20
21#define erofs_dbg(fmt, ...) \
22 pr_debug(fmt "\n", ##__VA_ARGS__)
23
24#define DBG_BUGON(condition) BUG_ON(condition)
25
26/* no obvious reason to support explicit PAGE_SIZE != 4096 for now */
27#if PAGE_SIZE != 4096
28#error incompatible PAGE_SIZE is already defined
29#endif
30
31#define PAGE_MASK (~(PAGE_SIZE - 1))
32
33#define LOG_BLOCK_SIZE (12)
34#define EROFS_BLKSIZ (1U << LOG_BLOCK_SIZE)
35
36#define EROFS_ISLOTBITS 5
37#define EROFS_SLOTSIZE (1U << EROFS_ISLOTBITS)
38
39typedef u64 erofs_off_t;
40typedef u64 erofs_nid_t;
41/* data type for filesystem-wide blocks number */
42typedef u32 erofs_blk_t;
43
44#define NULL_ADDR ((unsigned int)-1)
45#define NULL_ADDR_UL ((unsigned long)-1)
46
47#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ)
48#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ)
49#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ)
50
51#define BLK_ROUND_UP(addr) DIV_ROUND_UP(addr, EROFS_BLKSIZ)
52
53struct erofs_buffer_head;
54
55struct erofs_device_info {
56 u32 blocks;
57 u32 mapped_blkaddr;
58};
59
60struct erofs_sb_info {
61 struct erofs_device_info *devs;
62
63 u64 total_blocks;
64 u64 primarydevice_blocks;
65
66 erofs_blk_t meta_blkaddr;
67 erofs_blk_t xattr_blkaddr;
68
69 u32 feature_compat;
70 u32 feature_incompat;
71 u64 build_time;
72 u32 build_time_nsec;
73
74 unsigned char islotbits;
75
76 /* what we really care is nid, rather than ino.. */
77 erofs_nid_t root_nid;
78 /* used for statfs, f_files - f_favail */
79 u64 inos;
80
81 u8 uuid[16];
82
83 u16 available_compr_algs;
84 u16 lz4_max_distance;
85 u32 checksum;
86 u16 extra_devices;
87 union {
88 u16 devt_slotoff; /* used for mkfs */
89 u16 device_id_mask; /* used for others */
90 };
91};
92
93/* global sbi */
94extern struct erofs_sb_info sbi;
95
96static inline erofs_off_t iloc(erofs_nid_t nid)
97{
98 return blknr_to_addr(sbi.meta_blkaddr) + (nid << sbi.islotbits);
99}
100
101#define EROFS_FEATURE_FUNCS(name, compat, feature) \
102static inline bool erofs_sb_has_##name(void) \
103{ \
104 return sbi.feature_##compat & EROFS_FEATURE_##feature; \
105} \
106static inline void erofs_sb_set_##name(void) \
107{ \
108 sbi.feature_##compat |= EROFS_FEATURE_##feature; \
109} \
110static inline void erofs_sb_clear_##name(void) \
111{ \
112 sbi.feature_##compat &= ~EROFS_FEATURE_##feature; \
113}
114
115EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING)
116EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
117EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
118EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
119EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
120EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
121
122#define EROFS_I_EA_INITED (1 << 0)
123#define EROFS_I_Z_INITED (1 << 1)
124
125struct erofs_inode {
126 struct list_head i_hash, i_subdirs, i_xattrs;
127
128 union {
129 /* (erofsfuse) runtime flags */
130 unsigned int flags;
131 /* (mkfs.erofs) device ID containing source file */
132 u32 dev;
133 };
134 unsigned int i_count;
135 struct erofs_inode *i_parent;
136
137 umode_t i_mode;
138 erofs_off_t i_size;
139
140 u64 i_ino[2];
141 u32 i_uid;
142 u32 i_gid;
143 u64 i_ctime;
144 u32 i_ctime_nsec;
145 u32 i_nlink;
146
147 union {
148 u32 i_blkaddr;
149 u32 i_blocks;
150 u32 i_rdev;
151 struct {
152 unsigned short chunkformat;
153 unsigned char chunkbits;
154 };
155 } u;
156
157 unsigned char datalayout;
158 unsigned char inode_isize;
159 /* inline tail-end packing size */
160 unsigned short idata_size;
161
162 unsigned int xattr_isize;
163 unsigned int extent_isize;
164
165 erofs_nid_t nid;
166 struct erofs_buffer_head *bh;
167 struct erofs_buffer_head *bh_inline, *bh_data;
168
169 void *idata;
170
171 union {
172 void *compressmeta;
173 void *chunkindexes;
174 struct {
175 uint16_t z_advise;
176 uint8_t z_algorithmtype[2];
177 uint8_t z_logical_clusterbits;
178 uint8_t z_physical_clusterblks;
179 };
180 };
181};
182
183static inline bool is_inode_layout_compression(struct erofs_inode *inode)
184{
185 return erofs_inode_is_data_compressed(inode->datalayout);
186}
187
188static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
189 unsigned int bits)
190{
191 return (value >> bit) & ((1 << bits) - 1);
192}
193
194static inline unsigned int erofs_inode_version(unsigned int value)
195{
196 return erofs_bitrange(value, EROFS_I_VERSION_BIT,
197 EROFS_I_VERSION_BITS);
198}
199
200static inline unsigned int erofs_inode_datalayout(unsigned int value)
201{
202 return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
203 EROFS_I_DATALAYOUT_BITS);
204}
205
206#define IS_ROOT(x) ((x) == (x)->i_parent)
207
208struct erofs_dentry {
209 struct list_head d_child; /* child of parent list */
210
211 unsigned int type;
212 char name[EROFS_NAME_LEN];
213 union {
214 struct erofs_inode *inode;
215 erofs_nid_t nid;
216 };
217};
218
219static inline bool is_dot_dotdot(const char *name)
220{
221 if (name[0] != '.')
222 return false;
223
224 return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
225}
226
227enum {
228 BH_Meta,
229 BH_Mapped,
230 BH_Encoded,
231 BH_FullMapped,
232};
233
234/* Has a disk mapping */
235#define EROFS_MAP_MAPPED (1 << BH_Mapped)
236/* Located in metadata (could be copied from bd_inode) */
237#define EROFS_MAP_META (1 << BH_Meta)
238/* The extent is encoded */
239#define EROFS_MAP_ENCODED (1 << BH_Encoded)
240/* The length of extent is full */
241#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
242
243struct erofs_map_blocks {
244 char mpage[EROFS_BLKSIZ];
245
246 erofs_off_t m_pa, m_la;
247 u64 m_plen, m_llen;
248
249 unsigned short m_deviceid;
250 char m_algorithmformat;
251 unsigned int m_flags;
252 erofs_blk_t index;
253};
254
255/*
256 * Used to get the exact decompressed length, e.g. fiemap (consider lookback
257 * approach instead if possible since it's more metadata lightweight.)
258 */
259#define EROFS_GET_BLOCKS_FIEMAP 0x0002
260
261enum {
262 Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
263 Z_EROFS_COMPRESSION_RUNTIME_MAX
264};
265
266struct erofs_map_dev {
267 erofs_off_t m_pa;
268 unsigned int m_deviceid;
269};
270
271/* fs.c */
272int erofs_blk_read(void *buf, erofs_blk_t start, u32 nblocks);
273int erofs_dev_read(int device_id, void *buf, u64 offset, size_t len);
274
275/* super.c */
276int erofs_read_superblock(void);
277
278/* namei.c */
279int erofs_read_inode_from_disk(struct erofs_inode *vi);
280int erofs_ilookup(const char *path, struct erofs_inode *vi);
281int erofs_read_inode_from_disk(struct erofs_inode *vi);
282
283/* data.c */
284int erofs_pread(struct erofs_inode *inode, char *buf,
285 erofs_off_t count, erofs_off_t offset);
286int erofs_map_blocks(struct erofs_inode *inode,
287 struct erofs_map_blocks *map, int flags);
288int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map);
289/* zmap.c */
290int z_erofs_fill_inode(struct erofs_inode *vi);
291int z_erofs_map_blocks_iter(struct erofs_inode *vi,
292 struct erofs_map_blocks *map, int flags);
293
294#ifdef EUCLEAN
295#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
296#else
297#define EFSCORRUPTED EIO
298#endif
299
300#define CRC32C_POLY_LE 0x82F63B78
301static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
302{
303 int i;
304
305 while (len--) {
306 crc ^= *in++;
307 for (i = 0; i < 8; i++)
308 crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
309 }
310 return crc;
311}
312
313#endif