[PATCH] erofs-utils: lib: fix missing CBLKCNT for big pcluster dedupe

Gao Xiang hsiangkao at linux.alibaba.com
Tue Nov 22 17:45:27 AEDT 2022


CBLKCNT needs to be stored for big pcluster dedupe.  Otherwise,
the decompression could fail due to incomplete compressed data.

Reported-by: Yue Hu <huyue2 at coolpad.com>
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/compress.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/compress.c b/lib/compress.c
index 17b3213..50fea0c 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -186,11 +186,6 @@ static int z_erofs_compress_dedupe(struct erofs_inode *inode,
 		if (z_erofs_dedupe_match(&dctx))
 			break;

-		/* fall back to noncompact indexes for deduplication */
-		inode->z_advise &= ~Z_EROFS_ADVISE_COMPACTED_2B;
-		inode->datalayout = EROFS_INODE_FLAT_COMPRESSION_LEGACY;
-		erofs_sb_set_dedupe();
-
 		delta = ctx->queue + ctx->head - dctx.cur;
 		if (delta) {
 			DBG_BUGON(delta < 0);
@@ -199,10 +194,24 @@ static int z_erofs_compress_dedupe(struct erofs_inode *inode,
 			ctx->e.length -= delta;
 		}

+		/*
+		 * For big pcluster dedupe, leave two indices at least to store
+		 * CBLKCNT as the first step.  Even laterly, an one-block
+		 * decompresssion could be done as another try in practice.
+		 */
+		z_erofs_write_indexes(ctx);
+		if (dctx.e.compressedblks > 1 &&
+		    ctx->clusterofs + dctx.e.length < 2*EROFS_BLKSIZ)
+			return ret;
+
+		/* fall back to noncompact indexes for deduplication */
+		inode->z_advise &= ~Z_EROFS_ADVISE_COMPACTED_2B;
+		inode->datalayout = EROFS_INODE_FLAT_COMPRESSION_LEGACY;
+		erofs_sb_set_dedupe();
+
 		erofs_dbg("Dedupe %u %scompressed data (delta %d) to %u of %u blocks",
 			  dctx.e.length, dctx.e.raw ? "un" : "",
 			  delta, dctx.e.blkaddr, dctx.e.compressedblks);
-		z_erofs_write_indexes(ctx);
 		ctx->e = dctx.e;
 		ctx->head += dctx.e.length - delta;
 		DBG_BUGON(*len < dctx.e.length - delta);
--
2.30.2



More information about the Linux-erofs mailing list