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;
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 */
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);
/* 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) {
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);
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;
}
* 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;
* 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;
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;
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;
}
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;
}
* 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 &&
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 */
if (ret < 0)
return ret;
e->inlined = true;
- e->compressedblks = 1;
+ e->plen = blksz;
e->raw = false;
} else {
unsigned int tailused, padding;
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);
/* 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;
}
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;
}
int z_erofs_convert_to_compacted_format(struct erofs_inode *inode,
- erofs_blk_t blkaddr,
+ erofs_off_t pstart,
unsigned int legacymetasize,
void *compressmeta)
{
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",
}
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;
struct erofs_inode *inode = ictx->inode;
ctx->remaining -= inode->fragment_size;
}
- ctx->blkaddr = blkaddr;
+ ctx->pstart = pstart;
while (ctx->remaining) {
const u64 rx = min_t(u64, ctx->remaining,
Z_EROFS_COMPR_QUEUE_SZ - ctx->tail);
ei->e = (struct z_erofs_inmem_extent) {
.length = 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);
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 = malloc(BLK_ROUND_UP(sbi, inode->i_size) *
sizeof(struct z_erofs_lcluster_index) +
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;
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;
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:
{
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;
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, 0);
}
DBG_BUGON(!head);
- blkaddr = erofs_mapbh(NULL, bh->block);
+ pstart = erofs_pos(sbi, erofs_mapbh(NULL, bh->block));
ret = 0;
do {
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);
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);
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
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) {
};
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: