[RFC PATCH 2/2] erofs-utils: fuse: support tail-packing inline compressed data
Yue Hu
huyue2 at yulong.com
Mon Oct 25 23:30:44 AEDT 2021
Add tail-packing inline compressed data support for erofsfuse.
Signed-off-by: Yue Hu <huyue2 at yulong.com>
---
lib/zmap.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 90 insertions(+), 5 deletions(-)
diff --git a/lib/zmap.c b/lib/zmap.c
index 1084faa..de79f03 100644
--- a/lib/zmap.c
+++ b/lib/zmap.c
@@ -442,6 +442,66 @@ err_bonus_cblkcnt:
return -EFSCORRUPTED;
}
+static erofs_off_t compacted_inline_data_addr(struct erofs_inode *vi)
+{
+ const erofs_off_t ebase = round_up(iloc(vi->nid) + vi->inode_isize +
+ vi->xattr_isize, 8) +
+ sizeof(struct z_erofs_map_header);
+ const unsigned int totalidx = DIV_ROUND_UP(vi->i_size, EROFS_BLKSIZ);
+ unsigned int compacted_4b_initial, compacted_4b_end;
+ unsigned int compacted_2b;
+ erofs_off_t addr;
+
+ compacted_4b_initial = (32 - ebase % 32) / 4;
+ if (compacted_4b_initial == 32 / 4)
+ compacted_4b_initial = 0;
+
+ if (compacted_4b_initial > totalidx) {
+ compacted_4b_initial = 0;
+ compacted_2b = 0;
+ } else if (vi->z_advise & Z_EROFS_ADVISE_COMPACTED_2B) {
+ compacted_2b = rounddown(totalidx - compacted_4b_initial, 16);
+ } else
+ compacted_2b = 0;
+
+ compacted_4b_end = totalidx - compacted_4b_initial - compacted_2b;
+
+ addr = ebase;
+ addr += compacted_4b_initial * 4;
+ addr += compacted_2b * 2;
+ if (compacted_4b_end > 1)
+ addr += (compacted_4b_end/2) * 8;
+ if (compacted_4b_end % 2)
+ addr += 8;
+
+ return addr;
+}
+
+static erofs_off_t legacy_inline_data_addr(struct erofs_inode *vi)
+{
+ const erofs_off_t ibase = iloc(vi->nid);
+ const unsigned int totalidx = DIV_ROUND_UP(vi->i_size, EROFS_BLKSIZ);
+ erofs_off_t addr;
+
+ addr = Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize +
+ vi->xattr_isize) +
+ totalidx * sizeof(struct z_erofs_vle_decompressed_index);
+ return addr;
+}
+
+static erofs_off_t z_erofs_inline_data_addr(struct erofs_inode *vi)
+{
+ const unsigned int datamode = vi->datalayout;
+
+ if (datamode == EROFS_INODE_FLAT_COMPRESSION)
+ return compacted_inline_data_addr(vi);
+
+ if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
+ return legacy_inline_data_addr(vi);
+
+ return -EINVAL;
+}
+
int z_erofs_map_blocks_iter(struct erofs_inode *vi,
struct erofs_map_blocks *map)
{
@@ -454,6 +514,7 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
unsigned int lclusterbits, endoff;
unsigned long initial_lcn;
unsigned long long ofs, end;
+ bool tailpacking;
/* when trying to read beyond EOF, leave it unmapped */
if (map->m_la >= vi->i_size) {
@@ -467,6 +528,8 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
if (err)
goto out;
+ tailpacking = vi->z_advise & Z_EROFS_ADVISE_TAILPACKING;
+
lclusterbits = vi->z_logical_clusterbits;
ofs = map->m_la;
initial_lcn = ofs >> lclusterbits;
@@ -478,6 +541,9 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
map->m_flags = EROFS_MAP_ZIPPED; /* by default, compressed */
end = (m.lcn + 1ULL) << lclusterbits;
+
+ map->m_flags &= ~EROFS_MAP_META;
+
switch (m.type) {
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
if (endoff >= m.clusterofs)
@@ -485,6 +551,16 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
if (endoff >= m.clusterofs) {
map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
+ if (tailpacking &&
+ end == round_up(vi->i_size, 1<<lclusterbits)) {
+ end = vi->i_size;
+ map->m_flags |= EROFS_MAP_META;
+ }
+ if (tailpacking &&
+ end == round_down(vi->i_size, 1<<lclusterbits) &&
+ vi->i_size - map->m_la <= EROFS_BLKSIZ) {
+ map->m_flags |= EROFS_MAP_META;
+ }
break;
}
/* m.lcn should be >= 1 if endoff < m.clusterofs */
@@ -495,7 +571,10 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
goto out;
}
end = (m.lcn << lclusterbits) | m.clusterofs;
- map->m_flags |= EROFS_MAP_FULL_MAPPED;
+ if (tailpacking && end == vi->i_size)
+ map->m_flags |= EROFS_MAP_META;
+ else
+ map->m_flags |= EROFS_MAP_FULL_MAPPED;
m.delta[0] = 1;
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
/* get the correspoinding first chunk */
@@ -511,11 +590,17 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
}
map->m_llen = end - map->m_la;
- map->m_pa = blknr_to_addr(m.pblk);
- err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
- if (err)
- goto out;
+ if (map->m_flags & EROFS_MAP_META) {
+ map->m_pa = z_erofs_inline_data_addr(vi);
+ map->m_plen = EROFS_BLKSIZ;
+ } else {
+ map->m_pa = blknr_to_addr(m.pblk);
+
+ err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
+ if (err)
+ goto out;
+ }
map->m_flags |= EROFS_MAP_MAPPED;
out:
--
2.29.0
More information about the Linux-erofs
mailing list