Using --blobdev with --MZ flushes flat inodes before unified device
addresses are assigned, leaving their data addresses unresolved.

Reserve metadata zone space before calculating device addresses, then
flush the zone once those addresses are available.

Assisted-by: Codex:gpt-6-astra
Signed-off-by: Yifan Zhao <[email protected]>
---
 lib/importer.c         |  7 ++++++-
 lib/liberofs_metabox.h |  1 +
 lib/metabox.c          | 42 ++++++++++++++++++++++++------------------
 3 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/lib/importer.c b/lib/importer.c
index 89d4d8b..4506040 100644
--- a/lib/importer.c
+++ b/lib/importer.c
@@ -120,7 +120,8 @@ int erofs_importer_flush_all(struct erofs_importer *im)
        if (err)
                return err;
 
-       err = erofs_metazone_flush(sbi);
+       /* Include the metadata zone before assigning unified device addresses. 
*/
+       err = erofs_metazone_reserve(sbi);
        if (err)
                return err;
 
@@ -132,6 +133,10 @@ int erofs_importer_flush_all(struct erofs_importer *im)
        if (err)
                return err;
 
+       err = erofs_metazone_flush(sbi);
+       if (err)
+               return err;
+
        err = erofs_write_device_table(sbi);
        if (err)
                return err;
diff --git a/lib/liberofs_metabox.h b/lib/liberofs_metabox.h
index f966c20..156b651 100644
--- a/lib/liberofs_metabox.h
+++ b/lib/liberofs_metabox.h
@@ -25,6 +25,7 @@ void erofs_metadata_exit(struct erofs_sb_info *sbi);
 int erofs_metadata_init(struct erofs_sb_info *sbi);
 struct erofs_bufmgr *erofs_metadata_bmgr(struct erofs_sb_info *sbi, bool mbox);
 int erofs_metabox_iflush(struct erofs_importer *im);
+int erofs_metazone_reserve(struct erofs_sb_info *sbi);
 int erofs_metazone_flush(struct erofs_sb_info *sbi);
 
 #endif
diff --git a/lib/metabox.c b/lib/metabox.c
index 5c2eada..4750b36 100644
--- a/lib/metabox.c
+++ b/lib/metabox.c
@@ -117,18 +117,16 @@ int erofs_metabox_iflush(struct erofs_importer *im)
        return 0;
 }
 
-int erofs_metazone_flush(struct erofs_sb_info *sbi)
+int erofs_metazone_reserve(struct erofs_sb_info *sbi)
 {
        struct erofs_metamgr *m2gr = sbi->m2gr;
        struct erofs_buffer_head *bh;
-       struct erofs_bufmgr *m2bgr;
-       erofs_blk_t meta_blkaddr;
        u64 length, pos_out;
-       int ret, count;
 
        if (!m2gr)
                return 0;
-       bh = erofs_balloc(sbi->bmgr, DATA, 0, 0);
+       length = erofs_pos(sbi, erofs_mapbh(m2gr->bmgr, NULL));
+       bh = erofs_balloc(sbi->bmgr, DATA, length, 0);
        if (IS_ERR(bh))
                return PTR_ERR(bh);
        erofs_mapbh(NULL, bh->block);
@@ -137,29 +135,37 @@ int erofs_metazone_flush(struct erofs_sb_info *sbi)
                erofs_bdrop(bh, true);
                return -EFAULT;
        }
-       meta_blkaddr = pos_out >> sbi->blkszbits;
-       sbi->metazone_startblk = meta_blkaddr;
+       sbi->metazone_startblk = pos_out >> sbi->blkszbits;
+       /* Keep the mapped space; its contents will be copied after inode 
flush. */
+       erofs_bdrop(bh, false);
+       return 0;
+}
 
-       m2bgr = m2gr->bmgr;
-       ret = erofs_bflush(m2bgr, NULL);
-       if (ret)
-               return ret;
+int erofs_metazone_flush(struct erofs_sb_info *sbi)
+{
+       struct erofs_metamgr *m2gr = sbi->m2gr;
+       u64 length, pos_out;
+       int ret, count;
 
-       length = erofs_mapbh(m2bgr, NULL) << sbi->blkszbits;
-       ret = erofs_bh_balloon(bh, length);
-       if (ret < 0)
+       if (!m2gr)
+               return 0;
+       if (sbi->metazone_startblk == EROFS_META_NEW_ADDR)
+               return -EINVAL;
+
+       ret = erofs_bflush(m2gr->bmgr, NULL);
+       if (ret)
                return ret;
 
+       length = erofs_pos(sbi, erofs_mapbh(m2gr->bmgr, NULL));
+       pos_out = erofs_pos(sbi, sbi->metazone_startblk);
        do {
                count = min_t(erofs_off_t, length, INT_MAX);
                ret = erofs_io_xcopy(sbi->bmgr->vf, (off_t)pos_out,
                                     &m2gr->vf, count, false);
                if (ret < 0)
-                       break;
+                       return ret;
                pos_out += count;
        } while (length -= count);
-       bh->op = &erofs_drop_directly_bhops;
-       erofs_bdrop(bh, false);
-       sbi->meta_blkaddr += meta_blkaddr;
+       sbi->meta_blkaddr += sbi->metazone_startblk;
        return 0;
 }
-- 
2.55.0


Reply via email to