- `pstart` should be `erofs_off_t` instead of `erofs_blk_t`, otherwise,
  its upper 32 bits may be truncated;

- If it falls back to uncompressed inodes due to insufficient
  space savings, dedupe-ext records should also be revoked.

Reported-by: Axel Fontaine <a...@axelfontaine.com>
Fixes: cf04b8b78f09 ("erofs-utils: mkfs: implement extent-based deduplication")
Closes: https://github.com/erofs/erofs-utils/issues/23
Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com>
---
 include/erofs/dedupe.h |  2 +-
 lib/compress.c         | 15 +++++++++------
 lib/dedupe_ext.c       | 21 +++++++++++----------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/include/erofs/dedupe.h b/include/erofs/dedupe.h
index ffb00a50..f9caa611 100644
--- a/include/erofs/dedupe.h
+++ b/include/erofs/dedupe.h
@@ -34,7 +34,7 @@ void z_erofs_dedupe_exit(void);
 
 int z_erofs_dedupe_ext_insert(struct z_erofs_inmem_extent *e,
                              u64 hash);
-erofs_blk_t z_erofs_dedupe_ext_match(struct erofs_sb_info *sbi,
+erofs_off_t z_erofs_dedupe_ext_match(struct erofs_sb_info *sbi,
                        u8 *encoded, unsigned int size, bool raw, u64 *hash);
 void z_erofs_dedupe_ext_commit(bool drop);
 int z_erofs_dedupe_ext_init(void);
diff --git a/lib/compress.c b/lib/compress.c
index 6f65993c..b16f5d1d 100644
--- a/lib/compress.c
+++ b/lib/compress.c
@@ -403,7 +403,7 @@ static int write_uncompressed_block(struct 
z_erofs_compress_sctx *ctx,
        memcpy(dst, ctx->queue + ctx->head + rightpart, count - rightpart);
 
        if (ctx->membuf) {
-               erofs_dbg("Writing %u uncompressed data of %s", count,
+               erofs_dbg("Recording %u uncompressed data of %s", count,
                          inode->i_srcpath);
                memcpy(ctx->membuf + ctx->memoff, dst, erofs_blksiz(sbi));
                ctx->memoff += erofs_blksiz(sbi);
@@ -705,7 +705,7 @@ frag_packing:
 
                /* write compressed data */
                if (ctx->membuf) {
-                       erofs_dbg("Writing %u compressed data of %u bytes of 
%s",
+                       erofs_dbg("Recording %u compressed data of %u bytes of 
%s",
                                  e->length, e->plen, inode->i_srcpath);
 
                        memcpy(ctx->membuf + ctx->memoff,
@@ -1207,6 +1207,7 @@ int erofs_commit_compressed_file(struct 
z_erofs_compress_ictx *ictx,
        /* estimate if data compression saves space or not */
        if (!inode->fragment_size && ptotal + inode->idata_size +
            legacymetasize >= inode->i_size) {
+               z_erofs_dedupe_ext_commit(true);
                z_erofs_dedupe_commit(true);
                ret = -ENOSPC;
                goto err_free_meta;
@@ -1411,7 +1412,7 @@ int z_erofs_merge_segment(struct z_erofs_compress_ictx 
*ictx,
        bool dedupe_ext = cfg.c_fragments;
        erofs_off_t off = 0;
        int ret = 0, ret2;
-       erofs_blk_t dupb;
+       erofs_off_t dpo;
        u64 hash;
 
        list_for_each_entry_safe(ei, n, &sctx->extents, list) {
@@ -1429,10 +1430,10 @@ int z_erofs_merge_segment(struct z_erofs_compress_ictx 
*ictx,
                        continue;
 
                if (dedupe_ext) {
-                       dupb = z_erofs_dedupe_ext_match(sbi, sctx->membuf + off,
+                       dpo = z_erofs_dedupe_ext_match(sbi, sctx->membuf + off,
                                                ei->e.plen, ei->e.raw, &hash);
-                       if (dupb != EROFS_NULL_ADDR) {
-                               ei->e.pstart = dupb;
+                       if (dpo) {
+                               ei->e.pstart = dpo;
                                sctx->pstart -= ei->e.plen;
                                off += ei->e.plen;
                                ictx->dedupe = true;
@@ -1444,6 +1445,8 @@ int z_erofs_merge_segment(struct z_erofs_compress_ictx 
*ictx,
                                continue;
                        }
                }
+               erofs_dbg("Writing %u %scompressed data of %s to %llu", 
ei->e.length,
+                         ei->e.raw ? "un" : "", ictx->inode->i_srcpath, 
ei->e.pstart);
                ret2 = erofs_dev_write(sbi, sctx->membuf + off, ei->e.pstart,
                                       ei->e.plen);
                off += ei->e.plen;
diff --git a/lib/dedupe_ext.c b/lib/dedupe_ext.c
index c2c5ca94..d7a9b737 100644
--- a/lib/dedupe_ext.c
+++ b/lib/dedupe_ext.c
@@ -32,14 +32,14 @@ int z_erofs_dedupe_ext_insert(struct z_erofs_inmem_extent 
*e,
        return 0;
 }
 
-erofs_blk_t z_erofs_dedupe_ext_match(struct erofs_sb_info *sbi,
+erofs_off_t z_erofs_dedupe_ext_match(struct erofs_sb_info *sbi,
                                     u8 *encoded, unsigned int len,
                                     bool raw, u64 *hash)
 {
        struct z_erofs_dedupe_ext_item *item;
        struct list_head *p;
        u64 _xxh64;
-       char *memb;
+       char *memb = NULL;
        int ret;
 
        *hash = _xxh64 = xxh64(encoded, len, 0);
@@ -47,19 +47,20 @@ erofs_blk_t z_erofs_dedupe_ext_match(struct erofs_sb_info 
*sbi,
        list_for_each_entry(item, p, list) {
                if (item->xxh64 == _xxh64 && item->e.plen == len &&
                    item->e.raw == raw) {
-                       memb = malloc(len);
-                       if (!memb)
-                               break;
-                       ret = erofs_dev_read(sbi, 0, memb, item->e.pstart, len);
-                       if (ret < 0 || memcmp(memb, encoded, len)) {
-                               free(memb);
-                               break;
+                       if (!memb) {
+                               memb = malloc(len);
+                               if (!memb)
+                                       break;
                        }
+                       ret = erofs_dev_read(sbi, 0, memb, item->e.pstart, len);
+                       if (ret < 0 || memcmp(memb, encoded, len))
+                               continue;
                        free(memb);
                        return item->e.pstart;
                }
        }
-       return EROFS_NULL_ADDR;
+       free(memb);
+       return 0;
 }
 
 void z_erofs_dedupe_ext_commit(bool drop)
-- 
2.43.5


Reply via email to