From: Gao Xiang <hsiang...@linux.alibaba.com> Just split out on-disk compressed metadata commit logic.
Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- lib/compress.c | 191 +++++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 86 deletions(-) diff --git a/lib/compress.c b/lib/compress.c index b084446..8ca4033 100644 --- a/lib/compress.c +++ b/lib/compress.c @@ -1031,6 +1031,102 @@ int z_erofs_compress_segment(struct z_erofs_compress_sctx *ctx, return 0; } +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) +{ + struct erofs_inode *inode = ictx->inode; + struct erofs_sb_info *sbi = inode->sbi; + unsigned int legacymetasize; + u8 *compressmeta; + int ret; + + /* fall back to no compression mode */ + DBG_BUGON(compressed_blocks < !!inode->idata_size); + compressed_blocks -= !!inode->idata_size; + + compressmeta = malloc(BLK_ROUND_UP(sbi, inode->i_size) * + sizeof(struct z_erofs_lcluster_index) + + Z_EROFS_LEGACY_MAP_HEADER_SIZE); + if (!compressmeta) { + ret = -ENOMEM; + goto err_free_idata; + } + ictx->metacur = compressmeta + Z_EROFS_LEGACY_MAP_HEADER_SIZE; + z_erofs_write_indexes(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 + + legacymetasize >= inode->i_size) { + z_erofs_dedupe_commit(true); + ret = -ENOSPC; + goto err_free_meta; + } + z_erofs_dedupe_commit(false); + z_erofs_write_mapheader(inode, compressmeta); + + if (!ictx->fragemitted) + sbi->saved_by_deduplication += inode->fragment_size; + + /* if the entire file is a fragment, a simplified form is used. */ + if (inode->i_size <= inode->fragment_size) { + DBG_BUGON(inode->i_size < inode->fragment_size); + DBG_BUGON(inode->fragmentoff >> 63); + *(__le64 *)compressmeta = + cpu_to_le64(inode->fragmentoff | 1ULL << 63); + inode->datalayout = EROFS_INODE_COMPRESSED_FULL; + 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)); + } 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); + + if (inode->idata_size) { + bh->op = &erofs_skip_write_bhops; + inode->bh_data = bh; + } else { + erofs_bdrop(bh, false); + } + + inode->u.i_blocks = compressed_blocks; + + if (inode->datalayout == EROFS_INODE_COMPRESSED_FULL) { + inode->extent_isize = legacymetasize; + } else { + ret = z_erofs_convert_to_compacted_format(inode, blkaddr, + legacymetasize, + compressmeta); + DBG_BUGON(ret); + } + inode->compressmeta = compressmeta; + if (!erofs_is_packed_inode(inode)) + erofs_droid_blocklist_write(inode, blkaddr, compressed_blocks); + return 0; + +err_free_meta: + free(compressmeta); + inode->compressmeta = NULL; +err_free_idata: + if (inode->idata) { + free(inode->idata); + inode->idata = NULL; + } + erofs_bdrop(bh, true); /* revoke buffer */ + return ret; +} + #ifdef EROFS_MT_ENABLED void *z_erofs_mt_wq_tls_alloc(struct erofs_workqueue *wq, void *ptr) { @@ -1260,23 +1356,9 @@ int erofs_write_compressed_file(struct erofs_inode *inode, int fd, u64 fpos) static struct z_erofs_compress_sctx sctx; struct erofs_compress_cfg *ccfg; erofs_blk_t blkaddr, compressed_blocks = 0; - unsigned int legacymetasize; int ret; bool ismt = false; struct erofs_sb_info *sbi = inode->sbi; - u8 *compressmeta = malloc(BLK_ROUND_UP(sbi, inode->i_size) * - sizeof(struct z_erofs_lcluster_index) + - Z_EROFS_LEGACY_MAP_HEADER_SIZE); - - if (!compressmeta) - return -ENOMEM; - - /* allocate main data buffer */ - bh = erofs_balloc(DATA, 0, 0, 0); - if (IS_ERR(bh)) { - ret = PTR_ERR(bh); - goto err_free_meta; - } /* initialize per-file compression setting */ inode->z_advise = 0; @@ -1321,20 +1403,24 @@ int erofs_write_compressed_file(struct erofs_inode *inode, int fd, u64 fpos) if (cfg.c_fragments && !erofs_is_packed_inode(inode)) { ret = z_erofs_fragments_dedupe(inode, fd, &ctx.tof_chksum); if (ret < 0) - goto err_bdrop; + return ret; } - blkaddr = erofs_mapbh(bh->block); /* start_blkaddr */ ctx.inode = inode; ctx.fd = fd; ctx.fpos = fpos; - ctx.metacur = compressmeta + Z_EROFS_LEGACY_MAP_HEADER_SIZE; init_list_head(&ctx.extents); ctx.fix_dedupedfrag = false; ctx.fragemitted = false; sctx = (struct z_erofs_compress_sctx) { .ictx = &ctx, }; init_list_head(&sctx.extents); + /* allocate main data buffer */ + bh = erofs_balloc(DATA, 0, 0, 0); + if (IS_ERR(bh)) + return PTR_ERR(bh); + blkaddr = erofs_mapbh(bh->block); /* start_blkaddr */ + if (cfg.c_all_fragments && !erofs_is_packed_inode(inode) && !inode->fragment_size) { ret = z_erofs_pack_file_from_fd(inode, fd, ctx.tof_chksum); @@ -1363,10 +1449,6 @@ int erofs_write_compressed_file(struct erofs_inode *inode, int fd, u64 fpos) compressed_blocks = sctx.blkaddr - blkaddr; } - /* fall back to no compression mode */ - DBG_BUGON(compressed_blocks < !!inode->idata_size); - compressed_blocks -= !!inode->idata_size; - /* generate an extent for the deduplicated fragment */ if (inode->fragment_size && !ctx.fragemitted) { struct z_erofs_extent_item *ei; @@ -1388,80 +1470,17 @@ int erofs_write_compressed_file(struct erofs_inode *inode, int fd, u64 fpos) z_erofs_commit_extent(&sctx, ei); } z_erofs_fragments_commit(inode); - if (!ismt) list_splice_tail(&sctx.extents, &ctx.extents); - z_erofs_write_indexes(&ctx); - legacymetasize = ctx.metacur - compressmeta; - /* estimate if data compression saves space or not */ - if (!inode->fragment_size && - compressed_blocks * erofs_blksiz(sbi) + inode->idata_size + - legacymetasize >= inode->i_size) { - z_erofs_dedupe_commit(true); - ret = -ENOSPC; - goto err_free_idata; - } - z_erofs_dedupe_commit(false); - z_erofs_write_mapheader(inode, compressmeta); - - if (!ctx.fragemitted) - sbi->saved_by_deduplication += inode->fragment_size; - - /* if the entire file is a fragment, a simplified form is used. */ - if (inode->i_size <= inode->fragment_size) { - DBG_BUGON(inode->i_size < inode->fragment_size); - DBG_BUGON(inode->fragmentoff >> 63); - *(__le64 *)compressmeta = - cpu_to_le64(inode->fragmentoff | 1ULL << 63); - inode->datalayout = EROFS_INODE_COMPRESSED_FULL; - 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)); - } 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); - - if (inode->idata_size) { - bh->op = &erofs_skip_write_bhops; - inode->bh_data = bh; - } else { - erofs_bdrop(bh, false); - } - - inode->u.i_blocks = compressed_blocks; - - if (inode->datalayout == EROFS_INODE_COMPRESSED_FULL) { - inode->extent_isize = legacymetasize; - } else { - ret = z_erofs_convert_to_compacted_format(inode, blkaddr, - legacymetasize, - compressmeta); - DBG_BUGON(ret); - } - inode->compressmeta = compressmeta; - if (!erofs_is_packed_inode(inode)) - erofs_droid_blocklist_write(inode, blkaddr, compressed_blocks); - return 0; - + return erofs_commit_compressed_file(&ctx, bh, blkaddr, + compressed_blocks); err_free_idata: if (inode->idata) { free(inode->idata); inode->idata = NULL; } -err_bdrop: erofs_bdrop(bh, true); /* revoke buffer */ -err_free_meta: - free(compressmeta); - inode->compressmeta = NULL; return ret; } -- 2.30.2