blob: 433a3c6c1eb831f6b3c90e293b0f4107b16cc973 [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
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800108/* make sure that any user of the erofs headers has at least 64bit off_t type */
109extern int erofs_assert_largefile[sizeof(off_t) - 8];
Huang Jianan024fb2f2022-02-26 15:05:47 +0800110
111static inline erofs_off_t iloc(erofs_nid_t nid)
112{
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800113 return erofs_pos(sbi.meta_blkaddr) + (nid << sbi.islotbits);
Huang Jianan024fb2f2022-02-26 15:05:47 +0800114}
115
116#define EROFS_FEATURE_FUNCS(name, compat, feature) \
117static inline bool erofs_sb_has_##name(void) \
118{ \
119 return sbi.feature_##compat & EROFS_FEATURE_##feature; \
120} \
121static inline void erofs_sb_set_##name(void) \
122{ \
123 sbi.feature_##compat |= EROFS_FEATURE_##feature; \
124} \
125static inline void erofs_sb_clear_##name(void) \
126{ \
127 sbi.feature_##compat &= ~EROFS_FEATURE_##feature; \
128}
129
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800130EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_ZERO_PADDING)
Huang Jianan024fb2f2022-02-26 15:05:47 +0800131EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
132EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
133EROFS_FEATURE_FUNCS(chunked_file, incompat, INCOMPAT_CHUNKED_FILE)
134EROFS_FEATURE_FUNCS(device_table, incompat, INCOMPAT_DEVICE_TABLE)
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800135EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
136EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
137EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
138EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
Huang Jianan024fb2f2022-02-26 15:05:47 +0800139EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
140
141#define EROFS_I_EA_INITED (1 << 0)
142#define EROFS_I_Z_INITED (1 << 1)
143
144struct erofs_inode {
145 struct list_head i_hash, i_subdirs, i_xattrs;
146
147 union {
148 /* (erofsfuse) runtime flags */
149 unsigned int flags;
150 /* (mkfs.erofs) device ID containing source file */
151 u32 dev;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800152 /* (mkfs.erofs) queued sub-directories blocking dump */
153 u32 subdirs_queued;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800154 };
155 unsigned int i_count;
156 struct erofs_inode *i_parent;
157
158 umode_t i_mode;
159 erofs_off_t i_size;
160
161 u64 i_ino[2];
162 u32 i_uid;
163 u32 i_gid;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800164 u64 i_mtime;
165 u32 i_mtime_nsec;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800166 u32 i_nlink;
167
168 union {
169 u32 i_blkaddr;
170 u32 i_blocks;
171 u32 i_rdev;
172 struct {
173 unsigned short chunkformat;
174 unsigned char chunkbits;
175 };
176 } u;
177
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800178 char *i_srcpath;
179
Huang Jianan024fb2f2022-02-26 15:05:47 +0800180 unsigned char datalayout;
181 unsigned char inode_isize;
182 /* inline tail-end packing size */
183 unsigned short idata_size;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800184 bool compressed_idata;
185 bool lazy_tailblock;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800186
187 unsigned int xattr_isize;
188 unsigned int extent_isize;
189
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800190 unsigned int xattr_shared_count;
191 unsigned int *xattr_shared_xattrs;
192
Huang Jianan024fb2f2022-02-26 15:05:47 +0800193 erofs_nid_t nid;
194 struct erofs_buffer_head *bh;
195 struct erofs_buffer_head *bh_inline, *bh_data;
196
197 void *idata;
198
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800199 /* (ztailpacking) in order to recover uncompressed EOF data */
200 void *eof_tailraw;
201 unsigned int eof_tailrawsize;
202
Huang Jianan024fb2f2022-02-26 15:05:47 +0800203 union {
204 void *compressmeta;
205 void *chunkindexes;
206 struct {
207 uint16_t z_advise;
208 uint8_t z_algorithmtype[2];
209 uint8_t z_logical_clusterbits;
210 uint8_t z_physical_clusterblks;
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800211 uint64_t z_tailextent_headlcn;
212 unsigned int z_idataoff;
213#define z_idata_size idata_size
Huang Jianan024fb2f2022-02-26 15:05:47 +0800214 };
215 };
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800216 uint64_t capabilities;
217 erofs_off_t fragmentoff;
218 unsigned int fragment_size;
Huang Jianan024fb2f2022-02-26 15:05:47 +0800219};
220
221static inline bool is_inode_layout_compression(struct erofs_inode *inode)
222{
223 return erofs_inode_is_data_compressed(inode->datalayout);
224}
225
226static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
227 unsigned int bits)
228{
229 return (value >> bit) & ((1 << bits) - 1);
230}
231
232static inline unsigned int erofs_inode_version(unsigned int value)
233{
234 return erofs_bitrange(value, EROFS_I_VERSION_BIT,
235 EROFS_I_VERSION_BITS);
236}
237
238static inline unsigned int erofs_inode_datalayout(unsigned int value)
239{
240 return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
241 EROFS_I_DATALAYOUT_BITS);
242}
243
244#define IS_ROOT(x) ((x) == (x)->i_parent)
245
246struct erofs_dentry {
247 struct list_head d_child; /* child of parent list */
248
249 unsigned int type;
250 char name[EROFS_NAME_LEN];
251 union {
252 struct erofs_inode *inode;
253 erofs_nid_t nid;
254 };
255};
256
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800257static inline bool is_dot_dotdot_len(const char *name, unsigned int len)
258{
259 if (len >= 1 && name[0] != '.')
260 return false;
261
262 return len == 1 || (len == 2 && name[1] == '.');
263}
264
Huang Jianan024fb2f2022-02-26 15:05:47 +0800265static inline bool is_dot_dotdot(const char *name)
266{
267 if (name[0] != '.')
268 return false;
269
270 return name[1] == '\0' || (name[1] == '.' && name[2] == '\0');
271}
272
273enum {
274 BH_Meta,
275 BH_Mapped,
276 BH_Encoded,
277 BH_FullMapped,
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800278 BH_Fragment,
279 BH_Partialref,
Huang Jianan024fb2f2022-02-26 15:05:47 +0800280};
281
282/* Has a disk mapping */
283#define EROFS_MAP_MAPPED (1 << BH_Mapped)
284/* Located in metadata (could be copied from bd_inode) */
285#define EROFS_MAP_META (1 << BH_Meta)
286/* The extent is encoded */
287#define EROFS_MAP_ENCODED (1 << BH_Encoded)
288/* The length of extent is full */
289#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800290/* Located in the special packed inode */
291#define EROFS_MAP_FRAGMENT (1 << BH_Fragment)
292/* The extent refers to partial decompressed data */
293#define EROFS_MAP_PARTIAL_REF (1 << BH_Partialref)
Huang Jianan024fb2f2022-02-26 15:05:47 +0800294
295struct erofs_map_blocks {
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800296 char mpage[EROFS_MAX_BLOCK_SIZE];
Huang Jianan024fb2f2022-02-26 15:05:47 +0800297
298 erofs_off_t m_pa, m_la;
299 u64 m_plen, m_llen;
300
301 unsigned short m_deviceid;
302 char m_algorithmformat;
303 unsigned int m_flags;
304 erofs_blk_t index;
305};
306
307/*
308 * Used to get the exact decompressed length, e.g. fiemap (consider lookback
309 * approach instead if possible since it's more metadata lightweight.)
310 */
311#define EROFS_GET_BLOCKS_FIEMAP 0x0002
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800312/* Used to map tail extent for tailpacking inline or fragment pcluster */
313#define EROFS_GET_BLOCKS_FINDTAIL 0x0008
Huang Jianan024fb2f2022-02-26 15:05:47 +0800314
315enum {
316 Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800317 Z_EROFS_COMPRESSION_INTERLACED,
Huang Jianan024fb2f2022-02-26 15:05:47 +0800318 Z_EROFS_COMPRESSION_RUNTIME_MAX
319};
320
321struct erofs_map_dev {
322 erofs_off_t m_pa;
323 unsigned int m_deviceid;
324};
325
326/* fs.c */
327int erofs_blk_read(void *buf, erofs_blk_t start, u32 nblocks);
328int erofs_dev_read(int device_id, void *buf, u64 offset, size_t len);
329
330/* super.c */
331int erofs_read_superblock(void);
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800332void erofs_put_super(void);
Huang Jianan024fb2f2022-02-26 15:05:47 +0800333
334/* namei.c */
335int erofs_read_inode_from_disk(struct erofs_inode *vi);
336int erofs_ilookup(const char *path, struct erofs_inode *vi);
337int erofs_read_inode_from_disk(struct erofs_inode *vi);
338
339/* data.c */
340int erofs_pread(struct erofs_inode *inode, char *buf,
341 erofs_off_t count, erofs_off_t offset);
Yifan Zhao39ace5c2023-07-07 23:52:12 +0800342int erofs_map_blocks(struct erofs_inode *inode, struct erofs_map_blocks *map,
343 int flags);
344int erofs_map_dev(struct erofs_map_dev *map);
345int erofs_read_one_data(struct erofs_map_blocks *map, char *buffer, u64 offset,
346 size_t len);
347int z_erofs_read_one_data(struct erofs_inode *inode,
348 struct erofs_map_blocks *map, char *raw, char *buffer,
349 erofs_off_t skip, erofs_off_t length, bool trimmed);
350
351static inline int erofs_get_occupied_size(const struct erofs_inode *inode,
352 erofs_off_t *size)
353{
354 *size = 0;
355 switch (inode->datalayout) {
356 case EROFS_INODE_FLAT_INLINE:
357 case EROFS_INODE_FLAT_PLAIN:
358 case EROFS_INODE_CHUNK_BASED:
359 *size = inode->i_size;
360 break;
361 case EROFS_INODE_COMPRESSED_FULL:
362 case EROFS_INODE_COMPRESSED_COMPACT:
363 *size = inode->u.i_blocks * erofs_blksiz();
364 break;
365 default:
366 return -EOPNOTSUPP;
367 }
368 return 0;
369}
370
371/* data.c */
372int erofs_getxattr(struct erofs_inode *vi, const char *name, char *buffer,
373 size_t buffer_size);
374int erofs_listxattr(struct erofs_inode *vi, char *buffer, size_t buffer_size);
375
Huang Jianan024fb2f2022-02-26 15:05:47 +0800376/* zmap.c */
377int z_erofs_fill_inode(struct erofs_inode *vi);
378int z_erofs_map_blocks_iter(struct erofs_inode *vi,
379 struct erofs_map_blocks *map, int flags);
380
381#ifdef EUCLEAN
382#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
383#else
384#define EFSCORRUPTED EIO
385#endif
386
387#define CRC32C_POLY_LE 0x82F63B78
388static inline u32 erofs_crc32c(u32 crc, const u8 *in, size_t len)
389{
390 int i;
391
392 while (len--) {
393 crc ^= *in++;
394 for (i = 0; i < 8; i++)
395 crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0);
396 }
397 return crc;
398}
399
400#endif