aboutsummaryrefslogtreecommitdiff
path: root/fs/erofs/decompress.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/erofs/decompress.c')
-rw-r--r--fs/erofs/decompress.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/fs/erofs/decompress.c b/fs/erofs/decompress.c
index 2be3b844cf..e04e5c34a8 100644
--- a/fs/erofs/decompress.c
+++ b/fs/erofs/decompress.c
@@ -15,8 +15,8 @@ static int z_erofs_decompress_lz4(struct z_erofs_decompress_req *rq)
if (erofs_sb_has_lz4_0padding()) {
support_0padding = true;
- while (!src[inputmargin & ~PAGE_MASK])
- if (!(++inputmargin & ~PAGE_MASK))
+ while (!src[inputmargin & (erofs_blksiz() - 1)])
+ if (!(++inputmargin & (erofs_blksiz() - 1)))
break;
if (inputmargin >= rq->inputsize)
@@ -40,6 +40,9 @@ static int z_erofs_decompress_lz4(struct z_erofs_decompress_req *rq)
rq->decodedlength);
if (ret != (int)rq->decodedlength) {
+ erofs_err("failed to %s decompress %d in[%u, %u] out[%u]",
+ rq->partial_decoding ? "partial" : "full",
+ ret, rq->inputsize, inputmargin, rq->decodedlength);
ret = -EIO;
goto out;
}
@@ -58,13 +61,30 @@ out:
int z_erofs_decompress(struct z_erofs_decompress_req *rq)
{
- if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
- if (rq->inputsize != EROFS_BLKSIZ)
+ if (rq->alg == Z_EROFS_COMPRESSION_INTERLACED) {
+ unsigned int count, rightpart, skip;
+
+ /* XXX: should support inputsize >= erofs_blksiz() later */
+ if (rq->inputsize > erofs_blksiz())
return -EFSCORRUPTED;
- DBG_BUGON(rq->decodedlength > EROFS_BLKSIZ);
- DBG_BUGON(rq->decodedlength < rq->decodedskip);
+ if (rq->decodedlength > erofs_blksiz())
+ return -EFSCORRUPTED;
+
+ if (rq->decodedlength < rq->decodedskip)
+ return -EFSCORRUPTED;
+ count = rq->decodedlength - rq->decodedskip;
+ skip = erofs_blkoff(rq->interlaced_offset + rq->decodedskip);
+ rightpart = min(erofs_blksiz() - skip, count);
+ memcpy(rq->out, rq->in + skip, rightpart);
+ memcpy(rq->out + rightpart, rq->in, count - rightpart);
+ return 0;
+ } else if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
+ if (rq->decodedlength > rq->inputsize)
+ return -EFSCORRUPTED;
+
+ DBG_BUGON(rq->decodedlength < rq->decodedskip);
memcpy(rq->out, rq->in + rq->decodedskip,
rq->decodedlength - rq->decodedskip);
return 0;