}
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;
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) {
return inpage;
}
kunmap_atomic(inpage);
- might_sleep();
src = erofs_vm_map_ram(rq->in, nrpages_in);
if (!src)
return ERR_PTR(-ENOMEM);
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;
}
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,
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;
}
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)