* [RFC PATCH v2 0/2] erofs-utils: compression inline feature
@ 2021-10-29 5:49 Yue Hu
2021-10-29 5:49 ` [RFC PATCH v2 1/2] erofs-utils: support tail-packing inline compressed data Yue Hu
2021-10-29 5:49 ` [RFC PATCH v2 2/2] erofs-utils: fuse: " Yue Hu
0 siblings, 2 replies; 3+ messages in thread
From: Yue Hu @ 2021-10-29 5:49 UTC (permalink / raw)
To: linux-erofs; +Cc: zhangwen, Yue Hu, geshifei, shaojunjun
Now, we only support tail-end inline data for uncompressed file. We should
also support it for compressed file to further decrease tail extent I/O and
save more space. That is original intention as well from Xiang.
Note that tail pcluster data is compressed by 4KB in this patch, which looks
like inefficent. As Xiang mentioned, there is another better way to handle it.
This patch is just using 4KB compression policy, we may improve it next.
Thanks.
Yue Hu (2):
erofs-utils: support tail-packing inline compressed data
erofs-utils: fuse: support tail-packing inline compressed data
include/erofs/internal.h | 4 ++
include/erofs_fs.h | 10 ++-
lib/compress.c | 76 ++++++++++++++++++-----
lib/compressor.c | 9 +--
lib/decompress.c | 7 ++-
lib/inode.c | 40 ++++++------
lib/zmap.c | 130 ++++++++++++++++++++++++++++++++++++---
mkfs/main.c | 6 ++
8 files changed, 228 insertions(+), 54 deletions(-)
--
2.29.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH v2 1/2] erofs-utils: support tail-packing inline compressed data
2021-10-29 5:49 [RFC PATCH v2 0/2] erofs-utils: compression inline feature Yue Hu
@ 2021-10-29 5:49 ` Yue Hu
2021-10-29 5:49 ` [RFC PATCH v2 2/2] erofs-utils: fuse: " Yue Hu
1 sibling, 0 replies; 3+ messages in thread
From: Yue Hu @ 2021-10-29 5:49 UTC (permalink / raw)
To: linux-erofs; +Cc: zhangwen, Yue Hu, geshifei, shaojunjun
Currently, we only support tail-end inline data for uncompressed
files, let's support it as well for compressed files.
The idea is from Xiang.
Signed-off-by: Yue Hu <huyue2@yulong.com>
---
changes since v1:
- add 2 bytes to record compressed size of tail-pcluster suggested from
Xiang and update related code.
include/erofs/internal.h | 1 +
include/erofs_fs.h | 10 ++++--
lib/compress.c | 76 +++++++++++++++++++++++++++++++---------
lib/compressor.c | 9 ++---
lib/decompress.c | 4 +++
lib/inode.c | 40 ++++++++++-----------
mkfs/main.c | 6 ++++
7 files changed, 102 insertions(+), 44 deletions(-)
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index da7be56..3769c27 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -109,6 +109,7 @@ static inline void erofs_sb_clear_##name(void) \
EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING)
EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS)
EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER)
+EROFS_FEATURE_FUNCS(tailpacking, incompat, INCOMPAT_TAILPACKING)
EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
#define EROFS_I_EA_INITED (1 << 0)
diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index 18fc182..5a363e2 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -22,10 +22,12 @@
#define EROFS_FEATURE_INCOMPAT_LZ4_0PADDING 0x00000001
#define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002
#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002
+#define EROFS_FEATURE_INCOMPAT_TAILPACKING 0x00000004
#define EROFS_ALL_FEATURE_INCOMPAT \
(EROFS_FEATURE_INCOMPAT_LZ4_0PADDING | \
EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
- EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER)
+ EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \
+ EROFS_FEATURE_INCOMPAT_TAILPACKING)
#define EROFS_SB_EXTSLOT_SIZE 16
@@ -230,14 +232,18 @@ struct z_erofs_lz4_cfgs {
* (4B) + 2B + (4B) if compacted 2B is on.
* bit 1 : HEAD1 big pcluster (0 - off; 1 - on)
* bit 2 : HEAD2 big pcluster (0 - off; 1 - on)
+ * bit 3 : inline (un)compressed data
*/
#define Z_EROFS_ADVISE_COMPACTED_2B 0x0001
#define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002
#define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004
+#define Z_EROFS_ADVISE_TAILPACKING 0x0008
struct z_erofs_map_header {
- __le32 h_reserved1;
+ __le16 h_reserved1;
__le16 h_advise;
+ /* record the compressed size of tail-packing pcluster */
+ __le16 h_idata_size;
/*
* bit 0-3 : algorithm type of head 1 (logical cluster type 01);
* bit 4-7 : algorithm type of head 2 (logical cluster type 11).
diff --git a/lib/compress.c b/lib/compress.c
index 2093bfd..9491f9b 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -159,6 +159,17 @@ static unsigned int z_erofs_get_max_pclusterblks(struct erofs_inode *inode)
return cfg.c_physical_clusterblks;
}
+static int z_erofs_fill_inline_data(struct erofs_inode *inode, char *data,
+ unsigned int len)
+{
+ inode->idata_size = len;
+ inode->idata = malloc(inode->idata_size);
+ if (!inode->idata)
+ return -ENOMEM;
+ memcpy(inode->idata, data, inode->idata_size);
+ return 0;
+}
+
static int vle_compress_one(struct erofs_inode *inode,
struct z_erofs_vle_compress_ctx *ctx,
bool final)
@@ -169,15 +180,20 @@ static int vle_compress_one(struct erofs_inode *inode,
int ret;
static char dstbuf[EROFS_CONFIG_COMPR_MAX_SZ + EROFS_BLKSIZ];
char *const dst = dstbuf + EROFS_BLKSIZ;
+ bool tail_pcluster = false;
while (len) {
- const unsigned int pclustersize =
+ unsigned int pclustersize =
z_erofs_get_max_pclusterblks(inode) * EROFS_BLKSIZ;
bool raw;
- if (len <= pclustersize) {
+ if (!tail_pcluster && len <= pclustersize) {
if (final) {
- if (len <= EROFS_BLKSIZ)
+ /* TODO: compress with 2 pclusters */
+ if (erofs_sb_has_tailpacking()) {
+ tail_pcluster = true;
+ pclustersize = EROFS_BLKSIZ;
+ } else if (len <= EROFS_BLKSIZ)
goto nocompression;
} else {
break;
@@ -194,6 +210,16 @@ static int vle_compress_one(struct erofs_inode *inode,
inode->i_srcpath,
erofs_strerror(ret));
}
+ if (tail_pcluster && len < EROFS_BLKSIZ) {
+ ret = z_erofs_fill_inline_data(inode,
+ (char *)(ctx->queue + ctx->head), len);
+ if (ret)
+ return ret;
+ count = len;
+ raw = true;
+ ctx->compressedblks = 1;
+ goto add_head;
+ }
nocompression:
ret = write_uncompressed_extent(ctx, &len, dst);
if (ret < 0)
@@ -202,6 +228,15 @@ nocompression:
ctx->compressedblks = 1;
raw = true;
} else {
+ if (tail_pcluster && ret < EROFS_BLKSIZ &&
+ !(len - count)) {
+ ret = z_erofs_fill_inline_data(inode, dst, ret);
+ if (ret)
+ return ret;
+ raw = false;
+ ctx->compressedblks = 1;
+ goto add_head;
+ }
const unsigned int tailused = ret & (EROFS_BLKSIZ - 1);
const unsigned int padding =
erofs_sb_has_lz4_0padding() && tailused ?
@@ -226,11 +261,13 @@ nocompression:
raw = false;
}
+add_head:
ctx->head += count;
/* write compression indexes for this pcluster */
vle_write_indexes(ctx, count, raw);
- ctx->blkaddr += ctx->compressedblks;
+ if (!inode->idata_size)
+ ctx->blkaddr += ctx->compressedblks;
len -= count;
if (!final && ctx->head >= EROFS_CONFIG_COMPR_MAX_SZ) {
@@ -448,6 +485,7 @@ static void z_erofs_write_mapheader(struct erofs_inode *inode,
{
struct z_erofs_map_header h = {
.h_advise = cpu_to_le16(inode->z_advise),
+ .h_idata_size = cpu_to_le16(inode->idata_size),
.h_algorithmtype = inode->z_algorithmtype[1] << 4 |
inode->z_algorithmtype[0],
/* lclustersize */
@@ -475,7 +513,7 @@ int erofs_write_compressed_file(struct erofs_inode *inode)
fd = open(inode->i_srcpath, O_RDONLY | O_BINARY);
if (fd < 0) {
ret = -errno;
- goto err_free;
+ goto err_free_meta;
}
/* allocate main data buffer */
@@ -503,8 +541,6 @@ int erofs_write_compressed_file(struct erofs_inode *inode)
inode->z_algorithmtype[1] = algorithmtype[1];
inode->z_logical_clusterbits = LOG_BLOCK_SIZE;
- z_erofs_write_mapheader(inode, compressmeta);
-
blkaddr = erofs_mapbh(bh->block); /* start_blkaddr */
ctx.blkaddr = blkaddr;
ctx.metacur = compressmeta + Z_EROFS_LEGACY_MAP_HEADER_SIZE;
@@ -530,19 +566,23 @@ int erofs_write_compressed_file(struct erofs_inode *inode)
goto err_bdrop;
}
+ inode->idata_size = 0;
+
/* do the final round */
ret = vle_compress_one(inode, &ctx, true);
if (ret)
- goto err_bdrop;
+ goto err_free_id;
/* fall back to no compression mode */
compressed_blocks = ctx.blkaddr - blkaddr;
- if (compressed_blocks >= BLK_ROUND_UP(inode->i_size)) {
+ if (compressed_blocks >= BLK_ROUND_UP(inode->i_size) -
+ (inode->idata_size ? 1 : 0) ) {
ret = -ENOSPC;
- goto err_bdrop;
+ goto err_free_id;
}
vle_write_indexes_final(&ctx);
+ z_erofs_write_mapheader(inode, compressmeta);
close(fd);
DBG_BUGON(!compressed_blocks);
@@ -553,12 +593,11 @@ int erofs_write_compressed_file(struct erofs_inode *inode)
inode->i_srcpath, (unsigned long long)inode->i_size,
compressed_blocks);
- /*
- * TODO: need to move erofs_bdrop to erofs_write_tail_end
- * when both mkfs & kernel support compression inline.
- */
- erofs_bdrop(bh, false);
- inode->idata_size = 0;
+ if (inode->idata_size)
+ inode->bh_data = bh;
+ else
+ erofs_bdrop(bh, false);
+
inode->u.i_blocks = compressed_blocks;
legacymetasize = ctx.metacur - compressmeta;
@@ -573,11 +612,14 @@ int erofs_write_compressed_file(struct erofs_inode *inode)
inode->compressmeta = compressmeta;
return 0;
+err_free_id:
+ if (inode->idata)
+ free(inode->idata);
err_bdrop:
erofs_bdrop(bh, true); /* revoke buffer */
err_close:
close(fd);
-err_free:
+err_free_meta:
free(compressmeta);
return ret;
}
diff --git a/lib/compressor.c b/lib/compressor.c
index 8836e0c..26189b6 100644
--- a/lib/compressor.c
+++ b/lib/compressor.c
@@ -28,7 +28,7 @@ int erofs_compress_destsize(struct erofs_compress *c,
void *dst,
unsigned int dstsize)
{
- unsigned uncompressed_size;
+ unsigned compressed_size;
int ret;
DBG_BUGON(!c->alg);
@@ -41,9 +41,10 @@ int erofs_compress_destsize(struct erofs_compress *c,
return ret;
/* check if there is enough gains to compress */
- uncompressed_size = *srcsize;
- if (roundup(ret, EROFS_BLKSIZ) >= uncompressed_size *
- c->compress_threshold / 100)
+ compressed_size = *srcsize <= EROFS_BLKSIZ ? ret :
+ roundup(ret, EROFS_BLKSIZ);
+
+ if (*srcsize <= compressed_size * c->compress_threshold / 100)
return -EAGAIN;
return ret;
}
diff --git a/lib/decompress.c b/lib/decompress.c
index 490c4bc..0b6678d 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -9,6 +9,7 @@
#include "erofs/decompress.h"
#include "erofs/err.h"
+#include "erofs/print.h"
#ifdef LZ4_ENABLED
#include <lz4.h>
@@ -50,6 +51,9 @@ static int z_erofs_decompress_lz4(struct z_erofs_decompress_req *rq)
rq->decodedlength);
if (ret != (int)rq->decodedlength) {
+ erofs_err("failed to %s decompress %d in[%u, %u] out[%u]",
+ rq->partial_decoding ? "partial" : "full",
+ ret, rq->inputsize, inputmargin, rq->decodedlength);
ret = -EIO;
goto out;
}
diff --git a/lib/inode.c b/lib/inode.c
index 787e5b4..6d5c9f3 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -521,9 +521,6 @@ int erofs_prepare_tail_block(struct erofs_inode *inode)
struct erofs_buffer_head *bh;
int ret;
- if (!inode->idata_size)
- return 0;
-
bh = inode->bh_data;
if (!bh) {
bh = erofs_balloc(DATA, EROFS_BLKSIZ, 0, 0);
@@ -557,26 +554,21 @@ int erofs_prepare_inode_buffer(struct erofs_inode *inode)
inodesize = Z_EROFS_VLE_EXTENT_ALIGN(inodesize) +
inode->extent_isize;
- if (is_inode_layout_compression(inode))
- goto noinline;
-
- /*
- * if the file size is block-aligned for uncompressed files,
- * should use EROFS_INODE_FLAT_PLAIN data mapping mode.
- */
if (!inode->idata_size)
- inode->datalayout = EROFS_INODE_FLAT_PLAIN;
+ goto noinline;
bh = erofs_balloc(INODE, inodesize, 0, inode->idata_size);
if (bh == ERR_PTR(-ENOSPC)) {
int ret;
- inode->datalayout = EROFS_INODE_FLAT_PLAIN;
-noinline:
/* expend an extra block for tail-end data */
ret = erofs_prepare_tail_block(inode);
if (ret)
return ret;
+noinline:
+ if (!is_inode_layout_compression(inode))
+ inode->datalayout = EROFS_INODE_FLAT_PLAIN;
+
bh = erofs_balloc(INODE, inodesize, 0, 0);
if (IS_ERR(bh))
return PTR_ERR(bh);
@@ -584,7 +576,14 @@ noinline:
} else if (IS_ERR(bh)) {
return PTR_ERR(bh);
} else if (inode->idata_size) {
- inode->datalayout = EROFS_INODE_FLAT_INLINE;
+ if (is_inode_layout_compression(inode)) {
+ struct z_erofs_map_header *h = inode->compressmeta;
+ h->h_advise |= Z_EROFS_ADVISE_TAILPACKING;
+ erofs_dbg("%s: inline data (%u bytes)",
+ inode->i_srcpath, inode->idata_size);
+ } else {
+ inode->datalayout = EROFS_INODE_FLAT_INLINE;
+ }
/* allocate inline buffer */
ibh = erofs_battach(bh, META, inode->idata_size);
@@ -647,13 +646,12 @@ int erofs_write_tail_end(struct erofs_inode *inode)
ret = dev_write(inode->idata, pos, inode->idata_size);
if (ret)
return ret;
- if (inode->idata_size < EROFS_BLKSIZ) {
- ret = dev_fillzero(pos + inode->idata_size,
- EROFS_BLKSIZ - inode->idata_size,
- false);
- if (ret)
- return ret;
- }
+ ret = dev_fillzero(pos + inode->idata_size,
+ EROFS_BLKSIZ - inode->idata_size,
+ false);
+ if (ret)
+ return ret;
+
inode->idata_size = 0;
free(inode->idata);
inode->idata = NULL;
diff --git a/mkfs/main.c b/mkfs/main.c
index e476189..7dd29df 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -48,6 +48,7 @@ static struct option long_options[] = {
{"product-out", required_argument, NULL, 11},
{"fs-config-file", required_argument, NULL, 12},
#endif
+ {"inline", no_argument, NULL, 13},
{0, 0, 0, 0},
};
@@ -87,6 +88,7 @@ static void usage(void)
" --all-root make all files owned by root\n"
" --help display this help and exit\n"
" --max-extent-bytes=# set maximum decompressed extent size # in bytes\n"
+ " --inline tail-packing inline compressed data\n"
#ifndef NDEBUG
" --random-pclusterblks randomize pclusterblks for big pcluster (debugging only)\n"
#endif
@@ -304,6 +306,10 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
}
cfg.c_physical_clusterblks = i / EROFS_BLKSIZ;
break;
+ case 13:
+ erofs_sb_set_tailpacking();
+ erofs_warn("EXPERIMENTAL compression inline feature in use. Use at your own risk!");
+ break;
case 1:
usage();
--
2.29.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [RFC PATCH v2 2/2] erofs-utils: fuse: support tail-packing inline compressed data
2021-10-29 5:49 [RFC PATCH v2 0/2] erofs-utils: compression inline feature Yue Hu
2021-10-29 5:49 ` [RFC PATCH v2 1/2] erofs-utils: support tail-packing inline compressed data Yue Hu
@ 2021-10-29 5:49 ` Yue Hu
1 sibling, 0 replies; 3+ messages in thread
From: Yue Hu @ 2021-10-29 5:49 UTC (permalink / raw)
To: linux-erofs; +Cc: zhangwen, Yue Hu, geshifei, shaojunjun
Add tail-packing inline compressed data support for erofsfuse.
Signed-off-by: Yue Hu <huyue2@yulong.com>
---
changes since v1:
- add tail-packing information to inode and get it on first read.
- update tail-packing checking logic.
include/erofs/internal.h | 3 +
lib/decompress.c | 3 -
lib/zmap.c | 130 ++++++++++++++++++++++++++++++++++++---
3 files changed, 126 insertions(+), 10 deletions(-)
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 3769c27..ce9fb40 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -165,6 +165,8 @@ struct erofs_inode {
uint16_t z_advise;
uint8_t z_algorithmtype[2];
uint8_t z_logical_clusterbits;
+ uint16_t z_idata_size;
+ uint64_t z_idata_addr;
};
};
#ifdef WITH_ANDROID
@@ -251,6 +253,7 @@ struct erofs_map_blocks {
unsigned int m_flags;
erofs_blk_t index;
+ unsigned long m_taillcn;
};
/* super.c */
diff --git a/lib/decompress.c b/lib/decompress.c
index 0b6678d..ac5d126 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -73,9 +73,6 @@ out:
int z_erofs_decompress(struct z_erofs_decompress_req *rq)
{
if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
- if (rq->inputsize != EROFS_BLKSIZ)
- return -EFSCORRUPTED;
-
DBG_BUGON(rq->decodedlength > EROFS_BLKSIZ);
DBG_BUGON(rq->decodedlength < rq->decodedskip);
diff --git a/lib/zmap.c b/lib/zmap.c
index 1084faa..6fcb5cd 100644
--- a/lib/zmap.c
+++ b/lib/zmap.c
@@ -12,6 +12,9 @@
#include "erofs/io.h"
#include "erofs/print.h"
+static int z_erofs_map_tail_data_blocks(struct erofs_inode *vi,
+ struct erofs_map_blocks *map);
+
int z_erofs_fill_inode(struct erofs_inode *vi)
{
if (!erofs_sb_has_big_pcluster() &&
@@ -26,7 +29,68 @@ int z_erofs_fill_inode(struct erofs_inode *vi)
return 0;
}
-static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
+static erofs_off_t compacted_inline_data_addr(struct erofs_inode *vi)
+{
+ const erofs_off_t ebase = round_up(iloc(vi->nid) + vi->inode_isize +
+ vi->xattr_isize, 8) +
+ sizeof(struct z_erofs_map_header);
+ const unsigned int totalidx = DIV_ROUND_UP(vi->i_size, EROFS_BLKSIZ);
+ unsigned int compacted_4b_initial, compacted_4b_end;
+ unsigned int compacted_2b;
+ erofs_off_t addr;
+
+ compacted_4b_initial = (32 - ebase % 32) / 4;
+ if (compacted_4b_initial == 32 / 4)
+ compacted_4b_initial = 0;
+
+ if (compacted_4b_initial > totalidx) {
+ compacted_4b_initial = 0;
+ compacted_2b = 0;
+ } else if (vi->z_advise & Z_EROFS_ADVISE_COMPACTED_2B) {
+ compacted_2b = rounddown(totalidx - compacted_4b_initial, 16);
+ } else
+ compacted_2b = 0;
+
+ compacted_4b_end = totalidx - compacted_4b_initial - compacted_2b;
+
+ addr = ebase;
+ addr += compacted_4b_initial * 4;
+ addr += compacted_2b * 2;
+ if (compacted_4b_end > 1)
+ addr += (compacted_4b_end/2) * 8;
+ if (compacted_4b_end % 2)
+ addr += 8;
+
+ return addr;
+}
+
+static erofs_off_t legacy_inline_data_addr(struct erofs_inode *vi)
+{
+ const erofs_off_t ibase = iloc(vi->nid);
+ const unsigned int totalidx = DIV_ROUND_UP(vi->i_size, EROFS_BLKSIZ);
+ erofs_off_t addr;
+
+ addr = Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize +
+ vi->xattr_isize) +
+ totalidx * sizeof(struct z_erofs_vle_decompressed_index);
+ return addr;
+}
+
+static erofs_off_t z_erofs_inline_data_addr(struct erofs_inode *vi)
+{
+ const unsigned int datamode = vi->datalayout;
+
+ if (datamode == EROFS_INODE_FLAT_COMPRESSION)
+ return compacted_inline_data_addr(vi);
+
+ if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
+ return legacy_inline_data_addr(vi);
+
+ return -EINVAL;
+}
+
+static int z_erofs_fill_inode_lazy(struct erofs_inode *vi,
+ struct erofs_map_blocks *map)
{
int ret;
erofs_off_t pos;
@@ -46,6 +110,7 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
h = (struct z_erofs_map_header *)buf;
vi->z_advise = le16_to_cpu(h->h_advise);
+ vi->z_idata_size = le16_to_cpu(h->h_idata_size);
vi->z_algorithmtype[0] = h->h_algorithmtype & 15;
vi->z_algorithmtype[1] = h->h_algorithmtype >> 4;
@@ -64,6 +129,15 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
vi->nid * 1ULL);
return -EFSCORRUPTED;
}
+ if (vi->z_advise & Z_EROFS_ADVISE_TAILPACKING)
+ vi->z_idata_addr = z_erofs_inline_data_addr(vi);
+
+ if (vi->z_idata_size) {
+ ret = z_erofs_map_tail_data_blocks(vi, map);
+ if (ret)
+ return ret;
+ }
+
vi->flags |= EROFS_I_Z_INITED;
return 0;
}
@@ -375,6 +449,37 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
return 0;
}
+static int z_erofs_map_tail_data_blocks(struct erofs_inode *vi,
+ struct erofs_map_blocks *map)
+{
+ struct z_erofs_maprecorder m = {
+ .inode = vi,
+ .map = map,
+ .kaddr = map->mpage,
+ };
+ unsigned long lcn;
+ unsigned int lclusterbits, endoff;
+ int err;
+
+ lclusterbits = vi->z_logical_clusterbits;
+ lcn = (vi->i_size - 1) >> lclusterbits;
+ endoff = (vi->i_size - 1) & ((1 << lclusterbits) - 1);
+
+ err = z_erofs_load_cluster_from_disk(&m, lcn);
+ if (err)
+ return err;
+
+ if (endoff >= m.clusterofs)
+ goto out;
+
+ err = z_erofs_extent_lookback(&m, 1);
+ if (err)
+ return err;
+out:
+ map->m_taillcn = m.lcn;
+ return 0;
+}
+
static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
unsigned int initial_lcn)
{
@@ -463,12 +568,12 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
goto out;
}
- err = z_erofs_fill_inode_lazy(vi);
+ ofs = map->m_la;
+ err = z_erofs_fill_inode_lazy(vi, map);
if (err)
goto out;
lclusterbits = vi->z_logical_clusterbits;
- ofs = map->m_la;
initial_lcn = ofs >> lclusterbits;
endoff = ofs & ((1 << lclusterbits) - 1);
@@ -511,11 +616,22 @@ int z_erofs_map_blocks_iter(struct erofs_inode *vi,
}
map->m_llen = end - map->m_la;
- map->m_pa = blknr_to_addr(m.pblk);
- err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
- if (err)
- goto out;
+ if (m.lcn == map->m_taillcn && vi->z_idata_size) {
+ map->m_plen = vi->z_idata_size;
+
+ if (vi->z_advise & Z_EROFS_ADVISE_TAILPACKING)
+ map->m_pa = vi->z_idata_addr;
+ else
+ map->m_pa = blknr_to_addr(m.pblk);
+ map->m_flags |= EROFS_MAP_META;
+ } else {
+ map->m_pa = blknr_to_addr(m.pblk);
+
+ err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
+ if (err)
+ goto out;
+ }
map->m_flags |= EROFS_MAP_MAPPED;
out:
--
2.29.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-10-29 5:52 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-10-29 5:49 [RFC PATCH v2 0/2] erofs-utils: compression inline feature Yue Hu
2021-10-29 5:49 ` [RFC PATCH v2 1/2] erofs-utils: support tail-packing inline compressed data Yue Hu
2021-10-29 5:49 ` [RFC PATCH v2 2/2] erofs-utils: fuse: " Yue Hu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.