#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER    0x00000002
 #define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE    0x00000004
 #define EROFS_FEATURE_INCOMPAT_DEVICE_TABLE    0x00000008
+#define EROFS_FEATURE_INCOMPAT_COMPR_HEAD2     0x00000008
 #define EROFS_ALL_FEATURE_INCOMPAT             \
        (EROFS_FEATURE_INCOMPAT_LZ4_0PADDING | \
         EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
         EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \
         EROFS_FEATURE_INCOMPAT_CHUNKED_FILE | \
-        EROFS_FEATURE_INCOMPAT_DEVICE_TABLE)
+        EROFS_FEATURE_INCOMPAT_DEVICE_TABLE | \
+        EROFS_FEATURE_INCOMPAT_COMPR_HEAD2)
 
 #define EROFS_SB_EXTSLOT_SIZE  16
 
 #define Z_EROFS_VLE_LEGACY_HEADER_PADDING       8
 
 /*
- * Fixed-sized output compression ondisk Logical Extent cluster type:
- *    0 - literal (uncompressed) cluster
- *    1 - compressed cluster (for the head logical cluster)
- *    2 - compressed cluster (for the other logical clusters)
+ * Fixed-sized output compression on-disk logical cluster type:
+ *    0   - literal (uncompressed) lcluster
+ *    1,3 - compressed lcluster (for HEAD lclusters)
+ *    2   - compressed lcluster (for NONHEAD lclusters)
  *
  * In detail,
- *    0 - literal (uncompressed) cluster,
+ *    0 - literal (uncompressed) lcluster,
  *        di_advise = 0
- *        di_clusterofs = the literal data offset of the cluster
- *        di_blkaddr = the blkaddr of the literal cluster
+ *        di_clusterofs = the literal data offset of the lcluster
+ *        di_blkaddr = the blkaddr of the literal pcluster
  *
- *    1 - compressed cluster (for the head logical cluster)
- *        di_advise = 1
- *        di_clusterofs = the decompressed data offset of the cluster
- *        di_blkaddr = the blkaddr of the compressed cluster
+ *    1,3 - compressed lcluster (for HEAD lclusters)
+ *        di_advise = 1 or 3
+ *        di_clusterofs = the decompressed data offset of the lcluster
+ *        di_blkaddr = the blkaddr of the compressed pcluster
  *
- *    2 - compressed cluster (for the other logical clusters)
+ *    2 - compressed lcluster (for NONHEAD lclusters)
  *        di_advise = 2
  *        di_clusterofs =
- *           the decompressed data offset in its own head cluster
- *        di_u.delta[0] = distance to its corresponding head cluster
- *        di_u.delta[1] = distance to its corresponding tail cluster
- *                (di_advise could be 0, 1 or 2)
+ *           the decompressed data offset in its own HEAD lcluster
+ *        di_u.delta[0] = distance to this HEAD lcluster
+ *        di_u.delta[1] = distance to the next HEAD lcluster
  */
 enum {
        Z_EROFS_VLE_CLUSTER_TYPE_PLAIN          = 0,
-       Z_EROFS_VLE_CLUSTER_TYPE_HEAD           = 1,
+       Z_EROFS_VLE_CLUSTER_TYPE_HEAD1          = 1,
        Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD        = 2,
-       Z_EROFS_VLE_CLUSTER_TYPE_RESERVED       = 3,
+       Z_EROFS_VLE_CLUSTER_TYPE_HEAD2          = 3,
        Z_EROFS_VLE_CLUSTER_TYPE_MAX
 };
 
 
 {
        struct erofs_inode *const vi = EROFS_I(inode);
        struct super_block *const sb = inode->i_sb;
-       int err;
+       int err, headnr;
        erofs_off_t pos;
        struct page *page;
        void *kaddr;
        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(sb, "unknown compression format %u for nid %llu, please upgrade kernel",
-                         vi->z_algorithmtype[0], vi->nid);
+       headnr = 0;
+       if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX ||
+           vi->z_algorithmtype[++headnr] >= Z_EROFS_COMPRESSION_MAX) {
+               erofs_err(sb, "unknown HEAD%u format %u for nid %llu, please upgrade kernel",
+                         headnr + 1, vi->z_algorithmtype[headnr], vi->nid);
                err = -EOPNOTSUPP;
                goto unmap_done;
        }
                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)) {
+                       if (!(vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 |
+                                       Z_EROFS_ADVISE_BIG_PCLUSTER_2))) {
                                DBG_BUGON(1);
                                return -EFSCORRUPTED;
                        }
                m->delta[1] = le16_to_cpu(di->di_u.delta[1]);
                break;
        case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
                m->clusterofs = le16_to_cpu(di->di_clusterofs);
                m->pblk = le32_to_cpu(di->di_u.blkaddr);
                break;
                }
                return z_erofs_extent_lookback(m, m->delta[0]);
        case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
                m->headtype = m->type;
                map->m_la = (lcn << lclusterbits) | m->clusterofs;
                break;
        int err;
 
        DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN &&
-                 m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD);
+                 m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 &&
+                 m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD2);
+       DBG_BUGON(m->type != m->headtype);
+
        if (m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
-           !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) {
+           ((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1) &&
+            !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) ||
+           ((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) &&
+            !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2))) {
                map->m_plen = 1 << lclusterbits;
                return 0;
        }
-
        lcn = m->lcn + 1;
        if (m->compressedlcs)
                goto out;
 
        switch (m->type) {
        case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
                /*
                 * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
                 * rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
                        DBG_BUGON(!m->delta[1] &&
                                  m->clusterofs != 1 << lclusterbits);
                } else if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
-                          m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD) {
+                          m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 ||
+                          m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) {
                        /* go on until the next HEAD lcluster */
                        if (lcn != headlcn)
                                break;
 
        switch (m.type) {
        case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
+       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
                if (endoff >= m.clusterofs) {
                        m.headtype = m.type;
                        map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
 
        if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN)
                map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED;
+       else if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2)
+               map->m_algorithmformat = vi->z_algorithmtype[1];
        else
                map->m_algorithmformat = vi->z_algorithmtype[0];