diff options
Diffstat (limited to 'fs/erofs/decompressor.c')
-rw-r--r-- | fs/erofs/decompressor.c | 24 |
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); |