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

Reply via email to