147e4937aSGao Xiang /* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */
247e4937aSGao Xiang /*
3ea559e7bSGao Xiang * EROFS (Enhanced ROM File System) on-disk format definition
4ea559e7bSGao Xiang *
547e4937aSGao Xiang * Copyright (C) 2017-2018 HUAWEI, Inc.
6592e7cd0SAlexander A. Klimov * https://www.huawei.com/
72a9dc7a8SGao Xiang * Copyright (C) 2021, Alibaba Cloud
847e4937aSGao Xiang */
947e4937aSGao Xiang #ifndef __EROFS_FS_H
1047e4937aSGao Xiang #define __EROFS_FS_H
1147e4937aSGao Xiang
1247e4937aSGao Xiang #define EROFS_SUPER_OFFSET 1024
1347e4937aSGao Xiang
14b858a484SPratik Shinde #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001
15a1108dcdSDavid Anderson #define EROFS_FEATURE_COMPAT_MTIME 0x00000002
16*3f339920SJingbo Xu #define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004
17b858a484SPratik Shinde
1847e4937aSGao Xiang /*
19426a9308SGao Xiang * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should
20426a9308SGao Xiang * be incompatible with this kernel version.
2147e4937aSGao Xiang */
227e508f2cSHuang Jianan #define EROFS_FEATURE_INCOMPAT_ZERO_PADDING 0x00000001
2314373711SGao Xiang #define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002
245404c330SGao Xiang #define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002
252a9dc7a8SGao Xiang #define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE 0x00000004
26dfeab2e9SGao Xiang #define EROFS_FEATURE_INCOMPAT_DEVICE_TABLE 0x00000008
2772bb5262SGao Xiang #define EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 0x00000008
28ab92184fSYue Hu #define EROFS_FEATURE_INCOMPAT_ZTAILPACKING 0x00000010
29b15b2e30SYue Hu #define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020
305c2a6425SGao Xiang #define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020
316a318ccdSJingbo Xu #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040
328e6c8fa9SGao Xiang #define EROFS_ALL_FEATURE_INCOMPAT \
337e508f2cSHuang Jianan (EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \
348e6c8fa9SGao Xiang EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
352a9dc7a8SGao Xiang EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \
36dfeab2e9SGao Xiang EROFS_FEATURE_INCOMPAT_CHUNKED_FILE | \
3772bb5262SGao Xiang EROFS_FEATURE_INCOMPAT_DEVICE_TABLE | \
38ab92184fSYue Hu EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \
39b15b2e30SYue Hu EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \
405c2a6425SGao Xiang EROFS_FEATURE_INCOMPAT_FRAGMENTS | \
416a318ccdSJingbo Xu EROFS_FEATURE_INCOMPAT_DEDUPE | \
426a318ccdSJingbo Xu EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES)
4347e4937aSGao Xiang
4414373711SGao Xiang #define EROFS_SB_EXTSLOT_SIZE 16
4514373711SGao Xiang
46dfeab2e9SGao Xiang struct erofs_deviceslot {
47ba73eaddSJeffle Xu u8 tag[64]; /* digest(sha256), etc. */
48dfeab2e9SGao Xiang __le32 blocks; /* total fs blocks of this device */
49dfeab2e9SGao Xiang __le32 mapped_blkaddr; /* map starting at mapped_blkaddr */
50dfeab2e9SGao Xiang u8 reserved[56];
51dfeab2e9SGao Xiang };
52dfeab2e9SGao Xiang #define EROFS_DEVT_SLOT_SIZE sizeof(struct erofs_deviceslot)
53dfeab2e9SGao Xiang
5414373711SGao Xiang /* erofs on-disk super block (currently 128 bytes) */
5547e4937aSGao Xiang struct erofs_super_block {
564b66eb51SGao Xiang __le32 magic; /* file system magic number */
574b66eb51SGao Xiang __le32 checksum; /* crc32c(super_block) */
58426a9308SGao Xiang __le32 feature_compat;
59d3c4bdccSJingbo Xu __u8 blkszbits; /* filesystem block size in bit shift */
6014373711SGao Xiang __u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */
6147e4937aSGao Xiang
624b66eb51SGao Xiang __le16 root_nid; /* nid of root directory */
634b66eb51SGao Xiang __le64 inos; /* total valid ino # (== f_files - f_favail) */
6447e4937aSGao Xiang
652833f4bbSGao Xiang __le64 build_time; /* compact inode time derivation */
662833f4bbSGao Xiang __le32 build_time_nsec; /* compact inode time derivation in ns scale */
674b66eb51SGao Xiang __le32 blocks; /* used for statfs */
684b66eb51SGao Xiang __le32 meta_blkaddr; /* start block address of metadata area */
694b66eb51SGao Xiang __le32 xattr_blkaddr; /* start block address of shared xattr area */
704b66eb51SGao Xiang __u8 uuid[16]; /* 128-bit uuid for volume */
714b66eb51SGao Xiang __u8 volume_name[16]; /* volume name */
72426a9308SGao Xiang __le32 feature_incompat;
7314373711SGao Xiang union {
7414373711SGao Xiang /* bitmap for available compression algorithms */
7514373711SGao Xiang __le16 available_compr_algs;
7614373711SGao Xiang /* customized sliding window size instead of 64k by default */
775d50538fSHuang Jianan __le16 lz4_max_distance;
7814373711SGao Xiang } __packed u1;
79dfeab2e9SGao Xiang __le16 extra_devices; /* # of devices besides the primary device */
80dfeab2e9SGao Xiang __le16 devt_slotoff; /* startoff = devt_slotoff * devt_slotsize */
81d3c4bdccSJingbo Xu __u8 dirblkbits; /* directory block size in bit shift */
82b3bfcb9dSJingbo Xu __u8 xattr_prefix_count; /* # of long xattr name prefixes */
83b3bfcb9dSJingbo Xu __le32 xattr_prefix_start; /* start of long xattr prefixes */
84b15b2e30SYue Hu __le64 packed_nid; /* nid of the special packed inode */
85*3f339920SJingbo Xu __u8 xattr_filter_reserved; /* reserved for xattr name filter */
86*3f339920SJingbo Xu __u8 reserved2[23];
87ed34aa4aSGao Xiang };
8847e4937aSGao Xiang
8947e4937aSGao Xiang /*
901c7f49a7SGao Xiang * EROFS inode datalayout (i_format in on-disk inode):
912833f4bbSGao Xiang * 0 - uncompressed flat inode without tail-packing inline data:
922833f4bbSGao Xiang * 1 - compressed inode with non-compact indexes:
932833f4bbSGao Xiang * 2 - uncompressed flat inode with tail-packing inline data:
942833f4bbSGao Xiang * 3 - compressed inode with compact indexes:
952833f4bbSGao Xiang * 4 - chunk-based inode with (optional) multi-device support:
962a9dc7a8SGao Xiang * 5~7 - reserved
9747e4937aSGao Xiang */
9847e4937aSGao Xiang enum {
9960a49ba8SGao Xiang EROFS_INODE_FLAT_PLAIN = 0,
1001c7f49a7SGao Xiang EROFS_INODE_COMPRESSED_FULL = 1,
10160a49ba8SGao Xiang EROFS_INODE_FLAT_INLINE = 2,
1021c7f49a7SGao Xiang EROFS_INODE_COMPRESSED_COMPACT = 3,
1032a9dc7a8SGao Xiang EROFS_INODE_CHUNK_BASED = 4,
1048a765682SGao Xiang EROFS_INODE_DATALAYOUT_MAX
10547e4937aSGao Xiang };
10647e4937aSGao Xiang
erofs_inode_is_data_compressed(unsigned int datamode)10747e4937aSGao Xiang static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
10847e4937aSGao Xiang {
1091c7f49a7SGao Xiang return datamode == EROFS_INODE_COMPRESSED_COMPACT ||
1101c7f49a7SGao Xiang datamode == EROFS_INODE_COMPRESSED_FULL;
11147e4937aSGao Xiang }
11247e4937aSGao Xiang
1132833f4bbSGao Xiang /* bit definitions of inode i_format */
114745ed7d7SGao Xiang #define EROFS_I_VERSION_MASK 0x01
115745ed7d7SGao Xiang #define EROFS_I_DATALAYOUT_MASK 0x07
11647e4937aSGao Xiang
11747e4937aSGao Xiang #define EROFS_I_VERSION_BIT 0
1188a765682SGao Xiang #define EROFS_I_DATALAYOUT_BIT 1
119745ed7d7SGao Xiang #define EROFS_I_ALL_BIT 4
12047e4937aSGao Xiang
121745ed7d7SGao Xiang #define EROFS_I_ALL ((1 << EROFS_I_ALL_BIT) - 1)
12224a806d8SGao Xiang
1232a9dc7a8SGao Xiang /* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */
1242a9dc7a8SGao Xiang #define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F
1252a9dc7a8SGao Xiang /* with chunk indexes or just a 4-byte blkaddr array */
1262a9dc7a8SGao Xiang #define EROFS_CHUNK_FORMAT_INDEXES 0x0020
1272a9dc7a8SGao Xiang
1282a9dc7a8SGao Xiang #define EROFS_CHUNK_FORMAT_ALL \
1292a9dc7a8SGao Xiang (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES)
1302a9dc7a8SGao Xiang
1311c7f49a7SGao Xiang /* 32-byte on-disk inode */
1321c7f49a7SGao Xiang #define EROFS_INODE_LAYOUT_COMPACT 0
1331c7f49a7SGao Xiang /* 64-byte on-disk inode */
1341c7f49a7SGao Xiang #define EROFS_INODE_LAYOUT_EXTENDED 1
1351c7f49a7SGao Xiang
1362a9dc7a8SGao Xiang struct erofs_inode_chunk_info {
1372a9dc7a8SGao Xiang __le16 format; /* chunk blkbits, etc. */
1382a9dc7a8SGao Xiang __le16 reserved;
1392a9dc7a8SGao Xiang };
1402a9dc7a8SGao Xiang
1411c7f49a7SGao Xiang union erofs_inode_i_u {
1421c7f49a7SGao Xiang /* total compressed blocks for compressed inodes */
1431c7f49a7SGao Xiang __le32 compressed_blocks;
1441c7f49a7SGao Xiang
1451c7f49a7SGao Xiang /* block address for uncompressed flat inodes */
1461c7f49a7SGao Xiang __le32 raw_blkaddr;
1471c7f49a7SGao Xiang
1481c7f49a7SGao Xiang /* for device files, used to indicate old/new device # */
1491c7f49a7SGao Xiang __le32 rdev;
1501c7f49a7SGao Xiang
1511c7f49a7SGao Xiang /* for chunk-based files, it contains the summary info */
1521c7f49a7SGao Xiang struct erofs_inode_chunk_info c;
1531c7f49a7SGao Xiang };
1541c7f49a7SGao Xiang
1554b66eb51SGao Xiang /* 32-byte reduced form of an ondisk inode */
1568a765682SGao Xiang struct erofs_inode_compact {
1578a765682SGao Xiang __le16 i_format; /* inode format hints */
15847e4937aSGao Xiang
15947e4937aSGao Xiang /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */
1604b66eb51SGao Xiang __le16 i_xattr_icount;
1614b66eb51SGao Xiang __le16 i_mode;
1624b66eb51SGao Xiang __le16 i_nlink;
1634b66eb51SGao Xiang __le32 i_size;
1644b66eb51SGao Xiang __le32 i_reserved;
1651c7f49a7SGao Xiang union erofs_inode_i_u i_u;
16647e4937aSGao Xiang
1674b66eb51SGao Xiang __le32 i_ino; /* only used for 32-bit stat compatibility */
1684b66eb51SGao Xiang __le16 i_uid;
1694b66eb51SGao Xiang __le16 i_gid;
1704b66eb51SGao Xiang __le32 i_reserved2;
171ed34aa4aSGao Xiang };
17247e4937aSGao Xiang
1734b66eb51SGao Xiang /* 64-byte complete form of an ondisk inode */
1748a765682SGao Xiang struct erofs_inode_extended {
1758a765682SGao Xiang __le16 i_format; /* inode format hints */
17647e4937aSGao Xiang
17747e4937aSGao Xiang /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */
1784b66eb51SGao Xiang __le16 i_xattr_icount;
1794b66eb51SGao Xiang __le16 i_mode;
1804b66eb51SGao Xiang __le16 i_reserved;
1814b66eb51SGao Xiang __le64 i_size;
1821c7f49a7SGao Xiang union erofs_inode_i_u i_u;
18347e4937aSGao Xiang
1841c7f49a7SGao Xiang __le32 i_ino; /* only used for 32-bit stat compatibility */
1854b66eb51SGao Xiang __le32 i_uid;
1864b66eb51SGao Xiang __le32 i_gid;
187a1108dcdSDavid Anderson __le64 i_mtime;
188a1108dcdSDavid Anderson __le32 i_mtime_nsec;
1894b66eb51SGao Xiang __le32 i_nlink;
1904b66eb51SGao Xiang __u8 i_reserved2[16];
191ed34aa4aSGao Xiang };
19247e4937aSGao Xiang
19347e4937aSGao Xiang /*
19447e4937aSGao Xiang * inline xattrs (n == i_xattr_icount):
19547e4937aSGao Xiang * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes
19647e4937aSGao Xiang * 12 bytes / \
19747e4937aSGao Xiang * / \
19847e4937aSGao Xiang * /-----------------------\
19947e4937aSGao Xiang * | erofs_xattr_entries+ |
20047e4937aSGao Xiang * +-----------------------+
20147e4937aSGao Xiang * inline xattrs must starts in erofs_xattr_ibody_header,
20247e4937aSGao Xiang * for read-only fs, no need to introduce h_refcount
20347e4937aSGao Xiang */
20447e4937aSGao Xiang struct erofs_xattr_ibody_header {
205*3f339920SJingbo Xu __le32 h_name_filter; /* bit value 1 indicates not-present */
20647e4937aSGao Xiang __u8 h_shared_count;
20747e4937aSGao Xiang __u8 h_reserved2[7];
2087acc3d1aSGao Xiang __le32 h_shared_xattrs[]; /* shared xattr id array */
209ed34aa4aSGao Xiang };
21047e4937aSGao Xiang
21147e4937aSGao Xiang /* Name indexes */
21247e4937aSGao Xiang #define EROFS_XATTR_INDEX_USER 1
21347e4937aSGao Xiang #define EROFS_XATTR_INDEX_POSIX_ACL_ACCESS 2
21447e4937aSGao Xiang #define EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT 3
21547e4937aSGao Xiang #define EROFS_XATTR_INDEX_TRUSTED 4
21647e4937aSGao Xiang #define EROFS_XATTR_INDEX_LUSTRE 5
21747e4937aSGao Xiang #define EROFS_XATTR_INDEX_SECURITY 6
21847e4937aSGao Xiang
219b3bfcb9dSJingbo Xu /*
220b3bfcb9dSJingbo Xu * bit 7 of e_name_index is set when it refers to a long xattr name prefix,
221b3bfcb9dSJingbo Xu * while the remained lower bits represent the index of the prefix.
222b3bfcb9dSJingbo Xu */
223b3bfcb9dSJingbo Xu #define EROFS_XATTR_LONG_PREFIX 0x80
224b3bfcb9dSJingbo Xu #define EROFS_XATTR_LONG_PREFIX_MASK 0x7f
225b3bfcb9dSJingbo Xu
226*3f339920SJingbo Xu #define EROFS_XATTR_FILTER_BITS 32
227*3f339920SJingbo Xu #define EROFS_XATTR_FILTER_DEFAULT UINT32_MAX
228*3f339920SJingbo Xu #define EROFS_XATTR_FILTER_SEED 0x25BBE08F
229*3f339920SJingbo Xu
23047e4937aSGao Xiang /* xattr entry (for both inline & shared xattrs) */
23147e4937aSGao Xiang struct erofs_xattr_entry {
23247e4937aSGao Xiang __u8 e_name_len; /* length of name */
23347e4937aSGao Xiang __u8 e_name_index; /* attribute name index */
23447e4937aSGao Xiang __le16 e_value_size; /* size of attribute value */
23547e4937aSGao Xiang /* followed by e_name and e_value */
2367acc3d1aSGao Xiang char e_name[]; /* attribute name */
237ed34aa4aSGao Xiang };
23847e4937aSGao Xiang
239b3bfcb9dSJingbo Xu /* long xattr name prefix */
240b3bfcb9dSJingbo Xu struct erofs_xattr_long_prefix {
241b3bfcb9dSJingbo Xu __u8 base_index; /* short xattr name prefix index */
242b3bfcb9dSJingbo Xu char infix[]; /* infix apart from short prefix */
243b3bfcb9dSJingbo Xu };
244b3bfcb9dSJingbo Xu
erofs_xattr_ibody_size(__le16 i_xattr_icount)245b6796abdSGao Xiang static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount)
246b6796abdSGao Xiang {
247b6796abdSGao Xiang if (!i_xattr_icount)
248b6796abdSGao Xiang return 0;
249b6796abdSGao Xiang
250b6796abdSGao Xiang return sizeof(struct erofs_xattr_ibody_header) +
251b6796abdSGao Xiang sizeof(__u32) * (le16_to_cpu(i_xattr_icount) - 1);
252b6796abdSGao Xiang }
25347e4937aSGao Xiang
25447e4937aSGao Xiang #define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry))
255b6796abdSGao Xiang
erofs_xattr_entry_size(struct erofs_xattr_entry * e)256b6796abdSGao Xiang static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e)
257b6796abdSGao Xiang {
258b6796abdSGao Xiang return EROFS_XATTR_ALIGN(sizeof(struct erofs_xattr_entry) +
259b6796abdSGao Xiang e->e_name_len + le16_to_cpu(e->e_value_size));
260b6796abdSGao Xiang }
26147e4937aSGao Xiang
2622a9dc7a8SGao Xiang /* represent a zeroed chunk (hole) */
2632a9dc7a8SGao Xiang #define EROFS_NULL_ADDR -1
2642a9dc7a8SGao Xiang
2652a9dc7a8SGao Xiang /* 4-byte block address array */
2662a9dc7a8SGao Xiang #define EROFS_BLOCK_MAP_ENTRY_SIZE sizeof(__le32)
2672a9dc7a8SGao Xiang
2682a9dc7a8SGao Xiang /* 8-byte inode chunk indexes */
2692a9dc7a8SGao Xiang struct erofs_inode_chunk_index {
2702a9dc7a8SGao Xiang __le16 advise; /* always 0, don't care for now */
271dfeab2e9SGao Xiang __le16 device_id; /* back-end storage id (with bits masked) */
2722a9dc7a8SGao Xiang __le32 blkaddr; /* start block address of this inode chunk */
2732a9dc7a8SGao Xiang };
2742a9dc7a8SGao Xiang
2751c7f49a7SGao Xiang /* dirent sorts in alphabet order, thus we can do binary search */
2761c7f49a7SGao Xiang struct erofs_dirent {
2771c7f49a7SGao Xiang __le64 nid; /* node number */
2781c7f49a7SGao Xiang __le16 nameoff; /* start offset of file name */
2791c7f49a7SGao Xiang __u8 file_type; /* file type */
2801c7f49a7SGao Xiang __u8 reserved; /* reserved */
2811c7f49a7SGao Xiang } __packed;
2821c7f49a7SGao Xiang
2831c7f49a7SGao Xiang /*
2841c7f49a7SGao Xiang * EROFS file types should match generic FT_* types and
2851c7f49a7SGao Xiang * it seems no need to add BUILD_BUG_ONs since potential
2861c7f49a7SGao Xiang * unmatchness will break other fses as well...
2871c7f49a7SGao Xiang */
2881c7f49a7SGao Xiang
2891c7f49a7SGao Xiang #define EROFS_NAME_LEN 255
2901c7f49a7SGao Xiang
2919f6cc76eSGao Xiang /* maximum supported size of a physical compression cluster */
2929f6cc76eSGao Xiang #define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024)
2939f6cc76eSGao Xiang
294ea559e7bSGao Xiang /* available compression algorithm types (for h_algorithmtype) */
29547e4937aSGao Xiang enum {
29660a49ba8SGao Xiang Z_EROFS_COMPRESSION_LZ4 = 0,
297622ceaddSGao Xiang Z_EROFS_COMPRESSION_LZMA = 1,
298ffa09b3bSGao Xiang Z_EROFS_COMPRESSION_DEFLATE = 2,
29947e4937aSGao Xiang Z_EROFS_COMPRESSION_MAX
30047e4937aSGao Xiang };
301622ceaddSGao Xiang #define Z_EROFS_ALL_COMPR_ALGS ((1 << Z_EROFS_COMPRESSION_MAX) - 1)
30247e4937aSGao Xiang
30346249cdeSGao Xiang /* 14 bytes (+ length field = 16 bytes) */
30446249cdeSGao Xiang struct z_erofs_lz4_cfgs {
30546249cdeSGao Xiang __le16 max_distance;
3065404c330SGao Xiang __le16 max_pclusterblks;
3075404c330SGao Xiang u8 reserved[10];
30846249cdeSGao Xiang } __packed;
30946249cdeSGao Xiang
310622ceaddSGao Xiang /* 14 bytes (+ length field = 16 bytes) */
311622ceaddSGao Xiang struct z_erofs_lzma_cfgs {
312622ceaddSGao Xiang __le32 dict_size;
313622ceaddSGao Xiang __le16 format;
314622ceaddSGao Xiang u8 reserved[8];
315622ceaddSGao Xiang } __packed;
316622ceaddSGao Xiang
317622ceaddSGao Xiang #define Z_EROFS_LZMA_MAX_DICT_SIZE (8 * Z_EROFS_PCLUSTER_MAX_SIZE)
318622ceaddSGao Xiang
319ffa09b3bSGao Xiang /* 6 bytes (+ length field = 8 bytes) */
320ffa09b3bSGao Xiang struct z_erofs_deflate_cfgs {
321ffa09b3bSGao Xiang u8 windowbits; /* 8..15 for DEFLATE */
322ffa09b3bSGao Xiang u8 reserved[5];
323ffa09b3bSGao Xiang } __packed;
324ffa09b3bSGao Xiang
32547e4937aSGao Xiang /*
32647e4937aSGao Xiang * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on)
32747e4937aSGao Xiang * e.g. for 4k logical cluster size, 4B if compacted 2B is off;
32847e4937aSGao Xiang * (4B) + 2B + (4B) if compacted 2B is on.
3295404c330SGao Xiang * bit 1 : HEAD1 big pcluster (0 - off; 1 - on)
3305404c330SGao Xiang * bit 2 : HEAD2 big pcluster (0 - off; 1 - on)
331ab92184fSYue Hu * bit 3 : tailpacking inline pcluster (0 - off; 1 - on)
332fdffc091SYue Hu * bit 4 : interlaced plain pcluster (0 - off; 1 - on)
333b15b2e30SYue Hu * bit 5 : fragment pcluster (0 - off; 1 - on)
33447e4937aSGao Xiang */
3355404c330SGao Xiang #define Z_EROFS_ADVISE_COMPACTED_2B 0x0001
3365404c330SGao Xiang #define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002
3375404c330SGao Xiang #define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004
338ab92184fSYue Hu #define Z_EROFS_ADVISE_INLINE_PCLUSTER 0x0008
339fdffc091SYue Hu #define Z_EROFS_ADVISE_INTERLACED_PCLUSTER 0x0010
340b15b2e30SYue Hu #define Z_EROFS_ADVISE_FRAGMENT_PCLUSTER 0x0020
34147e4937aSGao Xiang
342b15b2e30SYue Hu #define Z_EROFS_FRAGMENT_INODE_BIT 7
34347e4937aSGao Xiang struct z_erofs_map_header {
344b15b2e30SYue Hu union {
345b15b2e30SYue Hu /* fragment data offset in the packed inode */
346b15b2e30SYue Hu __le32 h_fragmentoff;
347b15b2e30SYue Hu struct {
348ab92184fSYue Hu __le16 h_reserved1;
349ab92184fSYue Hu /* indicates the encoded size of tailpacking data */
350ab92184fSYue Hu __le16 h_idata_size;
351b15b2e30SYue Hu };
352b15b2e30SYue Hu };
35347e4937aSGao Xiang __le16 h_advise;
35447e4937aSGao Xiang /*
35547e4937aSGao Xiang * bit 0-3 : algorithm type of head 1 (logical cluster type 01);
35647e4937aSGao Xiang * bit 4-7 : algorithm type of head 2 (logical cluster type 11).
35747e4937aSGao Xiang */
35847e4937aSGao Xiang __u8 h_algorithmtype;
35947e4937aSGao Xiang /*
36047e4937aSGao Xiang * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096;
361b15b2e30SYue Hu * bit 3-6 : reserved;
362b15b2e30SYue Hu * bit 7 : move the whole file into packed inode or not.
36347e4937aSGao Xiang */
36447e4937aSGao Xiang __u8 h_clusterbits;
36547e4937aSGao Xiang };
36647e4937aSGao Xiang
36747e4937aSGao Xiang /*
3681c7f49a7SGao Xiang * On-disk logical cluster type:
36972bb5262SGao Xiang * 0 - literal (uncompressed) lcluster
37072bb5262SGao Xiang * 1,3 - compressed lcluster (for HEAD lclusters)
37172bb5262SGao Xiang * 2 - compressed lcluster (for NONHEAD lclusters)
37247e4937aSGao Xiang *
37347e4937aSGao Xiang * In detail,
37472bb5262SGao Xiang * 0 - literal (uncompressed) lcluster,
37547e4937aSGao Xiang * di_advise = 0
37672bb5262SGao Xiang * di_clusterofs = the literal data offset of the lcluster
37772bb5262SGao Xiang * di_blkaddr = the blkaddr of the literal pcluster
37847e4937aSGao Xiang *
37972bb5262SGao Xiang * 1,3 - compressed lcluster (for HEAD lclusters)
38072bb5262SGao Xiang * di_advise = 1 or 3
38172bb5262SGao Xiang * di_clusterofs = the decompressed data offset of the lcluster
38272bb5262SGao Xiang * di_blkaddr = the blkaddr of the compressed pcluster
38347e4937aSGao Xiang *
38472bb5262SGao Xiang * 2 - compressed lcluster (for NONHEAD lclusters)
38547e4937aSGao Xiang * di_advise = 2
38647e4937aSGao Xiang * di_clusterofs =
38772bb5262SGao Xiang * the decompressed data offset in its own HEAD lcluster
38872bb5262SGao Xiang * di_u.delta[0] = distance to this HEAD lcluster
38972bb5262SGao Xiang * di_u.delta[1] = distance to the next HEAD lcluster
39047e4937aSGao Xiang */
39147e4937aSGao Xiang enum {
3921c7f49a7SGao Xiang Z_EROFS_LCLUSTER_TYPE_PLAIN = 0,
3931c7f49a7SGao Xiang Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1,
3941c7f49a7SGao Xiang Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2,
3951c7f49a7SGao Xiang Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3,
3961c7f49a7SGao Xiang Z_EROFS_LCLUSTER_TYPE_MAX
39747e4937aSGao Xiang };
39847e4937aSGao Xiang
3991c7f49a7SGao Xiang #define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2
4001c7f49a7SGao Xiang #define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0
40147e4937aSGao Xiang
4025c2a6425SGao Xiang /* (noncompact only, HEAD) This pcluster refers to partial decompressed data */
4031c7f49a7SGao Xiang #define Z_EROFS_LI_PARTIAL_REF (1 << 15)
4045c2a6425SGao Xiang
4055404c330SGao Xiang /*
4065404c330SGao Xiang * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the
4075404c330SGao Xiang * compressed block count of a compressed extent (in logical clusters, aka.
4085404c330SGao Xiang * block count of a pcluster).
4095404c330SGao Xiang */
4101c7f49a7SGao Xiang #define Z_EROFS_LI_D0_CBLKCNT (1 << 11)
4115404c330SGao Xiang
4121c7f49a7SGao Xiang struct z_erofs_lcluster_index {
41347e4937aSGao Xiang __le16 di_advise;
4142833f4bbSGao Xiang /* where to decompress in the head lcluster */
41547e4937aSGao Xiang __le16 di_clusterofs;
41647e4937aSGao Xiang
41747e4937aSGao Xiang union {
4182833f4bbSGao Xiang /* for the HEAD lclusters */
41947e4937aSGao Xiang __le32 blkaddr;
42047e4937aSGao Xiang /*
4212833f4bbSGao Xiang * for the NONHEAD lclusters
4222833f4bbSGao Xiang * [0] - distance to its HEAD lcluster
4232833f4bbSGao Xiang * [1] - distance to the next HEAD lcluster
42447e4937aSGao Xiang */
42547e4937aSGao Xiang __le16 delta[2];
426ed34aa4aSGao Xiang } di_u;
427ed34aa4aSGao Xiang };
42847e4937aSGao Xiang
4291c7f49a7SGao Xiang #define Z_EROFS_FULL_INDEX_ALIGN(end) \
4301c7f49a7SGao Xiang (ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8)
43147e4937aSGao Xiang
43247e4937aSGao Xiang /* check the EROFS on-disk layout strictly at compile time */
erofs_check_ondisk_layout_definitions(void)43347e4937aSGao Xiang static inline void erofs_check_ondisk_layout_definitions(void)
43447e4937aSGao Xiang {
435b15b2e30SYue Hu const __le64 fmh = *(__le64 *)&(struct z_erofs_map_header) {
436b15b2e30SYue Hu .h_clusterbits = 1 << Z_EROFS_FRAGMENT_INODE_BIT
437b15b2e30SYue Hu };
438b15b2e30SYue Hu
43947e4937aSGao Xiang BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128);
4408a765682SGao Xiang BUILD_BUG_ON(sizeof(struct erofs_inode_compact) != 32);
4418a765682SGao Xiang BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64);
44247e4937aSGao Xiang BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12);
44347e4937aSGao Xiang BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4);
4442a9dc7a8SGao Xiang BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4);
4452a9dc7a8SGao Xiang BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8);
44647e4937aSGao Xiang BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8);
4471c7f49a7SGao Xiang BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8);
44847e4937aSGao Xiang BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12);
4492a9dc7a8SGao Xiang /* keep in sync between 2 index structures for better extendibility */
4502a9dc7a8SGao Xiang BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) !=
4511c7f49a7SGao Xiang sizeof(struct z_erofs_lcluster_index));
452dfeab2e9SGao Xiang BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128);
45347e4937aSGao Xiang
4541c7f49a7SGao Xiang BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) <
4551c7f49a7SGao Xiang Z_EROFS_LCLUSTER_TYPE_MAX - 1);
456b15b2e30SYue Hu /* exclude old compiler versions like gcc 7.5.0 */
457b15b2e30SYue Hu BUILD_BUG_ON(__builtin_constant_p(fmh) ?
458b15b2e30SYue Hu fmh != cpu_to_le64(1ULL << 63) : 0);
45947e4937aSGao Xiang }
46047e4937aSGao Xiang
46147e4937aSGao Xiang #endif
462