Skip to content

Commit

Permalink
erofs: Update erofs_fs.h to latest version
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Larsson <alexl@redhat.com>
  • Loading branch information
alexlarsson committed Aug 29, 2023
1 parent c15e9b1 commit 8e3d434
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 96 deletions.
193 changes: 101 additions & 92 deletions libcomposefs/erofs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001
#define EROFS_FEATURE_COMPAT_MTIME 0x00000002
#define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004

/*
* Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should
Expand All @@ -27,6 +28,7 @@
#define EROFS_FEATURE_INCOMPAT_ZTAILPACKING 0x00000010
#define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020
#define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020
#define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040
#define EROFS_ALL_FEATURE_INCOMPAT \
(EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \
EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
Expand All @@ -36,7 +38,8 @@
EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \
EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \
EROFS_FEATURE_INCOMPAT_FRAGMENTS | \
EROFS_FEATURE_INCOMPAT_DEDUPE)
EROFS_FEATURE_INCOMPAT_DEDUPE | \
EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES)

#define EROFS_SB_EXTSLOT_SIZE 16

Expand All @@ -53,7 +56,7 @@ struct erofs_super_block {
__le32 magic; /* file system magic number */
__le32 checksum; /* crc32c(super_block) */
__le32 feature_compat;
__u8 blkszbits; /* support block_size == PAGE_SIZE only */
__u8 blkszbits; /* filesystem block size in bit shift */
__u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */

__le16 root_nid; /* nid of root directory */
Expand All @@ -75,49 +78,47 @@ struct erofs_super_block {
} __packed u1;
__le16 extra_devices; /* # of devices besides the primary device */
__le16 devt_slotoff; /* startoff = devt_slotoff * devt_slotsize */
__u8 reserved[6];
__u8 dirblkbits; /* directory block size in bit shift */
__u8 xattr_prefix_count; /* # of long xattr name prefixes */
__le32 xattr_prefix_start; /* start of long xattr prefixes */
__le64 packed_nid; /* nid of the special packed inode */
__u8 reserved2[24];
__u8 xattr_filter_reserved; /* reserved for xattr name filter */
__u8 reserved2[23];
};

/*
* erofs inode datalayout (i_format in on-disk inode):
* EROFS inode datalayout (i_format in on-disk inode):
* 0 - uncompressed flat inode without tail-packing inline data:
* inode, [xattrs], ... | ... | no-holed data
* 1 - compressed inode with non-compact indexes:
* inode, [xattrs], [map_header], extents ... | ...
* 2 - uncompressed flat inode with tail-packing inline data:
* inode, [xattrs], tailpacking data, ... | ... | no-holed data
* 3 - compressed inode with compact indexes:
* inode, [xattrs], map_header, extents ... | ...
* 4 - chunk-based inode with (optional) multi-device support:
* inode, [xattrs], chunk indexes ... | ...
* 5~7 - reserved
*/
enum {
EROFS_INODE_FLAT_PLAIN = 0,
EROFS_INODE_FLAT_COMPRESSION_LEGACY = 1,
EROFS_INODE_COMPRESSED_FULL = 1,
EROFS_INODE_FLAT_INLINE = 2,
EROFS_INODE_FLAT_COMPRESSION = 3,
EROFS_INODE_COMPRESSED_COMPACT = 3,
EROFS_INODE_CHUNK_BASED = 4,
EROFS_INODE_DATALAYOUT_MAX
};

static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
{
return datamode == EROFS_INODE_FLAT_COMPRESSION ||
datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY;
return datamode == EROFS_INODE_COMPRESSED_COMPACT ||
datamode == EROFS_INODE_COMPRESSED_FULL;
}

/* bit definitions of inode i_format */
#define EROFS_I_VERSION_BITS 1
#define EROFS_I_DATALAYOUT_BITS 3
#define EROFS_I_VERSION_MASK 0x01
#define EROFS_I_DATALAYOUT_MASK 0x07

#define EROFS_I_VERSION_BIT 0
#define EROFS_I_DATALAYOUT_BIT 1
#define EROFS_I_ALL_BIT 4

#define EROFS_I_ALL \
((1 << (EROFS_I_DATALAYOUT_BIT + EROFS_I_DATALAYOUT_BITS)) - 1)
#define EROFS_I_ALL ((1 << EROFS_I_ALL_BIT) - 1)

/* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */
#define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F
Expand All @@ -127,11 +128,30 @@ static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
#define EROFS_CHUNK_FORMAT_ALL \
(EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES)

/* 32-byte on-disk inode */
#define EROFS_INODE_LAYOUT_COMPACT 0
/* 64-byte on-disk inode */
#define EROFS_INODE_LAYOUT_EXTENDED 1

struct erofs_inode_chunk_info {
__le16 format; /* chunk blkbits, etc. */
__le16 reserved;
};

