forked from luck/tmp_suning_uos_patched
staging: erofs: introduce LZ4 decompression inplace
compressed data will be usually loaded into last pages of the extent (the last page for 4k) for in-place decompression (more specifically, in-place IO), as ilustration below, start of compressed logical extent | end of this logical extent | | ______v___________________________v________ ... | page 6 | page 7 | page 8 | page 9 | ... |__________|__________|__________|__________| . ^ . ^ . |compressed| . | data | . . . |< dstsize >|<margin>| oend iend op ip Therefore, it's possible to do decompression inplace (thus no memcpy at all) if the margin is sufficient and safe enough [1], and it can be implemented only for fixed-size output compression compared with fixed-size input compression. No memcpy for most of in-place IO (about 99% of enwik9) after decompression inplace is implemented and sequential read will be improved of course (see the following patches for test results). [1]b17f578a91
5997e139f5
Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Gao Xiang <gaoxiang25@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7fc45dbc93
commit
0ffd71bcc3
|
@ -17,6 +17,7 @@ enum {
|
|||
};
|
||||
|
||||
struct z_erofs_decompress_req {
|
||||
struct super_block *sb;
|
||||
struct page **in, **out;
|
||||
|
||||
unsigned short pageofs_out;
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#endif
|
||||
|
||||
#define LZ4_MAX_DISTANCE_PAGES DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE)
|
||||
#ifndef LZ4_DECOMPRESS_INPLACE_MARGIN
|
||||
#define LZ4_DECOMPRESS_INPLACE_MARGIN(srcsize) (((srcsize) >> 8) + 32)
|
||||
#endif
|
||||
|
||||
struct z_erofs_decompressor {
|
||||
/*
|
||||
|
@ -112,7 +115,7 @@ static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
|
|||
{
|
||||
unsigned int inputmargin, inlen;
|
||||
u8 *src;
|
||||
bool copied;
|
||||
bool copied, support_0padding;
|
||||
int ret;
|
||||
|
||||
if (rq->inputsize > PAGE_SIZE)
|
||||
|
@ -120,13 +123,38 @@ static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
|
|||
|
||||
src = kmap_atomic(*rq->in);
|
||||
inputmargin = 0;
|
||||
support_0padding = false;
|
||||
|
||||
/* decompression inplace is only safe when 0padding is enabled */
|
||||
if (EROFS_SB(rq->sb)->requirements & EROFS_REQUIREMENT_LZ4_0PADDING) {
|
||||
support_0padding = true;
|
||||
|
||||
while (!src[inputmargin & ~PAGE_MASK])
|
||||
if (!(++inputmargin & ~PAGE_MASK))
|
||||
break;
|
||||
|
||||
if (inputmargin >= rq->inputsize) {
|
||||
kunmap_atomic(src);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
copied = false;
|
||||
inlen = rq->inputsize - inputmargin;
|
||||
if (rq->inplace_io) {
|
||||
src = generic_copy_inplace_data(rq, src, inputmargin);
|
||||
inputmargin = 0;
|
||||
copied = true;
|
||||
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->inputsize - oend <
|
||||
LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) {
|
||||
src = generic_copy_inplace_data(rq, src, inputmargin);
|
||||
inputmargin = 0;
|
||||
copied = true;
|
||||
}
|
||||
}
|
||||
|
||||
ret = LZ4_decompress_safe_partial(src + inputmargin, out,
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
* Any bits that aren't in EROFS_ALL_REQUIREMENTS should be
|
||||
* incompatible with this kernel version.
|
||||
*/
|
||||
#define EROFS_ALL_REQUIREMENTS 0
|
||||
#define EROFS_REQUIREMENT_LZ4_0PADDING 0x00000001
|
||||
#define EROFS_ALL_REQUIREMENTS EROFS_REQUIREMENT_LZ4_0PADDING
|
||||
|
||||
struct erofs_super_block {
|
||||
/* 0 */__le32 magic; /* in the little endian */
|
||||
|
|
Loading…
Reference in New Issue
Block a user