[RFC PATCH v2 2/2] erofs-utils: fuse: support tail-packing inline compressed data
Yue Hu
huyue2 at yulong.com
Fri Oct 29 16:49:31 AEDT 2021
Add tail-packing inline compressed data support for erofsfuse.
Signed-off-by: Yue Hu <huyue2 at yulong.com>
---
changes since v1:
- add tail-packing information to inode and get it on first read.
- update tail-packing checking logic.
include/erofs/internal.h | 3 +
lib/decompress.c | 3 -
lib/zmap.c | 130 ++++++++++++++++++++++++++++++++++++---
3 files changed, 126 insertions(+), 10 deletions(-)
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 3769c27..ce9fb40 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -165,6 +165,8 @@ struct erofs_inode {
uint16_t z_advise;
uint8_t z_algorithmtype[2];
uint8_t z_logical_clusterbits;
+ uint16_t z_idata_size;
+ uint64_t z_idata_addr;
};
};
#ifdef WITH_ANDROID
@@ -251,6 +253,7 @@ struct erofs_map_blocks {
unsigned int m_flags;
erofs_blk_t index;
+ unsigned long m_taillcn;
};
/* super.c */
diff --git a/lib/decompress.c b/lib/decompress.c
index 0b6678d..ac5d126 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -73,9 +73,6 @@ out:
int z_erofs_decompress(struct z_erofs_decompress_req *rq)
{
if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
- if (rq->inputsize != EROFS_BLKSIZ)
- return -EFSCORRUPTED;
-
DBG_BUGON(rq->decodedlength > EROFS_BLKSIZ);
DBG_BUGON(rq->decodedlength < rq->decodedskip);
diff --git a/lib/zmap.c b/lib/zmap.c
index 1084faa..6fcb5cd 100644
--- a/lib/zmap.c
+++ b/lib/zmap.c
@@ -12,6 +12,9 @@
#include "erofs/io.h"
#include "erofs/print.h"
+static int z_erofs_map_tail_data_blocks(struct erofs_inode *vi,
+ struct erofs_map_blocks *map);
+
int z_erofs_fill_inode(struct erofs_inode *vi)
{
if (!erofs_sb_has_big_pcluster() &&
@@ -26,7 +29,68 @@ int z_erofs_fill_inode(struct erofs_inode *vi)
return 0;
}
-static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
+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;
+}
+
+static int z_erofs_fill_inode_lazy(struct erofs_inode *vi,
+ struct erofs_map_blocks *map)
{
int ret;
erofs_off_t pos;
@@ -46,6 +110,7 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
h = (struct z_erofs_map_header *)buf;
vi->z_advise = le16_to_cpu(h->h_advise);
+ vi->z_idata_size = le16_to_cpu(h->h_idata_size);
vi->z_algorithmtype[0] = h->h_algorithmtype & 15;
vi->z_algorithmtype[1] = h->h_algorithmtype >> 4;
@@ -64,6 +129,15 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
vi->nid * 1ULL);
return -EFSCORRUPTED;
}
+ if (vi->z_advise & Z_EROFS_ADVISE_TAILPACKING)
+ vi->z_idata_addr = z_erofs_inline_data_addr(vi);
+
+ if (vi->z_idata_size) {
+ ret = z_erofs_map_tail_data_blocks(vi, map);
+ if (ret)
+ return ret;
+ }
+
vi->flags |= EROFS_I_Z_INITED;
return 0;
}
@@ -375,6 +449,37 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
return 0;
}
+static int z_erofs_map_tail_data_blocks(struct erofs_inode *vi,
+ struct erofs_map_blocks *map)
+{
+ struct z_erofs_maprecorder m = {
+ .inode = vi,
+ .map = map,
+ .kaddr = map->mpage,
+ };
+ unsigned long lcn;
+ unsigned int lclusterbits, endoff;
+ int err;
+
+ lclusterbits = vi->z_logical_clusterbits;
+ lcn = (vi->i_size - 1) >> lclusterbits;
+ endoff = (vi->i_size - 1) & ((1 << lclusterbits) - 1);
+
+ err = z_erofs_load_cluster_from_disk(&m, lcn);
+ if (err)
+ return err;
+
+ if (endoff >= m.clusterofs)
+ goto out;
+
+ err = z_erofs_extent_lookback(&m, 1);
+ if (err)
+ return err;
+out:
+ map->m_taillcn = m.lcn;
+ return 0;
+}
+
static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
unsigned int initial_lcn)
{
@@ -463,12 +568,12 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
goto out;
}
- err = z_erofs_fill_inode_lazy(vi);
+ ofs = map->m_la;
+ err = z_erofs_fill_inode_lazy(vi, map);
if (err)
goto out;
lclusterbits = vi->z_logical_clusterbits;
- ofs = map->m_la;
initial_lcn = ofs >> lclusterbits;
endoff = ofs & ((1 << lclusterbits) - 1);
@@ -511,11 +616,22 @@ 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 (m.lcn == map->m_taillcn && vi->z_idata_size) {
+ map->m_plen = vi->z_idata_size;
+
+ if (vi->z_advise & Z_EROFS_ADVISE_TAILPACKING)
+ map->m_pa = vi->z_idata_addr;
+ else
+ map->m_pa = blknr_to_addr(m.pblk);
+ map->m_flags |= EROFS_MAP_META;
+ } 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