erofs-utils: lib: split vle_compress_one()
authorGao Xiang <hsiangkao@linux.alibaba.com>
Mon, 18 Dec 2023 14:57:09 +0000 (22:57 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Sun, 14 Jan 2024 09:16:52 +0000 (17:16 +0800)
Split compression for each extent into a new helper for later reworking.

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20231218145710.132164-2-hsiangkao@linux.alibaba.com
lib/compress.c

index a5ef6e4a505ef023963bca637b6c8a33c03913ac..eafbad148cb009712a81c6bb0f03c06e68adad20 100644 (file)
@@ -400,7 +400,8 @@ static bool z_erofs_fixup_deduped_fragment(struct z_erofs_vle_compress_ctx *ctx,
        return true;
 }
 
-static int vle_compress_one(struct z_erofs_vle_compress_ctx *ctx)
+static int __z_erofs_compress_one(struct z_erofs_vle_compress_ctx *ctx,
+                                 struct z_erofs_inmem_extent *e)
 {
        static char dstbuf[EROFS_CONFIG_COMPR_MAX_SZ + EROFS_MAX_BLOCK_SIZE];
        struct erofs_inode *inode = ctx->inode;
@@ -411,181 +412,177 @@ static int vle_compress_one(struct z_erofs_vle_compress_ctx *ctx)
        unsigned int len = ctx->tail - ctx->head;
        bool is_packed_inode = erofs_is_packed_inode(inode);
        bool final = !ctx->remaining;
+       bool may_packing = (cfg.c_fragments && final && !is_packed_inode);
+       bool may_inline = (cfg.c_ztailpacking && final && !may_packing);
+       unsigned int compressedsize;
        int ret;
 
-       while (len) {
-               bool may_packing = (cfg.c_fragments && final &&
-                                  !is_packed_inode);
-               bool may_inline = (cfg.c_ztailpacking && final &&
-                                 !may_packing);
-               bool fix_dedupedfrag = ctx->fix_dedupedfrag;
-               unsigned int compressedsize;
-
-               if (z_erofs_compress_dedupe(ctx, &len))
-                       break;
-
-               if (len <= ctx->pclustersize) {
-                       if (!final || !len)
-                               break;
-                       if (may_packing) {
-                               if (inode->fragment_size && !fix_dedupedfrag) {
-                                       ctx->pclustersize = roundup(len, blksz);
-                                       goto fix_dedupedfrag;
-                               }
-                               ctx->e.length = len;
-                               goto frag_packing;
+       if (len <= ctx->pclustersize) {
+               if (!final || !len)
+                       return 1;
+               if (may_packing) {
+                       if (inode->fragment_size && !ctx->fix_dedupedfrag) {
+                               ctx->pclustersize = roundup(len, blksz);
+                               goto fix_dedupedfrag;
                        }
-                       if (!may_inline && len <= blksz)
-                               goto nocompression;
+                       e->length = len;
+                       goto frag_packing;
                }
+               if (!may_inline && len <= blksz)
+                       goto nocompression;
+       }
 
-               ctx->e.length = min(len,
-                               cfg.c_max_decompressed_extent_bytes);
+       e->length = min(len, cfg.c_max_decompressed_extent_bytes);
+       ret = erofs_compress_destsize(h, ctx->queue + ctx->head,
+                                     &e->length, dst, ctx->pclustersize);
+       if (ret <= 0) {
+               erofs_err("failed to compress %s: %s", inode->i_srcpath,
+                         erofs_strerror(ret));
+               return ret;
+       }
 
-               ret = erofs_compress_destsize(h, ctx->queue + ctx->head,
-                               &ctx->e.length, dst, ctx->pclustersize);
-               if (ret <= 0) {
-                       erofs_err("failed to compress %s: %s", inode->i_srcpath,
-                                 erofs_strerror(ret));
-                       return ret;
-               }
+       compressedsize = ret;
+       /* even compressed size is smaller, there is no real gain */
+       if (!(may_inline && e->length == len && ret < blksz))
+               ret = roundup(ret, blksz);
 
-               compressedsize = ret;
-               /* even compressed size is smaller, there is no real gain */
-               if (!(may_inline && ctx->e.length == len && ret < blksz))
-                       ret = roundup(ret, blksz);
-
-               /* check if there is enough gain to keep the compressed data */
-               if (ret * h->compress_threshold / 100 >= ctx->e.length) {
-                       if (may_inline && len < blksz) {
-                               ret = z_erofs_fill_inline_data(inode,
-                                               ctx->queue + ctx->head,
-                                               len, true);
-                       } else {
-                               may_inline = false;
-                               may_packing = false;
+       /* check if there is enough gain to keep the compressed data */
+       if (ret * h->compress_threshold / 100 >= e->length) {
+               if (may_inline && len < blksz) {
+                       ret = z_erofs_fill_inline_data(inode,
+                                       ctx->queue + ctx->head, len, true);
+               } else {
+                       may_inline = false;
+                       may_packing = false;
 nocompression:
-                               ret = write_uncompressed_extent(ctx, &len, dst);
-                       }
+                       ret = write_uncompressed_extent(ctx, &len, dst);
+               }
 
-                       if (ret < 0)
-                               return ret;
-                       ctx->e.length = ret;
+               if (ret < 0)
+                       return ret;
+               e->length = ret;
 
-                       /*
-                        * XXX: For now, we have to leave `ctx->compressedblks
-                        * = 1' since there is no way to generate compressed
-                        * indexes after the time that ztailpacking is decided.
-                        */
-                       ctx->e.compressedblks = 1;
-                       ctx->e.raw = true;
-               } else if (may_packing && len == ctx->e.length &&
-                          compressedsize < ctx->pclustersize &&
-                          (!inode->fragment_size || fix_dedupedfrag)) {
+               /*
+                * XXX: For now, we have to leave `ctx->compressedblk = 1'
+                * since there is no way to generate compressed indexes after
+                * the time that ztailpacking is decided.
+                */
+               e->compressedblks = 1;
+               e->raw = true;
+       } else if (may_packing && len == e->length &&
+                  compressedsize < ctx->pclustersize &&
+                  (!inode->fragment_size || ctx->fix_dedupedfrag)) {
 frag_packing:
-                       ret = z_erofs_pack_fragments(inode,
-                                                    ctx->queue + ctx->head,
-                                                    len, ctx->tof_chksum);
-                       if (ret < 0)
-                               return ret;
-                       ctx->e.compressedblks = 0; /* indicate a fragment */
-                       ctx->e.raw = false;
-                       ctx->fragemitted = true;
-                       fix_dedupedfrag = false;
-               /* tailpcluster should be less than 1 block */
-               } else if (may_inline && len == ctx->e.length &&
-                          compressedsize < blksz) {
-                       if (ctx->clusterofs + len <= blksz) {
-                               inode->eof_tailraw = malloc(len);
-                               if (!inode->eof_tailraw)
-                                       return -ENOMEM;
-
-                               memcpy(inode->eof_tailraw,
-                                      ctx->queue + ctx->head, len);
-                               inode->eof_tailrawsize = len;
-                       }
-
-                       ret = z_erofs_fill_inline_data(inode, dst,
-                                       compressedsize, false);
-                       if (ret < 0)
-                               return ret;
-                       ctx->e.compressedblks = 1;
-                       ctx->e.raw = false;
-               } else {
-                       unsigned int tailused, padding;
+               ret = z_erofs_pack_fragments(inode, ctx->queue + ctx->head,
+                                            len, ctx->tof_chksum);
+               if (ret < 0)
+                       return ret;
+               e->compressedblks = 0; /* indicate a fragment */
+               e->raw = false;
+               ctx->fragemitted = true;
+       /* tailpcluster should be less than 1 block */
+       } else if (may_inline && len == e->length && compressedsize < blksz) {
+               if (ctx->clusterofs + len <= blksz) {
+                       inode->eof_tailraw = malloc(len);
+                       if (!inode->eof_tailraw)
+                               return -ENOMEM;
+
+                       memcpy(inode->eof_tailraw, ctx->queue + ctx->head, len);
+                       inode->eof_tailrawsize = len;
+               }
 
-                       /*
-                        * If there's space left for the last round when
-                        * deduping fragments, try to read the fragment and
-                        * recompress a little more to check whether it can be
-                        * filled up. Fix up the fragment if succeeds.
-                        * Otherwise, just drop it and go to packing.
-                        */
-                       if (may_packing && len == ctx->e.length &&
-                           (compressedsize & (blksz - 1)) &&
-                           ctx->tail < sizeof(ctx->queue)) {
-                               ctx->pclustersize =
-                                       roundup(compressedsize, blksz);
-                               goto fix_dedupedfrag;
-                       }
+               ret = z_erofs_fill_inline_data(inode, dst,
+                               compressedsize, false);
+               if (ret < 0)
+                       return ret;
+               e->compressedblks = 1;
+               e->raw = false;
+       } else {
+               unsigned int tailused, padding;
 
-                       if (may_inline && len == ctx->e.length)
-                               tryrecompress_trailing(ctx, h,
-                                               ctx->queue + ctx->head,
-                                               &ctx->e.length, dst,
-                                               &compressedsize);
+               /*
+                * If there's space left for the last round when deduping
+                * fragments, try to read the fragment and recompress a little
+                * more to check whether it can be filled up.  Fix the fragment
+                * if succeeds.  Otherwise, just drop it and go on packing.
+                */
+               if (may_packing && len == e->length &&
+                   (compressedsize & (blksz - 1)) &&
+                   ctx->tail < sizeof(ctx->queue)) {
+                       ctx->pclustersize = roundup(compressedsize, blksz);
+                       goto fix_dedupedfrag;
+               }
 
-                       ctx->e.compressedblks = BLK_ROUND_UP(sbi, compressedsize);
-                       DBG_BUGON(ctx->e.compressedblks * blksz >=
-                                 ctx->e.length);
+               if (may_inline && len == e->length)
+                       tryrecompress_trailing(ctx, h, ctx->queue + ctx->head,
+                                       &e->length, dst, &compressedsize);
 
-                       padding = 0;
-                       tailused = compressedsize & (blksz - 1);
-                       if (tailused)
-                               padding = blksz - tailused;
-
-                       /* zero out garbage trailing data for non-0padding */
-                       if (!erofs_sb_has_lz4_0padding(sbi)) {
-                               memset(dst + compressedsize, 0, padding);
-                               padding = 0;
-                       }
+               e->compressedblks = BLK_ROUND_UP(sbi, compressedsize);
+               DBG_BUGON(e->compressedblks * blksz >= e->length);
 
-                       /* write compressed data */
-                       erofs_dbg("Writing %u compressed data to %u of %u blocks",
-                                 ctx->e.length, ctx->blkaddr,
-                                 ctx->e.compressedblks);
+               padding = 0;
+               tailused = compressedsize & (blksz - 1);
+               if (tailused)
+                       padding = blksz - tailused;
 
-                       ret = blk_write(sbi, dst - padding, ctx->blkaddr,
-                                       ctx->e.compressedblks);
-                       if (ret)
-                               return ret;
-                       ctx->e.raw = false;
-                       may_inline = false;
-                       may_packing = false;
+               /* zero out garbage trailing data for non-0padding */
+               if (!erofs_sb_has_lz4_0padding(sbi)) {
+                       memset(dst + compressedsize, 0, padding);
+                       padding = 0;
                }
-               ctx->e.partial = false;
-               ctx->e.blkaddr = ctx->blkaddr;
-               if (!may_inline && !may_packing && !is_packed_inode)
-                       (void)z_erofs_dedupe_insert(&ctx->e,
-                                                   ctx->queue + ctx->head);
-               ctx->blkaddr += ctx->e.compressedblks;
-               ctx->head += ctx->e.length;
-               len -= ctx->e.length;
 
-               if (fix_dedupedfrag &&
-                   z_erofs_fixup_deduped_fragment(ctx, len))
-                       break;
+               /* write compressed data */
+               erofs_dbg("Writing %u compressed data to %u of %u blocks",
+                         e->length, ctx->blkaddr, e->compressedblks);
 
-               if (z_erofs_need_refill(ctx))
-                       break;
+               ret = blk_write(sbi, dst - padding, ctx->blkaddr,
+                               e->compressedblks);
+               if (ret)
+                       return ret;
+               e->raw = false;
+               may_inline = false;
+               may_packing = false;
        }
+       e->partial = false;
+       e->blkaddr = ctx->blkaddr;
+       if (!may_inline && !may_packing && !is_packed_inode)
+               (void)z_erofs_dedupe_insert(e, ctx->queue + ctx->head);
+       ctx->blkaddr += e->compressedblks;
+       ctx->head += e->length;
        return 0;
 
 fix_dedupedfrag:
        DBG_BUGON(!inode->fragment_size);
        ctx->remaining += inode->fragment_size;
-       ctx->e.length = 0;
+       e->length = 0;
        ctx->fix_dedupedfrag = true;
+       return 1;
+}
+
+static int z_erofs_compress_one(struct z_erofs_vle_compress_ctx *ctx)
+{
+       unsigned int len = ctx->tail - ctx->head;
+       int ret;
+
+       while (len) {
+               if (z_erofs_compress_dedupe(ctx, &len))
+                       break;
+
+               ret = __z_erofs_compress_one(ctx, &ctx->e);
+               if (ret) {
+                       if (ret > 0)
+                               break;          /* need more data */
+                       return ret;
+               }
+
+               len -= ctx->e.length;
+               if (ctx->fix_dedupedfrag && !ctx->fragemitted &&
+                   z_erofs_fixup_deduped_fragment(ctx, len))
+                       break;
+
+               if (z_erofs_need_refill(ctx))
+                       break;
+       }
        return 0;
 }
 
@@ -964,7 +961,7 @@ int erofs_write_compressed_file(struct erofs_inode *inode, int fd)
                        ctx.remaining -= rx;
                        ctx.tail += rx;
 
-                       ret = vle_compress_one(&ctx);
+                       ret = z_erofs_compress_one(&ctx);
                        if (ret)
                                goto err_free_idata;
                }