Loading fs/erofs/decompressor.c +46 −39 Original line number Diff line number Diff line Loading @@ -105,30 +105,20 @@ 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; 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); } 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; Loading @@ -139,10 +129,34 @@ static void *z_erofs_lz4_handle_overlap(struct z_erofs_decompress_req *rq, return ERR_PTR(-ENOMEM); *maptype = 1; return src; docopy: /* Or copy compressed data which can be overlapped to per-CPU buffer */ in = rq->in; } /* * 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]) break; if (i >= rq->inpages) { kunmap_local(inpage); *maptype = 3; return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT); } } /* * 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); Loading @@ -150,20 +164,13 @@ static void *z_erofs_lz4_handle_overlap(struct z_erofs_decompress_req *rq, 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; Loading Loading
fs/erofs/decompressor.c +46 −39 Original line number Diff line number Diff line Loading @@ -105,30 +105,20 @@ 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; 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); } 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; Loading @@ -139,10 +129,34 @@ static void *z_erofs_lz4_handle_overlap(struct z_erofs_decompress_req *rq, return ERR_PTR(-ENOMEM); *maptype = 1; return src; docopy: /* Or copy compressed data which can be overlapped to per-CPU buffer */ in = rq->in; } /* * 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]) break; if (i >= rq->inpages) { kunmap_local(inpage); *maptype = 3; return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT); } } /* * 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); Loading @@ -150,20 +164,13 @@ static void *z_erofs_lz4_handle_overlap(struct z_erofs_decompress_req *rq, 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; Loading