erofs/zmap.c: Fix incorrect offset calculation
[platform/kernel/linux-starfive.git] / fs / erofs / zmap.c
index 0bb6692..39cc014 100644 (file)
@@ -694,10 +694,15 @@ static int z_erofs_do_map_blocks(struct inode *inode,
                map->m_pa = blknr_to_addr(m.pblk);
                err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
                if (err)
-                       goto out;
+                       goto unmap_out;
        }
 
        if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN) {
+               if (map->m_llen > map->m_plen) {
+                       DBG_BUGON(1);
+                       err = -EFSCORRUPTED;
+                       goto unmap_out;
+               }
                if (vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER)
                        map->m_algorithmformat =
                                Z_EROFS_COMPRESSION_INTERLACED;
@@ -718,14 +723,12 @@ static int z_erofs_do_map_blocks(struct inode *inode,
                if (!err)
                        map->m_flags |= EROFS_MAP_FULL_MAPPED;
        }
+
 unmap_out:
        erofs_unmap_metabuf(&m.map->buf);
-
-out:
        erofs_dbg("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o",
                  __func__, map->m_la, map->m_pa,
                  map->m_llen, map->m_plen, map->m_flags);
-
        return err;
 }
 
@@ -790,12 +793,16 @@ static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset,
                iomap->type = IOMAP_HOLE;
                iomap->addr = IOMAP_NULL_ADDR;
                /*
-                * No strict rule how to describe extents for post EOF, yet
-                * we need do like below. Otherwise, iomap itself will get
+                * No strict rule on how to describe extents for post EOF, yet
+                * we need to do like below. Otherwise, iomap itself will get
                 * into an endless loop on post EOF.
+                *
+                * Calculate the effective offset by subtracting extent start
+                * (map.m_la) from the requested offset, and add it to length.
+                * (NB: offset >= map.m_la always)
                 */
                if (iomap->offset >= inode->i_size)
-                       iomap->length = length + map.m_la - offset;
+                       iomap->length = length + offset - map.m_la;
        }
        iomap->flags = 0;
        return 0;