From: Gao Xiang <[email protected]> Add multiple block compression runtime support for erofsfuse.
Signed-off-by: Gao Xiang <[email protected]> --- lib/data.c | 4 +-- lib/zmap.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/lib/data.c b/lib/data.c index 3781846743aa..b330a91e4e34 100644 --- a/lib/data.c +++ b/lib/data.c @@ -127,7 +127,7 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer, }; bool partial; unsigned int algorithmformat; - char raw[EROFS_BLKSIZ]; + char raw[1024 * EROFS_BLKSIZ]; end = offset + size; while (end > offset) { @@ -142,7 +142,7 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer, continue; } - ret = dev_read(raw, map.m_pa, EROFS_BLKSIZ); + ret = dev_read(raw, map.m_pa, map.m_plen); if (ret < 0) return -EIO; diff --git a/lib/zmap.c b/lib/zmap.c index ee63de74cab2..096fd35cdeb3 100644 --- a/lib/zmap.c +++ b/lib/zmap.c @@ -14,7 +14,8 @@ int z_erofs_fill_inode(struct erofs_inode *vi) { - if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { + if (!erofs_sb_has_big_pcluster() && + vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { vi->z_advise = 0; vi->z_algorithmtype[0] = 0; vi->z_algorithmtype[1] = 0; @@ -37,7 +38,8 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi) if (vi->flags & EROFS_I_Z_INITED) return 0; - DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); + DBG_BUGON(!erofs_sb_has_big_pcluster() && + vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); pos = round_up(iloc(vi->nid) + vi->inode_isize + vi->xattr_isize, 8); ret = dev_read(buf, pos, sizeof(buf)); @@ -81,7 +83,7 @@ struct z_erofs_maprecorder { u8 type; u16 clusterofs; u16 delta[2]; - erofs_blk_t pblk; + erofs_blk_t pblk, compressedlcs; }; static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, @@ -130,6 +132,15 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: m->clusterofs = 1 << vi->z_logical_clusterbits; m->delta[0] = le16_to_cpu(di->di_u.delta[0]); + if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) { + if (!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } + m->compressedlcs = m->delta[0] & + ~Z_EROFS_VLE_DI_D0_CBLKCNT; + m->delta[0] = 1; + } m->delta[1] = le16_to_cpu(di->di_u.delta[1]); break; case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: @@ -333,6 +344,51 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, return 0; } +static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m, + unsigned int initial_lcn) +{ + struct erofs_inode *const vi = m->inode; + struct erofs_map_blocks *const map = m->map; + const unsigned int lclusterbits = vi->z_logical_clusterbits; + unsigned long lcn; + int err; + + DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN && + m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD); + if (!((map->m_flags & EROFS_MAP_ZIPPED) && + (vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1))) { + map->m_plen = 1 << lclusterbits; + return 0; + } + + lcn = m->lcn + 1; + if (lcn == initial_lcn && !m->compressedlcs) + m->compressedlcs = 2; + + if (m->compressedlcs) + goto out; + + err = z_erofs_load_cluster_from_disk(m, lcn); + if (err) + return err; + + switch (m->type) { + case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + DBG_BUGON(m->delta[0] != 1); + if (m->compressedlcs) { + break; + } + default: + erofs_err("cannot found CBLKCNT @ lcn %lu of nid %llu", + lcn, (unsigned long long)vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } +out: + map->m_plen = m->compressedlcs << lclusterbits; + return 0; +} + int z_erofs_map_blocks_iter(struct erofs_inode *vi, struct erofs_map_blocks *map) { @@ -343,6 +399,7 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi, }; int err = 0; unsigned int lclusterbits, endoff; + unsigned long initial_lcn; unsigned long long ofs, end; /* when trying to read beyond EOF, leave it unmapped */ @@ -359,10 +416,10 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi, lclusterbits = vi->z_logical_clusterbits; ofs = map->m_la; - m.lcn = ofs >> lclusterbits; + initial_lcn = ofs >> lclusterbits; endoff = ofs & ((1 << lclusterbits) - 1); - err = z_erofs_load_cluster_from_disk(&m, m.lcn); + err = z_erofs_load_cluster_from_disk(&m, initial_lcn); if (err) goto out; @@ -401,8 +458,11 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi, } map->m_llen = end - map->m_la; - map->m_plen = 1 << lclusterbits; map->m_pa = blknr_to_addr(m.pblk); + + err = z_erofs_get_extent_compressedlen(&m, initial_lcn); + if (err) + goto out; map->m_flags |= EROFS_MAP_MAPPED; out: -- 2.24.0
