xref: /openbmc/linux/fs/erofs/erofs_fs.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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