diff options
author | Gao Xiang <gaoxiang25@huawei.com> | 2019-06-15 02:36:32 +0800 |
---|---|---|
committer | Gao Xiang <hsiangkao@aol.com> | 2019-08-03 11:27:42 +0800 |
commit | d90641d76b41f2b142439f3b1ee360daecaf0baa (patch) | |
tree | 68091051140e7793667a4d94998f5f9bdadee0e6 /lib | |
parent | 76b822726ff8186133431cdce492e65b71c35cfe (diff) |
erofs-utils: support decompress in-place
In the view of kernel, it usually loads compressed data 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
It's natural to think it further, why not decompressing in-place?
1) Decompressing in-place can be easily implemented since oend is
_strictly_ not greater than iend for fixed-output decompression;
2) Decompressing in-place can be guaranteed with a appropriate
minimum margin rather than do decompress simulatation
for all extents;
*) Many implementations of memcpy can perform overlapped copy
well if op <= ip (it'd better to use memmove, of course).
This patch enables 0PADDING in order to support decompress in-place.
Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.c | 61 | ||||
-rw-r--r-- | lib/config.c | 2 |
2 files changed, 43 insertions, 20 deletions
diff --git a/lib/compress.c b/lib/compress.c index ed4dba4..a977c87 100644 --- a/lib/compress.c +++ b/lib/compress.c @@ -113,6 +113,36 @@ static void vle_write_indexes(struct z_erofs_vle_compress_ctx *ctx, ctx->clusterofs = clusterofs + count; } +static int write_uncompressed_block(struct z_erofs_vle_compress_ctx *ctx, + unsigned int *len, + char *dst) +{ + int ret; + unsigned int count; + + if (!(sbi.requirements & EROFS_REQUIREMENT_LZ4_0PADDING)) { + /* fix up clusterofs to 0 if possable */ + if (ctx->head >= ctx->clusterofs) { + ctx->head -= ctx->clusterofs; + *len += ctx->clusterofs; + ctx->clusterofs = 0; + } + } + + /* write uncompressed data */ + count = min(EROFS_BLKSIZ, *len); + + memcpy(dst, ctx->queue + ctx->head, count); + memset(dst + count, 0, EROFS_BLKSIZ - count); + + erofs_dbg("Writing %u uncompressed data to block %u", + count, ctx->blkaddr); + ret = blk_write(dst, ctx->blkaddr, 1); + if (ret) + return ret; + return count; +} + static int vle_compress_one(struct erofs_inode *inode, struct z_erofs_vle_compress_ctx *ctx, bool final) @@ -121,7 +151,8 @@ static int vle_compress_one(struct erofs_inode *inode, unsigned int len = ctx->tail - ctx->head; unsigned int count; int ret; - char dst[EROFS_BLKSIZ]; + static char dstbuf[EROFS_BLKSIZ * 2]; + char *const dst = dstbuf + EROFS_BLKSIZ; while (len) { bool raw; @@ -143,32 +174,22 @@ static int vle_compress_one(struct erofs_inode *inode, erofs_strerror(ret)); } nocompression: - /* fix up clusterofs to 0 if possable */ - if (ctx->head >= ctx->clusterofs) { - ctx->head -= ctx->clusterofs; - len += ctx->clusterofs; - ctx->clusterofs = 0; - } - - /* write uncompressed data */ - count = min(EROFS_BLKSIZ, len); - - memcpy(dst, ctx->queue + ctx->head, count); - memset(dst + count, 0, EROFS_BLKSIZ - count); - - erofs_dbg("Writing %u uncompressed data to block %u", - count, ctx->blkaddr); - - ret = blk_write(dst, ctx->blkaddr, 1); - if (ret) + ret = write_uncompressed_block(ctx, &len, dst); + if (ret < 0) return ret; + count = ret; raw = true; } else { /* write compressed data */ erofs_dbg("Writing %u compressed data to block %u", count, ctx->blkaddr); - ret = blk_write(dst, ctx->blkaddr, 1); + if (sbi.requirements & EROFS_REQUIREMENT_LZ4_0PADDING) + ret = blk_write(dst - (EROFS_BLKSIZ - ret), + ctx->blkaddr, 1); + else + ret = blk_write(dst, ctx->blkaddr, 1); + if (ret) return ret; raw = false; diff --git a/lib/config.c b/lib/config.c index 07e2846..2e91b92 100644 --- a/lib/config.c +++ b/lib/config.c @@ -8,6 +8,7 @@ */ #include <string.h> #include "erofs/print.h" +#include "erofs/internal.h" struct erofs_configure cfg; @@ -20,6 +21,7 @@ void erofs_init_configure(void) cfg.c_dry_run = false; cfg.c_legacy_compress = false; cfg.c_compr_level_master = -1; + sbi.requirements = EROFS_REQUIREMENT_LZ4_0PADDING; } void erofs_show_config(void) |