mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
erofs: tidy up z_erofs_lz4_handle_overlap()
[ Upstream commit9ae77198d4] - Add some useful comments to explain inplace I/Os and decompression; - Rearrange the code to get rid of one unnecessary goto. Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com> Stable-dep-of:21e161de2d("erofs: fix unsigned underflow in z_erofs_lz4_handle_overlap()") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
d309d3308d
commit
24da4cc6bf
+46
-39
@@ -105,44 +105,58 @@ static int z_erofs_lz4_prepare_dstpages(struct z_erofs_decompress_req *rq,
|
||||
return kaddr ? 1 : 0;
|
||||
}
|
||||
|
||||
static void *z_erofs_lz4_handle_overlap(struct z_erofs_decompress_req *rq,
|
||||
static void *z_erofs_lz4_handle_overlap(const struct z_erofs_decompress_req *rq,
|
||||
void *inpage, void *out, unsigned int *inputmargin,
|
||||
int *maptype, bool may_inplace)
|
||||
{
|
||||
unsigned int oend, omargin, total, i;
|
||||
unsigned int oend, omargin, cnt, i;
|
||||
struct page **in;
|
||||
void *src, *tmp;
|
||||
|
||||
if (rq->inplace_io) {
|
||||
oend = rq->pageofs_out + rq->outputsize;
|
||||
omargin = PAGE_ALIGN(oend) - oend;
|
||||
if (rq->partial_decoding || !may_inplace ||
|
||||
omargin < LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize))
|
||||
goto docopy;
|
||||
void *src;
|
||||
|
||||
/*
|
||||
* If in-place I/O isn't used, for example, the bounce compressed cache
|
||||
* can hold data for incomplete read requests. Just map the compressed
|
||||
* buffer as well and decompress directly.
|
||||
*/
|
||||
if (!rq->inplace_io) {
|
||||
if (rq->inpages <= 1) {
|
||||
*maptype = 0;
|
||||
return inpage;
|
||||
}
|
||||
kunmap_local(inpage);
|
||||
src = erofs_vm_map_ram(rq->in, rq->inpages);
|
||||
if (!src)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
*maptype = 1;
|
||||
return src;
|
||||
}
|
||||
/*
|
||||
* Then, deal with in-place I/Os. The reasons why in-place I/O is useful
|
||||
* are: (1) It minimizes memory footprint during the I/O submission,
|
||||
* which is useful for slow storage (including network devices and
|
||||
* low-end HDDs/eMMCs) but with a lot inflight I/Os; (2) If in-place
|
||||
* decompression can also be applied, it will reuse the unique buffer so
|
||||
* that no extra CPU D-cache is polluted with temporary compressed data
|
||||
* for extreme performance.
|
||||
*/
|
||||
oend = rq->pageofs_out + rq->outputsize;
|
||||
omargin = PAGE_ALIGN(oend) - oend;
|
||||
if (!rq->partial_decoding && may_inplace &&
|
||||
omargin >= LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize)) {
|
||||
for (i = 0; i < rq->inpages; ++i)
|
||||
if (rq->out[rq->outpages - rq->inpages + i] !=
|
||||
rq->in[i])
|
||||
goto docopy;
|
||||
kunmap_local(inpage);
|
||||
*maptype = 3;
|
||||
return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT);
|
||||
break;
|
||||
if (i >= rq->inpages) {
|
||||
kunmap_local(inpage);
|
||||
*maptype = 3;
|
||||
return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
if (rq->inpages <= 1) {
|
||||
*maptype = 0;
|
||||
return inpage;
|
||||
}
|
||||
kunmap_local(inpage);
|
||||
src = erofs_vm_map_ram(rq->in, rq->inpages);
|
||||
if (!src)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
*maptype = 1;
|
||||
return src;
|
||||
|
||||
docopy:
|
||||
/* Or copy compressed data which can be overlapped to per-CPU buffer */
|
||||
in = rq->in;
|
||||
/*
|
||||
* If in-place decompression can't be applied, copy compressed data that
|
||||
* may potentially overlap during decompression to a per-CPU buffer.
|
||||
*/
|
||||
src = z_erofs_get_gbuf(rq->inpages);
|
||||
if (!src) {
|
||||
DBG_BUGON(1);
|
||||
@@ -150,20 +164,13 @@ docopy:
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
tmp = src;
|
||||
total = rq->inputsize;
|
||||
while (total) {
|
||||
unsigned int page_copycnt =
|
||||
min_t(unsigned int, total, PAGE_SIZE - *inputmargin);
|
||||
|
||||
for (i = 0, in = rq->in; i < rq->inputsize; i += cnt, ++in) {
|
||||
cnt = min_t(u32, rq->inputsize - i, PAGE_SIZE - *inputmargin);
|
||||
if (!inpage)
|
||||
inpage = kmap_local_page(*in);
|
||||
memcpy(tmp, inpage + *inputmargin, page_copycnt);
|
||||
memcpy(src + i, inpage + *inputmargin, cnt);
|
||||
kunmap_local(inpage);
|
||||
inpage = NULL;
|
||||
tmp += page_copycnt;
|
||||
total -= page_copycnt;
|
||||
++in;
|
||||
*inputmargin = 0;
|
||||
}
|
||||
*maptype = 2;
|
||||
|
||||
Reference in New Issue
Block a user