union erofs_inode_i_u {
/* total compressed blocks for compressed inodes */
__le32 compressed_blocks;

/* block address for uncompressed flat inodes */
__le32 raw_blkaddr;

/* for device files, used to indicate old/new device # */
__le32 rdev;

/* for chunk-based files, it contains the summary info */
struct erofs_inode_chunk_info c;
};

/* 32-byte reduced form of an ondisk inode */
struct erofs_inode_compact {
__le16 i_format; /* inode format hints */
Expand All @@ -142,29 +162,14 @@ struct erofs_inode_compact {
__le16 i_nlink;
__le32 i_size;
__le32 i_reserved;
union {
/* total compressed blocks for compressed inodes */
__le32 compressed_blocks;
/* block address for uncompressed flat inodes */
__le32 raw_blkaddr;

/* for device files, used to indicate old/new device # */
__le32 rdev;

/* for chunk-based files, it contains the summary info */
struct erofs_inode_chunk_info c;
} i_u;
__le32 i_ino; /* only used for 32-bit stat compatibility */
union erofs_inode_i_u i_u;

__le32 i_ino; /* only used for 32-bit stat compatibility */
__le16 i_uid;
__le16 i_gid;
__le32 i_reserved2;
};

/* 32-byte on-disk inode */
#define EROFS_INODE_LAYOUT_COMPACT 0
/* 64-byte on-disk inode */
#define EROFS_INODE_LAYOUT_EXTENDED 1

/* 64-byte complete form of an ondisk inode */
struct erofs_inode_extended {
__le16 i_format; /* inode format hints */
Expand All @@ -174,22 +179,9 @@ struct erofs_inode_extended {
__le16 i_mode;
__le16 i_reserved;
__le64 i_size;
union {
/* total compressed blocks for compressed inodes */
__le32 compressed_blocks;
/* block address for uncompressed flat inodes */
__le32 raw_blkaddr;

/* for device files, used to indicate old/new device # */
__le32 rdev;

/* for chunk-based files, it contains the summary info */
struct erofs_inode_chunk_info c;
} i_u;

/* only used for 32-bit stat compatibility */
__le32 i_ino;
union erofs_inode_i_u i_u;

__le32 i_ino; /* only used for 32-bit stat compatibility */
__le32 i_uid;
__le32 i_gid;
__le64 i_mtime;
Expand All @@ -198,10 +190,6 @@ struct erofs_inode_extended {
__u8 i_reserved2[16];
};

#define EROFS_MAX_SHARED_XATTRS (128)
/* h_shared_count between 129 ... 255 are special # */
#define EROFS_SHARED_XATTR_EXTENT (255)

/*
* inline xattrs (n == i_xattr_icount):
* erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes
Expand All @@ -214,7 +202,7 @@ struct erofs_inode_extended {
* for read-only fs, no need to introduce h_refcount
*/
struct erofs_xattr_ibody_header {
__le32 h_reserved;
__le32 h_name_filter; /* bit value 1 indicates not-present */
__u8 h_shared_count;
__u8 h_reserved2[7];
__le32 h_shared_xattrs[]; /* shared xattr id array */
Expand All @@ -228,6 +216,17 @@ struct erofs_xattr_ibody_header {
#define EROFS_XATTR_INDEX_LUSTRE 5
#define EROFS_XATTR_INDEX_SECURITY 6

/*
* bit 7 of e_name_index is set when it refers to a long xattr name prefix,
* while the remained lower bits represent the index of the prefix.
*/
#define EROFS_XATTR_LONG_PREFIX 0x80
#define EROFS_XATTR_LONG_PREFIX_MASK 0x7f

#define EROFS_XATTR_FILTER_BITS 32
#define EROFS_XATTR_FILTER_DEFAULT UINT32_MAX
#define EROFS_XATTR_FILTER_SEED 0x25BBE08F

/* xattr entry (for both inline & shared xattrs) */
struct erofs_xattr_entry {
__u8 e_name_len; /* length of name */
Expand All @@ -237,6 +236,12 @@ struct erofs_xattr_entry {
char e_name[]; /* attribute name */
};

/* long xattr name prefix */
struct erofs_xattr_long_prefix {
__u8 base_index; /* short xattr name prefix index */
char infix[]; /* infix apart from short prefix */
};

static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount)
{
if (!i_xattr_icount)
Expand Down Expand Up @@ -267,13 +272,30 @@ struct erofs_inode_chunk_index {
__le32 blkaddr; /* start block address of this inode chunk */
};

/* dirent sorts in alphabet order, thus we can do binary search */
struct erofs_dirent {
__le64 nid; /* node number */
__le16 nameoff; /* start offset of file name */
__u8 file_type; /* file type */
__u8 reserved; /* reserved */
} __packed;

/*
* EROFS file types should match generic FT_* types and
* it seems no need to add BUILD_BUG_ONs since potential
* unmatchness will break other fses as well...
*/

#define EROFS_NAME_LEN 255

/* maximum supported size of a physical compression cluster */
#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024)

/* available compression algorithm types (for h_algorithmtype) */
enum {
Z_EROFS_COMPRESSION_LZ4 = 0,
Z_EROFS_COMPRESSION_LZMA = 1,
Z_EROFS_COMPRESSION_DEFLATE = 2,
Z_EROFS_COMPRESSION_MAX
};
#define Z_EROFS_ALL_COMPR_ALGS ((1 << Z_EROFS_COMPRESSION_MAX) - 1)
Expand All @@ -294,6 +316,12 @@ struct z_erofs_lzma_cfgs {

#define Z_EROFS_LZMA_MAX_DICT_SIZE (8 * Z_EROFS_PCLUSTER_MAX_SIZE)

/* 6 bytes (+ length field = 8 bytes) */
struct z_erofs_deflate_cfgs {
u8 windowbits; /* 8..15 for DEFLATE */
u8 reserved[5];
} __packed;

/*
* bit 0 : COMPACTED_2B indexes (0 - off; 1 - on)
* e.g. for 4k logical cluster size, 4B if compacted 2B is off;
Expand Down Expand Up @@ -336,10 +364,8 @@ struct z_erofs_map_header {
__u8 h_clusterbits;
};

#define Z_EROFS_VLE_LEGACY_HEADER_PADDING 8

/*
* Fixed-sized output compression on-disk logical cluster type:
* On-disk logical cluster type:
* 0 - literal (uncompressed) lcluster
* 1,3 - compressed lcluster (for HEAD lclusters)
* 2 - compressed lcluster (for NONHEAD lclusters)
Expand All @@ -363,27 +389,27 @@ struct z_erofs_map_header {
* di_u.delta[1] = distance to the next HEAD lcluster
*/
enum {
Z_EROFS_VLE_CLUSTER_TYPE_PLAIN = 0,
Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 = 1,
Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD = 2,
Z_EROFS_VLE_CLUSTER_TYPE_HEAD2 = 3,
Z_EROFS_VLE_CLUSTER_TYPE_MAX
Z_EROFS_LCLUSTER_TYPE_PLAIN = 0,
Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1,
Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2,
Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3,
Z_EROFS_LCLUSTER_TYPE_MAX
};

#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2
#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0
#define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2
#define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0

/* (noncompact only, HEAD) This pcluster refers to partial decompressed data */
#define Z_EROFS_VLE_DI_PARTIAL_REF (1 << 15)
#define Z_EROFS_LI_PARTIAL_REF (1 << 15)

/*
* D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the
* compressed block count of a compressed extent (in logical clusters, aka.
* block count of a pcluster).
*/
#define Z_EROFS_VLE_DI_D0_CBLKCNT (1 << 11)
#define Z_EROFS_LI_D0_CBLKCNT (1 << 11)

struct z_erofs_vle_decompressed_index {
struct z_erofs_lcluster_index {
__le16 di_advise;
/* where to decompress in the head lcluster */
__le16 di_clusterofs;
Expand All @@ -400,25 +426,8 @@ struct z_erofs_vle_decompressed_index {
} di_u;
};

#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \
(round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \
sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING)

/* dirent sorts in alphabet order, thus we can do binary search */
struct erofs_dirent {
__le64 nid; /* node number */
__le16 nameoff; /* start offset of file name */
__u8 file_type; /* file type */
__u8 reserved; /* reserved */
} __packed;

/*
* EROFS file types should match generic FT_* types and
* it seems no need to add BUILD_BUG_ONs since potential
* unmatchness will break other fses as well...
*/

#define EROFS_NAME_LEN 255
#define Z_EROFS_FULL_INDEX_ALIGN(end) \
(ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8)

/* check the EROFS on-disk layout strictly at compile time */
static inline void erofs_check_ondisk_layout_definitions(void)
Expand All @@ -435,15 +444,15 @@ static inline void erofs_check_ondisk_layout_definitions(void)
BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4);
BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8);
BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8);
BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8);
BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8);
BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12);
/* keep in sync between 2 index structures for better extendibility */
BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) !=
sizeof(struct z_erofs_vle_decompressed_index));
sizeof(struct z_erofs_lcluster_index));
BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128);

BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) <
Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1);
BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) <
Z_EROFS_LCLUSTER_TYPE_MAX - 1);
/* exclude old compiler versions like gcc 7.5.0 */
BUILD_BUG_ON(__builtin_constant_p(fmh) ?
fmh != cpu_to_le64(1ULL << 63) : 0);
Expand Down
2 changes: 1 addition & 1 deletion libcomposefs/lcfs-writer-erofs.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ static int compute_erofs_shared_xattrs(struct lcfs_ctx_s *ctx)

ent = hash_lookup(xattr_hash, &hkey);
assert(ent != NULL);
if (ent->shared && n_shared < EROFS_MAX_SHARED_XATTRS) {
if (ent->shared && n_shared < EROFS_XATTR_LONG_PREFIX) {
xattr->erofs_shared_xattr_offset = ent->shared_offset;
n_shared++;
} else {
Expand Down
Loading

0 comments on commit 8e3d434

Please sign in to comment.