[PATCH v2 7/8] erofs-utils: lib: use compressed offsets in `struct z_erofs_inmem_extent`
Gao Xiang
hsiangkao at linux.alibaba.com
Sun Mar 16 14:36:38 AEDT 2025
... to prepare for the new on-disk encoded extents.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
no change.
include/erofs/dedupe.h | 4 +-
lib/compress.c | 164 +++++++++++++++++++++--------------------
lib/dedupe.c | 12 +--
3 files changed, 91 insertions(+), 89 deletions(-)
diff --git a/include/erofs/dedupe.h b/include/erofs/dedupe.h
index 4cbfb2c..1af08e3 100644
--- a/include/erofs/dedupe.h
+++ b/include/erofs/dedupe.h
@@ -13,8 +13,8 @@ extern "C"
#include "internal.h"
struct z_erofs_inmem_extent {
- erofs_blk_t blkaddr;
- unsigned int compressedblks;
+ erofs_off_t pstart;
+ unsigned int plen;
unsigned int length;
bool raw, partial, inlined;
};
diff --git a/lib/compress.c b/lib/compress.c
index 97eb776..98288d4 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -78,7 +78,7 @@ struct z_erofs_compress_sctx { /* segment context */
unsigned int head, tail;
unsigned int pclustersize;
- erofs_blk_t blkaddr; /* pointing to the next blkaddr */
+ erofs_off_t pstart;
u16 clusterofs;
int seg_idx;
@@ -143,11 +143,14 @@ static void z_erofs_write_full_indexes(struct z_erofs_compress_ictx *ctx,
struct erofs_sb_info *sbi = inode->sbi;
unsigned int clusterofs = ctx->clusterofs;
unsigned int count = e->length;
- unsigned int d0 = 0, d1 = (clusterofs + count) / erofs_blksiz(sbi);
+ unsigned int bbits = sbi->blkszbits;
+ unsigned int d0 = 0, d1 = (clusterofs + count) >> bbits;
struct z_erofs_lcluster_index di;
unsigned int type, advise;
DBG_BUGON(!count);
+ DBG_BUGON(e->pstart & (BIT(bbits) - 1));
+
di.di_clusterofs = cpu_to_le16(ctx->clusterofs);
/* whether the tail-end (un)compressed block or not */
@@ -162,11 +165,10 @@ static void z_erofs_write_full_indexes(struct z_erofs_compress_ictx *ctx,
Z_EROFS_LCLUSTER_TYPE_HEAD1;
di.di_advise = cpu_to_le16(type);
- if (inode->datalayout == EROFS_INODE_COMPRESSED_FULL &&
- !e->compressedblks)
+ if (inode->datalayout == EROFS_INODE_COMPRESSED_FULL && !e->plen)
di.di_u.blkaddr = cpu_to_le32(inode->fragmentoff >> 32);
else
- di.di_u.blkaddr = cpu_to_le32(e->blkaddr);
+ di.di_u.blkaddr = cpu_to_le32(e->pstart >> bbits);
memcpy(ctx->metacur, &di, sizeof(di));
ctx->metacur += sizeof(di);
@@ -180,7 +182,7 @@ static void z_erofs_write_full_indexes(struct z_erofs_compress_ictx *ctx,
/* XXX: big pcluster feature should be per-inode */
if (d0 == 1 && erofs_sb_has_big_pcluster(sbi)) {
type = Z_EROFS_LCLUSTER_TYPE_NONHEAD;
- di.di_u.delta[0] = cpu_to_le16(e->compressedblks |
+ di.di_u.delta[0] = cpu_to_le16((e->plen >> bbits) |
Z_EROFS_LI_D0_CBLKCNT);
di.di_u.delta[1] = cpu_to_le16(d1);
} else if (d0) {
@@ -208,10 +210,10 @@ static void z_erofs_write_full_indexes(struct z_erofs_compress_ictx *ctx,
Z_EROFS_LCLUSTER_TYPE_HEAD1;
if (inode->datalayout == EROFS_INODE_COMPRESSED_FULL &&
- !e->compressedblks)
+ !e->plen)
di.di_u.blkaddr = cpu_to_le32(inode->fragmentoff >> 32);
else
- di.di_u.blkaddr = cpu_to_le32(e->blkaddr);
+ di.di_u.blkaddr = cpu_to_le32(e->pstart >> bbits);
if (e->partial) {
DBG_BUGON(e->raw);
@@ -223,12 +225,12 @@ static void z_erofs_write_full_indexes(struct z_erofs_compress_ictx *ctx,
memcpy(ctx->metacur, &di, sizeof(di));
ctx->metacur += sizeof(di);
- count -= erofs_blksiz(sbi) - clusterofs;
+ count -= (1 << bbits) - clusterofs;
clusterofs = 0;
++d0;
--d1;
- } while (clusterofs + count >= erofs_blksiz(sbi));
+ } while (clusterofs + count >= 1 << bbits);
ctx->clusterofs = clusterofs + count;
}
@@ -307,7 +309,7 @@ static int z_erofs_compress_dedupe(struct z_erofs_compress_sctx *ctx)
* CBLKCNT as the first step. Even laterly, an one-block
* decompresssion could be done as another try in practice.
*/
- if (dctx.e.compressedblks > 1 &&
+ if (dctx.e.plen > erofs_blksiz(sbi) &&
((ctx->clusterofs + ei->e.length - delta) & lclustermask) +
dctx.e.length < 2 * (lclustermask + 1))
break;
@@ -327,7 +329,7 @@ static int z_erofs_compress_dedupe(struct z_erofs_compress_sctx *ctx)
* previous big pcluster, make sure that the previous
* CBLKCNT is still kept.
*/
- if (ei->e.compressedblks > 1 &&
+ if (ei->e.plen > erofs_blksiz(sbi) &&
(ctx->clusterofs & lclustermask) + ei->e.length
- delta < 2 * (lclustermask + 1))
break;
@@ -340,11 +342,10 @@ static int z_erofs_compress_dedupe(struct z_erofs_compress_sctx *ctx)
inode->datalayout = EROFS_INODE_COMPRESSED_FULL;
erofs_sb_set_dedupe(sbi);
- sbi->saved_by_deduplication +=
- dctx.e.compressedblks * erofs_blksiz(sbi);
- erofs_dbg("Dedupe %u %scompressed data (delta %d) to %u of %u blocks",
+ sbi->saved_by_deduplication += dctx.e.plen;
+ erofs_dbg("Dedupe %u %scompressed data (delta %d) to %llu of %u bytes",
dctx.e.length, dctx.e.raw ? "un" : "",
- delta, dctx.e.blkaddr, dctx.e.compressedblks);
+ delta, dctx.e.pstart | 0ULL, dctx.e.plen);
z_erofs_commit_extent(ctx, ei);
ei = ctx->pivot;
@@ -391,9 +392,9 @@ static int write_uncompressed_block(struct z_erofs_compress_sctx *ctx,
memcpy(ctx->membuf + ctx->memoff, dst, erofs_blksiz(sbi));
ctx->memoff += erofs_blksiz(sbi);
} else {
- erofs_dbg("Writing %u uncompressed data to block %u", count,
- ctx->blkaddr);
- ret = erofs_blk_write(sbi, dst, ctx->blkaddr, 1);
+ erofs_dbg("Writing %u uncompressed data to %llu", count,
+ ctx->pstart | 0ULL);
+ ret = erofs_dev_write(sbi, dst, ctx->pstart, erofs_blksiz(sbi));
if (ret)
return ret;
}
@@ -426,12 +427,12 @@ static int write_uncompressed_extents(struct z_erofs_compress_sctx *ctx,
ei->e = (struct z_erofs_inmem_extent) {
.length = count,
- .compressedblks = BLK_ROUND_UP(inode->sbi, count),
+ .plen = round_up(count, erofs_blksiz(inode->sbi)),
.raw = true,
- .blkaddr = ctx->blkaddr,
+ .pstart = ctx->pstart,
};
- if (ctx->blkaddr != EROFS_NULL_ADDR)
- ctx->blkaddr += ei->e.compressedblks;
+ if (ctx->pstart != EROFS_NULL_ADDR)
+ ctx->pstart += ei->e.plen;
z_erofs_commit_extent(ctx, ei);
ctx->head += count;
}
@@ -619,7 +620,7 @@ nocompression:
* since there is no way to generate compressed indexes after
* the time that ztailpacking is decided.
*/
- e->compressedblks = 1;
+ e->plen = blksz;
e->raw = true;
} else if (may_packing && len == e->length &&
compressedsize < ctx->pclustersize &&
@@ -629,7 +630,7 @@ frag_packing:
len, ictx->tof_chksum);
if (ret < 0)
return ret;
- e->compressedblks = 0; /* indicate a fragment */
+ e->plen = 0; /* indicate a fragment */
e->raw = false;
ictx->fragemitted = true;
/* tailpcluster should be less than 1 block */
@@ -648,7 +649,7 @@ frag_packing:
if (ret < 0)
return ret;
e->inlined = true;
- e->compressedblks = 1;
+ e->plen = blksz;
e->raw = false;
} else {
unsigned int tailused, padding;
@@ -675,8 +676,8 @@ frag_packing:
return ret;
}
- e->compressedblks = BLK_ROUND_UP(sbi, compressedsize);
- DBG_BUGON(e->compressedblks * blksz >= e->length);
+ e->plen = round_up(compressedsize, blksz);
+ DBG_BUGON(e->plen >= e->length);
padding = 0;
tailused = compressedsize & (blksz - 1);
@@ -691,18 +692,18 @@ frag_packing:
/* write compressed data */
if (ctx->membuf) {
- erofs_dbg("Writing %u compressed data of %u blocks of %s",
- e->length, e->compressedblks, inode->i_srcpath);
+ erofs_dbg("Writing %u compressed data of %u bytes of %s",
+ e->length, e->plen, inode->i_srcpath);
- memcpy(ctx->membuf + ctx->memoff, dst - padding,
- e->compressedblks * blksz);
- ctx->memoff += e->compressedblks * blksz;
+ memcpy(ctx->membuf + ctx->memoff,
+ dst - padding, e->plen);
+ ctx->memoff += e->plen;
} else {
- erofs_dbg("Writing %u compressed data to %u of %u blocks",
- e->length, ctx->blkaddr, e->compressedblks);
+ erofs_dbg("Writing %u compressed data to %llu of %u bytes",
+ e->length, ctx->pstart, e->plen);
- ret = erofs_blk_write(sbi, dst - padding, ctx->blkaddr,
- e->compressedblks);
+ ret = erofs_dev_write(sbi, dst - padding, ctx->pstart,
+ e->plen);
if (ret)
return ret;
}
@@ -711,9 +712,9 @@ frag_packing:
may_packing = false;
}
e->partial = false;
- e->blkaddr = ctx->blkaddr;
- if (ctx->blkaddr != EROFS_NULL_ADDR)
- ctx->blkaddr += e->compressedblks;
+ e->pstart = ctx->pstart;
+ if (ctx->pstart != EROFS_NULL_ADDR)
+ ctx->pstart += e->plen;
if (!may_inline && !may_packing && !is_packed_inode)
(void)z_erofs_dedupe_insert(e, ctx->queue + ctx->head);
ctx->head += e->length;
@@ -864,7 +865,7 @@ static void *write_compacted_indexes(u8 *out,
}
int z_erofs_convert_to_compacted_format(struct erofs_inode *inode,
- erofs_blk_t blkaddr,
+ erofs_off_t pstart,
unsigned int legacymetasize,
void *compressmeta)
{
@@ -883,15 +884,19 @@ int z_erofs_convert_to_compacted_format(struct erofs_inode *inode,
unsigned int compacted_2b;
bool dummy_head;
bool big_pcluster = erofs_sb_has_big_pcluster(sbi);
+ erofs_blk_t blkaddr;
if (logical_clusterbits < sbi->blkszbits)
return -EINVAL;
+ if (pstart & (erofs_blksiz(sbi) - 1))
+ return -EINVAL;
if (logical_clusterbits > 14) {
erofs_err("compact format is unsupported for lcluster size %u",
1 << logical_clusterbits);
return -EOPNOTSUPP;
}
+ blkaddr = pstart >> sbi->blkszbits;
if (inode->z_advise & Z_EROFS_ADVISE_COMPACTED_2B) {
if (logical_clusterbits > 12) {
erofs_err("compact 2B is unsupported for lcluster size %u",
@@ -1064,12 +1069,12 @@ void z_erofs_drop_inline_pcluster(struct erofs_inode *inode)
}
int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
- u64 offset, erofs_blk_t blkaddr)
+ u64 offset, erofs_off_t pstart)
{
struct z_erofs_compress_ictx *ictx = ctx->ictx;
int fd = ictx->fd;
- ctx->blkaddr = blkaddr;
+ ctx->pstart = pstart;
while (ctx->remaining) {
const u64 rx = min_t(u64, ctx->remaining,
Z_EROFS_COMPR_QUEUE_SZ - ctx->tail);
@@ -1109,10 +1114,10 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
ei->e = (struct z_erofs_inmem_extent) {
.length = ictx->inode->fragment_size,
- .compressedblks = 0,
+ .plen = 0,
.raw = false,
.partial = false,
- .blkaddr = ctx->blkaddr,
+ .pstart = ctx->pstart,
};
init_list_head(&ei->list);
z_erofs_commit_extent(ctx, ei);
@@ -1122,20 +1127,19 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx,
int erofs_commit_compressed_file(struct z_erofs_compress_ictx *ictx,
struct erofs_buffer_head *bh,
- erofs_blk_t blkaddr,
- erofs_blk_t compressed_blocks)
+ erofs_off_t pstart, erofs_off_t ptotal)
{
struct erofs_inode *inode = ictx->inode;
struct erofs_sb_info *sbi = inode->sbi;
- unsigned int legacymetasize;
+ unsigned int legacymetasize, bbits = sbi->blkszbits;
u8 *compressmeta;
int ret;
z_erofs_fragments_commit(inode);
/* fall back to no compression mode */
- DBG_BUGON(compressed_blocks < !!inode->idata_size);
- compressed_blocks -= !!inode->idata_size;
+ DBG_BUGON(pstart < (!!inode->idata_size) << bbits);
+ ptotal -= (!!inode->idata_size) << bbits;
compressmeta = z_erofs_write_indexes(ictx);
if (!compressmeta) {
@@ -1145,8 +1149,7 @@ int erofs_commit_compressed_file(struct z_erofs_compress_ictx *ictx,
legacymetasize = ictx->metacur - compressmeta;
/* estimate if data compression saves space or not */
- if (!inode->fragment_size &&
- compressed_blocks * erofs_blksiz(sbi) + inode->idata_size +
+ if (!inode->fragment_size && ptotal + inode->idata_size +
legacymetasize >= inode->i_size) {
z_erofs_dedupe_commit(true);
ret = -ENOSPC;
@@ -1167,17 +1170,15 @@ int erofs_commit_compressed_file(struct z_erofs_compress_ictx *ictx,
legacymetasize = Z_EROFS_LEGACY_MAP_HEADER_SIZE;
}
- if (compressed_blocks) {
- ret = erofs_bh_balloon(bh, erofs_pos(sbi, compressed_blocks));
- DBG_BUGON(ret != erofs_blksiz(sbi));
+ if (ptotal) {
+ ret = erofs_bh_balloon(bh, ptotal);
} else {
if (!cfg.c_fragments && !cfg.c_dedupe)
DBG_BUGON(!inode->idata_size);
}
- erofs_info("compressed %s (%llu bytes) into %u blocks",
- inode->i_srcpath, (unsigned long long)inode->i_size,
- compressed_blocks);
+ erofs_info("compressed %s (%llu bytes) into %u bytes",
+ inode->i_srcpath, inode->i_size | 0ULL, ptotal);
if (inode->idata_size) {
bh->op = &erofs_skip_write_bhops;
@@ -1186,19 +1187,20 @@ int erofs_commit_compressed_file(struct z_erofs_compress_ictx *ictx,
erofs_bdrop(bh, false);
}
- inode->u.i_blocks = compressed_blocks;
+ inode->u.i_blocks = BLK_ROUND_UP(sbi, ptotal);
if (inode->datalayout == EROFS_INODE_COMPRESSED_FULL) {
inode->extent_isize = legacymetasize;
} else {
- ret = z_erofs_convert_to_compacted_format(inode, blkaddr,
+ ret = z_erofs_convert_to_compacted_format(inode, pstart,
legacymetasize,
compressmeta);
DBG_BUGON(ret);
}
inode->compressmeta = compressmeta;
if (!erofs_is_packed_inode(inode))
- erofs_droid_blocklist_write(inode, blkaddr, compressed_blocks);
+ erofs_droid_blocklist_write(inode, pstart >> bbits,
+ inode->u.i_blocks);
return 0;
err_free_meta:
@@ -1326,25 +1328,25 @@ int z_erofs_merge_segment(struct z_erofs_compress_ictx *ictx,
{
struct z_erofs_extent_item *ei, *n;
struct erofs_sb_info *sbi = ictx->inode->sbi;
- erofs_blk_t blkoff = 0;
+ erofs_off_t off = 0;
int ret = 0, ret2;
list_for_each_entry_safe(ei, n, &sctx->extents, list) {
list_del(&ei->list);
list_add_tail(&ei->list, &ictx->extents);
- if (ei->e.blkaddr != EROFS_NULL_ADDR) /* deduped extents */
+ if (ei->e.pstart != EROFS_NULL_ADDR) /* deduped extents */
continue;
- ei->e.blkaddr = sctx->blkaddr;
- sctx->blkaddr += ei->e.compressedblks;
+ ei->e.pstart = sctx->pstart;
+ sctx->pstart += ei->e.plen;
/* skip write data but leave blkaddr for inline fallback */
- if (ei->e.inlined || !ei->e.compressedblks)
+ if (ei->e.inlined || !ei->e.plen)
continue;
- ret2 = erofs_blk_write(sbi, sctx->membuf + blkoff * erofs_blksiz(sbi),
- ei->e.blkaddr, ei->e.compressedblks);
- blkoff += ei->e.compressedblks;
+ ret2 = erofs_dev_write(sbi, sctx->membuf + off, ei->e.pstart,
+ ei->e.plen);
+ off += ei->e.plen;
if (ret2) {
ret = ret2;
continue;
@@ -1416,7 +1418,7 @@ int erofs_mt_write_compressed_file(struct z_erofs_compress_ictx *ictx)
struct erofs_sb_info *sbi = ictx->inode->sbi;
struct erofs_buffer_head *bh = NULL;
struct erofs_compress_work *head = ictx->mtworks, *cur;
- erofs_blk_t blkaddr, compressed_blocks = 0;
+ erofs_off_t pstart, ptotal = 0;
int ret;
bh = erofs_balloc(sbi->bmgr, DATA, 0, 0);
@@ -1426,7 +1428,7 @@ int erofs_mt_write_compressed_file(struct z_erofs_compress_ictx *ictx)
}
DBG_BUGON(!head);
- blkaddr = erofs_mapbh(NULL, bh->block);
+ pstart = erofs_pos(sbi, erofs_mapbh(NULL, bh->block));
ret = 0;
do {
@@ -1441,13 +1443,13 @@ int erofs_mt_write_compressed_file(struct z_erofs_compress_ictx *ictx)
if (!ret) {
int ret2;
- cur->ctx.blkaddr = blkaddr;
+ cur->ctx.pstart = pstart;
ret2 = z_erofs_merge_segment(ictx, &cur->ctx);
if (ret2)
ret = ret2;
- compressed_blocks += cur->ctx.blkaddr - blkaddr;
- blkaddr = cur->ctx.blkaddr;
+ ptotal += cur->ctx.pstart - pstart;
+ pstart = cur->ctx.pstart;
}
pthread_mutex_lock(&z_erofs_mt_ctrl.mutex);
@@ -1458,8 +1460,7 @@ int erofs_mt_write_compressed_file(struct z_erofs_compress_ictx *ictx)
if (ret)
goto out;
- ret = erofs_commit_compressed_file(ictx, bh,
- blkaddr - compressed_blocks, compressed_blocks);
+ ret = erofs_commit_compressed_file(ictx, bh, pstart - ptotal, ptotal);
out:
close(ictx->fd);
@@ -1586,7 +1587,8 @@ int erofs_write_compressed_file(struct z_erofs_compress_ictx *ictx)
static struct z_erofs_compress_sctx sctx;
struct erofs_compress_cfg *ccfg = ictx->ccfg;
struct erofs_inode *inode = ictx->inode;
- erofs_blk_t blkaddr;
+ struct erofs_sb_info *sbi = inode->sbi;
+ erofs_off_t pstart;
int ret;
#ifdef EROFS_MT_ENABLED
@@ -1600,7 +1602,7 @@ int erofs_write_compressed_file(struct z_erofs_compress_ictx *ictx)
ret = PTR_ERR(bh);
goto err_free_idata;
}
- blkaddr = erofs_mapbh(NULL, bh->block); /* start_blkaddr */
+ pstart = erofs_mapbh(NULL, bh->block) << sbi->blkszbits;
ictx->seg_num = 1;
sctx = (struct z_erofs_compress_sctx) {
@@ -1614,13 +1616,13 @@ int erofs_write_compressed_file(struct z_erofs_compress_ictx *ictx)
};
init_list_head(&sctx.extents);
- ret = z_erofs_compress_segment(&sctx, -1, blkaddr);
+ ret = z_erofs_compress_segment(&sctx, -1, pstart);
if (ret)
goto err_free_idata;
list_splice_tail(&sctx.extents, &ictx->extents);
- ret = erofs_commit_compressed_file(ictx, bh, blkaddr,
- sctx.blkaddr - blkaddr);
+ ret = erofs_commit_compressed_file(ictx, bh, pstart,
+ sctx.pstart - pstart);
goto out;
err_free_idata:
diff --git a/lib/dedupe.c b/lib/dedupe.c
index bc62841..5bfb566 100644
--- a/lib/dedupe.c
+++ b/lib/dedupe.c
@@ -71,8 +71,8 @@ struct z_erofs_dedupe_item {
long long hash;
u64 prefix_xxh64;
- erofs_blk_t compressed_blkaddr;
- unsigned int compressed_blks;
+ erofs_off_t pstart;
+ unsigned int plen;
int original_length;
bool partial, raw;
@@ -139,8 +139,8 @@ int z_erofs_dedupe_match(struct z_erofs_dedupe_ctx *ctx)
(window_size + extra < e->original_length);
ctx->e.raw = e->raw;
ctx->e.inlined = false;
- ctx->e.blkaddr = e->compressed_blkaddr;
- ctx->e.compressedblks = e->compressed_blks;
+ ctx->e.pstart = e->pstart;
+ ctx->e.plen = e->plen;
return 0;
}
return -ENOENT;
@@ -165,8 +165,8 @@ int z_erofs_dedupe_insert(struct z_erofs_inmem_extent *e,
di->hash = erofs_rolling_hash_init(original_data,
window_size, true);
memcpy(di->payload, original_data, e->length);
- di->compressed_blkaddr = e->blkaddr;
- di->compressed_blks = e->compressedblks;
+ di->pstart = e->pstart;
+ di->plen = e->plen;
di->partial = e->partial;
di->raw = e->raw;
--
2.43.5
More information about the Linux-erofs
mailing list