lkml.org 
[lkml]   [2019]   [Jul]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 21/24] erofs: introduce LZ4 decompression inplace
    Date
    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] https://github.com/lz4/lz4/commit/b17f578a919b7e6b078cede2d52be29dd48c8e8c
    https://github.com/lz4/lz4/commit/5997e139f53169fa3a1c1b4418d2452a90b01602

    Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
    ---
    fs/erofs/decompressor.c | 36 ++++++++++++++++++++++++++++++++----
    fs/erofs/erofs_fs.h | 2 +-
    2 files changed, 33 insertions(+), 5 deletions(-)

    diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
    index 2ee10bb7e440..18fcbd75423e 100644
    --- a/fs/erofs/decompressor.c
    +++ b/fs/erofs/decompressor.c
    @@ -14,6 +14,9 @@
    #endif

    #define LZ4_MAX_DISTANCE_PAGES (DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE) + 1)
    +#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,
    diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h
    index a0a8f44c603d..8d0f61cba349 100644
    --- a/fs/erofs/erofs_fs.h
    +++ b/fs/erofs/erofs_fs.h
    @@ -18,7 +18,7 @@
    * incompatible with this kernel version.
    */
    #define EROFS_REQUIREMENT_LZ4_0PADDING 0x00000001
    -#define EROFS_ALL_REQUIREMENTS 0
    +#define EROFS_ALL_REQUIREMENTS EROFS_REQUIREMENT_LZ4_0PADDING

    struct erofs_super_block {
    /* 0 */__le32 magic; /* in the little endian */
    --
    2.17.1
    \
     
     \ /
      Last update: 2019-07-11 16:59    [W:4.144 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site