summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGao Xiang <gaoxiang25@huawei.com>2019-06-15 02:36:32 +0800
committerGao Xiang <hsiangkao@aol.com>2019-08-03 11:27:42 +0800
commitd90641d76b41f2b142439f3b1ee360daecaf0baa (patch)
tree68091051140e7793667a4d94998f5f9bdadee0e6 /lib
parent76b822726ff8186133431cdce492e65b71c35cfe (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.c61
-rw-r--r--lib/config.c2
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)