diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c index 6f6e3d0af..526706480 100755 --- a/fs/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -125,11 +125,11 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, } static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq, - void *inpage, unsigned int *inputmargin, int *maptype, - bool support_0padding) + void *inpage, void *out, unsigned int *inputmargin, int *maptype, + bool support_0padding) { unsigned int nrpages_in, nrpages_out; - unsigned int ofull, oend, inputsize, total, i, j; + unsigned int ofull, oend, inputsize, total, i; struct page **in; void *src, *tmp; @@ -144,12 +144,13 @@ static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq, ofull - oend < LZ4_DECOMPRESS_INPLACE_MARGIN(inputsize)) goto docopy; - for (i = 0; i < nrpages_in; ++i) { - DBG_BUGON(rq->in[i] == NULL); - for (j = 0; j < nrpages_out - nrpages_in + i; ++j) - if (rq->out[j] == rq->in[i]) - goto docopy; - } + for (i = 0; i < nrpages_in; ++i) + if (rq->out[nrpages_out - nrpages_in + i] != + rq->in[i]) + goto docopy; + kunmap_atomic(inpage); + *maptype = 3; + return out + ((nrpages_out - nrpages_in) << PAGE_SHIFT); } if (nrpages_in <= 1) { @@ -157,7 +158,6 @@ static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq, return inpage; } kunmap_atomic(inpage); - might_sleep(); src = erofs_vm_map_ram(rq->in, nrpages_in); if (!src) return ERR_PTR(-ENOMEM); @@ -194,10 +194,10 @@ docopy: return src; } -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 *dst) { unsigned int inputmargin; - u8 *headpage, *src; + u8 *out, *headpage, *src; bool support_0padding; int ret, maptype; @@ -221,11 +221,12 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) } rq->inputsize -= inputmargin; - src = z_erofs_handle_inplace_io(rq, headpage, &inputmargin, &maptype, - support_0padding); + src = z_erofs_handle_inplace_io(rq, headpage, dst, &inputmargin, + &maptype, support_0padding); if (IS_ERR(src)) return PTR_ERR(src); + out = dst + rq->pageofs_out; /* legacy format could compress extra data in a pcluster. */ if (rq->partial_decoding || !support_0padding) ret = LZ4_decompress_safe_partial(src + inputmargin, out, @@ -254,7 +255,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) vm_unmap_ram(src, PAGE_ALIGN(rq->inputsize) >> PAGE_SHIFT); } else if (maptype == 2) { erofs_put_pcpubuf(src); - } else { + } else if (maptype != 3) { DBG_BUGON(1); return -EFAULT; } @@ -355,8 +356,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); if (!dst_maptype) kunmap_atomic(dst); else if (dst_maptype == 2)