Hi Chao, On 2019/6/21 15:46, Chao Yu wrote: > On 2019/6/21 0:07, Gao Xiang wrote: >> This patch introduces new compacted compression indexes. >> >> In contract to legacy compression indexes that >> each 4k logical cluster has an 8-byte index, >> compacted ondisk compression indexes will have >> amortized 2 bytes for each 4k logical cluster (compacted 2B) >> amortized 4 bytes for each 4k logical cluster (compacted 4B) >> >> In detail, several continuous clusters will be encoded in >> a compacted pack with cluster types, offsets, and one blkaddr >> at the end of the pack to leave 4-byte margin for better >> decoding performance, as illustrated below: >> _____________________________________________ >> |___@_____ encoded bits __________|_ blkaddr _| >> 0 . amortized * vcnt >> . . >> . . amortized * vcnt - 4 >> . . >> .___________________. >> |_type_|_clusterofs_| >> >> Note that compacted 2 / 4B should be aligned with 32 / 8 bytes >> in order to avoid each pack crossing page boundary. >> >> Signed-off-by: Gao Xiang <gaoxiang25@xxxxxxxxxx> >> --- >> drivers/staging/erofs/data.c | 4 +-- >> drivers/staging/erofs/erofs_fs.h | 57 +++++++++++++++++++++++++------ >> drivers/staging/erofs/inode.c | 5 +-- >> drivers/staging/erofs/internal.h | 11 ++---- >> drivers/staging/erofs/unzip_vle.c | 8 ++--- >> 5 files changed, 56 insertions(+), 29 deletions(-) >> >> diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c >> index 746685f90564..cc31c3e5984c 100644 >> --- a/drivers/staging/erofs/data.c >> +++ b/drivers/staging/erofs/data.c >> @@ -124,7 +124,7 @@ static int erofs_map_blocks_flatmode(struct inode *inode, >> trace_erofs_map_blocks_flatmode_enter(inode, map, flags); >> >> nblocks = DIV_ROUND_UP(inode->i_size, PAGE_SIZE); >> - lastblk = nblocks - is_inode_layout_inline(inode); >> + lastblk = nblocks - is_inode_flat_inline(inode); >> >> if (unlikely(offset >= inode->i_size)) { >> /* leave out-of-bound access unmapped */ >> @@ -139,7 +139,7 @@ static int erofs_map_blocks_flatmode(struct inode *inode, >> if (offset < blknr_to_addr(lastblk)) { >> map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la; >> map->m_plen = blknr_to_addr(lastblk) - offset; >> - } else if (is_inode_layout_inline(inode)) { >> + } else if (is_inode_flat_inline(inode)) { >> /* 2 - inode inline B: inode, [xattrs], inline last blk... */ >> struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); >> >> diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h >> index 8ddb2b3e7d39..a05139f1df60 100644 >> --- a/drivers/staging/erofs/erofs_fs.h >> +++ b/drivers/staging/erofs/erofs_fs.h >> @@ -49,19 +49,29 @@ struct erofs_super_block { >> * erofs inode data mapping: >> * 0 - inode plain without inline data A: >> * inode, [xattrs], ... | ... | no-holed data >> - * 1 - inode VLE compression B: >> + * 1 - inode VLE compression B (legacy): >> * inode, [xattrs], extents ... | ... >> * 2 - inode plain with inline data C: >> * inode, [xattrs], last_inline_data, ... | ... | no-holed data >> - * 3~7 - reserved >> + * 3 - inode compression D: >> + * inode, [xattrs], map_header, extents ... | ... >> + * 4~7 - reserved >> */ >> enum { >> - EROFS_INODE_LAYOUT_PLAIN, >> - EROFS_INODE_LAYOUT_COMPRESSION, >> - EROFS_INODE_LAYOUT_INLINE, >> + EROFS_INODE_FLAT_PLAIN, >> + EROFS_INODE_FLAT_COMPRESSION_LEGACY, >> + EROFS_INODE_FLAT_INLINE, >> + EROFS_INODE_FLAT_COMPRESSION, >> EROFS_INODE_LAYOUT_MAX >> }; >> >> +static bool erofs_inode_is_data_compressed(unsigned int datamode) >> +{ >> + if (datamode == EROFS_INODE_FLAT_COMPRESSION) >> + return true; >> + return datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY; >> +} >> + >> /* bit definitions of inode i_advise */ >> #define EROFS_I_VERSION_BITS 1 >> #define EROFS_I_DATA_MAPPING_BITS 3 >> @@ -176,11 +186,37 @@ struct erofs_xattr_entry { >> sizeof(struct erofs_xattr_entry) + \ >> (entry)->e_name_len + le16_to_cpu((entry)->e_value_size)) >> >> -/* have to be aligned with 8 bytes on disk */ >> -struct erofs_extent_header { >> - __le32 eh_checksum; >> - __le32 eh_reserved[3]; >> -} __packed; >> +/* available compression algorithm types */ >> +enum { >> + Z_EROFS_COMPRESSION_LZ4, >> + Z_EROFS_COMPRESSION_MAX >> +}; >> + >> +/* >> + * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) >> + * e.g. for 4k logical cluster size, 4B if compacted 2B is off; >> + * (4B) + 2B + (4B) if compacted 2B is on. >> + */ >> +#define Z_EROFS_ADVISE_COMPACTED_2B_BIT 0 >> + >> +#define Z_EROFS_ADVISE_COMPACTED_2B (1 << Z_EROFS_ADVISE_COMPACTED_2B_BIT) >> + >> +struct z_erofs_map_header { >> + __le32 h_reserved1; >> + __le16 h_advise; >> + /* >> + * bit 0-3 : algorithm type of head 1 (logical cluster type 01); >> + * bit 4-7 : algorithm type of head 2 (logical cluster type 11). >> + */ >> + __u8 h_algorithmtype; >> + /* >> + * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; >> + * bit 3-4 : (physical - logical) cluster bits of head 1: >> + * For example, if logical clustersize = 4096, 1 for 8192. >> + * bit 5-7 : (physical - logical) cluster bits of head 2. >> + */ >> + __u8 h_clusterbits; >> +}; >> >> /* >> * Z_EROFS Variable-sized Logical Extent cluster type: >> @@ -270,7 +306,6 @@ static inline void erofs_check_ondisk_layout_definitions(void) >> BUILD_BUG_ON(sizeof(struct erofs_inode_v2) != 64); >> BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); >> BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); >> - BUILD_BUG_ON(sizeof(struct erofs_extent_header) != 16); >> BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8); >> BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); >> >> diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c >> index e51348f7e838..3539290b8e45 100644 >> --- a/drivers/staging/erofs/inode.c >> +++ b/drivers/staging/erofs/inode.c >> @@ -127,12 +127,9 @@ static int fill_inline_data(struct inode *inode, void *data, >> { >> struct erofs_vnode *vi = EROFS_V(inode); >> struct erofs_sb_info *sbi = EROFS_I_SB(inode); >> - const int mode = vi->datamode; >> - >> - DBG_BUGON(mode >= EROFS_INODE_LAYOUT_MAX); >> >> /* should be inode inline C */ >> - if (mode != EROFS_INODE_LAYOUT_INLINE) >> + if (!is_inode_flat_inline(inode)) >> return 0; >> >> /* fast symlink (following ext4) */ >> diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h >> index 1666cceecb3c..c851d0be6cf6 100644 >> --- a/drivers/staging/erofs/internal.h >> +++ b/drivers/staging/erofs/internal.h >> @@ -382,19 +382,14 @@ static inline unsigned long inode_datablocks(struct inode *inode) >> return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); >> } >> >> -static inline bool is_inode_layout_plain(struct inode *inode) >> -{ >> - return EROFS_V(inode)->datamode == EROFS_INODE_LAYOUT_PLAIN; >> -} >> - >> static inline bool is_inode_layout_compression(struct inode *inode) >> { >> - return EROFS_V(inode)->datamode == EROFS_INODE_LAYOUT_COMPRESSION; >> + return erofs_inode_is_data_compressed(EROFS_V(inode)->datamode); >> } >> >> -static inline bool is_inode_layout_inline(struct inode *inode) >> +static inline bool is_inode_flat_inline(struct inode *inode) >> { >> - return EROFS_V(inode)->datamode == EROFS_INODE_LAYOUT_INLINE; >> + return EROFS_V(inode)->datamode == EROFS_INODE_FLAT_INLINE; >> } >> >> extern const struct super_operations erofs_sops; >> diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c >> index f3d0d2c03939..0db9bc50f67c 100644 >> --- a/drivers/staging/erofs/unzip_vle.c >> +++ b/drivers/staging/erofs/unzip_vle.c >> @@ -1643,8 +1643,8 @@ vle_extent_blkaddr(struct inode *inode, pgoff_t index) >> struct erofs_vnode *vi = EROFS_V(inode); >> >> unsigned int ofs = Z_EROFS_VLE_EXTENT_ALIGN(vi->inode_isize + >> - vi->xattr_isize) + sizeof(struct erofs_extent_header) + >> - index * sizeof(struct z_erofs_vle_decompressed_index); >> + vi->xattr_isize) + >> + 16 + index * sizeof(struct z_erofs_vle_decompressed_index); >> >> return erofs_blknr(iloc(sbi, vi->nid) + ofs); >> } >> @@ -1656,8 +1656,8 @@ vle_extent_blkoff(struct inode *inode, pgoff_t index) >> struct erofs_vnode *vi = EROFS_V(inode); >> >> unsigned int ofs = Z_EROFS_VLE_EXTENT_ALIGN(vi->inode_isize + >> - vi->xattr_isize) + sizeof(struct erofs_extent_header) + >> - index * sizeof(struct z_erofs_vle_decompressed_index); >> + vi->xattr_isize) + >> + 16 + index * sizeof(struct z_erofs_vle_decompressed_index); > > We can add one macro to wrap above offset (16) for better readability, anyway, > this patch looks good to me. :) OK, that is fine. I will add a marco to wrap up this number. Since currently we don't read or use the legacy extent header at all, I will make it obsoleted and remove the 16-byte legacy extent header directly. However, in the future, I tend to add z_erofs_map_header support for the legacy index format as well in order to support large cluster size and more compression format, therefore it could be 8-byte z_erofs_map_header + 8-byte Z_EROFS_VLE_EXTENT_HEADER_PADDING and we need to add a requirement field for this expension. :) Thanks, Gao Xiang > > Reviewed-by: Chao Yu <yuchao0@xxxxxxxxxx> > > Thanks, > >> >> return erofs_blkoff(iloc(sbi, vi->nid) + ofs); >> } >>