summaryrefslogtreecommitdiffstats
path: root/fs/erofs/decompressor.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/erofs/decompressor.c')
-rw-r--r--fs/erofs/decompressor.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
index f921580b5..36693924d 100644
--- a/fs/erofs/decompressor.c
+++ b/fs/erofs/decompressor.c
@@ -24,7 +24,8 @@ struct z_erofs_decompressor {
*/
int (*prepare_destpages)(struct z_erofs_decompress_req *rq,
struct list_head *pagepool);
- int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out);
+ int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out,
+ u8 *obase);
char *name;
};
@@ -114,10 +115,13 @@ static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq,
return tmp;
}
-static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
+static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out,
+ u8 *obase)
{
+ const uint nrpages_out = PAGE_ALIGN(rq->pageofs_out +
+ rq->outputsize) >> PAGE_SHIFT;
unsigned int inputmargin, inlen;
- u8 *src;
+ u8 *src, *src2;
bool copied, support_0padding;
int ret;
@@ -125,6 +129,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
return -EOPNOTSUPP;
src = kmap_atomic(*rq->in);
+ src2 = src;
inputmargin = 0;
support_0padding = false;
@@ -148,16 +153,15 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
if (rq->inplace_io) {
const uint oend = (rq->pageofs_out +
rq->outputsize) & ~PAGE_MASK;
- const uint nr = PAGE_ALIGN(rq->pageofs_out +
- rq->outputsize) >> PAGE_SHIFT;
-
if (rq->partial_decoding || !support_0padding ||
- rq->out[nr - 1] != rq->in[0] ||
+ rq->out[nrpages_out - 1] != rq->in[0] ||
rq->inputsize - oend <
LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) {
src = generic_copy_inplace_data(rq, src, inputmargin);
inputmargin = 0;
copied = true;
+ } else {
+ src = obase + ((nrpages_out - 1) << PAGE_SHIFT);
}
}
@@ -187,7 +191,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
if (copied)
erofs_put_pcpubuf(src);
else
- kunmap_atomic(src);
+ kunmap_atomic(src2);
return ret;
}
@@ -257,7 +261,7 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
return PTR_ERR(dst);
rq->inplace_io = false;
- ret = alg->decompress(rq, dst);
+ ret = alg->decompress(rq, dst, NULL);
if (!ret)
copy_from_pcpubuf(rq->out, dst, rq->pageofs_out,
rq->outputsize);
@@ -291,7 +295,7 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
dst_maptype = 2;
dstmap_out:
- ret = alg->decompress(rq, dst + rq->pageofs_out);
+ ret = alg->decompress(rq, dst + rq->pageofs_out, dst);
if (!dst_maptype)
kunmap_atomic(dst);