From: Yue Hu <[email protected]> Support uncompressed data layout with on-disk interlaced offset in compression mode for erofsfuse.
Signed-off-by: Yue Hu <[email protected]> --- include/erofs/decompress.h | 3 +++ include/erofs_fs.h | 2 ++ lib/data.c | 8 +++++++- lib/decompress.c | 17 +++++++++++++++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/erofs/decompress.h b/include/erofs/decompress.h index 82bf7b8..a9067cb 100644 --- a/include/erofs/decompress.h +++ b/include/erofs/decompress.h @@ -23,6 +23,9 @@ struct z_erofs_decompress_req { unsigned int decodedskip; unsigned int inputsize, decodedlength; + /* cut point of interlaced uncompressed data */ + unsigned int interlaced_offset; + /* indicate the algorithm will be used for decompression */ unsigned int alg; bool partial_decoding; diff --git a/include/erofs_fs.h b/include/erofs_fs.h index 08f9761..b8a7421 100644 --- a/include/erofs_fs.h +++ b/include/erofs_fs.h @@ -294,11 +294,13 @@ struct z_erofs_lzma_cfgs { * bit 1 : HEAD1 big pcluster (0 - off; 1 - on) * bit 2 : HEAD2 big pcluster (0 - off; 1 - on) * bit 3 : tailpacking inline pcluster (0 - off; 1 - on) + * bit 4 : interlaced plain pcluster (0 - off; 1 - on) */ #define Z_EROFS_ADVISE_COMPACTED_2B 0x0001 #define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002 #define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004 #define Z_EROFS_ADVISE_INLINE_PCLUSTER 0x0008 +#define Z_EROFS_ADVISE_INTERLACED_PCLUSTER 0x0010 struct z_erofs_map_header { __le16 h_reserved1; diff --git a/lib/data.c b/lib/data.c index ad7b2cb..2d76816 100644 --- a/lib/data.c +++ b/lib/data.c @@ -226,7 +226,7 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer, }; struct erofs_map_dev mdev; bool partial; - unsigned int bufsize = 0; + unsigned int bufsize = 0, interlaced_offset; char *raw = NULL; int ret = 0; @@ -287,10 +287,16 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer, if (ret < 0) break; + interlaced_offset = 0; + if ((inode->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER) && + map.m_algorithmformat == Z_EROFS_COMPRESSION_SHIFTED) + interlaced_offset = erofs_blkoff(map.m_la); + ret = z_erofs_decompress(&(struct z_erofs_decompress_req) { .in = raw, .out = buffer + end - offset, .decodedskip = skip, + .interlaced_offset = interlaced_offset, .inputsize = map.m_plen, .decodedlength = length, .alg = map.m_algorithmformat, diff --git a/lib/decompress.c b/lib/decompress.c index 1661f91..39da555 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -132,14 +132,27 @@ out: int z_erofs_decompress(struct z_erofs_decompress_req *rq) { if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) { + unsigned int count, rightpart, skip; + if (rq->inputsize > EROFS_BLKSIZ) return -EFSCORRUPTED; DBG_BUGON(rq->decodedlength > EROFS_BLKSIZ); DBG_BUGON(rq->decodedlength < rq->decodedskip); - memcpy(rq->out, rq->in + rq->decodedskip, - rq->decodedlength - rq->decodedskip); + count = rq->decodedlength - rq->decodedskip; + + if (rq->interlaced_offset) { + skip = erofs_blkoff(rq->interlaced_offset + + rq->decodedskip); + rightpart = min(EROFS_BLKSIZ - skip, count); + } else { + skip = rq->decodedskip; + rightpart = count; + } + memcpy(rq->out, rq->in + skip, rightpart); + memcpy(rq->out + rightpart, rq->in, count - rightpart); + return 0; } -- 2.17.1
