Source kernel commit: 72bb52620fdffca95a14ee52188a33cd84e574e2 Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- lib/zmap.c | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-)
diff --git a/lib/zmap.c b/lib/zmap.c index 0a9bc6a..ee0af1f 100644 --- a/lib/zmap.c +++ b/lib/zmap.c @@ -71,7 +71,8 @@ static int z_erofs_load_full_lcluster(struct z_erofs_maprecorder *m, m->clusterofs = 1 << vi->z_logical_clusterbits; m->delta[0] = le16_to_cpu(di->di_u.delta[0]); if (m->delta[0] & Z_EROFS_LI_D0_CBLKCNT) { - if (!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { + if (!(vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | + Z_EROFS_ADVISE_BIG_PCLUSTER_2))) { DBG_BUGON(1); return -EFSCORRUPTED; } @@ -327,6 +328,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, return z_erofs_extent_lookback(m, m->delta[0]); case Z_EROFS_LCLUSTER_TYPE_PLAIN: case Z_EROFS_LCLUSTER_TYPE_HEAD1: + case Z_EROFS_LCLUSTER_TYPE_HEAD2: m->headtype = m->type; map->m_la = (lcn << lclusterbits) | m->clusterofs; break; @@ -350,10 +352,15 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m, int err; DBG_BUGON(m->type != Z_EROFS_LCLUSTER_TYPE_PLAIN && - m->type != Z_EROFS_LCLUSTER_TYPE_HEAD1); + m->type != Z_EROFS_LCLUSTER_TYPE_HEAD1 && + m->type != Z_EROFS_LCLUSTER_TYPE_HEAD2); + DBG_BUGON(m->type != m->headtype); if (m->headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN || - !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { + ((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD1) && + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) || + ((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) && + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2))) { map->m_plen = 1 << lclusterbits; return 0; } @@ -380,6 +387,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m, switch (m->type) { case Z_EROFS_LCLUSTER_TYPE_PLAIN: case Z_EROFS_LCLUSTER_TYPE_HEAD1: + case Z_EROFS_LCLUSTER_TYPE_HEAD2: /* * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type * rather than CBLKCNT, it's a 1 lcluster-sized pcluster. @@ -431,7 +439,8 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m) DBG_BUGON(!m->delta[1] && m->clusterofs != 1 << lclusterbits); } else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN || - m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1) { + m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 || + m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) { /* go on until the next HEAD lcluster */ if (lcn != headlcn) break; @@ -484,6 +493,7 @@ static int z_erofs_do_map_blocks(struct erofs_inode *vi, switch (m.type) { case Z_EROFS_LCLUSTER_TYPE_PLAIN: case Z_EROFS_LCLUSTER_TYPE_HEAD1: + case Z_EROFS_LCLUSTER_TYPE_HEAD2: if (endoff >= m.clusterofs) { m.headtype = m.type; map->m_la = (m.lcn << lclusterbits) | m.clusterofs; @@ -553,6 +563,8 @@ static int z_erofs_do_map_blocks(struct erofs_inode *vi, else map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; + } else if (m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) { + map->m_algorithmformat = vi->z_algorithmtype[1]; } else { map->m_algorithmformat = vi->z_algorithmtype[0]; } @@ -572,18 +584,18 @@ out: static int z_erofs_fill_inode_lazy(struct erofs_inode *vi) { - int ret; erofs_off_t pos; struct z_erofs_map_header *h; char buf[sizeof(struct z_erofs_map_header)]; struct erofs_sb_info *sbi = vi->sbi; + int err, headnr; if (vi->flags & EROFS_I_Z_INITED) return 0; pos = round_up(erofs_iloc(vi) + vi->inode_isize + vi->xattr_isize, 8); - ret = erofs_dev_read(sbi, 0, buf, pos, sizeof(buf)); - if (ret < 0) + err = erofs_dev_read(sbi, 0, buf, pos, sizeof(buf)); + if (err < 0) return -EIO; h = (struct z_erofs_map_header *)buf; @@ -602,9 +614,11 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi) vi->z_algorithmtype[0] = h->h_algorithmtype & 15; vi->z_algorithmtype[1] = h->h_algorithmtype >> 4; - if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) { - erofs_err("unknown compression format %u for nid %llu", - vi->z_algorithmtype[0], (unsigned long long)vi->nid); + headnr = 0; + if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX || + vi->z_algorithmtype[++headnr] >= Z_EROFS_COMPRESSION_MAX) { + erofs_err("unknown HEAD%u format %u for nid %llu", + headnr + 1, vi->z_algorithmtype[0], vi->nid | 0ULL); return -EOPNOTSUPP; } @@ -621,7 +635,7 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi) struct erofs_map_blocks map = { .index = UINT_MAX }; vi->idata_size = le16_to_cpu(h->h_idata_size); - ret = z_erofs_do_map_blocks(vi, &map, + err = z_erofs_do_map_blocks(vi, &map, EROFS_GET_BLOCKS_FINDTAIL); if (!map.m_plen || erofs_blkoff(sbi, map.m_pa) + map.m_plen > erofs_blksiz(sbi)) { @@ -629,18 +643,18 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi) map.m_plen | 0ULL); return -EFSCORRUPTED; } - if (ret < 0) - return ret; + if (err < 0) + return err; } if (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER && !(h->h_clusterbits >> Z_EROFS_FRAGMENT_INODE_BIT)) { struct erofs_map_blocks map = { .index = UINT_MAX }; vi->fragmentoff = le32_to_cpu(h->h_fragmentoff); - ret = z_erofs_do_map_blocks(vi, &map, + err = z_erofs_do_map_blocks(vi, &map, EROFS_GET_BLOCKS_FINDTAIL); - if (ret < 0) - return ret; + if (err < 0) + return err; } out: vi->flags |= EROFS_I_Z_INITED; -- 2.43.5