return lo;
 }
 
+static int get_compacted_la_distance(unsigned int lclusterbits,
+                                    unsigned int encodebits,
+                                    unsigned int vcnt, u8 *in, int i)
+{
+       const unsigned int lomask = (1 << lclusterbits) - 1;
+       unsigned int lo, d1 = 0;
+       u8 type;
+
+       DBG_BUGON(i >= vcnt);
+
+       do {
+               lo = decode_compactedbits(lclusterbits, lomask,
+                                         in, encodebits * i, &type);
+
+               if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+                       return d1;
+               ++d1;
+       } while (++i < vcnt);
+
+       /* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */
+       if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT))
+               d1 += lo - 1;
+       return d1;
+}
+
 static int unpack_compacted_index(struct z_erofs_maprecorder *m,
                                  unsigned int amortizedshift,
-                                 unsigned int eofs)
+                                 unsigned int eofs, bool lookahead)
 {
        struct erofs_inode *const vi = EROFS_I(m->inode);
        const unsigned int lclusterbits = vi->z_logical_clusterbits;
        m->type = type;
        if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
                m->clusterofs = 1 << lclusterbits;
+
+               /* figure out lookahead_distance: delta[1] if needed */
+               if (lookahead)
+                       m->delta[1] = get_compacted_la_distance(lclusterbits,
+                                               encodebits, vcnt, in, i);
                if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
                        if (!big_pcluster) {
                                DBG_BUGON(1);
 }
 
 static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
-                                           unsigned long lcn)
+                                           unsigned long lcn, bool lookahead)
 {
        struct inode *const inode = m->inode;
        struct erofs_inode *const vi = EROFS_I(inode);
        err = z_erofs_reload_indexes(m, erofs_blknr(pos));
        if (err)
                return err;
-       return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos));
+       return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos),
+                                     lookahead);
 }
 
 static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
-                                         unsigned int lcn)
+                                         unsigned int lcn, bool lookahead)
 {
        const unsigned int datamode = EROFS_I(m->inode)->datalayout;
 
                return legacy_load_cluster_from_disk(m, lcn);
 
        if (datamode == EROFS_INODE_FLAT_COMPRESSION)
-               return compacted_load_cluster_from_disk(m, lcn);
+               return compacted_load_cluster_from_disk(m, lcn, lookahead);
 
        return -EINVAL;
 }
 
        /* load extent head logical cluster if needed */
        lcn -= lookback_distance;
-       err = z_erofs_load_cluster_from_disk(m, lcn);
+       err = z_erofs_load_cluster_from_disk(m, lcn, false);
        if (err)
                return err;
 
        if (m->compressedlcs)
                goto out;
 
-       err = z_erofs_load_cluster_from_disk(m, lcn);
+       err = z_erofs_load_cluster_from_disk(m, lcn, false);
        if (err)
                return err;
 
        return -EFSCORRUPTED;
 }
 
+static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
+{
+       struct inode *inode = m->inode;
+       struct erofs_inode *vi = EROFS_I(inode);
+       struct erofs_map_blocks *map = m->map;
+       unsigned int lclusterbits = vi->z_logical_clusterbits;
+       u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits;
+       int err;
+
+       do {
+               /* handle the last EOF pcluster (no next HEAD lcluster) */
+               if ((lcn << lclusterbits) >= inode->i_size) {
+                       map->m_llen = inode->i_size - map->m_la;
+                       return 0;
+               }
+
+               err = z_erofs_load_cluster_from_disk(m, lcn, true);
+               if (err)
+                       return err;
+
+               if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
+                       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) {
+                       /* go on until the next HEAD lcluster */
+                       if (lcn != headlcn)
+                               break;
+                       m->delta[1] = 1;
+               } else {
+                       erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu",
+                                 m->type, lcn, vi->nid);
+                       DBG_BUGON(1);
+                       return -EOPNOTSUPP;
+               }
+               lcn += m->delta[1];
+       } while (m->delta[1]);
+
+       map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la;
+       return 0;
+}
+
 int z_erofs_map_blocks_iter(struct inode *inode,
                            struct erofs_map_blocks *map,
                            int flags)
        initial_lcn = ofs >> lclusterbits;
        endoff = ofs & ((1 << lclusterbits) - 1);
 
-       err = z_erofs_load_cluster_from_disk(&m, initial_lcn);
+       err = z_erofs_load_cluster_from_disk(&m, initial_lcn, false);
        if (err)
                goto unmap_out;
 
        err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
        if (err)
                goto out;
+
+       if (flags & EROFS_GET_BLOCKS_FIEMAP) {
+               err = z_erofs_get_extent_decompressedlen(&m);
+               if (!err)
+                       map->m_flags |= EROFS_MAP_FULL_MAPPED;
+       }
 unmap_out:
        if (m.kaddr)
                kunmap_atomic(m.kaddr);