162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * EROFS (Enhanced ROM File System) on-disk format definition 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017-2018 HUAWEI, Inc. 662306a36Sopenharmony_ci * https://www.huawei.com/ 762306a36Sopenharmony_ci * Copyright (C) 2021, Alibaba Cloud 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#ifndef __EROFS_FS_H 1062306a36Sopenharmony_ci#define __EROFS_FS_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define EROFS_SUPER_OFFSET 1024 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 1562306a36Sopenharmony_ci#define EROFS_FEATURE_COMPAT_MTIME 0x00000002 1662306a36Sopenharmony_ci#define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should 2062306a36Sopenharmony_ci * be incompatible with this kernel version. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_ZERO_PADDING 0x00000001 2362306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002 2462306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002 2562306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE 0x00000004 2662306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_DEVICE_TABLE 0x00000008 2762306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 0x00000008 2862306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_ZTAILPACKING 0x00000010 2962306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020 3062306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020 3162306a36Sopenharmony_ci#define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040 3262306a36Sopenharmony_ci#define EROFS_ALL_FEATURE_INCOMPAT \ 3362306a36Sopenharmony_ci (EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \ 3462306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \ 3562306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \ 3662306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_CHUNKED_FILE | \ 3762306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_DEVICE_TABLE | \ 3862306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \ 3962306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \ 4062306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_FRAGMENTS | \ 4162306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_DEDUPE | \ 4262306a36Sopenharmony_ci EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define EROFS_SB_EXTSLOT_SIZE 16 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct erofs_deviceslot { 4762306a36Sopenharmony_ci u8 tag[64]; /* digest(sha256), etc. */ 4862306a36Sopenharmony_ci __le32 blocks; /* total fs blocks of this device */ 4962306a36Sopenharmony_ci __le32 mapped_blkaddr; /* map starting at mapped_blkaddr */ 5062306a36Sopenharmony_ci u8 reserved[56]; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci#define EROFS_DEVT_SLOT_SIZE sizeof(struct erofs_deviceslot) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* erofs on-disk super block (currently 128 bytes) */ 5562306a36Sopenharmony_cistruct erofs_super_block { 5662306a36Sopenharmony_ci __le32 magic; /* file system magic number */ 5762306a36Sopenharmony_ci __le32 checksum; /* crc32c(super_block) */ 5862306a36Sopenharmony_ci __le32 feature_compat; 5962306a36Sopenharmony_ci __u8 blkszbits; /* filesystem block size in bit shift */ 6062306a36Sopenharmony_ci __u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci __le16 root_nid; /* nid of root directory */ 6362306a36Sopenharmony_ci __le64 inos; /* total valid ino # (== f_files - f_favail) */ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci __le64 build_time; /* compact inode time derivation */ 6662306a36Sopenharmony_ci __le32 build_time_nsec; /* compact inode time derivation in ns scale */ 6762306a36Sopenharmony_ci __le32 blocks; /* used for statfs */ 6862306a36Sopenharmony_ci __le32 meta_blkaddr; /* start block address of metadata area */ 6962306a36Sopenharmony_ci __le32 xattr_blkaddr; /* start block address of shared xattr area */ 7062306a36Sopenharmony_ci __u8 uuid[16]; /* 128-bit uuid for volume */ 7162306a36Sopenharmony_ci __u8 volume_name[16]; /* volume name */ 7262306a36Sopenharmony_ci __le32 feature_incompat; 7362306a36Sopenharmony_ci union { 7462306a36Sopenharmony_ci /* bitmap for available compression algorithms */ 7562306a36Sopenharmony_ci __le16 available_compr_algs; 7662306a36Sopenharmony_ci /* customized sliding window size instead of 64k by default */ 7762306a36Sopenharmony_ci __le16 lz4_max_distance; 7862306a36Sopenharmony_ci } __packed u1; 7962306a36Sopenharmony_ci __le16 extra_devices; /* # of devices besides the primary device */ 8062306a36Sopenharmony_ci __le16 devt_slotoff; /* startoff = devt_slotoff * devt_slotsize */ 8162306a36Sopenharmony_ci __u8 dirblkbits; /* directory block size in bit shift */ 8262306a36Sopenharmony_ci __u8 xattr_prefix_count; /* # of long xattr name prefixes */ 8362306a36Sopenharmony_ci __le32 xattr_prefix_start; /* start of long xattr prefixes */ 8462306a36Sopenharmony_ci __le64 packed_nid; /* nid of the special packed inode */ 8562306a36Sopenharmony_ci __u8 xattr_filter_reserved; /* reserved for xattr name filter */ 8662306a36Sopenharmony_ci __u8 reserved2[23]; 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* 9062306a36Sopenharmony_ci * EROFS inode datalayout (i_format in on-disk inode): 9162306a36Sopenharmony_ci * 0 - uncompressed flat inode without tail-packing inline data: 9262306a36Sopenharmony_ci * 1 - compressed inode with non-compact indexes: 9362306a36Sopenharmony_ci * 2 - uncompressed flat inode with tail-packing inline data: 9462306a36Sopenharmony_ci * 3 - compressed inode with compact indexes: 9562306a36Sopenharmony_ci * 4 - chunk-based inode with (optional) multi-device support: 9662306a36Sopenharmony_ci * 5~7 - reserved 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_cienum { 9962306a36Sopenharmony_ci EROFS_INODE_FLAT_PLAIN = 0, 10062306a36Sopenharmony_ci EROFS_INODE_COMPRESSED_FULL = 1, 10162306a36Sopenharmony_ci EROFS_INODE_FLAT_INLINE = 2, 10262306a36Sopenharmony_ci EROFS_INODE_COMPRESSED_COMPACT = 3, 10362306a36Sopenharmony_ci EROFS_INODE_CHUNK_BASED = 4, 10462306a36Sopenharmony_ci EROFS_INODE_DATALAYOUT_MAX 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic inline bool erofs_inode_is_data_compressed(unsigned int datamode) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci return datamode == EROFS_INODE_COMPRESSED_COMPACT || 11062306a36Sopenharmony_ci datamode == EROFS_INODE_COMPRESSED_FULL; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* bit definitions of inode i_format */ 11462306a36Sopenharmony_ci#define EROFS_I_VERSION_MASK 0x01 11562306a36Sopenharmony_ci#define EROFS_I_DATALAYOUT_MASK 0x07 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define EROFS_I_VERSION_BIT 0 11862306a36Sopenharmony_ci#define EROFS_I_DATALAYOUT_BIT 1 11962306a36Sopenharmony_ci#define EROFS_I_ALL_BIT 4 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define EROFS_I_ALL ((1 << EROFS_I_ALL_BIT) - 1) 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */ 12462306a36Sopenharmony_ci#define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F 12562306a36Sopenharmony_ci/* with chunk indexes or just a 4-byte blkaddr array */ 12662306a36Sopenharmony_ci#define EROFS_CHUNK_FORMAT_INDEXES 0x0020 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define EROFS_CHUNK_FORMAT_ALL \ 12962306a36Sopenharmony_ci (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES) 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* 32-byte on-disk inode */ 13262306a36Sopenharmony_ci#define EROFS_INODE_LAYOUT_COMPACT 0 13362306a36Sopenharmony_ci/* 64-byte on-disk inode */ 13462306a36Sopenharmony_ci#define EROFS_INODE_LAYOUT_EXTENDED 1 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistruct erofs_inode_chunk_info { 13762306a36Sopenharmony_ci __le16 format; /* chunk blkbits, etc. */ 13862306a36Sopenharmony_ci __le16 reserved; 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciunion erofs_inode_i_u { 14262306a36Sopenharmony_ci /* total compressed blocks for compressed inodes */ 14362306a36Sopenharmony_ci __le32 compressed_blocks; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci /* block address for uncompressed flat inodes */ 14662306a36Sopenharmony_ci __le32 raw_blkaddr; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* for device files, used to indicate old/new device # */ 14962306a36Sopenharmony_ci __le32 rdev; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* for chunk-based files, it contains the summary info */ 15262306a36Sopenharmony_ci struct erofs_inode_chunk_info c; 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* 32-byte reduced form of an ondisk inode */ 15662306a36Sopenharmony_cistruct erofs_inode_compact { 15762306a36Sopenharmony_ci __le16 i_format; /* inode format hints */ 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ 16062306a36Sopenharmony_ci __le16 i_xattr_icount; 16162306a36Sopenharmony_ci __le16 i_mode; 16262306a36Sopenharmony_ci __le16 i_nlink; 16362306a36Sopenharmony_ci __le32 i_size; 16462306a36Sopenharmony_ci __le32 i_reserved; 16562306a36Sopenharmony_ci union erofs_inode_i_u i_u; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci __le32 i_ino; /* only used for 32-bit stat compatibility */ 16862306a36Sopenharmony_ci __le16 i_uid; 16962306a36Sopenharmony_ci __le16 i_gid; 17062306a36Sopenharmony_ci __le32 i_reserved2; 17162306a36Sopenharmony_ci}; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci/* 64-byte complete form of an ondisk inode */ 17462306a36Sopenharmony_cistruct erofs_inode_extended { 17562306a36Sopenharmony_ci __le16 i_format; /* inode format hints */ 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ 17862306a36Sopenharmony_ci __le16 i_xattr_icount; 17962306a36Sopenharmony_ci __le16 i_mode; 18062306a36Sopenharmony_ci __le16 i_reserved; 18162306a36Sopenharmony_ci __le64 i_size; 18262306a36Sopenharmony_ci union erofs_inode_i_u i_u; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci __le32 i_ino; /* only used for 32-bit stat compatibility */ 18562306a36Sopenharmony_ci __le32 i_uid; 18662306a36Sopenharmony_ci __le32 i_gid; 18762306a36Sopenharmony_ci __le64 i_mtime; 18862306a36Sopenharmony_ci __le32 i_mtime_nsec; 18962306a36Sopenharmony_ci __le32 i_nlink; 19062306a36Sopenharmony_ci __u8 i_reserved2[16]; 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* 19462306a36Sopenharmony_ci * inline xattrs (n == i_xattr_icount): 19562306a36Sopenharmony_ci * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes 19662306a36Sopenharmony_ci * 12 bytes / \ 19762306a36Sopenharmony_ci * / \ 19862306a36Sopenharmony_ci * /-----------------------\ 19962306a36Sopenharmony_ci * | erofs_xattr_entries+ | 20062306a36Sopenharmony_ci * +-----------------------+ 20162306a36Sopenharmony_ci * inline xattrs must starts in erofs_xattr_ibody_header, 20262306a36Sopenharmony_ci * for read-only fs, no need to introduce h_refcount 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_cistruct erofs_xattr_ibody_header { 20562306a36Sopenharmony_ci __le32 h_name_filter; /* bit value 1 indicates not-present */ 20662306a36Sopenharmony_ci __u8 h_shared_count; 20762306a36Sopenharmony_ci __u8 h_reserved2[7]; 20862306a36Sopenharmony_ci __le32 h_shared_xattrs[]; /* shared xattr id array */ 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* Name indexes */ 21262306a36Sopenharmony_ci#define EROFS_XATTR_INDEX_USER 1 21362306a36Sopenharmony_ci#define EROFS_XATTR_INDEX_POSIX_ACL_ACCESS 2 21462306a36Sopenharmony_ci#define EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 21562306a36Sopenharmony_ci#define EROFS_XATTR_INDEX_TRUSTED 4 21662306a36Sopenharmony_ci#define EROFS_XATTR_INDEX_LUSTRE 5 21762306a36Sopenharmony_ci#define EROFS_XATTR_INDEX_SECURITY 6 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/* 22062306a36Sopenharmony_ci * bit 7 of e_name_index is set when it refers to a long xattr name prefix, 22162306a36Sopenharmony_ci * while the remained lower bits represent the index of the prefix. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci#define EROFS_XATTR_LONG_PREFIX 0x80 22462306a36Sopenharmony_ci#define EROFS_XATTR_LONG_PREFIX_MASK 0x7f 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci#define EROFS_XATTR_FILTER_BITS 32 22762306a36Sopenharmony_ci#define EROFS_XATTR_FILTER_DEFAULT UINT32_MAX 22862306a36Sopenharmony_ci#define EROFS_XATTR_FILTER_SEED 0x25BBE08F 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* xattr entry (for both inline & shared xattrs) */ 23162306a36Sopenharmony_cistruct erofs_xattr_entry { 23262306a36Sopenharmony_ci __u8 e_name_len; /* length of name */ 23362306a36Sopenharmony_ci __u8 e_name_index; /* attribute name index */ 23462306a36Sopenharmony_ci __le16 e_value_size; /* size of attribute value */ 23562306a36Sopenharmony_ci /* followed by e_name and e_value */ 23662306a36Sopenharmony_ci char e_name[]; /* attribute name */ 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci/* long xattr name prefix */ 24062306a36Sopenharmony_cistruct erofs_xattr_long_prefix { 24162306a36Sopenharmony_ci __u8 base_index; /* short xattr name prefix index */ 24262306a36Sopenharmony_ci char infix[]; /* infix apart from short prefix */ 24362306a36Sopenharmony_ci}; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci if (!i_xattr_icount) 24862306a36Sopenharmony_ci return 0; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci return sizeof(struct erofs_xattr_ibody_header) + 25162306a36Sopenharmony_ci sizeof(__u32) * (le16_to_cpu(i_xattr_icount) - 1); 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry)) 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci return EROFS_XATTR_ALIGN(sizeof(struct erofs_xattr_entry) + 25962306a36Sopenharmony_ci e->e_name_len + le16_to_cpu(e->e_value_size)); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci/* represent a zeroed chunk (hole) */ 26362306a36Sopenharmony_ci#define EROFS_NULL_ADDR -1 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/* 4-byte block address array */ 26662306a36Sopenharmony_ci#define EROFS_BLOCK_MAP_ENTRY_SIZE sizeof(__le32) 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci/* 8-byte inode chunk indexes */ 26962306a36Sopenharmony_cistruct erofs_inode_chunk_index { 27062306a36Sopenharmony_ci __le16 advise; /* always 0, don't care for now */ 27162306a36Sopenharmony_ci __le16 device_id; /* back-end storage id (with bits masked) */ 27262306a36Sopenharmony_ci __le32 blkaddr; /* start block address of this inode chunk */ 27362306a36Sopenharmony_ci}; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/* dirent sorts in alphabet order, thus we can do binary search */ 27662306a36Sopenharmony_cistruct erofs_dirent { 27762306a36Sopenharmony_ci __le64 nid; /* node number */ 27862306a36Sopenharmony_ci __le16 nameoff; /* start offset of file name */ 27962306a36Sopenharmony_ci __u8 file_type; /* file type */ 28062306a36Sopenharmony_ci __u8 reserved; /* reserved */ 28162306a36Sopenharmony_ci} __packed; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/* 28462306a36Sopenharmony_ci * EROFS file types should match generic FT_* types and 28562306a36Sopenharmony_ci * it seems no need to add BUILD_BUG_ONs since potential 28662306a36Sopenharmony_ci * unmatchness will break other fses as well... 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci#define EROFS_NAME_LEN 255 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci/* maximum supported size of a physical compression cluster */ 29262306a36Sopenharmony_ci#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024) 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci/* available compression algorithm types (for h_algorithmtype) */ 29562306a36Sopenharmony_cienum { 29662306a36Sopenharmony_ci Z_EROFS_COMPRESSION_LZ4 = 0, 29762306a36Sopenharmony_ci Z_EROFS_COMPRESSION_LZMA = 1, 29862306a36Sopenharmony_ci Z_EROFS_COMPRESSION_DEFLATE = 2, 29962306a36Sopenharmony_ci Z_EROFS_COMPRESSION_MAX 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci#define Z_EROFS_ALL_COMPR_ALGS ((1 << Z_EROFS_COMPRESSION_MAX) - 1) 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/* 14 bytes (+ length field = 16 bytes) */ 30462306a36Sopenharmony_cistruct z_erofs_lz4_cfgs { 30562306a36Sopenharmony_ci __le16 max_distance; 30662306a36Sopenharmony_ci __le16 max_pclusterblks; 30762306a36Sopenharmony_ci u8 reserved[10]; 30862306a36Sopenharmony_ci} __packed; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci/* 14 bytes (+ length field = 16 bytes) */ 31162306a36Sopenharmony_cistruct z_erofs_lzma_cfgs { 31262306a36Sopenharmony_ci __le32 dict_size; 31362306a36Sopenharmony_ci __le16 format; 31462306a36Sopenharmony_ci u8 reserved[8]; 31562306a36Sopenharmony_ci} __packed; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci#define Z_EROFS_LZMA_MAX_DICT_SIZE (8 * Z_EROFS_PCLUSTER_MAX_SIZE) 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/* 6 bytes (+ length field = 8 bytes) */ 32062306a36Sopenharmony_cistruct z_erofs_deflate_cfgs { 32162306a36Sopenharmony_ci u8 windowbits; /* 8..15 for DEFLATE */ 32262306a36Sopenharmony_ci u8 reserved[5]; 32362306a36Sopenharmony_ci} __packed; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* 32662306a36Sopenharmony_ci * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) 32762306a36Sopenharmony_ci * e.g. for 4k logical cluster size, 4B if compacted 2B is off; 32862306a36Sopenharmony_ci * (4B) + 2B + (4B) if compacted 2B is on. 32962306a36Sopenharmony_ci * bit 1 : HEAD1 big pcluster (0 - off; 1 - on) 33062306a36Sopenharmony_ci * bit 2 : HEAD2 big pcluster (0 - off; 1 - on) 33162306a36Sopenharmony_ci * bit 3 : tailpacking inline pcluster (0 - off; 1 - on) 33262306a36Sopenharmony_ci * bit 4 : interlaced plain pcluster (0 - off; 1 - on) 33362306a36Sopenharmony_ci * bit 5 : fragment pcluster (0 - off; 1 - on) 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci#define Z_EROFS_ADVISE_COMPACTED_2B 0x0001 33662306a36Sopenharmony_ci#define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002 33762306a36Sopenharmony_ci#define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004 33862306a36Sopenharmony_ci#define Z_EROFS_ADVISE_INLINE_PCLUSTER 0x0008 33962306a36Sopenharmony_ci#define Z_EROFS_ADVISE_INTERLACED_PCLUSTER 0x0010 34062306a36Sopenharmony_ci#define Z_EROFS_ADVISE_FRAGMENT_PCLUSTER 0x0020 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci#define Z_EROFS_FRAGMENT_INODE_BIT 7 34362306a36Sopenharmony_cistruct z_erofs_map_header { 34462306a36Sopenharmony_ci union { 34562306a36Sopenharmony_ci /* fragment data offset in the packed inode */ 34662306a36Sopenharmony_ci __le32 h_fragmentoff; 34762306a36Sopenharmony_ci struct { 34862306a36Sopenharmony_ci __le16 h_reserved1; 34962306a36Sopenharmony_ci /* indicates the encoded size of tailpacking data */ 35062306a36Sopenharmony_ci __le16 h_idata_size; 35162306a36Sopenharmony_ci }; 35262306a36Sopenharmony_ci }; 35362306a36Sopenharmony_ci __le16 h_advise; 35462306a36Sopenharmony_ci /* 35562306a36Sopenharmony_ci * bit 0-3 : algorithm type of head 1 (logical cluster type 01); 35662306a36Sopenharmony_ci * bit 4-7 : algorithm type of head 2 (logical cluster type 11). 35762306a36Sopenharmony_ci */ 35862306a36Sopenharmony_ci __u8 h_algorithmtype; 35962306a36Sopenharmony_ci /* 36062306a36Sopenharmony_ci * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; 36162306a36Sopenharmony_ci * bit 3-6 : reserved; 36262306a36Sopenharmony_ci * bit 7 : move the whole file into packed inode or not. 36362306a36Sopenharmony_ci */ 36462306a36Sopenharmony_ci __u8 h_clusterbits; 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* 36862306a36Sopenharmony_ci * On-disk logical cluster type: 36962306a36Sopenharmony_ci * 0 - literal (uncompressed) lcluster 37062306a36Sopenharmony_ci * 1,3 - compressed lcluster (for HEAD lclusters) 37162306a36Sopenharmony_ci * 2 - compressed lcluster (for NONHEAD lclusters) 37262306a36Sopenharmony_ci * 37362306a36Sopenharmony_ci * In detail, 37462306a36Sopenharmony_ci * 0 - literal (uncompressed) lcluster, 37562306a36Sopenharmony_ci * di_advise = 0 37662306a36Sopenharmony_ci * di_clusterofs = the literal data offset of the lcluster 37762306a36Sopenharmony_ci * di_blkaddr = the blkaddr of the literal pcluster 37862306a36Sopenharmony_ci * 37962306a36Sopenharmony_ci * 1,3 - compressed lcluster (for HEAD lclusters) 38062306a36Sopenharmony_ci * di_advise = 1 or 3 38162306a36Sopenharmony_ci * di_clusterofs = the decompressed data offset of the lcluster 38262306a36Sopenharmony_ci * di_blkaddr = the blkaddr of the compressed pcluster 38362306a36Sopenharmony_ci * 38462306a36Sopenharmony_ci * 2 - compressed lcluster (for NONHEAD lclusters) 38562306a36Sopenharmony_ci * di_advise = 2 38662306a36Sopenharmony_ci * di_clusterofs = 38762306a36Sopenharmony_ci * the decompressed data offset in its own HEAD lcluster 38862306a36Sopenharmony_ci * di_u.delta[0] = distance to this HEAD lcluster 38962306a36Sopenharmony_ci * di_u.delta[1] = distance to the next HEAD lcluster 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_cienum { 39262306a36Sopenharmony_ci Z_EROFS_LCLUSTER_TYPE_PLAIN = 0, 39362306a36Sopenharmony_ci Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1, 39462306a36Sopenharmony_ci Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2, 39562306a36Sopenharmony_ci Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3, 39662306a36Sopenharmony_ci Z_EROFS_LCLUSTER_TYPE_MAX 39762306a36Sopenharmony_ci}; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci#define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2 40062306a36Sopenharmony_ci#define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci/* (noncompact only, HEAD) This pcluster refers to partial decompressed data */ 40362306a36Sopenharmony_ci#define Z_EROFS_LI_PARTIAL_REF (1 << 15) 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci/* 40662306a36Sopenharmony_ci * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the 40762306a36Sopenharmony_ci * compressed block count of a compressed extent (in logical clusters, aka. 40862306a36Sopenharmony_ci * block count of a pcluster). 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_ci#define Z_EROFS_LI_D0_CBLKCNT (1 << 11) 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistruct z_erofs_lcluster_index { 41362306a36Sopenharmony_ci __le16 di_advise; 41462306a36Sopenharmony_ci /* where to decompress in the head lcluster */ 41562306a36Sopenharmony_ci __le16 di_clusterofs; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci union { 41862306a36Sopenharmony_ci /* for the HEAD lclusters */ 41962306a36Sopenharmony_ci __le32 blkaddr; 42062306a36Sopenharmony_ci /* 42162306a36Sopenharmony_ci * for the NONHEAD lclusters 42262306a36Sopenharmony_ci * [0] - distance to its HEAD lcluster 42362306a36Sopenharmony_ci * [1] - distance to the next HEAD lcluster 42462306a36Sopenharmony_ci */ 42562306a36Sopenharmony_ci __le16 delta[2]; 42662306a36Sopenharmony_ci } di_u; 42762306a36Sopenharmony_ci}; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci#define Z_EROFS_FULL_INDEX_ALIGN(end) \ 43062306a36Sopenharmony_ci (ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8) 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci/* check the EROFS on-disk layout strictly at compile time */ 43362306a36Sopenharmony_cistatic inline void erofs_check_ondisk_layout_definitions(void) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci const __le64 fmh = *(__le64 *)&(struct z_erofs_map_header) { 43662306a36Sopenharmony_ci .h_clusterbits = 1 << Z_EROFS_FRAGMENT_INODE_BIT 43762306a36Sopenharmony_ci }; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); 44062306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_inode_compact) != 32); 44162306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64); 44262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); 44362306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); 44462306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4); 44562306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8); 44662306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); 44762306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8); 44862306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); 44962306a36Sopenharmony_ci /* keep in sync between 2 index structures for better extendibility */ 45062306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 45162306a36Sopenharmony_ci sizeof(struct z_erofs_lcluster_index)); 45262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) < 45562306a36Sopenharmony_ci Z_EROFS_LCLUSTER_TYPE_MAX - 1); 45662306a36Sopenharmony_ci /* exclude old compiler versions like gcc 7.5.0 */ 45762306a36Sopenharmony_ci BUILD_BUG_ON(__builtin_constant_p(fmh) ? 45862306a36Sopenharmony_ci fmh != cpu_to_le64(1ULL << 63) : 0); 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci#endif 462