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

Reply via email to